Implements step 1 of ADR-0057's three-layer metadata split. The 40-byte
minting-NFT commitment, previously set to '' on every genesis, now carries
the irreducible-minimum identity so a wallet with no network at all can
show "ASM (DEA, 2 dp)" for an on-chain amount — no BCMR URL fetch, no
local registry lookup.
Binary layout (pinned per ADR-0057 §1):
byte 0: magic = 0x44 ('D')
byte 1: version = 0x01
byte 2: decimals (uint8, 0..18)
byte 3: assetClass byte (ASSET_CLASS_BYTE table)
bytes 4..15: ticker, 12 UTF-8 bytes right-padded with 0x00 (ASCII only)
bytes 16..39: reserved zero (24 B for future flags)
Disambiguation vs AdjustableFeeCapped (ADR-0011) which already uses the
commitment for live feeBps: length (40 vs 1-2) + magic byte. The genesis
planner enforces mutual exclusion at write time — assetClass is honoured
only when adjustableFee is NOT set.
Changes:
- NEW src/wallet/metadata-commitment.ts: pure encoder/decoder + format
constants, no deps outside src/token/assetClass. Decoder returns null
for anything not a well-formed metadata commitment (empty, short,
wrong-magic, wrong-version) so callers can fall through to BCMR / local
registry / "Unknown".
- NEW test/unit/wallet/metadata-commitment.test.ts: 32/32 pass. Round-
trips every asset class, pins the exact byte layout, exercises every
rejection case including the AdjustableFee-ScriptNum ambiguity.
- src/wallet/genesis.ts: GenesisIntent gains optional `assetClass`;
prepareGenesis populates GenesisPlan.metadataCommitmentHex when the
caller provides it AND adjustableFee is not set. Encoder failures
(ticker too long, non-ASCII, decimals out of range) become INFO
warnings on the plan — never block genesis.
- src/wallet/wallet.ts: createAsset picks the NFT shape by precedence:
(1) adjustable-fee ScriptNum commitment, (2) ADR-0057 metadata
commitment, (3) empty default (prior behaviour).
- wiki/decisions.md: ADR-0057 appended — the three-layer split, the
binary layout, the AdjustableFee disambiguation rule, and what steps
2 (Sia BCMR mirror) and 3 (BCMR consumer in shells/app) still owe.
Backward-compatible by construction: callers that don't set assetClass
get the exact prior commitment: '' default. 47/47 tests green (existing
genesis.test + new metadata-commitment.test). Core tsc clean.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>