@flashbots/ethers-provider-bundle
Advanced tools
Comparing version 0.4.4 to 0.5.0
@@ -13,2 +13,6 @@ import { BlockTag, TransactionReceipt, TransactionRequest } from '@ethersproject/abstract-provider'; | ||
} | ||
export declare enum FlashbotsTransactionResolution { | ||
TransactionIncluded = 0, | ||
TransactionDropped = 1 | ||
} | ||
export declare enum FlashbotsBundleConflictType { | ||
@@ -47,2 +51,8 @@ NoConflict = 0, | ||
} | ||
export interface FlashbotsPrivateTransactionResponse { | ||
transaction: TransactionAccountNonce; | ||
wait: () => Promise<FlashbotsTransactionResolution>; | ||
simulate: () => Promise<SimulationResponse>; | ||
receipts: () => Promise<Array<TransactionReceipt>>; | ||
} | ||
export interface TransactionSimulationBase { | ||
@@ -80,2 +90,3 @@ txHash: string; | ||
export declare type FlashbotsTransaction = FlashbotsTransactionResponse | RelayResponseError; | ||
export declare type FlashbotsPrivateTransaction = FlashbotsPrivateTransactionResponse | RelayResponseError; | ||
export interface GetUserStatsResponseSuccess { | ||
@@ -170,4 +181,10 @@ signing_address: string; | ||
sendBundle(bundledTransactions: Array<FlashbotsBundleTransaction | FlashbotsBundleRawTransaction>, targetBlockNumber: number, opts?: FlashbotsOptions): Promise<FlashbotsTransaction>; | ||
sendPrivateTransaction(transaction: FlashbotsBundleTransaction | FlashbotsBundleRawTransaction, opts?: { | ||
maxBlockNumber?: number; | ||
simulationTimestamp?: number; | ||
}): Promise<FlashbotsPrivateTransaction>; | ||
cancelPrivateTransaction(txHash: string): Promise<boolean | RelayResponseError>; | ||
signBundle(bundledTransactions: Array<FlashbotsBundleTransaction | FlashbotsBundleRawTransaction>): Promise<Array<string>>; | ||
private wait; | ||
private waitForBlock; | ||
private waitForTxInclusion; | ||
getUserStats(): Promise<GetUserStatsResponse>; | ||
@@ -182,4 +199,4 @@ getBundleStats(bundleHash: string, blockNumber: number): Promise<GetBundleStatsResponse>; | ||
private fetchReceipts; | ||
private prepareBundleRequest; | ||
private prepareRelayRequest; | ||
} | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.FlashbotsBundleProvider = exports.FlashbotsBundleConflictType = exports.FlashbotsBundleResolution = exports.BASE_FEE_MAX_CHANGE_DENOMINATOR = exports.DEFAULT_FLASHBOTS_RELAY = void 0; | ||
exports.FlashbotsBundleProvider = exports.FlashbotsBundleConflictType = exports.FlashbotsTransactionResolution = exports.FlashbotsBundleResolution = exports.BASE_FEE_MAX_CHANGE_DENOMINATOR = exports.DEFAULT_FLASHBOTS_RELAY = void 0; | ||
const web_1 = require("@ethersproject/web"); | ||
@@ -10,2 +10,3 @@ const ethers_1 = require("ethers"); | ||
exports.BASE_FEE_MAX_CHANGE_DENOMINATOR = 8; | ||
const PRIVATE_TX_WAIT_BLOCKS = 25; // # of blocks | ||
var FlashbotsBundleResolution; | ||
@@ -17,2 +18,7 @@ (function (FlashbotsBundleResolution) { | ||
})(FlashbotsBundleResolution = exports.FlashbotsBundleResolution || (exports.FlashbotsBundleResolution = {})); | ||
var FlashbotsTransactionResolution; | ||
(function (FlashbotsTransactionResolution) { | ||
FlashbotsTransactionResolution[FlashbotsTransactionResolution["TransactionIncluded"] = 0] = "TransactionIncluded"; | ||
FlashbotsTransactionResolution[FlashbotsTransactionResolution["TransactionDropped"] = 1] = "TransactionDropped"; | ||
})(FlashbotsTransactionResolution = exports.FlashbotsTransactionResolution || (exports.FlashbotsTransactionResolution = {})); | ||
var FlashbotsBundleConflictType; | ||
@@ -104,3 +110,3 @@ (function (FlashbotsBundleConflictType) { | ||
}; | ||
const request = JSON.stringify(this.prepareBundleRequest('eth_sendBundle', [params])); | ||
const request = JSON.stringify(this.prepareRelayRequest('eth_sendBundle', [params])); | ||
const response = await this.request(request); | ||
@@ -126,3 +132,3 @@ if (response.error !== undefined && response.error !== null) { | ||
bundleTransactions, | ||
wait: () => this.wait(bundleTransactions, targetBlockNumber, TIMEOUT_MS), | ||
wait: () => this.waitForBlock(bundleTransactions, targetBlockNumber, TIMEOUT_MS), | ||
simulate: () => this.simulate(bundleTransactions.map((tx) => tx.signedTransaction), targetBlockNumber, undefined, opts === null || opts === void 0 ? void 0 : opts.minTimestamp), | ||
@@ -137,2 +143,56 @@ receipts: () => this.fetchReceipts(bundleTransactions), | ||
} | ||
async sendPrivateTransaction(transaction, opts) { | ||
let signedTransaction; | ||
if ("signedTransaction" in transaction) { | ||
signedTransaction = transaction.signedTransaction; | ||
} | ||
else { | ||
signedTransaction = await transaction.signer.signTransaction(transaction.transaction); | ||
} | ||
const startBlockNumberPromise = this.genericProvider.getBlockNumber(); | ||
const params = { | ||
tx: signedTransaction, | ||
maxBlockNumber: opts === null || opts === void 0 ? void 0 : opts.maxBlockNumber, | ||
}; | ||
const request = JSON.stringify(this.prepareRelayRequest('eth_sendPrivateTransaction', [params])); | ||
const response = await this.request(request); | ||
if (response.error !== undefined && response.error !== null) { | ||
return { | ||
error: { | ||
message: response.error.message, | ||
code: response.error.code | ||
} | ||
}; | ||
} | ||
const transactionDetails = ethers_1.ethers.utils.parseTransaction(signedTransaction); | ||
const privateTransaction = { | ||
signedTransaction: signedTransaction, | ||
hash: ethers_1.ethers.utils.keccak256(signedTransaction), | ||
account: transactionDetails.from || "0x0", | ||
nonce: transactionDetails.nonce, | ||
}; | ||
const startBlockNumber = await startBlockNumberPromise; | ||
return { | ||
transaction: privateTransaction, | ||
wait: () => this.waitForTxInclusion(privateTransaction.hash, (opts === null || opts === void 0 ? void 0 : opts.maxBlockNumber) || startBlockNumber + 25, TIMEOUT_MS), | ||
simulate: () => this.simulate([privateTransaction.signedTransaction], startBlockNumber, undefined, opts === null || opts === void 0 ? void 0 : opts.simulationTimestamp), | ||
receipts: () => this.fetchReceipts([privateTransaction]), | ||
}; | ||
} | ||
async cancelPrivateTransaction(txHash) { | ||
const params = { | ||
txHash, | ||
}; | ||
const request = JSON.stringify(this.prepareRelayRequest('eth_cancelPrivateTransaction', [params])); | ||
const response = await this.request(request); | ||
if (response.error !== undefined && response.error !== null) { | ||
return { | ||
error: { | ||
message: response.error.message, | ||
code: response.error.code | ||
} | ||
}; | ||
} | ||
return true; | ||
} | ||
async signBundle(bundledTransactions) { | ||
@@ -169,3 +229,3 @@ const nonces = {}; | ||
} | ||
wait(transactionAccountNonces, targetBlockNumber, timeout) { | ||
waitForBlock(transactionAccountNonces, targetBlockNumber, timeout) { | ||
return new Promise((resolve, reject) => { | ||
@@ -230,2 +290,50 @@ let timer = null; | ||
} | ||
waitForTxInclusion(transactionHash, maxBlockNumber, timeout) { | ||
return new Promise((resolve, reject) => { | ||
let timer = null; | ||
let done = false; | ||
// runs on new block event | ||
const handler = async (blockNumber) => { | ||
if (blockNumber <= maxBlockNumber) { | ||
// check tx status on mainnet | ||
const sentTxStatus = await this.genericProvider.getTransaction(transactionHash); | ||
if (sentTxStatus && sentTxStatus.confirmations >= 1) { | ||
resolve(FlashbotsTransactionResolution.TransactionIncluded); | ||
} | ||
else { | ||
return; | ||
} | ||
} | ||
else { | ||
// tx not included in specified range, bail | ||
this.genericProvider.removeListener('block', handler); | ||
resolve(FlashbotsTransactionResolution.TransactionDropped); | ||
} | ||
if (timer) { | ||
clearTimeout(timer); | ||
} | ||
if (done) { | ||
return; | ||
} | ||
done = true; | ||
this.genericProvider.removeListener('block', handler); | ||
}; | ||
this.genericProvider.on('block', handler); | ||
// time out if we've been trying for too long | ||
if (timeout > 0) { | ||
timer = setTimeout(() => { | ||
if (done) { | ||
return; | ||
} | ||
timer = null; | ||
done = true; | ||
this.genericProvider.removeListener('block', handler); | ||
reject('Timed out'); | ||
}, timeout); | ||
if (timer.unref) { | ||
timer.unref(); | ||
} | ||
} | ||
}); | ||
} | ||
async getUserStats() { | ||
@@ -235,3 +343,3 @@ const blockDetails = await this.genericProvider.getBlock('latest'); | ||
const params = [evmBlockNumber]; | ||
const request = JSON.stringify(this.prepareBundleRequest('flashbots_getUserStats', params)); | ||
const request = JSON.stringify(this.prepareRelayRequest('flashbots_getUserStats', params)); | ||
const response = await this.request(request); | ||
@@ -251,3 +359,3 @@ if (response.error !== undefined && response.error !== null) { | ||
const params = [{ bundleHash, blockNumber: evmBlockNumber }]; | ||
const request = JSON.stringify(this.prepareBundleRequest('flashbots_getBundleStats', params)); | ||
const request = JSON.stringify(this.prepareRelayRequest('flashbots_getBundleStats', params)); | ||
const response = await this.request(request); | ||
@@ -292,3 +400,3 @@ if (response.error !== undefined && response.error !== null) { | ||
]; | ||
const request = JSON.stringify(this.prepareBundleRequest('eth_callBundle', params)); | ||
const request = JSON.stringify(this.prepareRelayRequest('eth_callBundle', params)); | ||
const response = await this.request(request); | ||
@@ -459,3 +567,3 @@ if (response.error !== undefined && response.error !== null) { | ||
} | ||
prepareBundleRequest(method, params) { | ||
prepareRelayRequest(method, params) { | ||
return { | ||
@@ -462,0 +570,0 @@ method: method, |
{ | ||
"name": "@flashbots/ethers-provider-bundle", | ||
"version": "0.4.4", | ||
"version": "0.5.0", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "build/index.js", |
# ethers-provider-flashbots-bundle | ||
This repository contains the `FlashbotsBundleProvider` ethers.js provider, an additional `Provider` to `ethers.js` to enable high-level access to `eth_sendBundle` and `eth_callBundle` rpc endpoint on [mev-relay](https://github.com/flashbots/mev-relay-js). **`mev-relay` is a hosted service; it is not necessary to run `mev-relay` or `mev-geth` to proceed with this example.** | ||
This repository contains the `FlashbotsBundleProvider` ethers.js provider, an additional `Provider` to `ethers.js` to enable high-level access to `eth_sendBundle` and `eth_callBundle` rpc endpoint on [mev-relay](https://github.com/flashbots/mev-relay-js). **`mev-relay` is a hosted service; it is not necessary to run `mev-relay` or `mev-geth` to proceed with this example.** | ||
@@ -13,3 +13,4 @@ Flashbots-enabled relays and miners expose two new jsonrpc endpoints: `eth_sendBundle` and `eth_callBundle`. Since these are non-standard endpoints, ethers.js and other libraries do not natively support these requests (like `getTransactionCount`). In order to interact with these endpoints, you will need access to another full-featured (non-Flashbots) endpoint for nonce-calculation, gas estimation, and transaction status. | ||
Install ethers.js and the Flashbots ethers bundle provider | ||
Install ethers.js and the Flashbots ethers bundle provider. | ||
```bash | ||
@@ -65,2 +66,3 @@ npm install --save ethers | ||
## Block Targeting | ||
The last thing required for `sendBundle()` is block targeting. Every bundle specifically references a single block. If your bundle is valid for multiple blocks (including all blocks until it is mined), `sendBundle()` must be called for every block, ideally on one of the blocks immediately prior. This gives you a chance to re-evaluate the opportunity you are capturing and re-sign your transactions with a higher nonce, if necessary. | ||
@@ -75,5 +77,6 @@ | ||
## Gas Prices and EIP-1559 | ||
Before EIP-1559 was activated, the most common way for searchers to submit transactions is with `gasPrice=0`, with an on-chain payment to `block.coinbase` conditional on the transaction's success. All transactions must pay `baseFee` now, an attribute of a block. For an example of how to ensure you are using this `baseFee`, see `demo.ts` in this repository. | ||
``` | ||
Before EIP-1559 was activated, the most common way for searchers to submit transactions is with `gasPrice=0`, with an on-chain payment to `block.coinbase` conditional on the transaction's success. All transactions must pay `baseFee` now, an attribute of a block. For an example of how to ensure you are using this `baseFee`, see `demo.ts` in this repository. | ||
```js | ||
const block = await provider.getBlock(blockNumber) | ||
@@ -107,2 +110,3 @@ const maxBaseFeeInFutureBlock = FlashbotsBundleProvider.getMaxBaseFeeInFutureBlock(block.baseFeePerGas, BLOCKS_IN_THE_FUTURE) | ||
Simulate: | ||
```ts | ||
@@ -115,2 +119,3 @@ const signedTransactions = await flashbotsProvider.signBundle(transactionBundle) | ||
Send: | ||
```ts | ||
@@ -124,2 +129,3 @@ const flashbotsTransactionResponse = await flashbotsProvider.sendBundle( | ||
## FlashbotsTransactionResponse | ||
After calling `sendBundle`, this provider will return a Promise of an object with helper functions related to the bundle you submitted. | ||
@@ -137,2 +143,3 @@ | ||
Beyond target block number, an object can be passed in with optional attributes: | ||
```ts | ||
@@ -148,3 +155,3 @@ { | ||
While each bundle targets only a single block, you can add a filter for validity based on the block's timestamp. This does *not* allow for targeting any block number based on a timestamp or instruct miners on what timestamp to use, it merely serves as a secondary filter. | ||
While each bundle targets only a single block, you can add a filter for validity based on the block's timestamp. This does _not_ allow for targeting any block number based on a timestamp or instruct miners on what timestamp to use, it merely serves as a secondary filter. | ||
@@ -157,3 +164,3 @@ If your bundle is not valid before a certain time or includes an expiring opportunity, setting these values allows the miner to skip bundle processing earlier in the phase. | ||
Transaction bundles will not be considered for inclusion if they include *any* transactions that revert or fail. While this is normally desirable, there are some advanced use-cases where a searcher might WANT to bring a failing transaction to the chain. This is normally desirable for nonce management. Consider: | ||
Transaction bundles will not be considered for inclusion if they include _any_ transactions that revert or fail. While this is normally desirable, there are some advanced use-cases where a searcher might WANT to bring a failing transaction to the chain. This is normally desirable for nonce management. Consider: | ||
@@ -181,2 +188,3 @@ Transaction Nonce #1 = Failed (unrelated) token transfer | ||
## Bundle and User Statistics | ||
The Flashbots relay can also return statistics about you as a user (identified solely by your signing address) and any bundle previously submitted. | ||
@@ -186,2 +194,3 @@ | ||
- `getBundleStats(bundleHash, targetBlockNumber)` returns data specific to a single bundle submission, including detailed timestamps for the various phases a bundle goes before reaching miners. You can get the bundleHash from the simulation: | ||
```js | ||
@@ -202,2 +211,36 @@ const simulation = await flashbotsProvider.simulate(signedTransactions, targetBlockNumber) | ||
## Sending a Private Transaction | ||
To send a _single_ transaction without having to send it as a bundle, use the `sendPrivateTransaction` function. This method allows us to process transactions faster and more efficiently than regular bundles. When you send a transaction using this method, we will try to send it to miners over the next 25 blocks (up to, but not past the target block number). | ||
```js | ||
const tx = { | ||
from: wallet.address, | ||
to: wallet.address, | ||
value: "0x42", | ||
gasPrice: BigNumber.from(99).mul(1e9), // 99 gwei | ||
gasLimit: BigNumber.from(21000), | ||
} | ||
const privateTx = { | ||
transaction: tx, | ||
signer: wallet, | ||
} | ||
const res = await flashbotsProvider.sendPrivateTransaction(privateTx) | ||
``` | ||
Optionally, you can set the following parameters to fine-tune your submission: | ||
```js | ||
// highest block number your tx can be included in | ||
const maxBlockNumber = (await provider.getBlockNumber()) + 10; | ||
// timestamp for simulations | ||
const minTimestamp = 1645753192; | ||
const res = await flashbotsProvider.sendPrivateTransaction( | ||
privateTx, | ||
{maxBlockNumber, minTimestamp} | ||
) | ||
``` | ||
## Flashbots on Goerli | ||
@@ -208,2 +251,3 @@ | ||
1. Ensure your genericProvider passed in to the FlashbotsBundleProvider constructor is connected to Goerli (gas estimates and nonce requests need to correspond to the correct chain): | ||
```ts | ||
@@ -215,2 +259,3 @@ import { providers } from 'ethers' | ||
2. Set the relay endpoint to `https://relay-goerli.flashbots.net/` | ||
```ts | ||
@@ -217,0 +262,0 @@ const flashbotsProvider = await FlashbotsBundleProvider.create( |
154
src/index.ts
@@ -11,2 +11,3 @@ import { BlockTag, TransactionReceipt, TransactionRequest } from '@ethersproject/abstract-provider' | ||
export const BASE_FEE_MAX_CHANGE_DENOMINATOR = 8 | ||
const PRIVATE_TX_WAIT_BLOCKS = 25 // # of blocks | ||
@@ -19,2 +20,7 @@ export enum FlashbotsBundleResolution { | ||
export enum FlashbotsTransactionResolution { | ||
TransactionIncluded, | ||
TransactionDropped, | ||
} | ||
export enum FlashbotsBundleConflictType { | ||
@@ -59,2 +65,9 @@ NoConflict, | ||
export interface FlashbotsPrivateTransactionResponse { | ||
transaction: TransactionAccountNonce | ||
wait: () => Promise<FlashbotsTransactionResolution> | ||
simulate: () => Promise<SimulationResponse> | ||
receipts: () => Promise<Array<TransactionReceipt>> | ||
} | ||
export interface TransactionSimulationBase { | ||
@@ -100,2 +113,4 @@ txHash: string | ||
export type FlashbotsPrivateTransaction = FlashbotsPrivateTransactionResponse | RelayResponseError | ||
export interface GetUserStatsResponseSuccess { | ||
@@ -289,3 +304,3 @@ signing_address: string | ||
const request = JSON.stringify(this.prepareBundleRequest('eth_sendBundle', [params])) | ||
const request = JSON.stringify(this.prepareRelayRequest('eth_sendBundle', [params])) | ||
const response = await this.request(request) | ||
@@ -313,3 +328,3 @@ if (response.error !== undefined && response.error !== null) { | ||
bundleTransactions, | ||
wait: () => this.wait(bundleTransactions, targetBlockNumber, TIMEOUT_MS), | ||
wait: () => this.waitForBlock(bundleTransactions, targetBlockNumber, TIMEOUT_MS), | ||
simulate: () => | ||
@@ -336,2 +351,72 @@ this.simulate( | ||
public async sendPrivateTransaction( | ||
transaction: FlashbotsBundleTransaction | FlashbotsBundleRawTransaction, | ||
opts?: { | ||
maxBlockNumber?: number, | ||
simulationTimestamp?: number, | ||
}, | ||
): Promise<FlashbotsPrivateTransaction> { | ||
let signedTransaction: string; | ||
if ("signedTransaction" in transaction) { | ||
signedTransaction = transaction.signedTransaction | ||
} else { | ||
signedTransaction = await transaction.signer.signTransaction(transaction.transaction) | ||
} | ||
const startBlockNumberPromise = this.genericProvider.getBlockNumber() | ||
const params = { | ||
tx: signedTransaction, | ||
maxBlockNumber: opts?.maxBlockNumber, | ||
} | ||
const request = JSON.stringify(this.prepareRelayRequest('eth_sendPrivateTransaction', [params])) | ||
const response = await this.request(request) | ||
if (response.error !== undefined && response.error !== null) { | ||
return { | ||
error: { | ||
message: response.error.message, | ||
code: response.error.code | ||
} | ||
} | ||
} | ||
const transactionDetails = ethers.utils.parseTransaction(signedTransaction) | ||
const privateTransaction = { | ||
signedTransaction: signedTransaction, | ||
hash: ethers.utils.keccak256(signedTransaction), | ||
account: transactionDetails.from || "0x0", | ||
nonce: transactionDetails.nonce, | ||
} | ||
const startBlockNumber = await startBlockNumberPromise | ||
return { | ||
transaction: privateTransaction, | ||
wait: () => this.waitForTxInclusion(privateTransaction.hash, opts?.maxBlockNumber || startBlockNumber + 25, TIMEOUT_MS), | ||
simulate: () => | ||
this.simulate( | ||
[privateTransaction.signedTransaction], | ||
startBlockNumber, | ||
undefined, | ||
opts?.simulationTimestamp, | ||
), | ||
receipts: () => this.fetchReceipts([privateTransaction]), | ||
} | ||
} | ||
public async cancelPrivateTransaction(txHash: string): Promise<boolean | RelayResponseError> { | ||
const params = { | ||
txHash, | ||
} | ||
const request = JSON.stringify(this.prepareRelayRequest('eth_cancelPrivateTransaction', [params])) | ||
const response = await this.request(request) | ||
if (response.error !== undefined && response.error !== null) { | ||
return { | ||
error: { | ||
message: response.error.message, | ||
code: response.error.code | ||
} | ||
} | ||
} | ||
return true; | ||
} | ||
public async signBundle(bundledTransactions: Array<FlashbotsBundleTransaction | FlashbotsBundleRawTransaction>): Promise<Array<string>> { | ||
@@ -366,3 +451,3 @@ const nonces: { [address: string]: BigNumber } = {} | ||
private wait(transactionAccountNonces: Array<TransactionAccountNonce>, targetBlockNumber: number, timeout: number) { | ||
private waitForBlock(transactionAccountNonces: Array<TransactionAccountNonce>, targetBlockNumber: number, timeout: number) { | ||
return new Promise<FlashbotsBundleResolution>((resolve, reject) => { | ||
@@ -411,3 +496,2 @@ let timer: NodeJS.Timer | null = null | ||
done = true | ||
this.genericProvider.removeListener('block', handler) | ||
@@ -435,2 +519,54 @@ } | ||
private waitForTxInclusion(transactionHash: string, maxBlockNumber: number, timeout: number) { | ||
return new Promise<FlashbotsTransactionResolution>((resolve, reject) => { | ||
let timer: NodeJS.Timer | null = null | ||
let done = false | ||
// runs on new block event | ||
const handler = async (blockNumber: number) => { | ||
if (blockNumber <= maxBlockNumber) { | ||
// check tx status on mainnet | ||
const sentTxStatus = await this.genericProvider.getTransaction(transactionHash) | ||
if (sentTxStatus && sentTxStatus.confirmations >= 1) { | ||
resolve(FlashbotsTransactionResolution.TransactionIncluded) | ||
} else { | ||
return | ||
} | ||
} else { | ||
// tx not included in specified range, bail | ||
this.genericProvider.removeListener('block', handler) | ||
resolve(FlashbotsTransactionResolution.TransactionDropped) | ||
} | ||
if (timer) { | ||
clearTimeout(timer) | ||
} | ||
if (done) { | ||
return | ||
} | ||
done = true | ||
this.genericProvider.removeListener('block', handler) | ||
} | ||
this.genericProvider.on('block', handler) | ||
// time out if we've been trying for too long | ||
if (timeout > 0) { | ||
timer = setTimeout(() => { | ||
if (done) { | ||
return | ||
} | ||
timer = null | ||
done = true | ||
this.genericProvider.removeListener('block', handler) | ||
reject('Timed out') | ||
}, timeout) | ||
if (timer.unref) { | ||
timer.unref() | ||
} | ||
} | ||
}) | ||
} | ||
public async getUserStats(): Promise<GetUserStatsResponse> { | ||
@@ -441,3 +577,3 @@ const blockDetails = await this.genericProvider.getBlock('latest') | ||
const params = [evmBlockNumber] | ||
const request = JSON.stringify(this.prepareBundleRequest('flashbots_getUserStats', params)) | ||
const request = JSON.stringify(this.prepareRelayRequest('flashbots_getUserStats', params)) | ||
const response = await this.request(request) | ||
@@ -460,3 +596,3 @@ if (response.error !== undefined && response.error !== null) { | ||
const params = [{ bundleHash, blockNumber: evmBlockNumber }] | ||
const request = JSON.stringify(this.prepareBundleRequest('flashbots_getBundleStats', params)) | ||
const request = JSON.stringify(this.prepareRelayRequest('flashbots_getBundleStats', params)) | ||
const response = await this.request(request) | ||
@@ -507,3 +643,3 @@ if (response.error !== undefined && response.error !== null) { | ||
] | ||
const request = JSON.stringify(this.prepareBundleRequest('eth_callBundle', params)) | ||
const request = JSON.stringify(this.prepareRelayRequest('eth_callBundle', params)) | ||
const response = await this.request(request) | ||
@@ -707,4 +843,4 @@ if (response.error !== undefined && response.error !== null) { | ||
private prepareBundleRequest( | ||
method: 'eth_callBundle' | 'eth_sendBundle' | 'flashbots_getUserStats' | 'flashbots_getBundleStats', | ||
private prepareRelayRequest( | ||
method: 'eth_callBundle' | 'eth_sendBundle' | 'eth_sendPrivateTransaction' | 'eth_cancelPrivateTransaction' | 'flashbots_getUserStats' | 'flashbots_getBundleStats', | ||
params: RpcParams | ||
@@ -711,0 +847,0 @@ ) { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
239361
1896
254