Skip to content
This repository was archived by the owner on Oct 20, 2024. It is now read-only.

Commit 8e662ad

Browse files
authored
Implement flashbots_getBundleStats (metachris#9)
* Implement flashbots_getBundleStats * Add FlashbotsGetBundleStats example * Handle error in the FlashbotsGetBundleStats example
1 parent e8a0f2d commit 8e662ad

File tree

4 files changed

+121
-1
lines changed

4 files changed

+121
-1
lines changed

examples/getbundlestats/main.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package main
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
7+
"github.com/ethereum/go-ethereum/crypto"
8+
"github.com/metachris/flashbotsrpc"
9+
)
10+
11+
var privateKey, _ = crypto.GenerateKey() // creating a new private key for testing. you probably want to use an existing key.
12+
// var privateKey, _ = crypto.HexToECDSA("YOUR_PRIVATE_KEY")
13+
14+
func main() {
15+
rpc := flashbotsrpc.New("https://relay.flashbots.net")
16+
rpc.Debug = true
17+
18+
sendBundleArgs := flashbotsrpc.FlashbotsSendBundleRequest{
19+
Txs: []string{"YOUR_RAW_TX"},
20+
BlockNumber: fmt.Sprintf("0x%x", 13281018),
21+
}
22+
23+
result, err := rpc.FlashbotsSendBundle(privateKey, sendBundleArgs)
24+
if err != nil {
25+
if errors.Is(err, flashbotsrpc.ErrRelayErrorResponse) {
26+
// ErrRelayErrorResponse means it's a standard Flashbots relay error response, so probably a user error, rather than JSON or network error
27+
fmt.Println(err.Error())
28+
} else {
29+
fmt.Printf("error: %+v\n", err)
30+
}
31+
return
32+
}
33+
34+
getBundleStatsArgs := flashbotsrpc.FlashbotsGetBundleStatsParam{
35+
BlockNumber: fmt.Sprintf("0x%x", 13281018),
36+
BundleHash: result.BundleHash,
37+
}
38+
bundleStats, err := rpc.FlashbotsGetBundleStats(privateKey, getBundleStatsArgs)
39+
if err != nil {
40+
if errors.Is(err, flashbotsrpc.ErrRelayErrorResponse) {
41+
// ErrRelayErrorResponse means it's a standard Flashbots relay error response, so probably a user error, rather than JSON or network error
42+
fmt.Println(err.Error())
43+
} else {
44+
fmt.Printf("error: %+v\n", err)
45+
}
46+
return
47+
}
48+
49+
// Print result
50+
fmt.Printf("%+v\n", bundleStats)
51+
}

flashbotsrpc.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,15 @@ func (rpc *FlashbotsRPC) FlashbotsSendBundle(privKey *ecdsa.PrivateKey, param Fl
640640
return res, err
641641
}
642642

