Skip to content

Commit 613d97b

Browse files
committed
feat:add README
Signed-off-by: grapebaba <281165273@qq.com>
1 parent 958782d commit 613d97b

2 files changed

Lines changed: 342 additions & 0 deletions

File tree

‎CONTRIBUTING.md‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Contribute to mev-share-java
2+
3+
## Create a fork
4+
5+
First, create a fork of the mev-share-java repo in your own account so that you can work with your own copy.
6+
7+
**To create a fork using the website**
8+
9+
1. Log in to your Github account.
10+
1. Browse to the [mev-share-java repo](https://github.com/optimism-java/mev-share-java) on GitHub.
11+
1. Choose **Fork** in the top-right, then choose **Create new fork**.
12+
1. For **Owner**, select your username.
13+
1. For **Repository name**, we suggest keeping the name mev-share-java, but you can use any name.
14+
1. Optional. To contribute you need only the main branch of the repo. To include all branches, unselect the checkbox for **Copy the `main` branch only**.
15+
1. Click **Create fork**.
16+
17+
### Clone your fork
18+
19+
Next, clone your fork of the repo to your local workspace.
20+
21+
**To clone your fork to your local workspace**
22+
1. Open the GitHub page for your fork of the repo, then click **Sync fork**.
23+
1. Click **Code**, then click **HTTPS** and copy the web URL displayed.
24+
1. Open a terminal session and navigate to the folder to use, then run the following command, replacing the URL with the URL you copied from the Git page:
25+
26+
`git clone https://github.com/github-user-name/mev-share-java.git`
27+
28+
The repo is automatically cloned into the `mev-share-java` folder in your workspace.
29+
Create a branch of your fork with following command (or follow the [GitHub topic on branching](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-and-deleting-branches-within-your-repository))
30+
31+
`git checkout -b your-branch-name`
32+
33+
Use the following command to set the [remote upstream repo](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/configuring-a-remote-repository-for-a-fork):
34+
35+
`git remote add upstream https://github.com/optimism-java/mev-share-java.git`
36+
37+
You now have a fork of the mev-share-java repo set up in your local workspace. You can make changes to the files in the workspace, add commits, then push your changes to your fork of the repo to then create a Pull Request.
38+
39+
`./gradlew build`
40+
41+
Run build before you submit a Pull Request.

‎README.md‎

Lines changed: 301 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,305 @@
22
[![License](https://img.shields.io/badge/license-MIT-blue)](https://opensource.org/licenses/MIT)
33
![Coverage](.github/badges/jacoco.svg)
44
![Branches](.github/badges/branches.svg)
5+
56
# mev-share-java
7+
8+
Mev-share-java is a Java library for working with MEV-share.
9+
10+
Based on [Specs](https://github.com/flashbots/mev-share)
11+
12+
## Using
13+
14+
Download the latest jar from maven central.
15+
16+
### Maven
17+
18+
```xml
19+
<dependency>
20+
<groupId>me.grapebaba</groupId>
21+
<artifactId>mev-share-java</artifactId>
22+
<version>0.1.0</version>
23+
</dependency>
24+
```
25+
26+
### Gradle
27+
28+
```groovy
29+
implementation 'me.grapebaba:mev-share-java:0.1.0'
30+
```
31+
32+
## Building Locally
33+
34+
To get started you need to install JDK17+, then run the following command:
35+
36+
```bash
37+
GOERLI_RPC_URL=<GOERLI_RPC_URL> SIGNER_PRIVATE_KEY=<SIGNER_PRIVATE_KEY> ./gradlew clean build
38+
```
39+
40+
## Javadoc
41+
42+
For the latest javadocs for the `main` branch, run `./gradlew javadoc` and open
43+
the document under the `build/docs/javadoc/index.html` in your browser.
44+
45+
## Testing
46+
47+
### To run unit tests
48+
49+
```
50+
GOERLI_RPC_URL=<GOERLI_RPC_URL> SIGNER_PRIVATE_KEY=<SIGNER_PRIVATE_KEY> ./gradlew test
51+
```
52+
53+
## How to use it
54+
55+
### Create a MEVShare instance
56+
57+
```java
58+
// Create a credential instance for authentication using Web3j
59+
Credentials authSigner = Credentials.create("<hex string of privateKey>");
60+
61+
// Create an ethereum provider instance using Web3j
62+
Web3j web3j = Web3j.build(new HttpService("<ethereum network rpc url>"));
63+
64+
// Create a Mev share network options instance or use built-in options
65+
Network network = new Network()
66+
.setName("<network name>")
67+
.setChainId("<chain id>")
68+
.setRpcUrl("<mev share network rpc url>")
69+
.setStreamUrl("<mev share network stream url>");
70+
71+
Network network = Network.GOERLI;
72+
Network network = Network.MAINNET;
73+
74+
// Create a Mev share instance
75+
MevShareClient mevShareClient = new MevShareClient(network, authSigner, web3j);
76+
```
77+
78+
### History events Query
79+
80+
```java
81+
// Query the Event info
82+
CompletableFuture<EventHistoryInfo> historyInfoFuture = mevShareClient.getEventHistoryInfo();
83+
84+
// Query the Event List by params
85+
EventHistoryParams historyParams = new EventHistoryParams().setLimit(20).setBlockStart(BigInteger.valueOf(1_000_000L));
86+
CompletableFuture<List<EventHistoryEntry>> eventHistory = mevShareClient.getEventHistory(historyParams);
87+
```
88+
89+
### Subscribe to events stream
90+
91+
```java
92+
// Create an event listener which handles the event
93+
Consumer<MevShareEvent> eventListener = mevShareEvent -> {
94+
// do something and do not block here...
95+
};
96+
97+
// Subscribe to events stream
98+
Disposable disposable = mevShareClient.subscribe(eventListener);
99+
100+
// remember to release when no longer to subscribe events
101+
disposable.dispose();
102+
```
103+
104+
### Send bundle
105+
106+
#### Send a bundle including a hash item
107+
108+
```java
109+
110+
// Listen to the event stream and capture the bundle hash
111+
CompletableFuture<MevShareEvent> future = new CompletableFuture<>();
112+
Disposable eventSource = mevShareClient.subscribe(mevShareEvent -> {
113+
if (mevShareEvent.getHash() != null) {
114+
future.complete(mevShareEvent);
115+
}
116+
});
117+
MevShareEvent mevShareEvent = future.get();
118+
eventSource.dispose();
119+
120+
BigInteger number = web3j.ethGetBlockByNumber(DefaultBlockParameterName.LATEST, false)
121+
.send()
122+
.getBlock()
123+
.getNumber();
124+
125+
Inclusion inclusion =
126+
new Inclusion().setBlock(number.add(BigInteger.ONE)).setMaxBlock(number.add(BigInteger.valueOf(4)));
127+
128+
BundleItemType.HashItem bundleItem = new BundleItemType.HashItem().setHash(mevShareEvent.getHash());
129+
130+
// Create a backrun transaction
131+
Credentials signer = Credentials.create("<private key>");
132+
BigInteger nonce = web3j.ethGetTransactionCount(signer.getAddress(), DefaultBlockParameterName.PENDING)
133+
.send()
134+
.getTransactionCount();
135+
BigInteger gasPrice = web3j.ethGasPrice().send().getGasPrice();
136+
BigInteger gasLimit = DefaultGasProvider.GAS_LIMIT;
137+
final String to = "<to address>";
138+
final String amount = "<ether amount>";
139+
RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
140+
nonce,
141+
gasPrice,
142+
gasLimit,
143+
to,
144+
Convert.toWei(amount, Convert.Unit.ETHER).toBigInteger());
145+
byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, Network.GOERLI.chainId(), signer);
146+
String hexValue = Numeric.toHexString(signedMessage);
147+
148+
BundleItemType.TxItem txItem =
149+
new BundleItemType.TxItem().setTx(hexValue).setCanRevert(true);
150+
151+
// Construct the bundle with bundle hash item and backrun transaction item
152+
BundleParams bundleParams = new BundleParams().setInclusion(inclusion).setBody(List.of(bundleItem, txItem));
153+
154+
// Send the bundle
155+
CompletableFuture<SendBundleResponse> res = mevShareClient.sendBundle(bundleParams);
156+
```
157+
158+
#### Send a bundle with privacy
159+
Bundles that only contain signed transactions can share hints about the transactions in their bundle by setting the privacy parameter
160+
```java
161+
// Create a transaction
162+
Credentials signer = Credentials.create("<private key>");
163+
BigInteger nonce = web3j.ethGetTransactionCount(signer.getAddress(), DefaultBlockParameterName.PENDING)
164+
.send()
165+
.getTransactionCount();
166+
BigInteger gasPrice = web3j.ethGasPrice().send().getGasPrice();
167+
BigInteger gasLimit = DefaultGasProvider.GAS_LIMIT;
168+
final String to = "<to address>";
169+
final String amount = "<ether amount>";
170+
RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
171+
nonce,
172+
gasPrice,
173+
gasLimit,
174+
to,
175+
Convert.toWei(amount, Convert.Unit.ETHER).toBigInteger());
176+
byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, Network.GOERLI.chainId(), signer);
177+
String hexValue = Numeric.toHexString(signedMessage);
178+
179+
BundleItemType.TxItem txItem =
180+
new BundleItemType.TxItem().setTx(hexValue).setCanRevert(true);
181+
182+
// Set privacy parameter
183+
HintPreferences hintPreferences = new HintPreferences()
184+
.setCalldata(true)
185+
.setContractAddress(true)
186+
.setFunctionSelector(true)
187+
.setLogs(true)
188+
.setTxHash(true);
189+
List<String> builders = new ArrayList<>();
190+
builders.add("flashbots");
191+
192+
BundlePrivacy bundlePrivacy =
193+
new BundlePrivacy().setHints(hintPreferences).setBuilders(builders);
194+
195+
// Construct the bundle with transaction item
196+
BundleParams bundleParams = new BundleParams()
197+
.setInclusion(inclusion)
198+
.setBody(List.of(txItem))
199+
.setPrivacy(bundlePrivacy);
200+
201+
// Send the bundle
202+
CompletableFuture<SendBundleResponse> res = MEV_SHARE_CLIENT.sendBundle(bundleParams);
203+
```
204+
205+
### Simulate bundle
206+
207+
```java
208+
// Create a transaction
209+
var latestBlock = web3j.ethGetBlockByNumber(DefaultBlockParameterName.LATEST, false)
210+
.send()
211+
.getBlock();
212+
var parentBlock = web3j.ethGetBlockByNumber(
213+
DefaultBlockParameter.valueOf(latestBlock.getNumber().subtract(BigInteger.ONE)), false)
214+
.send()
215+
.getBlock();
216+
217+
Inclusion inclusion = new Inclusion()
218+
.setBlock(latestBlock.getNumber().subtract(BigInteger.ONE))
219+
.setMaxBlock(latestBlock.getNumber().add(BigInteger.valueOf(10)));
220+
221+
Credentials signer = Credentials.create("<private key>");
222+
BigInteger nonce = web3j.ethGetTransactionCount(signer.getAddress(), DefaultBlockParameterName.PENDING)
223+
.send()
224+
.getTransactionCount();
225+
final String to = "<to address>";
226+
RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
227+
nonce,
228+
web3j.ethGasPrice().send().getGasPrice(),
229+
DefaultGasProvider.GAS_LIMIT,
230+
to,
231+
Convert.toWei("0", Convert.Unit.ETHER).toBigInteger());
232+
byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, Network.GOERLI.chainId(), signer);
233+
String hexValue = Numeric.toHexString(signedMessage);
234+
235+
// Construct the bundle params with transaction item
236+
BundleItemType.TxItem bundleItem =
237+
new BundleItemType.TxItem().setTx(hexValue).setCanRevert(true);
238+
239+
BundleParams bundleParams = new BundleParams().setInclusion(inclusion).setBody(List.of(bundleItem));
240+
241+
// Create a simbundle options
242+
SimBundleOptions options = new SimBundleOptions()
243+
.setParentBlock(latestBlock.getNumber().subtract(BigInteger.ONE))
244+
.setBlockNumber(latestBlock.getNumber())
245+
.setTimestamp(parentBlock.getTimestamp().add(BigInteger.valueOf(12)))
246+
.setGasLimit(parentBlock.getGasLimit())
247+
.setBaseFee(parentBlock.getBaseFeePerGas())
248+
.setTimeout(30);
249+
250+
// Simulate the bundle
251+
CompletableFuture<SimBundleResponse> res = mevShareClient.simBundle(bundleParams, options);
252+
```
253+
254+
### Send private transaction
255+
256+
```java
257+
// Create a transaction
258+
EthBlock.Block latest = web3j.ethGetBlockByNumber(DefaultBlockParameterName.LATEST, false)
259+
.send()
260+
.getBlock();
261+
262+
BigInteger maxPriorityFeePerGas = BigInteger.valueOf(1_000_000_000L);
263+
264+
Credentials signer = Credentials.create("<private key>");
265+
BigInteger nonce = web3j.ethGetTransactionCount(signer.getAddress(), DefaultBlockParameterName.PENDING)
266+
.send()
267+
.getTransactionCount();
268+
final String to = "<to address>";
269+
270+
RawTransaction rawTransaction = RawTransaction.createTransaction(
271+
5L,
272+
nonce,
273+
latest.getGasLimit(),
274+
to,
275+
Convert.toWei("0", Convert.Unit.ETHER).toBigInteger(),
276+
Numeric.toHexString("<data>".getBytes(StandardCharsets.UTF_8)),
277+
maxPriorityFeePerGas,
278+
latest.getBaseFeePerGas().multiply(BigInteger.TWO).add(maxPriorityFeePerGas));
279+
byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, Network.GOERLI.chainId(), signer);
280+
String signRawTx = Numeric.toHexString(signedMessage);
281+
282+
// Create a private transaction options
283+
PrivateTxOptions txOptions = new PrivateTxOptions()
284+
.setHints(new HintPreferences()
285+
.setCalldata(true)
286+
.setContractAddress(true)
287+
.setFunctionSelector(true)
288+
.setLogs(true));
289+
290+
// Send the private transaction
291+
CompletableFuture<String> res = mevShareClient.sendPrivateTransaction(signRawTx, txOptions);
292+
```
293+
294+
## Examples
295+
For more examples, you can see [example](https://github.com/optimism-java/mev-share-java/tree/main/example)
296+
297+
> Examples require a `.env` file (or that you populate your environment directly with the appropriate variables).
298+
299+
```sh
300+
cd src/examples
301+
cp .env.example .env
302+
vim .env
303+
```
304+
305+
## Contribution
306+
To help mev-share-java grow, follow [Contributing to mev-share-java](CONTRIBUTING.md).

0 commit comments

Comments
 (0)