erigon-pulse/docs/readthedocs/source/rpc/tutorial.rst
Evgeny Danilenko 74847d77e6
Rename to Erigon (#2018)
* turbo-geth to erigon

* tg, turbo to erigon
2021-05-26 11:35:39 +01:00

119 lines
4.2 KiB
ReStructuredText

Tutorial: Build a personalized daemon
=====================================
For the following tutorial, we will make references to https://github.com/Giulio2002/hello-tg-daemon.
We are going to build our daemon using golang and Erigon packages, so first of all we are going to create a file in which we are going to store our API methods and informations. (`api.go`).
our daemon will only contain one method: `myNamespace_getBlockNumberByHash` which will return the block number associated to certain hash.
.. code-block:: go
package main
import (
"context"
"github.com/ledgerwatch/erigon/common"
"github.com/ledgerwatch/erigon/core/rawdb"
"github.com/ledgerwatch/erigon/ethdb"
)
// API - implementation of ExampleApi
type API struct {
kv ethdb.RwKV
db ethdb.Getter
}
type ExampleAPI interface {
GetBlockNumberByHash(ctx context.Context, hash common.Hash) (uint64, error)
}
func NewAPI(kv ethdb.RwKV, db ethdb.Getter) *API {
return &API{kv: kv, db: db}
}
func (api *API) GetBlockNumberByHash(ctx context.Context, hash common.Hash) (uint64, error) {
return rawdb.ReadBlockByHash(api.db, hash).NumberU64(), nil
}
The type `Api` is the type that is going to contain the methods for our custom daemon. This type has two members: `kv` and `db` which are objects used to interact with the Erigon node remotely. they behave like normal db objects and can be used alongside with the rawdb package.
In our example we are making an rpcdaemon call that by receiving a certain block hash, it give the block number associated as an output. this is all done in `GetBlockNumberByHash`.
Now we are going to make our `main.go` where we are going to serve the api we made in `api.go`.
.. code-block:: go
package main
import (
"context"
"os"
"github.com/ledgerwatch/erigon/cmd/rpcdaemon/cli"
"github.com/ledgerwatch/erigon/cmd/rpcdaemon/commands"
"github.com/ledgerwatch/erigon/cmd/utils"
"github.com/ledgerwatch/erigon/common"
"github.com/ledgerwatch/erigon/ethdb"
"github.com/ledgerwatch/erigon/log"
"github.com/ledgerwatch/erigon/rpc"
"github.com/spf13/cobra"
)
func main() {
cmd, cfg := cli.RootCommand()
cmd.RunE = func(cmd *cobra.Command, args []string) error {
db, backend, err := cli.OpenDB(*cfg)
if err != nil {
log.Error("Could not connect to remoteDb", "error", err)
return nil
}
apiList := APIList(db, backend, cfg)
return cli.StartRpcServer(cmd.Context(), *cfg, apiList)
}
if err := cmd.ExecuteContext(utils.RootContext()); err != nil {
log.Error(err.Error())
os.Exit(1)
}
}
func APIList(kv ethdb.RwKV, eth ethdb.Backend, cfg *cli.Flags) []rpc.API {
dbReader := ethdb.NewObjectDatabase(kv)
api := NewAPI(kv, dbReader)
customAPIList := []rpc.API{
{
Namespace: "myNamespace",
Public: true,
Service: ExampleAPI(api),
Version: "1.0",
},
}
// Add default Erigon api's
return commands.APIList(kv, eth, *cfg, customAPIList)
}
In the main we are just running our rpcdaemon as we defined it in `APIList`, in fact in `APIList` we are configuring our custom rpcdaemon to serve the ExampleAPI's mathods on namespace `myNamespace` meaning that in order to call GetBlockNumberByHash via json rpc we have to call method `myNamespace_getBlockNumberByHash`.
Let's now try it:
.. code-block:: sh
$ go build
$ ./hello-tg-daemon --http.api=myNamespace # the flag enables our namespace.
**Note: Remember to run Erigon with --private.api.addr=localhost:9090**
now it should be all set and we can test it with:
.. code-block:: sh
curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"myNamespace_getBlockNumberByHash","params":["ANYHASH"],"id":1}' localhost:8545
another example of custom daemon can be found at https://github.com/torquem-ch/project-1/blob/master/api.go.
Happy Building ~~~.