github.com/MetalBlockchain/metalgo@v1.11.9/indexer/service.md (about) 1 --- 2 tags: [AvalancheGo APIs] 3 description: This page is an overview of the Index API associated with AvalancheGo. 4 sidebar_label: Index API 5 pagination_label: Index API 6 --- 7 8 # Index API 9 10 AvalancheGo can be configured to run with an indexer. That is, it saves (indexes) every container (a 11 block, vertex or transaction) it accepts on the X-Chain, P-Chain and C-Chain. To run AvalancheGo 12 with indexing enabled, set command line flag 13 [--index-enabled](/nodes/configure/avalanchego-config-flags.md#apis) to true. **AvalancheGo 14 will only index containers that are accepted when running with `--index-enabled` set to true.** To 15 ensure your node has a complete index, run a node with a fresh database and `--index-enabled` set to 16 true. The node will accept every block, vertex and transaction in the network history during 17 bootstrapping, ensuring your index is complete. It is OK to turn off your node if it is running with 18 indexing enabled. If it restarts with indexing still enabled, it will accept all containers that 19 were accepted while it was offline. The indexer should never fail to index an accepted block, vertex 20 or transaction. 21 22 Indexed containers (that is, accepted blocks, vertices and transactions) are timestamped with the 23 time at which the node accepted that container. Note that if the container was indexed during 24 bootstrapping, other nodes may have accepted the container much earlier. Every container indexed 25 during bootstrapping will be timestamped with the time at which the node bootstrapped, not when it 26 was first accepted by the network. 27 28 If `--index-enabled` is changed to `false` from `true`, AvalancheGo won't start as doing so would 29 cause a previously complete index to become incomplete, unless the user explicitly says to do so 30 with `--index-allow-incomplete`. This protects you from accidentally running with indexing disabled, 31 after previously running with it enabled, which would result in an incomplete index. 32 33 This document shows how to query data from AvalancheGo's Index API. The Index API is only available 34 when running with `--index-enabled`. 35 36 ## Go Client 37 38 There is a Go implementation of an Index API client. See documentation 39 [here](https://pkg.go.dev/github.com/ava-labs/avalanchego/indexer#Client). This client can be used 40 inside a Go program to connect to an AvalancheGo node that is running with the Index API enabled and 41 make calls to the Index API. 42 43 ## Format 44 45 This API uses the `json 2.0` RPC format. For more information on making JSON RPC calls, see 46 [here](/reference/standards/guides/issuing-api-calls.md). 47 48 ## Endpoints 49 50 Each chain has one or more index. To see if a C-Chain block is accepted, for example, send an API 51 call to the C-Chain block index. To see if an X-Chain vertex is accepted, for example, send an API 52 call to the X-Chain vertex index. 53 54 ### C-Chain Blocks 55 56 ```text 57 /ext/index/C/block 58 ``` 59 60 ### P-Chain Blocks 61 62 ```text 63 /ext/index/P/block 64 ``` 65 66 ### X-Chain Transactions 67 68 ```text 69 /ext/index/X/tx 70 ``` 71 72 ### X-Chain Blocks 73 74 ```text 75 /ext/index/X/block 76 ``` 77 78 :::caution 79 80 To ensure historical data can be accessed, the `/ext/index/X/vtx` is still accessible, 81 even though it is no longer populated with chain data since the Cortina activation. 82 If you are using `V1.10.0` or higher, you need to migrate to using the `/ext/index/X/block` endpoint. 83 84 ::: 85 86 ## Methods 87 88 ### `index.getContainerByID` 89 90 Get container by ID. 91 92 **Signature:** 93 94 ```sh 95 index.getContainerByID({ 96 id: string, 97 encoding: string 98 }) -> { 99 id: string, 100 bytes: string, 101 timestamp: string, 102 encoding: string, 103 index: string 104 } 105 ``` 106 107 **Request:** 108 109 - `id` is the container's ID 110 - `encoding` is `"hex"` only. 111 112 **Response:** 113 114 - `id` is the container's ID 115 - `bytes` is the byte representation of the container 116 - `timestamp` is the time at which this node accepted the container 117 - `encoding` is `"hex"` only. 118 - `index` is how many containers were accepted in this index before this one 119 120 **Example Call:** 121 122 ```sh 123 curl --location --request POST 'localhost:9650/ext/index/X/tx' \ 124 --header 'Content-Type: application/json' \ 125 --data-raw '{ 126 "jsonrpc": "2.0", 127 "method": "index.getContainerByID", 128 "params": { 129 "id": "6fXf5hncR8LXvwtM8iezFQBpK5cubV6y1dWgpJCcNyzGB1EzY", 130 "encoding":"hex" 131 }, 132 "id": 1 133 }' 134 ``` 135 136 **Example Response:** 137 138 ```json 139 { 140 "jsonrpc": "2.0", 141 "id": 1, 142 "result": { 143 "id": "6fXf5hncR8LXvwtM8iezFQBpK5cubV6y1dWgpJCcNyzGB1EzY", 144 "bytes": "0x00000000000400003039d891ad56056d9c01f18f43f58b5c784ad07a4a49cf3d1f11623804b5cba2c6bf00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db000000070429ccc5c5eb3b80000000000000000000000001000000013cb7d3842e8cee6a0ebd09f1fe884f6861e1b29c00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db000000050429d069189e0000000000010000000000000000c85fc1980a77c5da78fe5486233fc09a769bb812bcb2cc548cf9495d046b3f1b00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db00000007000003a352a38240000000000000000000000001000000013cb7d3842e8cee6a0ebd09f1fe884f6861e1b29c0000000100000009000000011cdb75d4e0b0aeaba2ebc1ef208373fedc1ebbb498f8385ad6fb537211d1523a70d903b884da77d963d56f163191295589329b5710113234934d0fd59c01676b00b63d2108", 145 "timestamp": "2021-04-02T15:34:00.262979-07:00", 146 "encoding": "hex", 147 "index": "0" 148 } 149 } 150 ``` 151 152 ### `index.getContainerByIndex` 153 154 Get container by index. The first container accepted is at index 0, the second is at index 1, etc. 155 156 **Signature:** 157 158 ```sh 159 index.getContainerByIndex({ 160 index: uint64, 161 encoding: string 162 }) -> { 163 id: string, 164 bytes: string, 165 timestamp: string, 166 encoding: string, 167 index: string 168 } 169 ``` 170 171 **Request:** 172 173 - `index` is how many containers were accepted in this index before this one 174 - `encoding` is `"hex"` only. 175 176 **Response:** 177 178 - `id` is the container's ID 179 - `bytes` is the byte representation of the container 180 - `timestamp` is the time at which this node accepted the container 181 - `index` is how many containers were accepted in this index before this one 182 - `encoding` is `"hex"` only. 183 184 **Example Call:** 185 186 ```sh 187 curl --location --request POST 'localhost:9650/ext/index/X/tx' \ 188 --header 'Content-Type: application/json' \ 189 --data-raw '{ 190 "jsonrpc": "2.0", 191 "method": "index.getContainerByIndex", 192 "params": { 193 "index":0, 194 "encoding": "hex" 195 }, 196 "id": 1 197 }' 198 ``` 199 200 **Example Response:** 201 202 ```json 203 { 204 "jsonrpc": "2.0", 205 "id": 1, 206 "result": { 207 "id": "6fXf5hncR8LXvwtM8iezFQBpK5cubV6y1dWgpJCcNyzGB1EzY", 208 "bytes": "0x00000000000400003039d891ad56056d9c01f18f43f58b5c784ad07a4a49cf3d1f11623804b5cba2c6bf00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db000000070429ccc5c5eb3b80000000000000000000000001000000013cb7d3842e8cee6a0ebd09f1fe884f6861e1b29c00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db000000050429d069189e0000000000010000000000000000c85fc1980a77c5da78fe5486233fc09a769bb812bcb2cc548cf9495d046b3f1b00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db00000007000003a352a38240000000000000000000000001000000013cb7d3842e8cee6a0ebd09f1fe884f6861e1b29c0000000100000009000000011cdb75d4e0b0aeaba2ebc1ef208373fedc1ebbb498f8385ad6fb537211d1523a70d903b884da77d963d56f163191295589329b5710113234934d0fd59c01676b00b63d2108", 209 "timestamp": "2021-04-02T15:34:00.262979-07:00", 210 "encoding": "hex", 211 "index": "0" 212 } 213 } 214 ``` 215 216 ### `index.getContainerRange` 217 218 Returns the transactions at index [`startIndex`], [`startIndex+1`], ... , [`startIndex+n-1`] 219 220 - If [`n`] == 0, returns an empty response (for example: null). 221 - If [`startIndex`] > the last accepted index, returns an error (unless the above apply.) 222 - If [`n`] > [`MaxFetchedByRange`], returns an error. 223 - If we run out of transactions, returns the ones fetched before running out. 224 - `numToFetch` must be in `[0,1024]`. 225 226 **Signature:** 227 228 ```sh 229 index.getContainerRange({ 230 startIndex: uint64, 231 numToFetch: uint64, 232 encoding: string 233 }) -> []{ 234 id: string, 235 bytes: string, 236 timestamp: string, 237 encoding: string, 238 index: string 239 } 240 ``` 241 242 **Request:** 243 244 - `startIndex` is the beginning index 245 - `numToFetch` is the number of containers to fetch 246 - `encoding` is `"hex"` only. 247 248 **Response:** 249 250 - `id` is the container's ID 251 - `bytes` is the byte representation of the container 252 - `timestamp` is the time at which this node accepted the container 253 - `encoding` is `"hex"` only. 254 - `index` is how many containers were accepted in this index before this one 255 256 **Example Call:** 257 258 ```sh 259 curl --location --request POST 'localhost:9650/ext/index/X/tx' \ 260 --header 'Content-Type: application/json' \ 261 --data-raw '{ 262 "jsonrpc": "2.0", 263 "method": "index.getContainerRange", 264 "params": { 265 "startIndex":0, 266 "numToFetch":100, 267 "encoding": "hex" 268 }, 269 "id": 1 270 }' 271 ``` 272 273 **Example Response:** 274 275 ```json 276 { 277 "jsonrpc": "2.0", 278 "id": 1, 279 "result": [ 280 { 281 "id": "6fXf5hncR8LXvwtM8iezFQBpK5cubV6y1dWgpJCcNyzGB1EzY", 282 "bytes": "0x00000000000400003039d891ad56056d9c01f18f43f58b5c784ad07a4a49cf3d1f11623804b5cba2c6bf00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db000000070429ccc5c5eb3b80000000000000000000000001000000013cb7d3842e8cee6a0ebd09f1fe884f6861e1b29c00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db000000050429d069189e0000000000010000000000000000c85fc1980a77c5da78fe5486233fc09a769bb812bcb2cc548cf9495d046b3f1b00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db00000007000003a352a38240000000000000000000000001000000013cb7d3842e8cee6a0ebd09f1fe884f6861e1b29c0000000100000009000000011cdb75d4e0b0aeaba2ebc1ef208373fedc1ebbb498f8385ad6fb537211d1523a70d903b884da77d963d56f163191295589329b5710113234934d0fd59c01676b00b63d2108", 283 "timestamp": "2021-04-02T15:34:00.262979-07:00", 284 "encoding": "hex", 285 "index": "0" 286 } 287 ] 288 } 289 ``` 290 291 ### `index.getIndex` 292 293 Get a container's index. 294 295 **Signature:** 296 297 ```sh 298 index.getIndex({ 299 id: string, 300 encoding: string 301 }) -> { 302 index: string 303 } 304 ``` 305 306 **Request:** 307 308 - `id` is the ID of the container to fetch 309 - `encoding` is `"hex"` only. 310 311 **Response:** 312 313 - `index` is how many containers were accepted in this index before this one 314 315 **Example Call:** 316 317 ```sh 318 curl --location --request POST 'localhost:9650/ext/index/X/tx' \ 319 --header 'Content-Type: application/json' \ 320 --data-raw '{ 321 "jsonrpc": "2.0", 322 "method": "index.getIndex", 323 "params": { 324 "id":"6fXf5hncR8LXvwtM8iezFQBpK5cubV6y1dWgpJCcNyzGB1EzY", 325 "encoding": "hex" 326 }, 327 "id": 1 328 }' 329 ``` 330 331 **Example Response:** 332 333 ```json 334 { 335 "jsonrpc": "2.0", 336 "result": { 337 "index": "0" 338 }, 339 "id": 1 340 } 341 ``` 342 343 ### `index.getLastAccepted` 344 345 Get the most recently accepted container. 346 347 **Signature:** 348 349 ```sh 350 index.getLastAccepted({ 351 encoding:string 352 }) -> { 353 id: string, 354 bytes: string, 355 timestamp: string, 356 encoding: string, 357 index: string 358 } 359 ``` 360 361 **Request:** 362 363 - `encoding` is `"hex"` only. 364 365 **Response:** 366 367 - `id` is the container's ID 368 - `bytes` is the byte representation of the container 369 - `timestamp` is the time at which this node accepted the container 370 - `encoding` is `"hex"` only. 371 372 **Example Call:** 373 374 ```sh 375 curl --location --request POST 'localhost:9650/ext/index/X/tx' \ 376 --header 'Content-Type: application/json' \ 377 --data-raw '{ 378 "jsonrpc": "2.0", 379 "method": "index.getLastAccepted", 380 "params": { 381 "encoding": "hex" 382 }, 383 "id": 1 384 }' 385 ``` 386 387 **Example Response:** 388 389 ```json 390 { 391 "jsonrpc": "2.0", 392 "id": 1, 393 "result": { 394 "id": "6fXf5hncR8LXvwtM8iezFQBpK5cubV6y1dWgpJCcNyzGB1EzY", 395 "bytes": "0x00000000000400003039d891ad56056d9c01f18f43f58b5c784ad07a4a49cf3d1f11623804b5cba2c6bf00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db000000070429ccc5c5eb3b80000000000000000000000001000000013cb7d3842e8cee6a0ebd09f1fe884f6861e1b29c00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db000000050429d069189e0000000000010000000000000000c85fc1980a77c5da78fe5486233fc09a769bb812bcb2cc548cf9495d046b3f1b00000001dbcf890f77f49b96857648b72b77f9f82937f28a68704af05da0dc12ba53f2db00000007000003a352a38240000000000000000000000001000000013cb7d3842e8cee6a0ebd09f1fe884f6861e1b29c0000000100000009000000011cdb75d4e0b0aeaba2ebc1ef208373fedc1ebbb498f8385ad6fb537211d1523a70d903b884da77d963d56f163191295589329b5710113234934d0fd59c01676b00b63d2108", 396 "timestamp": "2021-04-02T15:34:00.262979-07:00", 397 "encoding": "hex", 398 "index": "0" 399 } 400 } 401 ``` 402 403 ### `index.isAccepted` 404 405 Returns true if the container is in this index. 406 407 **Signature:** 408 409 ```sh 410 index.isAccepted({ 411 id: string, 412 encoding: string 413 }) -> { 414 isAccepted: bool 415 } 416 ``` 417 418 **Request:** 419 420 - `id` is the ID of the container to fetch 421 - `encoding` is `"hex"` only. 422 423 **Response:** 424 425 - `isAccepted` displays if the container has been accepted 426 427 **Example Call:** 428 429 ```sh 430 curl --location --request POST 'localhost:9650/ext/index/X/tx' \ 431 --header 'Content-Type: application/json' \ 432 --data-raw '{ 433 "jsonrpc": "2.0", 434 "method": "index.isAccepted", 435 "params": { 436 "id":"6fXf5hncR8LXvwtM8iezFQBpK5cubV6y1dWgpJCcNyzGB1EzY", 437 "encoding": "hex" 438 }, 439 "id": 1 440 }' 441 ``` 442 443 **Example Response:** 444 445 ```json 446 { 447 "jsonrpc": "2.0", 448 "result": { 449 "isAccepted": true 450 }, 451 "id": 1 452 } 453 ``` 454 455 ## Example: Iterating Through X-Chain Transaction 456 457 Here is an example of how to iterate through all transactions on the X-Chain. 458 459 :::warning 460 To help users to try out this example and other index APIs, we have set up a testing 461 indexer node located at [https://indexer-demo.avax.network](https://indexer-demo.avax.network). This 462 indexer node is not for production use. We may change or shut it down at any time without notice. 463 ::: 464 465 You can use the Index API to get the ID of every transaction that has been accepted on the X-Chain, 466 and use the X-Chain API method `avm.getTx` to get a human-readable representation of the 467 transaction. 468 469 To get an X-Chain transaction by its index (the order it was accepted in), use Index API method 470 [index.getlastaccepted](#indexgetlastaccepted). 471 472 For example, to get the _second_ transaction (note that `"index":1`) accepted on the X-Chain, do: 473 474 ```sh 475 curl --location --request POST 'https://indexer-demo.avax.network/ext/index/X/tx' \ 476 --header 'Content-Type: application/json' \ 477 --data-raw '{ 478 "jsonrpc": "2.0", 479 "method": "index.getContainerByIndex", 480 "params": { 481 "encoding":"hex", 482 "index":1 483 }, 484 "id": 1 485 }' 486 ``` 487 488 This returns the ID of the second transaction accepted in the X-Chain's history. To get the third 489 transaction on the X-Chain, use `"index":2`, and so on. 490 491 The above API call gives the response below: 492 493 ```json 494 { 495 "jsonrpc": "2.0", 496 "result": { 497 "id": "ZGYTSU8w3zUP6VFseGC798vA2Vnxnfj6fz1QPfA9N93bhjJvo", 498 "bytes": "0x00000000000000000001ed5f38341e436e5d46e2bb00b45d62ae97d1b050c64bc634ae10626739e35c4b0000000221e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff000000070000000129f6afc0000000000000000000000001000000017416792e228a765c65e2d76d28ab5a16d18c342f21e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff0000000700000222afa575c00000000000000000000000010000000187d6a6dd3cd7740c8b13a410bea39b01fa83bb3e000000016f375c785edb28d52edb59b54035c96c198e9d80f5f5f5eee070592fe9465b8d0000000021e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff0000000500000223d9ab67c0000000010000000000000000000000010000000900000001beb83d3d29f1247efb4a3a1141ab5c966f46f946f9c943b9bc19f858bd416d10060c23d5d9c7db3a0da23446b97cd9cf9f8e61df98e1b1692d764c84a686f5f801a8da6e40", 499 "timestamp": "2021-11-04T00:42:55.01643414Z", 500 "encoding": "hex", 501 "index": "1" 502 }, 503 "id": 1 504 } 505 ``` 506 507 The ID of this transaction is `ZGYTSU8w3zUP6VFseGC798vA2Vnxnfj6fz1QPfA9N93bhjJvo`. 508 509 To get the transaction by its ID, use API method `avm.getTx`: 510 511 ```sh 512 curl -X POST --data '{ 513 "jsonrpc":"2.0", 514 "id" :1, 515 "method" :"avm.getTx", 516 "params" :{ 517 "txID":"ZGYTSU8w3zUP6VFseGC798vA2Vnxnfj6fz1QPfA9N93bhjJvo", 518 "encoding": "json" 519 } 520 }' -H 'content-type:application/json;' https://api.avax.network/ext/bc/X 521 ``` 522 523 Response: 524 525 ```json 526 { 527 "jsonrpc": "2.0", 528 "result": { 529 "tx": { 530 "unsignedTx": { 531 "networkID": 1, 532 "blockchainID": "2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM", 533 "outputs": [ 534 { 535 "assetID": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z", 536 "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", 537 "output": { 538 "addresses": ["X-avax1wst8jt3z3fm9ce0z6akj3266zmgccdp03hjlaj"], 539 "amount": 4999000000, 540 "locktime": 0, 541 "threshold": 1 542 } 543 }, 544 { 545 "assetID": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z", 546 "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", 547 "output": { 548 "addresses": ["X-avax1slt2dhfu6a6qezcn5sgtagumq8ag8we75f84sw"], 549 "amount": 2347999000000, 550 "locktime": 0, 551 "threshold": 1 552 } 553 } 554 ], 555 "inputs": [ 556 { 557 "txID": "qysTYUMCWdsR3MctzyfXiSvoSf6evbeFGRLLzA4j2BjNXTknh", 558 "outputIndex": 0, 559 "assetID": "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z", 560 "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", 561 "input": { 562 "amount": 2352999000000, 563 "signatureIndices": [0] 564 } 565 } 566 ], 567 "memo": "0x" 568 }, 569 "credentials": [ 570 { 571 "fxID": "spdxUxVJQbX85MGxMHbKw1sHxMnSqJ3QBzDyDYEP3h6TLuxqQ", 572 "credential": { 573 "signatures": [ 574 "0xbeb83d3d29f1247efb4a3a1141ab5c966f46f946f9c943b9bc19f858bd416d10060c23d5d9c7db3a0da23446b97cd9cf9f8e61df98e1b1692d764c84a686f5f801" 575 ] 576 } 577 } 578 ] 579 }, 580 "encoding": "json" 581 }, 582 "id": 1 583 } 584 ```