From 0c08fb0a14385905a9d9ad4882a52a393f0be1e5 Mon Sep 17 00:00:00 2001 From: "(Nam) Pham Tien" Date: Thu, 22 Feb 2024 15:05:43 +0700 Subject: [PATCH] feat: simulate bundle --- pkg/mev/blxr_bundle_sender.go | 6 +++++ pkg/mev/bundle_sender.go | 13 +++++++--- pkg/mev/bundle_sender_test.go | 48 +++++++++++++++++++++++++++++++++++ pkg/mev/pkg.go | 13 ++++++---- 4 files changed, 72 insertions(+), 8 deletions(-) diff --git a/pkg/mev/blxr_bundle_sender.go b/pkg/mev/blxr_bundle_sender.go index 479dbb1..2ae261b 100644 --- a/pkg/mev/blxr_bundle_sender.go +++ b/pkg/mev/blxr_bundle_sender.go @@ -111,6 +111,12 @@ func (s *BloxrouteClient) CancelBundle( return nil } +func (s *BloxrouteClient) SimulateBundle( + _ context.Context, _ uint64, _ ...*types.Transaction, +) (SendBundleResponse, error) { + return SendBundleResponse{}, fmt.Errorf("method not support") +} + type BLXRSubmitBundleRequest struct { ID string `json:"id,omitempty"` Method string `json:"method,omitempty"` diff --git a/pkg/mev/bundle_sender.go b/pkg/mev/bundle_sender.go index 58586eb..c919de4 100644 --- a/pkg/mev/bundle_sender.go +++ b/pkg/mev/bundle_sender.go @@ -47,14 +47,14 @@ func (s *Client) SendBundle( blockNumber uint64, txs ...*types.Transaction, ) (SendBundleResponse, error) { - return s.sendBundle(ctx, uuid, blockNumber, txs...) + return s.sendBundle(ctx, ETHSendBundleMethod, uuid, blockNumber, txs...) } func (s *Client) CancelBundle( ctx context.Context, bundleUUID string, ) error { if s.cancelBySendBundle { - if _, err := s.sendBundle(ctx, &bundleUUID, 0); err != nil { + if _, err := s.sendBundle(ctx, ETHSendBundleMethod, &bundleUUID, 0); err != nil { return fmt.Errorf("cancel by send bundle error: %w", err) } return nil @@ -120,8 +120,15 @@ func (s *Client) CancelBundle( return nil } +func (s *Client) SimulateBundle( + ctx context.Context, blockNumber uint64, txs ...*types.Transaction, +) (SendBundleResponse, error) { + return s.sendBundle(ctx, EthCallBundleMethod, nil, blockNumber, txs...) +} + func (s *Client) sendBundle( ctx context.Context, + method string, uuid *string, blockNumber uint64, txs ...*types.Transaction, @@ -129,7 +136,7 @@ func (s *Client) sendBundle( req := SendBundleRequest{ ID: SendBundleID, JSONRPC: JSONRPC2, - Method: ETHSendBundleMethod, + Method: method, } p := new(SendBundleParams).SetBlockNumber(blockNumber).SetTransactions(txs...) if uuid != nil { diff --git a/pkg/mev/bundle_sender_test.go b/pkg/mev/bundle_sender_test.go index 1cf5b2a..484e4a5 100644 --- a/pkg/mev/bundle_sender_test.go +++ b/pkg/mev/bundle_sender_test.go @@ -9,10 +9,12 @@ import ( "github.com/KyberNetwork/tradinglib/pkg/convert" "github.com/KyberNetwork/tradinglib/pkg/mev" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/google/uuid" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -91,3 +93,49 @@ func TestCancelBeaver(t *testing.T) { require.NoError(t, sender.CancelBundle(ctx, bundleUUID)) } + +func Test_UnmarshalSimulationResponse(t *testing.T) { + response := "{\n \"jsonrpc\": \"2.0\",\n \"id\": 1,\n \"result\": {\n \"bundleGasPrice\": \"1\",\n \"bundleHash\": \"0x4753e95178e232c1cd0436acbb2340d9fe3442331c4650379fb436c7ee8c8489\",\n \"coinbaseDiff\": \"63000\",\n \"ethSentToCoinbase\": \"0\",\n \"gasFees\": \"63000\",\n \"results\": [\n {\n \"coinbaseDiff\": \"21000\",\n \"ethSentToCoinbase\": \"0\",\n \"fromAddress\": \"0xf84bB4749ef5745258812243B65d6Ec06B52Cc4f\",\n \"gasFees\": \"21000\",\n \"gasPrice\": \"1\",\n \"gasUsed\": 21000,\n \"toAddress\": \"0x4592D8f8D7B001e72Cb26A73e4Fa1806a51aC79d\",\n \"txHash\": \"0x31c0d14c4cf1dceaecad2b028472490fc7ed5a3b7f6cdcb78fa26673448b5665\",\n \"value\": \"0x\"\n },\n {\n \"coinbaseDiff\": \"21000\",\n \"ethSentToCoinbase\": \"0\",\n \"fromAddress\": \"0xf84bB4749ef5745258812243B65d6Ec06B52Cc4f\",\n \"gasFees\": \"21000\",\n \"gasPrice\": \"1\",\n \"gasUsed\": 21000,\n \"toAddress\": \"0x4592D8f8D7B001e72Cb26A73e4Fa1806a51aC79d\",\n \"txHash\": \"0xe7e261a582b11be10ded10262e98a938230ecae1adc155e23d5cc805021d10f4\",\n \"value\": \"0x\"\n },\n {\n \"coinbaseDiff\": \"21000\",\n \"ethSentToCoinbase\": \"0\",\n \"fromAddress\": \"0xf84bB4749ef5745258812243B65d6Ec06B52Cc4f\",\n \"gasFees\": \"21000\",\n \"gasPrice\": \"1\",\n \"gasUsed\": 21000,\n \"toAddress\": \"0x4592D8f8D7B001e72Cb26A73e4Fa1806a51aC79d\",\n \"txHash\": \"0x7ad464764e279a1849f517c83c459b0088b454f0928f61d0c3882ce09483e2d1\",\n \"value\": \"0x\"\n }\n ],\n \"stateBlockNumber\": 1,\n \"totalGasUsed\": 63000\n }\n}" // nolint:lll + var submitResponse mev.SendBundleResponse + + require.NoError(t, json.Unmarshal([]byte(response), &submitResponse)) + + t.Logf("%+v", submitResponse) +} + +func Test_SimulateBundle(t *testing.T) { + t.Skip() + rawTxs := []string{ + "0xf868808502540be400825208944592d8f8d7b001e72cb26a73e4fa1806a51ac79d82271080820a96a017691fd52972f52132d2db29c305afd89f50924b0cbc6e875ec8c6bcca14d287a015db7d1ab52dd19e40e7fe91018df63df9d5c5a5e21541dc2c8548a5ae9cee37", // nolint:lll + "0xf868018502540be400825208944592d8f8d7b001e72cb26a73e4fa1806a51ac79d82271080820a96a0aba458c7c6d1feac6c414c8f8cf562251609a2fb6710fcfce0c7783b106e5f41a00c0e780a9ea923e177dcc52aa143887ec21c9697f305a54f41b648f733e98d3e", // nolint:lll + "0xf868028502540be400825208944592d8f8d7b001e72cb26a73e4fa1806a51ac79d82271080820a95a05ddce4890eac66bfb20eba1493d12093c7551f1f5269a31487c718ee0ea2d12ca02ca061024dfad8d35cce7233eb3f75cdfc57ea80547f49ed887c1f257f4db719", // nolint:lll + } + + blockNumber := 1 + + txs := make([]*types.Transaction, 0, len(rawTxs)) + for _, rawTx := range rawTxs { + var tx types.Transaction + b, err := hexutil.Decode(rawTx) + require.NoError(t, err) + err = tx.UnmarshalBinary(b) + require.NoError(t, err) + txs = append(txs, &tx) + } + + var ( + simulationEndpoint = "http://localhost:8545" + client = mev.NewClient(http.DefaultClient, simulationEndpoint, nil, false, mev.BundleSenderTypeFlashbot) + ) + + simulationResponse, err := client.SimulateBundle(context.Background(), uint64(blockNumber), txs...) + require.NoError(t, err) + + assert.Equal(t, "", simulationResponse.Error.Messange) + assert.Equal(t, 0, simulationResponse.Error.Code) + assert.Equal( + t, + "0x99872010193b755b7dfad328508c751173521ee9b5349eab111b33096bf9e19a", + simulationResponse.Result.BundleHash, + ) +} diff --git a/pkg/mev/pkg.go b/pkg/mev/pkg.go index 69a60c1..4ff06c0 100644 --- a/pkg/mev/pkg.go +++ b/pkg/mev/pkg.go @@ -22,11 +22,13 @@ const ( ) const ( - JSONRPC2 = "2.0" - SendBundleID = 1 - BloxrouteSubmitBundleMethod = "blxr_submit_bundle" - ETHSendBundleMethod = "eth_sendBundle" - ETHCancelBundleMethod = "eth_cancelBundle" + JSONRPC2 = "2.0" + SendBundleID = 1 + BloxrouteSubmitBundleMethod = "blxr_submit_bundle" + BloxrouteSimulationBundleMethod = "blxr_simulate_bundle" + ETHSendBundleMethod = "eth_sendBundle" + EthCallBundleMethod = "eth_callBundle" + ETHCancelBundleMethod = "eth_cancelBundle" ) type IBundleSender interface { @@ -39,6 +41,7 @@ type IBundleSender interface { CancelBundle( ctx context.Context, bundleUUID string, ) error + SimulateBundle(ctx context.Context, blockNumber uint64, txs ...*types.Transaction) (SendBundleResponse, error) } var (