# Transactions

Every change to the MLX ledger is a transaction signed by a wallet's Ed25519 key or by the sequencer, ordered into hash-linked, signed blocks.

## What a transaction is

A transaction is a small JSON object. The wallet signs it, sends it to `POST /api/tx`, and the sequencer applies it to the ledger in a block. Nothing else changes a balance.

```json title="A signed transfer"
{
  "chain": "mlx-1",
  "from": "luca.mlx",
  "nonce": 4,
  "ts": 1793116800000,
  "pk": "7812b1435b317df04f45731ac508ae7774d4731ee0445fd46ccdcc5019faa524",
  "body": { "type": "transfer", "to": "shop.mlx", "token": "USDC", "amount": "2500000" },
  "sig": "ce8c7621b38777895b06107168e08a542bf9d5fbaf2ac53bb1b9a1b1d3ade2635d5c00150a2f76990b49330365d964c2b55d3289bbc9cc3e380550a2715cb10f"
}
```

| Field | Type | Notes |
|---|---|---|
| `chain` | string | The network's chain id. Production is `mlx-1`; `GET /api/stats` returns it as `chain`. |
| `from` | string | The wallet that signs, for example `luca.mlx`. `sequencer` for system transactions. |
| `nonce` | integer | The wallet's next nonce: its current `nonce` plus one. `create_account` uses `0`. |
| `ts` | integer | When it was signed, in milliseconds since 1970. Must be close to the network's clock. |
| `pk` | string | The signer's Ed25519 public key, 64 lowercase hex characters. |
| `body` | object | What to do. `body.type` names the [transaction type](/transactions/types). |
| `sig` | string | Ed25519 signature, 128 hex characters, over the transaction's hash. |

Amounts are strings of base units with 6 decimals: `"2500000"` is 2.5 USDC.

## Hash and signature

The transaction's hash is SHA-256 of its canonical JSON (keys sorted, no whitespace) without `sig`. The signature is Ed25519 over those 32 hash bytes. The hash is also the transaction's id: `GET /api/tx/<hash>`. Signing the same fields twice gives the same hash, so sending a transaction again never applies it twice. Details and a worked example: [Keys and signing](/transactions/keys-and-signing).

## Nonces

Each wallet has a `nonce`, starting at `0` when it is created. A transaction applies only with nonce = current nonce + 1, and a successful one moves the wallet's nonce up by one. A failed transaction does not use its nonce: sign the next one with the same number. The sequencer applies a wallet's transactions in nonce order, and one that arrives ahead of its predecessor waits for it briefly in the mempool. See [Submitting](/transactions/submitting#nonces).

Read a wallet's current nonce from `GET /api/account/<name>` (`account.nonce`).

## Blocks

The sequencer takes transactions from the mempool, applies them in order and seals them into a block. A submit seals a block right away when it can; a scheduled job seals anything left. Each block carries:

- `prev`: the hash of the block before it, so blocks form a chain from the genesis block (height 0);
- `txRoot`: a Merkle root over the hashes of the transactions it holds;
- `producer` and `sig`: the sequencer's public key and its Ed25519 signature over the block hash.

A transaction that fails is still recorded in its block, with `status: "failed"` and an `error`, and changes nothing. Every block then goes into the ledger's [transparency log](/integrity/overview). Block endpoints: [Blocks](/network/blocks).

## User and system transactions

| | User transactions | System transactions |
|---|---|---|
| Signed by | the wallet's own key (`pk` must be the key the wallet was created with) | the sequencer's key (`from: "sequencer"`, `nonce: 0`) |
| Examples | `create_account`, `transfer`, `swap`, `buy_node`, `withdraw`, `bind_device` | `deposit`, `mint_node`, `compute_reward`, `withdraw_settle`, `issue`, `adjust`, `gift` |
| Who sends them | wallets, MLX Node's link sheet, your own code | the network itself: the payment watcher, the hourly reward run, withdrawal payouts, the operator's admin |

System transactions are public like any other: they show on the explorer with their reason, and the hourly [state commitment](/integrity/state) covers the balances they produce. A user cannot send one: a system type signed by a wallet fails.

## Where to go next

:::cards
- [Keys and signing](/transactions/keys-and-signing) How the key comes from the 24 words, the canonical JSON and the exact bytes signed, with a runnable example.
- [Submitting](/transactions/submitting) POST /api/tx, its replies, statuses, nonce order, limits and how to wait for a block.
- [Transaction types](/transactions/types) Every user transaction's fields and rules, and the system transactions.
- [Integrity](/integrity/overview) Check that the history you were shown is the one everyone else sees.
:::
