diff --git a/docs/_dapp/native.md b/docs/_dapp/native.md index f248fc7522..34d9816d97 100644 --- a/docs/_dapp/native.md +++ b/docs/_dapp/native.md @@ -3,64 +3,247 @@ title: Go API sort_key: C --- -The Ethereum blockchain along with its two extension protocols Whisper and Swarm was -originally conceptualized to become the supporting pillar of web3, providing the -consensus, messaging and storage backbone for a new generation of distributed (actually, -decentralized) applications called DApps. +Ethereum was originally conceptualized to be the base layer for [Web3][web3-link], providing +the backbone for a new generation of decentralized, permissionless and censorship resistant +applications called [dapps][dapp-link]. The first step towards this vision was the development +of clients providing an RPC interface into the peer-to-peer protocols. This allowed users to +transact between accounts and interact with smart contracts using command line tools. +Geth was one of the original clients to provide this type of gateway to the Ethereum network. -The first incarnation towards this dream of web3 was a command line client providing an -RPC interface into the peer-to-peer protocols. The client was soon enough extended with a -web-browser-like graphical user interface, permitting developers to write DApps based on -the tried and proven HTML/CSS/JS technologies. +Before long, web-browser-like graphical interfaces (e.g. Mist) were created to extend clients, and +client functions were built into websites built using the time-tested HTML/CSS/JS stack. +However, to support the most diverse, complex dapps, developers require programmatic access to client +functions through an API. This opens up client technologies as re-usable, composable units that +can be applied in creative ways by a global community of developers. -As many DApps have more complex requirements than what a browser environment can handle, -it became apparent that providing programmatic access to the web3 pillars would open the -door towards a new class of applications. As such, the second incarnation of the web3 -dream is to open up all our technologies for other projects as reusable components. +To support this, Geth ships official Go packages that can be embedded into third party +desktop and server applications. There is also a [mobile API](/docs/dapp/mobile) that can be +used to embed Geth into mobile applications. -Starting with the 1.5 release family of `go-ethereum`, we transitioned away from providing -only a full blown Ethereum client and started shipping official Go packages that could be -embedded into third party desktop and server applications. +This page provides a high-level overview of the Go API. -*Note, this guide will assume you are familiar with Go development. It will make no -attempts to cover general topics about Go project layouts, import paths or any other -standard methodologies. If you are new to Go, consider reading its [getting started guides][go-guide] first.* +*Note, this guide will assume some familiarity with Go development. It does not cover general topics +about Go project layouts, import paths or any other standard methodologies. If you are new to Go, +consider reading [Getting Started with Go][go-guide] first.* -## Quick overview +## Overview -Our reusable Go libraries focus on four main usage areas: +Geth's reusable Go libraries focus on three main usage areas: - Simplified client side account management - Remote node interfacing via different transports - Contract interactions through auto-generated bindings -- In-process Ethereum, Whisper and Swarm peer-to-peer node -You can watch a quick overview about these in Peter's (@karalabe) talk titled "Import -Geth: Ethereum from Go and beyond", presented at the Ethereum Devcon2 developer conference -in September, 2016 (Shanghai). Slides are [available here][peter-slides]. +The libraries are updated synchronously with the Geth Github repository. +The Go libraries can be viewed in full at [Go Packages][go-pkg-link]. -[![Peter's Devcon2 talk](https://img.youtube.com/vi/R0Ia1U9Gxjg/0.jpg)](https://www.youtube.com/watch?v=R0Ia1U9Gxjg) +Péter Szilágyi (@karalabe) gave a high level overview of the Go libraries in +a talk at DevCon2 in Shanghai in 2016. The slides are still a useful resource +([available here][peter-slides]) and the talk itself can be viewed by clicking +the image below (it is also archived on [IPFS][ipfs-link]). + +[![Peter's Devcon2 talk](/static/images/devcon2_labelled.webp)](https://www.youtube.com/watch?v=R0Ia1U9Gxjg) ## Go packages -The `go-ethereum` library is distributed as a collection of standard Go packages straight -from our GitHub repository. The packages can be used directly via the official Go toolkit, -without needing any third party tools. External dependencies are vendored locally into -`vendor`, ensuring both self-containment as well as code stability. If you reuse -`go-ethereum` in your own project, please follow these best practices and vendor it -yourself too to avoid any accidental API breakages! +The `go-ethereum` library is distributed as a collection of standard Go packages straight from go-ethereum's +GitHub repository. The packages can be used directly via the official Go toolkit, without needing any +third party tools. -The canonical import path for `go-ethereum` is `github.com/ethereum/go-ethereum`, with all -packages residing underneath. Although there are [quite a number][go-ethereum-dir] of -them, you'll only need to care about a limited subset, each of which will be properly -introduced in their relevant section. +The canonical import path for Geth is `github.com/ethereum/go-ethereum`, with all packages residing +underneath. Although there are [lots of them][go-ethereum-dir] most developers will only care about +a limited subset. -You can download all our packages via: +All the Geth packages can be downloaded using: ``` $ go get -d github.com/ethereum/go-ethereum/... ``` +More Go API support for dapp developers can be found on the [Go Contract Bindings](/docs/dapp/native-bindings) +and [Go Account Management](/docs/dapp/native-accounts) pages. + + +## Tutorial + +This section includes some basic usage examples for the `ethclient` and `gethclient` packages available as +part of the Go API. The `ethclient` package provides a client that implements the full Ethereum JSON-RPC API, +whereas `gethclient` offers the Geth-specific API. + +### Instantiating a client + +The client is an instance of the `Client` struct which has associated functions that wrap requests to the Ethereum +or Geth RPC API endpoints. + +A client is instantiated by passing a raw url or path to an ipc file to the client's `Dial` function. In the following +code snippet the path to the ipc file for a local Geth node is provided to `ethclient.Dial()`. + +```go +// create instance of ethclient and assign to cl +cl, err := ethclient.Dial("/tmp/geth.ipc") +if err != nil { + panic(err) +} +_ = cl +``` + +### Interacting with the client + +The client can now be used to handle requests to the Geth node using the full JSON-RPC API. For example, the function +`BlockNumer()` wraps a call to the `eth_blockNumber` endpoint. The function `SendTransaction` wraps a call to +`eth_sendTransaction`. The full list of client methods can be found [here][ethclient-pkg]. + +Frequently, the functions take an instance of the `Context` type as their leading argument. This defines context about requests sent from the application such as deadlines, cancellation signals etc. More information on this can +be found in the [Go documentation](https://pkg.go.dev/golang.org/x/net/context). An empty context instance can be +created using `Context.Background()`. + +### Querying client for data + +A simple starting point is to fetch the chain ID from the client. This e.g. is needed when signing a transaction as is to be seen in the next section. + +```go +chainid, err := cl.ChainID(context.Background()) +if err != nil { + return err +} +``` + +Unlike `ChainID`, many functions require arguments other than context. The Go API takes in and returns high-level types which are used in Geth internals as well to simplify programming and remove the need for knowing how data needs to be formatted exactly as per the JSON-RPC API spec. For example to find out the nonce for an account at a given block the address needs to be provided as a `common.Address` type and the block number as a `*big.Int`: + +```go +addr := common.HexToAddress("0xb02A2EdA1b317FBd16760128836B0Ac59B560e9D") +nonce, err := cl.NonceAt(context.Background(), addr, big.NewInt(14000000)) +``` + +### Querying past events + +Contracts emit events during execution which can be queried from the client. The parameters for the event one is interested in have to be filled out in the `ethereum.FilterQuery` object. This includes which event topics are of interested, from which contracts and during which range of blocks. The example below queries `Transfer` events of all ERC-20 tokens for the last 10 blocks: + +```go +blockNum, err := cl.BlockNumber(context.Background()) +if err != nil { + return err +} +q := ethereum.FilterQuery{ + FromBlock: new(big.Int).Sub(blockNum, big.NewInt(10)), + ToBlock: blockNum, + Topics: [][]common.Hash{common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef")}, +} +logs, err := cl.FilterLogs(context.Background(), q) +if err != nil { + return err +} +``` + +### Sending a transaction + +Sending a transaction is achieved using the `SendTransaction()` function. `SendTransaction` takes an instance of +`context.Context` as its leading argument and a signed transaction as its second argument. The signed transaction +must be generated in advance. Building the signed transaction is a multi-stage +process that requires first generating a key pair if none exists already, retrieving some chain data and defining sender and recipient +addresses. Then these data can be collected into a transaction object and signed. The resulting signed transaction +can then be passed to `SendTransaction`. + +The example below assumes the following key pair has already been generated: + +```go +// SK and ADDR are the secret key and sender address +SK = "0xaf5ead4413ff4b78bc94191a2926ae9ccbec86ce099d65aaf469e9eb1a0fa87f" +ADDR = "0x6177843db3138ae69679A54b95cf345ED759450d" +``` + +The secret key and address can be used to send a transaction. In the example below 1 ETH is sent from the +address `ADDR` to an arbitrary recipient. + +```go +import ( + "context" + "math/big" + + "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" +) + +// sendTransaction sends a transaction with 1 ETH to a specified address. +func sendTransaction(cl *ethclient.Client) error { + var ( + sk = crypto.ToECDSAUnsafe(common.FromHex(SK)) + to = common.HexToAddress("0xb02A2EdA1b317FBd16760128836B0Ac59B560e9D") + value = new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether)) + sender = common.HexToAddress(ADDR) + gasLimit = uint64(21000) + ) + // Retrieve the chainid (needed for signer) + chainid, err := cl.ChainID(context.Background()) + if err != nil { + return err + } + // Retrieve the pending nonce + nonce, err := cl.PendingNonceAt(context.Background(), sender) + if err != nil { + return err + } + // Get suggested gas price + tipCap, _ := cl.SuggestGasTipCap(context.Background()) + feeCap, _ := cl.SuggestGasPrice(context.Background()) + // Create a new transaction + tx := types.NewTx( + &types.DynamicFeeTx{ + ChainID: chainid, + Nonce: nonce, + GasTipCap: tipCap, + GasFeeCap: feeCap, + Gas: gasLimit, + To: &to, + Value: value, + Data: nil, + }) + // Sign the transaction using our keys + signedTx, _ := types.SignTx(tx, types.NewLondonSigner(chainid), sk) + // Send the transaction to our node + return cl.SendTransaction(context.Background(), signedTx) +} +``` + +### gethclient + +An instance of `gethclient` can be used in exactly the same way as `ethclient`. However, `gethclient` +includes Geth-specific API methods. These additional methods are: + +```shell +CallContract() +CreatAccessList() +GCStats() +GetNodeInfo() +GetProof() +MemStats() +SetHead() +SubscribePendingTransactions() +``` +*Note that both `ethclient` and `gethclient` have a `CallContract()` function - the difference is that +the `gethclient` version includes an `overrides` argument.* + +Details relating to these endpoints can be found at [pkg.go.dev][go-api-docs] or the Geth [Github][ethclient-link]. +The code snippets in this tutorial were adapted from a more more in-depth set of examples available on +[Github][web3go-link]. + + +## Summary + +There are a wide variety of Go APIs available for dapp developers that abstract away the complexity of interacting with Ethereum +using a set of composable, reusable functions provided by Geth. + [go-guide]: https://github.com/golang/go/wiki#getting-started-with-go [peter-slides]: https://ethereum.karalabe.com/talks/2016-devcon.html [go-ethereum-dir]: https://pkg.go.dev/github.com/ethereum/go-ethereum/#section-directories +[ethclient-pkg]:https://pkg.go.dev/github.com/ethereum/go-ethereum/ethclient#Client +[go-pkg-link]: https://pkg.go.dev/github.com/ethereum/go-ethereum#section-directories +[ipfs-link]: https://ipfs.io/ipfs/QmQRuKPKWWJAamrMqAp9rytX6Q4NvcXUKkhvu3kuREKqXR +[dapp-link]: https://ethereum.org/en/glossary/#dapp +[web3-link]: https://ethereum.org/en/web3/ +[ethclient-link]: https://github.com/ethereum/go-ethereum/tree/master/ethclient +[go-api-docs]:https://pkg.go.dev/github.com/ethereum/go-ethereum@v1.10.19/ethclient/gethclient +[web3go-link]:https://github.com/MariusVanDerWijden/web3go diff --git a/static/images/devcon2_labelled.webp b/static/images/devcon2_labelled.webp new file mode 100644 index 0000000000..321326e64a Binary files /dev/null and b/static/images/devcon2_labelled.webp differ