1111 */
1212import { describe , it } from "mocha" ;
1313import * as assert from "assert" ;
14- import * as utxolib from "@bitgo/utxo-lib" ;
1514import { BitGoPsbt , type HydrationUnspent } from "../../js/fixedScriptWallet/BitGoPsbt.js" ;
1615import { ZcashBitGoPsbt } from "../../js/fixedScriptWallet/ZcashBitGoPsbt.js" ;
16+ import { supportsScriptType } from "../../js/fixedScriptWallet/index.js" ;
1717import { ChainCode } from "../../js/fixedScriptWallet/chains.js" ;
1818import { ECPair } from "../../js/ecpair.js" ;
1919import { Transaction } from "../../js/transaction.js" ;
20+ import { coinNames , type CoinName , isMainnet } from "../../js/coinName.js" ;
2021import { getDefaultWalletKeys , getKeyTriple } from "../../js/testutils/keys.js" ;
21- import { getCoinNameForNetwork } from "../networks.js" ;
2222
2323const ZCASH_NU5_HEIGHT = 1687105 ;
2424
2525const p2msScriptTypes = [ "p2sh" , "p2shP2wsh" , "p2wsh" ] as const ;
2626
27- function isSupportedNetwork ( n : utxolib . Network ) : boolean {
28- return utxolib . isMainnet ( n ) && n !== utxolib . networks . bitcoinsv && n !== utxolib . networks . ecash ;
27+ // Coins excluded from round-trip tests (use special handling or not supported)
28+ const EXCLUDED_COINS : CoinName [ ] = [ "bsv" , "bcha" , "zec" ] ;
29+
30+ function isSupportedCoin ( coin : CoinName ) : boolean {
31+ return isMainnet ( coin ) && ! EXCLUDED_COINS . includes ( coin ) ;
2932}
3033
3134function createHalfSignedP2msPsbt (
32- network : utxolib . Network ,
35+ coinName : CoinName ,
3336 valueOverride ?: bigint ,
3437) : { psbt : BitGoPsbt ; unspents : HydrationUnspent [ ] } {
35- const coinName = getCoinNameForNetwork ( network ) ;
3638 const rootWalletKeys = getDefaultWalletKeys ( ) ;
3739 const [ userXprv ] = getKeyTriple ( "default" ) ;
3840
3941 const supportedTypes = p2msScriptTypes . filter ( ( scriptType ) =>
40- utxolib . bitgo . outputScripts . isSupportedScriptType ( network , scriptType ) ,
42+ supportsScriptType ( coinName , scriptType ) ,
4143 ) ;
4244
43- const isZcash = utxolib . getMainnet ( network ) === utxolib . networks . zcash ;
45+ const isZcash = coinName === "zec" || coinName === "tzec" ;
4446 const psbt = isZcash
4547 ? ZcashBitGoPsbt . createEmpty ( coinName as "zec" | "tzec" , rootWalletKeys , {
4648 version : 4 ,
@@ -79,7 +81,7 @@ describe("BitGoPsbt.fromHalfSignedLegacyTransaction", function () {
7981 // because BigInt::from(value_js).as_f64() calls JsValue::as_f64(), which
8082 // returns None for JS BigInt (it only works for JS Number).
8183 const rootWalletKeys = getDefaultWalletKeys ( ) ;
82- const { psbt, unspents } = createHalfSignedP2msPsbt ( utxolib . networks . bitcoin ) ;
84+ const { psbt, unspents } = createHalfSignedP2msPsbt ( "btc" ) ;
8385 const txBytes = psbt . getHalfSignedLegacyFormat ( ) ;
8486
8587 assert . doesNotThrow ( ( ) => {
@@ -93,7 +95,7 @@ describe("BitGoPsbt.fromHalfSignedLegacyTransaction", function () {
9395 const rootWalletKeys = getDefaultWalletKeys ( ) ;
9496 // 21 million BTC in satoshis — the maximum possible UTXO value
9597 const maxSats = 21_000_000n * 100_000_000n ;
96- const { psbt, unspents } = createHalfSignedP2msPsbt ( utxolib . networks . bitcoin , maxSats ) ;
98+ const { psbt, unspents } = createHalfSignedP2msPsbt ( "btc" , maxSats ) ;
9799 const txBytes = psbt . getHalfSignedLegacyFormat ( ) ;
98100
99101 assert . doesNotThrow ( ( ) => {
@@ -103,19 +105,13 @@ describe("BitGoPsbt.fromHalfSignedLegacyTransaction", function () {
103105 } ) ;
104106
105107 describe ( "Round-trip: getHalfSignedLegacyFormat → fromHalfSignedLegacyTransaction" , function ( ) {
106- // Zcash uses a non-standard transaction format (version 4 overwintered) that
107- // fromHalfSignedLegacyTransaction does not support; skip it here.
108- const roundTripNetworks = utxolib
109- . getNetworkList ( )
110- . filter ( isSupportedNetwork )
111- . filter ( ( n ) => utxolib . getMainnet ( n ) !== utxolib . networks . zcash ) ;
112-
113- for ( const network of roundTripNetworks ) {
114- const networkName = utxolib . getNetworkName ( network ) ;
115- it ( `${ networkName } : reconstructed PSBT serializes without error` , function ( ) {
108+ // Supported coins for round-trip: all mainnet UTXO coins except special formats
109+ const roundTripCoins = coinNames . filter ( isSupportedCoin ) ;
110+
111+ for ( const coinName of roundTripCoins ) {
112+ it ( `${ coinName } : reconstructed PSBT serializes without error` , function ( ) {
116113 const rootWalletKeys = getDefaultWalletKeys ( ) ;
117- const coinName = getCoinNameForNetwork ( network ) ;
118- const { psbt, unspents } = createHalfSignedP2msPsbt ( network ) ;
114+ const { psbt, unspents } = createHalfSignedP2msPsbt ( coinName ) ;
119115 const txBytes = psbt . getHalfSignedLegacyFormat ( ) ;
120116
121117 const reconstructed = BitGoPsbt . fromHalfSignedLegacyTransaction (
@@ -178,7 +174,7 @@ describe("BitGoPsbt.fromHalfSignedLegacyTransaction", function () {
178174 // With dynamic dispatch, fromHalfSignedLegacyTransaction now validates the transaction type
179175 // and rejects Zcash early with a clear error message, directing to ZcashBitGoPsbt.createEmpty().
180176 const rootWalletKeys = getDefaultWalletKeys ( ) ;
181- const { psbt : zcashPsbt , unspents } = createHalfSignedP2msPsbt ( utxolib . networks . zcash ) ;
177+ const { psbt : zcashPsbt , unspents } = createHalfSignedP2msPsbt ( "zec" ) ;
182178
183179 // Step 1: Extract Zcash PSBT as legacy format
184180 const txBytes = zcashPsbt . getHalfSignedLegacyFormat ( ) ;
@@ -197,7 +193,7 @@ describe("BitGoPsbt.fromHalfSignedLegacyTransaction", function () {
197193 it ( "should round-trip Zcash PSBT via ZcashBitGoPsbt.fromHalfSignedLegacyTransaction (with blockHeight)" , function ( ) {
198194 // This test verifies the round-trip: create Zcash PSBT → extract legacy format → reconstruct PSBT
199195 const rootWalletKeys = getDefaultWalletKeys ( ) ;
200- const { psbt, unspents } = createHalfSignedP2msPsbt ( utxolib . networks . zcash ) ;
196+ const { psbt, unspents } = createHalfSignedP2msPsbt ( "zec" ) ;
201197
202198 // Step 1: Extract half-signed legacy format (this is what would be transmitted)
203199 const legacyBytes = psbt . getHalfSignedLegacyFormat ( ) ;
@@ -227,7 +223,7 @@ describe("BitGoPsbt.fromHalfSignedLegacyTransaction", function () {
227223 it ( "should round-trip Zcash PSBT via ZcashBitGoPsbt.fromHalfSignedLegacyTransaction (with consensusBranchId)" , function ( ) {
228224 // This test verifies the round-trip with explicit consensus branch ID instead of block height
229225 const rootWalletKeys = getDefaultWalletKeys ( ) ;
230- const { psbt, unspents } = createHalfSignedP2msPsbt ( utxolib . networks . zcash ) ;
226+ const { psbt, unspents } = createHalfSignedP2msPsbt ( "zec" ) ;
231227
232228 // Step 1: Extract half-signed legacy format
233229 const legacyBytes = psbt . getHalfSignedLegacyFormat ( ) ;
@@ -258,7 +254,7 @@ describe("BitGoPsbt.fromHalfSignedLegacyTransaction", function () {
258254 // Dynamic dispatch enhancement: fromHalfSignedLegacyTransaction now accepts
259255 // either txBytes OR a pre-decoded ITransaction instance
260256 const rootWalletKeys = getDefaultWalletKeys ( ) ;
261- const { psbt, unspents } = createHalfSignedP2msPsbt ( utxolib . networks . bitcoin ) ;
257+ const { psbt, unspents } = createHalfSignedP2msPsbt ( "btc" ) ;
262258 const txBytes = psbt . getHalfSignedLegacyFormat ( ) ;
263259
264260 // Method 1: Pass raw bytes (uses dynamic dispatch internally)
0 commit comments