phase 2.5-2.6: native asset send + cold-sign flow

InputUtxo gains an `assets: BTreeMap<String, u64>` field matching
aldabra-chain::Utxo's shape (`policy_id_hex(56) || asset_name_hex`
key). new AssetSpec type for the recipient asset list.

asset-aware select_utxos:
- phase 1: per-asset greedy by holding size, pulls UTXOs containing
  each requested asset until coverage ≥ target
- phase 2: ada-only greedy to top up lovelace need
this preserves the prior ada-only behavior when assets list is empty.

build_signed_payment_with_assets / build_unsigned_payment_with_assets
build outputs with .add_asset() for each requested + each leftover
(change-side). guards: token-bearing change must hold ≥ min_utxo
ADA — surfaced as a clearer error than letting the chain reject a
sub-min output.

cold-sign flow (phase 2.6):
- new tools wallet.send.unsigned (returns {cbor_hex, summary} json
  for human review + cold-signer consumption) and
  wallet.submit_signed_tx (takes hex-encoded signed cbor → submit).
- PaymentSummary now carries send_assets + change_assets vecs so the
  human reviewer can spot accidental token transfers.
- summary.tx_hash is the predicted body hash; signed CBOR will hash
  to the same value (signature is over the body, not the cbor wrapper).

helpers: hex_encode/decode, parse_policy_id, parse_asset_name,
split_asset_key. mcp side defines its own McpAssetSpec with
schemars::JsonSchema derive so the schemars dep doesn't bleed into
the security-boundary core crate.

48 unit tests (was 41). new coverage: asset-aware selection (greedy +
missing-asset error), policy/asset-name parsers, multi-asset cbor
build, change-asset summary correctness.

phase 2.7 (live preprod smoke against funded wallet) procedure
documented in internal notes; needs sulkta's faucet ada.
This commit is contained in:
Sulkta 2026-05-04 11:35:06 -07:00
parent 44bae07bc9
commit a472695558
3 changed files with 823 additions and 91 deletions

View file

@ -38,7 +38,11 @@ use zeroize::ZeroizeOnDrop;
pub mod derive;
pub mod tx;
pub use derive::{derive_payment_key, derive_stake_key, PaymentKey, StakeKey};
pub use tx::{build_signed_payment, InputUtxo, ProtocolParams};
pub use tx::{
build_signed_payment, build_signed_payment_with_assets, build_unsigned_payment,
build_unsigned_payment_with_assets, hex_decode, AssetSpec, InputUtxo, PaymentSummary,
ProtocolParams, UnsignedPayment,
};
#[derive(Debug, Error)]
pub enum WalletError {