Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/api/_category_.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"label": "API",
"position": 6
"position": 5
}
44 changes: 41 additions & 3 deletions docs/api/conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,31 @@ Behavior shared by all indexer API endpoints.

## Pagination

List endpoints accept two query parameters:
List endpoints support two pagination styles: simple offset-based paging and opaque keyset cursors. Both validate `items` the same way.

### `items` validation

| Parameter | Type | Default | Description |
| --------- | ---- | ------- | ----------- |
| `offset` | integer | `0` | Number of items to skip |
| `items` | integer | `10` | Page size, capped at `100` |

`items` must be at least 1 (`items=0` returns HTTP 400) and at most 100; non-numeric values are rejected as well. This applies to both pagination styles.

### Offset pagination

For shallow listing ("the first few results"), pass `offset`:

| Parameter | Type | Default | Description |
| --------- | ---- | ------- | ----------- |
| `offset` | integer | `0` | Number of items to skip |

```bash
curl "https://api-server.mintlayer.org/api/v2/transaction?offset=0&items=20"
```

Invalid values (non-numeric, or `items` above 100) return a client error. The transaction list endpoint additionally accepts `offset_mode`:
Deep offsets re-read every preceding row on each request, so they get slower the deeper you page. For long walks, use keyset pagination instead.

The transaction list endpoint additionally accepts `offset_mode`:

| `offset_mode` | Behavior |
| ------------- | -------- |
Expand All @@ -30,6 +43,31 @@ Invalid values (non-numeric, or `items` above 100) return a client error. The tr

Use `absolute` when you need stable pagination (e.g. syncing all transactions); use the default for "recent activity" views.

### Keyset pagination (cursors)

