Skip to content

Instantly share code, notes, and snippets.

@coffeexcoin
Created August 18, 2024 18:02
Show Gist options
  • Save coffeexcoin/4a74f4306205ce9995668bdfa835d458 to your computer and use it in GitHub Desktop.
Save coffeexcoin/4a74f4306205ce9995668bdfa835d458 to your computer and use it in GitHub Desktop.
viem flashbots
import { Account, Address, Chain, Client, ClientConfig, createClient, createTestClient, Hash, Hex, http, ParseAccount, Prettify, RpcSchema, Transport } from "viem";
export type FlashbotsRpcSchema = [
/**
* @description Simulate a bundle against a specific block number, including simulating a bundle at the top of the next block.
* @link https://docs.flashbots.net/flashbots-auction/advanced/rpc-endpoint#eth_callbundle
* @example
* provider.request({ method: 'eth_callBundle', params: [ txs: ['0x...', '0x...'], blockNumber: '0x...', stateBlockNumber: '0x...' ] })
* // => { bundleGasPrice: '0x...', bundleHash: '0x...', coinbaseDiff: '0x...', ethSentToCoinbase: '0x...', gasFees: '0x...', results: [ { coinbaseDiff: '0x...', ethSentToCoinbase: '0x...', gasFees: '0x...', gasUsed: '0x...', toAddress: '0x...', txHash: '0x...', value: '0x...' } ], stateBlockNumber: '0x...', totalGasUsed: '0x...' }
*/
{
Method: 'eth_callBundle',
Parameters?: [CallBundleRequestParams]
ReturnType: CallBundleResponseType
},
]
export type FlashbotsActions<
transport extends Transport = Transport,
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
> = {
/**
* Simulate a bundle against a specific block number, including simulating a bundle at the top of the next block.
*
* - Docs: https://viem.sh/docs/actions/flashbots/call
* - JSON-RPC Methods: [`eth_callBundle`](https://docs.flashbots.net/flashbots-auction/advanced/rpc-endpoint#eth_callbundle)
*
* @param args - {@link CallBundleRequestParams}
* @returns The simulated call results. {@link CallBundleResponseType}
*
* @example
* import { createFlashbotsClient, http } from 'viem'
* import { mainnet } from 'viem/chains'
*
* const client = createFlashbotsClient({
* chain: mainnet,
* transport: http(),
* })
* const data = await client.callBundle({
* txs: '0x...',
* blockNumber: '0x...',
* stateBlockNumber: '0x...'
* })
*/
callBundle: (args: CallBundleRequestParams) => Promise<CallBundleResponseType>
}
type FlashbotsClient<
transport extends Transport = Transport,
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = undefined,
rpcSchema extends RpcSchema | undefined = undefined,
> = Prettify<
Client<
transport,
chain,
account,
rpcSchema extends RpcSchema
? [...FlashbotsRpcSchema, ...rpcSchema]
: FlashbotsRpcSchema,
FlashbotsActions<transport, chain>
>
>
export type FlashbotsClientConfig<
transport extends Transport = Transport,
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = undefined,
rpcSchema extends RpcSchema | undefined = undefined,
> = Prettify<
ClientConfig<transport, chain, account, rpcSchema>
>
export function createFlashbotsClient<
transport extends Transport,
chain extends Chain | undefined = undefined,
account extends Account | undefined = undefined,
rpcSchema extends RpcSchema | undefined = undefined,
>(
parameters: FlashbotsClientConfig<transport, chain, account, rpcSchema>,
): FlashbotsClient<transport, chain, ParseAccount<account>, rpcSchema> {
const { key = 'flashbots', name = 'Flashbots Client' } = parameters
const client = createClient({
...parameters,
key,
name,
type: 'flashbotsClient',
})
return client.extend(flashbotsActions) as any
}
type CallBundleRequestParams = {
txs: Array<Hex>,
blockNumber: bigint,
stateBlockNumber: bigint | "latest",
timestamp?: number
}
type CallBundleResponseType = {
bundleGasPrice: bigint,
bundleHash: Hex,
coinbaseDiff: bigint,
ethSentToCoinbase: bigint,
gasFees: bigint,
results: Array<{
coinbaseDiff: bigint,
ethSentToCoinbase: bigint,
gasFees: bigint,
gasUsed: bigint,
toAddress: Address,
txHash: Hash,
value: bigint
}>,
stateBlockNumber: number,
totalGasUsed: number
}
export function flashbotsActions<
transport extends Transport = Transport,
chain extends Chain | undefined = Chain | undefined,
account extends Account | undefined = Account | undefined,
>(
client: FlashbotsClient
): FlashbotsActions {
return {
callBundle: (args) => callBundle(client, args)
}
}
export async function callBundle<
chain extends Chain | undefined,
account extends Account | undefined = undefined,
>(
client: FlashbotsClient<Transport, chain, account>,
args: CallBundleRequestParams,
): Promise<CallBundleResponseType> {
const response = await client.request({
method: "eth_callBundle",
params: [args]
})
return response;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment