This is a go library for simulating and sending bundles to the Flashbots mev-geth relay.
Simulate Bundle
start := time.Now()
signingKey, _ := crypto.HexToECDSA(flashbotsSigningKeyHex)
privateKey, _ := crypto.HexToECDSA(privateKeyHex)
publicKeyCrypto := privateKey.Public()
publicKey, _ := publicKey.(*ecdsa.publicKeyCrypto)
client, err = ethclient.Dial(providerURL)
if err != nil {
log.Fatal(err)
}
// signedTxs is an array of signed transactions objects
// signedTxs []*types.Transaction
txs := []string{}
for _, tx := range signedTxs {
data, err := tx.MarshalBinary()
if err != nil {
log.Fatal(err)
}
txs = append(txs, hexutil.Encode(data))
}
block, err := client.HeaderByNumber(context.Background(), nil)
if err != nil {
log.Fatal(err)
}
fb := flashbots.NewProvider(signingKey, privateKey, flashbots.DefaultRelayURL)
resp, err := fb.Simulate(txs, block.Number, "latest", 0)
if err != nil {
log.Fatal(err)
}
err = resp.HasError()
if err != nil {
log.Fatal(err)
}
cb, _ := new(big.Float).SetString(resp.Result.CoinbaseDiff)
eth := new(big.Float).Quo(cb, big.NewFloat(math.Pow10(18)))
wei, _ := resp.EffectiveGasPrice()
gwei := toGwei(wei)
fmt.Printf("Simulation completed in %fs. Cost: %f eth, effective price: %d gwei\n", time.Since(start).Seconds(), eth, gwei)
Send Bundle
signingKey, _ := crypto.HexToECDSA(flashbotsSigningKeyHex)
privateKey, _ := crypto.HexToECDSA(privateKeyHex)
publicKeyCrypto := privateKey.Public()
publicKey, _ := publicKey.(*ecdsa.publicKeyCrypto)
client, err = ethclient.Dial(providerURL)
if err != nil {
log.Fatal(err)
}
// signedTxs is an array of signed transactions objects
// signedTxs []*types.Transaction
txs := []string{}
for _, tx := range signedTxs {
data, err := tx.MarshalBinary()
if err != nil {
log.Fatal(err)
}
txs = append(txs, hexutil.Encode(data))
}
block, err := client.HeaderByNumber(context.Background(), nil)
if err != nil {
log.Fatal(err)
}
fb := flashbots.NewProvider(signingKey, privateKey, flashbots.DefaultRelayURL)
for i := int64(0); i < attempts; i++ {
targetBlockNumber := new(big.Int).Add(block.Number, big.NewInt(int64(i)))
_, err := fb.SendBundle(txs, targetBlockNumber, &flashbots.Options{})
if err != nil {
log.Fatal(err)
}
fmt.Printf("submitted for block: %d\n", targetBlockNumber)
}