{"id":18542780,"url":"https://github.com/coinbase/chainnode","last_synced_at":"2025-04-09T18:32:15.695Z","repository":{"id":187779496,"uuid":"673492979","full_name":"coinbase/chainnode","owner":"coinbase","description":null,"archived":false,"fork":false,"pushed_at":"2023-12-08T22:38:03.000Z","size":1074,"stargazers_count":13,"open_issues_count":3,"forks_count":7,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-24T10:38:48.345Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coinbase.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-01T18:48:16.000Z","updated_at":"2024-11-23T12:55:17.000Z","dependencies_parsed_at":null,"dependency_job_id":"99087c84-8cd3-4b8a-b535-20a4b78c9507","html_url":"https://github.com/coinbase/chainnode","commit_stats":null,"previous_names":["coinbase/chainnode"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coinbase%2Fchainnode","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coinbase%2Fchainnode/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coinbase%2Fchainnode/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coinbase%2Fchainnode/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coinbase","download_url":"https://codeload.github.com/coinbase/chainnode/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248087871,"owners_count":21045604,"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":[],"created_at":"2024-11-06T20:10:38.766Z","updated_at":"2025-04-09T18:32:10.674Z","avatar_url":"https://github.com/coinbase.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [Overview](#overview)\n- [Quick Start](#quick-start)\n- [Configuration](#configuration)\n  - [Environment Variables](#environment-variables)\n  - [Endpoint Group](#endpoint-group)\n  - [Overriding the Configuration](#overriding-the-configuration)\n- [Testing](#testing)\n  - [Unit Test](#unit-test)\n  - [Integration Test](#integration-test)\n  - [Functional Test](#functional-test)\n    - [Run Functional Test Locally](#run-functional-test-locally)\n- [Local Development](#local-development)\n  - [Running Server](#running-server)\n  - [Manage workflow locally](#manage-workflow-locally)\n- [Storage](#storage)\n- [API](#api)\n  - [DNS](#dns)\n  - [API Documentation](#api-documentation)\n  - [Eth namespace](#eth-namespace)\n  - [Debug namespace](#debug-namespace)\n  - [Net namespace](#net-namespace)\n  - [Web3 namespace](#web3-namespace)\n  - [Batch Request](#batch-request)\n  - [Bor namespace (only for **Polygon**)](#bor-namespace-only-for-polygon)\n  - [GraphQL](#graphql)\n  - [Connect to Geth JavaScript Console](#connect-to-geth-javascript-console)\n- [TAG Generator for Proxy Methods](#tag-generator-for-proxy-methods)\n  - [TAG Usage:](#tag-usage)\n  - [Changing TAG's generated code format:](#changing-tags-generated-code-format)\n  - [Updating TAG's Unit Test:](#updating-tags-unit-test)\n- [JSONRPC Server Batch Request Limit](#jsonrpc-server-batch-request-limit)\n  - [Default Limit](#default-limit)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n## Overview\nChainNode is a highly available and scalable Node as a Service (NaaS) built on top of [ChainStorage](https://github.com/coinbase/chainstorage). Under the hooks, the on-chain data is backed by a fast key-value store, and most of the queries are served directly by the key-value store. The data is continuously replicated from ChainStorage (which in turn synchronizes the changes from a small node cluster), and re-indexed for various query patterns.\n\n## Quick Start\n\nMake sure your local go version is 1.18 by running the following commands:\n```shell\nbrew install go@1.18\nbrew unlink go\nbrew link go@1.18\n```\n\nTo set up for the first time (only done once):\n```shell\nmake bootstrap\n```\n\nRebuild everything:\n```shell\nmake build\n```\n\n## Configuration\n\n### Environment Variables\n\nChainNode depends on the following environment variables to resolve the path of the configuration.\nThe directory structure is as follows: `config/{namespace}/{blockchain}/{network}/{environment}.yml`.\n\n- `CHAINNODE_NAMESPACE`:\n  A `{namespace}` is logical grouping of several services, each of which manages its own blockchain and network. The\n  default namespace is [chainnode](/config/chainnode).\n  To deploy a different namespace, set the env var to the name of a subdirectory of [./config](/config).\n- `CHAINNODE_CONFIG`:\n  This env var, in the format of `{blockchain}-{network}`, determines the blockchain and network managed by the service.\n  The naming is defined\n  in [c3/common](/protos/coinbase/c3/common/common.proto).\n- `CHAINNODE_ENVIRONMENT`:\n  This env var controls the `{environment}` in which the service is deployed. Possible values include `production`\n  , `development`, and `local` (which is also the default value).\n\n### Endpoint Group\n\nEndpoint group is an abstraction for one or more JSON-RPC endpoints.\n[EndpointProvider](internal/clients/blockchain/endpoints/endpoint_provider.go) uses the `endpoint_group` config to implement\nclient-side routing to the node provider.\n\nChainNode utilizes two endpoint groups to serve its needs to the node provider:\n* primary: This endpoint group is used to proxy the requests from the downstream node providers. Certain APIs, such as eth_call \n  and eth_getBalance, cannot be fulfilled by the storage layer, because the data is not available in ChainNode data source ChainStorage.\n  To handle such requests, ChainNode redirect the request to this primary endpoint provider instead.\n* validator: This endpoint group is used for validation purpose. For a percentage of incoming requests to ChainNode, the validation\n  is performed by comparing the response from ChainNode and the response from this validator endpoint provider for an identical request.\n\nIf your node provider, e.g. QuickNode, already has built-in load balancing, your endpoint group may contain only one\nendpoint, as illustrated by the following configuration:\n```yaml\nchain:\n  client:\n    primary:\n      endpoint_group: |\n        {\n          \"endpoints\": [\n            {\n              \"name\": \"quicknode-foo-bar-sticky\",\n              \"url\": \"https://foo-bar.matic.quiknode.pro/****\",\n              \"weight\": 1\n            }\n          ]\n        }\n    validator:\n      endpoint_group: |\n        {\n          \"endpoints\": [\n            {\n              \"name\": \"quicknode-foo-bar-round-robin\",\n              \"url\": \"https://foo-bar.matic.quiknode.pro/****\",\n              \"weight\": 1\n            }\n          ]\n        }\n```\n\n### Overriding the Configuration\n\nYou may override any configuration using an environment variable. The environment variable should be prefixed with\n\"CHAINNODE_\". For nested dictionary, use underscore to separate the keys.\n\nFor example, you may override the endpoint group config at runtime by injecting the following environment variables:\n* primary: CHAINNODE_CHAIN_CLIENT_PRIMARY_ENDPOINT_GROUP\n* validator: CHAINNODE_CHAIN_CLIENT_VALIDATOR_ENDPOINT_GROUP\n\nAlternatively, you may override the configuration by creating `secrets.yml` within the same directory. Its attributes\nwill be merged into the runtime configuration and take the highest precedence. Note that this file may contain\ncredentials and is excluded from check-in by `.gitignore`.\n\n## Testing\n### Unit Test\n```shell\n# Run everything\nmake test\n\n# Run the controller package only\nmake test TARGET=internal/controller/...\n```\n\n### Integration Test\n```shell\n# Run everything\nmake integration\n\n# Run the workflow package only\nmake integration TARGET=internal/workflow/...\n\n# Run TestIntegrationBlobByHashStorageTestSuite only\nmake integration TARGET=internal/storage/... TEST_FILTER=TestIntegrationBlobByHashStorageTestSuite\n```\n\n### Functional Test\n#### Run Functional Test Locally\n```shell\n# Run everything\nmake functional\n\n# Run ControllerTestSuite only\nmake functional TARGET=internal/controller/... TEST_FILTER=ControllerTestSuite\n\n# Run one test in ControllerTestSuite\nmake functional TARGET=internal/controller/... TEST_FILTER=ControllerTestSuite/TestBlocksByHash\n```\n\n## Local Development\n### Running Server\n\nStart the dockers by the docker-compose file from project root folder:\n```shell\nmake localstack\n```\n\nThe next step is to start the server locally in a new terminal:\n```shell\n# Ethereum Mainnet\n# Use aws local stack\n# Starts API server\nmake server\n\n# Setup ChainStorage SDK credentials:\nexport CHAINSTORAGE_SDK_AUTH_HEADER=cb-nft-api-token\nexport CHAINSTORAGE_SDK_AUTH_TOKEN=****\n\n# Starts workflow workers\nmake worker\n\n# If want to start testnet (goerli) server\n# Use aws local stack\nmake server CHAINNODE_CONFIG_NAME=ethereum-goerli\nmake worker CHAINNODE_CONFIG_NAME=ethereum-goerli\n```\n\n### Manage workflow locally\nAfter finishing running server and worker, manage workflows using admin CLI:\n\n```shell\n# start coordinator locally\ngo run ./cmd/admin workflow start --workflow coordinator  --input '{}' --blockchain ethereum --env local --network mainnet\n\n# stop coordinator locally\ngo run ./cmd/admin workflow stop --workflow coordinator   --input '' --blockchain ethereum --env local --network mainnet\n\n# start an ingestor for blocks collection locally.\n# Note that if you already run coordinator locally, there is no need to start an individual ingestor.\n# This command is used when a new ingestor is being developed.\n# When local testing, please specify the desired tag inside the input struct. Example: '{\"collection\":\"blocks\", tag:1}'\ngo run ./cmd/admin workflow start --workflow ingestor --input '{\"collection\":\"blocks\"}' --blockchain ethereum --env local --network mainnet\n\n\n# stop an ingestor for blocks collection locally\ngo run ./cmd/admin workflow stop --workflow ingestor --input '{}' --blockchain ethereum --env local --network mainnet --workflowID workflow.ingestor/blocks/{tag}\n```\n\n## Storage\n\nInspect a table using AWS CLI:\n\n```shell\n# scan the entire table\naws dynamodb --no-sign-request --region local --endpoint-url http://localhost:4566 scan --table-name chainnode-collection-ethereum-mainnet --attributes-to-get \"pk\" \"sk\" \"tag\" \"height\" \"hash\"\n\n# get a specific item\naws dynamodb --no-sign-request --region local --endpoint-url http://localhost:4566 get-item --table-name chainnode-collection-ethereum-mainnet --key '{\"pk\": {\"S\": \"1#checkpoints\"}, \"sk\": {\"S\": \"blocks\"}}'\n```\n\nThe data within each dynamoDB item is compressed uzing gzip format. `base64 -d | gunzip` can be used to \nuncompress it to make it readable in the terminal. Example:\n\n```shell\n# Make data human-readable and format JSON\naws dynamodb --no-sign-request --region local --endpoint-url http://localhost:4566 get-item --table-name chainnode-collection-ethereum-mainnet --key '{\"pk\": {\"S\": \"\u003cpartition_key\u003e\"}, \"sk\": {\"S\": \"\u003csort_key\u003e\"}}' | jq -r '.Item.data.B' | base64 -d | gunzip | jq\n```\n\n## API\n\n### DNS\n- Local: `localhost:8000`\n\n### API Documentation\n[JSON-RPC API Methods](https://ethereum.org/en/developers/docs/apis/json-rpc/#json-rpc-methods)\n\n### Eth namespace\nCaveat: ChainNode only supports the following block tags: `latest`, `earliest`, and block number in hex format.\n\n```shell\n# eth_blockNumber: https://eth.wiki/json-rpc/API#eth_blocknumber\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_blockNumber\"}' | jq\n\n# eth_getBlockByNumber: https://eth.wiki/json-rpc/API#eth_getblockbynumber\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getBlockByNumber\", \"params\": [\"0xdad3c1\", false]}' | jq\n\n# eth_getBlockByNumber with proxying turned off\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -H \"x-chainnode-routing-mode: native-only\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getBlockByNumber\", \"params\": [\"pending\", false]}' | jq\n\n# eth_getBlockByHash: https://eth.wiki/json-rpc/API#eth_getblockbyhash\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getBlockByHash\", \"params\": [\"0x849a3ac8f0d81df1a645701cdb9f90e58500d2eabb80ff3b7f4e8c13f025eff2\", false]}' | jq\n\n# eth_getBlockTransactionCountByHash https://eth.wiki/json-rpc/API#eth_getblocktransactioncountbyhash\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getBlockTransactionCountByHash\", \"params\": [\"0x849a3ac8f0d81df1a645701cdb9f90e58500d2eabb80ff3b7f4e8c13f025eff2\"]}' | jq\n\n# GetBlockTransactionCountByNumber https://eth.wiki/json-rpc/API#eth_getblocktransactioncountbynumber\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getBlockTransactionCountByNumber\", \"params\": [\"0xdad3c1\"]}' | jq\n\n# eth_getTransactionByHash: https://eth.wiki/json-rpc/API#eth_gettransactionbyhash\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getTransactionByHash\", \"params\": [\"0x633982a26e0cfba940613c52b31c664fe977e05171e35f62da2426596007e249\"]}' | jq\n\n# eth_getTransactionReceipt: https://eth.wiki/json-rpc/API#eth_gettransactionreceipt\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getTransactionReceipt\", \"params\": [\"0x633982a26e0cfba940613c52b31c664fe977e05171e35f62da2426596007e249\"]}' | jq\n\n# eth_getTransactionByBlockHashAndIndex https://eth.wiki/json-rpc/API#eth_gettransactionbyblockhashandindex\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getTransactionByBlockHashAndIndex\", \"params\": [\"0x849a3ac8f0d81df1a645701cdb9f90e58500d2eabb80ff3b7f4e8c13f025eff2\", \"0x0\"]}' | jq\n\n# eth_getTransactionByBlockNumberAndIndex https://eth.wiki/json-rpc/API#eth_gettransactionbyblocknumberandindex\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getTransactionByBlockNumberAndIndex\", \"params\": [\"0xdad3c1\", \"0x0\"]}' | jq\n\n# eth_getLogs: https://eth.wiki/json-rpc/API#eth_getlogs\n# CAVEAT: eth_getLogs has a max block range limit of 1000 blocks.\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getLogs\", \"params\": [{\"fromBlock\": \"0xdad3c1\", \"toBlock\": \"0xdad3c2\"}]}' | jq\n\n# eth_call: https://eth.wiki/json-rpc/API#eth_call\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_call\", \"params\":[{ \"to\": \"0x514910771af9ca656af840dff83e8264ecf986ca\", \"data\": \"0x70a08231000000000000000000000000f27eee60abacb983251fea941dd7350280a538ba\"}, \"latest\"]}' | jq\n\n# eth_getBalance: https://eth.wiki/json-rpc/API#eth_getbalance\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getBalance\", \"params\":[\"0x8d97689c9818892b700e27f316cc3e41e17fbeb9\", \"latest\"]}' | jq\n\n# eth_getCode: https://eth.wiki/json-rpc/API#eth_getcode\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getCode\", \"params\":[\"0x7f268357a8c2552623316e2562d90e642bb538e5\", \"latest\"]}' | jq\n\n# eth_getTransactionCount: https://eth.wiki/json-rpc/API#eth_gettransactioncount\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getTransactionCount\", \"params\":[\"0xe222489ae12e15713cc1d65dd0ab2f5b18721bfd\", \"latest\"]}' | jq\n\n# eth_chainId: https://docs.alchemy.com/alchemy/apis/ethereum/eth-chainid\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_chainId\"}' | jq\n\n# eth_sendRawTransaction: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendrawtransaction\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_sendRawTransaction\", \"params\": [\"0xf889808609184e72a00082271094000000000000000000000000000000000000000080a47f74657374320000000000000000000000000000000000000000000000000000006000571ca08a8bbf888cfa37bbf0bb965423625641fc956967b81d12e23709cead01446075a01ce999b56a8a88504be365442ea61239198e23d1fce7d00fcfc5cd3b44b7215f\"]}'\n\n# eth_gasPrice: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gasprice\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_gasPrice\"}'\n\n# eth_getStorageAt: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getstorageat\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getStorageAt\", \"params\": [\"0x6c8f2a135f6ed072de4503bd7c4999a1a17f824b\", \"0x0\", \"latest\"]}'\n\n# eth_estimateGas: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_estimategas\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_estimateGas\", \"params\": [{\"from\": \"0x8d97689c9818892b700e27f316cc3e41e17fbeb9\", \"to\": \"0xd3cda913deb6f67967b99d67acdfa1712c293601\", \"value\": \"0x1\"}]}'\n\n#eth_protocolVersion: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_protocolversion\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_protocolVersion\"}'\n\n#eth_syncing: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_syncing\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_syncing\"}'\n\n# eth_feeHistory\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_feeHistory\", \"params\": [4, \"latest\", [25, 75]]}'\n\n# eth_mining: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_mining\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_mining\"}'\n\n# eth_hashrate: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_hashrate\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_hashrate\"}'\n\n# eth_accounts: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_accounts\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_accounts\"}'\n\n# eth_newFilter: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_newfilter\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_newFilter\", \"params\":[{}]}'\n\n# eth_newBlockFilter: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_newblockfilter\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_newBlockFilter\"}'\n\n# eth_uninstallFilter: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_uninstallfilter\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_uninstallFilter\", \"params\":[\"0x81440f9af726125cb7fc671eb0f2d8728d6ad699989a\"]}'\n\n# eth_getFilterChanges: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getfilterchanges\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getFilterChanges\", \"params\":[\"0x81440f9af726125cb7fc671eb0f2d8728d6ad699989a\"]}'\n\n# eth_getFilterLogs: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getfilterlogs\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getFilterLogs\", \"params\":[\"0x81440f9af726125cb7fc671eb0f2d8728d6ad699989a\"]}'\n\n# eth_getWork: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getwork\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getWork\"}'\n\n# eth_submitWork: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_submitwork\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_submitWork\", \"params\": [\"0x0000000000000001\", \"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\", \"0xD1FE5700000000000000000000000000D1FE5700000000000000000000000000\"]}'\n\n# eth_submitHashrate: https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_submithashrate\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_submitHashrate\", \"params\":[\"0x500000\", \"0x59daa26581d0acd1fce254fb7e85952f4c09d0915afd33d3886cd914bc7d283c\"]}'\n```\n\n### Debug namespace\nCaveat: ChainNode only supports the following tracer types: `callTracer`.\n\n```bash\n# debug_traceBlockByHash: https://geth.ethereum.org/docs/rpc/ns-debug#debug_traceblockbyhash\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"debug_traceBlockByHash\", \"params\": [\"0xe075488f2716495e97c43f6eb2994964074a70245cca5844b308479ccbbb9ae7\", {\"tracer\": \"callTracer\"}]}' | jq\n\n# debug_traceBlockByNumber: https://geth.ethereum.org/docs/rpc/ns-debug#debug_traceblockbynumber\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"debug_traceBlockByNumber\", \"params\": [\"0xe11130\", {\"tracer\": \"callTracer\"}]}' | jq\n```\n\n### Net namespace\n```bash\n# net_version: https://eth.wiki/json-rpc/API#net_version\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"net_version\"}' | jq\n\n# net_listening: https://ethereum.org/en/developers/docs/apis/json-rpc/#net_listening\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"net_listening\"}' | jq\n\n# net_peercount: https://ethereum.org/en/developers/docs/apis/json-rpc/#net_peercount\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"net_peerCount\"}' | jq\n```\n\n### Web3 namespace\n```bash\n# web3_clientVersion: https://ethereum.org/en/developers/docs/apis/json-rpc/#web3_clientversion\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"web3_clientVersion\"}'\n```\n\n### Batch Request\n```bash\n# batch request of eth_getTransactionReceipt: https://www.jsonrpc.org/specification#batch\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '[{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getTransactionReceipt\", \"params\": [\"0x633982a26e0cfba940613c52b31c664fe977e05171e35f62da2426596007e249\"]}, { \"jsonrpc\": \"2.0\", \"id\": 2, \"method\": \"eth_getTransactionReceipt\", \"params\": [\"0x3a7d521b20b5684e0e9ec14aeebe8ccab67137f7d5c2589efb55b0625fcc9c6d\"]}]' | jq\n```\n\n### Bor namespace (only for **Polygon**)\n```bash\n# bor_getAuthor: https://www.quicknode.com/docs/polygon/bor_getAuthor\ncurl -s localhost:8000/v1 -H \"Content-Type: application/json\" -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"bor_getAuthor\", \"params\": [\"latest\"]}' | jq .\n```\n\n### GraphQL\n```bash\n# GraphQL is available in select network: https://geth.ethereum.org/docs/interacting-with-geth/rpc/graphql\ncurl -s localhost:8000/v1/graphql -H \"Content-Type: application/json\" -d '{ \"query\": \"query { block { number } }\" }'\n```\n\n### Connect to Geth JavaScript Console\n- Install geth following the [instructions](https://geth.ethereum.org/docs/install-and-build/installing-geth)\n- Run the following command:\n```bash\n~$ geth attach localhost:8000/v1\nWelcome to the Geth JavaScript console!\n\ninstance: Geth/v1.10.19-omnibus-1fd05ab6/linux-amd64/go1.18.3\nat block: 15135980 (Wed Jul 13 2022 11:51:25 GMT-0700 (PDT))\nmodules: debug:1.0 eth:1.0 net:1.0 rpc:1.0 web3:1.0\n\nTo exit, press ctrl-d\n\u003e eth.blockNumber\n15135980\n\u003e eth.getBlockByNumber(15135980)\n...\n\u003e eth.getTransaction(\"0xc16410b8245b404e20319b6825e846b7b0c985da8e62a1db7c66524877530194\")\n...\n\u003e debug.traceBlockByNumber(15135980, {\"tracer\": \"callTracer\"})\n...\n```\n\n## TAG Generator for Proxy Methods\nChainNode Template API Generator (TAG) is a templated code generator capable of self-implementing ChainNode Proxy API methods.\n### TAG Usage:\n  1. Fill in TAG Template (`internal/tag_generator/tag_template.txt`) such that it contains the method signature of all proxy methods that require implementation. \n  2. The code generator is automatically invoked via `make build`. If you would only like to call the TAG generator instead of the entire build process, run `make tag`\n  3. Code-generated implementation for proxy methods will be stored in internal/controller/ethereum/handler with all of the generated files being denoted with the `*tag_generated.go` suffix\n\n### Changing TAG's generated code format:\n  - The code generated by TAG are based on a series of text/template files found in `internal/tag/code_templates`. Templates define the structure of the generated code while unique attributes of the structure are filled out in `generator.go`\n  - Example of Code Generation Template:\n    ```bash\n    func (n {{.Namespace}}) {{.MethodName}}({{.ParametersAndTypes}}) (json.RawMessage, error) {\n        return n.receiver.{{.MethodName}}({{.Parameters}})\n    }\n     ```\n    - All elements of the template that are to be filled out by the generator have placeholder values: `{{.VariableName}}`\n    - Fixed values including parentheses, newlines, tabs can be directly hard coded in the templates.\n  - Example of Using Code Generation Template in Generator:\n    - Code Generation Templates are filled out in the generator using Maps. Declare a map such that the keys are the placeholder values in the templates, values are the values to fill in the template\n    ```bash\n    for i := range element {\n        vars := make(map[string]interface{})\n        vars[\"Namespace\"] = element[i].Namespace\n        vars[\"MethodName\"] = element[i].ApiName\n        vars[\"ParametersAndTypes\"] = parseParametersAndTypes(element[i].Parameter, element[i].ParameterType)\n        vars[\"Parameters\"] = parseParameters(element[i].Parameter)\n        namespace = tag.ProcessTemplate(namespaceTmpl, vars)\n    }\n    ```\n    - In this example: we replace the Namespace, MethodName, ParametersAndTypes, Parameters placeholder values and substitute in the actual values to be used for code generation.\n    - `tag.ProcessTemplate` takes 2 parameters: `string containing path to the template file` as well as a `map containing the key value pairs to be injected into the template`. The function injects the actual values into the template file, returning a string containing the contents of the template with the injected values.\n  - IMPORTANT: following any changes to TAG's code templates, it is important that the unit test also be updated (procedure in the following section)\n\n### Updating TAG's Unit Test:\n  - TAG's unit test only needs to be updated when the format of TAG's code generation is changed (see section above). \n  - Unit test should be directly edited (`internal/utils/fixtures/tag/*`) such that the expected values now reflect the changes of the new generated code format.\n  - Unit tests for TAG's code generation functions are stored in `internal/tag_generator/unit_test_templates/*`; responsible for testing functions used for TAG code generation process.\n  - Unit tests for TAG's code generation output are stored in `internal/utils/fixtures/tag/*`; responsible for validating code generation output.\n\n## JSONRPC Server Batch Request Limit\n### Default Limit\n  - The JSONRPC service batch request limit has a default limit defined per chain in the `base.yml` configuration file(note: it could also have overrides in different environments, please check `development.yml` and `production.yml` as well). e.g. ethereum default limit is [1000](https://github.com/coinbase/chainnode/blob/5da99f53ee5bc9c1a313e2e5078702406abb42b4/config/chainnode/ethereum/mainnet/base.yml#L77)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoinbase%2Fchainnode","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoinbase%2Fchainnode","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoinbase%2Fchainnode/lists"}