Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 46 additions & 2 deletions packages/wasm-utxo/js/fixedScriptWallet/BitGoPsbt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,19 +193,22 @@ export class BitGoPsbt extends PsbtBase<WasmBitGoPsbt> implements IPsbtWithAddre
/**
* Convert a half-signed legacy transaction to a psbt-lite.
*
* @deprecated Use `fromNetworkFormat()` instead. Signature-count enforcement
* (exactly 1 sig per wallet input) is moving to the caller.
*
* Extracts partial signatures from scriptSig/witness and creates a PSBT
* with proper wallet metadata (bip32Derivation, scripts, witnessUtxo).
* Only supports p2sh, p2shP2wsh, and p2wsh inputs (not taproot).
*
* Supports both Bitcoin-like coins (BTC, LTC, DOGE) and Dash (DASH).
* Zcash is NOT supported; use ZcashBitGoPsbt.fromHalfSignedLegacyTransaction instead.
* Zcash is NOT supported; use ZcashBitGoPsbt.fromNetworkFormat instead.
*
* @param txBytesOrTx - Transaction bytes or decoded transaction instance (Bitcoin-like or Dash)
* @param network - Network name
* @param walletKeys - The wallet's root keys
* @param unspents - Chain, index, and value for each input
* @param _options - Reserved for future use and signature compatibility with subclasses
* @throws Error if transaction is Zcash (use ZcashBitGoPsbt.fromHalfSignedLegacyTransaction instead)
* @throws Error if transaction is Zcash (use ZcashBitGoPsbt.fromNetworkFormat instead)
*/
static fromHalfSignedLegacyTransaction(
txBytesOrTx: Uint8Array | Transaction | DashTransaction,
Expand Down Expand Up @@ -243,6 +246,47 @@ export class BitGoPsbt extends PsbtBase<WasmBitGoPsbt> implements IPsbtWithAddre
return new BitGoPsbt(wasm);
}

/**
* Convert a network-format transaction to a PSBT.
*
* Accepts both the half-signed legacy format (5-slot scriptSig/witness with OP_0
* placeholders) and the fully-signed network format (compact 4-item form). The
* resulting PSBT will contain all partial signatures present in the transaction.
*
* Use this when you don't know ahead of time whether the transaction is half-signed
* or fully-signed. For Zcash, use ZcashBitGoPsbt.fromNetworkFormat() instead.
*
* @param txBytesOrTx - Transaction bytes or decoded Transaction/DashTransaction
* @param network - Network name
* @param walletKeys - The wallet's root keys
* @param unspents - Chain, index, and value for each input
*/
static fromNetworkFormat(
txBytesOrTx: Uint8Array | Transaction | DashTransaction,
network: NetworkName,
walletKeys: WalletKeysArg,
unspents: HydrationUnspent[],
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_options?: unknown,
): BitGoPsbt {
const keys = RootWalletKeys.from(walletKeys);

const tx =
txBytesOrTx instanceof Uint8Array
? Transaction.fromBytes(txBytesOrTx, toCoinName(network))
: txBytesOrTx;

if (tx instanceof ZcashTransaction) {
throw new Error("Use ZcashBitGoPsbt.fromNetworkFormat() for Zcash transactions");
}

const wasm: WasmBitGoPsbt =
tx instanceof DashTransaction
? WasmBitGoPsbt.from_network_format_dash(tx.wasm, network, keys.wasm, unspents)
: WasmBitGoPsbt.from_network_format(tx.wasm, network, keys.wasm, unspents);
return new BitGoPsbt(wasm);
}

