A ChainAdapter for Substrate chains that is driven by runtime metadata plus a small per-chain profile, so that Quantus mainnet, Heisenberg and any later post-quantum Substrate chain are profiles rather than crates. It talks only to our own nodes over TLS, since public endpoints do not exist.
Facts the design rests on
quantus-cli already carries a working subxt Config with the Dilithium signature enum and the two custom transaction extensions (ReversibleTransactionExtension, WormholeProofRecorderExtension, neither contributes signed bytes). Lift it; do not re-derive it.
subxt 0.50 needs that custom Config; 0.51 adds a custom_extension builder. Track it, do not wait for it.
The signing context depends on specVersion; the adapter reads the runtime version at connect and on every runtime upgrade.
Incoming transfers may be signed by either scheme variant; both decode.
High-security accounts must use the reversible-transfers extrinsics and are blocked from plain transfers by the extension; the adapter must know which kind of account it is sending from.
Operator-owned decisions
Endpoint list and TLS: which hosts, and whether mTLS or a bearer token authenticates the wallet to our nodes. Needed before the RPC child; recorded on that issue.
History source: block scanning in the wallet, or an indexer on our infra (blackbeard.observer already ingests every block). Default: indexer, exposed through the relay; the wallet never scans.
Definition of done
Against a dev node in CI and against Heisenberg from a laptop: connect, read balance and nonce, build a transfer_keep_alive, sign with the wallet's ML-DSA-65 key, submit, watch it to finality, and see the balance move. The same binary does the same against mainnet with only a profile change.
## Goal
A `ChainAdapter` for Substrate chains that is driven by runtime metadata plus a small per-chain profile, so that Quantus mainnet, Heisenberg and any later post-quantum Substrate chain are profiles rather than crates. It talks only to our own nodes over TLS, since public endpoints do not exist.
## Facts the design rests on
- quantus-cli already carries a working subxt `Config` with the Dilithium signature enum and the two custom transaction extensions (`ReversibleTransactionExtension`, `WormholeProofRecorderExtension`, neither contributes signed bytes). Lift it; do not re-derive it.
- subxt 0.50 needs that custom `Config`; 0.51 adds a `custom_extension` builder. Track it, do not wait for it.
- The signing context depends on `specVersion`; the adapter reads the runtime version at connect and on every runtime upgrade.
- Incoming transfers may be signed by either scheme variant; both decode.
- High-security accounts must use the reversible-transfers extrinsics and are blocked from plain transfers by the extension; the adapter must know which kind of account it is sending from.
## Operator-owned decisions
- Endpoint list and TLS: which hosts, and whether mTLS or a bearer token authenticates the wallet to our nodes. **Needed before the RPC child; recorded on that issue.**
- History source: block scanning in the wallet, or an indexer on our infra (blackbeard.observer already ingests every block). **Default: indexer, exposed through the relay; the wallet never scans.**
## Definition of done
Against a dev node in CI and against Heisenberg from a laptop: connect, read balance and nonce, build a `transfer_keep_alive`, sign with the wallet's ML-DSA-65 key, submit, watch it to finality, and see the balance move. The same binary does the same against mainnet with only a profile change.
Children, in dependency order: #18 (chain profiles) → #19 (subxt config) and #20 (RPC to our nodes) → #21 (balances and heads) → #22 (transfer with reversal). #23 (history via indexer) and #24 (dev node in CI) run in parallel from #18 and #19 respectively.
Children, in dependency order: #18 (chain profiles) → #19 (subxt config) and #20 (RPC to our nodes) → #21 (balances and heads) → #22 (transfer with reversal). #23 (history via indexer) and #24 (dev node in CI) run in parallel from #18 and #19 respectively.
Added #53 (public node endpoints on oolon, throttled, routed to bob), the infrastructure half of the decision recorded on #20. It has no code dependency and can start now; #20 consumes its result.
Added #53 (public node endpoints on oolon, throttled, routed to bob), the infrastructure half of the decision recorded on #20. It has no code dependency and can start now; #20 consumes its result.
Every child is closed: #18, #19, #20, #21, #22, #23, #24 and #53. The chain layer as it stands: profiles shipped as TOML with operator overrides; a subxt config for ML-DSA signatures under the FIPS 204 context from spec 148; a connection manager with failover, backoff, a polling runtime-version watch and a measured block interval; balances and pending reversible transfers read at the best block with the finalized height alongside (the PoW finality lag is about 100 blocks); transfers, reversible transfers and cancels prepared for review, priced, signed by the session and watched; history from blackbeard.observer cached in SQLite; a pinned quantus-node --dev in CI; and the public names wss://quantus.blackbeard.observer and wss://planck.blackbeard.observer on oolon, throttled per client. Closing the epic.
Every child is closed: #18, #19, #20, #21, #22, #23, #24 and #53. The chain layer as it stands: profiles shipped as TOML with operator overrides; a subxt config for ML-DSA signatures under the FIPS 204 context from spec 148; a connection manager with failover, backoff, a polling runtime-version watch and a measured block interval; balances and pending reversible transfers read at the best block with the finalized height alongside (the PoW finality lag is about 100 blocks); transfers, reversible transfers and cancels prepared for review, priced, signed by the session and watched; history from blackbeard.observer cached in SQLite; a pinned `quantus-node --dev` in CI; and the public names `wss://quantus.blackbeard.observer` and `wss://planck.blackbeard.observer` on oolon, throttled per client. Closing the epic.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Goal
A
ChainAdapterfor Substrate chains that is driven by runtime metadata plus a small per-chain profile, so that Quantus mainnet, Heisenberg and any later post-quantum Substrate chain are profiles rather than crates. It talks only to our own nodes over TLS, since public endpoints do not exist.Facts the design rests on
Configwith the Dilithium signature enum and the two custom transaction extensions (ReversibleTransactionExtension,WormholeProofRecorderExtension, neither contributes signed bytes). Lift it; do not re-derive it.Config; 0.51 adds acustom_extensionbuilder. Track it, do not wait for it.specVersion; the adapter reads the runtime version at connect and on every runtime upgrade.Operator-owned decisions
Definition of done
Against a dev node in CI and against Heisenberg from a laptop: connect, read balance and nonce, build a
transfer_keep_alive, sign with the wallet's ML-DSA-65 key, submit, watch it to finality, and see the balance move. The same binary does the same against mainnet with only a profile change.Children, in dependency order: #18 (chain profiles) → #19 (subxt config) and #20 (RPC to our nodes) → #21 (balances and heads) → #22 (transfer with reversal). #23 (history via indexer) and #24 (dev node in CI) run in parallel from #18 and #19 respectively.
Added #53 (public node endpoints on oolon, throttled, routed to bob), the infrastructure half of the decision recorded on #20. It has no code dependency and can start now; #20 consumes its result.
Every child is closed: #18, #19, #20, #21, #22, #23, #24 and #53. The chain layer as it stands: profiles shipped as TOML with operator overrides; a subxt config for ML-DSA signatures under the FIPS 204 context from spec 148; a connection manager with failover, backoff, a polling runtime-version watch and a measured block interval; balances and pending reversible transfers read at the best block with the finalized height alongside (the PoW finality lag is about 100 blocks); transfers, reversible transfers and cancels prepared for review, priced, signed by the session and watched; history from blackbeard.observer cached in SQLite; a pinned
quantus-node --devin CI; and the public nameswss://quantus.blackbeard.observerandwss://planck.blackbeard.observeron oolon, throttled per client. Closing the epic.