diff --git a/.github/dependabot.yml b/.github/dependabot.yml index cf79e3cf..84b36bcc 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,10 +4,6 @@ updates: directory: "/" schedule: interval: "daily" - - package-ecosystem: "gomod" - directory: "/examples" - schedule: - interval: "daily" - package-ecosystem: "npm" directory: "/docs" schedule: diff --git a/README.md b/README.md index 64b7f38c..a463340c 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ defer client.Close() // 2. Make a batch request var ( - balance big.Int + balance *big.Int nonce uint64 ) if err := client.Call( @@ -168,30 +168,30 @@ List of supported RPC methods for [`w3.Client`](https://pkg.go.dev/github.com/lm | Method | Go Code | :---------------------------------------- | :------- -| `eth_blockNumber` | `eth.BlockNumber().Returns(blockNumber *big.Int)` +| `eth_blockNumber` | `eth.BlockNumber().Returns(blockNumber **big.Int)` | `eth_call` | `eth.Call(msg *w3types.Message, blockNumber *big.Int, overrides w3types.State).Returns(output *[]byte)`
`eth.CallFunc(contract common.Address, f w3types.Func, args ...any).Returns(returns ...any)` | `eth_chainId` | `eth.ChainID().Returns(chainID *uint64)` -| `eth_createAccessList` | `eth.AccessList(msg *w3types.Message, blockNumber *big.Int).Returns(resp *eth.AccessListResponse)` +| `eth_createAccessList` | `eth.AccessList(msg *w3types.Message, blockNumber *big.Int).Returns(resp **eth.AccessListResponse)` | `eth_estimateGas` | `eth.EstimateGas(msg *w3types.Message, blockNumber *big.Int).Returns(gas *uint64)` -| `eth_gasPrice` | `eth.GasPrice().Returns(gasPrice *big.Int)` -| `eth_maxPriorityFeePerGas` | `eth.GasTipCap().Returns(gasTipCap *big.Int)` -| `eth_getBalance` | `eth.Balance(addr common.Address, blockNumber *big.Int).Returns(balance *big.Int)` -| `eth_getBlockByHash` | `eth.BlockByHash(hash common.Hash).Returns(block *types.Block)`
`eth.HeaderByHash(hash common.Hash).Returns(header *types.Header)` -| `eth_getBlockByNumber` | `eth.BlockByNumber(number *big.Int).Returns(block *types.Block)`
`eth.HeaderByNumber(number *big.Int).Returns(header *types.Header)` +| `eth_gasPrice` | `eth.GasPrice().Returns(gasPrice **big.Int)` +| `eth_maxPriorityFeePerGas` | `eth.GasTipCap().Returns(gasTipCap **big.Int)` +| `eth_getBalance` | `eth.Balance(addr common.Address, blockNumber *big.Int).Returns(balance **big.Int)` +| `eth_getBlockByHash` | `eth.BlockByHash(hash common.Hash).Returns(block *types.Block)`
`eth.HeaderByHash(hash common.Hash).Returns(header **types.Header)` +| `eth_getBlockByNumber` | `eth.BlockByNumber(number *big.Int).Returns(block *types.Block)`
`eth.HeaderByNumber(number *big.Int).Returns(header **types.Header)` | `eth_getBlockReceipts` | `eth.BlockReceipts(blockNumber *big.Int).Returns(receipts *types.Receipts)` | `eth_getBlockTransactionCountByHash` | `eth.BlockTxCountByHash(hash common.Hash).Returns(count *uint)` | `eth_getBlockTransactionCountByNumber` | `eth.BlockTxCountByNumber(number *big.Int).Returns(count *uint)` | `eth_getCode` | `eth.Code(addr common.Address, blockNumber *big.Int).Returns(code *[]byte)` | `eth_getLogs` | `eth.Logs(q ethereum.FilterQuery).Returns(logs *[]types.Log)` | `eth_getStorageAt` | `eth.StorageAt(addr common.Address, slot common.Hash, blockNumber *big.Int).Returns(storage *common.Hash)` -| `eth_getTransactionByHash` | `eth.Tx(hash common.Hash).Returns(tx *types.Transaction)` -| `eth_getTransactionByBlockHashAndIndex` | `eth.TxByBlockHashAndIndex(blockHash common.Hash, index uint).Returns(tx *types.Transaction)` -| `eth_getTransactionByBlockNumberAndIndex` | `eth.TxByBlockNumberAndIndex(blockNumber *big.Int, index uint).Returns(tx *types.Transaction)` +| `eth_getTransactionByHash` | `eth.Tx(hash common.Hash).Returns(tx **types.Transaction)` +| `eth_getTransactionByBlockHashAndIndex` | `eth.TxByBlockHashAndIndex(blockHash common.Hash, index uint).Returns(tx **types.Transaction)` +| `eth_getTransactionByBlockNumberAndIndex` | `eth.TxByBlockNumberAndIndex(blockNumber *big.Int, index uint).Returns(tx **types.Transaction)` | `eth_getTransactionCount` | `eth.Nonce(addr common.Address, blockNumber *big.Int).Returns(nonce *uint)` -| `eth_getTransactionReceipt` | `eth.TxReceipt(txHash common.Hash).Returns(receipt *types.Receipt)` +| `eth_getTransactionReceipt` | `eth.TxReceipt(txHash common.Hash).Returns(receipt **types.Receipt)` | `eth_sendRawTransaction` | `eth.SendRawTx(rawTx []byte).Returns(hash *common.Hash)`
`eth.SendTx(tx *types.Transaction).Returns(hash *common.Hash)` -| `eth_getUncleByBlockHashAndIndex` | `eth.UncleByBlockHashAndIndex(hash common.Hash, index uint).Returns(uncle *types.Header)` -| `eth_getUncleByBlockNumberAndIndex` | `eth.UncleByBlockNumberAndIndex(number *big.Int, index uint).Returns(uncle *types.Header)` +| `eth_getUncleByBlockHashAndIndex` | `eth.UncleByBlockHashAndIndex(hash common.Hash, index uint).Returns(uncle **types.Header)` +| `eth_getUncleByBlockNumberAndIndex` | `eth.UncleByBlockNumberAndIndex(number *big.Int, index uint).Returns(uncle **types.Header)` | `eth_getUncleCountByBlockHash` | `eth.UncleCountByBlockHash(hash common.Hash).Returns(count *uint)` | `eth_getUncleCountByBlockNumber` | `eth.UncleCountByBlockNumber(number *big.Int).Returns(count *uint)` @@ -199,16 +199,16 @@ List of supported RPC methods for [`w3.Client`](https://pkg.go.dev/github.com/lm | Method | Go Code | :----------------------- | :------- -| `debug_traceCall` | `debug.TraceCall(msg *w3types.Message, blockNumber *big.Int, config *debug.TraceConfig).Returns(trace *debug.Trace)`
`debug.CallTraceCall(msg *w3types.Message, blockNumber *big.Int, overrides w3types.State).Returns(trace *debug.CallTrace)` -| `debug_traceTransaction` | `debug.TraceTx(txHash common.Hash, config *debug.TraceConfig).Returns(trace *debug.Trace)`
`debug.CallTraceTx(txHash common.Hash, overrides w3types.State).Returns(trace *debug.CallTrace)` +| `debug_traceCall` | `debug.TraceCall(msg *w3types.Message, blockNumber *big.Int, config *debug.TraceConfig).Returns(trace **debug.Trace)`
`debug.CallTraceCall(msg *w3types.Message, blockNumber *big.Int, overrides w3types.State).Returns(trace **debug.CallTrace)` +| `debug_traceTransaction` | `debug.TraceTx(txHash common.Hash, config *debug.TraceConfig).Returns(trace **debug.Trace)`
`debug.CallTraceTx(txHash common.Hash, overrides w3types.State).Returns(trace **debug.CallTrace)` ### [`txpool`](https://pkg.go.dev/github.com/lmittmann/w3/module/txpool) | Method | Go Code | :--------------------| :------- -| `txpool_content` | `txpool.Content().Returns(resp *txpool.ContentResponse)` -| `txpool_contentFrom` | `txpool.ContentFrom(addr common.Address).Returns(resp *txpool.ContentFromResponse)` -| `txpool_status` | `txpool.Status().Returns(resp *txpool.StatusResponse)` +| `txpool_content` | `txpool.Content().Returns(resp **txpool.ContentResponse)` +| `txpool_contentFrom` | `txpool.ContentFrom(addr common.Address).Returns(resp **txpool.ContentFromResponse)` +| `txpool_status` | `txpool.Status().Returns(resp **txpool.StatusResponse)` ### [`web3`](https://pkg.go.dev/github.com/lmittmann/w3/module/web3) diff --git a/client_test.go b/client_test.go index 793e4f3e..abb0e0d9 100644 --- a/client_test.go +++ b/client_test.go @@ -48,7 +48,7 @@ func ExampleClient() { // 2. Make a batch request var ( - balance big.Int + balance *big.Int nonce uint64 ) if err := client.Call( @@ -58,7 +58,7 @@ func ExampleClient() { // handle error } - fmt.Printf("balance: %s\nnonce: %d\n", w3.FromWei(&balance, 18), nonce) + fmt.Printf("balance: %s\nnonce: %d\n", w3.FromWei(balance, 18), nonce) } func ExampleClient_Call_balanceOf() { @@ -76,8 +76,8 @@ func ExampleClient_Call_balanceOf() { balanceOf = w3.MustNewFunc("balanceOf(address)", "uint256") // Declare variables for the RPC responses. - ethBalance big.Int - weth9Balance big.Int + ethBalance *big.Int + weth9Balance *big.Int ) // Do batch request (both RPC requests are send in the same @@ -91,7 +91,7 @@ func ExampleClient_Call_balanceOf() { } fmt.Printf("Combined balance: %v wei", - new(big.Int).Add(ðBalance, &weth9Balance), + new(big.Int).Add(ethBalance, weth9Balance), ) } @@ -103,7 +103,7 @@ func ExampleClient_Call_nonceAndBalance() { addr = w3.A("0x000000000000000000000000000000000000c0Fe") nonce uint64 - balance big.Int + balance *big.Int ) if err := client.Call( @@ -114,7 +114,7 @@ func ExampleClient_Call_nonceAndBalance() { return } - fmt.Printf("%s: Nonce: %d, Balance: ♦%s\n", addr, nonce, w3.FromWei(&balance, 18)) + fmt.Printf("%s: Nonce: %d, Balance: ♦%s\n", addr, nonce, w3.FromWei(balance, 18)) } func ExampleClient_Call_sendERC20transferTx() { @@ -329,21 +329,6 @@ func (c *testCaller) HandleResponse(elem rpc.BatchElem) (err error) { return c.ReturnErr } -func TestClientCall_NilReference(t *testing.T) { - client := w3.MustDial("https://rpc.ankr.com/eth") - defer client.Close() - - var block *types.Block - err := client.Call( - eth.BlockByNumber(nil).Returns(block), - ) - - want := "w3: cannot return Go value of type *types.Block: value must be passed as a non-nil pointer reference" - if diff := cmp.Diff(want, err.Error()); diff != "" { - t.Fatalf("(-want, +got)\n%s", diff) - } -} - func BenchmarkCall_BalanceNonce(b *testing.B) { if *benchRPC == "" { b.Skipf("Missing -benchRPC") @@ -360,7 +345,7 @@ func BenchmarkCall_BalanceNonce(b *testing.B) { b.Run("Batch", func(b *testing.B) { var ( nonce uint64 - balance big.Int + balance *big.Int ) for range b.N { w3Client.Call( @@ -395,7 +380,7 @@ func BenchmarkCall_Balance100(b *testing.B) { } b.Run("Batch", func(b *testing.B) { - var balance big.Int + var balance *big.Int for range b.N { requests := make([]w3types.RPCCaller, len(addr100)) for j := range len(requests) { @@ -477,7 +462,7 @@ func BenchmarkCall_Block100(b *testing.B) { } b.Run("Batch", func(b *testing.B) { - var block types.Block + var block *types.Block for range b.N { requests := make([]w3types.RPCCaller, len(block100)) for j := range len(requests) { diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx index 531fb5a3..0a36234f 100644 --- a/docs/pages/index.mdx +++ b/docs/pages/index.mdx @@ -58,7 +58,7 @@ defer client.Close() // 2. Make a batch request var ( - balance big.Int + balance *big.Int nonce uint64 ) if err := client.Call( @@ -188,30 +188,30 @@ List of supported RPC methods for [`w3.Client`](https://pkg.go.dev/github.com/lm | Method | Go Code | :---------------------------------------- | :------- -| `eth_blockNumber` | `eth.BlockNumber().Returns(blockNumber *big.Int)` +| `eth_blockNumber` | `eth.BlockNumber().Returns(blockNumber **big.Int)` | `eth_call` | `eth.Call(msg *w3types.Message, blockNumber *big.Int, overrides w3types.State).Returns(output *[]byte)`
`eth.CallFunc(contract common.Address, f w3types.Func, args ...any).Returns(returns ...any)` | `eth_chainId` | `eth.ChainID().Returns(chainID *uint64)` -| `eth_createAccessList` | `eth.AccessList(msg *w3types.Message, blockNumber *big.Int).Returns(resp *eth.AccessListResponse)` +| `eth_createAccessList` | `eth.AccessList(msg *w3types.Message, blockNumber *big.Int).Returns(resp **eth.AccessListResponse)` | `eth_estimateGas` | `eth.EstimateGas(msg *w3types.Message, blockNumber *big.Int).Returns(gas *uint64)` -| `eth_gasPrice` | `eth.GasPrice().Returns(gasPrice *big.Int)` -| `eth_maxPriorityFeePerGas` | `eth.GasTipCap().Returns(gasTipCap *big.Int)` -| `eth_getBalance` | `eth.Balance(addr common.Address, blockNumber *big.Int).Returns(balance *big.Int)` -| `eth_getBlockByHash` | `eth.BlockByHash(hash common.Hash).Returns(block *types.Block)`
`eth.HeaderByHash(hash common.Hash).Returns(header *types.Header)` -| `eth_getBlockByNumber` | `eth.BlockByNumber(number *big.Int).Returns(block *types.Block)`
`eth.HeaderByNumber(number *big.Int).Returns(header *types.Header)` +| `eth_gasPrice` | `eth.GasPrice().Returns(gasPrice **big.Int)` +| `eth_maxPriorityFeePerGas` | `eth.GasTipCap().Returns(gasTipCap **big.Int)` +| `eth_getBalance` | `eth.Balance(addr common.Address, blockNumber *big.Int).Returns(balance **big.Int)` +| `eth_getBlockByHash` | `eth.BlockByHash(hash common.Hash).Returns(block *types.Block)`
`eth.HeaderByHash(hash common.Hash).Returns(header **types.Header)` +| `eth_getBlockByNumber` | `eth.BlockByNumber(number *big.Int).Returns(block *types.Block)`
`eth.HeaderByNumber(number *big.Int).Returns(header **types.Header)` | `eth_getBlockReceipts` | `eth.BlockReceipts(blockNumber *big.Int).Returns(receipts *types.Receipts)` | `eth_getBlockTransactionCountByHash` | `eth.BlockTxCountByHash(hash common.Hash).Returns(count *uint)` | `eth_getBlockTransactionCountByNumber` | `eth.BlockTxCountByNumber(number *big.Int).Returns(count *uint)` | `eth_getCode` | `eth.Code(addr common.Address, blockNumber *big.Int).Returns(code *[]byte)` | `eth_getLogs` | `eth.Logs(q ethereum.FilterQuery).Returns(logs *[]types.Log)` | `eth_getStorageAt` | `eth.StorageAt(addr common.Address, slot common.Hash, blockNumber *big.Int).Returns(storage *common.Hash)` -| `eth_getTransactionByHash` | `eth.Tx(hash common.Hash).Returns(tx *types.Transaction)` -| `eth_getTransactionByBlockHashAndIndex` | `eth.TxByBlockHashAndIndex(blockHash common.Hash, index uint).Returns(tx *types.Transaction)` -| `eth_getTransactionByBlockNumberAndIndex` | `eth.TxByBlockNumberAndIndex(blockNumber *big.Int, index uint).Returns(tx *types.Transaction)` +| `eth_getTransactionByHash` | `eth.Tx(hash common.Hash).Returns(tx **types.Transaction)` +| `eth_getTransactionByBlockHashAndIndex` | `eth.TxByBlockHashAndIndex(blockHash common.Hash, index uint).Returns(tx **types.Transaction)` +| `eth_getTransactionByBlockNumberAndIndex` | `eth.TxByBlockNumberAndIndex(blockNumber *big.Int, index uint).Returns(tx **types.Transaction)` | `eth_getTransactionCount` | `eth.Nonce(addr common.Address, blockNumber *big.Int).Returns(nonce *uint)` -| `eth_getTransactionReceipt` | `eth.TxReceipt(txHash common.Hash).Returns(receipt *types.Receipt)` +| `eth_getTransactionReceipt` | `eth.TxReceipt(txHash common.Hash).Returns(receipt **types.Receipt)` | `eth_sendRawTransaction` | `eth.SendRawTx(rawTx []byte).Returns(hash *common.Hash)`
`eth.SendTx(tx *types.Transaction).Returns(hash *common.Hash)` -| `eth_getUncleByBlockHashAndIndex` | `eth.UncleByBlockHashAndIndex(hash common.Hash, index uint).Returns(uncle *types.Header)` -| `eth_getUncleByBlockNumberAndIndex` | `eth.UncleByBlockNumberAndIndex(number *big.Int, index uint).Returns(uncle *types.Header)` +| `eth_getUncleByBlockHashAndIndex` | `eth.UncleByBlockHashAndIndex(hash common.Hash, index uint).Returns(uncle **types.Header)` +| `eth_getUncleByBlockNumberAndIndex` | `eth.UncleByBlockNumberAndIndex(number *big.Int, index uint).Returns(uncle **types.Header)` | `eth_getUncleCountByBlockHash` | `eth.UncleCountByBlockHash(hash common.Hash).Returns(count *uint)` | `eth_getUncleCountByBlockNumber` | `eth.UncleCountByBlockNumber(number *big.Int).Returns(count *uint)` @@ -219,16 +219,16 @@ List of supported RPC methods for [`w3.Client`](https://pkg.go.dev/github.com/lm | Method | Go Code | :----------------------- | :------- -| `debug_traceCall` | `debug.TraceCall(msg *w3types.Message, blockNumber *big.Int, config *debug.TraceConfig).Returns(trace *debug.Trace)`
`debug.CallTraceCall(msg *w3types.Message, blockNumber *big.Int, overrides w3types.State).Returns(trace *debug.CallTrace)` -| `debug_traceTransaction` | `debug.TraceTx(txHash common.Hash, config *debug.TraceConfig).Returns(trace *debug.Trace)`
`debug.CallTraceTx(txHash common.Hash, overrides w3types.State).Returns(trace *debug.CallTrace)` +| `debug_traceCall` | `debug.TraceCall(msg *w3types.Message, blockNumber *big.Int, config *debug.TraceConfig).Returns(trace **debug.Trace)`
`debug.CallTraceCall(msg *w3types.Message, blockNumber *big.Int, overrides w3types.State).Returns(trace **debug.CallTrace)` +| `debug_traceTransaction` | `debug.TraceTx(txHash common.Hash, config *debug.TraceConfig).Returns(trace **debug.Trace)`
`debug.CallTraceTx(txHash common.Hash, overrides w3types.State).Returns(trace **debug.CallTrace)` ### [`txpool`](https://pkg.go.dev/github.com/lmittmann/w3/module/txpool) | Method | Go Code | :--------------------| :------- -| `txpool_content` | `txpool.Content().Returns(resp *txpool.ContentResponse)` -| `txpool_contentFrom` | `txpool.ContentFrom(addr common.Address).Returns(resp *txpool.ContentFromResponse)` -| `txpool_status` | `txpool.Status().Returns(resp *txpool.StatusResponse)` +| `txpool_content` | `txpool.Content().Returns(resp **txpool.ContentResponse)` +| `txpool_contentFrom` | `txpool.ContentFrom(addr common.Address).Returns(resp **txpool.ContentFromResponse)` +| `txpool_status` | `txpool.Status().Returns(resp **txpool.StatusResponse)` ### [`web3`](https://pkg.go.dev/github.com/lmittmann/w3/module/web3) diff --git a/examples/scan_blocks/main.go b/examples/scan_blocks/main.go index 7d53ca1c..5a8e50d9 100644 --- a/examples/scan_blocks/main.go +++ b/examples/scan_blocks/main.go @@ -1,5 +1,5 @@ /* -scan_blocks interates over blocks with their transactions from a given start block. +scan_blocks iterates over blocks with their transactions from a given start block. Usage: @@ -37,7 +37,7 @@ func main() { // parse flags flag.Uint64Var(&startBlock, "start", 10_000_000, "Start block") flag.Usage = func() { - fmt.Println("scan_blocks interates over blocks with their transactions from a given start block.") + fmt.Println("scan_blocks iterates over blocks with their transactions from a given start block.") flag.PrintDefaults() } flag.Parse() @@ -48,7 +48,7 @@ func main() { // fetch blocks in bulk calls := make([]w3types.RPCCaller, bulkSize) - blocks := make([]types.Block, bulkSize) + blocks := make([]*types.Block, bulkSize) for i, txCount := 0, 0; ; i++ { j := i % bulkSize @@ -62,7 +62,7 @@ func main() { for _, block := range blocks { txCount += len(block.Transactions()) - processBlock(&block) + processBlock(block) } fmt.Printf("\rFetched %d blocks with a total of %d transactions", i+1, txCount) } diff --git a/internal/module/factory.go b/internal/module/factory.go index 0cc456ac..ac13ab51 100644 --- a/internal/module/factory.go +++ b/internal/module/factory.go @@ -91,9 +91,10 @@ func WithRetWrapper[T any](fn RetWrapperFunc[T]) Option[T] { } } -var ( - HexBigRetWrapper RetWrapperFunc[big.Int] = func(ret *big.Int) any { return (*hexutil.Big)(ret) } - HexUintRetWrapper RetWrapperFunc[uint] = func(ret *uint) any { return (*hexutil.Uint)(ret) } - HexUint64RetWrapper RetWrapperFunc[uint64] = func(ret *uint64) any { return (*hexutil.Uint64)(ret) } - HexBytesRetWrapper RetWrapperFunc[[]byte] = func(ret *[]byte) any { return (*hexutil.Bytes)(ret) } -) +func HexBigRetWrapper(ret **big.Int) any { + *ret = new(big.Int) + return (*hexutil.Big)(*ret) +} +func HexUintRetWrapper(ret *uint) any { return (*hexutil.Uint)(ret) } +func HexUint64RetWrapper(ret *uint64) any { return (*hexutil.Uint64)(ret) } +func HexBytesRetWrapper(ret *[]byte) any { return (*hexutil.Bytes)(ret) } diff --git a/module/debug/call_trace.go b/module/debug/call_trace.go index 81a4434c..a489b6b3 100644 --- a/module/debug/call_trace.go +++ b/module/debug/call_trace.go @@ -11,17 +11,17 @@ import ( ) // CallTraceCall requests the call trace of the given message. -func CallTraceCall(msg *w3types.Message, blockNumber *big.Int, overrides w3types.State) w3types.RPCCallerFactory[CallTrace] { +func CallTraceCall(msg *w3types.Message, blockNumber *big.Int, overrides w3types.State) w3types.RPCCallerFactory[*CallTrace] { return module.NewFactory( "debug_traceCall", []any{msg, module.BlockNumberArg(blockNumber), &traceConfig{Tracer: "callTracer", Overrides: overrides}}, - module.WithArgsWrapper[CallTrace](msgArgsWrapper), + module.WithArgsWrapper[*CallTrace](msgArgsWrapper), ) } // CallTraceTx requests the call trace of the transaction with the given hash. -func CallTraceTx(txHash common.Hash, overrides w3types.State) w3types.RPCCallerFactory[CallTrace] { - return module.NewFactory[CallTrace]( +func CallTraceTx(txHash common.Hash, overrides w3types.State) w3types.RPCCallerFactory[*CallTrace] { + return module.NewFactory[*CallTrace]( "debug_traceTransaction", []any{txHash, &traceConfig{Tracer: "callTracer", Overrides: overrides}}, ) diff --git a/module/debug/call_trace_test.go b/module/debug/call_trace_test.go index 5697f9ec..edc7ebe5 100644 --- a/module/debug/call_trace_test.go +++ b/module/debug/call_trace_test.go @@ -10,7 +10,7 @@ import ( ) func TestCallTraceTx(t *testing.T) { - tests := []rpctest.TestCase[debug.CallTrace]{ + rpctest.RunTestCases(t, []rpctest.TestCase[*debug.CallTrace]{ { Golden: "traceCall_callTracer", Call: debug.CallTraceCall(&w3types.Message{ @@ -41,7 +41,5 @@ func TestCallTraceTx(t *testing.T) { RevertReason: "BA: Insufficient gas (ETH) for refund", }, }, - } - - rpctest.RunTestCases(t, tests) + }) } diff --git a/module/debug/trace.go b/module/debug/trace.go index ef846170..1c35af54 100644 --- a/module/debug/trace.go +++ b/module/debug/trace.go @@ -14,23 +14,23 @@ import ( ) // TraceCall requests the trace of the given message. -func TraceCall(msg *w3types.Message, blockNumber *big.Int, config *TraceConfig) w3types.RPCCallerFactory[Trace] { +func TraceCall(msg *w3types.Message, blockNumber *big.Int, config *TraceConfig) w3types.RPCCallerFactory[*Trace] { if config == nil { config = &TraceConfig{} } return module.NewFactory( "debug_traceCall", []any{msg, module.BlockNumberArg(blockNumber), config}, - module.WithArgsWrapper[Trace](msgArgsWrapper), + module.WithArgsWrapper[*Trace](msgArgsWrapper), ) } // TraceTx requests the trace of the transaction with the given hash. -func TraceTx(txHash common.Hash, config *TraceConfig) w3types.RPCCallerFactory[Trace] { +func TraceTx(txHash common.Hash, config *TraceConfig) w3types.RPCCallerFactory[*Trace] { if config == nil { config = &TraceConfig{} } - return module.NewFactory[Trace]( + return module.NewFactory[*Trace]( "debug_traceTransaction", []any{txHash, config}, ) diff --git a/module/debug/trace_test.go b/module/debug/trace_test.go index 7f3ebc17..22fec78f 100644 --- a/module/debug/trace_test.go +++ b/module/debug/trace_test.go @@ -12,7 +12,7 @@ import ( ) func TestTraceTx(t *testing.T) { - tests := []rpctest.TestCase[debug.Trace]{ + rpctest.RunTestCases(t, []rpctest.TestCase[*debug.Trace]{ { Golden: "traceTx__1150000_0", Call: debug.TraceTx(w3.H("0x38f299591902bfada359527fa6b9b597a959c41c6f72a3b484807fbf52dc8abe"), nil), @@ -38,13 +38,11 @@ func TestTraceTx(t *testing.T) { }, }, }, - } - - rpctest.RunTestCases(t, tests) + }) } func TestTraceCall(t *testing.T) { - tests := []rpctest.TestCase[debug.Trace]{ + rpctest.RunTestCases(t, []rpctest.TestCase[*debug.Trace]{ { Golden: "traceCall", Call: debug.TraceCall(&w3types.Message{ @@ -58,7 +56,5 @@ func TestTraceCall(t *testing.T) { Gas: 21000, }, }, - } - - rpctest.RunTestCases(t, tests) + }) } diff --git a/module/eth/balance.go b/module/eth/balance.go index 2e8f9f4b..3082a328 100644 --- a/module/eth/balance.go +++ b/module/eth/balance.go @@ -11,7 +11,7 @@ import ( // Balance requests the balance of the given common.Address addr at the given // blockNumber. If blockNumber is nil, the balance at the latest known block is // requested. -func Balance(addr common.Address, blockNumber *big.Int) w3types.RPCCallerFactory[big.Int] { +func Balance(addr common.Address, blockNumber *big.Int) w3types.RPCCallerFactory[*big.Int] { return module.NewFactory( "eth_getBalance", []any{addr, module.BlockNumberArg(blockNumber)}, diff --git a/module/eth/balance_test.go b/module/eth/balance_test.go index f62acc51..9c679d0d 100644 --- a/module/eth/balance_test.go +++ b/module/eth/balance_test.go @@ -10,7 +10,7 @@ import ( ) func TestBalance(t *testing.T) { - tests := []rpctest.TestCase[big.Int]{ + rpctest.RunTestCases(t, []rpctest.TestCase[*big.Int]{ { Golden: "get_balance", Call: eth.Balance(w3.A("0x000000000000000000000000000000000000c0Fe"), nil), @@ -21,7 +21,5 @@ func TestBalance(t *testing.T) { Call: eth.Balance(w3.A("0x000000000000000000000000000000000000c0Fe"), big.NewInt(255)), WantRet: w3.I("0.1 ether"), }, - } - - rpctest.RunTestCases(t, tests) + }) } diff --git a/module/eth/block.go b/module/eth/block.go index e1b2b198..e3cadc3a 100644 --- a/module/eth/block.go +++ b/module/eth/block.go @@ -11,7 +11,7 @@ import ( ) // BlockByHash requests the block with the given hash with full transactions. -func BlockByHash(hash common.Hash) w3types.RPCCallerFactory[types.Block] { +func BlockByHash(hash common.Hash) w3types.RPCCallerFactory[*types.Block] { return module.NewFactory( "eth_getBlockByHash", []any{hash, true}, @@ -21,7 +21,7 @@ func BlockByHash(hash common.Hash) w3types.RPCCallerFactory[types.Block] { // BlockByNumber requests the block with the given number with full // transactions. If number is nil, the latest block is requested. -func BlockByNumber(number *big.Int) w3types.RPCCallerFactory[types.Block] { +func BlockByNumber(number *big.Int) w3types.RPCCallerFactory[*types.Block] { return module.NewFactory( "eth_getBlockByNumber", []any{module.BlockNumberArg(number), true}, @@ -50,8 +50,8 @@ func BlockTxCountByNumber(number *big.Int) w3types.RPCCallerFactory[uint] { } // HeaderByHash requests the header with the given hash. -func HeaderByHash(hash common.Hash) w3types.RPCCallerFactory[types.Header] { - return module.NewFactory[types.Header]( +func HeaderByHash(hash common.Hash) w3types.RPCCallerFactory[*types.Header] { + return module.NewFactory[*types.Header]( "eth_getBlockByHash", []any{hash, false}, ) @@ -59,14 +59,14 @@ func HeaderByHash(hash common.Hash) w3types.RPCCallerFactory[types.Header] { // HeaderByNumber requests the header with the given number. If number is nil, // the latest header is requested. -func HeaderByNumber(number *big.Int) w3types.RPCCallerFactory[types.Header] { - return module.NewFactory[types.Header]( +func HeaderByNumber(number *big.Int) w3types.RPCCallerFactory[*types.Header] { + return module.NewFactory[*types.Header]( "eth_getBlockByNumber", []any{module.BlockNumberArg(number), false}, ) } -var blockRetWrapper = func(ret *types.Block) any { return &rpcBlock{ret} } +func blockRetWrapper(ret **types.Block) any { *ret = new(types.Block); return &rpcBlock{*ret} } type rpcBlock struct{ *types.Block } diff --git a/module/eth/block_number.go b/module/eth/block_number.go index 5595c21a..0897f6bc 100644 --- a/module/eth/block_number.go +++ b/module/eth/block_number.go @@ -8,7 +8,7 @@ import ( ) // BlockNumber requests the number of the most recent block. -func BlockNumber() w3types.RPCCallerFactory[big.Int] { +func BlockNumber() w3types.RPCCallerFactory[*big.Int] { return module.NewFactory( "eth_blockNumber", nil, diff --git a/module/eth/block_number_test.go b/module/eth/block_number_test.go index 4fe2c3bd..4fdb7db9 100644 --- a/module/eth/block_number_test.go +++ b/module/eth/block_number_test.go @@ -10,13 +10,11 @@ import ( ) func TestBlockNumber(t *testing.T) { - tests := []rpctest.TestCase[big.Int]{ + rpctest.RunTestCases(t, []rpctest.TestCase[*big.Int]{ { Golden: "block_number", Call: eth.BlockNumber(), WantRet: w3.I("0xc0fe"), }, - } - - rpctest.RunTestCases(t, tests) + }) } diff --git a/module/eth/block_test.go b/module/eth/block_test.go index c77e847d..4add91ab 100644 --- a/module/eth/block_test.go +++ b/module/eth/block_test.go @@ -13,7 +13,7 @@ import ( ) func TestBlockByHash(t *testing.T) { - tests := []rpctest.TestCase[types.Block]{ + rpctest.RunTestCases(t, []rpctest.TestCase[*types.Block]{ { Golden: "get_block_by_hash__1", Call: eth.BlockByHash(w3.H("0x88e96d4537bea4d9c05d12549907b32561d3bf31f45aae734cdc119f13406cb6")), @@ -101,13 +101,11 @@ func TestBlockByHash(t *testing.T) { }, }), }, - } - - rpctest.RunTestCases(t, tests) + }) } func TestBlockByNumber(t *testing.T) { - tests := []rpctest.TestCase[types.Block]{ + rpctest.RunTestCases(t, []rpctest.TestCase[*types.Block]{ { Golden: "get_block_by_number__1", Call: eth.BlockByNumber(big.NewInt(1)), @@ -168,42 +166,36 @@ func TestBlockByNumber(t *testing.T) { Call: eth.BlockByNumber(big.NewInt(999999999)), WantErr: errors.New("w3: call failed: not found"), }, - } - - rpctest.RunTestCases(t, tests) + }) } func TestBlockTxCountByHash(t *testing.T) { - tests := []rpctest.TestCase[uint]{ + rpctest.RunTestCases(t, []rpctest.TestCase[uint]{ { Golden: "block_transaction_count_by_hash__15050000", Call: eth.BlockTxCountByHash(w3.H("0xc43d35f6a64f8a64f046c8deb4069572d622dfe7f028f62301b186f08f0e96f2")), - WantRet: ptr[uint](32), + WantRet: 32, }, { Golden: "block_transaction_count_by_hash__0x00", Call: eth.BlockTxCountByHash(common.Hash{}), WantErr: errors.New("w3: call failed: not found"), }, - } - - rpctest.RunTestCases(t, tests) + }) } func TestBlockTxCountByNumber(t *testing.T) { - tests := []rpctest.TestCase[uint]{ + rpctest.RunTestCases(t, []rpctest.TestCase[uint]{ { Golden: "block_transaction_count_by_number__15050000", Call: eth.BlockTxCountByNumber(big.NewInt(15050000)), - WantRet: ptr[uint](32), + WantRet: 32, }, - } - - rpctest.RunTestCases(t, tests) + }) } func TestHeaderByHash(t *testing.T) { - tests := []rpctest.TestCase[types.Header]{ + rpctest.RunTestCases(t, []rpctest.TestCase[*types.Header]{ { Golden: "get_block_by_hash__12965000", Call: eth.HeaderByHash(w3.H("0x9b83c12c69edb74f6c8dd5d052765c1adf940e320bd1291696e6fa07829eee71")), @@ -226,13 +218,11 @@ func TestHeaderByHash(t *testing.T) { BaseFee: w3.I("0x3b9aca00"), }, }, - } - - rpctest.RunTestCases(t, tests) + }) } func TestHeaderByNumber(t *testing.T) { - tests := []rpctest.TestCase[types.Header]{ + rpctest.RunTestCases(t, []rpctest.TestCase[*types.Header]{ { Golden: "get_block_by_number__12965000", Call: eth.HeaderByNumber(big.NewInt(12965000)), @@ -255,9 +245,7 @@ func TestHeaderByNumber(t *testing.T) { BaseFee: w3.I("0x3b9aca00"), }, }, - } - - rpctest.RunTestCases(t, tests) + }) } func ptr[T any](v T) *T { return &v } diff --git a/module/eth/call.go b/module/eth/call.go index bfc1d5f7..31760a13 100644 --- a/module/eth/call.go +++ b/module/eth/call.go @@ -44,11 +44,11 @@ func EstimateGas(msg *w3types.Message, blockNumber *big.Int) w3types.RPCCallerFa // AccessList requests the access list of the given message at the given // blockNumber. If blockNumber is nil, the access list of the message at the // latest block is requested. -func AccessList(msg *w3types.Message, blockNumber *big.Int) w3types.RPCCallerFactory[AccessListResponse] { +func AccessList(msg *w3types.Message, blockNumber *big.Int) w3types.RPCCallerFactory[*AccessListResponse] { return module.NewFactory( "eth_createAccessList", []any{msg, module.BlockNumberArg(blockNumber)}, - module.WithArgsWrapper[AccessListResponse](msgArgsWrapper), + module.WithArgsWrapper[*AccessListResponse](msgArgsWrapper), ) } diff --git a/module/eth/call_test.go b/module/eth/call_test.go index a8f87a9f..42711813 100644 --- a/module/eth/call_test.go +++ b/module/eth/call_test.go @@ -15,7 +15,7 @@ import ( var funcBalanceOf = w3.MustNewFunc("balanceOf(address)", "uint256") func TestCall(t *testing.T) { - tests := []rpctest.TestCase[[]byte]{ + rpctest.RunTestCases(t, []rpctest.TestCase[[]byte]{ { Golden: "call_func", Call: eth.Call(&w3types.Message{ @@ -23,7 +23,7 @@ func TestCall(t *testing.T) { Func: funcBalanceOf, Args: []any{w3.A("0x000000000000000000000000000000000000c0Fe")}, }, nil, nil), - WantRet: ptr(make([]byte, 32)), + WantRet: make([]byte, 32), }, { Golden: "call_func__overrides", @@ -38,11 +38,9 @@ func TestCall(t *testing.T) { }, }, }), - WantRet: ptr(common.BigToHash(big.NewInt(42)).Bytes()), + WantRet: common.BigToHash(big.NewInt(42)).Bytes(), }, - } - - rpctest.RunTestCases(t, tests) + }) } func TestCallFunc(t *testing.T) { @@ -67,7 +65,7 @@ func TestCallFunc(t *testing.T) { } func TestEstimateGas(t *testing.T) { - tests := []rpctest.TestCase[uint64]{ + rpctest.RunTestCases(t, []rpctest.TestCase[uint64]{ { Golden: "estimate_gas", Call: eth.EstimateGas(&w3types.Message{ @@ -75,15 +73,13 @@ func TestEstimateGas(t *testing.T) { Func: funcBalanceOf, Args: []any{w3.A("0x000000000000000000000000000000000000c0Fe")}, }, nil), - WantRet: ptr[uint64](23750), + WantRet: 23750, }, - } - - rpctest.RunTestCases(t, tests) + }) } func TestAccessList(t *testing.T) { - tests := []rpctest.TestCase[eth.AccessListResponse]{ + rpctest.RunTestCases(t, []rpctest.TestCase[*eth.AccessListResponse]{ { Golden: "create_access_list", Call: eth.AccessList(&w3types.Message{ @@ -103,7 +99,5 @@ func TestAccessList(t *testing.T) { GasUsed: 26050, }, }, - } - - rpctest.RunTestCases(t, tests) + }) } diff --git a/module/eth/chain_id_test.go b/module/eth/chain_id_test.go index b6182088..0425beed 100644 --- a/module/eth/chain_id_test.go +++ b/module/eth/chain_id_test.go @@ -8,13 +8,11 @@ import ( ) func TestChainID(t *testing.T) { - tests := []rpctest.TestCase[uint64]{ + rpctest.RunTestCases(t, []rpctest.TestCase[uint64]{ { Golden: "chain_id", Call: eth.ChainID(), - WantRet: ptr[uint64](1), + WantRet: 1, }, - } - - rpctest.RunTestCases(t, tests) + }) } diff --git a/module/eth/code_test.go b/module/eth/code_test.go index 59170cc0..bb1a8fc5 100644 --- a/module/eth/code_test.go +++ b/module/eth/code_test.go @@ -9,13 +9,11 @@ import ( ) func TestCode(t *testing.T) { - tests := []rpctest.TestCase[[]byte]{ + rpctest.RunTestCases(t, []rpctest.TestCase[[]byte]{ { Golden: "get_code", Call: eth.Code(w3.A("0x000000000000000000000000000000000000c0DE"), nil), - WantRet: ptr(w3.B("0xdeadbeef")), + WantRet: w3.B("0xdeadbeef"), }, - } - - rpctest.RunTestCases(t, tests) + }) } diff --git a/module/eth/gas_price.go b/module/eth/gas_price.go index ac33e9f0..bc6f9ccb 100644 --- a/module/eth/gas_price.go +++ b/module/eth/gas_price.go @@ -8,7 +8,7 @@ import ( ) // GasPrice requests the current gas price in wei. -func GasPrice() w3types.RPCCallerFactory[big.Int] { +func GasPrice() w3types.RPCCallerFactory[*big.Int] { return module.NewFactory( "eth_gasPrice", nil, diff --git a/module/eth/gas_price_test.go b/module/eth/gas_price_test.go index 5245a709..a3c2b75e 100644 --- a/module/eth/gas_price_test.go +++ b/module/eth/gas_price_test.go @@ -10,13 +10,11 @@ import ( ) func TestGasPrice(t *testing.T) { - tests := []rpctest.TestCase[big.Int]{ + rpctest.RunTestCases(t, []rpctest.TestCase[*big.Int]{ { Golden: "gas_price", Call: eth.GasPrice(), WantRet: w3.I("0xc0fe"), }, - } - - rpctest.RunTestCases(t, tests) + }) } diff --git a/module/eth/gas_tip_cap.go b/module/eth/gas_tip_cap.go index 06d54f26..8f8709eb 100644 --- a/module/eth/gas_tip_cap.go +++ b/module/eth/gas_tip_cap.go @@ -9,7 +9,7 @@ import ( // GasTipCap requests the currently suggested gas tip cap after EIP-1559 to // allow a timely execution of a transaction. -func GasTipCap() w3types.RPCCallerFactory[big.Int] { +func GasTipCap() w3types.RPCCallerFactory[*big.Int] { return module.NewFactory( "eth_maxPriorityFeePerGas", nil, diff --git a/module/eth/gas_tip_cap_test.go b/module/eth/gas_tip_cap_test.go index 407c7018..ff9d00cd 100644 --- a/module/eth/gas_tip_cap_test.go +++ b/module/eth/gas_tip_cap_test.go @@ -10,13 +10,11 @@ import ( ) func TestGasTipCap(t *testing.T) { - tests := []rpctest.TestCase[big.Int]{ + rpctest.RunTestCases(t, []rpctest.TestCase[*big.Int]{ { Golden: "gas_tip_cap", Call: eth.GasTipCap(), WantRet: w3.I("0xc0fe"), }, - } - - rpctest.RunTestCases(t, tests) + }) } diff --git a/module/eth/storage_at_test.go b/module/eth/storage_at_test.go index 707cb674..1f2f202c 100644 --- a/module/eth/storage_at_test.go +++ b/module/eth/storage_at_test.go @@ -10,13 +10,11 @@ import ( ) func TestStorageAt(t *testing.T) { - tests := []rpctest.TestCase[common.Hash]{ + rpctest.RunTestCases(t, []rpctest.TestCase[common.Hash]{ { Golden: "get_storage_at", Call: eth.StorageAt(w3.A("0x000000000000000000000000000000000000c0DE"), w3.H("0x0000000000000000000000000000000000000000000000000000000000000001"), nil), - WantRet: ptr(w3.H("0x0000000000000000000000000000000000000000000000000000000000000042")), + WantRet: w3.H("0x0000000000000000000000000000000000000000000000000000000000000042"), }, - } - - rpctest.RunTestCases(t, tests) + }) } diff --git a/module/eth/tx.go b/module/eth/tx.go index 3bcf832b..3a6a8ce3 100644 --- a/module/eth/tx.go +++ b/module/eth/tx.go @@ -11,24 +11,24 @@ import ( ) // Tx requests the transaction with the given hash. -func Tx(hash common.Hash) w3types.RPCCallerFactory[types.Transaction] { - return module.NewFactory[types.Transaction]( +func Tx(hash common.Hash) w3types.RPCCallerFactory[*types.Transaction] { + return module.NewFactory[*types.Transaction]( "eth_getTransactionByHash", []any{hash}, ) } // TxByBlockHashAndIndex requests the transaction in the given block with the given index. -func TxByBlockHashAndIndex(blockHash common.Hash, index uint64) w3types.RPCCallerFactory[types.Transaction] { - return module.NewFactory[types.Transaction]( +func TxByBlockHashAndIndex(blockHash common.Hash, index uint64) w3types.RPCCallerFactory[*types.Transaction] { + return module.NewFactory[*types.Transaction]( "eth_getTransactionByBlockHashAndIndex", []any{blockHash, hexutil.Uint64(index)}, ) } // TxByBlockNumberAndIndex requests the transaction in the given block with the given index. -func TxByBlockNumberAndIndex(blockNumber *big.Int, index uint64) w3types.RPCCallerFactory[types.Transaction] { - return module.NewFactory[types.Transaction]( +func TxByBlockNumberAndIndex(blockNumber *big.Int, index uint64) w3types.RPCCallerFactory[*types.Transaction] { + return module.NewFactory[*types.Transaction]( "eth_getTransactionByBlockNumberAndIndex", []any{module.BlockNumberArg(blockNumber), hexutil.Uint64(index)}, ) @@ -60,8 +60,8 @@ func SendTx(tx *types.Transaction) w3types.RPCCallerFactory[common.Hash] { } // TxReceipt requests the receipt of the transaction with the given hash. -func TxReceipt(txHash common.Hash) w3types.RPCCallerFactory[types.Receipt] { - return module.NewFactory[types.Receipt]( +func TxReceipt(txHash common.Hash) w3types.RPCCallerFactory[*types.Receipt] { + return module.NewFactory[*types.Receipt]( "eth_getTransactionReceipt", []any{txHash}, ) diff --git a/module/eth/tx_test.go b/module/eth/tx_test.go index d274c54d..9af056eb 100644 --- a/module/eth/tx_test.go +++ b/module/eth/tx_test.go @@ -29,87 +29,63 @@ var type2Tx = types.NewTx(&types.DynamicFeeTx{ }) func TestTx(t *testing.T) { - tests := []rpctest.TestCase[types.Transaction]{ - { - Golden: "get_transaction_by_hash__type0", - Call: eth.Tx(w3.H("0x2ecd08e86079f08cfc27c326aa01b1c8d62f288d5961118056bac7da315f94d9")), - WantRet: types.NewTx(&types.LegacyTx{ - Nonce: 3292, - GasPrice: w3.I("1559 gwei"), - Gas: 21000, - To: w3.APtr("0x46499275b5c4d67dfa46B92D89aADA3158ea392e"), - V: w3.I("0x26"), - R: w3.I("0xcfaab0b753c1d71f695029e5b5da2f2f619370f5f224a42e1c19dcdcb9e814da"), - S: w3.I("0x606961e8b1dce9439df856ef1d1243f81f45938bac647568253260473efe7cc1"), - }), - }, - { - Golden: "get_transaction_by_hash__type2", - Call: eth.Tx(w3.H("0xed382cb554ad10e94921d263a56c670669d6c380bbdacdbf96fed625b7132a1d")), - WantRet: type2Tx, - }, - { - Golden: "get_transaction_by_hash__0x00", - Call: eth.Tx(common.Hash{}), - WantErr: fmt.Errorf("w3: call failed: not found"), - }, - } - - rpctest.RunTestCases(t, tests, - cmp.AllowUnexported(types.Transaction{}, atomic.Value{}), - cmpopts.IgnoreFields(types.Transaction{}, "time"), - ) -} - -func TestTxByBlockHashAndIndex(t *testing.T) { - tests := []rpctest.TestCase[types.Transaction]{ - { - Golden: "get_transaction_by_block_hash_and_index", - Call: eth.TxByBlockHashAndIndex(w3.H("0xa32d159805750cbe428b799a49b85dcb2300f61d806786f317260e721727d162"), 98), - WantRet: type2Tx, - }, - { - Golden: "get_transaction_by_block_hash_and_index__300", - Call: eth.TxByBlockHashAndIndex(w3.H("0xa32d159805750cbe428b799a49b85dcb2300f61d806786f317260e721727d162"), 300), - WantErr: fmt.Errorf("w3: call failed: not found"), + rpctest.RunTestCases(t, + []rpctest.TestCase[*types.Transaction]{ + { + Golden: "get_transaction_by_hash__type0", + Call: eth.Tx(w3.H("0x2ecd08e86079f08cfc27c326aa01b1c8d62f288d5961118056bac7da315f94d9")), + WantRet: types.NewTx(&types.LegacyTx{ + Nonce: 3292, + GasPrice: w3.I("1559 gwei"), + Gas: 21000, + To: w3.APtr("0x46499275b5c4d67dfa46B92D89aADA3158ea392e"), + V: w3.I("0x26"), + R: w3.I("0xcfaab0b753c1d71f695029e5b5da2f2f619370f5f224a42e1c19dcdcb9e814da"), + S: w3.I("0x606961e8b1dce9439df856ef1d1243f81f45938bac647568253260473efe7cc1"), + }), + }, + { + Golden: "get_transaction_by_hash__type2", + Call: eth.Tx(w3.H("0xed382cb554ad10e94921d263a56c670669d6c380bbdacdbf96fed625b7132a1d")), + WantRet: type2Tx, + }, + { + Golden: "get_transaction_by_hash__0x00", + Call: eth.Tx(common.Hash{}), + WantErr: fmt.Errorf("w3: call failed: not found"), + }, }, - } - - rpctest.RunTestCases(t, tests, cmp.AllowUnexported(types.Transaction{}, atomic.Value{}), cmpopts.IgnoreFields(types.Transaction{}, "time"), ) } func TestTxByBlockNumberAndIndex(t *testing.T) { - tests := []rpctest.TestCase[types.Transaction]{ - { - Golden: "get_transaction_by_block_number_and_index", - Call: eth.TxByBlockNumberAndIndex(big.NewInt(12965001), 98), - WantRet: type2Tx, + rpctest.RunTestCases(t, + []rpctest.TestCase[*types.Transaction]{ + { + Golden: "get_transaction_by_block_number_and_index", + Call: eth.TxByBlockNumberAndIndex(big.NewInt(12965001), 98), + WantRet: type2Tx, + }, }, - } - - rpctest.RunTestCases(t, tests, cmp.AllowUnexported(types.Transaction{}, atomic.Value{}), cmpopts.IgnoreFields(types.Transaction{}, "time"), ) } func TestSendTx(t *testing.T) { - tests := []rpctest.TestCase[common.Hash]{ + rpctest.RunTestCases(t, []rpctest.TestCase[common.Hash]{ { Golden: "send_raw_transaction", Call: eth.SendTx(type2Tx), - WantRet: ptr(w3.H("0xed382cb554ad10e94921d263a56c670669d6c380bbdacdbf96fed625b7132a1d")), + WantRet: w3.H("0xed382cb554ad10e94921d263a56c670669d6c380bbdacdbf96fed625b7132a1d"), }, - } - - rpctest.RunTestCases(t, tests) + }) } func TestTxReceipt(t *testing.T) { - tests := []rpctest.TestCase[types.Receipt]{ + rpctest.RunTestCases(t, []rpctest.TestCase[*types.Receipt]{ { Golden: "get_transaction_receipt", Call: eth.TxReceipt(w3.H("0xed382cb554ad10e94921d263a56c670669d6c380bbdacdbf96fed625b7132a1d")), @@ -147,17 +123,15 @@ func TestTxReceipt(t *testing.T) { Call: eth.TxReceipt(common.Hash{}), WantErr: fmt.Errorf("w3: call failed: not found"), }, - } - - rpctest.RunTestCases(t, tests) + }) } func TestBlockReceipts(t *testing.T) { - tests := []rpctest.TestCase[types.Receipts]{ + rpctest.RunTestCases(t, []rpctest.TestCase[types.Receipts]{ { Golden: "get_block_receipts", Call: eth.BlockReceipts(big.NewInt(0xc0fe)), - WantRet: &types.Receipts{ + WantRet: types.Receipts{ { Type: 2, Status: types.ReceiptStatusSuccessful, @@ -188,19 +162,15 @@ func TestBlockReceipts(t *testing.T) { }, }, }, - } - - rpctest.RunTestCases(t, tests) + }) } func TestNonce(t *testing.T) { - tests := []rpctest.TestCase[uint64]{ + rpctest.RunTestCases(t, []rpctest.TestCase[uint64]{ { Golden: "get_transaction_count", Call: eth.Nonce(w3.A("0x000000000000000000000000000000000000c0Fe"), nil), - WantRet: ptr[uint64](1), + WantRet: 1, }, - } - - rpctest.RunTestCases(t, tests) + }) } diff --git a/module/eth/uncle.go b/module/eth/uncle.go index 85fbeadc..30458d42 100644 --- a/module/eth/uncle.go +++ b/module/eth/uncle.go @@ -12,8 +12,8 @@ import ( // UncleByBlockHashAndIndex requests the uncle of the block with the given hash // at the given index. -func UncleByBlockHashAndIndex(hash common.Hash, index uint) w3types.RPCCallerFactory[types.Header] { - return module.NewFactory[types.Header]( +func UncleByBlockHashAndIndex(hash common.Hash, index uint) w3types.RPCCallerFactory[*types.Header] { + return module.NewFactory[*types.Header]( "eth_getUncleByBlockHashAndIndex", []any{hash, hexutil.Uint(index)}, ) @@ -21,8 +21,8 @@ func UncleByBlockHashAndIndex(hash common.Hash, index uint) w3types.RPCCallerFac // UncleByBlockNumberAndIndex requests the uncle of the block with the given // number at the given index. -func UncleByBlockNumberAndIndex(number *big.Int, index uint) w3types.RPCCallerFactory[types.Header] { - return module.NewFactory[types.Header]( +func UncleByBlockNumberAndIndex(number *big.Int, index uint) w3types.RPCCallerFactory[*types.Header] { + return module.NewFactory[*types.Header]( "eth_getUncleByBlockNumberAndIndex", []any{module.BlockNumberArg(number), hexutil.Uint(index)}, ) diff --git a/module/eth/uncle_test.go b/module/eth/uncle_test.go index 07d0cb7c..ebb40740 100644 --- a/module/eth/uncle_test.go +++ b/module/eth/uncle_test.go @@ -41,7 +41,7 @@ func blockBloom(data []byte) (bloom types.Bloom) { } func TestUncleByBlockHashAndIndex(t *testing.T) { - tests := []rpctest.TestCase[types.Header]{ + rpctest.RunTestCases(t, []rpctest.TestCase[*types.Header]{ { Golden: "uncle_by_hash_and_index__15050036", Call: eth.UncleByBlockHashAndIndex(w3.H("0x7a98a492c1288a8451905bc665cb28d45fbdf8913c34d4ad756acb0609342e67"), 0), @@ -52,43 +52,35 @@ func TestUncleByBlockHashAndIndex(t *testing.T) { Call: eth.UncleByBlockHashAndIndex(w3.H("0x7a98a492c1288a8451905bc665cb28d45fbdf8913c34d4ad756acb0609342e67"), 1), WantErr: errors.New("w3: call failed: not found"), }, - } - - rpctest.RunTestCases(t, tests) + }) } func TestUncleByBlockNumberAndIndex(t *testing.T) { - tests := []rpctest.TestCase[types.Header]{ + rpctest.RunTestCases(t, []rpctest.TestCase[*types.Header]{ { Golden: "uncle_by_number_and_index__15050036", Call: eth.UncleByBlockNumberAndIndex(big.NewInt(15050036), 0), WantRet: header15050036, }, - } - - rpctest.RunTestCases(t, tests) + }) } func TestUncleCountByBlockHash(t *testing.T) { - tests := []rpctest.TestCase[uint]{ + rpctest.RunTestCases(t, []rpctest.TestCase[uint]{ { Golden: "uncle_count_by_hash__15050036", Call: eth.UncleCountByBlockHash(w3.H("0x7a98a492c1288a8451905bc665cb28d45fbdf8913c34d4ad756acb0609342e67")), - WantRet: ptr[uint](1), + WantRet: 1, }, - } - - rpctest.RunTestCases(t, tests) + }) } func TestUncleCountByBlockNumber(t *testing.T) { - tests := []rpctest.TestCase[uint]{ + rpctest.RunTestCases(t, []rpctest.TestCase[uint]{ { Golden: "uncle_count_by_number__15050036", Call: eth.UncleCountByBlockNumber(big.NewInt(15050036)), - WantRet: ptr[uint](1), + WantRet: 1, }, - } - - rpctest.RunTestCases(t, tests) + }) } diff --git a/module/txpool/content.go b/module/txpool/content.go index 7b0f74a2..5b097715 100644 --- a/module/txpool/content.go +++ b/module/txpool/content.go @@ -11,8 +11,8 @@ import ( ) // Content requests the pending and queued transactions in the transaction pool. -func Content() w3types.RPCCallerFactory[ContentResponse] { - return module.NewFactory[ContentResponse]( +func Content() w3types.RPCCallerFactory[*ContentResponse] { + return module.NewFactory[*ContentResponse]( "txpool_content", nil, ) @@ -20,8 +20,8 @@ func Content() w3types.RPCCallerFactory[ContentResponse] { // ContentFrom requests the pending and queued transactions in the transaction pool // from the given address. -func ContentFrom(addr common.Address) w3types.RPCCallerFactory[ContentFromResponse] { - return module.NewFactory[ContentFromResponse]( +func ContentFrom(addr common.Address) w3types.RPCCallerFactory[*ContentFromResponse] { + return module.NewFactory[*ContentFromResponse]( "txpool_contentFrom", []any{addr}, ) diff --git a/module/txpool/content_test.go b/module/txpool/content_test.go index 8ac2bf64..8497b3d4 100644 --- a/module/txpool/content_test.go +++ b/module/txpool/content_test.go @@ -6,60 +6,59 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/lmittmann/w3" "github.com/lmittmann/w3/module/txpool" "github.com/lmittmann/w3/rpctest" ) func TestContent(t *testing.T) { - tests := []rpctest.TestCase[txpool.ContentResponse]{ + rpctest.RunTestCases(t, []rpctest.TestCase[*txpool.ContentResponse]{ { Golden: "content", Call: txpool.Content(), WantRet: &txpool.ContentResponse{ Pending: map[common.Address][]*types.Transaction{ - common.HexToAddress("0x000454307bB96E303044046a6eB2736D2aD560B6"): { + w3.A("0x000454307bB96E303044046a6eB2736D2aD560B6"): { types.NewTx(&types.DynamicFeeTx{ ChainID: big.NewInt(1), Nonce: 4652, GasTipCap: big.NewInt(31407912032), GasFeeCap: big.NewInt(202871575924), Gas: 1100000, - To: ptr(common.HexToAddress("0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B")), + To: w3.APtr("0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B"), Value: big.NewInt(81000000000000000), - Data: common.FromHex("0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000001896e196d5300000000000000000000000000000000000000000000000000000000000000030b090c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000011fc51222ce800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000004657febe8d8000000000000000000000000000000000000000000000000000011fc51222ce800000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000008d538a82c84d7003aa0e7f1098bd9dc5ea1777be000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000"), - R: new(big.Int).SetBytes(common.FromHex("0xf91729846ac8bb780a7239b7f0157d53330bba310a0811f4eec2eae25172c252")), - S: new(big.Int).SetBytes(common.FromHex("0x1bb9a1b9aea8b128e0e8dc42b17664be50c7b4073973c730b6c4cf2a3b3503cb")), + Data: w3.B("0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000001896e196d5300000000000000000000000000000000000000000000000000000000000000030b090c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000011fc51222ce800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000004657febe8d8000000000000000000000000000000000000000000000000000011fc51222ce800000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000008d538a82c84d7003aa0e7f1098bd9dc5ea1777be000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000"), + R: new(big.Int).SetBytes(w3.B("0xf91729846ac8bb780a7239b7f0157d53330bba310a0811f4eec2eae25172c252")), + S: new(big.Int).SetBytes(w3.B("0x1bb9a1b9aea8b128e0e8dc42b17664be50c7b4073973c730b6c4cf2a3b3503cb")), }), }, }, Queued: map[common.Address][]*types.Transaction{ - common.HexToAddress("0x1BA4Ca9ac6ff4CF192C11E8C1624563f302cAA87"): { + w3.A("0x1BA4Ca9ac6ff4CF192C11E8C1624563f302cAA87"): { types.NewTx(&types.DynamicFeeTx{ ChainID: big.NewInt(1), Nonce: 183, GasTipCap: big.NewInt(110000000), GasFeeCap: big.NewInt(20027736270), Gas: 99226, - To: ptr(common.HexToAddress("0x1BA4Ca9ac6ff4CF192C11E8C1624563f302cAA87")), + To: w3.APtr("0x1BA4Ca9ac6ff4CF192C11E8C1624563f302cAA87"), Value: big.NewInt(0), Data: []byte{}, - R: new(big.Int).SetBytes(common.FromHex("0xea35c7c0643b79664b0bbb7f42d64edd371508ae4c33c1f817a80a2655465935")), - S: new(big.Int).SetBytes(common.FromHex("0x76d39f794e9e1ee359d66b7d3b19b90aaf2051b2159c68f3bb8c954558989da8")), + R: new(big.Int).SetBytes(w3.B("0xea35c7c0643b79664b0bbb7f42d64edd371508ae4c33c1f817a80a2655465935")), + S: new(big.Int).SetBytes(w3.B("0x76d39f794e9e1ee359d66b7d3b19b90aaf2051b2159c68f3bb8c954558989da8")), }), }, }, }, }, - } - - rpctest.RunTestCases(t, tests) + }) } func TestContentFrom(t *testing.T) { - tests := []rpctest.TestCase[txpool.ContentFromResponse]{ + rpctest.RunTestCases(t, []rpctest.TestCase[*txpool.ContentFromResponse]{ { Golden: "contentFrom", - Call: txpool.ContentFrom(common.HexToAddress("0x1BA4Ca9ac6ff4CF192C11E8C1624563f302cAA87")), + Call: txpool.ContentFrom(w3.A("0x1BA4Ca9ac6ff4CF192C11E8C1624563f302cAA87")), WantRet: &txpool.ContentFromResponse{ Queued: []*types.Transaction{ types.NewTx(&types.DynamicFeeTx{ @@ -68,18 +67,14 @@ func TestContentFrom(t *testing.T) { GasTipCap: big.NewInt(110000000), GasFeeCap: big.NewInt(20027736270), Gas: 99226, - To: ptr(common.HexToAddress("0x1BA4Ca9ac6ff4CF192C11E8C1624563f302cAA87")), + To: w3.APtr("0x1BA4Ca9ac6ff4CF192C11E8C1624563f302cAA87"), Value: big.NewInt(0), Data: []byte{}, - R: new(big.Int).SetBytes(common.FromHex("0xea35c7c0643b79664b0bbb7f42d64edd371508ae4c33c1f817a80a2655465935")), - S: new(big.Int).SetBytes(common.FromHex("0x76d39f794e9e1ee359d66b7d3b19b90aaf2051b2159c68f3bb8c954558989da8")), + R: new(big.Int).SetBytes(w3.B("0xea35c7c0643b79664b0bbb7f42d64edd371508ae4c33c1f817a80a2655465935")), + S: new(big.Int).SetBytes(w3.B("0x76d39f794e9e1ee359d66b7d3b19b90aaf2051b2159c68f3bb8c954558989da8")), }), }, }, }, - } - - rpctest.RunTestCases(t, tests) + }) } - -func ptr[T any](v T) *T { return &v } diff --git a/module/txpool/status.go b/module/txpool/status.go index 4cd64e11..d263baba 100644 --- a/module/txpool/status.go +++ b/module/txpool/status.go @@ -9,8 +9,8 @@ import ( ) // Status requests the number of pending and queued transactions in the transaction pool. -func Status() w3types.RPCCallerFactory[StatusResponse] { - return module.NewFactory[StatusResponse]( +func Status() w3types.RPCCallerFactory[*StatusResponse] { + return module.NewFactory[*StatusResponse]( "txpool_status", nil, ) diff --git a/module/txpool/status_test.go b/module/txpool/status_test.go index 9d61d255..9cd9556b 100644 --- a/module/txpool/status_test.go +++ b/module/txpool/status_test.go @@ -8,13 +8,11 @@ import ( ) func TestStatus(t *testing.T) { - tests := []rpctest.TestCase[txpool.StatusResponse]{ + rpctest.RunTestCases(t, []rpctest.TestCase[*txpool.StatusResponse]{ { Golden: "status", Call: txpool.Status(), WantRet: &txpool.StatusResponse{Pending: 10, Queued: 7}, }, - } - - rpctest.RunTestCases(t, tests) + }) } diff --git a/module/web3/client_version_test.go b/module/web3/client_version_test.go index 2795d7b2..70f99db8 100644 --- a/module/web3/client_version_test.go +++ b/module/web3/client_version_test.go @@ -9,20 +9,16 @@ import ( ) func TestClientVersion(t *testing.T) { - tests := []rpctest.TestCase[string]{ + rpctest.RunTestCases(t, []rpctest.TestCase[string]{ { Golden: "client_version", Call: web3.ClientVersion(), - WantRet: ptr("Geth"), + WantRet: "Geth", }, { Golden: "client_version__err", Call: web3.ClientVersion(), WantErr: errors.New("w3: call failed: the method web3_clientVersion does not exist/is not available"), }, - } - - rpctest.RunTestCases(t, tests) + }) } - -func ptr[T any](v T) *T { return &v } diff --git a/rpctest/test_case.go b/rpctest/test_case.go index ccd6a517..b345c8ff 100644 --- a/rpctest/test_case.go +++ b/rpctest/test_case.go @@ -16,7 +16,7 @@ import ( type TestCase[T any] struct { Golden string // File name in local "testdata/" directory without ".golden" extension Call w3types.RPCCallerFactory[T] // Call to test - WantRet *T // Wanted return value of the call + WantRet T // Wanted return value of the call WantErr error // Wanted error of the call } @@ -33,14 +33,14 @@ func RunTestCases[T any](t *testing.T, tests []TestCase[T], opts ...cmp.Option) client := w3.MustDial(srv.URL()) defer client.Close() - gotRet := new(T) - gotErr := client.Call(test.Call.Returns(gotRet)) + var gotRet T + gotErr := client.Call(test.Call.Returns(&gotRet)) comp(t, test.WantRet, gotRet, test.WantErr, gotErr, opts...) }) } } -func comp[T any](t *testing.T, wantVal, gotVal *T, wantErr, gotErr error, opts ...cmp.Option) { +func comp[T any](t *testing.T, wantVal, gotVal T, wantErr, gotErr error, opts ...cmp.Option) { t.Helper() // compare errors diff --git a/w3vm/bench_test.go b/w3vm/bench_test.go index cc9fc364..73de63e0 100644 --- a/w3vm/bench_test.go +++ b/w3vm/bench_test.go @@ -24,16 +24,14 @@ import ( func BenchmarkVM(b *testing.B) { const ( startBlock int64 = 19_000_000 - endBlock int64 = startBlock + 10 + nBlocks int = 10 ) // fetch blocks - blocks := make([]*types.Block, 0, endBlock-startBlock) - calls := make([]w3types.RPCCaller, 0, endBlock-startBlock) - for i := startBlock; i < endBlock; i++ { - block := new(types.Block) - blocks = append(blocks, block) - calls = append(calls, eth.BlockByNumber(big.NewInt(i)).Returns(block)) + blocks := make([]*types.Block, nBlocks) + calls := make([]w3types.RPCCaller, nBlocks) + for i, block := range blocks { + calls[i] = eth.BlockByNumber(big.NewInt(int64(i))).Returns(&block) } if err := client.Call(calls...); err != nil { diff --git a/w3vm/vm.go b/w3vm/vm.go index ebae1525..ea43ebb9 100644 --- a/w3vm/vm.go +++ b/w3vm/vm.go @@ -410,15 +410,13 @@ func (opts *options) Init() error { latest := opts.forkBlockNumber == nil if latest { - opts.forkBlockNumber = new(big.Int) - calls = append(calls, eth.BlockNumber().Returns(opts.forkBlockNumber)) + calls = append(calls, eth.BlockNumber().Returns(&opts.forkBlockNumber)) } if opts.header == nil && opts.blockCtx == nil { - opts.header = new(types.Header) if latest { - calls = append(calls, eth.HeaderByNumber(pendingBlockNumber).Returns(opts.header)) + calls = append(calls, eth.HeaderByNumber(pendingBlockNumber).Returns(&opts.header)) } else { - calls = append(calls, eth.HeaderByNumber(opts.forkBlockNumber).Returns(opts.header)) + calls = append(calls, eth.HeaderByNumber(opts.forkBlockNumber).Returns(&opts.header)) } } diff --git a/w3vm/vm_test.go b/w3vm/vm_test.go index 33160ebd..713710bf 100644 --- a/w3vm/vm_test.go +++ b/w3vm/vm_test.go @@ -670,7 +670,6 @@ func TestVMApply_Integration(t *testing.T) { for _, test := range tests { t.Run(test.Name, func(t *testing.T) { // execute blocks - for i := test.Offset; i < test.Offset+test.Size; i++ { // gather block and receipts blockNumber := big.NewInt(int64(i)) @@ -679,7 +678,7 @@ func TestVMApply_Integration(t *testing.T) { t.Parallel() var ( - block types.Block + block *types.Block receipts types.Receipts ) if err := client.Call(