-
Notifications
You must be signed in to change notification settings - Fork 164
protect: Add "Nonce Management" page to document eth_getTransactionCount
behavior.
#573
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
03b0961
c939467
ca87c0e
bb02d11
e99813f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
--- | ||
title: Nonce Management | ||
--- | ||
|
||
import Tabs from '@theme/Tabs'; | ||
import TabItem from '@theme/TabItem'; | ||
|
||
Normally, a wallet can call `eth_getTransactionCount` to get the next nonce to use for a transaction. | ||
However, since transactions sent to Flashbots Protect are potentially sensitive, even exposing the incremented nonce can leak information about the user's activity. | ||
|
||
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. | ||
|
||
This is done by sending a JSON-RPC request to the Flashbots Protect RPC endpoint with the following parameters: | ||
|
||
```json | ||
{ | ||
"jsonrpc": "2.0", | ||
"method": "eth_getTransactionCount", | ||
"params": [ | ||
"0xYOUR_ADDRESS", | ||
"pending" | ||
], | ||
"id": 1 | ||
} | ||
``` | ||
|
||
The request is 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. | ||
|
||
### Authentication | ||
|
||
To authenticate your request, sign the payload and include the signed payload in the `X-Flashbots-Signature` header of your request. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We might want to (instead, or in addition) link directly to the authentication section in our API docs https://docs.flashbots.net/flashbots-auction/advanced/rpc-endpoint#authentication. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought about that, but that section is relay-specific so includes some wording such as:
That conflicts with the usage here. |
||
```curl | ||
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 | ||
``` | ||
|
||
The private key of the address your want to query must be used to sign the payload. | ||
|
||
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: | ||
|
||
<Tabs | ||
defaultValue="ethers.js" | ||
values={[ | ||
{ label: 'ethers.js', value: 'ethers.js', }, | ||
{ label: 'web3.py', value: 'web3.py' }, | ||
{ label: 'go', value: 'go' }, | ||
]} | ||
> | ||
<TabItem value="ethers.js"> | ||
|
||
```ts | ||
import {Wallet, utils} from 'ethers'; | ||
|
||
const privateKey = '0x1234'; | ||
const wallet = new Wallet(privateKey); | ||
const body = | ||
'{"jsonrpc":"2.0","method":"eth_getTransactionCount","params":["0xYOUR_ADDRESS","pending"],"id":1}'; | ||
const signature = wallet.address + ':' + wallet.signMessage(utils.id(body)); | ||
``` | ||
|
||
</TabItem> | ||
<TabItem value="web3.py"> | ||
|
||
```py | ||
from web3 import Web3 | ||
from eth_account import Account, messages | ||
|
||
body = '{"jsonrpc":"2.0","method":"eth_getTransactionCount","params":["0xYOUR_ADDRESS","pending"],"id":1}' | ||
message = messages.encode_defunct(text=Web3.keccak(text=body).hex()) | ||
signature = Account.from_key(private_key).address + ':' + Account.sign_message(message, private_key).signature.hex() | ||
``` | ||
|
||
</TabItem> | ||
<TabItem value="go"> | ||
|
||
```go | ||
body := `{"jsonrpc":"2.0","method":"eth_getTransactionCount","params":["0xYOUR_ADDRESS","pending"],"id":1}` | ||
hashedBody := crypto.Keccak256Hash([]byte(body)).Hex() | ||
sig, err := crypto.Sign(accounts.TextHash([]byte(hashedBody)), privKey) | ||
signature := crypto.PubkeyToAddress(privKey.PublicKey).Hex() + ":" + hexutil.Encode(sig) | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> | ||
|
Uh oh!
There was an error while loading. Please reload this page.