Skip to content

Commit 4f29f57

Browse files
Implements Mempool endpoint (#89)
* Enables `txpool` in GETH * Adds `GetMempool` method to the `Client` interface * Implements `/mempool` * Implements `GetMempool` method on `Client` struct
1 parent fcd83f4 commit 4f29f57

File tree

9 files changed

+523
-11
lines changed

9 files changed

+523
-11
lines changed

ethereum/client.go

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ const (
4848
)
4949

5050
// Client allows for querying a set of specific Ethereum endpoints in an
51-
// idempotent manner. Client relies on the eth_*, debug_*, and admin_*
51+
// idempotent manner. Client relies on the eth_*, debug_*, admin_*, and txpool_*
5252
// methods and on the graphql endpoint.
5353
//
5454
// Client borrows HEAVILY from https://github.com/ethereum/go-ethereum/tree/master/ethclient.
@@ -1389,3 +1389,60 @@ func (ec *Client) Call(
13891389

13901390
return nil, fmt.Errorf("%w: %s", ErrCallMethodInvalid, request.Method)
13911391
}
1392+
1393+
// TxPoolContentResponse represents the response for a call to
1394+
// geth node on the "txpool_content" method.
1395+
type TxPoolContentResponse struct {
1396+
Pending txPool `json:"pending"`
1397+
Queued txPool `json:"queued"`
1398+
}
1399+
1400+
type txPool map[string]txPoolInner
1401+
1402+
type txPoolInner map[string]txPoolTxInfo
1403+
1404+
type txPoolTxInfo struct {
1405+
BlockHash *string `json:"blockHash"`
1406+
BlockNumber *string `json:"blockNumber"`
1407+
From string `json:"from"`
1408+
Gas string `json:"gas"`
1409+
GasPrice string `json:"gasPrice"`
1410+
Hash string `json:"hash"`
1411+
Input string `json:"input"`
1412+
Nonce string `json:"nonce"`
1413+
To string `json:"to"`
1414+
TransactionIndex int64 `json:"transactionIndex"`
1415+
Value string `json:"value"`
1416+
Type string `json:"type"`
1417+
V string `json:"v"`
1418+
R string `json:"r"`
1419+
S string `json:"s"`
1420+
}
1421+
1422+
// GetMempool get and returns all the transactions on Ethereum TxPool (pending and queued).
1423+
func (ec *Client) GetMempool(ctx context.Context) (*RosettaTypes.MempoolResponse, error) {
1424+
var response TxPoolContentResponse
1425+
if err := ec.c.CallContext(ctx, &response, "txpool_content"); err != nil {
1426+
return nil, err
1427+
}
1428+
1429+
identifiers := make([]*RosettaTypes.TransactionIdentifier, 0)
1430+
1431+
for _, inner := range response.Pending {
1432+
for _, info := range inner {
1433+
identifiers = append(identifiers, &RosettaTypes.TransactionIdentifier{
1434+
Hash: info.Hash,
1435+
})
1436+
}
1437+
}
1438+
1439+
for _, inner := range response.Queued {
1440+
for _, info := range inner {
1441+
identifiers = append(identifiers, &RosettaTypes.TransactionIdentifier{
1442+
Hash: info.Hash,
1443+
})
1444+
}
1445+
}
1446+
1447+
return &RosettaTypes.MempoolResponse{TransactionIdentifiers: identifiers}, nil
1448+
}

ethereum/client_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import (
2121
"fmt"
2222
"io/ioutil"
2323
"math/big"
24+
"reflect"
25+
"sort"
2426
"testing"
2527

2628
mocks "github.com/coinbase/rosetta-ethereum/mocks/ethereum"
@@ -2392,3 +2394,70 @@ func TestSendTransaction(t *testing.T) {
23922394
mockJSONRPC.AssertExpectations(t)
23932395
mockGraphQL.AssertExpectations(t)
23942396
}
2397+
2398+
func TestGetMempool(t *testing.T) {
2399+
mockJSONRPC := &mocks.JSONRPC{}
2400+
mockGraphQL := &mocks.GraphQL{}
2401+
ctx := context.Background()
2402+
expectedMempool := &RosettaTypes.MempoolResponse{
2403+
TransactionIdentifiers: []*RosettaTypes.TransactionIdentifier{
2404+
{Hash: "0x994024ef9f05d1cb25d01572642c1f550c78d214a52c306bb100d22c025b59d4"},
2405+
{Hash: "0x0859cb844087a280fa031ce2a0879f4f9832f431d6de67f57d0ca32e90dd9e21"},
2406+
{Hash: "0xa6de13e0a4465c9b55726d0826d020ed179fa1bda882a00e90aa467266af1815"},
2407+
{Hash: "0x94e28f01121fd56dead7b89c46c8d6ba32bb79dad5f7e29c1d523224479f10f4"},
2408+
{Hash: "0xf98b8a6589fa27f66545f31d443140c16eaa3da3896e66c4f05a03defa12cda4"},
2409+
{Hash: "0x4c652b9e779277f06e17b6a4c4db6658ac012f7c93f5eeab80e7802cce3ff556"},
2410+
{Hash: "0xa81f636c4b47831efd324dce5c48fe3a3d7a4f0020fae063887e8c2765ff1088"},
2411+
{Hash: "0x3bc19098a49974002ba933ac8f9c753ce5af538ab93fc68586849e8b8b0dce80"},
2412+
{Hash: "0x3401ec802cbe4b02d5be18717b53bb8177bd746f95a54da4674d7c27620facda"},
2413+
{Hash: "0x3d1c58eced8f15f3224e9b2579420d078dbd2adba8e825cee91fd306b0943f89"},
2414+
{Hash: "0xda591f0b15423aedb52f6b0e778b1fbc6757547d69277e2ba1aa7093583d1efb"},
2415+
{Hash: "0xb39652e66c57a6693e44b92b5c471952c26cabf9442a9a76c372f8690658cb4c"},
2416+
{Hash: "0x1e8700bf7215b2da0cfadcf34717f387577254e0871d828e5453a0593ce8060f"},
2417+
{Hash: "0x83811383fb7840a03c25a7cbae7e9af138b17853563eb9e212727be2d0b9667f"},
2418+
{Hash: "0x1e53751e1312cae3324a6b36c67dc95bfec993d7b4939c0de8c0dc761a0afd31"},
2419+
{Hash: "0xc1052f9378db5a779c42ae2de9a0b94c8a6357c815446d6ba55485dcc1b187ef"},
2420+
},
2421+
}
2422+
2423+
c := &Client{
2424+
c: mockJSONRPC,
2425+
g: mockGraphQL,
2426+
traceSemaphore: semaphore.NewWeighted(100),
2427+
}
2428+
2429+
mockJSONRPC.On(
2430+
"CallContext", ctx, mock.Anything, "txpool_content",
2431+
).Return(
2432+
nil,
2433+
).Run(
2434+
func(args mock.Arguments) {
2435+
r, ok := args.Get(1).(*TxPoolContentResponse)
2436+
assert.True(t, ok)
2437+
2438+
file, err := ioutil.ReadFile("testdata/txpool_content.json")
2439+
assert.NoError(t, err)
2440+
2441+
err = json.Unmarshal(file, r)
2442+
assert.NoError(t, err)
2443+
},
2444+
).Once()
2445+
2446+
actualMempool, err := c.GetMempool(ctx)
2447+
assert.NoError(t, err)
2448+
2449+
assert.Len(t, actualMempool.TransactionIdentifiers, len(expectedMempool.TransactionIdentifiers))
2450+
2451+
// Sort both slices to compare later
2452+
sort.Slice(expectedMempool.TransactionIdentifiers, func(i, j int) bool {
2453+
return expectedMempool.TransactionIdentifiers[i].Hash < expectedMempool.TransactionIdentifiers[j].Hash
2454+
})
2455+
2456+
sort.Slice(actualMempool.TransactionIdentifiers, func(i, j int) bool {
2457+
return actualMempool.TransactionIdentifiers[i].Hash < actualMempool.TransactionIdentifiers[j].Hash
2458+
})
2459+
2460+
assert.True(t, reflect.DeepEqual(actualMempool, expectedMempool))
2461+
2462+
mockJSONRPC.AssertExpectations(t)
2463+
}

ethereum/geth.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ HTTPHost = "0.0.0.0"
88
HTTPPort = 8545
99
HTTPVirtualHosts = ["*"]
1010
GraphQLVirtualHosts = ["*"]
11-
HTTPModules = ["eth", "debug", "admin"]
11+
HTTPModules = ["eth", "debug", "admin", "txpool"]
1212
IPCPath = ""
1313

1414
[Node.HTTPTimeouts]

0 commit comments

Comments
 (0)