← docs

Tokens — the first thing the ledger does

The Tokens page (M6's "Tokens" and M7's "transaction building" together): create a fungible token, send it, and for a managed-supply token grant, revoke and hand the issuer role on. Everything is read back by an index over the ledger chain; nothing is inferred from what this machine sent.

What was built

Layer File Does
Engine arcade/state.py Handlers for 55 (grant), 56 (revoke), 70 (change issuer), 200 (any data: valid, no-op) alongside 0, 4, 50, 54
Index arcade/ledger.py LedgerIndex: follows the ledger chain from its start block, one SQLite file per network, stops loudly on an unknown type, unwinds reorgs; queries for properties, holders, balances, history
Building arcade/tokens.py TokenSender.prepare → signed, decoded, not broadcast; broadcast only after the caller has shown it. Payload builders that refuse what the engine would reject
Web arcade/web/app.py, templates/tokens.html, token.html, _token_confirm.html The page; every action is prepare → confirm → broadcast the same bytes
Watcher arcade/web/watcher.py Syncs the index when the ledger tip moves, 500 blocks a tick

Rules and their sources are cited in the code; the ones not in M2 notes:

Rule Source
Grant: issuer only, managed only, cap so that total ever granted ≤ MAX tx.cpp:2158-2257
Revoke: any holder, from own balance tx.cpp:2260-2326
Change issuer: issuer only, needs a reference address tx.cpp:2329-2390
Grant with no reference lands on the issuer tx.cpp:672-675
Any data (200) is valid and changes nothing tx.cpp:2735-2747

What the tests pin

Seen in pixels, not in markup

The confirm screen was rendered in headless Firefox against the testnet node before the first real transaction. It labelled every Class B data output "change back to you": the wallet's decoder lists the sender's own key among a multisig output's addresses, and the label keyed on that. The test that now pins the labels (test_a_long_name_goes_class_b_and_reads_back) was written after the screenshot, not before.

Trying it on testnet

Open Tokens and click the red main tag: the page switches to testnet, and the green test tag switches back. Both chains are indexed all the time, so the switch shows a current index. The choice is remembered across restarts.

The first token created this way is Arcade Test, from nYW2BPLENpu2nGa7WCExvzxD3hQYueULFa, transaction 4b902684ca547b2433d7963c4428bbeee67c45fd74c812e1e3910e0cbc8bb7b5, Class B (the description pushed it past one OP_RETURN). 10,000 of it went to the GX10's testnet address in 26904d43d8d45dbc5dda67bf1cc95f8af2561c758f530f8ecf313116c9814da1, Class C. A second machine running the same version must show the same token, both holders and both history entries — that is the cross-check.

The first airdrop was examples/airdrop.py through the bot RPC (D-017, bot-rpc.md): 5 Arcade Test to every holder of #3 other than the sender — one send, to the GX10, in 585f0bdec7ab055619b1b72977b785913ccc504936c6d73a91c084f768ffdffa, fee 0.00257 as the node's mempool reported it. GX10 should show 10,005.

Not yet