The counterpart to the importer, and the thing that stops it being a one-way
door. Without it an extension backup is readable only by polkadot-js-format
tooling, so a user who brought a wallet in could not take it back out.
The assumption that blocked this — that we cannot write the CLI format because we
do not store a mnemonic — turns out to be false. The format has a null-mnemonic
shape and the CLI writes one itself for every raw-seed wallet; crystal_alice,
which `quantus developer create-test-wallets` produces, has exactly that
alongside `derivation_path: "m/"`.
Verified against quantus-cli 2.2.2 rather than inferred. Exports of both schemes
were written into ~/.quantus/wallets and the CLI listed them with the correct
address, scheme and human checkphrase, showed them under `wallet view`, and
answered `export --format mnemonic` with "Mnemonic phrase is not available for
this wallet" — which is a correct statement about the file, and only reachable by
deriving the Argon2 key, opening the AES-GCM box and parsing the payload. Those
probes were removed; the committed test round-trips through our own importer,
since CI has no CLI.
What a null-mnemonic export costs the user is exactly one thing, and it is not
spending: the CLI cannot re-export a phrase from it or derive further accounts.
That is the honest consequence of never storing a phrase we showed once, and it
is the same position a raw-seed CLI wallet is already in.
Argon2 parameters match the CLI's rather than being raised. They travel in the
file and the CLI reads them, so in principle anything works — but "in principle"
is load-bearing there, and a wallet a slightly older CLI cannot open is worse
than a conservatively tuned KDF. Salt and nonce are fresh per export.
metadata.exported_by marks the file, so a CLI maintainer reading a bug report can
tell where it came from without inferring from shape.
Refs quantus/common#8
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012uDUodEcRbBwNRi3UCmw8f