From 701f579413c15af5b59753a0df4e02fb10535f14 Mon Sep 17 00:00:00 2001 From: lmittmann Date: Thu, 3 Oct 2024 17:35:37 +0200 Subject: [PATCH 01/23] w3vm: restructured and added examples --- w3vm/example_test.go | 264 +++++++++++++++++++++++++++++++++++++++++++ w3vm/vm_test.go | 146 ------------------------ 2 files changed, 264 insertions(+), 146 deletions(-) create mode 100644 w3vm/example_test.go diff --git a/w3vm/example_test.go b/w3vm/example_test.go new file mode 100644 index 0000000..75cc58b --- /dev/null +++ b/w3vm/example_test.go @@ -0,0 +1,264 @@ +package w3vm_test + +import ( + "fmt" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/lmittmann/w3" + "github.com/lmittmann/w3/w3types" + "github.com/lmittmann/w3/w3vm" +) + +var ( + addrA = common.Address{0x0a} + addrB = common.Address{0x0b} +) + +func ExampleVM_simpleTransfer() { + vm, _ := w3vm.New( + w3vm.WithState(w3types.State{ + addrA: {Balance: w3.I("100 ether")}, + }), + ) + + // Print balances + balA, _ := vm.Balance(addrA) + balB, _ := vm.Balance(addrB) + fmt.Printf("Before transfer:\nA: %s ETH, B: %s ETH\n", w3.FromWei(balA, 18), w3.FromWei(balB, 18)) + + // Transfer 10 ETH from A to B + vm.Apply(&w3types.Message{ + From: addrA, + To: &addrB, + Value: w3.I("10 ether"), + }) + + // Print balances + balA, _ = vm.Balance(addrA) + balB, _ = vm.Balance(addrB) + fmt.Printf("After transfer:\nA: %s ETH, B: %s ETH\n", w3.FromWei(balA, 18), w3.FromWei(balB, 18)) + + // Output: + // Before transfer: + // A: 100 ETH, B: 0 ETH + // After transfer: + // A: 90 ETH, B: 10 ETH +} + +func ExampleVM_fakeTokenBalance() { + vm, err := w3vm.New( + w3vm.WithFork(client, nil), + w3vm.WithNoBaseFee(), + w3vm.WithState(w3types.State{ + addrWETH: {Storage: w3types.Storage{ + w3vm.WETHBalanceSlot(addrA): common.BigToHash(w3.I("100 ether")), + }}, + }), + ) + if err != nil { + // ... + } + + // Print WETH balance + var balA, balB *big.Int + if err := vm.CallFunc(addrWETH, funcBalanceOf, addrA).Returns(&balA); err != nil { + // ... + } + if err := vm.CallFunc(addrWETH, funcBalanceOf, addrB).Returns(&balB); err != nil { + // ... + } + fmt.Printf("Before transfer:\nA: %s WETH, B: %s WETH\n", w3.FromWei(balA, 18), w3.FromWei(balB, 18)) + + // Transfer 10 WETH from A to B + if _, err := vm.Apply(&w3types.Message{ + From: addrA, + To: &addrWETH, + Func: funcTransfer, + Args: []any{addrB, w3.I("10 ether")}, + }); err != nil { + // ... + } + + // Print WETH balance + if err := vm.CallFunc(addrWETH, funcBalanceOf, addrA).Returns(&balA); err != nil { + // ... + } + if err := vm.CallFunc(addrWETH, funcBalanceOf, addrB).Returns(&balB); err != nil { + // ... + } + fmt.Printf("After transfer:\nA: %s WETH, B: %s WETH\n", w3.FromWei(balA, 18), w3.FromWei(balB, 18)) + + // Output: + // Before transfer: + // A: 100 WETH, B: 0 WETH + // After transfer: + // A: 90 WETH, B: 10 WETH +} + +func ExampleVM_call() { + vm, err := w3vm.New( + w3vm.WithFork(client, nil), + w3vm.WithState(w3types.State{ + addrWETH: {Storage: w3types.Storage{ + w3vm.WETHBalanceSlot(addrA): common.BigToHash(w3.I("100 ether")), + }}, + }), + ) + if err != nil { + // ... + } + + receipt, err := vm.Call(&w3types.Message{ + To: &addrWETH, + Func: funcBalanceOf, + Args: []any{addrA}, + }) + if err != nil { + // ... + } + + var balance *big.Int + if err := receipt.DecodeReturns(&balance); err != nil { + // ... + } + fmt.Printf("Balance: %s WETH\n", w3.FromWei(balance, 18)) + + // Output: + // Balance: 100 WETH +} + +func ExampleVM_callFunc() { + vm, err := w3vm.New( + w3vm.WithFork(client, nil), + w3vm.WithState(w3types.State{ + addrWETH: {Storage: w3types.Storage{ + w3vm.WETHBalanceSlot(addrA): common.BigToHash(w3.I("100 ether")), + }}, + }), + ) + if err != nil { + // ... + } + + var balance *big.Int + if err := vm.CallFunc(addrWETH, funcBalanceOf, addrA).Returns(&balance); err != nil { + // ... + } + fmt.Printf("Balance: %s WETH\n", w3.FromWei(balance, 18)) + + // Output: + // Balance: 100 WETH +} + +func ExampleVM_uniswapV3Swap() { + var ( + addrRouter = w3.A("0xE592427A0AEce92De3Edee1F18E0157C05861564") + addrUNI = w3.A("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984") + + funcExactInput = w3.MustNewFunc(`exactInput( + ( + bytes path, + address recipient, + uint256 deadline, + uint256 amountIn, + uint256 amountOutMinimum + ) params + )`, "uint256 amountOut") + ) + + // mapping for the exactInput-function params-tuple + type ExactInputParams struct { + Path []byte + Recipient common.Address + Deadline *big.Int + AmountIn *big.Int + AmountOutMinimum *big.Int + } + + encodePath := func(tokenA, tokenB common.Address, fee uint32) []byte { + path := make([]byte, 43) + copy(path, tokenA[:]) + path[20], path[21], path[22] = byte(fee>>16), byte(fee>>8), byte(fee) + copy(path[23:], tokenB[:]) + return path + } + + vm, err := w3vm.New( + w3vm.WithFork(client, big.NewInt(20_000_000)), + w3vm.WithNoBaseFee(), + w3vm.WithState(w3types.State{ + addrWETH: {Storage: w3types.Storage{ + w3vm.WETHBalanceSlot(addrA): common.BigToHash(w3.I("1 ether")), + w3vm.WETHAllowanceSlot(addrA, addrRouter): common.BigToHash(w3.I("1 ether")), + }}, + }), + ) + if err != nil { + // ... + } + + receipt, err := vm.Apply(&w3types.Message{ + From: addrA, + To: &addrRouter, + Func: funcExactInput, + Args: []any{&ExactInputParams{ + Path: encodePath(addrWETH, addrUNI, 500), + Recipient: addrA, + Deadline: big.NewInt(time.Now().Unix()), + AmountIn: w3.I("1 ether"), + AmountOutMinimum: w3.Big0, + }}, + }) + if err != nil { + // ... + } + + // 3. Decode output amount + var amountOut *big.Int + if err := receipt.DecodeReturns(&amountOut); err != nil { + // ... + } + + fmt.Printf("AmountOut: %s UNI\n", w3.FromWei(amountOut, 18)) + + // Output: + // AmountOut: 278.327327986946583271 UNI +} + +// The [w3types.Message] sender can be freely chosen. Thus executions by any +// sender can be simulated. +func ExampleVM_prankZeroAddress() { + vm, err := w3vm.New( + w3vm.WithFork(client, big.NewInt(20_000_000)), + w3vm.WithNoBaseFee(), + ) + if err != nil { + // ... + } + + balZero, err := vm.Balance(w3.Addr0) + if err != nil { + // ... + } + + _, err = vm.Apply(&w3types.Message{ + From: w3.Addr0, + To: &addrA, + Value: balZero, + }) + if err != nil { + // ... + } + + balance, err := vm.Balance(addrA) + if err != nil { + // ... + } + + fmt.Printf("Received %s ETH from zero address\n", w3.FromWei(balance, 18)) + + // Output: + // Received 13365.401185473565028721 ETH from zero address +} diff --git a/w3vm/vm_test.go b/w3vm/vm_test.go index dc9fbd1..218420f 100644 --- a/w3vm/vm_test.go +++ b/w3vm/vm_test.go @@ -810,149 +810,3 @@ func BenchmarkTransferWETH9(b *testing.B) { } func ptr[T any](t T) *T { return &t } - -func ExampleVM_transferEthFromZeroAddress() { - client, err := w3.Dial("https://rpc.ankr.com/eth") - if err != nil { - // handle error - } - defer client.Close() - - vm, err := w3vm.New( - w3vm.WithFork(client, nil), - w3vm.WithNoBaseFee(), - ) - if err != nil { - // handle error - } - - recipient := w3vm.RandA() - - _, err = vm.Apply(&w3types.Message{ - From: common.Address{}, - To: &recipient, - Value: w3.I("1 ether"), - }) - if err != nil { - // handle error - } - - balance, err := vm.Balance(recipient) - if err != nil { - // handle error - } - - fmt.Printf("Balance: %s ETH\n", w3.FromWei(balance, 18)) - // Output: Balance: 1 ETH -} - -func ExampleVM() { - var ( - addrEOA = w3.A("0x000000000000000000000000000000000000c0Fe") - addrWETH = w3.A("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") - addrUNI = w3.A("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984") - addrRouter = w3.A("0xE592427A0AEce92De3Edee1F18E0157C05861564") - - funcExactInput = w3.MustNewFunc(`exactInput( - ( - bytes path, - address recipient, - uint256 deadline, - uint256 amountIn, - uint256 amountOutMinimum - ) params - )`, "uint256 amountOut") - ) - - type ExactInputParams struct { - Path []byte - Recipient common.Address - Deadline *big.Int - AmountIn *big.Int - AmountOutMinimum *big.Int - } - - encodePath := func(tokenA common.Address, fee uint32, tokenB common.Address) []byte { - path := make([]byte, 43) - copy(path, tokenA[:]) - path[20], path[21], path[22] = byte(fee>>16), byte(fee>>8), byte(fee) - copy(path[23:], tokenB[:]) - return path - } - - client, err := w3.Dial("https://rpc.ankr.com/eth") - if err != nil { - // handle error - } - defer client.Close() - - // 1. Create a VM that forks the Mainnet state from the latest block, - // disables the base fee, and has a fake WETH balance and approval for the router - vm, err := w3vm.New( - w3vm.WithFork(client, nil), - w3vm.WithNoBaseFee(), - w3vm.WithState(w3types.State{ - addrWETH: {Storage: w3types.Storage{ - w3vm.WETHBalanceSlot(addrEOA): common.BigToHash(w3.I("1 ether")), - w3vm.WETHAllowanceSlot(addrEOA, addrRouter): common.BigToHash(w3.I("1 ether")), - }}, - }), - ) - if err != nil { - // handle error - } - - // 2. Simulate a UniSwap v3 swap - receipt, err := vm.Apply(&w3types.Message{ - From: addrEOA, - To: &addrRouter, - Func: funcExactInput, - Args: []any{&ExactInputParams{ - Path: encodePath(addrWETH, 500, addrUNI), - Recipient: addrEOA, - Deadline: big.NewInt(time.Now().Unix()), - AmountIn: w3.I("1 ether"), - AmountOutMinimum: w3.Big0, - }}, - }) - if err != nil { - // handle error - } - - // 3. Decode output amount - var amountOut *big.Int - if err := receipt.DecodeReturns(&amountOut); err != nil { - // handle error - } - - fmt.Printf("amount out: %s UNI\n", w3.FromWei(amountOut, 18)) -} - -func ExampleVM_Call() { - client := w3.MustDial("https://rpc.ankr.com/eth") - defer client.Close() - - addrWETH := w3.A("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") - addrEOA := w3.A("0x000000000000000000000000000000000000c0Fe") - - vm, err := w3vm.New( - w3vm.WithFork(client, nil), - w3vm.WithState(w3types.State{ - addrWETH: {Storage: w3types.Storage{ - w3vm.WETHBalanceSlot(addrEOA): common.BigToHash(w3.I("1 ether")), - }}, - }), - ) - if err != nil { - // handle error - } - - balanceOf := w3.MustNewFunc("balanceOf(address)", "uint256") - var balance *big.Int - if err := vm.CallFunc(addrWETH, balanceOf, addrEOA).Returns(&balance); err != nil { - // handle error - } - fmt.Printf("%s: Balance: %s WETH\n", addrEOA, w3.FromWei(balance, 18)) - // Output: - // 0x000000000000000000000000000000000000c0Fe: Balance: 1 WETH -} From d940ac59f3cf93d16eb8fe0055b8c7dcfc337c5e Mon Sep 17 00:00:00 2001 From: lmittmann Date: Sat, 5 Oct 2024 11:52:57 +0200 Subject: [PATCH 02/23] moved rpc examples + created new examples --- client_test.go | 213 ---------------------- event_test.go | 28 --- example_test.go | 461 ++++++++++++++++++++++++++++++++++++++++++++++++ func_test.go | 101 ----------- 4 files changed, 461 insertions(+), 342 deletions(-) create mode 100644 example_test.go diff --git a/client_test.go b/client_test.go index abb0e0d..94e4729 100644 --- a/client_test.go +++ b/client_test.go @@ -5,18 +5,14 @@ import ( "context" "errors" "flag" - "fmt" "math/big" "strconv" "testing" - "time" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" "github.com/google/go-cmp/cmp" "github.com/lmittmann/w3" @@ -24,7 +20,6 @@ import ( "github.com/lmittmann/w3/module/eth" "github.com/lmittmann/w3/rpctest" "github.com/lmittmann/w3/w3types" - "golang.org/x/time/rate" ) var ( @@ -36,189 +31,6 @@ var ( `< [{"jsonrpc":"2.0","id":1,"result":"0x1"},{"jsonrpc":"2.0","id":2,"result":"0x1"}]` ) -func ExampleClient() { - addr := w3.A("0x0000000000000000000000000000000000000000") - - // 1. Connect to an RPC endpoint - client, err := w3.Dial("https://rpc.ankr.com/eth") - if err != nil { - // handle error - } - defer client.Close() - - // 2. Make a batch request - var ( - balance *big.Int - nonce uint64 - ) - if err := client.Call( - eth.Balance(addr, nil).Returns(&balance), - eth.Nonce(addr, nil).Returns(&nonce), - ); err != nil { - // handle error - } - - fmt.Printf("balance: %s\nnonce: %d\n", w3.FromWei(balance, 18), nonce) -} - -func ExampleClient_Call_balanceOf() { - // Connect to RPC endpoint (or panic on error) and - // close the connection when you are done. - client := w3.MustDial("https://rpc.ankr.com/eth") - defer client.Close() - - var ( - addr = w3.A("0x000000000000000000000000000000000000dEaD") - weth9 = w3.A("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") - - // Declare a Smart Contract function using Solidity syntax, - // no "abigen" and ABI JSON file needed. - balanceOf = w3.MustNewFunc("balanceOf(address)", "uint256") - - // Declare variables for the RPC responses. - ethBalance *big.Int - weth9Balance *big.Int - ) - - // Do batch request (both RPC requests are send in the same - // HTTP request). - if err := client.Call( - eth.Balance(addr, nil).Returns(ðBalance), - eth.CallFunc(weth9, balanceOf, addr).Returns(&weth9Balance), - ); err != nil { - fmt.Printf("Request failed: %v\n", err) - return - } - - fmt.Printf("Combined balance: %v wei", - new(big.Int).Add(ethBalance, weth9Balance), - ) -} - -func ExampleClient_Call_nonceAndBalance() { - client := w3.MustDial("https://rpc.ankr.com/eth") - defer client.Close() - - var ( - addr = w3.A("0x000000000000000000000000000000000000c0Fe") - - nonce uint64 - balance *big.Int - ) - - if err := client.Call( - eth.Nonce(addr, nil).Returns(&nonce), - eth.Balance(addr, nil).Returns(&balance), - ); err != nil { - fmt.Printf("Request failed: %v\n", err) - return - } - - fmt.Printf("%s: Nonce: %d, Balance: ♦%s\n", addr, nonce, w3.FromWei(balance, 18)) -} - -func ExampleClient_Call_sendERC20transferTx() { - client := w3.MustDial("https://rpc.ankr.com/eth") - defer client.Close() - - var ( - weth9 = w3.A("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") - receiver = w3.A("0x000000000000000000000000000000000000c0Fe") - eoaPrv, _ = crypto.GenerateKey() - ) - - funcTransfer := w3.MustNewFunc("transfer(address receiver, uint256 amount)", "bool") - input, err := funcTransfer.EncodeArgs(receiver, w3.I("1 ether")) - if err != nil { - fmt.Printf("Failed to encode args: %v\n", err) - return - } - - signer := types.LatestSigner(params.MainnetChainConfig) - var txHash common.Hash - if err := client.Call( - eth.SendTx(types.MustSignNewTx(eoaPrv, signer, &types.DynamicFeeTx{ - Nonce: 0, - To: &weth9, - Data: input, - GasTipCap: w3.I("1 gwei"), - GasFeeCap: w3.I("100 gwei"), - Gas: 100_000, - })).Returns(&txHash), - ); err != nil { - fmt.Printf("Failed to send tx: %v\n", err) - return - } - - fmt.Printf("Sent tx: %s\n", txHash) -} - -func ExampleCallErrors() { - client := w3.MustDial("https://rpc.ankr.com/eth") - defer client.Close() - - funcSymbol := w3.MustNewFunc("symbol()", "string") - - // list of addresses that might be an ERC20 token - potentialTokens := []common.Address{ - w3.A("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), - w3.A("0x00000000219ab540356cBB839Cbe05303d7705Fa"), - } - - // build symbol()-call for each potential ERC20 token - tokenSymbols := make([]string, len(potentialTokens)) - rpcCalls := make([]w3types.RPCCaller, len(potentialTokens)) - for i, addr := range potentialTokens { - rpcCalls[i] = eth.CallFunc(addr, funcSymbol).Returns(&tokenSymbols[i]) - } - - // execute batch request - var errs w3.CallErrors - if err := client.Call(rpcCalls...); errors.As(err, &errs) { - // handle call errors - } else if err != nil { - // handle other errors - fmt.Printf("Request failed: %v\n", err) - return - } - - for i, addr := range potentialTokens { - var symbol string - if errs == nil || errs[i] == nil { - symbol = tokenSymbols[i] - } else { - symbol = fmt.Sprintf("unknown symbol: %v", errs[i].Error()) - } - fmt.Printf("%s: %s\n", addr, symbol) - } - - // Output: - // 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2: WETH - // 0x00000000219ab540356cBB839Cbe05303d7705Fa: unknown symbol: execution reverted -} - -func ExampleClient_Subscribe() { - client := w3.MustDial("wss://mainnet.gateway.tenderly.co") - defer client.Close() - - txCh := make(chan *types.Transaction) - sub, err := client.Subscribe(eth.PendingTransactions(txCh)) - if err != nil { - fmt.Printf("Failed to subscribe: %v\n", err) - return - } - - for { - select { - case tx := <-txCh: - fmt.Printf("New pending tx: %s\n", tx.Hash()) - case err := <-sub.Err(): - fmt.Printf("Subscription error: %v\n", err) - return - } - } -} - func TestClientCall(t *testing.T) { tests := []struct { Buf *bytes.Buffer @@ -480,28 +292,3 @@ func BenchmarkCall_Block100(b *testing.B) { } }) } - -func ExampleWithRateLimiter() { - // Limit the client to 30 requests per second and allow bursts of up to - // 100 requests. - client := w3.MustDial("https://rpc.ankr.com/eth", - w3.WithRateLimiter(rate.NewLimiter(rate.Every(time.Second/30), 100), nil), - ) - defer client.Close() -} - -func ExampleWithRateLimiter_costFunc() { - // Limit the client to 30 calls per second and allow bursts of up to - // 100 calls using a cost function. Batch requests have an additional charge. - client := w3.MustDial("https://rpc.ankr.com/eth", - w3.WithRateLimiter(rate.NewLimiter(rate.Every(time.Second/30), 100), - func(methods []string) (cost int) { - cost = len(methods) // charge 1 CU per call - if len(methods) > 1 { - cost += 1 // charge 1 CU extra for the batch itself - } - return cost - }, - )) - defer client.Close() -} diff --git a/event_test.go b/event_test.go index b8c037a..6211330 100644 --- a/event_test.go +++ b/event_test.go @@ -1,7 +1,6 @@ package w3_test import ( - "fmt" "math/big" "strconv" "testing" @@ -13,33 +12,6 @@ import ( "github.com/lmittmann/w3" ) -func ExampleEvent_DecodeArgs() { - var ( - eventTransfer = w3.MustNewEvent("Transfer(address indexed from, address indexed to, uint256 value)") - log = &types.Log{ - Address: w3.A("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), - Topics: []common.Hash{ - w3.H("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"), - w3.H("0x000000000000000000000000000000000000000000000000000000000000c0fe"), - w3.H("0x000000000000000000000000000000000000000000000000000000000000dead"), - }, - Data: w3.B("0x0000000000000000000000000000000000000000000000001111d67bb1bb0000"), - } - - from common.Address - to common.Address - value big.Int - ) - - if err := eventTransfer.DecodeArgs(log, &from, &to, &value); err != nil { - fmt.Printf("Failed to decode event log: %v\n", err) - return - } - fmt.Printf("Transferred %s WETH9 from %s to %s", w3.FromWei(&value, 18), from, to) - // Output: - // Transferred 1.23 WETH9 from 0x000000000000000000000000000000000000c0Fe to 0x000000000000000000000000000000000000dEaD -} - func TestNewEvent(t *testing.T) { tests := []struct { Signature string diff --git a/example_test.go b/example_test.go new file mode 100644 index 0000000..400efdb --- /dev/null +++ b/example_test.go @@ -0,0 +1,461 @@ +package w3_test + +import ( + "crypto/ecdsa" + "errors" + "fmt" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" + "github.com/lmittmann/w3" + "github.com/lmittmann/w3/module/eth" + "github.com/lmittmann/w3/w3types" + "golang.org/x/time/rate" +) + +var ( + funcName = w3.MustNewFunc("name()", "string") + funcSymbol = w3.MustNewFunc("symbol()", "string") + funcDecimals = w3.MustNewFunc("decimals()", "uint8") + funcBalanceOf = w3.MustNewFunc("balanceOf(address)", "uint256") + + addrA = common.Address{0x0a} + addrB = common.Address{0x0b} + + prvA *ecdsa.PrivateKey // dummy private key for addrA + + addrWETH = w3.A("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") + addrDAI = w3.A("0x6B175474E89094C44Da98b954EedeAC495271d0F") + + client = w3.MustDial("https://rpc.ankr.com/eth") +) + +func ExampleClient_batchCallFunc() { + blockNumber := big.NewInt(20_000_000) + + var ( + name, symbol string + decimals uint8 + balance big.Int + ) + if err := client.Call( + eth.CallFunc(addrWETH, funcName).Returns(&name), + eth.CallFunc(addrWETH, funcSymbol).Returns(&symbol), + eth.CallFunc(addrWETH, funcDecimals).Returns(&decimals), + eth.CallFunc(addrWETH, funcBalanceOf, addrWETH).AtBlock(blockNumber).Returns(&balance), + ); err != nil { + // ... + } + + fmt.Printf("%s's own balance: %s %s\n", name, w3.FromWei(&balance, decimals), symbol) + // Output: + // Wrapped Ether's own balance: 748.980125465356473638 WETH +} + +func ExampleClient_batchCallFuncUniswapQuoter() { + blockNumber := big.NewInt(20_000_000) + + var ( + addrUniswapV3Quoter = w3.A("0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6") + addrTokenIn = addrWETH + addrTokenOut = addrDAI + + funcQuote = w3.MustNewFunc(`quoteExactInputSingle( + address tokenIn, + address tokenOut, + uint24 fee, + uint256 amountIn, + uint160 sqrtPriceLimitX96clear + )`, "uint256 amountOut") + ) + + var ( + amountIn = w3.I("100 ether") + amountOut100 *big.Int + amountOut500 *big.Int + amountOut3000 *big.Int + amountOut10000 *big.Int + ) + if err := client.Call( + eth.CallFunc(addrUniswapV3Quoter, funcQuote, addrTokenIn, addrTokenOut, big.NewInt(100), amountIn, w3.Big0).AtBlock(blockNumber).Returns(&amountOut100), + eth.CallFunc(addrUniswapV3Quoter, funcQuote, addrTokenIn, addrTokenOut, big.NewInt(500), amountIn, w3.Big0).AtBlock(blockNumber).Returns(&amountOut500), + eth.CallFunc(addrUniswapV3Quoter, funcQuote, addrTokenIn, addrTokenOut, big.NewInt(3000), amountIn, w3.Big0).AtBlock(blockNumber).Returns(&amountOut3000), + eth.CallFunc(addrUniswapV3Quoter, funcQuote, addrTokenIn, addrTokenOut, big.NewInt(10000), amountIn, w3.Big0).AtBlock(blockNumber).Returns(&amountOut10000), + ); err != nil { + // ... + } + fmt.Println("Swap 100 WETH for DAI:") + fmt.Printf("Pool with 0.01%% fee: %s DAI\n", w3.FromWei(amountOut100, 18)) + fmt.Printf("Pool with 0.05%% fee: %s DAI\n", w3.FromWei(amountOut500, 18)) + fmt.Printf("Pool with 0.3%% fee: %s DAI\n", w3.FromWei(amountOut3000, 18)) + fmt.Printf("Pool with 1%% fee: %s DAI\n", w3.FromWei(amountOut10000, 18)) + + // Output: + // Swap 100 WETH for DAI: + // Pool with 0.01% fee: 0.840975419471618588 DAI + // Pool with 0.05% fee: 371877.453117609415215338 DAI + // Pool with 0.3% fee: 378532.856217317782434539 DAI + // Pool with 1% fee: 3447.634026125332130689 DAI +} + +func ExampleClient_batchEOAState() { + var ( + nonce uint64 + balance *big.Int + ) + if err := client.Call( + eth.Nonce(addrA, nil).Returns(&nonce), + eth.Balance(addrA, nil).Returns(&balance), + ); err != nil { + // ... + } + + fmt.Printf("Nonce: %d\nBalance: %d\n", nonce, balance) +} + +func ExampleClient_batchTxDetails() { + txHash := w3.H("0xc31d7e7e85cab1d38ce1b8ac17e821ccd47dbde00f9d57f2bd8613bff9428396") + + var ( + tx *types.Transaction + receipt *types.Receipt + ) + if err := client.Call( + eth.Tx(txHash).Returns(&tx), + eth.TxReceipt(txHash).Returns(&receipt), + ); err != nil { + // ... + } + + fmt.Printf("Tx: %#v\nReceipt: %#v\n", tx, receipt) +} + +func ExampleClient_batchBlocks() { + const ( + startBlock = 20_000_000 + nBlocks = 1000 + batchSize = 100 + ) + + blocks := make([]*types.Block, nBlocks) + calls := make([]w3types.RPCCaller, batchSize) + for i := 0; i < nBlocks; i += batchSize { + for j := 0; j < batchSize; j++ { + blockNumber := new(big.Int).SetUint64(uint64(startBlock + i + j)) + calls[j] = eth.BlockByNumber(blockNumber).Returns(&blocks[i+j]) + } + if err := client.Call(calls...); err != nil { + // ... + } + fmt.Printf("Fetched %d blocks\n", i+batchSize) + } +} + +func ExampleClient_batchHandleError() { + tokens := []common.Address{addrWETH, addrA, addrB} + symbols := make([]string, len(tokens)) + + // build rpc calls + calls := make([]w3types.RPCCaller, len(tokens)) + for i, token := range tokens { + calls[i] = eth.CallFunc(token, funcSymbol).Returns(&symbols[i]) + } + + var batchErr w3.CallErrors + if err := client.Call(calls...); errors.As(err, &batchErr) { + } else if err != nil { + // all calls failed + } + + for i, symbol := range symbols { + if len(batchErr) > 0 && batchErr[i] != nil { + symbol = "call failed" + } + fmt.Printf("%s: %s\n", tokens[i], symbol) + } + + // Output: + // 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2: WETH + // 0x0a00000000000000000000000000000000000000: call failed + // 0x0B00000000000000000000000000000000000000: call failed +} + +// Transfer 1 ETH from addrA to addrB. +func ExampleClient_sendETHTransfer() { + var ( + nonce uint64 + gasPrice *big.Int + ) + if err := client.Call( + eth.Nonce(addrA, nil).Returns(&nonce), + eth.GasPrice().Returns(&gasPrice), + ); err != nil { + // ... + } + + signer := types.LatestSigner(params.MainnetChainConfig) + tx := types.MustSignNewTx(prvA, signer, &types.LegacyTx{ + Nonce: nonce, + Gas: 21_000, + GasPrice: gasPrice, + To: &addrB, + Value: w3.I("1 ether"), + }) + + var txHash common.Hash + if err := client.Call(eth.SendTx(tx).Returns(&txHash)); err != nil { + // ... + } + + fmt.Printf("Sent tx: %s\n", txHash) +} + +// Transfer 1 WETH from addrA to addrB. +func ExampleClient_sendTokenTransfer() { + var ( + nonce uint64 + gasPrice *big.Int + ) + if err := client.Call( + eth.Nonce(addrA, nil).Returns(&nonce), + eth.GasPrice().Returns(&gasPrice), + ); err != nil { + // ... + } + + funcTransfer := w3.MustNewFunc("transfer(address receiver, uint256 amount)", "bool") + data, err := funcTransfer.EncodeArgs(addrB, w3.I("1 ether")) + if err != nil { + // ... + } + + signer := types.LatestSigner(params.MainnetChainConfig) + tx := types.MustSignNewTx(prvA, signer, &types.LegacyTx{ + Nonce: nonce, + Gas: 100_000, + GasPrice: gasPrice, + To: &addrWETH, + Data: data, + }) + + var txHash common.Hash + if err := client.Call(eth.SendTx(tx).Returns(&txHash)); err != nil { + // ... + } + + fmt.Printf("Sent tx: %s\n", txHash) +} + +// Subscribe to pending transactions. +func ExampleClient_subscribeToPendingTransactions() { + client, err := w3.Dial("wss://mainnet.gateway.tenderly.co") + if err != nil { + // ... + } + defer client.Close() + + pendingTxCh := make(chan *types.Transaction) + sub, err := client.Subscribe(eth.PendingTransactions(pendingTxCh)) + if err != nil { + // ... + } + + for { + select { + case tx := <-pendingTxCh: + fmt.Printf("New pending tx: %s\n", tx.Hash()) + case err := <-sub.Err(): + fmt.Printf("Subscription error: %v\n", err) + return + } + } +} + +// Limit the number of requests to 10 per second, with bursts of up to 20 +// requests. +func ExampleClient_rateLimitByRequest() { + client, err := w3.Dial("https://rpc.ankr.com/eth", + w3.WithRateLimiter(rate.NewLimiter(rate.Every(time.Second/10), 20), nil), + ) + if err != nil { + // ... + } + defer client.Close() +} + +// Limit the number of requests to 300 compute units (CUs) per second, with +// bursts of up to 300 CUs. +// An individual CU can be charged per RPC method call. +func ExampleClient_rateLimitByComputeUnits() { + // cu returns the CU cost for all method calls in a batch. + cu := func(methods []string) (cost int) { + for _, method := range methods { + switch method { + case "eth_blockNumber": + cost += 5 + case "eth_getBalance", + "eth_getBlockByNumber", + "eth_getCode", + "eth_getStorageAt", + "eth_getTransactionByHash", + "eth_getTransactionReceipt": + cost += 15 + case "eth_call": + cost += 20 + case "eth_getTransactionCount": + cost += 25 + default: + panic(fmt.Sprintf("unknown costs for %q", method)) + } + } + return cost + } + + client, err := w3.Dial("https://rpc.ankr.com/eth", + w3.WithRateLimiter(rate.NewLimiter(rate.Every(time.Second/300), 300), cu), + ) + if err != nil { + // ... + } + defer client.Close() +} + +// ABI bindings for the ERC20 functions. +func ExampleFunc_erc20() { + var ( + funcTotalSupply = w3.MustNewFunc("totalSupply()", "uint256") + funcBalanceOf = w3.MustNewFunc("balanceOf(address)", "uint256") + funcTransfer = w3.MustNewFunc("transfer(address to, uint256 amount)", "bool") + funcAllowance = w3.MustNewFunc("allowance(address owner, address spender)", "uint256") + funcApprove = w3.MustNewFunc("approve(address spender, uint256 amount)", "bool") + funcTransferFrom = w3.MustNewFunc("transferFrom(address from, address to, uint256 amount)", "bool") + ) + _ = funcTotalSupply + _ = funcBalanceOf + _ = funcTransfer + _ = funcAllowance + _ = funcApprove + _ = funcTransferFrom +} + +// Encode and decode the arguments of the balanceOf function. +func ExampleFunc_balanceOf() { + // encode + input, err := funcBalanceOf.EncodeArgs(addrA) + if err != nil { + // ... + } + fmt.Printf("encoded: 0x%x\n", input) + + // decode + var who common.Address + if err := funcBalanceOf.DecodeArgs(input, &who); err != nil { + // ... + } + fmt.Printf("decoded: balanceOf(%s)\n", who) + + // Output: + // encoded: 0x70a082310000000000000000000000000a00000000000000000000000000000000000000 + // decoded: balanceOf(0x0a00000000000000000000000000000000000000) +} + +// ABI bindings for the Uniswap v4 swap function. +func ExampleFunc_uniswapV4Swap() { + funcSwap := w3.MustNewFunc(`swap( + (address currency0, address currency1, uint24 fee, int24 tickSpacing, address hooks) key, + (bool zeroForOne, int256 amountSpecified, uint160 sqrtPriceLimitX96) params, + bytes hookData + )`, "int256 delta") + + // ABI binding for the PoolKey struct. + type PoolKey struct { + Currency0 common.Address + Currency1 common.Address + Fee *big.Int + TickSpacing *big.Int + Hooks common.Address + } + + // ABI binding for the SwapParams struct. + type SwapParams struct { + ZeroForOne bool + AmountSpecified *big.Int + SqrtPriceLimitX96 *big.Int + } + + // encode + input, _ := funcSwap.EncodeArgs( + &PoolKey{ + Currency0: addrWETH, + Currency1: addrDAI, + Fee: big.NewInt(0), + TickSpacing: big.NewInt(0), + }, + &SwapParams{ + ZeroForOne: false, + AmountSpecified: big.NewInt(0), + SqrtPriceLimitX96: big.NewInt(0), + }, + []byte{}, + ) + fmt.Printf("encoded: 0x%x\n", input) + + // Output: + // encoded: 0xf3cd914c000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000000 + +} + +func ExampleFunc_DecodeReturns_getReserves() { + funcGetReserves := w3.MustNewFunc("getReserves()", "uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast") + output := w3.B( + "0x00000000000000000000000000000000000000000000003635c9adc5dea00000", + "0x0000000000000000000000000000000000000000000000a2a15d09519be00000", + "0x0000000000000000000000000000000000000000000000000000000064373057", + ) + + var ( + reserve0, reserve1 *big.Int + blockTimestampLast uint32 + ) + if err := funcGetReserves.DecodeReturns(output, &reserve0, &reserve1, &blockTimestampLast); err != nil { + // ... + } + fmt.Println("Reserve0:", reserve0) + fmt.Println("Reserve1:", reserve1) + fmt.Println("BlockTimestampLast:", blockTimestampLast) + // Output: + // Reserve0: 1000000000000000000000 + // Reserve1: 3000000000000000000000 + // BlockTimestampLast: 1681338455 +} + +func ExampleEvent_decodeTransferEvent() { + var ( + eventTransfer = w3.MustNewEvent("Transfer(address indexed from, address indexed to, uint256 value)") + log = &types.Log{ + Address: w3.A("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), + Topics: []common.Hash{ + w3.H("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"), + w3.H("0x000000000000000000000000000000000000000000000000000000000000c0fe"), + w3.H("0x000000000000000000000000000000000000000000000000000000000000dead"), + }, + Data: w3.B("0x0000000000000000000000000000000000000000000000001111d67bb1bb0000"), + } + + from common.Address + to common.Address + value big.Int + ) + + if err := eventTransfer.DecodeArgs(log, &from, &to, &value); err != nil { + fmt.Printf("Failed to decode event log: %v\n", err) + return + } + fmt.Printf("Transferred %s WETH9 from %s to %s", w3.FromWei(&value, 18), from, to) + + // Output: + // Transferred 1.23 WETH9 from 0x000000000000000000000000000000000000c0Fe to 0x000000000000000000000000000000000000dEaD +} diff --git a/func_test.go b/func_test.go index 73137a3..7493021 100644 --- a/func_test.go +++ b/func_test.go @@ -3,7 +3,6 @@ package w3_test import ( "bytes" "errors" - "fmt" "math/big" "strconv" "testing" @@ -16,106 +15,6 @@ import ( "github.com/lmittmann/w3/w3types" ) -func ExampleNewFunc_balanceOf() { - // ABI binding to the balanceOf function of an ERC20 Token. - funcBalanceOf, _ := w3.NewFunc("balanceOf(address)", "uint256") - - // Optionally names can be specified for function arguments. This is - // especially useful for more complex functions with many arguments. - funcBalanceOf, _ = w3.NewFunc("balanceOf(address who)", "uint256 amount") - - // ABI-encode the functions args. - input, _ := funcBalanceOf.EncodeArgs(w3.A("0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B")) - fmt.Printf("balanceOf input: 0x%x\n", input) - - // ABI-decode the functions args from a given input. - var ( - who common.Address - ) - funcBalanceOf.DecodeArgs(input, &who) - fmt.Printf("balanceOf args: %v\n", who) - - // ABI-decode the functions output. - var ( - output = w3.B("0x000000000000000000000000000000000000000000000000000000000000c0fe") - amount *big.Int - ) - funcBalanceOf.DecodeReturns(output, &amount) - fmt.Printf("balanceOf returns: %v\n", amount) - // Output: - // balanceOf input: 0x70a08231000000000000000000000000ab5801a7d398351b8be11c439e05c5b3259aec9b - // balanceOf args: 0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B - // balanceOf returns: 49406 -} - -func ExampleNewFunc_uniswapV4Swap() { - // ABI binding for the Uniswap v4 swap function. - funcSwap, _ := w3.NewFunc(`swap( - (address currency0, address currency1, uint24 fee, int24 tickSpacing, address hooks) key, - (bool zeroForOne, int256 amountSpecified, uint160 sqrtPriceLimitX96) params, - bytes hookData - )`, "int256 delta") - - // ABI binding for the PoolKey struct. - type PoolKey struct { - Currency0 common.Address - Currency1 common.Address - Fee *big.Int - TickSpacing *big.Int - Hooks common.Address - } - - // ABI binding for the SwapParams struct. - type SwapParams struct { - ZeroForOne bool - AmountSpecified *big.Int - SqrtPriceLimitX96 *big.Int - } - - // ABI-encode the functions args. - input, _ := funcSwap.EncodeArgs( - &PoolKey{ - Currency0: w3.A("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), - Currency1: w3.A("0x6B175474E89094C44Da98b954EedeAC495271d0F"), - Fee: big.NewInt(0), - TickSpacing: big.NewInt(0), - }, - &SwapParams{ - ZeroForOne: false, - AmountSpecified: big.NewInt(0), - SqrtPriceLimitX96: big.NewInt(0), - }, - []byte{}, - ) - fmt.Printf("swap input: 0x%x\n", input) - // Output: - // swap input: 0xf3cd914c000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000000 -} - -func ExampleFunc_DecodeReturns_getReserves() { - funcGetReserves := w3.MustNewFunc("getReserves()", "uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast") - output := w3.B( - "0x00000000000000000000000000000000000000000000003635c9adc5dea00000", - "0x0000000000000000000000000000000000000000000000a2a15d09519be00000", - "0x0000000000000000000000000000000000000000000000000000000064373057", - ) - - var ( - reserve0, reserve1 *big.Int - blockTimestampLast uint32 - ) - if err := funcGetReserves.DecodeReturns(output, &reserve0, &reserve1, &blockTimestampLast); err != nil { - // ... - } - fmt.Println("Reserve0:", reserve0) - fmt.Println("Reserve1:", reserve1) - fmt.Println("BlockTimestampLast:", blockTimestampLast) - // Output: - // Reserve0: 1000000000000000000000 - // Reserve1: 3000000000000000000000 - // BlockTimestampLast: 1681338455 -} - func TestNewFunc(t *testing.T) { tests := []struct { Signature string From e0ddb154dfad4fe3a84e323568669cb890922540 Mon Sep 17 00:00:00 2001 From: lmittmann Date: Sat, 5 Oct 2024 12:00:12 +0200 Subject: [PATCH 03/23] added callFunc examples --- example_test.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/example_test.go b/example_test.go index 400efdb..360877d 100644 --- a/example_test.go +++ b/example_test.go @@ -13,6 +13,7 @@ import ( "github.com/lmittmann/w3" "github.com/lmittmann/w3/module/eth" "github.com/lmittmann/w3/w3types" + "github.com/lmittmann/w3/w3vm" "golang.org/x/time/rate" ) @@ -183,6 +184,38 @@ func ExampleClient_batchHandleError() { // 0x0B00000000000000000000000000000000000000: call failed } +func ExampleClient_callFunc() { + var balance *big.Int + if err := client.Call( + eth.CallFunc(addrWETH, funcBalanceOf, addrA).Returns(&balance), + ); err != nil { + // ... + } + + fmt.Printf("Balance: %s WETH\n", w3.FromWei(balance, 18)) + + // Output: + // Balance: 0 WETH +} + +func ExampleClient_callFuncWithStateOverride() { + var balance *big.Int + if err := client.Call( + eth.CallFunc(addrWETH, funcBalanceOf, addrA).Overrides(w3types.State{ + addrWETH: {Storage: w3types.Storage{ + w3vm.WETHBalanceSlot(addrA): common.BigToHash(w3.I("100 ether")), + }}, + }).Returns(&balance), + ); err != nil { + // ... + } + + fmt.Printf("Balance: %s WETH\n", w3.FromWei(balance, 18)) + + // Output: + // Balance: 100 WETH +} + // Transfer 1 ETH from addrA to addrB. func ExampleClient_sendETHTransfer() { var ( From c44c2177ae90ab1fee34ccd105f3bedefd956e3d Mon Sep 17 00:00:00 2001 From: lmittmann Date: Sat, 5 Oct 2024 12:01:53 +0200 Subject: [PATCH 04/23] dropped `examples/` directory --- examples/README.md | 10 --- examples/go.mod | 37 --------- examples/go.sum | 145 --------------------------------- examples/scan_blocks/main.go | 74 ----------------- examples/token_balance/main.go | 72 ---------------- examples/uniswap_quote/main.go | 111 ------------------------- 6 files changed, 449 deletions(-) delete mode 100644 examples/README.md delete mode 100644 examples/go.mod delete mode 100644 examples/go.sum delete mode 100644 examples/scan_blocks/main.go delete mode 100644 examples/token_balance/main.go delete mode 100644 examples/uniswap_quote/main.go diff --git a/examples/README.md b/examples/README.md deleted file mode 100644 index 766ab6f..0000000 --- a/examples/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Examples - -The following example projects can help you understand `w3`: - -* [scan_blocks](scan_blocks/): Scan blocks blazing fast using batch requests. -* [token_balance](token_balance/): Fetch an accounts token balance and info in a single batch request. -* [uniswap_quote](uniswap_quote/): Get the best Uniswap V3 quote for the given token pair. - -Please [open an issue](https://github.com/lmittmann/w3/issues/new) if you -would like to see another example. diff --git a/examples/go.mod b/examples/go.mod deleted file mode 100644 index 08c8ff2..0000000 --- a/examples/go.mod +++ /dev/null @@ -1,37 +0,0 @@ -module examples - -go 1.22 - -require ( - github.com/ethereum/go-ethereum v1.14.8 - github.com/lmittmann/w3 v0.0.0 -) - -replace github.com/lmittmann/w3 => ../ - -require ( - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/StackExchange/wmi v1.2.1 // indirect - github.com/bits-and-blooms/bitset v1.10.0 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect - github.com/consensys/bavard v0.1.13 // indirect - github.com/consensys/gnark-crypto v0.12.1 // indirect - github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect - github.com/deckarep/golang-set/v2 v2.6.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect - github.com/ethereum/c-kzg-4844 v1.0.0 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/holiman/uint256 v1.3.1 // indirect - github.com/mmcloughlin/addchain v0.4.0 // indirect - github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect - github.com/supranational/blst v0.3.11 // indirect - github.com/tklauser/go-sysconf v0.3.12 // indirect - github.com/tklauser/numcpus v0.6.1 // indirect - golang.org/x/crypto v0.22.0 // indirect - golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/time v0.6.0 // indirect - rsc.io/tmplfunc v0.0.3 // indirect -) diff --git a/examples/go.sum b/examples/go.sum deleted file mode 100644 index fb2f063..0000000 --- a/examples/go.sum +++ /dev/null @@ -1,145 +0,0 @@ -github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= -github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= -github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= -github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= -github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= -github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= -github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= -github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I= -github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= -github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4= -github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= -github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= -github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v1.1.1 h1:XnKU22oiCLy2Xn8vp1re67cXg4SAasg/WDt1NtcRFaw= -github.com/cockroachdb/pebble v1.1.1/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU= -github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= -github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= -github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= -github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= -github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= -github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= -github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= -github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c h1:uQYC5Z1mdLRPrZhHjHxufI8+2UG/i25QG92j0Er9p6I= -github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= -github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI= -github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= -github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= -github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= -github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA= -github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/ethereum/go-ethereum v1.14.8 h1:NgOWvXS+lauK+zFukEvi85UmmsS/OkV0N23UZ1VTIig= -github.com/ethereum/go-ethereum v1.14.8/go.mod h1:TJhyuDq0JDppAkFXgqjwpdlQApywnu/m10kFPxh8vvs= -github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0 h1:KrE8I4reeVvf7C1tm8elRjj4BdscTYzz/WAbYyf/JI4= -github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0/go.mod h1:D9AJLVXSyZQXJQVk8oh1EwjISE+sJTn2duYIZC0dy3w= -github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= -github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= -github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= -github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/holiman/uint256 v1.3.1 h1:JfTzmih28bittyHM8z360dCjIA9dbPIBlcTI6lmctQs= -github.com/holiman/uint256 v1.3.1/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= -github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= -github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= -github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= -github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.12.0 h1:C+UIj/QWtmqY13Arb8kwMt5j34/0Z2iKamrJ+ryC0Gg= -github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a h1:CmF68hwI0XsOQ5UwlBopMi2Ow4Pbg32akc4KIVCOm+Y= -github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= -github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= -github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= -github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= -github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= -golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= -rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/examples/scan_blocks/main.go b/examples/scan_blocks/main.go deleted file mode 100644 index 5a8e50d..0000000 --- a/examples/scan_blocks/main.go +++ /dev/null @@ -1,74 +0,0 @@ -/* -scan_blocks iterates over blocks with their transactions from a given start block. - -Usage: - - scan_blocks [flags] - -Flags: - - -start uint - Start block (default 10_000_000) - -h, --help - help for scan_blocks -*/ -package main - -import ( - "flag" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/core/types" - "github.com/lmittmann/w3" - "github.com/lmittmann/w3/module/eth" - "github.com/lmittmann/w3/w3types" -) - -var ( - // number of blocks to fetch in a single request - bulkSize = 100 - - // flags - startBlock uint64 -) - -func main() { - // parse flags - flag.Uint64Var(&startBlock, "start", 10_000_000, "Start block") - flag.Usage = func() { - fmt.Println("scan_blocks iterates over blocks with their transactions from a given start block.") - flag.PrintDefaults() - } - flag.Parse() - - // connect to RPC endpoint - client := w3.MustDial("https://rpc.ankr.com/eth") - defer client.Close() - - // fetch blocks in bulk - calls := make([]w3types.RPCCaller, bulkSize) - blocks := make([]*types.Block, bulkSize) - - for i, txCount := 0, 0; ; i++ { - j := i % bulkSize - calls[j] = eth.BlockByNumber(new(big.Int).SetUint64(startBlock + uint64(i))).Returns(&blocks[j]) - - if j == bulkSize-1 { - if err := client.Call(calls...); err != nil { - fmt.Printf("Call failed: %v\r", err) - return - } - - for _, block := range blocks { - txCount += len(block.Transactions()) - processBlock(block) - } - fmt.Printf("\rFetched %d blocks with a total of %d transactions", i+1, txCount) - } - } -} - -func processBlock(b *types.Block) { - // Do something with the block and its transactions... -} diff --git a/examples/token_balance/main.go b/examples/token_balance/main.go deleted file mode 100644 index 4687cf9..0000000 --- a/examples/token_balance/main.go +++ /dev/null @@ -1,72 +0,0 @@ -/* -token_balance prints the balance of an ERC20 token for a given account. - -Usage: - - token_balance [flags] - -Flags: - - -acc string - Account address (default "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") - -token string - Token address (default "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") - -h, --help - help for token_balance -*/ -package main - -import ( - "flag" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/lmittmann/w3" - "github.com/lmittmann/w3/module/eth" -) - -var ( - // smart contract functions - funcName = w3.MustNewFunc("name()", "string") - funcSymbol = w3.MustNewFunc("symbol()", "string") - funcDecimals = w3.MustNewFunc("decimals()", "uint8") - funcBalanceOf = w3.MustNewFunc("balanceOf(address)", "uint256") - - // flags - addrAcc common.Address - addrToken common.Address -) - -func main() { - // parse flags - flag.TextVar(&addrAcc, "acc", w3.A("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), "Account address") - flag.TextVar(&addrToken, "token", w3.A("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), "Token address") - flag.Usage = func() { - fmt.Println("token_balance prints the balance of an ERC20 token for a given account.") - flag.PrintDefaults() - } - flag.Parse() - - // connect to RPC endpoint - client := w3.MustDial("https://rpc.ankr.com/eth") - defer client.Close() - - // fetch token details and account balance - var ( - name, symbol string - decimals uint8 - balance big.Int - ) - if err := client.Call( - eth.CallFunc(addrToken, funcName).Returns(&name), - eth.CallFunc(addrToken, funcSymbol).Returns(&symbol), - eth.CallFunc(addrToken, funcDecimals).Returns(&decimals), - eth.CallFunc(addrToken, funcBalanceOf, addrAcc).Returns(&balance), - ); err != nil { - fmt.Printf("Call failed: %v\n", err) - return - } - - fmt.Printf("%s balance of %s: %s %s\n", name, addrAcc, w3.FromWei(&balance, decimals), symbol) -} diff --git a/examples/uniswap_quote/main.go b/examples/uniswap_quote/main.go deleted file mode 100644 index 6e2cca2..0000000 --- a/examples/uniswap_quote/main.go +++ /dev/null @@ -1,111 +0,0 @@ -/* -uniswap_quote prints the UniSwap V3 exchange rate to swap amontIn of tokenIn for -tokenOut. - -Usage: - - uniswap_quote [flags] - -Flags: - - -amountIn string - Amount of tokenIn to exchange for tokenOut (default "1 ether") - -tokenIn string - Token in address (default "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") - -tokenOut string - Token out address (default "0x6B175474E89094C44Da98b954EedeAC495271d0F") - -h, --help - help for uniswap_quote -*/ -package main - -import ( - "flag" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/lmittmann/w3" - "github.com/lmittmann/w3/module/eth" - "github.com/lmittmann/w3/w3types" -) - -var ( - addrUniV3Quoter = w3.A("0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6") - - funcQuoteExactInputSingle = w3.MustNewFunc("quoteExactInputSingle(address tokenIn, address tokenOut, uint24 fee, uint256 amountIn, uint160 sqrtPriceLimitX96)", "uint256 amountOut") - funcName = w3.MustNewFunc("name()", "string") - funcSymbol = w3.MustNewFunc("symbol()", "string") - funcDecimals = w3.MustNewFunc("decimals()", "uint8") - - // flags - addrTokenIn common.Address - addrTokenOut common.Address - amountIn big.Int -) - -func main() { - // parse flags - flag.TextVar(&amountIn, "amountIn", w3.I("1 ether"), "Token address") - flag.TextVar(&addrTokenIn, "tokenIn", w3.A("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), "Token in") - flag.TextVar(&addrTokenOut, "tokenOut", w3.A("0x6B175474E89094C44Da98b954EedeAC495271d0F"), "Token out") - flag.Usage = func() { - fmt.Println("uniswap_quote prints the UniSwap V3 exchange rate to swap amontIn of tokenIn for tokenOut.") - flag.PrintDefaults() - } - flag.Parse() - - // connect to RPC endpoint - client := w3.MustDial("https://rpc.ankr.com/eth") - defer client.Close() - - // fetch token details - var ( - tokenInName string - tokenInSymbol string - tokenInDecimals uint8 - tokenOutName string - tokenOutSymbol string - tokenOutDecimals uint8 - ) - if err := client.Call( - eth.CallFunc(addrTokenIn, funcName).Returns(&tokenInName), - eth.CallFunc(addrTokenIn, funcSymbol).Returns(&tokenInSymbol), - eth.CallFunc(addrTokenIn, funcDecimals).Returns(&tokenInDecimals), - eth.CallFunc(addrTokenOut, funcName).Returns(&tokenOutName), - eth.CallFunc(addrTokenOut, funcSymbol).Returns(&tokenOutSymbol), - eth.CallFunc(addrTokenOut, funcDecimals).Returns(&tokenOutDecimals), - ); err != nil { - fmt.Printf("Failed to fetch token details: %v\n", err) - return - } - - // fetch quotes - var ( - fees = []*big.Int{big.NewInt(100), big.NewInt(500), big.NewInt(3000), big.NewInt(10000)} - calls = make([]w3types.RPCCaller, len(fees)) - amountsOut = make([]big.Int, len(fees)) - ) - for i, fee := range fees { - calls[i] = eth.CallFunc(addrUniV3Quoter, funcQuoteExactInputSingle, addrTokenIn, addrTokenOut, fee, &amountIn, w3.Big0).Returns(&amountsOut[i]) - } - err := client.Call(calls...) - callErrs, ok := err.(w3.CallErrors) - if err != nil && !ok { - fmt.Printf("Failed to fetch quotes: %v\n", err) - return - - } - - // print quotes - fmt.Printf("Exchange %q for %q\n", tokenInName, tokenOutName) - fmt.Printf("Amount in:\n %s %s\n", w3.FromWei(&amountIn, tokenInDecimals), tokenInSymbol) - fmt.Printf("Amount out:\n") - for i, fee := range fees { - if ok && callErrs[i] != nil { - fmt.Printf(" Pool (fee=%5v): Pool does not exist\n", fee) - continue - } - fmt.Printf(" Pool (fee=%5v): %s %s\n", fee, w3.FromWei(&amountsOut[i], tokenOutDecimals), tokenOutSymbol) - } -} From 8093c88d21a9c67c543663b616819e3ed338d65a Mon Sep 17 00:00:00 2001 From: lmittmann Date: Sat, 5 Oct 2024 12:05:21 +0200 Subject: [PATCH 05/23] workflows: fix --- .github/workflows/go.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 92398cf..c6eba1f 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -27,9 +27,7 @@ jobs: - name: staticcheck run: staticcheck ./... - name: go mod tidy - run: | - go mod tidy -diff - cd examples/ && go mod tidy -diff + run: go mod tidy -diff test: name: Test From ef5cacfe671ab46970909c75dd292f3de6eced37 Mon Sep 17 00:00:00 2001 From: lmittmann Date: Sat, 5 Oct 2024 13:26:11 +0200 Subject: [PATCH 06/23] update doc --- docs/pages/_meta.js | 2 -- docs/pages/examples/_meta.js | 20 ++++++++++++++++++++ docs/pages/examples/abi.mdx | 1 + docs/pages/examples/index.mdx | 1 + docs/pages/examples/rpc.mdx | 26 ++++++++++++++++++++++++++ docs/pages/examples/vm.mdx | 1 + 6 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 docs/pages/examples/_meta.js create mode 100644 docs/pages/examples/abi.mdx create mode 100644 docs/pages/examples/index.mdx create mode 100644 docs/pages/examples/rpc.mdx create mode 100644 docs/pages/examples/vm.mdx diff --git a/docs/pages/_meta.js b/docs/pages/_meta.js index 025426d..e54d3e6 100644 --- a/docs/pages/_meta.js +++ b/docs/pages/_meta.js @@ -69,8 +69,6 @@ export default { examples: { title: 'Examples', type: 'page', - href: 'https://github.com/lmittmann/w3/tree/main/examples', - newWindow: true }, godoc: { title: 'GoDoc', diff --git a/docs/pages/examples/_meta.js b/docs/pages/examples/_meta.js new file mode 100644 index 0000000..b59935f --- /dev/null +++ b/docs/pages/examples/_meta.js @@ -0,0 +1,20 @@ +export default { + index: { + title: 'Overview', + + theme: { breadcrumb: false, toc: false, pagination: false }, + }, + 'rpc': { + title: 'RPC', + + theme: { breadcrumb: false }, + }, + 'vm': { + title: 'VM', + theme: { breadcrumb: false }, + }, + 'abi': { + title: 'ABI', + theme: { breadcrumb: false }, + }, +} diff --git a/docs/pages/examples/abi.mdx b/docs/pages/examples/abi.mdx new file mode 100644 index 0000000..0f4971a --- /dev/null +++ b/docs/pages/examples/abi.mdx @@ -0,0 +1 @@ +# ABI Examples diff --git a/docs/pages/examples/index.mdx b/docs/pages/examples/index.mdx new file mode 100644 index 0000000..df635b4 --- /dev/null +++ b/docs/pages/examples/index.mdx @@ -0,0 +1 @@ +# Examples diff --git a/docs/pages/examples/rpc.mdx b/docs/pages/examples/rpc.mdx new file mode 100644 index 0000000..e6c5823 --- /dev/null +++ b/docs/pages/examples/rpc.mdx @@ -0,0 +1,26 @@ +# RPC Examples + +## `w3.Client` Examples + +* BatchBlocks +* BatchCallFunc +* BatchCallFuncUniswapQuoter +* BatchEOAState +* BatchHandleError +* BatchTxDetails +* CallFunc +* CallFuncWithStateOverride +* RateLimitByComputeUnits +* RateLimitByRequest +* SendETHTransfer +* SendTokenTransfer +* SubscribeToPendingTransactions + +## ABI Binding Examples + +* Event (DecodeTransferEvent) +* FromWei +* Func (BalanceOf) +* Func (Erc20) +* Func (UniswapV4Swap) +* Func.DecodeReturns (GetReserves) diff --git a/docs/pages/examples/vm.mdx b/docs/pages/examples/vm.mdx new file mode 100644 index 0000000..d1e2424 --- /dev/null +++ b/docs/pages/examples/vm.mdx @@ -0,0 +1 @@ +# VM Examples From 2e1e257e0620e761ba9f5731a4616c4907e6db5e Mon Sep 17 00:00:00 2001 From: lmittmann Date: Sat, 5 Oct 2024 17:56:54 +0200 Subject: [PATCH 07/23] fmt --- example_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/example_test.go b/example_test.go index 360877d..714004f 100644 --- a/example_test.go +++ b/example_test.go @@ -438,7 +438,6 @@ func ExampleFunc_uniswapV4Swap() { // Output: // encoded: 0xf3cd914c000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000000 - } func ExampleFunc_DecodeReturns_getReserves() { From 18fa9892d22df97fecd6e6cd3f769c7fa0dddf9a Mon Sep 17 00:00:00 2001 From: lmittmann Date: Sat, 5 Oct 2024 18:05:09 +0200 Subject: [PATCH 08/23] fmt --- example_test.go | 7 ------- w3vm/example_test.go | 6 ------ 2 files changed, 13 deletions(-) diff --git a/example_test.go b/example_test.go index 714004f..2d8b3be 100644 --- a/example_test.go +++ b/example_test.go @@ -93,7 +93,6 @@ func ExampleClient_batchCallFuncUniswapQuoter() { fmt.Printf("Pool with 0.05%% fee: %s DAI\n", w3.FromWei(amountOut500, 18)) fmt.Printf("Pool with 0.3%% fee: %s DAI\n", w3.FromWei(amountOut3000, 18)) fmt.Printf("Pool with 1%% fee: %s DAI\n", w3.FromWei(amountOut10000, 18)) - // Output: // Swap 100 WETH for DAI: // Pool with 0.01% fee: 0.840975419471618588 DAI @@ -177,7 +176,6 @@ func ExampleClient_batchHandleError() { } fmt.Printf("%s: %s\n", tokens[i], symbol) } - // Output: // 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2: WETH // 0x0a00000000000000000000000000000000000000: call failed @@ -193,7 +191,6 @@ func ExampleClient_callFunc() { } fmt.Printf("Balance: %s WETH\n", w3.FromWei(balance, 18)) - // Output: // Balance: 0 WETH } @@ -211,7 +208,6 @@ func ExampleClient_callFuncWithStateOverride() { } fmt.Printf("Balance: %s WETH\n", w3.FromWei(balance, 18)) - // Output: // Balance: 100 WETH } @@ -389,7 +385,6 @@ func ExampleFunc_balanceOf() { // ... } fmt.Printf("decoded: balanceOf(%s)\n", who) - // Output: // encoded: 0x70a082310000000000000000000000000a00000000000000000000000000000000000000 // decoded: balanceOf(0x0a00000000000000000000000000000000000000) @@ -435,7 +430,6 @@ func ExampleFunc_uniswapV4Swap() { []byte{}, ) fmt.Printf("encoded: 0x%x\n", input) - // Output: // encoded: 0xf3cd914c000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000000 } @@ -487,7 +481,6 @@ func ExampleEvent_decodeTransferEvent() { return } fmt.Printf("Transferred %s WETH9 from %s to %s", w3.FromWei(&value, 18), from, to) - // Output: // Transferred 1.23 WETH9 from 0x000000000000000000000000000000000000c0Fe to 0x000000000000000000000000000000000000dEaD } diff --git a/w3vm/example_test.go b/w3vm/example_test.go index 75cc58b..513123d 100644 --- a/w3vm/example_test.go +++ b/w3vm/example_test.go @@ -39,7 +39,6 @@ func ExampleVM_simpleTransfer() { balA, _ = vm.Balance(addrA) balB, _ = vm.Balance(addrB) fmt.Printf("After transfer:\nA: %s ETH, B: %s ETH\n", w3.FromWei(balA, 18), w3.FromWei(balB, 18)) - // Output: // Before transfer: // A: 100 ETH, B: 0 ETH @@ -89,7 +88,6 @@ func ExampleVM_fakeTokenBalance() { // ... } fmt.Printf("After transfer:\nA: %s WETH, B: %s WETH\n", w3.FromWei(balA, 18), w3.FromWei(balB, 18)) - // Output: // Before transfer: // A: 100 WETH, B: 0 WETH @@ -124,7 +122,6 @@ func ExampleVM_call() { // ... } fmt.Printf("Balance: %s WETH\n", w3.FromWei(balance, 18)) - // Output: // Balance: 100 WETH } @@ -147,7 +144,6 @@ func ExampleVM_callFunc() { // ... } fmt.Printf("Balance: %s WETH\n", w3.FromWei(balance, 18)) - // Output: // Balance: 100 WETH } @@ -222,7 +218,6 @@ func ExampleVM_uniswapV3Swap() { } fmt.Printf("AmountOut: %s UNI\n", w3.FromWei(amountOut, 18)) - // Output: // AmountOut: 278.327327986946583271 UNI } @@ -258,7 +253,6 @@ func ExampleVM_prankZeroAddress() { } fmt.Printf("Received %s ETH from zero address\n", w3.FromWei(balance, 18)) - // Output: // Received 13365.401185473565028721 ETH from zero address } From ccdaabab2fc8eb92ffc03a999a8d3437570d6f05 Mon Sep 17 00:00:00 2001 From: lmittmann Date: Sat, 5 Oct 2024 22:15:54 +0200 Subject: [PATCH 09/23] added tracing examples --- w3vm/example_test.go | 84 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/w3vm/example_test.go b/w3vm/example_test.go index 513123d..31f4911 100644 --- a/w3vm/example_test.go +++ b/w3vm/example_test.go @@ -6,7 +6,13 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/tracing" + "github.com/ethereum/go-ethereum/core/types" + gethVm "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/eth/tracers/logger" + "github.com/ethereum/go-ethereum/params" "github.com/lmittmann/w3" + "github.com/lmittmann/w3/module/eth" "github.com/lmittmann/w3/w3types" "github.com/lmittmann/w3/w3vm" ) @@ -256,3 +262,81 @@ func ExampleVM_prankZeroAddress() { // Output: // Received 13365.401185473565028721 ETH from zero address } + +func ExampleVM_traceAccessList() { + txHash := w3.H("0xbb4b3fc2b746877dce70862850602f1d19bd890ab4db47e6b7ee1da1fe578a0d") + + var ( + tx *types.Transaction + receipt *types.Receipt + ) + if err := client.Call( + eth.Tx(txHash).Returns(&tx), + eth.TxReceipt(txHash).Returns(&receipt), + ); err != nil { + // ... + } + + var header *types.Header + if err := client.Call(eth.HeaderByNumber(receipt.BlockNumber).Returns(&header)); err != nil { + // ... + } + + vm, err := w3vm.New( + w3vm.WithFork(client, receipt.BlockNumber), + ) + if err != nil { + // ... + } + + // setup access list hook + signer := types.MakeSigner(params.MainnetChainConfig, header.Number, header.Time) + from, _ := signer.Sender(tx) + + accessListTracer := logger.NewAccessListTracer( + nil, + from, *tx.To(), + gethVm.ActivePrecompiles(params.MainnetChainConfig.Rules(header.Number, header.Difficulty.Sign() == 0, header.Time)), + ) + + if _, err := vm.ApplyTx(tx, accessListTracer.Hooks()); err != nil { + // ... + } + fmt.Println("Access List:", accessListTracer.AccessList()) +} + +func ExampleVM_traceBlock() { + blockNumber := big.NewInt(20_000_000) + + var block *types.Block + if err := client.Call(eth.BlockByNumber(blockNumber).Returns(&block)); err != nil { + // ... + } + + vm, err := w3vm.New( + w3vm.WithFork(client, blockNumber), + ) + if err != nil { + // ... + } + + var ops [256]uint64 + tracer := &tracing.Hooks{ + OnOpcode: func(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { + ops[op]++ + }, + } + + for i, tx := range block.Transactions() { + if i > 4 { + break + } + vm.ApplyTx(tx, tracer) + } + + for op, count := range ops { + if count > 0 { + fmt.Printf("0x%02x %-14s %d\n", op, gethVm.OpCode(op), count) + } + } +} From fadf3dfa06d550f972041db1db63f175c67bf5c9 Mon Sep 17 00:00:00 2001 From: lmittmann Date: Sun, 6 Oct 2024 11:02:03 +0000 Subject: [PATCH 10/23] cleanup --- w3vm/example_test.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/w3vm/example_test.go b/w3vm/example_test.go index 31f4911..f3b2e77 100644 --- a/w3vm/example_test.go +++ b/w3vm/example_test.go @@ -327,10 +327,7 @@ func ExampleVM_traceBlock() { }, } - for i, tx := range block.Transactions() { - if i > 4 { - break - } + for _, tx := range block.Transactions() { vm.ApplyTx(tx, tracer) } From e4b4352224e37b711a034ce6764e100249d1429b Mon Sep 17 00:00:00 2001 From: lmittmann Date: Mon, 7 Oct 2024 16:17:00 +0200 Subject: [PATCH 11/23] . --- docs/pages/_meta.js | 3 ++- docs/pages/examples.mdx | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 docs/pages/examples.mdx diff --git a/docs/pages/_meta.js b/docs/pages/_meta.js index e54d3e6..e78c808 100644 --- a/docs/pages/_meta.js +++ b/docs/pages/_meta.js @@ -7,7 +7,7 @@ export default { '404': { title: '404', display: 'hidden', - 'theme': { + theme: { breadcrumb: false, toc: false, layout: 'full', @@ -68,6 +68,7 @@ export default { }, examples: { title: 'Examples', + theme: { breadcrumb: false, toc: false, pagination: false }, type: 'page', }, godoc: { diff --git a/docs/pages/examples.mdx b/docs/pages/examples.mdx new file mode 100644 index 0000000..df635b4 --- /dev/null +++ b/docs/pages/examples.mdx @@ -0,0 +1 @@ +# Examples From b4114369cadcf799d792e94e662637fe56805639 Mon Sep 17 00:00:00 2001 From: lmittmann Date: Mon, 7 Oct 2024 16:21:53 +0200 Subject: [PATCH 12/23] . --- docs/pages/_meta.js | 2 -- docs/pages/examples/_meta.js | 17 ++--------------- docs/pages/examples/abi.mdx | 1 - docs/pages/examples/index.mdx | 1 - docs/pages/examples/rpc.mdx | 26 -------------------------- docs/pages/examples/vm.mdx | 1 - 6 files changed, 2 insertions(+), 46 deletions(-) delete mode 100644 docs/pages/examples/abi.mdx delete mode 100644 docs/pages/examples/rpc.mdx delete mode 100644 docs/pages/examples/vm.mdx diff --git a/docs/pages/_meta.js b/docs/pages/_meta.js index e78c808..5787d01 100644 --- a/docs/pages/_meta.js +++ b/docs/pages/_meta.js @@ -67,8 +67,6 @@ export default { theme: { breadcrumb: false }, }, examples: { - title: 'Examples', - theme: { breadcrumb: false, toc: false, pagination: false }, type: 'page', }, godoc: { diff --git a/docs/pages/examples/_meta.js b/docs/pages/examples/_meta.js index b59935f..420787d 100644 --- a/docs/pages/examples/_meta.js +++ b/docs/pages/examples/_meta.js @@ -1,20 +1,7 @@ export default { index: { - title: 'Overview', - + title: 'Examples', + display: 'hidden', theme: { breadcrumb: false, toc: false, pagination: false }, }, - 'rpc': { - title: 'RPC', - - theme: { breadcrumb: false }, - }, - 'vm': { - title: 'VM', - theme: { breadcrumb: false }, - }, - 'abi': { - title: 'ABI', - theme: { breadcrumb: false }, - }, } diff --git a/docs/pages/examples/abi.mdx b/docs/pages/examples/abi.mdx deleted file mode 100644 index 0f4971a..0000000 --- a/docs/pages/examples/abi.mdx +++ /dev/null @@ -1 +0,0 @@ -# ABI Examples diff --git a/docs/pages/examples/index.mdx b/docs/pages/examples/index.mdx index df635b4..e69de29 100644 --- a/docs/pages/examples/index.mdx +++ b/docs/pages/examples/index.mdx @@ -1 +0,0 @@ -# Examples diff --git a/docs/pages/examples/rpc.mdx b/docs/pages/examples/rpc.mdx deleted file mode 100644 index e6c5823..0000000 --- a/docs/pages/examples/rpc.mdx +++ /dev/null @@ -1,26 +0,0 @@ -# RPC Examples - -## `w3.Client` Examples - -* BatchBlocks -* BatchCallFunc -* BatchCallFuncUniswapQuoter -* BatchEOAState -* BatchHandleError -* BatchTxDetails -* CallFunc -* CallFuncWithStateOverride -* RateLimitByComputeUnits -* RateLimitByRequest -* SendETHTransfer -* SendTokenTransfer -* SubscribeToPendingTransactions - -## ABI Binding Examples - -* Event (DecodeTransferEvent) -* FromWei -* Func (BalanceOf) -* Func (Erc20) -* Func (UniswapV4Swap) -* Func.DecodeReturns (GetReserves) diff --git a/docs/pages/examples/vm.mdx b/docs/pages/examples/vm.mdx deleted file mode 100644 index d1e2424..0000000 --- a/docs/pages/examples/vm.mdx +++ /dev/null @@ -1 +0,0 @@ -# VM Examples From 86a84b1b7c076b513baff12c16352a484cfd9b27 Mon Sep 17 00:00:00 2001 From: lmittmann Date: Mon, 7 Oct 2024 21:11:15 +0200 Subject: [PATCH 13/23] added example section --- docs/pages/examples.mdx | 33 +++++++++++++++++++++++++++++++++ docs/pages/examples/_meta.js | 2 +- example_test.go | 18 ++++++++++++++---- w3vm/example_test.go | 13 +++++++++++-- 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/docs/pages/examples.mdx b/docs/pages/examples.mdx index df635b4..3d67c65 100644 --- a/docs/pages/examples.mdx +++ b/docs/pages/examples.mdx @@ -1 +1,34 @@ # Examples + +## `w3.Client` Examples + +* **Batch Fetch** 1000 blocks ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchBlocks)) +* **Batch Call** the name, symbol, decimals, and balanceOf functions of the Wrapped Ether in a single batch ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchCallFunc)) +* **Batch Call** the Uniswap V3 Quoter for quotes on swapping 100 WETH for DAI in pools of all fee tiers in a single batch ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchCallFuncUniswapQuoter)) +* **Batch Fetch** the nonce and balance of an EOA in a single batch ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchEOAState)) +* **Batch Fetch** a transaction and its receipt in a single batch ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchTxDetails)) +* **Call** the token balance of an address ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-CallFunc)) +* **Call** the token balance of an address, with state override ([Playground](https://pkg.go.dev/github.com/lmittmann/))w3#example-Client-CallFuncWithStateOverride +* **Handle errors** of individual calls in a batch ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchHandleError)) +* **Rate Limit** the number of requests to 300 compute units (CUs) per second, with bursts of up to 300 CUs. An individual CU can be charged per RPC method call ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-RateLimitByComputeUnits)) +* **Rate Limit** the number of requests to 10 per second, with bursts of up to 20 requests ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-RateLimitByRequest)) +* **Send Ether** transfer ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-SendETHTransfer)) +* **Send ERC20 token** transfer (Wrapped Ether) ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-SendTokenTransfer)) +* **Subscribe** to pending transactions ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-SubscribeToPendingTransactions)) + +**[See all examples ↗](https://pkg.go.dev/github.com/lmittmann/w3#pkg-examples)** + + +## `w3vm.VM` Examples + +* **Ether transfer** ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-SimpleTransfer)) +* **ERC20 token transfer** with faked token balance (Wrapped Ether) ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-FakeTokenBalance)) +* **Uniswap V3 swap** ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-UniswapV3Swap)) + +* **Call ERC20 balanceOf** with raw a `w3types.Message` using the `Message.{Func,Args}` helper ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-Call)) +* **Call ERC20 balanceOf**, using the `VM.CallFunc` helper ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-CallFunc)) +* **Prank** a sender ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-PrankZeroAddress)) +* **Trace** the execution to obtain the access list ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-TraceAccessList)) +* **Trace** the execution of all op's in a block ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-TraceBlock)) + +**[See all examples ↗](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#pkg-examples)** diff --git a/docs/pages/examples/_meta.js b/docs/pages/examples/_meta.js index 420787d..d7bd5dc 100644 --- a/docs/pages/examples/_meta.js +++ b/docs/pages/examples/_meta.js @@ -2,6 +2,6 @@ export default { index: { title: 'Examples', display: 'hidden', - theme: { breadcrumb: false, toc: false, pagination: false }, + theme: { breadcrumb: false, toc: true, pagination: false }, }, } diff --git a/example_test.go b/example_test.go index 2d8b3be..5ddd4d7 100644 --- a/example_test.go +++ b/example_test.go @@ -34,6 +34,8 @@ var ( client = w3.MustDial("https://rpc.ankr.com/eth") ) +// Call the name, symbol, decimals, and balanceOf functions of the Wrapped Ether +// in a single batch. func ExampleClient_batchCallFunc() { blockNumber := big.NewInt(20_000_000) @@ -56,6 +58,8 @@ func ExampleClient_batchCallFunc() { // Wrapped Ether's own balance: 748.980125465356473638 WETH } +// Call the Uniswap V3 Quoter for quotes on swapping 100 WETH for DAI in pools +// of all fee tiers in a single batch. func ExampleClient_batchCallFuncUniswapQuoter() { blockNumber := big.NewInt(20_000_000) @@ -101,6 +105,7 @@ func ExampleClient_batchCallFuncUniswapQuoter() { // Pool with 1% fee: 3447.634026125332130689 DAI } +// Fetch the nonce and balance of an EOA in a single batch. func ExampleClient_batchEOAState() { var ( nonce uint64 @@ -116,6 +121,7 @@ func ExampleClient_batchEOAState() { fmt.Printf("Nonce: %d\nBalance: %d\n", nonce, balance) } +// Fetch a transaction and its receipt in a single batch. func ExampleClient_batchTxDetails() { txHash := w3.H("0xc31d7e7e85cab1d38ce1b8ac17e821ccd47dbde00f9d57f2bd8613bff9428396") @@ -133,6 +139,7 @@ func ExampleClient_batchTxDetails() { fmt.Printf("Tx: %#v\nReceipt: %#v\n", tx, receipt) } +// Fetch 1000 blocks in batches. func ExampleClient_batchBlocks() { const ( startBlock = 20_000_000 @@ -154,6 +161,7 @@ func ExampleClient_batchBlocks() { } } +// Handle errors of individual calls in a batch. func ExampleClient_batchHandleError() { tokens := []common.Address{addrWETH, addrA, addrB} symbols := make([]string, len(tokens)) @@ -182,6 +190,7 @@ func ExampleClient_batchHandleError() { // 0x0B00000000000000000000000000000000000000: call failed } +// Fetch the token balance of an address. func ExampleClient_callFunc() { var balance *big.Int if err := client.Call( @@ -195,6 +204,7 @@ func ExampleClient_callFunc() { // Balance: 0 WETH } +// Fetch the token balance of an address, with state override. func ExampleClient_callFuncWithStateOverride() { var balance *big.Int if err := client.Call( @@ -212,7 +222,7 @@ func ExampleClient_callFuncWithStateOverride() { // Balance: 100 WETH } -// Transfer 1 ETH from addrA to addrB. +// Send Ether transfer. func ExampleClient_sendETHTransfer() { var ( nonce uint64 @@ -242,7 +252,7 @@ func ExampleClient_sendETHTransfer() { fmt.Printf("Sent tx: %s\n", txHash) } -// Transfer 1 WETH from addrA to addrB. +// Send ERC20 token transfer (Wrapped Ether). func ExampleClient_sendTokenTransfer() { var ( nonce uint64 @@ -303,7 +313,7 @@ func ExampleClient_subscribeToPendingTransactions() { } } -// Limit the number of requests to 10 per second, with bursts of up to 20 +// Rate Limit the number of requests to 10 per second, with bursts of up to 20 // requests. func ExampleClient_rateLimitByRequest() { client, err := w3.Dial("https://rpc.ankr.com/eth", @@ -315,7 +325,7 @@ func ExampleClient_rateLimitByRequest() { defer client.Close() } -// Limit the number of requests to 300 compute units (CUs) per second, with +// Rate Limit the number of requests to 300 compute units (CUs) per second, with // bursts of up to 300 CUs. // An individual CU can be charged per RPC method call. func ExampleClient_rateLimitByComputeUnits() { diff --git a/w3vm/example_test.go b/w3vm/example_test.go index f3b2e77..73a424c 100644 --- a/w3vm/example_test.go +++ b/w3vm/example_test.go @@ -22,6 +22,7 @@ var ( addrB = common.Address{0x0b} ) +// Execute an Ether transfer. func ExampleVM_simpleTransfer() { vm, _ := w3vm.New( w3vm.WithState(w3types.State{ @@ -52,6 +53,7 @@ func ExampleVM_simpleTransfer() { // A: 90 ETH, B: 10 ETH } +// Execute an ERC20 token transfer with faked token balance (Wrapped Ether). func ExampleVM_fakeTokenBalance() { vm, err := w3vm.New( w3vm.WithFork(client, nil), @@ -101,6 +103,8 @@ func ExampleVM_fakeTokenBalance() { // A: 90 WETH, B: 10 WETH } +// Execute an ERC20 balanceOf call with raw a [w3types.Message] using the +// messages Func and Args helper. func ExampleVM_call() { vm, err := w3vm.New( w3vm.WithFork(client, nil), @@ -132,6 +136,7 @@ func ExampleVM_call() { // Balance: 100 WETH } +// Execute an ERC20 balanceOf call using the [VM.CallFunc] helper. func ExampleVM_callFunc() { vm, err := w3vm.New( w3vm.WithFork(client, nil), @@ -154,6 +159,7 @@ func ExampleVM_callFunc() { // Balance: 100 WETH } +// Execute an Uniswap V3 swap. func ExampleVM_uniswapV3Swap() { var ( addrRouter = w3.A("0xE592427A0AEce92De3Edee1F18E0157C05861564") @@ -228,8 +234,9 @@ func ExampleVM_uniswapV3Swap() { // AmountOut: 278.327327986946583271 UNI } -// The [w3types.Message] sender can be freely chosen. Thus executions by any -// sender can be simulated. +// Execute a message sent from the zero address. +// The [w3types.Message] sender can be freely chosen, making it possible to +// execute a message from any address. func ExampleVM_prankZeroAddress() { vm, err := w3vm.New( w3vm.WithFork(client, big.NewInt(20_000_000)), @@ -263,6 +270,7 @@ func ExampleVM_prankZeroAddress() { // Received 13365.401185473565028721 ETH from zero address } +// Trace a message execution to obtain the access list. func ExampleVM_traceAccessList() { txHash := w3.H("0xbb4b3fc2b746877dce70862850602f1d19bd890ab4db47e6b7ee1da1fe578a0d") @@ -305,6 +313,7 @@ func ExampleVM_traceAccessList() { fmt.Println("Access List:", accessListTracer.AccessList()) } +// Trace the execution of all op's in a block. func ExampleVM_traceBlock() { blockNumber := big.NewInt(20_000_000) From 3e296c6604c2367f87f783e3dcac984f5dee9a12 Mon Sep 17 00:00:00 2001 From: lmittmann Date: Mon, 7 Oct 2024 21:13:32 +0200 Subject: [PATCH 14/23] test --- docs/pages/examples/index.mdx | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/docs/pages/examples/index.mdx b/docs/pages/examples/index.mdx index e69de29..3d67c65 100644 --- a/docs/pages/examples/index.mdx +++ b/docs/pages/examples/index.mdx @@ -0,0 +1,34 @@ +# Examples + +## `w3.Client` Examples + +* **Batch Fetch** 1000 blocks ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchBlocks)) +* **Batch Call** the name, symbol, decimals, and balanceOf functions of the Wrapped Ether in a single batch ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchCallFunc)) +* **Batch Call** the Uniswap V3 Quoter for quotes on swapping 100 WETH for DAI in pools of all fee tiers in a single batch ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchCallFuncUniswapQuoter)) +* **Batch Fetch** the nonce and balance of an EOA in a single batch ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchEOAState)) +* **Batch Fetch** a transaction and its receipt in a single batch ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchTxDetails)) +* **Call** the token balance of an address ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-CallFunc)) +* **Call** the token balance of an address, with state override ([Playground](https://pkg.go.dev/github.com/lmittmann/))w3#example-Client-CallFuncWithStateOverride +* **Handle errors** of individual calls in a batch ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchHandleError)) +* **Rate Limit** the number of requests to 300 compute units (CUs) per second, with bursts of up to 300 CUs. An individual CU can be charged per RPC method call ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-RateLimitByComputeUnits)) +* **Rate Limit** the number of requests to 10 per second, with bursts of up to 20 requests ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-RateLimitByRequest)) +* **Send Ether** transfer ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-SendETHTransfer)) +* **Send ERC20 token** transfer (Wrapped Ether) ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-SendTokenTransfer)) +* **Subscribe** to pending transactions ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-SubscribeToPendingTransactions)) + +**[See all examples ↗](https://pkg.go.dev/github.com/lmittmann/w3#pkg-examples)** + + +## `w3vm.VM` Examples + +* **Ether transfer** ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-SimpleTransfer)) +* **ERC20 token transfer** with faked token balance (Wrapped Ether) ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-FakeTokenBalance)) +* **Uniswap V3 swap** ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-UniswapV3Swap)) + +* **Call ERC20 balanceOf** with raw a `w3types.Message` using the `Message.{Func,Args}` helper ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-Call)) +* **Call ERC20 balanceOf**, using the `VM.CallFunc` helper ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-CallFunc)) +* **Prank** a sender ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-PrankZeroAddress)) +* **Trace** the execution to obtain the access list ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-TraceAccessList)) +* **Trace** the execution of all op's in a block ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-TraceBlock)) + +**[See all examples ↗](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#pkg-examples)** From 5996e0b69a0e52a0cf8077e8b839ab26b34c0624 Mon Sep 17 00:00:00 2001 From: lmittmann Date: Mon, 7 Oct 2024 21:16:30 +0200 Subject: [PATCH 15/23] fix --- docs/pages/_meta.js | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/pages/_meta.js b/docs/pages/_meta.js index 5787d01..3d63b70 100644 --- a/docs/pages/_meta.js +++ b/docs/pages/_meta.js @@ -67,6 +67,7 @@ export default { theme: { breadcrumb: false }, }, examples: { + title: 'Examples', type: 'page', }, godoc: { From c5d005efcb3ed4dc31942833ec71c338f30ac539 Mon Sep 17 00:00:00 2001 From: lmittmann Date: Mon, 7 Oct 2024 21:19:18 +0200 Subject: [PATCH 16/23] test --- docs/pages/examples/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/examples/index.mdx b/docs/pages/examples/index.mdx index 3d67c65..35a4c6b 100644 --- a/docs/pages/examples/index.mdx +++ b/docs/pages/examples/index.mdx @@ -1,4 +1,4 @@ -# Examples +# Examples 2 ## `w3.Client` Examples From 33f06102013a73991920bbf89c83505350718d9e Mon Sep 17 00:00:00 2001 From: lmittmann Date: Mon, 7 Oct 2024 21:22:45 +0200 Subject: [PATCH 17/23] cleanup --- docs/pages/examples.mdx | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/docs/pages/examples.mdx b/docs/pages/examples.mdx index 3d67c65..e69de29 100644 --- a/docs/pages/examples.mdx +++ b/docs/pages/examples.mdx @@ -1,34 +0,0 @@ -# Examples - -## `w3.Client` Examples - -* **Batch Fetch** 1000 blocks ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchBlocks)) -* **Batch Call** the name, symbol, decimals, and balanceOf functions of the Wrapped Ether in a single batch ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchCallFunc)) -* **Batch Call** the Uniswap V3 Quoter for quotes on swapping 100 WETH for DAI in pools of all fee tiers in a single batch ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchCallFuncUniswapQuoter)) -* **Batch Fetch** the nonce and balance of an EOA in a single batch ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchEOAState)) -* **Batch Fetch** a transaction and its receipt in a single batch ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchTxDetails)) -* **Call** the token balance of an address ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-CallFunc)) -* **Call** the token balance of an address, with state override ([Playground](https://pkg.go.dev/github.com/lmittmann/))w3#example-Client-CallFuncWithStateOverride -* **Handle errors** of individual calls in a batch ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchHandleError)) -* **Rate Limit** the number of requests to 300 compute units (CUs) per second, with bursts of up to 300 CUs. An individual CU can be charged per RPC method call ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-RateLimitByComputeUnits)) -* **Rate Limit** the number of requests to 10 per second, with bursts of up to 20 requests ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-RateLimitByRequest)) -* **Send Ether** transfer ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-SendETHTransfer)) -* **Send ERC20 token** transfer (Wrapped Ether) ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-SendTokenTransfer)) -* **Subscribe** to pending transactions ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-SubscribeToPendingTransactions)) - -**[See all examples ↗](https://pkg.go.dev/github.com/lmittmann/w3#pkg-examples)** - - -## `w3vm.VM` Examples - -* **Ether transfer** ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-SimpleTransfer)) -* **ERC20 token transfer** with faked token balance (Wrapped Ether) ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-FakeTokenBalance)) -* **Uniswap V3 swap** ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-UniswapV3Swap)) - -* **Call ERC20 balanceOf** with raw a `w3types.Message` using the `Message.{Func,Args}` helper ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-Call)) -* **Call ERC20 balanceOf**, using the `VM.CallFunc` helper ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-CallFunc)) -* **Prank** a sender ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-PrankZeroAddress)) -* **Trace** the execution to obtain the access list ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-TraceAccessList)) -* **Trace** the execution of all op's in a block ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-TraceBlock)) - -**[See all examples ↗](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#pkg-examples)** From 34a65fa9ad1fc4807667d180d3f85e5a1a4a6bca Mon Sep 17 00:00:00 2001 From: lmittmann Date: Mon, 7 Oct 2024 21:23:41 +0200 Subject: [PATCH 18/23] fix --- docs/pages/examples/index.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/pages/examples/index.mdx b/docs/pages/examples/index.mdx index 35a4c6b..29fe485 100644 --- a/docs/pages/examples/index.mdx +++ b/docs/pages/examples/index.mdx @@ -1,4 +1,4 @@ -# Examples 2 +# Examples ## `w3.Client` Examples @@ -8,7 +8,7 @@ * **Batch Fetch** the nonce and balance of an EOA in a single batch ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchEOAState)) * **Batch Fetch** a transaction and its receipt in a single batch ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchTxDetails)) * **Call** the token balance of an address ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-CallFunc)) -* **Call** the token balance of an address, with state override ([Playground](https://pkg.go.dev/github.com/lmittmann/))w3#example-Client-CallFuncWithStateOverride +* **Call** the token balance of an address, with state override ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-CallFuncWithStateOverride)) * **Handle errors** of individual calls in a batch ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchHandleError)) * **Rate Limit** the number of requests to 300 compute units (CUs) per second, with bursts of up to 300 CUs. An individual CU can be charged per RPC method call ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-RateLimitByComputeUnits)) * **Rate Limit** the number of requests to 10 per second, with bursts of up to 20 requests ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-RateLimitByRequest)) From 2d38a7750ace5a108968da26cd76d7ade06543a7 Mon Sep 17 00:00:00 2001 From: lmittmann Date: Mon, 7 Oct 2024 21:37:32 +0200 Subject: [PATCH 19/23] drop redirects --- docs/public/_redirects | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/public/_redirects b/docs/public/_redirects index 4ccfb0c..e69de29 100644 --- a/docs/public/_redirects +++ b/docs/public/_redirects @@ -1 +0,0 @@ -/examples https://github.com/lmittmann/w3/tree/main/examples From 1160f2d4dc9bf6b3db74abffe43a13ecf68f2a2b Mon Sep 17 00:00:00 2001 From: lmittmann Date: Mon, 7 Oct 2024 21:53:13 +0200 Subject: [PATCH 20/23] link fixes --- README.md | 10 +++++----- w3vm/example_test.go | 3 +++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7daff0d..9d0c754 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ go get github.com/lmittmann/w3 [`w3.Client`](https://pkg.go.dev/github.com/lmittmann/w3#Client) is a batch request focused RPC client that can be used to connect to an Ethereum node via HTTP, WebSocket, or IPC. Its modular API allows to create custom RPC method integrations that can be used alongside the common methods implemented by this package. -**Example:** Batch Request ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client)) +**Example:** Batch Request ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchEOAState)) ```go // 1. Connect to an RPC endpoint @@ -59,10 +59,10 @@ if err := client.Call( If one or more calls in a batch request fail, `Client.Call` returns an error of type [`w3.CallErrors`](https://pkg.go.dev/github.com/lmittmann/w3#CallErrors). -**Example:** Check which RPC calls failed in a batch request ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-CallErrors)) +**Example:** Check which RPC calls failed in a batch request ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchHandleError)) ```go -var errs w3.CallErrors -if err := client.Call(rpcCalls...); errors.As(err, &errs) { +var batchErr w3.CallErrors +if err := client.Call(calls...); errors.As(err, &batchErr) { // handle call errors } else if err != nil { // handle other errors @@ -77,7 +77,7 @@ if err := client.Call(rpcCalls...); errors.As(err, &errs) { [`w3vm.VM`](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#VM) is a high-level EVM environment with a simple but powerful API to simulate EVM execution, test Smart Contracts, or trace transactions. It supports Mainnet state forking via RPC and state caching for faster testing. -**Example:** Simulate an Uniswap v3 swap ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM)) +**Example:** Simulate an Uniswap v3 swap ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-UniswapV3Swap)) ```go // 1. Create a VM that forks the Mainnet state from the latest block, diff --git a/w3vm/example_test.go b/w3vm/example_test.go index 73a424c..f0be1dc 100644 --- a/w3vm/example_test.go +++ b/w3vm/example_test.go @@ -193,6 +193,8 @@ func ExampleVM_uniswapV3Swap() { return path } + // 1. Create a VM that forks the Mainnet state from the latest block, + // disables the base fee, and has a fake WETH balance and approval for the router vm, err := w3vm.New( w3vm.WithFork(client, big.NewInt(20_000_000)), w3vm.WithNoBaseFee(), @@ -207,6 +209,7 @@ func ExampleVM_uniswapV3Swap() { // ... } + // 2. Simulate a Uniswap v3 swap receipt, err := vm.Apply(&w3types.Message{ From: addrA, To: &addrRouter, From ef6fcf4afb9c4e47819873acffacb70bfcfb1e6c Mon Sep 17 00:00:00 2001 From: lmittmann Date: Mon, 7 Oct 2024 21:59:13 +0200 Subject: [PATCH 21/23] added releases --- docs/pages/_meta.js | 6 ++++++ docs/pages/style.css | 1 + 2 files changed, 7 insertions(+) diff --git a/docs/pages/_meta.js b/docs/pages/_meta.js index 3d63b70..e65285a 100644 --- a/docs/pages/_meta.js +++ b/docs/pages/_meta.js @@ -70,6 +70,12 @@ export default { title: 'Examples', type: 'page', }, + releases: { + title: 'Releases', + type: 'page', + href: 'https://github.com/lmittmann/w3/releases', + newWindow: true + }, godoc: { title: 'GoDoc', type: 'page', diff --git a/docs/pages/style.css b/docs/pages/style.css index 3c36291..b939958 100644 --- a/docs/pages/style.css +++ b/docs/pages/style.css @@ -36,6 +36,7 @@ tr._border-gray-300 { /* Customize header */ .nextra-nav-container nav a[target="_blank"]:nth-child(2):after, .nextra-nav-container nav a[target="_blank"]:nth-child(3):after, +.nextra-nav-container nav a[target="_blank"]:nth-child(4):after, aside.nextra-sidebar-container li a[target="_blank"]:after { content: url('data:image/svg+xml,'); @apply pl-2; From d0ad884ee6ba25bcbadc6711b920581e6af0acac Mon Sep 17 00:00:00 2001 From: lmittmann Date: Mon, 7 Oct 2024 22:51:35 +0200 Subject: [PATCH 22/23] added sponsor notice --- README.md | 8 ++++++++ docs/pages/index.mdx | 10 +++++++++- docs/public/ef-logo-dark.svg | 1 + docs/public/ef-logo.svg | 1 + 4 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 docs/public/ef-logo-dark.svg create mode 100644 docs/public/ef-logo.svg diff --git a/README.md b/README.md index 9d0c754..f1ad7d8 100644 --- a/README.md +++ b/README.md @@ -273,3 +273,11 @@ func (f *getTransactionBySenderAndNonceFactory) HandleResponse(elem rpc.BatchEle return nil } ``` + +## Sponsors + + + + + ef logo + diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx index b3d55eb..78e5106 100644 --- a/docs/pages/index.mdx +++ b/docs/pages/index.mdx @@ -19,7 +19,7 @@ description: 'w3: Enhanced Ethereum Integration for Go' -Hello +W3 Gopher `w3` is your toolbelt for integrating with Ethereum in Go. Closely linked to `go‑ethereum`, it provides an ergonomic wrapper for working with **RPC**, **ABI's**, and the **EVM**. @@ -35,3 +35,11 @@ go get github.com/lmittmann/w3 * Use `w3vm.VM` to simulate EVM execution with optional tracing and Mainnet state forking, or test Smart Contracts. [learn more ➔](/vm-overview) * Use `w3.Func` and `w3.Event` to create ABI bindings from Solidity function and event signatures. [learn more ➔](/helper-abi) * Use `w3.A`, `w3.H`, and many other utility functions to parse addresses, hashes, and other common types from strings. [learn more ➔](/helper-utils) + + +## Sponsors + +
+ EF Logo + +
diff --git a/docs/public/ef-logo-dark.svg b/docs/public/ef-logo-dark.svg new file mode 100644 index 0000000..9b6c529 --- /dev/null +++ b/docs/public/ef-logo-dark.svg @@ -0,0 +1 @@ + diff --git a/docs/public/ef-logo.svg b/docs/public/ef-logo.svg new file mode 100644 index 0000000..ebffdce --- /dev/null +++ b/docs/public/ef-logo.svg @@ -0,0 +1 @@ +f1f5f9 From 45d68db242e67579610a0f7a98ae15131fbec2c2 Mon Sep 17 00:00:00 2001 From: lmittmann Date: Mon, 7 Oct 2024 22:53:26 +0200 Subject: [PATCH 23/23] small fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f1ad7d8..2cf8556 100644 --- a/README.md +++ b/README.md @@ -279,5 +279,5 @@ func (f *getTransactionBySenderAndNonceFactory) HandleResponse(elem rpc.BatchEle - ef logo + ef logo