diff --git a/rpc/eth_api.go b/rpc/eth_api.go index 4f9e9d9b..d3a28df7 100644 --- a/rpc/eth_api.go +++ b/rpc/eth_api.go @@ -102,8 +102,16 @@ func (e *PublicEthAPI) GetStorageAt(address common.Address, key string, blockNum } // GetTransactionCount returns the number of transactions at the given address up to the given block number. -func (e *PublicEthAPI) GetTransactionCount(address common.Address, blockNum rpc.BlockNumber) hexutil.Uint64 { - return 0 +func (e *PublicEthAPI) GetTransactionCount(address common.Address, blockNum rpc.BlockNumber) (hexutil.Uint64, error) { + ctx := e.cliCtx.WithHeight(blockNum.Int64()) + res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/nonce/%s", types.ModuleName, address), nil) + if err != nil { + return 0, err + } + + var out types.QueryResNonce + e.cliCtx.Codec.MustUnmarshalJSON(res, &out) + return hexutil.Uint64(out.Nonce), nil } // GetBlockTransactionCountByHash returns the number of transactions in the block identified by hash. diff --git a/x/evm/querier.go b/x/evm/querier.go index 13205133..c12f8159 100644 --- a/x/evm/querier.go +++ b/x/evm/querier.go @@ -1,6 +1,8 @@ package evm import ( + "math/big" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/ethermint/version" @@ -8,7 +10,6 @@ import ( ethcmn "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" abci "github.com/tendermint/tendermint/abci/types" - "math/big" ) // Supported endpoints @@ -18,6 +19,7 @@ const ( QueryBlockNumber = "blockNumber" QueryStorage = "storage" QueryCode = "code" + QueryNonce = "nonce" ) // NewQuerier is the module level router for state queries @@ -34,6 +36,8 @@ func NewQuerier(keeper Keeper) sdk.Querier { return queryStorage(ctx, path, keeper) case QueryCode: return queryCode(ctx, path, keeper) + case QueryNonce: + return queryNonce(ctx, path, keeper) default: return nil, sdk.ErrUnknownRequest("unknown query endpoint") } @@ -103,3 +107,15 @@ func queryCode(ctx sdk.Context, path []string, keeper Keeper) ([]byte, sdk.Error return res, nil } + +func queryNonce(ctx sdk.Context, path []string, keeper Keeper) ([]byte, sdk.Error) { + addr := ethcmn.BytesToAddress([]byte(path[1])) + nonce := keeper.GetNonce(ctx, addr) + nRes := types.QueryResNonce{Nonce: nonce} + res, err := codec.MarshalJSONIndent(keeper.cdc, nRes) + if err != nil { + panic("could not marshal result to JSON") + } + + return res, nil +} diff --git a/x/evm/types/querier.go b/x/evm/types/querier.go index b6e7cd57..c2765870 100644 --- a/x/evm/types/querier.go +++ b/x/evm/types/querier.go @@ -1,10 +1,12 @@ package types import ( - "github.com/ethereum/go-ethereum/common/hexutil" "math/big" + + "github.com/ethereum/go-ethereum/common/hexutil" ) +// QueryResProtocolVersion is response type for protocol version query type QueryResProtocolVersion struct { Version string `json:"result"` } @@ -13,6 +15,7 @@ func (q QueryResProtocolVersion) String() string { return q.Version } +// QueryResBalance is response type for balance query type QueryResBalance struct { Balance *hexutil.Big `json:"result"` } @@ -21,6 +24,7 @@ func (q QueryResBalance) String() string { return q.Balance.String() } +// QueryResBlockNumber is response type for block number query type QueryResBlockNumber struct { Number *big.Int `json:"result"` } @@ -29,6 +33,7 @@ func (q QueryResBlockNumber) String() string { return q.Number.String() } +// QueryResStorage is response type for storage query type QueryResStorage struct { Value []byte `json:"value"` } @@ -37,6 +42,7 @@ func (q QueryResStorage) String() string { return string(q.Value) } +// QueryResCode is response type for code query type QueryResCode struct { Code []byte } @@ -44,3 +50,12 @@ type QueryResCode struct { func (q QueryResCode) String() string { return string(q.Code) } + +// QueryResNonce is response type for Nonce query +type QueryResNonce struct { + Nonce uint64 `json:"result"` +} + +func (q QueryResNonce) String() string { + return string(q.Nonce) +}