/**
* Add an input to the PSBT
*
Expand Down
80 changes: 54 additions & 26 deletions packages/wasm-utxo/js/fixedScriptWallet/ZcashBitGoPsbt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,14 @@ export class ZcashBitGoPsbt extends BitGoPsbt {
}

/**
* Reconstruct a Zcash PSBT from a half-signed legacy transaction
* Reconstruct a Zcash PSBT from a network-format transaction (unsigned, half-signed, or fully-signed).
*
* This is the inverse of `getHalfSignedLegacyFormat()` for Zcash. It decodes the Zcash wire
* format (which includes version_group_id, expiry_height, and sapling fields), extracts
* partial signatures, and reconstructs a proper Zcash PSBT with consensus metadata.
* This is the Zcash equivalent of `BitGoPsbt.fromNetworkFormat()`. It decodes the Zcash wire
* format (which includes version_group_id, expiry_height, and sapling fields), extracts any
* partial signatures present, and reconstructs a proper Zcash PSBT with consensus metadata.
*
* Use this as the modern replacement for `fromHalfSignedLegacyTransaction`. Signature-count
* discovery (unsigned / half-signed / fully-signed) is left to the caller.
*
* Supports two modes for determining consensus_branch_id:
* - **Recommended**: Pass `blockHeight` to auto-determine consensus_branch_id via network upgrade activation heights
Expand All @@ -161,28 +164,53 @@ export class ZcashBitGoPsbt extends BitGoPsbt {
* @param unspents - Chain, index, and value for each input
* @param options - Either `{ blockHeight: number }` or `{ consensusBranchId: number }`
* @returns A ZcashBitGoPsbt instance
*/
static fromNetworkFormat(
txBytesOrTx: Uint8Array | ITransaction,
network: ZcashNetworkName,
walletKeys: WalletKeysArg,
unspents: HydrationUnspent[],
options: { blockHeight: number } | { consensusBranchId: number },
): ZcashBitGoPsbt {
const keys = RootWalletKeys.from(walletKeys);
const tx =
txBytesOrTx instanceof Uint8Array
? ZcashTransaction.fromBytes(txBytesOrTx)
: (txBytesOrTx as ZcashTransaction);

if ("blockHeight" in options) {
const wasm = WasmBitGoPsbt.from_network_format_zcash_with_block_height(
tx.wasm,
network,
keys.wasm,
unspents,
options.blockHeight,
);
return new ZcashBitGoPsbt(wasm);
} else {
const wasm = WasmBitGoPsbt.from_network_format_zcash_with_branch_id(
tx.wasm,
network,
keys.wasm,
unspents,
options.consensusBranchId,
);
return new ZcashBitGoPsbt(wasm);
}
}

/**
* Reconstruct a Zcash PSBT from a half-signed legacy transaction.
*
* @example
* ```typescript
* // Round-trip with block height (recommended)
* const legacyBytes = psbt.getHalfSignedLegacyFormat();
* const reconstructed = ZcashBitGoPsbt.fromHalfSignedLegacyTransaction(
* legacyBytes,
* "zec",
* walletKeys,
* unspents,
* { blockHeight: 1687105 } // NU5 activation height
* );
* @deprecated Use `fromNetworkFormat()` instead. Signature-count enforcement
* (exactly 1 sig per wallet input) is moving to the caller.
*
* // Or with explicit consensus branch ID
* const reconstructed = ZcashBitGoPsbt.fromHalfSignedLegacyTransaction(
* legacyBytes,
* "zec",
* walletKeys,
* unspents,
* { consensusBranchId: 0xC2D6D0B4 } // NU5 branch ID
* );
* ```
* @param txBytesOrTx - Either serialized Zcash transaction bytes or a decoded ZcashTransaction instance
* @param network - Zcash network name ("zcash", "zcashTest", "zec", "tzec")
* @param walletKeys - The wallet's root keys
* @param unspents - Chain, index, and value for each input
* @param options - Either `{ blockHeight: number }` or `{ consensusBranchId: number }`
* @returns A ZcashBitGoPsbt instance
*/
static fromHalfSignedLegacyTransaction(
txBytesOrTx: Uint8Array | ITransaction,
Expand All @@ -198,7 +226,7 @@ export class ZcashBitGoPsbt extends BitGoPsbt {
: (txBytesOrTx as ZcashTransaction);

if ("blockHeight" in options) {
const wasm = WasmBitGoPsbt.from_half_signed_legacy_transaction_zcash_with_block_height(
const wasm = WasmBitGoPsbt.from_network_format_zcash_with_block_height(
tx.wasm,
network,
keys.wasm,
Expand All @@ -207,7 +235,7 @@ export class ZcashBitGoPsbt extends BitGoPsbt {
);
return new ZcashBitGoPsbt(wasm);
} else {
const wasm = WasmBitGoPsbt.from_half_signed_legacy_transaction_zcash_with_branch_id(
const wasm = WasmBitGoPsbt.from_network_format_zcash_with_branch_id(
tx.wasm,
network,
keys.wasm,
Expand Down
Loading
Loading