{"id":13515193,"url":"https://github.com/lmittmann/w3","last_synced_at":"2025-04-09T04:08:01.931Z","repository":{"id":37833606,"uuid":"445624417","full_name":"lmittmann/w3","owner":"lmittmann","description":"Enhanced Ethereum Integration for Go","archived":false,"fork":false,"pushed_at":"2024-10-10T17:35:45.000Z","size":39702,"stargazers_count":179,"open_issues_count":3,"forks_count":32,"subscribers_count":9,"default_branch":"main","last_synced_at":"2024-10-13T19:12:18.176Z","etag":null,"topics":["abi","ethereum","evm","golang","rpc","smart-contracts","w3","web3"],"latest_commit_sha":null,"homepage":"http://w3.cool","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lmittmann.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-07T19:00:41.000Z","updated_at":"2024-10-10T17:35:48.000Z","dependencies_parsed_at":"2023-02-04T02:04:09.734Z","dependency_job_id":"68213f31-8f8d-4153-be13-ddae18169f49","html_url":"https://github.com/lmittmann/w3","commit_stats":{"total_commits":239,"total_committers":7,"mean_commits":"34.142857142857146","dds":"0.18828451882845187","last_synced_commit":"56314e04a1b2ae2bf19e477d79b0730ea0966872"},"previous_names":[],"tags_count":51,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lmittmann%2Fw3","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lmittmann%2Fw3/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lmittmann%2Fw3/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lmittmann%2Fw3/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lmittmann","download_url":"https://codeload.github.com/lmittmann/w3/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247974732,"owners_count":21026742,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["abi","ethereum","evm","golang","rpc","smart-contracts","w3","web3"],"created_at":"2024-08-01T05:01:07.343Z","updated_at":"2025-04-09T04:07:56.922Z","avatar_url":"https://github.com/lmittmann.png","language":"Go","readme":"# `w3`: Enhanced Ethereum Integration for Go\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/lmittmann/w3.svg)](https://pkg.go.dev/github.com/lmittmann/w3)\n[![Go Report Card](https://goreportcard.com/badge/github.com/lmittmann/w3)](https://goreportcard.com/report/github.com/lmittmann/w3)\n[![Coverage Status](https://coveralls.io/repos/github/lmittmann/w3/badge.svg?branch=main)](https://coveralls.io/github/lmittmann/w3?branch=main)\n[![Latest Release](https://img.shields.io/github/v/release/lmittmann/w3)](https://github.com/lmittmann/w3/releases)\n\u003cimg src=\"https://w3.cool/gopher.png\" align=\"right\" alt=\"W3 Gopher\" width=\"158\" height=\"224\"\u003e\n\n`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**.\n\n\n```\ngo get github.com/lmittmann/w3\n```\n\n\n## At a Glance\n\n* Use `w3.Client` to connect to an RPC endpoint. The client features batch request support for up to **80x faster requests** and easy extendibility. [learn\u0026nbsp;more\u0026nbsp;↗](#rpc-client)\n* Use `w3vm.VM` to simulate EVM execution with optional tracing and Mainnet state forking, or test Smart Contracts. [learn\u0026nbsp;more\u0026nbsp;↗](#vm)\n* Use `w3.Func` and `w3.Event` to create ABI bindings from Solidity function and event signatures. [learn\u0026nbsp;more\u0026nbsp;↗](#abi-bindings)\n* Use `w3.A`, `w3.H`, and many other utility functions to parse addresses, hashes, and other common types from strings. [learn\u0026nbsp;more\u0026nbsp;↗](#utils)\n\n\n## Getting Started\n\n### RPC Client\n\n[`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.\n\n**Example:** Batch Request ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchEOAState))\n\n```go\n// 1. Connect to an RPC endpoint\nclient, err := w3.Dial(\"https://rpc.ankr.com/eth\")\nif err != nil {\n    // handle error\n}\ndefer client.Close()\n\n// 2. Make a batch request\nvar (\n    balance *big.Int\n    nonce   uint64\n)\nif err := client.Call(\n    eth.Balance(addr, nil).Returns(\u0026balance),\n    eth.Nonce(addr, nil).Returns(\u0026nonce),\n); err != nil {\n    // handle error\n}\n```\n\n\u003e [!NOTE]\n\u003e #### Why send batch requests?\n\u003e Most of the time you need to call multiple RPC methods to get the data you need. When you make separate requests per RPC call you need a single round trip to the server for each call. This can be slow, especially for remote endpoints. Batching multiple RPC calls into a single request only requires a single round trip, and speeds up RPC calls significantly.\n\n#### Error Handling\n\nIf 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).\n\n**Example:** Check which RPC calls failed in a batch request ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-Client-BatchHandleError))\n```go\nvar batchErr w3.CallErrors\nif err := client.Call(calls...); errors.As(err, \u0026batchErr) {\n    // handle call errors\n} else if err != nil {\n    // handle other errors\n}\n```\n\n#### Learn More\n* List of supported [**RPC methods**](#rpc-methods)\n* Learn how to create [**custom RPC method bindings**](#custom-rpc-method-bindings)\n\n### VM\n\n[`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.\n\n**Example:** Simulate an Uniswap v3 swap ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3vm#example-VM-UniswapV3Swap))\n\n```go\n// 1. Create a VM that forks the Mainnet state from the latest block,\n// disables the base fee, and has a fake WETH balance and approval for the router\nvm, err := w3vm.New(\n    w3vm.WithFork(client, nil),\n    w3vm.WithNoBaseFee(),\n    w3vm.WithState(w3types.State{\n        addrWETH: {Storage: w3types.Storage{\n            w3vm.WETHBalanceSlot(addrEOA):               common.BigToHash(w3.I(\"1 ether\")),\n            w3vm.WETHAllowanceSlot(addrEOA, addrRouter): common.BigToHash(w3.I(\"1 ether\")),\n        }},\n    }),\n)\nif err != nil {\n    // handle error\n}\n\n// 2. Simulate a Uniswap v3 swap\nreceipt, err := vm.Apply(\u0026w3types.Message{\n    From: addrEOA,\n    To:   \u0026addrRouter,\n    Func: funcExactInput,\n    Args: []any{\u0026ExactInputParams{\n        Path:             encodePath(addrWETH, 500, addrUNI),\n        Recipient:        addrEOA,\n        Deadline:         big.NewInt(time.Now().Unix()),\n        AmountIn:         w3.I(\"1 ether\"),\n        AmountOutMinimum: w3.Big0,\n    }},\n})\nif err != nil {\n    // handle error\n}\n\n// 3. Decode output amount\nvar amountOut *big.Int\nif err := receipt.DecodeReturns(\u0026amountOut); err != nil {\n    // handle error\n}\n```\n\n### ABI Bindings\n\nABI bindings in `w3` are specified for individual functions using Solidity syntax and are usable for any contract that supports that function.\n\n**Example:** ABI binding for the ERC20 `balanceOf` function ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-NewFunc-BalanceOf))\n\n```go\nfuncBalanceOf := w3.MustNewFunc(\"balanceOf(address)\", \"uint256\")\n```\n\n**Example:** ABI binding for the Uniswap v4 `swap` function ([Playground](https://pkg.go.dev/github.com/lmittmann/w3#example-NewFunc-UniswapV4Swap))\n\n```go\nfuncSwap := w3.MustNewFunc(`swap(\n    (address currency0, address currency1, uint24 fee, int24 tickSpacing, address hooks) key,\n    (bool zeroForOne, int256 amountSpecified, uint160 sqrtPriceLimitX96) params,\n    bytes hookData\n)`, \"int256 delta\")\n```\n\nA [`Func`](https://pkg.go.dev/github.com/lmittmann/w3#Func) can be used to\n\n* encode arguments to the contracts input data ([`Func.EncodeArgs`](https://pkg.go.dev/github.com/lmittmann/w3#Func.EncodeArgs)),\n* decode arguments from the contracts input data ([`Func.DecodeArgs`](https://pkg.go.dev/github.com/lmittmann/w3#Func.DecodeArgs)), and\n* decode returns from the contracts output data ([`Func.DecodeReturns`](https://pkg.go.dev/github.com/lmittmann/w3#Func.DecodeReturns)).\n\n### Utils\n\nStatic addresses, hashes, bytes or integers can be parsed from (hex-)strings with the following utility functions that panic if the string is not valid.\n\n```go\naddr := w3.A(\"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\")\nhash := w3.H(\"0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3\")\nbytes := w3.B(\"0x27c5342c\")\namount := w3.I(\"12.34 ether\")\n```\n\nUse [go-ethereum/common](https://pkg.go.dev/github.com/ethereum/go-ethereum/common) to parse strings that may not be valid instead.\n\n\n## RPC Methods\n\nList of supported RPC methods for [`w3.Client`](https://pkg.go.dev/github.com/lmittmann/w3#Client).\n\n### [`eth`](https://pkg.go.dev/github.com/lmittmann/w3/module/eth)\n\n| Method                                    | Go Code\n| :---------------------------------------- | :-------\n| `eth_blockNumber`                         | `eth.BlockNumber().Returns(blockNumber **big.Int)`\n| `eth_call`                                | `eth.Call(msg *w3types.Message, blockNumber *big.Int, overrides w3types.State).Returns(output *[]byte)`\u003cbr\u003e`eth.CallFunc(contract common.Address, f w3types.Func, args ...any).Returns(returns ...any)`\n| `eth_chainId`                             | `eth.ChainID().Returns(chainID *uint64)`\n| `eth_createAccessList`                    | `eth.AccessList(msg *w3types.Message, blockNumber *big.Int).Returns(resp **eth.AccessListResponse)`\n| `eth_estimateGas`                         | `eth.EstimateGas(msg *w3types.Message, blockNumber *big.Int).Returns(gas *uint64)`\n| `eth_gasPrice`                            | `eth.GasPrice().Returns(gasPrice **big.Int)`\n| `eth_maxPriorityFeePerGas`                | `eth.GasTipCap().Returns(gasTipCap **big.Int)`\n| `eth_getBalance`                          | `eth.Balance(addr common.Address, blockNumber *big.Int).Returns(balance **big.Int)`\n| `eth_getBlockByHash`                      | `eth.BlockByHash(hash common.Hash).Returns(block *types.Block)`\u003cbr\u003e`eth.HeaderByHash(hash common.Hash).Returns(header **types.Header)`\n| `eth_getBlockByNumber`                    | `eth.BlockByNumber(number *big.Int).Returns(block *types.Block)`\u003cbr\u003e`eth.HeaderByNumber(number *big.Int).Returns(header **types.Header)`\n| `eth_getBlockReceipts`                    | `eth.BlockReceipts(blockNumber *big.Int).Returns(receipts *types.Receipts)`\n| `eth_getBlockTransactionCountByHash`      | `eth.BlockTxCountByHash(hash common.Hash).Returns(count *uint)`\n| `eth_getBlockTransactionCountByNumber`    | `eth.BlockTxCountByNumber(number *big.Int).Returns(count *uint)`\n| `eth_getCode`                             | `eth.Code(addr common.Address, blockNumber *big.Int).Returns(code *[]byte)`\n| `eth_getLogs`                             | `eth.Logs(q ethereum.FilterQuery).Returns(logs *[]types.Log)`\n| `eth_getStorageAt`                        | `eth.StorageAt(addr common.Address, slot common.Hash, blockNumber *big.Int).Returns(storage *common.Hash)`\n| `eth_getTransactionByHash`                | `eth.Tx(hash common.Hash).Returns(tx **types.Transaction)`\n| `eth_getTransactionByBlockHashAndIndex`   | `eth.TxByBlockHashAndIndex(blockHash common.Hash, index uint).Returns(tx **types.Transaction)`\n| `eth_getTransactionByBlockNumberAndIndex` | `eth.TxByBlockNumberAndIndex(blockNumber *big.Int, index uint).Returns(tx **types.Transaction)`\n| `eth_getTransactionCount`                 | `eth.Nonce(addr common.Address, blockNumber *big.Int).Returns(nonce *uint)`\n| `eth_getTransactionReceipt`               | `eth.TxReceipt(txHash common.Hash).Returns(receipt **types.Receipt)`\n| `eth_sendRawTransaction`                  | `eth.SendRawTx(rawTx []byte).Returns(hash *common.Hash)`\u003cbr\u003e`eth.SendTx(tx *types.Transaction).Returns(hash *common.Hash)`\n| `eth_getUncleByBlockHashAndIndex`         | `eth.UncleByBlockHashAndIndex(hash common.Hash, index uint).Returns(uncle **types.Header)`\n| `eth_getUncleByBlockNumberAndIndex`       | `eth.UncleByBlockNumberAndIndex(number *big.Int, index uint).Returns(uncle **types.Header)`\n| `eth_getUncleCountByBlockHash`            | `eth.UncleCountByBlockHash(hash common.Hash).Returns(count *uint)`\n| `eth_getUncleCountByBlockNumber`          | `eth.UncleCountByBlockNumber(number *big.Int).Returns(count *uint)`\n| `eth_syncing`                             | `eth.Syncing().Returns(syncing *bool)`\n\n### [`debug`](https://pkg.go.dev/github.com/lmittmann/w3/module/debug)\n\n| Method                   | Go Code\n| :----------------------- | :-------\n| `debug_traceCall`        | `debug.TraceCall(msg *w3types.Message, blockNumber *big.Int, config *debug.TraceConfig).Returns(trace **debug.Trace)`\u003cbr\u003e`debug.CallTraceCall(msg *w3types.Message, blockNumber *big.Int, overrides w3types.State).Returns(trace **debug.CallTrace)`\n| `debug_traceTransaction` | `debug.TraceTx(txHash common.Hash, config *debug.TraceConfig).Returns(trace **debug.Trace)`\u003cbr\u003e`debug.CallTraceTx(txHash common.Hash, overrides w3types.State).Returns(trace **debug.CallTrace)`\n\n### [`txpool`](https://pkg.go.dev/github.com/lmittmann/w3/module/txpool)\n\n| Method               | Go Code\n| :--------------------| :-------\n| `txpool_content`     | `txpool.Content().Returns(resp **txpool.ContentResponse)`\n| `txpool_contentFrom` | `txpool.ContentFrom(addr common.Address).Returns(resp **txpool.ContentFromResponse)`\n| `txpool_status`      | `txpool.Status().Returns(resp **txpool.StatusResponse)`\n\n### [`admin`](https://pkg.go.dev/github.com/lmittmann/w3/module/admin)\n\n| Method                    | Go Code\n| :------------------------ | :-------\n| `admin_addPeer`           | `admin.AddPeer(url *enode.Node).Returns(resp *bool)`\n| `admin_removePeer`        | `admin.RemovePeer(url *enode.Node).Returns(resp *bool)`\n| `admin_addTrustedPeer`    | `admin.AddTrustedPeer(url *enode.Node).Returns(resp *bool)`\n| `admin_removeTrustedPeer` | `admin.RemoveTrustedPeer(url *enode.Node).Returns(resp *bool)`\n| `admin_nodeInfo`          | `admin.NodeInfo().Returns(resp **admin.NodeInfoResponse)`\n\n### [`net`](https://pkg.go.dev/github.com/lmittmann/w3/module/net)\n\n| Method               | Go Code\n| :------------------- | :-------\n| `net_listening`     | `net.Listening().Returns(resp *bool)`\n| `net_peerCount`     | `net.PeerCount().Returns(resp *int)`\n| `net_version`       | `net.Version().Returns(resp *int)`\n\n### [`web3`](https://pkg.go.dev/github.com/lmittmann/w3/module/web3)\n\n| Method               | Go Code\n| :------------------- | :-------\n| `web3_clientVersion` | `web3.ClientVersion().Returns(clientVersion *string)`\n\n### Third Party RPC Method Packages\n\n| Package                                                                  | Description\n| :----------------------------------------------------------------------- | :-----------\n| [github.com/lmittmann/flashbots](https://github.com/lmittmann/flashbots) | Package `flashbots` implements RPC API bindings for the Flashbots relay and mev-geth.\n\n\n## Custom RPC Method Bindings\n\nCustom RPC method bindings can be created by implementing the [`w3types.RPCCaller`](https://pkg.go.dev/github.com/lmittmann/w3/w3types#RPCCaller) interface.\n\n**Example:** RPC binding for the Otterscan `ots_getTransactionBySenderAndNonce` method ([Playground](https://pkg.go.dev/github.com/lmittmann/w3/w3types#example-RPCCaller-GetTransactionBySenderAndNonce))\n\n```go\n// TxBySenderAndNonceFactory requests the senders transaction hash by the nonce.\nfunc TxBySenderAndNonceFactory(sender common.Address, nonce uint64) w3types.RPCCallerFactory[common.Hash] {\n    return \u0026getTransactionBySenderAndNonceFactory{\n        sender: sender,\n        nonce:  nonce,\n    }\n}\n\n// getTransactionBySenderAndNonceFactory implements the w3types.RPCCaller and\n// w3types.RPCCallerFactory interfaces. It stores the method parameters and\n// the reference to the return value.\ntype getTransactionBySenderAndNonceFactory struct {\n    // params\n    sender common.Address\n    nonce  uint64\n\n    // returns\n    returns *common.Hash\n}\n\n// Returns sets the reference to the return value.\nfunc (f *getTransactionBySenderAndNonceFactory) Returns(txHash *common.Hash) w3types.RPCCaller {\n    f.returns = txHash\n    return f\n}\n\n// CreateRequest creates a batch request element for the Otterscan getTransactionBySenderAndNonce method.\nfunc (f *getTransactionBySenderAndNonceFactory) CreateRequest() (rpc.BatchElem, error) {\n    return rpc.BatchElem{\n        Method: \"ots_getTransactionBySenderAndNonce\",\n        Args:   []any{f.sender, f.nonce},\n        Result: f.returns,\n    }, nil\n}\n\n// HandleResponse handles the response of the Otterscan getTransactionBySenderAndNonce method.\nfunc (f *getTransactionBySenderAndNonceFactory) HandleResponse(elem rpc.BatchElem) error {\n    if err := elem.Error; err != nil {\n        return err\n    }\n    return nil\n}\n```\n\n## Sponsors\n\n\u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/public/assets/ef-logo-dark.svg\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/public/assets/ef-logo.svg\"\u003e\n    \u003cimg src=\"docs/public/assets/ef-logo.svg\" alt=\"ef logo\" width=\"256\" height=\"auto\"\u003e\n\u003c/picture\u003e\n","funding_links":[],"categories":["Go"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flmittmann%2Fw3","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flmittmann%2Fw3","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flmittmann%2Fw3/lists"}