# Admin API URL: /docs/api-reference/admin-api This page is an overview of the Admin API associated with AvalancheGo. The Admin API can be used for measuring node health and debugging. The Admin API is disabled by default for security reasons. To run a node with the Admin API enabled, use [`config flag --api-admin-enabled=true`](https://build.avax.network/docs/nodes/configure/configs-flags#--api-admin-enabled-boolean). This API set is for a specific node, it is unavailable on the [public server](https://build.avax.network/docs/tooling/rpc-providers). ## Format This API uses the `json 2.0` RPC format. For details, see [here](https://build.avax.network/docs/api-reference/guides/issuing-api-calls). ## Endpoint ``` /ext/admin ``` ## Methods ### `admin.alias` Assign an API endpoint an alias, a different endpoint for the API. The original endpoint will still work. This change only affects this node; other nodes will not know about this alias. **Signature**: ``` admin.alias({endpoint:string, alias:string}) -> {} ``` * `endpoint` is the original endpoint of the API. `endpoint` should only include the part of the endpoint after `/ext/`. * The API being aliased can now be called at `ext/alias`. * `alias` can be at most 512 characters. **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"admin.alias", "params": { "alias":"myAlias", "endpoint":"bc/X" } }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/admin ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": {} } ``` Now, calls to the X-Chain can be made to either `/ext/bc/X` or, equivalently, to `/ext/myAlias`. ### `admin.aliasChain` Give a blockchain an alias, a different name that can be used any place the blockchain's ID is used. Aliasing a chain can also be done via the [Node API](https://build.avax.network/docs/nodes/configure/configs-flags#--chain-aliases-file-string). Note that the alias is set for each chain on each node individually. In a multi-node Avalanche L1, the same alias should be configured on each node to use an alias across an Avalanche L1 successfully. Setting an alias for a chain on one node does not register that alias with other nodes automatically. **Signature**: ``` admin.aliasChain( { chain:string, alias:string } ) -> {} ``` * `chain` is the blockchain's ID. * `alias` can now be used in place of the blockchain's ID (in API endpoints, for example.) **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"admin.aliasChain", "params": { "chain":"sV6o671RtkGBcno1FiaDbVcFv2sG5aVXMZYzKdP4VQAWmJQnM", "alias":"myBlockchainAlias" } }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/admin ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": {} } ``` Now, instead of interacting with the blockchain whose ID is `sV6o671RtkGBcno1FiaDbVcFv2sG5aVXMZYzKdP4VQAWmJQnM` by making API calls to `/ext/bc/sV6o671RtkGBcno1FiaDbVcFv2sG5aVXMZYzKdP4VQAWmJQnM`, one can also make calls to `ext/bc/myBlockchainAlias`. ### `admin.getChainAliases` Returns the aliases of the chain **Signature**: ``` admin.getChainAliases( { chain:string } ) -> {aliases:string[]} ``` * `chain` is the blockchain's ID. **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"admin.getChainAliases", "params": { "chain":"sV6o671RtkGBcno1FiaDbVcFv2sG5aVXMZYzKdP4VQAWmJQnM" } }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/admin ``` **Example Response**: ```json { "jsonrpc": "2.0", "result": { "aliases": [ "X", "avm", "2eNy1mUFdmaxXNj1eQHUe7Np4gju9sJsEtWQ4MX3ToiNKuADed" ] }, "id": 1 } ``` ### `admin.getLoggerLevel` Returns log and display levels of loggers. **Signature**: ``` admin.getLoggerLevel( { loggerName:string // optional } ) -> { loggerLevels: { loggerName: { logLevel: string, displayLevel: string } } } ``` * `loggerName` is the name of the logger to be returned. This is an optional argument. If not specified, it returns all possible loggers. **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"admin.getLoggerLevel", "params": { "loggerName": "C" } }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/admin ``` **Example Response**: ```json { "jsonrpc": "2.0", "result": { "loggerLevels": { "C": { "logLevel": "DEBUG", "displayLevel": "INFO" } } }, "id": 1 } ``` ### `admin.loadVMs` Dynamically loads any virtual machines installed on the node as plugins. See [here](https://build.avax.network/docs/virtual-machines#installing-a-vm) for more information on how to install a virtual machine on a node. **Signature**: ``` admin.loadVMs() -> { newVMs: map[string][]string failedVMs: map[string]string, } ``` * `failedVMs` is only included in the response if at least one virtual machine fails to be loaded. **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"admin.loadVMs", "params" :{} }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/admin ``` **Example Response**: ```json { "jsonrpc": "2.0", "result": { "newVMs": { "tGas3T58KzdjLHhBDMnH2TvrddhqTji5iZAMZ3RXs2NLpSnhH": ["foovm"] }, "failedVMs": { "rXJsCSEYXg2TehWxCEEGj6JU2PWKTkd6cBdNLjoe2SpsKD9cy": "error message" } }, "id": 1 } ``` ### `admin.lockProfile` Writes a profile of mutex statistics to `lock.profile`. **Signature**: ``` admin.lockProfile() -> {} ``` **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"admin.lockProfile", "params" :{} }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/admin ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": {} } ``` ### `admin.memoryProfile` Writes a memory profile of the to `mem.profile`. **Signature**: ``` admin.memoryProfile() -> {} ``` **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"admin.memoryProfile", "params" :{} }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/admin ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": {} } ``` ### `admin.setLoggerLevel` Sets log and display levels of loggers. **Signature**: ``` admin.setLoggerLevel( { loggerName: string, // optional logLevel: string, // optional displayLevel: string, // optional } ) -> {} ``` * `loggerName` is the logger's name to be changed. This is an optional parameter. If not specified, it changes all possible loggers. * `logLevel` is the log level of written logs, can be omitted. * `displayLevel` is the log level of displayed logs, can be omitted. `logLevel` and `displayLevel` cannot be omitted at the same time. **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"admin.setLoggerLevel", "params": { "loggerName": "C", "logLevel": "DEBUG", "displayLevel": "INFO" } }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/admin ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": {} } ``` ### `admin.startCPUProfiler` Start profiling the CPU utilization of the node. To stop, call `admin.stopCPUProfiler`. On stop, writes the profile to `cpu.profile`. **Signature**: ``` admin.startCPUProfiler() -> {} ``` **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"admin.startCPUProfiler", "params" :{} }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/admin ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": {} } ``` ### `admin.stopCPUProfiler` Stop the CPU profile that was previously started. **Signature**: ``` admin.stopCPUProfiler() -> {} ``` **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"admin.stopCPUProfiler" }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/admin ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": {} } ``` # Health API URL: /docs/api-reference/health-api This page is an overview of the Health API associated with AvalancheGo. The Health API can be used for measuring node health. This API set is for a specific node; it is unavailable on the [public server](https://build.avax.network/docs/tooling/rpc-providers). ## Health Checks The node periodically runs all health checks, including health checks for each chain. The frequency at which health checks are run can be specified with the [--health-check-frequency](https://build.avax.network/docs/nodes/configure/configs-flags) flag. ## Filterable Health Checks The health checks that are run by the node are filterable. You can specify which health checks you want to see by using `tags` filters. Returned results will only include health checks that match the specified tags and global health checks like `network`, `database` etc. When filtered, the returned results will not show the full node health, but only a subset of filtered health checks. This means the node can still be unhealthy in unfiltered checks, even if the returned results show that the node is healthy. AvalancheGo supports using subnetIDs as tags. ## GET Request To get an HTTP status code response that indicates the node's health, make a `GET` request. If the node is healthy, it will return a `200` status code. If the node is unhealthy, it will return a `503` status code. In-depth information about the node's health is included in the response body. ### Filtering To filter GET health checks, add a `tag` query parameter to the request. The `tag` parameter is a string. For example, to filter health results by subnetID `29uVeLPJB1eQJkzRemU8g8wZDw5uJRqpab5U2mX9euieVwiEbL`, use the following query: ```sh curl 'http://localhost:9650/ext/health?tag=29uVeLPJB1eQJkzRemU8g8wZDw5uJRqpab5U2mX9euieVwiEbL' ``` In this example returned results will contain global health checks and health checks that are related to subnetID `29uVeLPJB1eQJkzRemU8g8wZDw5uJRqpab5U2mX9euieVwiEbL`. **Note**: This filtering can show healthy results even if the node is unhealthy in other Chains/Avalanche L1s. In order to filter results by multiple tags, use multiple `tag` query parameters. For example, to filter health results by subnetID `29uVeLPJB1eQJkzRemU8g8wZDw5uJRqpab5U2mX9euieVwiEbL` and `28nrH5T2BMvNrWecFcV3mfccjs6axM1TVyqe79MCv2Mhs8kxiY` use the following query: ```sh curl 'http://localhost:9650/ext/health?tag=29uVeLPJB1eQJkzRemU8g8wZDw5uJRqpab5U2mX9euieVwiEbL&tag=28nrH5T2BMvNrWecFcV3mfccjs6axM1TVyqe79MCv2Mhs8kxiY' ``` The returned results will include health checks for both subnetIDs as well as global health checks. ### Endpoints The available endpoints for GET requests are: * `/ext/health` returns a holistic report of the status of the node. **Most operators should monitor this status.** * `/ext/health/health` is the same as `/ext/health`. * `/ext/health/readiness` returns healthy once the node has finished initializing. * `/ext/health/liveness` returns healthy once the endpoint is available. ## JSON RPC Request ### Format This API uses the `json 2.0` RPC format. For more information on making JSON RPC calls, see [here](https://build.avax.network/docs/api-reference/guides/issuing-api-calls). ### Endpoint ### Methods #### `health.health` This method returns the last set of health check results. **Example Call**: ```sh curl -H 'Content-Type: application/json' --data '{ "jsonrpc":"2.0", "id" :1, "method" :"health.health", "params": { "tags": ["11111111111111111111111111111111LpoYY", "29uVeLPJB1eQJkzRemU8g8wZDw5uJRqpab5U2mX9euieVwiEbL"] } }' 'http://localhost:9650/ext/health' ``` **Example Response**: ```json { "jsonrpc": "2.0", "result": { "checks": { "C": { "message": { "engine": { "consensus": { "lastAcceptedHeight": 31273749, "lastAcceptedID": "2Y4gZGzQnu8UjnHod8j1BLewHFVEbzhULPNzqrSWEHkHNqDrYL", "longestProcessingBlock": "0s", "processingBlocks": 0 }, "vm": null }, "networking": { "percentConnected": 0.9999592612587486 } }, "timestamp": "2024-03-26T19:44:45.2931-04:00", "duration": 20375 }, "P": { "message": { "engine": { "consensus": { "lastAcceptedHeight": 142517, "lastAcceptedID": "2e1FEPCBEkG2Q7WgyZh1v4nt3DXj1HDbDthyhxdq2Ltg3shSYq", "longestProcessingBlock": "0s", "processingBlocks": 0 }, "vm": null }, "networking": { "percentConnected": 0.9999592612587486 } }, "timestamp": "2024-03-26T19:44:45.293115-04:00", "duration": 8750 }, "X": { "message": { "engine": { "consensus": { "lastAcceptedHeight": 24464, "lastAcceptedID": "XuFCsGaSw9cn7Vuz5e2fip4KvP46Xu53S8uDRxaC2QJmyYc3w", "longestProcessingBlock": "0s", "processingBlocks": 0 }, "vm": null }, "networking": { "percentConnected": 0.9999592612587486 } }, "timestamp": "2024-03-26T19:44:45.29312-04:00", "duration": 23291 }, "bootstrapped": { "message": [], "timestamp": "2024-03-26T19:44:45.293078-04:00", "duration": 3375 }, "database": { "timestamp": "2024-03-26T19:44:45.293102-04:00", "duration": 1959 }, "diskspace": { "message": { "availableDiskBytes": 227332591616 }, "timestamp": "2024-03-26T19:44:45.293106-04:00", "duration": 3042 }, "network": { "message": { "connectedPeers": 284, "sendFailRate": 0, "timeSinceLastMsgReceived": "293.098ms", "timeSinceLastMsgSent": "293.098ms" }, "timestamp": "2024-03-26T19:44:45.2931-04:00", "duration": 2333 }, "router": { "message": { "longestRunningRequest": "66.90725ms", "outstandingRequests": 3 }, "timestamp": "2024-03-26T19:44:45.293097-04:00", "duration": 3542 } }, "healthy": true }, "id": 1 } ``` In this example response, every check has passed. So, the node is healthy. **Response Explanation**: * `checks` is a list of health check responses. * A check response may include a `message` with additional context. * A check response may include an `error` describing why the check failed. * `timestamp` is the timestamp of the last health check. * `duration` is the execution duration of the last health check, in nanoseconds. * `contiguousFailures` is the number of times in a row this check failed. * `timeOfFirstFailure` is the time this check first failed. * `healthy` is true all the health checks are passing. #### `health.readiness` This method returns the last evaluation of the startup health check results. **Example Call**: ```sh curl -H 'Content-Type: application/json' --data '{ "jsonrpc":"2.0", "id" :1, "method" :"health.readiness", "params": { "tags": ["11111111111111111111111111111111LpoYY", "29uVeLPJB1eQJkzRemU8g8wZDw5uJRqpab5U2mX9euieVwiEbL"] } }' 'http://localhost:9650/ext/health' ``` **Example Response**: ```json { "jsonrpc": "2.0", "result": { "checks": { "bootstrapped": { "message": [], "timestamp": "2024-03-26T20:02:45.299114-04:00", "duration": 2834 } }, "healthy": true }, "id": 1 } ``` In this example response, every check has passed. So, the node has finished the startup process. **Response Explanation**: * `checks` is a list of health check responses. * A check response may include a `message` with additional context. * A check response may include an `error` describing why the check failed. * `timestamp` is the timestamp of the last health check. * `duration` is the execution duration of the last health check, in nanoseconds. * `contiguousFailures` is the number of times in a row this check failed. * `timeOfFirstFailure` is the time this check first failed. * `healthy` is true all the health checks are passing. #### `health.liveness` This method returns healthy. **Example Call**: ```sh curl -H 'Content-Type: application/json' --data '{ "jsonrpc":"2.0", "id" :1, "method" :"health.liveness" }' 'http://localhost:9650/ext/health' ``` **Example Response**: ```json { "jsonrpc": "2.0", "result": { "checks": {}, "healthy": true }, "id": 1 } ``` In this example response, the node was able to handle the request and mark the service as healthy. **Response Explanation**: * `checks` is an empty list. * `healthy` is true. # Index API URL: /docs/api-reference/index-api This page is an overview of the Index API associated with AvalancheGo. AvalancheGo can be configured to run with an indexer. That is, it saves (indexes) every container (a block, vertex or transaction) it accepts on the X-Chain, P-Chain and C-Chain. To run AvalancheGo with indexing enabled, set command line flag [--index-enabled](https://build.avax.network/docs/nodes/configure/configs-flags#--index-enabled-boolean) to true. **AvalancheGo will only index containers that are accepted when running with `--index-enabled` set to true.** To ensure your node has a complete index, run a node with a fresh database and `--index-enabled` set to true. The node will accept every block, vertex and transaction in the network history during bootstrapping, ensuring your index is complete. It is OK to turn off your node if it is running with indexing enabled. If it restarts with indexing still enabled, it will accept all containers that were accepted while it was offline. The indexer should never fail to index an accepted block, vertex or transaction. Indexed containers (that is, accepted blocks, vertices and transactions) are timestamped with the time at which the node accepted that container. Note that if the container was indexed during bootstrapping, other nodes may have accepted the container much earlier. Every container indexed during bootstrapping will be timestamped with the time at which the node bootstrapped, not when it was first accepted by the network. If `--index-enabled` is changed to `false` from `true`, AvalancheGo won't start as doing so would cause a previously complete index to become incomplete, unless the user explicitly says to do so with `--index-allow-incomplete`. This protects you from accidentally running with indexing disabled, after previously running with it enabled, which would result in an incomplete index. This document shows how to query data from AvalancheGo's Index API. The Index API is only available when running with `--index-enabled`. ## Go Client There is a Go implementation of an Index API client. See documentation [here](https://pkg.go.dev/github.com/ava-labs/avalanchego/indexer#Client). This client can be used inside a Go program to connect to an AvalancheGo node that is running with the Index API enabled and make calls to the Index API. ## Format This API uses the `json 2.0` RPC format. For more information on making JSON RPC calls, see [here](https://build.avax.network/docs/api-reference/guides/issuing-api-calls). ## Endpoints Each chain has one or more index. To see if a C-Chain block is accepted, for example, send an API call to the C-Chain block index. To see if an X-Chain vertex is accepted, for example, send an API call to the X-Chain vertex index. ### C-Chain Blocks ``` /ext/index/C/block ``` ### P-Chain Blocks ``` /ext/index/P/block ``` ### X-Chain Transactions ``` /ext/index/X/tx ``` ### X-Chain Blocks ``` /ext/index/X/block ``` To ensure historical data can be accessed, the `/ext/index/X/vtx` is still accessible, even though it is no longer populated with chain data since the Cortina activation. If you are using `V1.10.0` or higher, you need to migrate to using the `/ext/index/X/block` endpoint. ## Methods ### `index.getContainerByID` Get container by ID. **Signature**: ``` index.getContainerByID({ id: string, encoding: string }) -> { id: string, bytes: string, timestamp: string, encoding: string, index: string } ``` **Request**: * `id` is the container's ID * `encoding` is `"hex"` only. **Response**: * `id` is the container's ID * `bytes` is the byte representation of the container * `timestamp` is the time at which this node accepted the container * `encoding` is `"hex"` only. * `index` is how many containers were accepted in this index before this one **Example Call**: ```sh curl --location --request POST 'localhost:9650/ext/index/X/tx' \ --header 'Content-Type: application/json' \ --data-raw '{ "jsonrpc": "2.0", "method": "index.getContainerByID", "params": { "id": "6fXf5hncR8LXvwtM8iezFQBpK5cubV6y1dWgpJCcNyzGB1EzY", "encoding":"hex" }, "id": 1 }' ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": { "id": "6fXf5hncR8LXvwtM8iezFQBpK5cubV6y1dWgpJCcNyzGB1EzY", "bytes": "0x00000000000400003039d891ad56056d9c01f18f43f58b5c784ad07a4a49cf3d1f11623804b5cba2c6bf00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db000000070429ccc5c5eb3b80000000000000000000000001000000013cb7d3842e8cee6a0ebd09f1fe884f6861e1b29c00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db000000050429d069189e0000000000010000000000000000c85fc1980a77c5da78fe5486233fc09a769bb812bcb2cc548cf9495d046b3f1b00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db00000007000003a352a38240000000000000000000000001000000013cb7d3842e8cee6a0ebd09f1fe884f6861e1b29c0000000100000009000000011cdb75d4e0b0aeaba2ebc1ef208373fedc1ebbb498f8385ad6fb537211d1523a70d903b884da77d963d56f163191295589329b5710113234934d0fd59c01676b00b63d2108", "timestamp": "2021-04-02T15:34:00.262979-07:00", "encoding": "hex", "index": "0" } } ``` ### `index.getContainerByIndex` Get container by index. The first container accepted is at index 0, the second is at index 1, etc. **Signature**: ``` index.getContainerByIndex({ index: uint64, encoding: string }) -> { id: string, bytes: string, timestamp: string, encoding: string, index: string } ``` **Request**: * `index` is how many containers were accepted in this index before this one * `encoding` is `"hex"` only. **Response**: * `id` is the container's ID * `bytes` is the byte representation of the container * `timestamp` is the time at which this node accepted the container * `index` is how many containers were accepted in this index before this one * `encoding` is `"hex"` only. **Example Call**: ```sh curl --location --request POST 'localhost:9650/ext/index/X/tx' \ --header 'Content-Type: application/json' \ --data-raw '{ "jsonrpc": "2.0", "method": "index.getContainerByIndex", "params": { "index":0, "encoding": "hex" }, "id": 1 }' ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": { "id": "6fXf5hncR8LXvwtM8iezFQBpK5cubV6y1dWgpJCcNyzGB1EzY", "bytes": "0x00000000000400003039d891ad56056d9c01f18f43f58b5c784ad07a4a49cf3d1f11623804b5cba2c6bf00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db000000070429ccc5c5eb3b80000000000000000000000001000000013cb7d3842e8cee6a0ebd09f1fe884f6861e1b29c00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db000000050429d069189e0000000000010000000000000000c85fc1980a77c5da78fe5486233fc09a769bb812bcb2cc548cf9495d046b3f1b00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db00000007000003a352a38240000000000000000000000001000000013cb7d3842e8cee6a0ebd09f1fe884f6861e1b29c0000000100000009000000011cdb75d4e0b0aeaba2ebc1ef208373fedc1ebbb498f8385ad6fb537211d1523a70d903b884da77d963d56f163191295589329b5710113234934d0fd59c01676b00b63d2108", "timestamp": "2021-04-02T15:34:00.262979-07:00", "encoding": "hex", "index": "0" } } ``` ### `index.getContainerRange` Returns the transactions at index \[`startIndex`], \[`startIndex+1`], ... , \[`startIndex+n-1`] * If \[`n`] == 0, returns an empty response (for example: null). * If \[`startIndex`] > the last accepted index, returns an error (unless the above apply.) * If \[`n`] > \[`MaxFetchedByRange`], returns an error. * If we run out of transactions, returns the ones fetched before running out. * `numToFetch` must be in `[0,1024]`. **Signature**: ``` index.getContainerRange({ startIndex: uint64, numToFetch: uint64, encoding: string }) -> []{ id: string, bytes: string, timestamp: string, encoding: string, index: string } ``` **Request**: * `startIndex` is the beginning index * `numToFetch` is the number of containers to fetch * `encoding` is `"hex"` only. **Response**: * `id` is the container's ID * `bytes` is the byte representation of the container * `timestamp` is the time at which this node accepted the container * `encoding` is `"hex"` only. * `index` is how many containers were accepted in this index before this one **Example Call**: ```sh curl --location --request POST 'localhost:9650/ext/index/X/tx' \ --header 'Content-Type: application/json' \ --data-raw '{ "jsonrpc": "2.0", "method": "index.getContainerRange", "params": { "startIndex":0, "numToFetch":100, "encoding": "hex" }, "id": 1 }' ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": [ { "id": "6fXf5hncR8LXvwtM8iezFQBpK5cubV6y1dWgpJCcNyzGB1EzY", "bytes": "0x00000000000400003039d891ad56056d9c01f18f43f58b5c784ad07a4a49cf3d1f11623804b5cba2c6bf00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db000000070429ccc5c5eb3b80000000000000000000000001000000013cb7d3842e8cee6a0ebd09f1fe884f6861e1b29c00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db000000050429d069189e0000000000010000000000000000c85fc1980a77c5da78fe5486233fc09a769bb812bcb2cc548cf9495d046b3f1b00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db00000007000003a352a38240000000000000000000000001000000013cb7d3842e8cee6a0ebd09f1fe884f6861e1b29c0000000100000009000000011cdb75d4e0b0aeaba2ebc1ef208373fedc1ebbb498f8385ad6fb537211d1523a70d903b884da77d963d56f163191295589329b5710113234934d0fd59c01676b00b63d2108", "timestamp": "2021-04-02T15:34:00.262979-07:00", "encoding": "hex", "index": "0" } ] } ``` ### `index.getIndex` Get a container's index. **Signature**: ``` index.getIndex({ id: string, encoding: string }) -> { index: string } ``` **Request**: * `id` is the ID of the container to fetch * `encoding` is `"hex"` only. **Response**: * `index` is how many containers were accepted in this index before this one **Example Call**: ```sh curl --location --request POST 'localhost:9650/ext/index/X/tx' \ --header 'Content-Type: application/json' \ --data-raw '{ "jsonrpc": "2.0", "method": "index.getIndex", "params": { "id":"6fXf5hncR8LXvwtM8iezFQBpK5cubV6y1dWgpJCcNyzGB1EzY", "encoding": "hex" }, "id": 1 }' ``` **Example Response**: ```json { "jsonrpc": "2.0", "result": { "index": "0" }, "id": 1 } ``` ### `index.getLastAccepted` Get the most recently accepted container. **Signature**: ``` index.getLastAccepted({ encoding:string }) -> { id: string, bytes: string, timestamp: string, encoding: string, index: string } ``` **Request**: * `encoding` is `"hex"` only. **Response**: * `id` is the container's ID * `bytes` is the byte representation of the container * `timestamp` is the time at which this node accepted the container * `encoding` is `"hex"` only. **Example Call**: ```sh curl --location --request POST 'localhost:9650/ext/index/X/tx' \ --header 'Content-Type: application/json' \ --data-raw '{ "jsonrpc": "2.0", "method": "index.getLastAccepted", "params": { "encoding": "hex" }, "id": 1 }' ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": { "id": "6fXf5hncR8LXvwtM8iezFQBpK5cubV6y1dWgpJCcNyzGB1EzY", "bytes": "0x00000000000400003039d891ad56056d9c01f18f43f58b5c784ad07a4a49cf3d1f11623804b5cba2c6bf00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db000000070429ccc5c5eb3b80000000000000000000000001000000013cb7d3842e8cee6a0ebd09f1fe884f6861e1b29c00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db000000050429d069189e0000000000010000000000000000c85fc1980a77c5da78fe5486233fc09a769bb812bcb2cc548cf9495d046b3f1b00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db00000007000003a352a38240000000000000000000000001000000013cb7d3842e8cee6a0ebd09f1fe884f6861e1b29c0000000100000009000000011cdb75d4e0b0aeaba2ebc1ef208373fedc1ebbb498f8385ad6fb537211d1523a70d903b884da77d963d56f163191295589329b5710113234934d0fd59c01676b00b63d2108", "timestamp": "2021-04-02T15:34:00.262979-07:00", "encoding": "hex", "index": "0" } } ``` ### `index.isAccepted` Returns true if the container is in this index. **Signature**: ``` index.isAccepted({ id: string, encoding: string }) -> { isAccepted: bool } ``` **Request**: * `id` is the ID of the container to fetch * `encoding` is `"hex"` only. **Response**: * `isAccepted` displays if the container has been accepted **Example Call**: ```sh curl --location --request POST 'localhost:9650/ext/index/X/tx' \ --header 'Content-Type: application/json' \ --data-raw '{ "jsonrpc": "2.0", "method": "index.isAccepted", "params": { "id":"6fXf5hncR8LXvwtM8iezFQBpK5cubV6y1dWgpJCcNyzGB1EzY", "encoding": "hex" }, "id": 1 }' ``` **Example Response**: ```json { "jsonrpc": "2.0", "result": { "isAccepted": true }, "id": 1 } ``` ## Example: Iterating Through X-Chain Transaction Here is an example of how to iterate through all transactions on the X-Chain. You can use the Index API to get the ID of every transaction that has been accepted on the X-Chain, and use the X-Chain API method `avm.getTx` to get a human-readable representation of the transaction. To get an X-Chain transaction by its index (the order it was accepted in), use Index API method [index.getlastaccepted](#indexgetlastaccepted). For example, to get the second transaction (note that `"index":1`) accepted on the X-Chain, do: ```sh curl --location --request POST 'https://indexer-demo.avax.network/ext/index/X/tx' \ --header 'Content-Type: application/json' \ --data-raw '{ "jsonrpc": "2.0", "method": "index.getContainerByIndex", "params": { "encoding":"hex", "index":1 }, "id": 1 }' ``` This returns the ID of the second transaction accepted in the X-Chain's history. To get the third transaction on the X-Chain, use `"index":2`, and so on. The above API call gives the response below: ```json { "jsonrpc": "2.0", "result": { "id": "ZGYTSU8w3zUP6VFseGC798vA2Vnxnfj6fz1QPfA9N93bhjJvo", "bytes": "0x00000000000000000001ed5f38341e436e5d46e2bb00b45d62ae97d1b050c64bc634ae10626739e35c4b0000000221e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff000000070000000129f6afc0000000000000000000000001000000017416792e228a765c65e2d76d28ab5a16d18c342f21e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff0000000700000222afa575c00000000000000000000000010000000187d6a6dd3cd7740c8b13a410bea39b01fa83bb3e000000016f375c785edb28d52edb59b54035c96c198e9d80f5f5f5eee070592fe9465b8d0000000021e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff0000000500000223d9ab67c0000000010000000000000000000000010000000900000001beb83d3d29f1247efb4a3a1141ab5c966f46f946f9c943b9bc19f858bd416d10060c23d5d9c7db3a0da23446b97cd9cf9f8e61df98e1b1692d764c84a686f5f801a8da6e40", "timestamp": "2021-11-04T00:42:55.01643414Z", "encoding": "hex", "index": "1" }, "id": 1 } ``` The ID of this transaction is `ZGYTSU8w3zUP6VFseGC798vA2Vnxnfj6fz1QPfA9N93bhjJvo`. To get the transaction by its ID, use API method `avm.getTx`: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"avm.getTx", "params" :{ "txID":"ZGYTSU8w3zUP6VFseGC798vA2Vnxnfj6fz1QPfA9N93bhjJvo", "encoding": "json" } }' -H 'content-type:application/json;' https://api.avax.network/ext/bc/X ``` **Response**: ```json { "jsonrpc": "2.0", "result": { "tx": { "unsignedTx": { "networkID": 1, "blockchainID": "2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM", "outputs": [ { "assetID": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z", "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", "output": { "addresses": ["X-avax1wst8jt3z3fm9ce0z6akj3266zmgccdp03hjlaj"], "amount": 4999000000, "locktime": 0, "threshold": 1 } }, { "assetID": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z", "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", "output": { "addresses": ["X-avax1slt2dhfu6a6qezcn5sgtagumq8ag8we75f84sw"], "amount": 2347999000000, "locktime": 0, "threshold": 1 } } ], "inputs": [ { "txID": "qysTYUMCWdsR3MctzyfXiSvoSf6evbeFGRLLzA4j2BjNXTknh", "outputIndex": 0, "assetID": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z", "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", "input": { "amount": 2352999000000, "signatureIndices": [0] } } ], "memo": "0x" }, "credentials": [ { "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", "credential": { "signatures": [ "0xbeb83d3d29f1247efb4a3a1141ab5c966f46f946f9c943b9bc19f858bd416d10060c23d5d9c7db3a0da23446b97cd9cf9f8e61df98e1b1692d764c84a686f5f801" ] } } ] }, "encoding": "json" }, "id": 1 } ``` # Introduction URL: /docs/api-reference Comprehensive reference documentation for Avalanche APIs. # Info API URL: /docs/api-reference/info-api This page is an overview of the Info API associated with AvalancheGo. The Info API can be used to access basic information about an Avalanche node. ## Format This API uses the `json 2.0` RPC format. For more information on making JSON RPC calls, see [here](https://build.avax.network/docs/api-reference/guides/issuing-api-calls). ## Endpoint ``` /ext/info ``` ## Methods ### `info.acps` Returns peer preferences for Avalanche Community Proposals (ACPs) **Signature**: ``` info.acps() -> { acps: map[uint32]{ supportWeight: uint64 supporters: set[string] objectWeight: uint64 objectors: set[string] abstainWeight: uint64 } } ``` **Example Call**: ```sh curl -sX POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"info.acps", "params" :{} }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/info ``` **Example Response**: ```json { "jsonrpc": "2.0", "result": { "acps": { "23": { "supportWeight": "0", "supporters": [], "objectWeight": "0", "objectors": [], "abstainWeight": "161147778098286584" }, "24": { "supportWeight": "0", "supporters": [], "objectWeight": "0", "objectors": [], "abstainWeight": "161147778098286584" }, "25": { "supportWeight": "0", "supporters": [], "objectWeight": "0", "objectors": [], "abstainWeight": "161147778098286584" }, "30": { "supportWeight": "0", "supporters": [], "objectWeight": "0", "objectors": [], "abstainWeight": "161147778098286584" }, "31": { "supportWeight": "0", "supporters": [], "objectWeight": "0", "objectors": [], "abstainWeight": "161147778098286584" }, "41": { "supportWeight": "0", "supporters": [], "objectWeight": "0", "objectors": [], "abstainWeight": "161147778098286584" }, "62": { "supportWeight": "0", "supporters": [], "objectWeight": "0", "objectors": [], "abstainWeight": "161147778098286584" } } }, "id": 1 } ``` ### `info.isBootstrapped` Check whether a given chain is done bootstrapping **Signature**: ``` info.isBootstrapped({chain: string}) -> {isBootstrapped: bool} ``` `chain` is the ID or alias of a chain. **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"info.isBootstrapped", "params": { "chain":"X" } }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/info ``` **Example Response**: ```json { "jsonrpc": "2.0", "result": { "isBootstrapped": true }, "id": 1 } ``` ### `info.getBlockchainID` Given a blockchain's alias, get its ID. (See [`admin.aliasChain`](https://build.avax.network/docs/api-reference/admin-api#adminaliaschain).) **Signature**: ``` info.getBlockchainID({alias:string}) -> {blockchainID:string} ``` **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"info.getBlockchainID", "params": { "alias":"X" } }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/info ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": { "blockchainID": "sV6o671RtkGBcno1FiaDbVcFv2sG5aVXMZYzKdP4VQAWmJQnM" } } ``` ### `info.getNetworkID` Get the ID of the network this node is participating in. **Signature**: ``` info.getNetworkID() -> { networkID: int } ``` **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"info.getNetworkID" }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/info ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": { "networkID": "2" } } ``` Network ID of 1 = Mainnet Network ID of 5 = Fuji (testnet) ### `info.getNetworkName` Get the name of the network this node is participating in. **Signature**: ``` info.getNetworkName() -> { networkName:string } ``` **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"info.getNetworkName" }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/info ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": { "networkName": "local" } } ``` ### `info.getNodeID` Get the ID, the BLS key, and the proof of possession(BLS signature) of this node. This endpoint set is for a specific node, it is unavailable on the [public server](https://build.avax.network/docs/tooling/rpc-providers). **Signature**: ``` info.getNodeID() -> { nodeID: string, nodePOP: { publicKey: string, proofOfPossession: string } } ``` * `nodeID` Node ID is the unique identifier of the node that you set to act as a validator on the Primary Network. * `nodePOP` is this node's BLS key and proof of possession. Nodes must register a BLS key to act as a validator on the Primary Network. Your node's POP is logged on startup and is accessible over this endpoint. * `publicKey` is the 48 byte hex representation of the BLS key. * `proofOfPossession` is the 96 byte hex representation of the BLS signature. **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"info.getNodeID" }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/info ``` **Example Response**: ```json { "jsonrpc": "2.0", "result": { "nodeID": "NodeID-5mb46qkSBj81k9g9e4VFjGGSbaaSLFRzD", "nodePOP": { "publicKey": "0x8f95423f7142d00a48e1014a3de8d28907d420dc33b3052a6dee03a3f2941a393c2351e354704ca66a3fc29870282e15", "proofOfPossession": "0x86a3ab4c45cfe31cae34c1d06f212434ac71b1be6cfe046c80c162e057614a94a5bc9f1ded1a7029deb0ba4ca7c9b71411e293438691be79c2dbf19d1ca7c3eadb9c756246fc5de5b7b89511c7d7302ae051d9e03d7991138299b5ed6a570a98" } }, "id": 1 } ``` ### `info.getNodeIP` Get the IP of this node. This endpoint set is for a specific node, it is unavailable on the [public server](https://build.avax.network/docs/tooling/rpc-providers). **Signature**: ``` info.getNodeIP() -> {ip: string} ``` **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"info.getNodeIP" }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/info ``` **Example Response**: ```json { "jsonrpc": "2.0", "result": { "ip": "192.168.1.1:9651" }, "id": 1 } ``` ### `info.getNodeVersion` Get the version of this node. **Signature**: ``` info.getNodeVersion() -> { version: string, databaseVersion: string, gitCommit: string, vmVersions: map[string]string, rpcProtocolVersion: string, } ``` where: * `version` is this node's version * `databaseVersion` is the version of the database this node is using * `gitCommit` is the Git commit that this node was built from * `vmVersions` is map where each key/value pair is the name of a VM, and the version of that VM this node runs * `rpcProtocolVersion` is the RPCChainVM protocol version **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"info.getNodeVersion" }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/info ``` **Example Response**: ```json { "jsonrpc": "2.0", "result": { "version": "avalanche/1.9.1", "databaseVersion": "v1.4.5", "rpcProtocolVersion": "18", "gitCommit": "79cd09ba728e1cecef40acd60702f0a2d41ea404", "vmVersions": { "avm": "v1.9.1", "evm": "v0.11.1", "platform": "v1.9.1" } }, "id": 1 } ``` ### `info.getTxFee` Deprecated as of [v1.12.2](https://github.com/ava-labs/avalanchego/releases/tag/v1.12.2). Get the fees of the network. **Signature**: ``` info.getTxFee() -> { txFee: uint64, createAssetTxFee: uint64, createSubnetTxFee: uint64, transformSubnetTxFee: uint64, createBlockchainTxFee: uint64, addPrimaryNetworkValidatorFee: uint64, addPrimaryNetworkDelegatorFee: uint64, addSubnetValidatorFee: uint64, addSubnetDelegatorFee: uint64 } ``` * `txFee` is the default fee for issuing X-Chain transactions. * `createAssetTxFee` is the fee for issuing a `CreateAssetTx` on the X-Chain. * `createSubnetTxFee` is no longer used. * `transformSubnetTxFee` is no longer used. * `createBlockchainTxFee` is no longer used. * `addPrimaryNetworkValidatorFee` is no longer used. * `addPrimaryNetworkDelegatorFee` is no longer used. * `addSubnetValidatorFee` is no longer used. * `addSubnetDelegatorFee` is no longer used. All fees are denominated in nAVAX. **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"info.getTxFee" }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/info ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": { "txFee": "1000000", "createAssetTxFee": "10000000", "createSubnetTxFee": "1000000000", "transformSubnetTxFee": "10000000000", "createBlockchainTxFee": "1000000000", "addPrimaryNetworkValidatorFee": "0", "addPrimaryNetworkDelegatorFee": "0", "addSubnetValidatorFee": "1000000", "addSubnetDelegatorFee": "1000000" } } ``` ### `info.getVMs` Get the virtual machines installed on this node. This endpoint set is for a specific node, it is unavailable on the [public server](https://build.avax.network/docs/tooling/rpc-providers). **Signature**: ``` info.getVMs() -> { vms: map[string][]string } ``` **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"info.getVMs", "params" :{} }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/info ``` **Example Response**: ```json { "jsonrpc": "2.0", "result": { "vms": { "jvYyfQTxGMJLuGWa55kdP2p2zSUYsQ5Raupu4TW34ZAUBAbtq": ["avm"], "mgj786NP7uDwBCcq6YwThhaN8FLyybkCa4zBWTQbNgmK6k9A6": ["evm"], "qd2U4HDWUvMrVUeTcCHp6xH3Qpnn1XbU5MDdnBoiifFqvgXwT": ["nftfx"], "rWhpuQPF1kb72esV2momhMuTYGkEb1oL29pt2EBXWmSy4kxnT": ["platform"], "rXJsCSEYXg2TehWxCEEGj6JU2PWKTkd6cBdNLjoe2SpsKD9cy": ["propertyfx"], "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ": ["secp256k1fx"] } }, "id": 1 } ``` ### `info.peers` Get a description of peer connections. **Signature**: ``` info.peers({ nodeIDs: string[] // optional }) -> { numPeers: int, peers:[]{ ip: string, publicIP: string, nodeID: string, version: string, lastSent: string, lastReceived: string, benched: string[], observedUptime: int, } } ``` * `nodeIDs` is an optional parameter to specify what NodeID's descriptions should be returned. If this parameter is left empty, descriptions for all active connections will be returned. If the node is not connected to a specified NodeID, it will be omitted from the response. * `ip` is the remote IP of the peer. * `publicIP` is the public IP of the peer. * `nodeID` is the prefixed Node ID of the peer. * `version` shows which version the peer runs on. * `lastSent` is the timestamp of last message sent to the peer. * `lastReceived` is the timestamp of last message received from the peer. * `benched` shows chain IDs that the peer is currently benched on. * `observedUptime` is this node's primary network uptime, observed by the peer. **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"info.peers", "params": { "nodeIDs": [] } }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/info ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": { "numPeers": 3, "peers": [ { "ip": "206.189.137.87:9651", "publicIP": "206.189.137.87:9651", "nodeID": "NodeID-8PYXX47kqLDe2wD4oPbvRRchcnSzMA4J4", "version": "avalanche/1.9.4", "lastSent": "2020-06-01T15:23:02Z", "lastReceived": "2020-06-01T15:22:57Z", "benched": [], "observedUptime": "99", "trackedSubnets": [], "benched": [] }, { "ip": "158.255.67.151:9651", "publicIP": "158.255.67.151:9651", "nodeID": "NodeID-C14fr1n8EYNKyDfYixJ3rxSAVqTY3a8BP", "version": "avalanche/1.9.4", "lastSent": "2020-06-01T15:23:02Z", "lastReceived": "2020-06-01T15:22:34Z", "benched": [], "observedUptime": "75", "trackedSubnets": [ "29uVeLPJB1eQJkzRemU8g8wZDw5uJRqpab5U2mX9euieVwiEbL" ], "benched": [] }, { "ip": "83.42.13.44:9651", "publicIP": "83.42.13.44:9651", "nodeID": "NodeID-LPbcSMGJ4yocxYxvS2kBJ6umWeeFbctYZ", "version": "avalanche/1.9.3", "lastSent": "2020-06-01T15:23:02Z", "lastReceived": "2020-06-01T15:22:55Z", "benched": [], "observedUptime": "95", "trackedSubnets": [], "benched": [] } ] } } ``` ### `info.uptime` Returns the network's observed uptime of this node. This is the only reliable source of data for your node's uptime. Other sources may be using data gathered with incomplete (limited) information. **Signature**: ``` info.uptime() -> { rewardingStakePercentage: float64, weightedAveragePercentage: float64 } ``` * `rewardingStakePercentage` is the percent of stake which thinks this node is above the uptime requirement. * `weightedAveragePercentage` is the stake-weighted average of all observed uptimes for this node. **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"info.uptime" }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/info ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": { "rewardingStakePercentage": "100.0000", "weightedAveragePercentage": "99.0000" } } ``` #### Example Avalanche L1 Call ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"info.uptime", "params" :{ "subnetID":"29uVeLPJB1eQJkzRemU8g8wZDw5uJRqpab5U2mX9euieVwiEbL" } }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/info ``` #### Example Avalanche L1 Response ```json { "jsonrpc": "2.0", "id": 1, "result": { "rewardingStakePercentage": "74.0741", "weightedAveragePercentage": "72.4074" } } ``` ### `info.upgrades` Returns the upgrade history and configuration of the network. **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"info.upgrades" }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/info ``` **Example Response**: ```json { "jsonrpc": "2.0", "result": { "apricotPhase1Time": "2020-12-05T05:00:00Z", "apricotPhase2Time": "2020-12-05T05:00:00Z", "apricotPhase3Time": "2020-12-05T05:00:00Z", "apricotPhase4Time": "2020-12-05T05:00:00Z", "apricotPhase4MinPChainHeight": 0, "apricotPhase5Time": "2020-12-05T05:00:00Z", "apricotPhasePre6Time": "2020-12-05T05:00:00Z", "apricotPhase6Time": "2020-12-05T05:00:00Z", "apricotPhasePost6Time": "2020-12-05T05:00:00Z", "banffTime": "2020-12-05T05:00:00Z", "cortinaTime": "2020-12-05T05:00:00Z", "cortinaXChainStopVertexID": "11111111111111111111111111111111LpoYY", "durangoTime": "2020-12-05T05:00:00Z", "etnaTime": "2024-10-09T20:00:00Z", "fortunaTime": "9999-12-01T05:00:00Z", "graniteTime": "9999-12-01T05:00:00Z" }, "id": 1 } ``` # Keystore API [Deprecated] URL: /docs/api-reference/keystore-api This page is an overview of the Keystore API associated with AvalancheGo. Because the node operator has access to your plain-text password, you should only create a keystore user on a node that you operate. If that node is breached, you could lose all your tokens. Keystore APIs are not recommended for use on Mainnet. Every node has a built-in keystore. Clients create users on the keystore, which act as identities to be used when interacting with blockchains. A keystore exists at the node level, so if you create a user on a node it exists *only* on that node. However, users may be imported and exported using this API. For validation and cross-chain transfer on the Mainnet, you should issue transactions through [AvalancheJS](https://github.com/tooling/avalanche-js). That way control keys for your funds won't be stored on the node, which significantly lowers the risk should a computer running a node be compromised. See following docs for details: 1. Transfer AVAX Tokens Between Chains: * C-Chain: [export](https://github.com/ava-labs/avalanchejs/blob/master/examples/c-chain/export.ts) and [import](https://github.com/ava-labs/avalanchejs/blob/master/examples/c-chain/import.ts) * P-Chain: [export](https://github.com/ava-labs/avalanchejs/blob/master/examples/p-chain/export.ts) and [import](https://github.com/ava-labs/avalanchejs/blob/master/examples/p-chain/import.ts) * X-Chain: [export](https://github.com/ava-labs/avalanchejs/blob/master/examples/x-chain/export.ts) and [import](https://github.com/ava-labs/avalanchejs/blob/master/examples/x-chain/import.ts) 2. [Add a Node to the Validator Set](https://github.com/nodes/validate/node-validator) This API set is for a specific node, it is unavailable on the [public server](https://github.com/tooling/rpc-providers). ## Format This API uses the `json 2.0` API format. For more information on making JSON RPC calls, see [here](https://github.com/api-reference/standards/guides/issuing-api-calls). ## Endpoint ``` /ext/keystore ``` ## Methods ### `keystore.createUser` Create a new user with the specified username and password. **Signature**: ``` keystore.createUser( { username:string, password:string } ) -> {} ``` * `username` and `password` can be at most 1024 characters. * Your request will be rejected if `password` is too weak. `password` should be at least 8 characters and contain upper and lower case letters as well as numbers and symbols. **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"keystore.createUser", "params" :{ "username":"myUsername", "password":"myPassword" } }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/keystore ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": {} } ``` ### `keystore.deleteUser` Deprecated as of [v1.9.12](https://github.com/ava-labs/avalanchego/releases/tag/v1.9.12). Delete a user. **Signature**: ``` keystore.deleteUser({ username: string, password:string }) -> {} ``` **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"keystore.deleteUser", "params" : { "username":"myUsername", "password":"myPassword" } }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/keystore ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": {} } ``` ### `keystore.exportUser` Deprecated as of [v1.9.12](https://github.com/ava-labs/avalanchego/releases/tag/v1.9.12). Export a user. The user can be imported to another node with [`keystore.importUser`](https://github.com/api-reference/keystore-api#keystoreimportuser). The user's password remains encrypted. **Signature**: ``` keystore.exportUser( { username:string, password:string, encoding:string //optional } ) -> { user:string, encoding:string } ``` `encoding` specifies the format of the string encoding user data. Can only be `hex` when a value is provided. **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"keystore.exportUser", "params" :{ "username":"myUsername", "password":"myPassword" } }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/keystore ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": { "user": "7655a29df6fc2747b0874e1148b423b954a25fcdb1f170d0ec8eb196430f7001942ce55b02a83b1faf50a674b1e55bfc00000000", "encoding": "hex" } } ``` ### `keystore.importUser` Deprecated as of [v1.9.12](https://github.com/ava-labs/avalanchego/releases/tag/v1.9.12). Import a user. `password` must match the user's password. `username` doesn't have to match the username `user` had when it was exported. **Signature**: ``` keystore.importUser( { username:string, password:string, user:string, encoding:string //optional } ) -> {} ``` `encoding` specifies the format of the string encoding user data. Can only be `hex` when a value is provided. **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"keystore.importUser", "params" :{ "username":"myUsername", "password":"myPassword", "user" :"0x7655a29df6fc2747b0874e1148b423b954a25fcdb1f170d0ec8eb196430f7001942ce55b02a83b1faf50a674b1e55bfc000000008cf2d869" } }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/keystore ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": {} } ``` ### `keystore.listUsers` Deprecated as of [v1.9.12](https://github.com/ava-labs/avalanchego/releases/tag/v1.9.12). List the users in this keystore. **Signature**: ``` keystore.ListUsers() -> { users: []string } ``` **Example Call**: ```sh curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"keystore.listUsers" }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/keystore ``` **Example Response**: ```json { "jsonrpc": "2.0", "id": 1, "result": { "users": ["myUsername"] } } ``` # Metrics API URL: /docs/api-reference/metrics-api This page is an overview of the Metrics API associated with AvalancheGo. The Metrics API allows clients to get statistics about a node's health and performance. This API set is for a specific node, it is unavailable on the [public server](https://build.avax.network/docs/tooling/rpc-providers). ## Endpoint ``` /ext/metrics ``` ## Usage To get the node metrics: ```sh curl -X POST 127.0.0.1:9650/ext/metrics ``` ## Format This API produces Prometheus compatible metrics. See [here](https://prometheus.io/docs/instrumenting/exposition_formats) for information on Prometheus' formatting. [Here](https://build.avax.network/docs/nodes/maintain/monitoring) is a tutorial that shows how to set up Prometheus and Grafana to monitor AvalancheGo node using the Metrics API. # Subnet-EVM API URL: /docs/api-reference/subnet-evm-api This page describes the API endpoints available for Subnet-EVM based blockchains. [Subnet-EVM](https://github.com/ava-labs/subnet-evm) APIs are identical to [Coreth](https://build.avax.network/docs/api-reference/c-chain/api) C-Chain APIs, except Avalanche Specific APIs starting with `avax`. Subnet-EVM also supports standard Ethereum APIs as well. For more information about Coreth APIs see [GitHub](https://github.com/ava-labs/coreth). Subnet-EVM has some additional APIs that are not available in Coreth. ## `eth_feeConfig` Subnet-EVM comes with an API request for getting fee config at a specific block. You can use this API to check your activated fee config. **Signature:** ```bash eth_feeConfig([blk BlkNrOrHash]) -> {feeConfig: json} ``` * `blk` is the block number or hash at which to retrieve the fee config. Defaults to the latest block if omitted. **Example Call:** ```bash curl -X POST --data '{ "jsonrpc": "2.0", "method": "eth_feeConfig", "params": [ "latest" ], "id": 1 }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/2ebCneCbwthjQ1rYT41nhd7M76Hc6YmosMAQrTFhBq8qeqh6tt/rpc ``` **Example Response:** ```json { "jsonrpc": "2.0", "id": 1, "result": { "feeConfig": { "gasLimit": 15000000, "targetBlockRate": 2, "minBaseFee": 33000000000, "targetGas": 15000000, "baseFeeChangeDenominator": 36, "minBlockGasCost": 0, "maxBlockGasCost": 1000000, "blockGasCostStep": 200000 }, "lastChangedAt": 0 } } ``` ## `eth_getChainConfig` `eth_getChainConfig` returns the Chain Config of the blockchain. This API is enabled by default with `internal-blockchain` namespace. This API exists on the C-Chain as well, but in addition to the normal Chain Config returned by the C-Chain `eth_getChainConfig` on `subnet-evm` additionally returns the upgrade config, which specifies network upgrades activated after the genesis. **Signature:** ```bash eth_getChainConfig({}) -> {chainConfig: json} ``` **Example Call:** ```bash curl -X POST --data '{ "jsonrpc":"2.0", "id" :1, "method" :"eth_getChainConfig", "params" :[] }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/Nvqcm33CX2XABS62iZsAcVUkavfnzp1Sc5k413wn5Nrf7Qjt7/rpc ``` **Example Response:** ```json { "jsonrpc": "2.0", "id": 1, "result": { "chainId": 43214, "feeConfig": { "gasLimit": 8000000, "targetBlockRate": 2, "minBaseFee": 33000000000, "targetGas": 15000000, "baseFeeChangeDenominator": 36, "minBlockGasCost": 0, "maxBlockGasCost": 1000000, "blockGasCostStep": 200000 }, "allowFeeRecipients": true, "homesteadBlock": 0, "eip150Block": 0, "eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0", "eip155Block": 0, "eip158Block": 0, "byzantiumBlock": 0, "constantinopleBlock": 0, "petersburgBlock": 0, "istanbulBlock": 0, "muirGlacierBlock": 0, "subnetEVMTimestamp": 0, "contractDeployerAllowListConfig": { "adminAddresses": ["0x8db97c7cece249c2b98bdc0226cc4c2a57bf52fc"], "blockTimestamp": 0 }, "contractNativeMinterConfig": { "adminAddresses": ["0x8db97c7cece249c2b98bdc0226cc4c2a57bf52fc"], "blockTimestamp": 0 }, "feeManagerConfig": { "adminAddresses": ["0x8db97c7cece249c2b98bdc0226cc4c2a57bf52fc"], "blockTimestamp": 0 }, "upgrades": { "precompileUpgrades": [ { "feeManagerConfig": { "adminAddresses": null, "blockTimestamp": 1661541259, "disable": true } }, { "feeManagerConfig": { "adminAddresses": null, "blockTimestamp": 1661541269 } } ] } } } ``` ## `eth_getActivePrecompilesAt` **DEPRECATED—instead use** [`eth_getActiveRulesAt`](#eth_getactiveprecompilesat). `eth_getActivePrecompilesAt` returns activated precompiles at a specific timestamp. If no timestamp is provided it returns the latest block timestamp. This API is enabled by default with `internal-blockchain` namespace. **Signature:** ```bash eth_getActivePrecompilesAt([timestamp uint]) -> {precompiles: []Precompile} ``` * `timestamp` specifies the timestamp to show the precompiles active at this time. If omitted it shows precompiles activated at the latest block timestamp. **Example Call:** ```bash curl -X POST --data '{ "jsonrpc": "2.0", "method": "eth_getActivePrecompilesAt", "params": [], "id": 1 }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/Nvqcm33CX2XABS62iZsAcVUkavfnzp1Sc5k413wn5Nrf7Qjt7/rpc ``` **Example Response:** ```json { "jsonrpc": "2.0", "id": 1, "result": { "contractDeployerAllowListConfig": { "adminAddresses": ["0x8db97c7cece249c2b98bdc0226cc4c2a57bf52fc"], "blockTimestamp": 0 }, "contractNativeMinterConfig": { "adminAddresses": ["0x8db97c7cece249c2b98bdc0226cc4c2a57bf52fc"], "blockTimestamp": 0 }, "feeManagerConfig": { "adminAddresses": ["0x8db97c7cece249c2b98bdc0226cc4c2a57bf52fc"], "blockTimestamp": 0 } } } ``` ## `eth_getActiveRulesAt` `eth_getActiveRulesAt` returns activated rules (precompiles, upgrades) at a specific timestamp. If no timestamp is provided it returns the latest block timestamp. This API is enabled by default with `internal-blockchain` namespace. **Signature:** ```bash eth_getActiveRulesAt([timestamp uint]) -> {rules: json} ``` * `timestamp` specifies the timestamp to show the rules active at this time. If omitted it shows rules activated at the latest block timestamp. **Example Call:** ```bash curl -X POST --data '{ "jsonrpc": "2.0", "method": "eth_getActiveRulesAt", "params": [], "id": 1 }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/Nvqcm33CX2XABS62iZsAcVUkavfnzp1Sc5k413wn5Nrf7Qjt7/rpc ``` **Example Response:** ```json { "jsonrpc": "2.0", "id": 1, "result": { "ethRules": { "IsHomestead": true, "IsEIP150": true, "IsEIP155": true, "IsEIP158": true, "IsByzantium": true, "IsConstantinople": true, "IsPetersburg": true, "IsIstanbul": true, "IsCancun": true }, "avalancheRules": { "IsSubnetEVM": true, "IsDurango": true, "IsEUpgrade": true }, "precompiles": { "contractNativeMinterConfig": { "timestamp": 0 }, "rewardManagerConfig": { "timestamp": 1712918700 }, "warpConfig": { "timestamp": 1714158045 } } } } ``` ## `validators.getCurrentValidators` This API retrieves the list of current validators for the Subnet/L1. It provides detailed information about each validator, including their ID, status, weight, connection, and uptime. URL: `http:///ext/bc//validators` **Signature:** ```bash validators.getCurrentValidators({nodeIDs: []string}) -> {validators: []Validator} ``` * `nodeIDs` is an optional parameter that specifies the node IDs of the validators to retrieve. If omitted, all validators are returned. **Example Call:** ```bash curl -X POST --data '{ "jsonrpc": "2.0", "method": "validators.getCurrentValidators", "params": { "nodeIDs": [] }, "id": 1 }' -H 'content-type:application/json;' 127.0.0.1:9650/ext/bc/C49rHzk3vLr1w9Z8sY7scrZ69TU4WcD2pRS6ZyzaSn9xA2U9F/validators ``` **Example Response:** ```json { "jsonrpc": "2.0", "result": { "validators": [ { "validationID": "nESqWkcNXihfdZESS2idWbFETMzatmkoTCktjxG1qryaQXfS6", "nodeID": "NodeID-P7oB2McjBGgW2NXXWVYjV8JEDFoW9xDE5", "weight": 20, "startTimestamp": 1732025492, "isActive": true, "isL1Validator": false, "isConnected": true, "uptimeSeconds": 36, "uptimePercentage": 100 } ] }, "id": 1 } ``` **Response Fields:** * `validationID`: (string) Unique identifier for the validation. This returns validation ID for L1s, AddSubnetValidator txID for Subnets. * `nodeID`: (string) Node identifier for the validator. * `weight`: (integer) The weight of the validator, often representing stake. * `startTimestamp`: (integer) UNIX timestamp for when validation started. * `isActive`: (boolean) Indicates if the validator is active. This returns true if this is L1 validator and has enough continuous subnet staking fees in P-Chain. It always returns true for subnet validators. * `isL1Validator`: (boolean) Indicates if the validator is a L1 validator or a subnet validator. * `isConnected`: (boolean) Indicates if the validator node is currently connected to the callee node. * `uptimeSeconds`: (integer) The number of seconds the validator has been online. * `uptimePercentage`: (float) The percentage of time the validator has been online. # Getting Started URL: /docs/avalanche-l1s As you begin your Avalanche L1 journey, it's useful to look at the lifecycle of taking an Avalanche L1 from idea to production. ## Figure Out Your Needs The first step of planning your Avalanche L1 is determining your application's needs. What features do you need that the Avalanche C-Chain doesn't provide? ### When to Choose an Avalanche L1 Building your own Avalanche L1 is a great choice when your project demands capabilities beyond those offered by the C-Chain. For instance, if you need the flexibility to use a custom gas token, require strict access control (for example, by only permitting users who are KYC-verified), or wish to implement a unique transaction fee model, then an Avalanche L1 can provide the necessary options. In addition, if having a completely sovereign network with its own governance and consensus mechanisms is central to your vision, an Avalanche L1 is likely the best path forward. ### Decide What Type of Avalanche L1 You Want After confirming that an Avalanche L1 suits your project's requirements, the next step is to select the type of virtual machine (VM) that will power your blockchain. Broadly, you can choose among three options. #### EVM-Based Avalanche L1s The majority of Avalanche L1s are utilizing the Ethereum Virtual Machine. They support Solidity smart contracts and standard [Ethereum APIs](/docs/api-reference/c-chain/api#ethereum-apis). Ava Labs' implementation, [Subnet-EVM](https://github.com/ava-labs/subnet-evm), is the most mature option available. It is recognized for its robust developer tooling and regular updates, making it the safest and most popular choice for building your blockchain. #### Custom Avalanche L1s Custom Avalanche L1s offer an open-ended interface that enables you to build any virtual machine you envision. Whether you fork an existing VM such as Subnet-EVM, integrate a non-Avalanche-native VM like Solana's, or build a completely new VM using any programming language you prefer, the choice is yours. For guidance on how to get started with VM development, see [Introduction to VMs](/docs/virtual-machines). ### Determine Tokenomics Avalanche L1s are powered by gas tokens, and building your own blockchain gives you the flexibility to determine which token to use and how to distribute it. Whether you decide to leverage AVAX, adapt an existing C-Chain token, or launch a new token entirely, you'll need to plan the allocation of tokens for validator rewards, establish an emission schedule, and decide whether transaction fees should be burned or redistributed as block rewards. ### Decide how to Customize Your Avalanche L1 Once you have selected your virtual machine, further customization may be necessary to align the blockchain with your specific needs. This might involve configuring the token allocation in the genesis block, setting gas fee rates, or making changes to the VM's behavior through precompiles. Such customizations often require careful iterative testing to perfect. For detailed instructions, refer to [Customize Your EVM-Powered Avalanche L1](/docs/avalanche-l1s/upgrade/customize-avalanche-l1). ### Available Subnet-EVM Precompiles The Subnet-EVM provides several precompiled contracts that you can use in your Avalanche L1 blockchain: * [AllowList Interface](/docs/avalanche-l1s/evm-configuration/allowlist) - A reusable interface for permission management * [Permissions](/docs/avalanche-l1s/evm-configuration/permissions) - Control contract deployment and transaction submission * [Tokenomics](/docs/avalanche-l1s/evm-configuration/tokenomics) - Manage native token supply and minting * [Transaction Fees & Validator Rewards](/docs/avalanche-l1s/evm-configuration/transaction-fees) - Configure fee parameters and reward mechanisms * [Warp Messenger](/docs/avalanche-l1s/evm-configuration/warpmessenger) - Perform cross-chain operations # WAGMI Avalanche L1 URL: /docs/avalanche-l1s/wagmi-avalanche-l1 Learn about the WAGMI Avalanche L1 in this detailed case study. This is one of the first cases of using Avalanche L1s as a proving ground for changes in a production VM (Coreth). Many underestimate how useful the isolation of Avalanche L1s is for performing complex VM testing on a live network (without impacting the stability of the primary network). We created a basic WAGMI Explorer [https://subnets-test.avax.network/wagmi](https://subnets-test.avax.network/wagmi) that surfaces aggregated usage statistics about the Avalanche L1. * SubnetID: [28nrH5T2BMvNrWecFcV3mfccjs6axM1TVyqe79MCv2Mhs8kxiY](https://explorer-xp.avax-test.network/avalanche-l1/28nrH5T2BMvNrWecFcV3mfccjs6axM1TVyqe79MCv2Mhs8kxiY?tab=validators) * ChainID: [2ebCneCbwthjQ1rYT41nhd7M76Hc6YmosMAQrTFhBq8qeqh6tt](https://testnet.avascan.info/blockchain/2ebCneCbwthjQ1rYT41nhd7M76Hc6YmosMAQrTFhBq8qeqh6tt) ### Network Parameters[​](#network-parameters "Direct link to heading") * NetworkID: 11111 * ChainID: 11111 * Block Gas Limit: 20,000,000 (2.5x C-Chain) * 10s Gas Target: 100,000,000 (\~6.67x C-Chain) * Min Fee: 1 Gwei (4% of C-Chain) * Target Block Rate: 2s (Same as C-Chain) The genesis file of WAGMI can be found [here](https://github.com/ava-labs/public-chain-assets/blob/1951594346dcc91682bdd8929bcf8c1bf6a04c33/chains/11111/genesis.json). ### Adding WAGMI to Core[​](#adding-wagmi-to-core "Direct link to heading") * Network Name: WAGMI * RPC URL: \[[https://subnets.avax.network/wagmi/wagmi-chain-testnet/rpc](https://subnets.avax.network/wagmi/wagmi-chain-testnet/rpc)] * WS URL: wss\://avalanche-l1s.avax.network/wagmi/wagmi-chain-testnet/ws * Chain ID: 11111 * Symbol: WGM * Explorer: \[[https://subnets.avax.network/wagmi/wagmi-chain-testnet/explorer](https://subnets.avax.network/wagmi/wagmi-chain-testnet/explorer)] This can be used with other wallets too, such as MetaMask. ## Case Study: WAGMI Upgrades[​](#case-study-wagmi-upgrades "Direct link to heading") This case study uses [WAGMI](https://subnets-test.avax.network/wagmi) Avalanche L1 upgrade to show how a network upgrade on an EVM-based (Ethereum Virtual Machine) Avalanche L1 can be done simply, and how the resulting upgrade can be used to dynamically control fee structure on the Avalanche L1. ### Introduction[​](#introduction "Direct link to heading") [Subnet-EVM](https://github.com/ava-labs/subnet-evm) aims to provide an easy to use toolbox to customize the EVM for your blockchain. It is meant to run out of the box for many Avalanche L1s without any modification. But what happens when you want to add a new feature updating the rules of your EVM? Instead of hard coding the timing of network upgrades in client code like most EVM chains, requiring coordinated deployments of new code, [Subnet-EVM v0.2.8](https://github.com/ava-labs/subnet-evm/releases/tag/v0.2.8) introduces the long awaited feature to perform network upgrades by just using a few lines of JSON in a configuration file. ### Network Upgrades: Enable/Disable Precompiles[​](#network-upgrades-enabledisable-precompiles "Direct link to heading") Detailed description of how to do this can be found in [Customize an Avalanche L1](/docs/avalanche-l1s/upgrade/customize-avalanche-l1#network-upgrades-enabledisable-precompiles) tutorial. Here's a summary: 1. Network Upgrade utilizes existing precompiles on the Subnet-EVM: * ContractDeployerAllowList, for restricting smart contract deployers * TransactionAllowList, for restricting who can submit transactions * NativeMinter, for minting native coins * FeeManager, for configuring dynamic fees * RewardManager, for enabling block rewards 2. Each of these precompiles can be individually enabled or disabled at a given timestamp as a network upgrade, or any of the parameters governing its behavior changed. 3. These upgrades must be specified in a file named `upgrade.json` placed in the same directory where [`config.json`](/docs/avalanche-l1s/upgrade/customize-avalanche-l1#avalanchego-chain-configs) resides: `{chain-config-dir}/{blockchainID}/upgrade.json`. ### Preparation[​](#preparation "Direct link to heading") To prepare for the first WAGMI network upgrade, on August 15, 2022, we had announced on [Twitter](https://twitter.com/AaronBuchwald/status/1559249414102720512) and shared on other social media such as Discord. For the second upgrade, on February 24, 2024, we had another announcement on [X](https://x.com/jceyonur/status/1760777031858745701?s=20). ### Deploying upgrade.json[​](#deploying-upgradejson "Direct link to heading") The content of the `upgrade.json` is: ```json { "precompileUpgrades": [ { "feeManagerConfig": { "adminAddresses": ["0x6f0f6DA1852857d7789f68a28bba866671f3880D"], "blockTimestamp": 1660658400 } }, { "contractNativeMinterConfig": { "blockTimestamp": 1708696800, "adminAddresses": ["0x6f0f6DA1852857d7789f68a28bba866671f3880D"], "managerAddresses": ["0xadFA2910DC148674910c07d18DF966A28CD21331"] } } ] } ``` With the above `upgrade.json`, we intend to perform two network upgrades: 1. The first upgrade is to activate the FeeManager precompile: * `0x6f0f6DA1852857d7789f68a28bba866671f3880D` is named as the new Admin of the FeeManager precompile. * `1660658400` is the [Unix timestamp](https://www.unixtimestamp.com/) for Tue Aug 16 2022 14:00:00 GMT+0000 (future time when we made the announcement) when the new FeeManager change would take effect. 2. The second upgrade is to activate the NativeMinter precompile: * `0x6f0f6DA1852857d7789f68a28bba866671f3880D` is named as the new Admin of the NativeMinter precompile. * `0xadFA2910DC148674910c07d18DF966A28CD21331` is named as the new Manager of the NativeMinter precompile. Manager addresses are enabled after Durango upgrades which occurred on February 13, 2024. * `1708696800` is the [Unix timestamp](https://www.unixtimestamp.com/) for Fri Feb 23 2024 14:00:00 GMT+0000 (future time when we made the announcement) when the new NativeMinter change would take effect. Detailed explanations of feeManagerConfig can be found in [here](/docs/avalanche-l1s/upgrade/customize-avalanche-l1#configuring-dynamic-fees), and for the contractNativeMinterConfig in [here](/docs/avalanche-l1s/upgrade/customize-avalanche-l1#minting-native-coins). We place the `upgrade.json` file in the chain config directory, which in our case is `~/.avalanchego/configs/chains/2ebCneCbwthjQ1rYT41nhd7M76Hc6YmosMAQrTFhBq8qeqh6tt/`. After that, we restart the node so the upgrade file is loaded. When the node restarts, AvalancheGo reads the contents of the JSON file and passes it into Subnet-EVM. We see a log of the chain configuration that includes the updated precompile upgrade. It looks like this: ```bash INFO [02-22|18:27:06.473] <2ebCneCbwthjQ1rYT41nhd7M76Hc6YmosMAQrTFhBq8qeqh6tt Chain> github.com/ava-labs/subnet-evm/core/blockchain.go:335: Upgrade Config: {"precompileUpgrades":[{"feeManagerConfig":{"adminAddresses":["0x6f0f6da1852857d7789f68a28bba866671f3880d"],"blockTimestamp":1660658400}},{"contractNativeMinterConfig":{"adminAddresses":["0x6f0f6da1852857d7789f68a28bba866671f3880d"],"managerAddresses":["0xadfa2910dc148674910c07d18df966a28cd21331"],"blockTimestamp":1708696800}}]} ``` We note that `precompileUpgrades` correctly shows the upcoming precompile upgrades. Upgrade is locked in and ready. ### Activations[​](#activations "Direct link to heading") When the time passed 10:00 AM EDT August 16, 2022 (Unix timestamp 1660658400), the `upgrade.json` had been executed as planned and the new FeeManager admin address has been activated. From now on, we don't need to issue any new code or deploy anything on the WAGMI nodes to change the fee structure. Let's see how it works in practice! For the second upgrade on February 23, 2024, the same process was followed. The `upgrade.json` had been executed after Durango, as planned, and the new NativeMinter admin and manager addresses have been activated. ### Using Fee Manager[​](#using-fee-manager "Direct link to heading") The owner `0x6f0f6DA1852857d7789f68a28bba866671f3880D` can now configure the fees on the Avalanche L1 as they see fit. To do that, all that's needed is access to the network, the private key for the newly set manager address and making calls on the precompiled contract. We will use [Remix](https://remix.ethereum.org/) online Solidity IDE and the [Core Browser Extension](https://support.avax.network/en/articles/6066879-core-extension-how-do-i-add-the-core-extension). Core comes with WAGMI network built-in. MetaMask will do as well but you will need to [add WAGMI](/docs/avalanche-l1s/wagmi-avalanche-l1) yourself. First using Core, we open the account as the owner `0x6f0f6DA1852857d7789f68a28bba866671f3880D`. Then we connect Core to WAGMI, Switch on the `Testnet Mode` in `Advanced` page in the hamburger menu: ![Core Testnet mode](/images/wagmi1.png) And then open the `Manage Networks` menu in the networks dropdown. Select WAGMI there by clicking the star icon: ![Core network selection](/images/wagmi2.png) We then switch to WAGMI in the networks dropdown. We are ready to move on to Remix now, so we open it in the browser. First, we check that Remix sees the extension and correctly talks to it. We select `Deploy & run transactions` icon on the left edge, and on the Environment dropdown, select `Injected Provider`. We need to approve the Remix network access in the Core browser extension. When that is done, `Custom (11111) network` is shown: ![Injected provider](/images/wagmi3.png) Good, we're talking to WAGMI Avalanche L1. Next we need to load the contracts into Remix. Using 'load from GitHub' option from the Remix home screen we load two contracts: * [IAllowList.sol](https://github.com/ava-labs/subnet-evm/blob/master/contracts/contracts/interfaces/IAllowList.sol) * and [IFeeManager.sol](https://github.com/ava-labs/subnet-evm/blob/master/contracts/contracts/interfaces/IFeeManager.sol). IFeeManager is our precompile, but it references the IAllowList, so we need that one as well. We compile IFeeManager.sol and use deployed contract at the precompile address `0x0200000000000000000000000000000000000003` used on the [Avalanche L1](https://github.com/ava-labs/subnet-evm/blob/master/precompile/contracts/feemanager/module.go#L21). ![Deployed contract](/images/wagmi4.png) Now we can interact with the FeeManager precompile from within Remix via Core. For example, we can use the `getFeeConfig` method to check the current fee configuration. This action can be performed by anyone as it is just a read operation. Once we have the new desired configuration for the fees on the Avalanche L1, we can use the `setFeeConfig` to change the parameters. This action can **only** be performed by the owner `0x6f0f6DA1852857d7789f68a28bba866671f3880D` as the `adminAddress` specified in the [`upgrade.json` above](#deploying-upgradejson). ![setFeeConfig](/images/wagmi5.png) When we call that method by pressing the `transact` button, a new transaction is posted to the Avalanche L1, and we can see it on [the explorer](https://subnets-test.avax.network/wagmi/block/0xad95ccf04f6a8e018ece7912939860553363cc23151a0a31ea429ba6e60ad5a3): ![transaction](/images/wagmi6.png) Immediately after the transaction is accepted, the new fee config takes effect. We can check with the `getFeeCofig` that the values are reflected in the active fee config (again this action can be performed by anyone): ![getFeeConfig](/images/wagmi7.png) That's it, fees changed! No network upgrades, no complex and risky deployments, just making a simple contract call and the new fee configuration is in place! ### Using NativeMinter[​](#using-nativeminter "Direct link to heading") For the NativeMinter, we can use the same process to connect to the Avalanche L1 and interact with the precompile. We can load INativeMinter interface using 'load from GitHub' option from the Remix home screen with following contracts: * [IAllowList.sol](https://github.com/ava-labs/subnet-evm/blob/master/contracts/contracts/interfaces/IAllowList.sol) * and [INativeMinter.sol](https://github.com/ava-labs/subnet-evm/blob/master/contracts/contracts/interfaces/INativeMinter.sol). We can compile them and interact with the deployed contract at the precompile address `0x0200000000000000000000000000000000000001` used on the [Avalanche L1](https://github.com/ava-labs/subnet-evm/blob/master/precompile/contracts/nativeminter/module.go#L22). ![Deployed contract](/images/wagmi8.png) The native minter precompile is used to mint native coins to specified addresses. The minted coins is added to the current supply and can be used by the recipient to pay for gas fees. For more information about the native minter precompile see [here](/docs/avalanche-l1s/upgrade/customize-avalanche-l1#minting-native-coins). `mintNativeCoin` method can be only called by enabled, manager and admin addresses. For this upgrade we have added both an admin and a manager address in [`upgrade.json` above](#deploying-upgradejson). The manager address was available after Durango upgrades which occurred on February 13, 2024. We will use the manager address `0xadfa2910dc148674910c07d18df966a28cd21331` to mint native coins. ![mintNativeCoin](/images/wagmi9.png) When we call that method by pressing the `transact` button, a new transaction is posted to the Avalanche L1, and we can see it on [the explorer](https://subnets-test.avax.network/wagmi/tx/0xc4aaba7b5863c1b8f6664ac1d483e2d7d392ab58d1a8feb0b6c318cbae7f1e93): ![tx](/images/wagmi10.png) As a result of this transaction, the native minter precompile minted a new native coin (1 WGM) to the recipient address `0xB78cbAa319ffBD899951AA30D4320f5818938310`. The address page on the explorer [here](https://subnets-test.avax.network/wagmi/address/0xB78cbAa319ffBD899951AA30D4320f5818938310) shows no incoming transaction; this is because the 1 WGM was directly minted by the EVM itself, without any sender. ### Conclusion[​](#conclusion "Direct link to heading") Network upgrades can be complex and perilous procedures to carry out safely. Our continuing efforts with Avalanche L1s is to make upgrades as painless and simple as possible. With the powerful combination of stateful precompiles and network upgrades via the upgrade configuration files we have managed to greatly simplify both the network upgrades and network parameter changes. This in turn enables much safer experimentation and many new use cases that were too risky and complex to carry out with high-coordination efforts required with the traditional network upgrade mechanisms. We hope this case study will help spark ideas for new things you may try on your own. We're looking forward to seeing what you have built and how easy upgrades help you in managing your Avalanche L1s! If you have any questions or issues, feel free to contact us on our [Discord](https://chat.avalabs.org/). Or just reach out to tell us what exciting new things you have built! # Why Build Avalanche L1s URL: /docs/avalanche-l1s/when-to-build-avalanche-l1 Learn key concepts to decide when to build your own Avalanche L1. ## Why Build Your Own Avalanche L1 There are many advantages to running your own Avalanche L1. If you find one or more of these a good match for your project then an Avalanche L1 might be a good solution for you. ### We Want Our Own Gas Token C-Chain is an Ethereum Virtual Machine (EVM) chain; it requires the gas fees to be paid in its native token. That is, the application may create its own utility tokens (ERC-20) on the C-Chain, but the gas must be paid in AVAX. In the meantime, [Subnet-EVM](https://github.com/ava-labs/subnet-evm) effectively creates an application-specific EVM-chain with full control over native(gas) coins. The operator can pre-allocate the native tokens in the chain genesis, and mint more using the [Subnet-EVM](https://github.com/ava-labs/subnet-evm) precompile contract. And these fees can be either burned (as AVAX burns in C-Chain) or configured to be sent to an address which can be a smart contract. Note that the Avalanche L1 gas token is specific to the application in the chain, thus unknown to the external parties. Moving assets to other chains requires trusted bridge contracts (or upcoming cross Avalanche L1 communication feature). ### We Want Higher Throughput The primary goal of the gas limit on C-Chain is to restrict the block size and therefore prevent network saturation. If a block can be arbitrarily large, it takes longer to propagate, potentially degrading the network performance. The C-Chain gas limit acts as a deterrent against any system abuse but can be quite limiting for high throughput applications. Unlike C-Chain, Avalanche L1 can be single-tenant, dedicated to the specific application, and thus host its own set of validators with higher bandwidth requirements, which allows for a higher gas limit thus higher transaction throughput. Plus, [Subnet-EVM](https://github.com/ava-labs/subnet-evm) supports fee configuration upgrades that can be adaptive to the surge in application traffic. Avalanche L1 workloads are isolated from the Primary Network; which means, the noisy neighbor effect of one workload (for example NFT mint on C-Chain) cannot destabilize the Avalanche L1 or surge its gas price. This failure isolation model in the Avalanche L1 can provide higher application reliability. ### We Want Strict Access Control The C-Chain is open and permissionless where anyone can deploy and interact with contracts. However, for regulatory reasons, some applications may need a consistent access control mechanism for all on-chain transactions. With [Subnet-EVM](https://github.com/ava-labs/subnet-evm), an application can require that “only authorized users may deploy contracts or make transactions.” Allow-lists are only updated by the administrators, and the allow list itself is implemented within the precompile contract, thus more transparent and auditable for compliance matters. ### We Need EVM Customization If your project is deployed on the C-Chain then your execution environment is dictated by the setup of the C-Chain. Changing any of the execution parameters means that the configuration of the C-Chain would need to change, and that is expensive, complex and difficult to change. So if your project needs some other capabilities, different execution parameters or precompiles that C-Chain does not provide, then Avalanche L1s are a solution you need. You can configure the EVM in an Avalanche L1 to run however you want, adding precompiles, and setting runtime parameters to whatever your project needs. ### We Need Custom Validator Management With the Etna upgrade, L1s can implement their own validator management logic through a *ValidatorManager* smart contract. This gives you complete control over your validator set, allowing you to define custom staking rules, implement permissionless proof-of-stake with your own token, or create permissioned proof-of-authority networks. The validator management can be handled directly through smart contracts, giving you programmatic control over validator selection and rewards distribution. ### We Want to Build a Sovereign Network L1s on Avalanche are truly sovereign networks that operate independently without relying on other systems. You have complete control over your network's consensus mechanisms, transaction processing, and security protocols. This independence allows you to scale horizontally without dependencies on other networks while maintaining full control over your network parameters and upgrades. This sovereignty is particularly important for projects that need complete autonomy over their blockchain's operation and evolution. ## Conclusion Here we presented some considerations in favor of running your own Avalanche L1 vs. deploying on the C-Chain. If an application has relatively low transaction rate and no special circumstances that would make the C-Chain a non-starter, you can begin with C-Chain deployment to leverage existing technical infrastructure, and later expand to an Avalanche L1. That way you can focus on working on the core of your project and once you have a solid product/market fit and have gained enough traction that the C-Chain is constricting you, plan a move to your own Avalanche L1. Of course, we're happy to talk to you about your architecture and help you choose the best path forward. Feel free to reach out to us on [Discord](https://chat.avalabs.org/) or other [community channels](https://www.avax.network/community) we run. # Asset Requirements URL: /docs/builderkit/asset-requirements Required assets and file structure for chain and token logos. # Asset Requirements BuilderKit requires specific asset files for displaying chain and token logos. These assets should follow a standardized file structure and naming convention. ## Chain Logos Chain logos are used by components like `ChainIcon`, `ChainDropdown`, and `TokenIconWithChain`. ### File Structure Chain logos should be placed at: ``` /chains/logo/{chain_id}.png ``` ### Examples ``` /chains/logo/43114.png // Avalanche C-Chain /chains/logo/43113.png // Fuji Testnet /chains/logo/173750.png // Echo L1 ``` ### Requirements * Format: PNG with transparency * Dimensions: 32x32px (minimum) * Background: Transparent * Shape: Circular or square with rounded corners * File size: \< 100KB ## Token Logos Token logos are used by components like `TokenIcon`, `TokenChip`, and `TokenRow`. ### File Structure Token logos should be placed at: ``` /tokens/logo/{chain_id}/{address}.png ``` ### Examples ``` /tokens/logo/43114/0x1234567890123456789012345678901234567890.png // Token on C-Chain /tokens/logo/43113/0x5678901234567890123456789012345678901234.png // Token on Fuji ``` ### Requirements * Format: PNG with transparency * Dimensions: 32x32px (minimum) * Background: Transparent * Shape: Circular or square with rounded corners * File size: \< 100KB ## Directory Structure Your public assets directory should look like this: ``` public/ ├── chains/ │ └── logo/ │ ├── 43114.png │ ├── 43113.png │ └── 173750.png └── tokens/ └── logo/ ├── 43114/ │ ├── 0x1234....png │ └── 0x5678....png └── 43113/ ├── 0x9012....png └── 0xabcd....png ``` # Custom Chain Setup URL: /docs/builderkit/chains Configure custom Avalanche L1 chains in your application. # Custom Chain Setup Learn how to configure custom Avalanche L1 chains in your BuilderKit application. ## Chain Definition Define your custom L1 chain using `viem`'s `defineChain`: ```tsx import { defineChain } from "viem"; export const myL1 = defineChain({ id: 173750, // Your L1 chain ID name: 'My L1', // Display name network: 'my-l1', // Network identifier nativeCurrency: { decimals: 18, name: 'Token', symbol: 'TKN', }, rpcUrls: { default: { http: ['https://api.avax.network/ext/L1/rpc'] }, }, blockExplorers: { default: { name: 'Explorer', url: 'https://explorer.avax.network/my-l1' }, }, // Optional: Custom metadata iconUrl: "/chains/logo/my-l1.png", icm_registry: "0x..." // ICM registry contract }); ``` ## Provider Configuration Add your custom L1 chain to the Web3Provider: ```tsx import { Web3Provider } from '@avalabs/builderkit'; import { avalanche } from '@wagmi/core/chains'; import { myL1 } from './chains/definitions/my-l1'; function App() { return ( ); } ``` ## Required Properties | Property | Type | Description | | ---------------- | -------- | ---------------------------- | | `id` | `number` | Unique L1 chain identifier | | `name` | `string` | Human-readable chain name | | `network` | `string` | Network identifier | | `nativeCurrency` | `object` | Chain's native token details | | `rpcUrls` | `object` | RPC endpoint configuration | | `blockExplorers` | `object` | Block explorer URLs | ## Optional Properties | Property | Type | Description | | -------------- | --------- | ------------------------------ | | `iconUrl` | `string` | Chain logo URL | | `icm_registry` | `string` | ICM registry contract address | | `testnet` | `boolean` | Whether the chain is a testnet | ## Example: Echo L1 Here's a complete example using the Echo L1: ```tsx import { defineChain } from "viem"; export const echo = defineChain({ id: 173750, name: 'Echo L1', network: 'echo', nativeCurrency: { decimals: 18, name: 'Ech', symbol: 'ECH', }, rpcUrls: { default: { http: ['https://subnets.avax.network/echo/testnet/rpc'] }, }, blockExplorers: { default: { name: 'Explorer', url: 'https://subnets-test.avax.network/echo' }, }, iconUrl: "/chains/logo/173750.png", icm_registry: "0xF86Cb19Ad8405AEFa7d09C778215D2Cb6eBfB228" }); ``` # Contribute URL: /docs/builderkit/contribute Guide for contributing to BuilderKit by building hooks, components, and flows. # Contributing to BuilderKit We welcome contributions to BuilderKit! Whether you're fixing bugs, adding new features, or improving documentation, your help makes BuilderKit better for everyone. ## What You Can Contribute ### Hooks Build reusable hooks that handle common Web3 functionality: * Chain data management * Token interactions * Contract integrations * State management * API integrations ### Components Create new UI components or enhance existing ones: * Form elements * Display components * Interactive elements * Layout components * Utility components ### Flows Design complete user journeys by combining components: * Token swaps * NFT minting * Governance voting * Staking interfaces * Custom protocols # Getting Started URL: /docs/builderkit/getting-started Quick setup guide for BuilderKit in your React application. Get started with BuilderKit in your React application. ## Installation ```bash npm install @avalabs/builderkit # or yarn add @avalabs/builderkit ``` ## Provider Setup Wrap your application with the Web3Provider to enable wallet connections and chain management: ```tsx import { Web3Provider } from '@avalabs/builderkit'; import { avalanche, avalancheFuji } from '@wagmi/core/chains'; import { echo } from './chains/definitions/echo'; import { dispatch } from './chains/definitions/dispatch'; // Configure chains const chains = [avalanche, avalancheFuji, echo, dispatch]; function App() { return ( ); } ``` ## Next Steps * Learn about [Token Configuration](/docs/builderkit/tokens) * Explore [Core Components](/docs/builderkit/components/control) * Check out [Pre-built Flows](/docs/builderkit/flows/ictt) # Introduction URL: /docs/builderkit A comprehensive React component library for building Web3 applications on Avalanche. BuilderKit is a powerful collection of React components and hooks designed specifically for building Web3 applications on Avalanche. It provides everything you need to create modern, user-friendly blockchain applications with minimal effort. ## Ready to Use Components BuilderKit offers a comprehensive set of components that handle common Web3 functionalities: * **Control Components**: Buttons, forms, and wallet connection interfaces * **Identity Components**: Address displays and domain name resolution * **Token Components**: Balance displays, inputs, and price conversions * **Input Components**: Specialized form inputs for Web3 data types * **Chain Components**: Network selection and chain information displays * **Transaction Components**: Transaction submission and status tracking * **Collectibles Components**: NFT displays and collection management ## Powerful Hooks BuilderKit provides hooks for seamless integration with Avalanche's ecosystem: ### Blockchain Interaction Access and manage blockchain data, tokens, and cross-chain operations with hooks for chains, tokens, DEX interactions, and inter-chain transfers. ### Precompile Integration Easily integrate with Avalanche's precompiled contracts for access control, fee management, native minting, rewards, and cross-chain messaging. ## Getting Started Get started quickly by installing BuilderKit in your React application: ```bash npm install @avalabs/builderkit # or yarn add @avalabs/builderkit ``` Check out our [Getting Started](/docs/builderkit/getting-started) guide to begin building your Web3 application. # Token Configuration URL: /docs/builderkit/tokens Guide for configuring tokens in BuilderKit flows. # Token Configuration BuilderKit flows require proper token configuration to function correctly. This guide explains the required fields for different token configurations. ## Basic Token Structure All tokens in BuilderKit share a common base structure with these required fields: ```typescript interface BaseToken { // Contract address of the token, use "native" for native chain token address: string; // Human-readable name of the token name: string; // Token symbol/ticker symbol: string; // Number of decimal places the token uses decimals: number; // ID of the chain where this token exists chain_id: number; } ``` ## ICTT Token Fields ICTT tokens extend the base structure with additional fields for cross-chain functionality: ```typescript interface ICTTToken extends BaseToken { // Whether this token can be used with ICTT supports_ictt: boolean; // Address of the contract that handles transfers transferer?: string; // Whether this token instance is a transferer is_transferer?: boolean; // Information about corresponding tokens on other chains mirrors: { // Contract address of the mirrored token address: string; // Transferer contract on the mirror chain transferer: string; // Chain ID where the mirror exists chain_id: number; // Decimal places of the mirrored token decimals: number; // Whether this is the home/original chain home?: boolean; }[]; } ``` ## Field Requirements ### Base Token Fields * `address`: Must be a valid contract address or "native" * `name`: Should be human-readable * `symbol`: Should match the token's trading symbol * `decimals`: Must match the token's contract configuration * `chain_id`: Must be a valid chain ID ### ICTT-Specific Fields * `supports_ictt`: Required for ICTT functionality * `transferer`: Required if token supports ICTT * `is_transferer`: Optional, indicates if token is a transferer * `mirrors`: Required for ICTT, must contain at least one mirror configuration ### Mirror Configuration Fields * `address`: Required, contract address on mirror chain * `transferer`: Required, transferer contract on mirror chain * `chain_id`: Required, must be different from token's chain\_id * `decimals`: Required, must match token contract * `home`: Optional, indicates original/home chain # Introduction URL: /docs/cross-chain Learn about different interoperability protocols in the Avalanche ecosystem. # When to Build on C-Chain URL: /docs/dapps/c-chain-or-avalanche-l1 Learn key concepts to decide when to build on the Avalanche C-Chain. Here are some advantages of the Avalanche C-Chain that you should take into account. ## High Composability with C-Chain Assets[​](#we-want-high-composability-with-c-chain-assets "Direct link to heading") C-Chain is a better option for seamless integration with existing C-Chain assets and contracts. It is easier to build a DeFi application on C-Chain, as it provides larger liquidity pools and thus allows for efficient exchange between popular assets. ## Low Initial Cost[​](#we-want-low-initial-cost "Direct link to heading") C-Chain has economic advantages of low-cost deployment and cheap transactions. The recent Etna upgrade trim down the base fee of Avalanche C-Chain by 25x, which results in much lower transaction costs. ## Low Operational Costs[​](#we-want-low-operational-costs "Direct link to heading") C-Chain is run and operated by thousands of nodes, it is highly decentralized and reliable, and all the infrastructure (explorers, indexers, exchanges, bridges) has already been built out by dedicated teams that maintain them for you at no extra charge. Project deployed on the C-Chain can leverage all of that basically for free. ## High Security[​](#we-want-high-security "Direct link to heading") The security of Avalanche Primary Network is a function of the security of the underlying validators and stake delegators. You can choose C-Chain in order to achieve maximum security by utilizing thousands of Avalanche Primary Network validators. ## Conclusion If an application has relatively low transaction rate and no special circumstances that would make the C-Chain a non-starter, you can begin with C-Chain deployment to leverage existing technical infrastructure, and later expand to an Avalanche L1. That way you can focus on working on the core of your project and once you have a solid product/market fit and have gained enough traction that the C-Chain is constricting you, plan a move to your own Avalanche L1. Of course, we're happy to talk to you about your architecture and help you choose the best path forward. Feel free to reach out to us on [Discord](https://chat.avalabs.org/) or other [community channels](https://www.avax.network/community) we run. # Introduction URL: /docs/dapps Learn about the Avalanche C-Chain. Avalanche is a [network of networks](/docs/quick-start/primary-network). One of the chains running on Avalanche Primary Network is an EVM fork called the C-Chain (contract chain). C-Chain runs a fork of [`go-ethereum`](https://geth.ethereum.org/docs/rpc/server) called [`coreth`](https://github.com/ava-labs/coreth) that has the networking and consensus portions replaced with Avalanche equivalents. What's left is the Ethereum VM, which runs Solidity smart contracts and manages data structures and blocks on the chain. As a result, you get a blockchain that can run all the Solidity smart contracts from Ethereum, but with much greater transaction bandwidth and instant finality that [Avalanche's revolutionary consensus](/docs/quick-start/avalanche-consensus) enables. Coreth is loaded as a plugin into [AvalancheGo](https://github.com/ava-labs/avalanchego), the client node application used to run Avalanche network. Any dApp deployed to Avalanche C-Chain will function the same as on Ethereum, but much faster and cheaper. ## Add C-Chain to Wallet ### Avalanche C-Chain Mainnet * **Network Name**: Avalanche Mainnet C-Chain * **RPC URL**: [https://api.avax.network/ext/bc/C/rpc](https://api.avax.network/ext/bc/C/rpc) * **WebSocket URL**: wss\://api.avax.network/ext/bc/C/ws * **ChainID**: `43114` * **Symbol**: `AVAX` * **Explorer**: [https://subnets.avax.network/c-chain](https://subnets.avax.network/c-chain) ### Avalanche Fuji Testnet * **Network Name**: Avalanche Fuji C-Chain * **RPC URL**: [https://api.avax-test.network/ext/bc/C/rpc](https://api.avax-test.network/ext/bc/C/rpc) * **WebSocket URL**: wss\://api.avax-test.network/ext/bc/C/ws * **ChainID**: `43113` * **Symbol**: `AVAX` * **Explorer**: [https://subnets-test.avax.network/c-chain](https://subnets-test.avax.network/c-chain) ### Via Block Explorers Head to either explorer linked above and select "Add Avalanche C-Chain to Wallet" under "Chain Info" to automatically add the network. Alternatively, visit [chainlist.org](https://chainlist.org/?search=Avalanche\&testnets=true) and connect your wallet. # Avalanche Community Proposals URL: /docs/quick-start/avalanche-community-proposals Learn about community proposals and how to create them. An Avalanche Community Proposal is a concise document that introduces a change or best practice for adoption on the [Avalanche Network](https://www.avax.network/). ACPs should provide clear technical specifications of any proposals and a compelling rationale for their adoption. ACPs are an open framework for proposing improvements and gathering consensus around changes to the Avalanche Network. ACPs can be proposed by anyone and will be merged into this repository as long as they are well-formatted and coherent. Once an overwhelming majority of the Avalanche Network/Community have [signaled their support for an ACP](/docs/nodes/configure/configs-flags#avalanche-community-proposals), it may be scheduled for activation on the Avalanche Network by Avalanche Network Clients (ANCs). It is ultimately up to members of the Avalanche Network/Community to adopt ACPs they support by running a compatible ANC, such as [AvalancheGo](https://github.com/ava-labs/avalanchego). ## ACP Tracks There are three kinds of ACP: * A `Standards Track` ACP describes a change to the design or function of the Avalanche Network, such as a change to the P2P networking protocol, P-Chain design, Avalanche L1 architecture, or any change/addition that affects the interoperability of Avalanche Network Clients (ANCs). * A `Best Practices Track` ACP describes a design pattern or common interface that should be used across the Avalanche Network to make it easier to integrate with Avalanche or for Avalanche L1s to interoperate with each other. This would include things like proposing a smart contract interface, not proposing a change to how smart contracts are executed. * A `Meta Track` ACP describes a change to the ACP process or suggests a new way for the Avalanche Community to collaborate. * A `Subnet Track` ACP describes a change to a particular Avalanche L1. This would include things like configuration changes or coordinated Layer 1 upgrades. ## ACP Statuses There are four statuses of an ACP: * A `Proposed` ACP has been merged into the main branch of the ACP repository. It is actively being discussed by the Avalanche Community and may be modified based on feedback. * An `Implementable` ACP is considered "ready for implementation" by the author and will no longer change meaningfully from its current form (which would require a new ACP). * An `Activated` ACP has been activated on the Avalanche Network via a coordinated upgrade by the Avalanche Community. Once an ACP is `Activated`, it is locked. * A `Stale` ACP has been abandoned by its author because it is not supported by the Avalanche Community or has been replaced with another ACP. ## ACP Workflow ### Step 0: Think of a Novel Improvement to Avalanche The ACP process begins with a new idea for Avalanche. Each potential ACP must have an author: someone who writes the ACP using the style and format described below, shepherds the associated GitHub Discussion, and attempts to build consensus around the idea. Note that ideas and any resulting ACP is public. Authors should not post any ideas or anything in an ACP that the Author wants to keep confidential or to keep ownership rights in (such as intellectual property rights). ### Step 1: Post Your Idea to [GitHub Discussions](https://github.com/avalanche-foundation/ACPs/discussions/categories/ideas) The author should first attempt to ascertain whether there is support for their idea by posting in the "Ideas" category of GitHub Discussions. Vetting an idea publicly before going as far as writing an ACP is meant to save both the potential author and the wider Avalanche Community time. Asking the Avalanche Community first if an idea is original helps prevent too much time being spent on something that is guaranteed to be rejected based on prior discussions (searching the Internet does not always do the trick). It also helps to make sure the idea is applicable to the entire community and not just the author. Small enhancements or patches often don't need standardization between multiple projects; these don't need an ACP and should be injected into the relevant development workflow with a patch submission to the applicable ANC issue tracker. ### Step 2: Propose an ACP via [Pull Request](https://github.com/avalanche-foundation/ACPs/pulls) Once the author feels confident that an idea has a decent chance of acceptance, an ACP should be drafted and submitted as a pull request (PR). This draft must be written in ACP style as described below. It is highly recommended that a single ACP contain a single key proposal or new idea. The more focused the ACP, the more successful it tends to be. If in doubt, split your ACP into several well-focused ones. The PR number of the ACP will become its assigned number. ### Step 3: Build Consensus on [GitHub Discussions](https://github.com/avalanche-foundation/ACPs/discussions/categories/discussion) and Provide an Implementation (if Applicable) ACPs will be merged by ACP maintainers if the proposal is generally well-formatted and coherent. ACP editors will attempt to merge anything worthy of discussion, regardless of feasibility or complexity, that is not a duplicate or incomplete. After an ACP is merged, an official GitHub Discussion will be opened for the ACP and linked to the proposal for community discussion. It is recommended for author or supportive Avalanche Community members to post an accompanying non-technical overview of their ACP for general consumption in this GitHub Discussion. The ACP should be reviewed and broadly supported before a reference implementation is started, again to avoid wasting the author and the Avalanche Community's time, unless a reference implementation will aid people in studying the ACP. ### Step 4: Mark ACP as `Implementable` via [Pull Request](https://github.com/avalanche-foundation/ACPs/pulls) Once an ACP is considered complete by the author, it should be marked as `Implementable`. At this point, all open questions should be addressed and an associated reference implementation should be provided (if applicable). As mentioned earlier, the Avalanche Foundation meets periodically to recommend the ratification of specific ACPs but it is ultimately up to members of the Avalanche Network/Community to adopt ACPs they support by running a compatible Avalanche Network Client (ANC), such as [AvalancheGo](https://github.com/ava-labs/avalanchego). ### \[Optional] Step 5: Mark ACP as `Stale` via [Pull Request](https://github.com/avalanche-foundation/ACPs/pulls) An ACP can be superseded by a different ACP, rendering the original obsolete. If this occurs, the original ACP will be marked as `Stale`. ACPs may also be marked as `Stale` if the author abandon work on it for a prolonged period of time (12+ months). ACPs may be reopened and moved back to `Proposed` if the author restart work. ## What Belongs in a Successful ACP? Each ACP must have the following parts: * `Preamble`: Markdown table containing metadata about the ACP, including the ACP number, a short descriptive title, the author, and optionally the contact info for each author, etc. * `Abstract`: Concise (\~200 word) description of the ACP * `Motivation`: Rationale for adopting the ACP and the specific issue/challenge/opportunity it addresses * `Specification`: Complete description of the semantics of any change should allow any ANC/Avalanche Community member to implement the ACP * `Security Considerations`: Security implications of the proposed ACP Each ACP can have the following parts: * `Open Questions`: Questions that should be resolved before implementation Each `Standards Track` ACP must have the following parts: * `Backwards Compatibility`: List of backwards incompatible changes required to implement the ACP and their impact on the Avalanche Community * `Reference Implementation`: Code, documentation, and telemetry (from a local network) of the ACP change Each `Best Practices Track` ACP can have the following parts: * `Backwards Compatibility`: List of backwards incompatible changes required to implement the ACP and their impact on the Avalanche Community * `Reference Implementation`: Code, documentation, and telemetry (from a local network) of the ACP change ### ACP Formats and Templates Each ACP is allocated a unique subdirectory in the `ACPs` directory. The name of this subdirectory must be of the form `N-T` where `N` is the ACP number and `T` is the ACP title with any spaces replaced by hyphens. ACPs must be written in [markdown](https://daringfireball.net/projects/markdown/syntax) format and stored at `ACPs/N-T/README.md`. Please see the [ACP template](https://github.com/avalanche-foundation/ACPs/blob/main/ACPs/TEMPLATE.md) for an example of the correct layout. ### Auxiliary Files ACPs may include auxiliary files such as diagrams or code snippets. Such files should be stored in the ACP's subdirectory (`ACPs/N-T/*`). There is no required naming convention for auxiliary files. ### Waived Copyright ACP authors must waive any copyright claims before an ACP will be merged into the repository. This can be done by including the following text in an ACP: ``` ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). ``` ## Contributing Before contributing to ACPs, please read the [ACP Terms of Contribution](https://github.com/avalanche-foundation/ACPs/blob/main/CONTRIBUTING.md). # Avalanche Consensus URL: /docs/quick-start/avalanche-consensus Learn about the groundbreaking Avalanche Consensus algorithms. Consensus is the task of getting a group of computers (a.k.a. nodes) to come to an agreement on a decision. In blockchain, this means that all the participants in a network have to agree on the changes made to the shared ledger. This agreement is reached through a specific process, a consensus protocol, that ensures that everyone sees the same information and that the information is accurate and trustworthy. ## Avalanche Consensus Avalanche Consensus is a consensus protocol that is scalable, robust, and decentralized. It combines features of both classical and Nakamoto consensus mechanisms to achieve high throughput, fast finality, and energy efficiency. For the whitepaper, see [here](https://www.avalabs.org/whitepapers). Key Features Include: * Speed: Avalanche consensus provides sub-second, immutable finality, ensuring that transactions are quickly confirmed and irreversible. * Scalability: Avalanche consensus enables high network throughput while ensuring low latency. * Energy Efficiency: Unlike other popular consensus protocols, participation in Avalanche consensus is neither computationally intensive nor expensive. * Adaptive Security: Avalanche consensus is designed to resist various attacks, including sybil attacks, distributed denial-of-service (DDoS) attacks, and collusion attacks. Its probabilistic nature ensures that the consensus outcome converges to the desired state, even when the network is under attack. ## Conceptual Overview Consensus protocols in the Avalanche family operate through repeated sub-sampled voting. When a node is determining whether a [transaction](http://support.avalabs.org/en/articles/4587384-what-is-a-transaction) should be accepted, it asks a small, random subset of [validator nodes](http://support.avalabs.org/en/articles/4064704-what-is-a-blockchain-validator) for their preference. Each queried validator replies with the transaction that it prefers, or thinks should be accepted. Consensus will never include a transaction that is determined to be **invalid**. For example, if you were to submit a transaction to send 100 AVAX to a friend, but your wallet only has 2 AVAX, this transaction is considered **invalid** and will not participate in consensus. If a sufficient majority of the validators sampled reply with the same preferred transaction, this becomes the preferred choice of the validator that inquired. In the future, this node will reply with the transaction preferred by the majority. The node repeats this sampling process until the validators queried reply with the same answer for a sufficient number of consecutive rounds. * The number of validators required to be considered a "sufficient majority" is referred to as "α" (*alpha*). * The number of consecutive rounds required to reach consensus, a.k.a. the "Confidence Threshold," is referred to as "β" (*beta*). * Both α and β are configurable. When a transaction has no conflicts, finalization happens very quickly. When conflicts exist, honest validators quickly cluster around conflicting transactions, entering a positive feedback loop until all correct validators prefer that transaction. This leads to the acceptance of non-conflicting transactions and the rejection of conflicting transactions. ![How Avalanche Consensus Works](/images/avalanche-consensus1.png) Avalanche Consensus guarantees that if any honest validator accepts a transaction, all honest validators will come to the same conclusion. For a great visualization, check out [this demo](https://tedyin.com/archive/snow-bft-demo/#/snow). ## Deep Dive Into Avalanche Consensus ### Intuition First, let's develop some intuition about the protocol. Imagine a room full of people trying to agree on what to get for lunch. Suppose it's a binary choice between pizza and barbecue. Some people might initially prefer pizza while others initially prefer barbecue. Ultimately, though, everyone's goal is to achieve **consensus**. Everyone asks a random subset of the people in the room what their lunch preference is. If more than half say pizza, the person thinks, "OK, looks like things are leaning toward pizza. I prefer pizza now." That is, they adopt the *preference* of the majority. Similarly, if a majority say barbecue, the person adopts barbecue as their preference. Everyone repeats this process. Each round, more and more people have the same preference. This is because the more people that prefer an option, the more likely someone is to receive a majority reply and adopt that option as their preference. After enough rounds, they reach consensus and decide on one option, which everyone prefers. ### Snowball The intuition above outlines the Snowball Algorithm, which is a building block of Avalanche consensus. Let's review the Snowball algorithm. #### Parameters * *n*: number of participants * *k* (sample size): between 1 and *n* * α (quorum size): between 1 and *k* * β (decision threshold): >= 1 #### Algorithm ``` preference := pizza consecutiveSuccesses := 0 while not decided: ask k random people their preference if >= α give the same response: preference := response with >= α if preference == old preference: consecutiveSuccesses++ else: consecutiveSuccesses = 1 else: consecutiveSuccesses = 0 if consecutiveSuccesses > β: decide(preference) ``` #### Algorithm Explained Everyone has an initial preference for pizza or barbecue. Until someone has *decided*, they query *k* people (the sample size) and ask them what they prefer. If α or more people give the same response, that response is adopted as the new preference. α is called the *quorum size*. If the new preference is the same as the old preference, the `consecutiveSuccesses` counter is incremented. If the new preference is different then the old preference, the `consecutiveSuccesses` counter is set to `1`. If no response gets a quorum (an α majority of the same response) then the `consecutiveSuccesses` counter is set to `0`. Everyone repeats this until they get a quorum for the same response β times in a row. If one person decides pizza, then every other person following the protocol will eventually also decide on pizza. Random changes in preference, caused by random sampling, cause a network preference for one choice, which begets more network preference for that choice until it becomes irreversible and then the nodes can decide. In our example, there is a binary choice between pizza or barbecue, but Snowball can be adapted to achieve consensus on decisions with many possible choices. The liveness and safety thresholds are parameterizable. As the quorum size, α, increases, the safety threshold increases, and the liveness threshold decreases. This means the network can tolerate more byzantine (deliberately incorrect, malicious) nodes and remain safe, meaning all nodes will eventually agree whether something is accepted or rejected. The liveness threshold is the number of malicious participants that can be tolerated before the protocol is unable to make progress. These values, which are constants, are quite small on the Avalanche Network. The sample size, *k*, is `20`. So when a node asks a group of nodes their opinion, it only queries `20` nodes out of the whole network. The quorum size, α, is `14`. So if `14` or more nodes give the same response, that response is adopted as the querying node's preference. The decision threshold, β, is `20`. A node decides on choice after receiving `20` consecutive quorum (α majority) responses. Snowball is very scalable as the number of nodes on the network, *n*, increases. Regardless of the number of participants in the network, the number of consensus messages sent remains the same because in a given query, a node only queries `20` nodes, even if there are thousands of nodes in the network. Everything discussed to this point is how Avalanche is described in [the Avalanche white-paper](https://assets-global.website-files.com/5d80307810123f5ffbb34d6e/6009805681b416f34dcae012_Avalanche%20Consensus%20Whitepaper.pdf). The implementation of the Avalanche consensus protocol by Ava Labs (namely in AvalancheGo) has some optimizations for latency and throughput. ### Blocks A block is a fundamental component that forms the structure of a blockchain. It serves as a container or data structure that holds a collection of transactions or other relevant information. Each block is cryptographically linked to the previous block, creating a chain of blocks, hence the term "blockchain." In addition to storing a reference of its parent, a block contains a set of transactions. These transactions can represent various types of information, such as financial transactions, smart contract operations, or data storage requests. If a node receives a vote for a block, it also counts as a vote for all of the block's ancestors (its parent, the parents' parent, etc.). ### Finality Avalanche consensus is probabilistically safe up to a safety threshold. That is, the probability that a correct node accepts a transaction that another correct node rejects can be made arbitrarily low by adjusting system parameters. In Nakamoto consensus protocol (as used in Bitcoin and Ethereum, for example), a block may be included in the chain but then be removed and not end up in the canonical chain. This means waiting an hour for transaction settlement. In Avalanche, acceptance/rejection are **final and irreversible** and only take a few seconds. ### Optimizations It's not safe for nodes to just ask, "Do you prefer this block?" when they query validators. In Ava Labs' implementation, during a query a node asks, "Given that this block exists, which block do you prefer?" Instead of getting back a binary yes/no, the node receives the other node's preferred block. Nodes don't only query upon hearing of a new block; they repeatedly query other nodes until there are no blocks processing. Nodes may not need to wait until they get all *k* query responses before registering the outcome of a poll. If a block has already received *alpha* votes, then there's no need to wait for the rest of the responses. ### Validators If it were free to become a validator on the Avalanche network, that would be problematic because a malicious actor could start many, many nodes which would get queried very frequently. The malicious actor could make the node act badly and cause a safety or liveness failure. The validators, the nodes which are queried as part of consensus, have influence over the network. They have to pay for that influence with real-world value in order to prevent this kind of ballot stuffing. This idea of using real-world value to buy influence over the network is called Proof of Stake. To become a validator, a node must **bond** (stake) something valuable (**AVAX**). The more AVAX a node bonds, the more often that node is queried by other nodes. When a node samples the network it's not uniformly random. Rather, it's weighted by stake amount. Nodes are incentivized to be validators because they get a reward if, while they validate, they're sufficiently correct and responsive. Avalanche doesn't have slashing. If a node doesn't behave well while validating, such as giving incorrect responses or perhaps not responding at all, its stake is still returned in whole, but with no reward. As long as a sufficient portion of the bonded AVAX is held by correct nodes, then the network is safe, and is live for virtuous transactions. ### Big Ideas Two big ideas in Avalanche are **subsampling** and **transitive voting**. Subsampling has low message overhead. It doesn't matter if there are twenty validators or two thousand validators; the number of consensus messages a node sends during a query remains constant. Transitive voting, where a vote for a block is a vote for all its ancestors, helps with transaction throughput. Each vote is actually many votes in one. ### Loose Ends Transactions are created by users which call an API on an [AvalancheGo](https://github.com/ava-labs/avalanchego) full node or create them using a library such as [AvalancheJS](https://github.com/ava-labs/avalanchejs). ### Other Observations Conflicting transactions are not guaranteed to be live. That's not really a problem because if you want your transaction to be live then you should not issue a conflicting transaction. Snowman is the name of Ava Labs' implementation of the Avalanche consensus protocol for linear chains. If there are no undecided transactions, the Avalanche consensus protocol *quiesces*. That is, it does nothing if there is no work to be done. This makes Avalanche more sustainable than Proof-of-work where nodes need to constantly do work. Avalanche has no leader. Any node can propose a transaction and any node that has staked AVAX can vote on every transaction, which makes the network more robust and decentralized. ## Why Do We Care? Avalanche is a general consensus engine. It doesn't matter what type of application is put on top of it. The protocol allows the decoupling of the application layer from the consensus layer. If you're building a dapp on Avalanche then you just need to define a few things, like how conflicts are defined and what is in a transaction. You don't need to worry about how nodes come to an agreement. The consensus protocol is a black box that put something into it and it comes back as accepted or rejected. Avalanche can be used for all kinds of applications, not just P2P payment networks. Avalanche's Primary Network has an instance of the Ethereum Virtual Machine, which is backward compatible with existing Ethereum Dapps and dev tooling. The Ethereum consensus protocol has been replaced with Avalanche consensus to enable lower block latency and higher throughput. Avalanche is very performant. It can process thousands of transactions per second with one to two second acceptance latency. ## Summary Avalanche consensus is a radical breakthrough in distributed systems. It represents as large a leap forward as the classical and Nakamoto consensus protocols that came before it. Now that you have a better understanding of how it works, check out other documentations for building game-changing Dapps and financial instruments on Avalanche. # Avalanche L1s URL: /docs/quick-start/avalanche-l1s Explore the multi-chain architecture of Avalanche ecosystem. An Avalanche L1 is a sovereign network which defines its own rules regarding its membership and token economics. It is composed of a dynamic subset of Avalanche validators working together to achieve consensus on the state of one or more blockchains. Each blockchain is validated by exactly one Avalanche L1, while an Avalanche L1 can validate many blockchains. Avalanche's [Primary Network](/docs/quick-start/primary-network) is a special Avalanche L1 running three blockchains: * The Platform Chain [(P-Chain)](/docs/quick-start/primary-network#p-chain) * The Contract Chain [(C-Chain)](/docs/quick-start/primary-network#c-chain) * The Exchange Chain [(X-Chain)](/docs/quick-start/primary-network#x-chain) ![image](/images/subnet1.png) Every validator of an Avalanche L1 **must** sync the P-Chain of the Primary Network for interoperability. Node operators that validate an Avalanche L1 with multiple chains do not need to run multiple machines for validation. For example, the Primary Network is an Avalanche L1 with three coexisting chains, all of which can be validated by a single node, or a single machine. ## Advantages ### Independent Networks * Avalanche L1s use virtual machines to specify their own execution logic, determine their own fee regime, maintain their own state, facilitate their own networking, and provide their own security. * Each Avalanche L1's performance is isolated from other Avalanche L1s in the ecosystem, so increased usage on one Avalanche L1 won't affect another. * Avalanche L1s can have their own token economics with their own native tokens, fee markets, and incentives determined by the Avalanche L1 deployer. * One Avalanche L1 can host multiple blockchains with customized [virtual machines](/docs/quick-start/virtual-machines). ### Native Interoperability Avalanche Warp Messaging enables native cross-Avalanche L1 communication and allows Virtual Machine (VM) developers to implement arbitrary communication protocols between any two Avalanche L1s. ### Accommodate App-Specific Requirements Different blockchain-based applications may require validators to have certain properties such as large amounts of RAM or CPU power. an Avalanche L1 could require that validators meet certain [hardware requirements](/docs/nodes/system-requirements#hardware-and-operating-systems) so that the application doesn't suffer from low performance due to slow validators. ### Launch Networks Designed With Compliance Avalanche's L1 architecture makes regulatory compliance manageable. As mentioned above, an Avalanche L1 may require validators to meet a set of requirements. Some examples of requirements the creators of an Avalanche L1 may choose include: * Validators must be located in a given country. * Validators must pass KYC/AML checks. * Validators must hold a certain license. ### Control Privacy of On-Chain Data Avalanche L1s are ideal for organizations interested in keeping their information private. Institutions conscious of their stakeholders' privacy can create a private Avalanche L1 where the contents of the blockchains would be visible only to a set of pre-approved validators. Define this at creation with a [single parameter](/docs/nodes/configure/avalanche-l1-configs#private-avalanche-l1). ### Validator Sovereignty In a heterogeneous network of blockchains, some validators will not want to validate certain blockchains because they simply have no interest in those blockchains. The Avalanche L1 model enables validators to concern themselves only with blockchain networks they choose to participate in. This greatly reduces the computational burden on validators. ## Develop Your Own Avalanche L1 Avalanche L1s on Avalanche are deployed by default with [Subnet-EVM](https://github.com/ava-labs/subnet-evm#subnet-evm), a fork of go-ethereum. It implements the Ethereum Virtual Machine and supports Solidity smart contracts as well as most other Ethereum client functionality. To get started, check out our [L1 Toolbox](/tools/l1-toolbox) or the tutorials in the [Avalanche CLI](/docs/tooling/create-avalanche-l1) section. # AVAX Token URL: /docs/quick-start/avax-token Learn about the native token of Avalanche Primary Network. AVAX is the native utility token of Avalanche. It's a hard-capped, scarce asset that is used to pay for fees, secure the platform through staking, and provide a basic unit of account between the multiple Avalanche L1s created on Avalanche. `1 nAVAX` is equal to `0.000000001 AVAX`. ## Utility AVAX is a capped-supply (up to 720M) resource in the Avalanche ecosystem that's used to power the network. AVAX is used to secure the ecosystem through staking and for day-to-day operations like issuing transactions. AVAX represents the weight that each node has in network decisions. No single actor owns the Avalanche Network, so each validator in the network is given a proportional weight in the network's decisions corresponding to the proportion of total stake that they own through proof of stake (PoS). Any entity trying to execute a transaction on Avalanche pays a corresponding fee (commonly known as "gas") to run it on the network. The fees used to execute a transaction on Avalanche is burned, or permanently removed from circulating supply. ## Tokenomics A fixed amount of 360M AVAX was minted at genesis, but a small amount of AVAX is constantly minted as a reward to validators. The protocol rewards validators for good behavior by minting them AVAX rewards at the end of their staking period. The minting process offsets the AVAX burned by transactions fees. While AVAX is still far away from its supply cap, it will almost always remain an inflationary asset. Avalanche does not take away any portion of a validator's already staked tokens (commonly known as "slashing") for negligent/malicious staking periods, however this behavior is disincentivized as validators who attempt to do harm to the network would expend their node's computing resources for no reward. AVAX is minted according to the following formula, where $R_j$ is the total number of tokens at year $j$, with $R_1 = 360M$, and $R_l$ representing the last year that the values of $\gamma,\lambda \in \R$ were changed; $c_j$ is the yet un-minted supply of coins to reach $720M$ at year $j$ such that $c_j \leq 360M$; $u$ represents a staker, with $u.s_{amount}$ representing the total amount of stake that $u$ possesses, and $u.s_{time}$ the length of staking for $u$. AVAX is minted according to the following formula, where $R_j$ is the total number of tokens at: $$ R_j = R_l + \sum_{\forall u} \rho(u.s_{amount}, u.s_{time}) \times \frac{c_j}{L} \times \left( \sum_{i=0}^{j}\frac{1}{\left(\gamma + \frac{1}{1 + i^\lambda}\right)^i} \right) $$ where, $$ L = \left(\sum_{i=0}^{\infty} \frac{1}{\left(\gamma + \frac{1}{1 + i^\lambda} \right)^i} \right) $$ At genesis, $c_1 = 360M$. The values of $\gamma$ and $\lambda$ are governable, and if changed, the function is recomputed with the new value of $c_*$. We have that $\sum_{*}\rho(*) \le 1$. $\rho(*)$ is a linear function that can be computed as follows ($u.s_{time}$ is measured in weeks, and $u.s_{amount}$ is measured in AVAX tokens): $$ \rho(u.s_{amount}, u.s_{time}) = (0.002 \times u.s_{time} + 0.896) \times \frac{u.s_{amount}}{R_j} $$ If the entire supply of tokens at year $j$ is staked for the maximum amount of staking time (one year, or 52 weeks), then $\sum_{\forall u}\rho(u.s_{amount}, u.s_{time}) = 1$. If, instead, every token is staked continuously for the minimal stake duration of two weeks, then $\sum_{\forall u}\rho(u.s_{amount}, u.s_{time}) = 0.9$. Therefore, staking for the maximum amount of time incurs an additional 11.11% of tokens minted, incentivizing stakers to stake for longer periods. Due to the capped-supply, the above function guarantees that AVAX will never exceed a total of $720M$ tokens, or $\lim_{j \to \infty} R(j) = 720M$. # Disclaimer URL: /docs/quick-start/disclaimer The Knowledge Base, including all the Help articles on this site, is provided for technical support purposes only, without representation, warranty or guarantee of any kind. Not an offer to sell or solicitation of an offer to buy any security or other regulated financial instrument. Not technical, investment, financial, accounting, tax, legal or other advice; please consult your own professionals. Please conduct your own research before connecting to or interacting with any dapp or third party or making any investment or financial decisions. MoonPay, ParaSwap and any other third party services or dapps you access are offered by third parties unaffiliated with us. Please review this [Notice](https://assets.website-files.com/602e8e4411398ca20cfcafd3/60ec9607c853cd466383f1ad_Important%20Notice%20-%20avalabs.org.pdf) and the [Terms of Use](https://core.app/terms/core). # Introduction URL: /docs/quick-start Learn about Avalanche Protocol and its unique features. Avalanche is an open-source platform for building decentralized applications in one interoperable, decentralized, and highly scalable ecosystem. Powered by a uniquely powerful [consensus mechanism](/docs/quick-start/avalanche-consensus), Avalanche is the first ecosystem designed to accommodate the scale of global finance, with near-instant transaction finality. ## Blazingly Fast Avalanche employs the fastest consensus mechanism of any Layer 1 blockchain. The unique consensus mechanism enables quick finality and low latency: in less than 2 seconds, your transaction is effectively processed and verified. ## Built to Scale Developers who build on Avalanche can build application-specific blockchains with complex rulesets or build on existing private or public Avalanche L1s in any language. Avalanche is incredibly energy-efficient and can run easily on consumer-grade hardware. The entire Avalanche network consumes the same amount of energy as 46 US households, equivalent to 0.0005% of the amount of energy consumed by Bitcoin. Solidity developers can build on Avalanche's implementation of the EVM straight out-of-the box, or build their own custom Virtual Machine (VM) for advanced use cases. ## Advanced Security Avalanche consensus scales to thousands of concurrent validators without suffering performance degradation making it one of the most secure protocols for internet scaling systems. Permissionless and permissioned custom blockchains deployed as an Avalanche L1s can include custom rulesets designed to be compliant with legal and jurisdictional considerations. # Primary Network URL: /docs/quick-start/primary-network Learn about the Avalanche Primary Network and its three blockchains. Avalanche is a heterogeneous network of blockchains. As opposed to homogeneous networks, where all applications reside in the same chain, heterogeneous networks allow separate chains to be created for different applications. The Primary Network is a special [Avalanche L1](/docs/quick-start/avalanche-l1s) that runs three blockchains: * The Platform Chain [(P-Chain)](/docs/quick-start/primary-network#p-chain) * The Contract Chain [(C-Chain)](/docs/quick-start/primary-network#c-chain) * The Exchange Chain [(X-Chain)](/docs/quick-start/primary-network#x-chain) [Avalanche Mainnet](/docs/quick-start/networks/mainnet) is comprised of the Primary Network and all deployed Avalanche L1s. A node can become a validator for the Primary Network by staking at least **2,000 AVAX**. ![Primary network](/images/primary-network1.png) ## The Chains All validators of the Primary Network are required to validate and secure the following: ### C-Chain The **C-Chain** is an implementation of the Ethereum Virtual Machine (EVM). The [C-Chain's API](/docs/api-reference/c-chain/api) supports Geth's API and supports the deployment and execution of smart contracts written in Solidity. The C-Chain is an instance of the [Coreth](https://github.com/ava-labs/coreth) Virtual Machine. ### P-Chain The **P-Chain** is responsible for all validator and Avalanche L1-level operations. The [P-Chain API](/docs/api-reference/p-chain/api) supports the creation of new blockchains and Avalanche L1s, the addition of validators to Avalanche L1s, staking operations, and other platform-level operations. The P-Chain is an instance of the Platform Virtual Machine. ### X-Chain The **X-Chain** is responsible for operations on digital smart assets known as **Avalanche Native Tokens**. A smart asset is a representation of a real-world resource (for example, equity, or a bond) with sets of rules that govern its behavior, like "can't be traded until tomorrow." The [X-Chain API](/docs/api-reference/x-chain/api) supports the creation and trade of Avalanche Native Tokens. One asset traded on the X-Chain is AVAX. When you issue a transaction to a blockchain on Avalanche, you pay a fee denominated in AVAX. The X-Chain is an instance of the Avalanche Virtual Machine (AVM). # Rewards Formula URL: /docs/quick-start/rewards-formula Learn about the rewards formula for the Avalanche Primary Network validator ## Primary Network Validator Rewards Consider a Primary Network validator which stakes a $Stake$ amount of `AVAX` for $StakingPeriod$ seconds. At the start of the staking period there is a $Supply$ amount of `AVAX` in the network. The maximum amount of `AVAX` is $MaximumSupply$. Then at the end of its staking period, a responsive Primary Network validator receives a reward calculated as follows: $$ Reward = \left(MaximumSupply - Supply \right) \times \frac{Stake}{Supply} \times \frac{Staking Period}{Minting Period} \times EffectiveConsumptionRate $$ where, $$ MaximumSupply - Supply = \text{the number of AVAX tokens left to emit in the network} $$ $$ \frac{Stake}{Supply} = \text{the individual's stake as a percentage of all available AVAX tokens in the network} $$ $$ \frac{StakingPeriod}{MintingPeriod} = \text{time tokens are locked up divided by the $MintingPeriod$} $$ $$ \text{$MintingPeriod$ is one year as configured by the network).} $$ $$ EffectiveConsumptionRate = $$ $$ \frac{MinConsumptionRate}{PercentDenominator} \times \left(1- \frac{Staking Period}{Minting Period}\right) + \frac{MaxConsumptionRate}{PercentDenominator} \times \frac{Staking Period}{Minting Period} $$ Note that $StakingPeriod$ is the staker's entire staking period, not just the staker's uptime, that is the aggregated time during which the staker has been responsive. The uptime comes into play only to decide whether a staker should be rewarded; to calculate the actual reward only the staking period duration is taken into account. $EffectiveConsumptionRate$ is the rate at which the Primary Network validator is rewarded based on $StakingPeriod$ selection. $MinConsumptionRate$ and $MaxConsumptionRate$ bound $EffectiveConsumptionRate$: $$ MinConsumptionRate \leq EffectiveConsumptionRate \leq MaxConsumptionRate $$ The larger $StakingPeriod$ is, the closer $EffectiveConsumptionRate$ is to $MaxConsumptionRate$. The smaller $StakingPeriod$ is, the closer $EffectiveConsumptionRate$ is to $MinConsumptionRate$. A staker achieves the maximum reward for its stake if $StakingPeriod$ = $Minting Period$. The reward is: $$ Max Reward = \left(MaximumSupply - Supply \right) \times \frac{Stake}{Supply} \times \frac{MaxConsumptionRate}{PercentDenominator} $$ Note that this formula is the same as the reward formula at the top of this section because $EffectiveConsumptionRate$ = $MaxConsumptionRate$. For reference, you can find all the Primary network parameters in [the section below](#primary-network-parameters-on-mainnet). ## Delegators Weight Checks There are bounds set of the maximum amount of delegators' stake that a validator can receive. The maximum weight $MaxWeight$ a validator $Validator$ can have is: $$ MaxWeight = \min(Validator.Weight \times MaxValidatorWeightFactor, MaxValidatorStake) $$ where $MaxValidatorWeightFactor$ and $MaxValidatorStake$ are the Primary Network Parameters described above. A delegator won't be added to a validator if the combination of their weights and all other validator's delegators' weight is larger than $MaxWeight$. Note that this must be true at any point in time. Note that setting $MaxValidatorWeightFactor$ to 1 disables delegation since the $MaxWeight = Validator.Weight$. ## Notes on Percentages `PercentDenominator = 1_000_000` is the denominator used to calculate percentages. It allows you to specify percentages up to 4 digital positions. To denominate your percentage in `PercentDenominator` just multiply it by `10_000`. For example: * `100%` corresponds to `100 * 10_000 = 1_000_000` * `1%` corresponds to `1* 10_000 = 10_000` * `0.02%` corresponds to `0.002 * 10_000 = 200` * `0.0007%` corresponds to `0.0007 * 10_000 = 7` ## Primary Network Parameters on Mainnet For reference we list below the Primary Network parameters on Mainnet: * `AssetID = Avax` * `InitialSupply = 240_000_000 Avax` * `MaximumSupply = 720_000_000 Avax`. * `MinConsumptionRate = 0.10 * reward.PercentDenominator`. * `MaxConsumptionRate = 0.12 * reward.PercentDenominator`. * `Minting Period = 365 * 24 * time.Hour`. * `MinValidatorStake = 2_000 Avax`. * `MaxValidatorStake = 3_000_000 Avax`. * `MinStakeDuration = 2 * 7 * 24 * time.Hour`. * `MaxStakeDuration = 365 * 24 * time.Hour`. * `MinDelegationFee = 20000`, that is `2%`. * `MinDelegatorStake = 25 Avax`. * `MaxValidatorWeightFactor = 5`. This is a platformVM parameter rather than a genesis one, so it's shared across networks. * `UptimeRequirement = 0.8`, that is `80%`. ### Interactive Graph The graph below demonstrates the reward as a function of the length of time staked. The x-axis depicts $\frac{StakingPeriod}{MintingPeriod}$ as a percentage while the y-axis depicts $Reward$ as a percentage of $MaximumSupply - Supply$, the amount of tokens left to be emitted. Graph variables correspond to those defined above: * `h` (high) = $MaxConsumptionRate$ * `l` (low) = $MinConsumptionRate$ * `s` = $\frac{Stake}{Supply}$