643+
func (rpc *FlashbotsRPC) FlashbotsGetBundleStats(privKey *ecdsa.PrivateKey, param FlashbotsGetBundleStatsParam) (res FlashbotsGetBundleStatsResponse, err error) {
644+
rawMsg, err := rpc.CallWithFlashbotsSignature("flashbots_getBundleStats", privKey, param)
645+
if err != nil {
646+
return res, err
647+
}
648+
err = json.Unmarshal(rawMsg, &res)
649+
return res, err
650+
}
651+
643652
// Simulate a full Ethereum block. numTx is the maximum number of tx to include, used for troubleshooting (default: 0 - all transactions)
644653
func (rpc *FlashbotsRPC) FlashbotsSimulateBlock(privKey *ecdsa.PrivateKey, block *types.Block, maxTx int) (res FlashbotsCallBundleResponse, err error) {
645654
if rpc.Debug {

flashbotsrpc_test.go

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
package flashbotsrpc
22

33
import (
4+
"crypto/ecdsa"
45
"errors"
56
"fmt"
67
"io/ioutil"
78
"math/big"
89
"net/http"
910
"strconv"
1011
"testing"
12+
"time"
1113

14+
"github.com/ethereum/go-ethereum/crypto"
1215
"github.com/jarcoal/httpmock"
1316
"github.com/stretchr/testify/require"
1417
"github.com/stretchr/testify/suite"
@@ -17,7 +20,8 @@ import (
1720

1821
type FlashbotsRPCTestSuite struct {
1922
suite.Suite
20-
rpc *FlashbotsRPC
23+
rpc *FlashbotsRPC
24+
privKey *ecdsa.PrivateKey
2125
}
2226

2327
func (s *FlashbotsRPCTestSuite) registerResponse(result string, callback func([]byte)) {
@@ -62,6 +66,9 @@ func (s *FlashbotsRPCTestSuite) paramsEqual(body []byte, expected string) {
6266
func (s *FlashbotsRPCTestSuite) SetupSuite() {
6367
s.rpc = NewFlashbotsRPC("http://127.0.0.1:8545", WithHttpClient(http.DefaultClient), WithLogger(nil), WithDebug(false))
6468

69+
privateKey, _ := crypto.GenerateKey()
70+
s.privKey = privateKey
71+
6572
httpmock.Activate()
6673
}
6774

@@ -1148,6 +1155,44 @@ func (s *FlashbotsRPCTestSuite) TestEthUninstallFilter() {
11481155
s.Require().Equal(boolRes, uninstall)
11491156
}
11501157

1158+
func (s *FlashbotsRPCTestSuite) TestFlashbotsGetBundleStats() {
1159+
params := FlashbotsGetBundleStatsParam{
1160+
BlockNumber: "0x7a69",
1161+
BundleHash: "0xdeadc0de",
1162+
}
1163+
1164+
s.registerResponseError(errors.New("Error"))
1165+
_, err := s.rpc.FlashbotsGetBundleStats(s.privKey, params)
1166+
s.Require().NotNil(err)
1167+
1168+
response := `{
1169+
"isSimulated": true,
1170+
"isSentToMiners": true,
1171+
"isHighPriority": true,
1172+
"simulatedAt": "2021-08-06T21:36:06.317Z",
1173+
"submittedAt": "2021-08-06T21:36:06.250Z",
1174+
"sentToMinersAt": "2021-08-06T21:36:06.343Z"
1175+
}`
1176+
1177+
s.registerResponse(response, func(body []byte) {
1178+
s.methodEqual(body, "flashbots_getBundleStats")
1179+
s.paramsEqual(body, `[{"blockNumber": "0x7a69", "bundleHash": "0xdeadc0de"}]`)
1180+
})
1181+
1182+
bundleStats, err := s.rpc.FlashbotsGetBundleStats(s.privKey, params)
1183+
s.Require().Nil(err)
1184+
1185+
expected := FlashbotsGetBundleStatsResponse{
1186+
IsSimulated: true,
1187+
IsSentToMiners: true,
1188+
IsHighPriority: true,
1189+
SimulatedAt: time.Date(2021, 8, 6, 21, 36, 6, 317000000, time.UTC),
1190+
SubmittedAt: time.Date(2021, 8, 6, 21, 36, 6, 250000000, time.UTC),
1191+
SentToMinersAt: time.Date(2021, 8, 6, 21, 36, 6, 343000000, time.UTC),
1192+
}
1193+
s.Require().Equal(expected, bundleStats)
1194+
}
1195+
11511196
func TestFlashbotsRPCTestSuite(t *testing.T) {
11521197
suite.Run(t, new(FlashbotsRPCTestSuite))
11531198
}

types.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"encoding/json"
66
"math/big"
7+
"time"
78
"unsafe"
89

910
"github.com/pkg/errors"
@@ -385,6 +386,20 @@ type FlashbotsSendBundleRequest struct {
385386
RevertingTxs *[]string `json:"revertingTxHashes,omitempty"` // (Optional) Array[String], A list of tx hashes that are allowed to revert
386387
}
387388

389+
type FlashbotsGetBundleStatsParam struct {
390+
BlockNumber string `json:"blockNumber"` // String, a hex encoded block number for which this bundle is valid on
391+
BundleHash string `json:"bundleHash"` // String, returned by the flashbots api when calling eth_sendBundle
392+
}
393+
394+
type FlashbotsGetBundleStatsResponse struct {
395+
IsSimulated bool `json:"isSimulated"`
396+
IsSentToMiners bool `json:"isSentToMiners"`
397+
IsHighPriority bool `json:"isHighPriority"`
398+
SimulatedAt time.Time `json:"simulatedAt"`
399+
SubmittedAt time.Time `json:"submittedAt"`
400+
SentToMinersAt time.Time `json:"sentToMinersAt"`
401+
}
402+
388403
type FlashbotsSendBundleResponse struct {
389404
BundleHash string `json:"bundleHash"`
390405
}

0 commit comments

Comments
 (0)