feat(wallet-metadata): Artemision opts into the ADR-0057 commitment on every MBA genesis

The wizard already classifies the user's intent via mint/supply/backing
axes (DEA / PLA / MCA / MTA) — now it also threads that `assetClass`
into the `GenesisIntent` so the planner can emit the 40-byte metadata
commitment on the minting NFT. Zero new UI copy; from this commit on,
every non-adjustable-fee MBA minted through Artemision carries a fully-
on-chain, offline-resolvable (ticker + decimals + class) record on its
minting-baton NFT.

- shells/app/src/screens/ArtemisionScreen.tsx:
  • Import classifyAssetClass from @core/token/assetClass
  • Compute mbaAssetClass = classifyAssetClass({backing:'mba', mint, supply})
    at plan time
  • Pass it to planGenesis as `assetClass`, mutually exclusive with
    `adjustableFee` (that path uses the commitment for live feeBps —
    the planner's own guard refuses the overlay; the UI mirrors it
    at the call site for clarity)

- wiki/decisions.md: ADR-0057 "UI opt-in path" section updated from
  "deferred" → "SHIPPED", and the NBA case called out as a follow-on
  because ADR-0054 (capped NBA cap-as-consensus) skips the minting NFT
  entirely for capped assets so the commitment has no carrier.

Regression:
- Full Vite build clean (shells/app)
- 47/47 core tests (test/unit/wallet/metadata-commitment + genesis)
- 31/31 shells/app BCMR-resolver tests
- tsc clean on shells/app

With steps 1 + 2 + 3 + UI opt-in all shipped, the metadata stack is
end-to-end for MBAs: Artemision wizard → planner emits NFT commitment +
BCMR OP_RETURN → BCMR uploaded to Sia via /api/bcmr-upload → consumer
in shells/app resolves it on first balance load → ticker/name shown.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Local Dev 2026-10-22 22:52:01 +03:00
parent 74a15d592e
commit f9be2bd593
2 changed files with 21 additions and 7 deletions

View file

@ -7,6 +7,7 @@ import { binToHex } from '@core/utils/hex.js';
import type { AssetDetailToken } from './AssetDetail';
import type { DisplayBalance } from '@core/wallet/display.js';
import { defaultDenomination, formatUnits } from '@core/tokenMetadata.js';
import { classifyAssetClass } from '@core/token/assetClass.js';
import { KatalogosPanel } from './KatalogosPanel';
import { TokenImportModal } from '../components/TokenImportModal';
@ -340,6 +341,12 @@ function Wizard({ session, onExit }: { session: CoreSession | null; onExit: () =
founderPubKeyHex: binToHex(raw),
};
})() : null;
// ADR-0057 opt-in: compute the asset class from the wizard's mint/supply
// axes and pass it so the planner emits the 40-byte metadata commitment
// on the minting NFT (ticker + decimals + class). Skipped on adjustable-
// fee mode — that covenant uses the commitment for live feeBps state
// and the planner's own guard refuses the overlay (mutually exclusive).
const mbaAssetClass = classifyAssetClass({ backing: 'mba', mint, supply });
const promise = isMba
? planGenesis(session, {
name: name.trim(),
@ -347,7 +354,7 @@ function Wizard({ session, onExit }: { session: CoreSession | null; onExit: () =
rateSats: denom.atomicRateSats,
founderFeeBps,
decimals: denom.decimals,
...(adjustableFee ? { adjustableFee } : {}),
...(adjustableFee ? { adjustableFee } : { assetClass: mbaAssetClass }),
}).then((p) => { if (!cancelled) { setNbaPlan(null); setPlan(p); } })
: planNbaGenesis(session, {
name: name.trim(),

View file

@ -3321,13 +3321,20 @@ the BCMR JSON extensions into their own on-chain OP_RETURN so Deviant wallets
can reconstruct an unseen MBA covenant without any HTTP hop. Only worth it
once we have a fully-offline demo use case.
### UI opt-in path
### UI opt-in path ✅ SHIPPED
Artemision wizard needs a one-liner change later: pass the already-classified
`assetClass` (which the create flow computes from mint/supply/backing axes
anyway via `classifyAssetClass()`) into `prepareGenesis`. Zero new UI; purely
plumbing in `ArtemisionScreen.tsx` when it builds the `GenesisIntent`. Left for
the follow-on so this ADR commit is scope-tight.
`ArtemisionScreen.tsx` now computes `mbaAssetClass = classifyAssetClass({
backing: 'mba', mint, supply })` from the wizard's existing mint/supply axes
and threads it into the MBA `GenesisIntent`. Opt-in is mutually exclusive with
`adjustableFee`: when the user picks adjustable-fee mode the wizard skips the
`assetClass` because the covenant uses the commitment for live state. Zero new
UI copy; the metadata just starts appearing on every non-adjustable MBA
genesis.
NBA genesis path deferred: `DeviantOpenMintNBA` (ADR-0054) skips the minting
NFT entirely on capped NBAs so the commitment has no carrier. An uncapped NBA
could carry the commitment on its baton; follow-on session to pick the right
UTXO carrier per NBA mint rule and wire the planner.
### Consequences