Flashbots MEV - 共享客户端
用 Typescript 书写的 MEV-Share 客户端库 .
依据 MEV- 共享光谱。 。 。 .
快速启动
从 npm 安装 :
yarn add @flashbots/mev-share-client
# or
npm i @flashbots/mev-share-client
或者,从源头复制库并构建:
git clone https://github.com/flashbots/mev-share-client-ts
cd mev-share-client-ts
yarn install && yarn build
# in your project, assuming it has the same parent directory as mev-share-client-ts
yarn add ../mev-share-client-ts
在您的项目中使用 mev- share- 客户端
:警告:变量表示于
ALL_CAPS是占位符;代码不编译. 实例/ 包含可编译的演示.
在你的项目中:
import { Wallet, JsonRpcProvider } from "ethers"
import MevShareClient, {
BundleParams,
HintPreferences,
IPendingBundle,
IPendingTransaction,
TransactionOptions
} from "@flashbots/mev-share-client"
const provider = new JsonRpcProvider(RPC_URL)
const authSigner = new Wallet(FB_REPUTATION_PRIVATE_KEY, provider)
这个 MevShareClient 类有Flashbots支持的网络的内置初始化器.
连接到 Ethereum 主网
const mevshare = MevShareClient.useEthereumMainnet(authSigner)
连接到 Etheryum Goerli
const mevshare = MevShareClient.useEthereumGoerli(authSigner)
连接到以太提供者或链式ID
Flashbot支持的网络有内置预设. 如果更方便的话,你可以使用一个 chainId (或乙醚.js) Network 对象,该对象有一个 chainId (第1款).
import { JsonRpcProvider, Wallet } from "ethers" // ethers v6
/** connects to Flashbots MEV-Share node on goerli */
const provider = new JsonRpcProvider("http://localhost:8545", {chainId: 5, name: "goerli"})
const authSigner = new Wallet("0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80")
.connect(provider)
const mevshare = MevShareClient.fromNetwork(authSigner, provider._network)
// manually with a chainId:
const mevshare = MevShareClient.fromNetwork(authSigner, {chainId: 5})
连接到自定义网络
要使用自定义网络参数, 您可以即时切换新参数 MevShareClient 直接出现。 这个例子是客户端用来连接主网的:
const mevshare = new MevShareClient(authSigner, {
name: "mainnet",
chainId: 1,
streamUrl: "https://mev-share.flashbots.net",
apiUrl: "https://relay.flashbots.net"
})
见 MevShareNetwork 内 src/ api/ 接口 更多细节.
实例
: 信息 来源:实例要求a
.env文件(或您直接用相应的变量填充环境).
cd src/examples
cp .env.example .env
vim .env
发送带有提示的 tx
此示例从 SENDER PRIVATE KEY 指定的账户中向 Goerli 上的 Flashbots MEV-Share 节点发送交易,并以六进制字符串作为调用数据 .
yarn example.tx
返回运行待决 tx
这个例子观察了 mev-share 流端待处理的 mev-share 交易,并试图备份全部交易. 此示例一直运行到一个后运行被包含在链上.
yarn example.backrun
查询事件历史
这个示例查询事件历史,从开始,直到找到共享交易和日志的事件.
yarn example.history
使用量
见 src/api/interfaces.ts (中文(简体) ) 用于界面定义.
on
使用 on 开始听关于Mev-share的事件。 函数登记在检测出新事件时调用提供的回调 .
const handler = mevshare.on("transaction", (tx: IPendingTransaction) => {
// handle pending tx
})
// ... before terminating program
handler.close()
sendTransaction
向 Flashbots MEV-Share 节点发送带有指定提示参数的私人交易.
const wallet = new Wallet(PRIVATE_KEY)
const tx = {
to: "0xfb000000387627910184cc42fc92995913806333",
value: BigInt(1e13 * 275), // price of a beer if ETH is $2000
data: "0x646f637320626179626565652121",
gasLimit: 42000,
maxFeePerGas: BigInt(1e9) * BigInt(42), // 42 gwei / gas
maxPriorityFeePerGas: BigInt(1e9) * BigInt(2), // 2 gwei / gas
chainId: 5,
type: 2,
}
// privacy & inclusion settings
const shareTxParams: TransactionOptions = {
hints: {
logs: true,
calldata: false,
functionSelector: true,
contractAddress: true,
},
maxBlockNumber: undefined,
builders: ["flashbots"]
}
const signedTx = await wallet.signTransaction(tx)
await mevshare.sendTransaction(SIGNED_TX, shareTxParams)
sendBundle
发送捆绑; 一系列带有参数的交易来指定包含条件和MEV回扣. 交易放在 body 带有折叠符的参数,以表示它们是新签的交易还是事件流的待决交易.
见 MEV - 共享文档 用于详细描述这些参数.
const targetBlock = 1 + await provider.getBlockNumber()
const bundleParams: BundleParams = {
inclusion: {
block: targetBlock,
},
body: [
{hash: TX_HASH_FROM_EVENT_STREAM},
{tx: SIGNED_TX, canRevert: false},
],
}
await mevshare.sendBundle(bundleParams)
包起来 仅限 包含签名交易的提示, 通过设置 privacy 参数 :
const targetBlock = 1 + await provider.getBlockNumber()
const bundleParams: BundleParams = {
inclusion: {
block: targetBlock,
maxBlock: targetBlock + 5, // allow bundle to land in next 5 blocks
},
body: [
{tx: await wallet.signTransaction(TX1), canRevert: false},
{tx: await wallet.signTransaction(TX2), canRevert: false},
],
privacy: {
hints: {
txHash: true,
calldata: true,
logs: true,
functionSelector: true,
contractAddress: true,
},
}
}
const backrunResult = await mevshare.sendBundle(bundleParams)
simulateBundle
模拟一捆. 接受修改块头以进行模拟的选项.
const bundle: BundleParams = {
inclusion: {
block: TARGET_BLOCK,
maxBlock: TARGET_BLOCK + 3,
},
body: [
{hash: "0xTARGET_TX_HASH"},
{tx: "0xSIGNED_BACKRUN_TX", canRevert: false}
],
// ...
}
// ...
// assume you sent the bundle and it didn't land, and you want to see if it would have landed in the previous block, but need the tx to think it's in the target block
const simBundleOptions: SimBundleOptions = {
parentBlock: TARGET_BLOCK - 1,
blockNumber: TARGET_BLOCK,
/*
Set any of these (block header) fields to override their respective values in the simulation context:
*/
// coinbase: string,
// timestamp: number,
// gasLimit: number,
// baseFee: bigint,
// timeout: number,
}
const simResult = await mevshare.simulateBundle(bundle, simBundleOptions)
此示例使用 parentBlock,但压倒了该州的 blockNumber 数值。 设置更多字段 SimBundleOptions 当测试有特定标准必须达到的智能合同时,例如块是一定数量,或者某个特定的时标已经通过,这些合同是有用的.
getEventHistoryInfo
获取关于事件历史终点的信息以用于 getEventHistory。 。 。 .
示例
const info = await mevshare.getEventHistoryInfo()
console.log(info)
返回这样的东西 :
{
count: 56934,
minBlock: 9091377,
maxBlock: 9190024,
minTimestamp: 1685452445,
maxTimestamp: 1686943324,
maxLimit: 500
}
getEventHistory
获取历史事件流数据.
利用我们的数据 getEventHistoryInfo 我们可以从头看事情 数据是被标注的,所以要读出所有的数据,你就必须通过它多次拨打来进行去除.
const info = await mevshare.getEventHistoryInfo()
// read every event
for (let i = 0; i < Math.ceil(info.count / info.maxLimit); i++) {
const events = await mevshare.getEventHistory({
limit: info.maxLimit,
offset: i * info.maxLimit,
blockStart: info.minBlock,
})
console.log(events)
}
您也可以通过时间戳过滤事件 :
const events = await mevshare.getEventHistory({
limit: info.maxLimit,
offset: i * info.maxLimit,
timestampStart: 1686942023,
})