a42b1e0f32
Implements the send half of the onchain zaps plan: a minimal, fund-safe BIP-174 PSBT pipeline plus the OnchainZapBuilder and `NostrSigner.signPsbt`. Every cryptographic step is validated against the BIP-341 wallet test vectors. nipBCOnchainZaps/psbt/: - BitcoinIO: little-endian Bitcoin consensus byte reader/writer (u16/u32/u64, compact-size varint, var-bytes). - BitcoinTransaction: OutPoint / TxIn / TxOut / transaction model with legacy and BIP-144 segwit serialization, segwit-aware parsing, and witness-stripped txid. Validated against the genesis coinbase tx and the BIP-341 9-input unsigned tx. - TaprootSigHash: BIP-341 SigMsg + TapSighash tagged hash for key-path spends. All six base sighash types plus both ANYONECANPAY variants verified against the seven BIP-341 keyPathSpending vectors. - Psbt: BIP-174 container subset (global unsigned-tx, per-input witness-utxo / tap-internal-key / tap-key-sig / sighash-type, per-output tap-internal-key). Unknown records round-trip verbatim. Typed accessor extensions. - PsbtSigner: signs the key-path P2TR inputs a given private key controls — derives the BIP-341 tweaked key, computes the all-inputs sighash, produces a BIP-340 Schnorr signature. Leaves inputs the key does not control untouched. - PsbtFinalizer: moves tap-key-sigs into the witness stack, yields a broadcastable transaction. nipBCOnchainZaps/build/: - OnchainZapBuilder: largest-first coin selection + unsigned-PSBT assembly for a NIP-BC zap. Sender spends from / changes back to the single Taproot address derived from their Nostr pubkey; recipient output pays the recipient's derived address. Dust-aware change handling, InsufficientFundsException, self-zap and dust-amount guards. nipBCOnchainZaps/taproot/: - TaprootAddress.tweakSecretKey: BIP-341 taproot_tweak_seckey (key-path-only), including the odd-y internal-key negation. Validated against the BIP-341 vector's tweakedPrivkey. Secp256k1Instance: new `privKeyNegate` primitive across commonMain expect + jvm / android / native actuals. Signer hierarchy — new `NostrSigner.signPsbt(psbtHex): String`: - NostrSignerSync / NostrSignerInternal: real implementation. - NostrSignerWithClientTag: delegates to the wrapped signer. - NostrSignerRemote (NIP-46) and NostrSignerExternal (NIP-55): throw SignerExceptions.UnsupportedMethodException — the bunker command and the Android Intent contract are Phase B, and depend on signer-app support. Tests: 31 new tests across the psbt/build/signers packages, anchored on the BIP-341 wallet-test-vectors so the tweak, sighash, signature, and finalized transaction are all checked against an authoritative source. Still pending: Phase B (NIP-55 sign_psbt Intent) and Phase D (send UI + broadcast + publish kind 8333).