Deeper listings — [pools](endpoints/pool.md#get-pool), [transactions](endpoints/transaction.md#get-transaction), [address balance holders](endpoints/statistics.md#get-statisticscoinholders), and the [order book](endpoints/order.md#get-orderpairpairbook) — accept an opaque `cursor` query parameter instead of relying on deep offsets:

```bash
curl "https://api-server.mintlayer.org/api/v2/pool?cursor=<next_cursor>&items=100"
```

- The cursor is an **opaque string** (base64-encoded JSON, at most 1 KiB and 16 keys). Treat it as a black box: never construct, decode, modify, or store one beyond the life of the walk — pass back exactly what the server returned. An empty value (`cursor=`) starts the listing from the beginning.
- When a `cursor` parameter is supplied, the response is an envelope instead of a plain array (the [holders](endpoints/statistics.md#get-statisticscoinholders) and [order book](endpoints/order.md#get-orderpairpairbook) endpoints always return the envelope):

```json
{
"items": ["..."],
"next_cursor": "eyJ0YWciOiJwb29scyIsImtleXMiOlsiMTAyMzAwIl0sImlkIjoibXBvb2wx..."
}
```

- Pass `next_cursor` back as `cursor` to fetch the following page. A `null` `next_cursor` means the listing is exhausted. (For the order book, `null` can also mean the walk was cut short by the server-side scan cap — see [Orders](endpoints/order.md#get-orderpairpairbook).)
- Ordering is stable, newest first. Ties are broken by descending byte-order ID, so equal-ranked entries keep a fixed relative order across pages. Transactions additionally order by ascending transaction index within a block, so consecutive pages reconstruct each block's transaction order.
- If both `cursor` and `offset` are given, the cursor takes precedence.
- Pages are guaranteed stable only once the scanner has fully caught up with the chain tip. While it is catching up (e.g. after a reorg), a concurrent walk may skip or repeat an entry.

Offset pagination remains the simple alternative for shallow listing; cursors are the right tool whenever a full listing needs to be walked.

## Amounts

All amounts are returned as an object with two representations:
Expand Down
41 changes: 41 additions & 0 deletions docs/api/endpoints/order.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,47 @@ curl "https://api-server.mintlayer.org/api/v2/order/pair/ML_mmltk18e0xfgmw3sn4s8

The pair direction is normalized (matching orders for the pair are returned regardless of give/ask orientation).

## GET /order/pair/\{pair\}/book

Returns the aggregated order book for a trading pair: open orders are grouped by price, and each price level's `amount` is the summed available balance across the orders at that price (an order filled partially contributes its remaining balance, which is carried as it fills).

The pair is `{BASE}_{QUOTE}` — exactly two non-empty, `_`-separated sides, each the coin ticker (`ML` on mainnet, case-insensitive) or a token ID. Both sides must be the native coin or a registered token; anything else is a client error (`400 {"error": "Invalid order trading pair"}`). The direction is normalized: requesting the reversed pair works and shows the mirrored side of the same orders.

Query parameters:

| Parameter | Description |
| --------- | ----------- |
| `side` | Required. `ask` lists the orders asking for the base currency (first in the pair) while giving the quote; `bid` lists the reverse (asking for quote, giving base) |
| `items` | Page size, capped at `100`. See [Conventions](../conventions.md#pagination) |
| `cursor` | [Keyset pagination](../conventions.md#keyset-pagination-cursors) cursor from `next_cursor`. Cursors are side-specific: a cursor from the ask book is rejected (HTTP 400) on the bid walk, and vice versa |

Ask levels are ordered by ascending price, bid levels by descending price (best price first). Each level's `price` is quote-per-base in two forms: `atoms` is the exact rational in atoms as a `numer/denom` string (quote atoms per base atom), and `decimal` is a display string floored from the exact value.

```bash
curl "https://api-server.mintlayer.org/api/v2/order/pair/ML_mmltk18e0xfgmw3sn4s8vqu0ypjsnlv2fhnm6ye4zcazwqpr9dujrrdf6qjyhh0e/book?side=ask&items=2"
```

```json
{
"items": [
{
"price": { "decimal": "1", "atoms": "1/1" },
"amount": { "atoms": "10000000000000", "decimal": "100" }
},
{
"price": { "decimal": "3", "atoms": "3/1" },
"amount": { "atoms": "98250000000000", "decimal": "982.5" }
}
],
"next_cursor": null
}
```

- `amount` is in the base currency of the pair; both amounts follow the [atoms/decimal convention](../conventions.md#amounts).
- A request scans at most 10,000 open orders. If the scan hit that cap, the response carries an additional `"truncated": true` and **no `next_cursor`**: the levels in hand may be an incomplete view of the book, so re-issue the request (e.g. with different parameters) rather than continuing from a cursor.
- Otherwise `next_cursor` follows the usual [keyset pagination](../conventions.md#keyset-pagination-cursors) contract, and `null` means the end of the book.
- The book is computed per request from a live snapshot of open orders. While the scanner is still catching up, a concurrent walk may skip or repeat a level — re-fetch from the start (`cursor=`) when you need a consistent view.

## Go SDK

```go
Expand Down
1 change: 1 addition & 0 deletions docs/api/endpoints/pool.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ curl "https://api-server.mintlayer.org/api/v2/pool?items=1"

- `margin_ratio_per_thousand` is the pool's commission in per-mille (e.g. `100%` means 10%... represented as per-thousand of the reward).
- `staker_balance` is the pool founder's pledge; `delegations_balance` is the total delegated by other users.
- The listing is ordered by creation height, newest first. Besides `offset`/`items`, it accepts [keyset pagination](../conventions.md#keyset-pagination-cursors) via `cursor`: with a `cursor` parameter the response is the `{items, next_cursor}` envelope instead of a plain array, and `cursor` takes precedence over `offset`. Pass `next_cursor` back as `cursor` to walk the full list without deep offsets; a `null` `next_cursor` ends the walk.

## GET /pool/\{id\}

Expand Down
58 changes: 55 additions & 3 deletions docs/api/endpoints/statistics.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Statistics"
description: "Supply statistics endpoints of the Mintlayer indexer API: coin and per-token."
description: "Supply statistics endpoints of the Mintlayer indexer API: coin and per-token supply counters and address balance holders."
sidebar_position: 7
---

Expand All @@ -25,20 +25,72 @@ curl https://api-server.mintlayer.org/api/v2/statistics/coin

All amounts follow the [atoms/decimal convention](../conventions.md#amounts).

The counters are maintained by the scanner while it indexes the chain (and rolled back on reorgs), so they are always up to date with the indexed tip:

- `preminted` — the total amount that has entered circulation: for the coin, transfer outputs and pool-creation pledges; for a token, transfer outputs since issuance.
- `staked` — the amount currently staked in pools (the founder's pledge plus delegated balances).
- `circulating_supply` — the amount currently in circulation: `preminted` minus everything `burned`. Burns are subtracted during indexing, so this counter already reflects everything counted in `burned`; the total amount ever minted is therefore `circulating_supply + burned`.
- `burned` — the total amount destroyed: outputs sent to burn destinations, plus the fees of token account commands (minting, freezing, authority changes, ...), which are burned rather than paid to anyone.

Consumers should treat an absent statistic as zero: the endpoint lists the statistics that have been written, and a counter with no recorded activity is omitted from the underlying listing rather than returned as `0`. The endpoints above render such absent counters as zero, as in the token example below.

## GET /statistics/token/\{id\}

Returns the same statistics for a specific token, identified by its bech32 token ID (`mmltk1...`):

```bash
curl https://api-server.mintlayer.org/api/v2/statistics/token/mmltk18e0xfgmw3sn4s8vqu0ypjsnlv2fhnm6ye4zcazwqpr9dujrrdf6qjyhh0e
```

```json
{
"burned": { "atoms": "0", "decimal": "0" },
"circulating_supply": { "atoms": "0", "decimal": "0" },
"preminted": { "atoms": "0", "decimal": "0" },
"staked": { "atoms": "0", "decimal": "0" },
"total_supply": { "atoms": "0", "decimal": "0" }
"staked": { "atoms": "0", "decimal": "0" }
}
```

For tokens, `circulating_supply` increases with transfer outputs and mint commands and decreases with everything burned. An unknown token returns HTTP 404 with `{"error": "Token not found"}`; a malformed token ID returns HTTP 400.

## GET /statistics/coin/holders

Lists the top addresses by coin balance, largest first:

```bash
curl "https://api-server.mintlayer.org/api/v2/statistics/coin/holders?items=2"
```

```json
{
"items": [
{
"address": "mtc1q8n9u3g3aw4h40gsagxn7yw0jatdfe9xsuftnvur",
"amount": { "atoms": "18923740491080455517", "decimal": "189237404.91080455517" }
},
{
"address": "mtc1q9sl5xwkfypf7gutvnwfscvzs9w9gjqc0vs90e34",
"amount": { "atoms": "98250000000000", "decimal": "982.5" }
}
],
"next_cursor": null
}
```

- Entries are ordered by balance, descending; ties are broken by address in descending byte order, so equal balances keep a stable order. Addresses with a zero balance are not listed.
- `amount` follows the [atoms/decimal convention](../conventions.md#amounts).
- The response is always the `{items, next_cursor}` envelope. Walk the full listing with [keyset pagination](../conventions.md#keyset-pagination-cursors): pass `next_cursor` back as `cursor`; `null` means the listing is exhausted.

## GET /statistics/token/\{id\}/holders

The same listing for the holders of a specific token, identified by its bech32 token ID (`mmltk1...`):

```bash
curl "https://api-server.mintlayer.org/api/v2/statistics/token/mmltk18e0xfgmw3sn4s8vqu0ypjsnlv2fhnm6ye4zcazwqpr9dujrrdf6qjyhh0e/holders?items=1"
```

Same response shape and ordering as the coin holders listing. An unknown token returns HTTP 404 with `{"error": "Token not found"}`.

## Go SDK

```go
Expand Down
9 changes: 8 additions & 1 deletion docs/api/endpoints/transaction.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ sidebar_position: 3

## GET /transaction

Lists transactions, newest first. Supports [pagination](../conventions.md#pagination) with `offset` and `items`.
Lists transactions, newest first. Supports [pagination](../conventions.md#pagination) with `offset` and `items`, or with an opaque keyset `cursor` for walking the full history.

```bash
curl "https://api-server.mintlayer.org/api/v2/transaction?offset=0&items=1"
Expand Down Expand Up @@ -54,6 +54,13 @@ Query parameters:
| --------- | ----------- |
| `offset`, `items` | Standard [pagination](../conventions.md#pagination) |
| `offset_mode` | `legacy` (default) or `absolute` for stable pagination over the global index. See [Conventions](../conventions.md#pagination) |
| `cursor` | [Keyset pagination](../conventions.md#keyset-pagination-cursors) cursor from `next_cursor`; an empty value starts from the beginning. Returns pages in the same, stable newest-first order (transactions within a block in ascending transaction index, so pages reconstruct block order) |

Notes on `cursor`:

- With a `cursor` parameter the response is the `{items, next_cursor}` envelope instead of a plain array; a `null` `next_cursor` ends the walk.
- `cursor` takes precedence over `offset`. Combining `cursor` with `offset_mode` is a client error.
- For shallow listing, plain `offset`/`items` remains the simple alternative.

## GET /transaction/\{id\}

Expand Down
6 changes: 3 additions & 3 deletions docs/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ curl https://api-server.mintlayer.org/

- **No authentication** for reads. The API is read-only by default and suitable for public frontends (CORS is open).
- **Writes are gated.** Submitting transactions via `POST /transaction` is disabled unless the server is started with `--enable-post-routes` (the production API does not expose it).
- **Pagination** on list endpoints via `offset` and `items` query parameters (default 10 items, max 100). See [Conventions](conventions.md).
- **Pagination** on list endpoints via `offset` and `items` query parameters (default 10 items, max 100), and via opaque keyset `cursor`s for walking deep listings (pools, transactions, holders, order book). See [Conventions](conventions.md).
- **Amounts** are returned as `{atoms, decimal}` pairs. See [Conventions](conventions.md).

## Documentation map
Expand All @@ -63,9 +63,9 @@ curl https://api-server.mintlayer.org/
| [Addresses](endpoints/address.md) | Balances, UTXOs, delegations, token authority |
| [Pools](endpoints/pool.md) | Staking pools, block stats, delegations |
| [Delegations](endpoints/delegation.md) | Delegation lookup |
| [Statistics](endpoints/statistics.md) | Coin and token supply statistics |
| [Statistics](endpoints/statistics.md) | Coin and token supply statistics, address balance holders |
| [Tokens](endpoints/token.md) | Fungible tokens, ticker lookup |
| [NFTs](endpoints/nft.md) | NFT issuance data |
| [Orders](endpoints/order.md) | On-chain order book |
| [Orders](endpoints/order.md) | On-chain order book, price-level aggregation |
| [Fee rate](endpoints/feerate.md) | Mempool fee estimates |
| [Transaction submission](endpoints/transaction-submission.md) | POST /transaction (gated) |
1 change: 1 addition & 0 deletions docs/build/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ For ports, RPC authentication, WebSocket subscriptions, regtest, and the WASM wr

- **[Go SDK](sdks/go/index.md)**, full coverage of the node, indexer, and wallet RPCs plus the embedded WASM cryptography runtime (no CGO). Recommended for services, exchanges, and backends.
- **[Rust SDK](sdks/rust/index.md)**, async sub-clients for the node, indexer, and wallet RPCs plus native cryptography and transaction building backed by mintlayer-core (opt-in `crypto` feature).
- **[Python SDK](sdks/python/index.md)**, the Go SDK ported to Python: synchronous RPC clients plus the WASM cryptography runtime bundled via wasmtime.

## Accept addresses from users

Expand Down
8 changes: 8 additions & 0 deletions docs/build/sdks/go/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"label": "Go SDK",
"position": 2,
"link": {
"type": "doc",
"id": "build/sdks/go/index"
}
}
2 changes: 1 addition & 1 deletion docs/build/sdks/javascript/_category_.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"label": "JavaScript SDK",
"position": 2,
"position": 1,
"link": {
"type": "doc",
"id": "build/sdks/javascript/index"
Expand Down
8 changes: 8 additions & 0 deletions docs/build/sdks/python/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"label": "Python SDK",
"position": 4,
"link": {
"type": "doc",
"id": "build/sdks/python/index"
}
}
Loading