|
| 1 | +--- |
| 2 | +title: Nonce Management |
| 3 | +--- |
| 4 | + |
| 5 | +import Tabs from '@theme/Tabs'; |
| 6 | +import TabItem from '@theme/TabItem'; |
| 7 | + |
| 8 | +Normally, a wallet can call `eth_getTransactionCount` to get the next nonce to use for a transaction. |
| 9 | +However, since transactions sent to Flashbots Protect are potentially sensitive, even exposing the incremented nonce can leak information about the user's activity. |
| 10 | + |
| 11 | +As such, transactions sent to Flashbots Protect are only included in the `eth_getTransactionCount` results when querying the `"pending"` nonce, and only if the request is signed by the user's private key. |
| 12 | + |
| 13 | +This is done by sending a JSON-RPC request to the Flashbots Protect RPC endpoint with the following parameters: |
| 14 | + |
| 15 | +```json |
| 16 | +{ |
| 17 | + "jsonrpc": "2.0", |
| 18 | + "method": "eth_getTransactionCount", |
| 19 | + "params": [ |
| 20 | + "0xYOUR_ADDRESS", |
| 21 | + "pending" |
| 22 | + ], |
| 23 | + "id": 1 |
| 24 | +} |
| 25 | +``` |
| 26 | + |
| 27 | +The request is then signed and the signature is included in the `X-Flashbots-Signature` header. Without such a signature, the returned nonce will only include transactions sent to the public mempool. |
| 28 | + |
| 29 | +### Authentication |
| 30 | + |
| 31 | +To authenticate your request, sign the payload and include the signed payload in the `X-Flashbots-Signature` header of your request. |
| 32 | + |
| 33 | +```curl |
| 34 | +curl -X POST -H "Content-Type: application/json" -H "X-Flashbots-Signature: <public key address>:<signature>" --data '{"jsonrpc":"2.0","method":"eth_getTransactionCount","params":["0xYOUR_ADDRESS","pending"],"id":1}' https://rpc.flashbots.net |
| 35 | +``` |
| 36 | + |
| 37 | +The private key of the address your want to query must be used to sign the payload. |
| 38 | + |
| 39 | +The signature is calculated by taking the [EIP-191](https://eips.ethereum.org/EIPS/eip-191) hash of the json body encoded as UTF-8 bytes. Here's an example using ethers.js: |
| 40 | + |
| 41 | +<Tabs |
| 42 | +defaultValue="ethers.js" |
| 43 | +values={[ |
| 44 | +{ label: 'ethers.js', value: 'ethers.js', }, |
| 45 | +{ label: 'web3.py', value: 'web3.py' }, |
| 46 | +{ label: 'go', value: 'go' }, |
| 47 | +]} |
| 48 | +> |
| 49 | +<TabItem value="ethers.js"> |
| 50 | + |
| 51 | +```ts |
| 52 | +import {Wallet, utils} from 'ethers'; |
| 53 | + |
| 54 | +const privateKey = '0x1234'; |
| 55 | +const wallet = new Wallet(privateKey); |
| 56 | +const body = |
| 57 | + '{"jsonrpc":"2.0","method":"eth_getTransactionCount","params":["0xYOUR_ADDRESS","pending"],"id":1}'; |
| 58 | +const signature = wallet.address + ':' + wallet.signMessage(utils.id(body)); |
| 59 | +``` |
| 60 | + |
| 61 | +</TabItem> |
| 62 | +<TabItem value="web3.py"> |
| 63 | + |
| 64 | +```py |
| 65 | +from web3 import Web3 |
| 66 | +from eth_account import Account, messages |
| 67 | + |
| 68 | +body = '{"jsonrpc":"2.0","method":"eth_getTransactionCount","params":["0xYOUR_ADDRESS","pending"],"id":1}' |
| 69 | +message = messages.encode_defunct(text=Web3.keccak(text=body).hex()) |
| 70 | +signature = Account.from_key(private_key).address + ':' + Account.sign_message(message, private_key).signature.hex() |
| 71 | +``` |
| 72 | + |
| 73 | +</TabItem> |
| 74 | +<TabItem value="go"> |
| 75 | + |
| 76 | +```go |
| 77 | +body := `{"jsonrpc":"2.0","method":"eth_getTransactionCount","params":["0xYOUR_ADDRESS","pending"],"id":1}` |
| 78 | +hashedBody := crypto.Keccak256Hash([]byte(body)).Hex() |
| 79 | +sig, err := crypto.Sign(accounts.TextHash([]byte(hashedBody)), privKey) |
| 80 | +signature := crypto.PubkeyToAddress(privKey.PublicKey).Hex() + ":" + hexutil.Encode(sig) |
| 81 | +``` |
| 82 | + |
| 83 | +</TabItem> |
| 84 | +</Tabs> |
| 85 | + |
0 commit comments