Numeric constants ported from dynamic-js-sdk's packages/bitcoin/src/
constants.ts. MUST stay identical to that file, and to this same file's
ports in kotlin-btc/swift-btc/csharp-btc — a drifted vSize or dust limit
silently produces a different fee than the JS SDK computes for the exact
same UTXOs, not something either language's own tests would catch alone.
Send priority, mapped onto an esplora confirmationTarget (see
BtcFeePlan.feeFor's doc) — NOT mempool.space's fastestFee/
halfHourFee/economyFee tiers, which the real SDK reads but this SDK's
actual API host (blockstream.info) doesn't expose.
Builds an unsigned PSBT (base64) sending amountInSatoshis to
recipientAddress from accountAddress — ports buildPsbt.ts's assembly
step (the fetch+selection+fee steps above are its utils). publicKeyHex
is accountAddress's own pubkey (from VerifiedCredential.
walletAdditionalAddresses — see that field's doc), needed to build the
P2WPKH witness script each input's witnessUtxo carries. Callers own
fetching allUtxos/feeEstimates (via the injected BtcService) — this
function is pure. isTestnet selects which bech32 HRP ('tb' vs 'bc') the
recipient/change addresses are validated against — the Dart equivalent of
the Kotlin/JS port's chainHash/network parameter.
HIGH maps to a 2-block confirmation target, MEDIUM to 6, LOW to 24 — the
only part of fee estimation that stays here, because the enum is a Dart
enum and the IR has none. Everything the target is then USED for lives in
BtcFeePlan (generated from packages/spec/src/btc.fee-rules.ts).
Finalizes a SIGNED (but not yet finalized) PSBT — after the MPC ceremony
(WalletSigner.signTransaction) attaches a partial signature per input,
this reads each input's own PSBT_IN_PARTIAL_SIG entry for publicKeyHex
(written by the server) and builds the P2WPKH witness stack
signature, pubkey by hand, exactly mirroring kotlin-btc's
finalizeAndExtract (there: reading bitcoin-kmp's own parsed partialSigs
map instead of hand-parsing PSBT bytes). Returns the finalized,
broadcastable raw tx hex.
Ports validateAndSelectUTXOs.ts: if the largest-first selection already
covers amount+fee, keep it; otherwise widen to ALL UTXOs if that's enough,
else throw. Deliberately never partially widens beyond "everything" —
matches the JS SDK's own fallback exactly.