diff --git a/modules/abstract-utxo/src/abstractUtxoCoin.ts b/modules/abstract-utxo/src/abstractUtxoCoin.ts index 818bd23de9..26cd2c6a5e 100644 --- a/modules/abstract-utxo/src/abstractUtxoCoin.ts +++ b/modules/abstract-utxo/src/abstractUtxoCoin.ts @@ -2,9 +2,7 @@ import assert from 'assert'; import { randomBytes } from 'crypto'; import _ from 'lodash'; -import * as utxolib from '@bitgo/utxo-lib'; -import { BIP32, fixedScriptWallet, hasPsbtMagic } from '@bitgo/wasm-utxo'; -import { bitgo, getMainnet } from '@bitgo/utxo-lib'; +import { address as wasmAddress, BIP32, fixedScriptWallet, hasPsbtMagic } from '@bitgo/wasm-utxo'; import { AddressCoinSpecific, BaseCoin, @@ -62,7 +60,6 @@ import { getReplayProtectionPubkeys, isReplayProtectionUnspent } from './transac import { supportedCrossChainRecoveries } from './config'; import { assertValidTransactionRecipient, - DecodedTransaction, explainTx, fromExtendedAddressFormat, isScriptRecipient, @@ -77,14 +74,7 @@ import { ErrorImplicitExternalOutputs, } from './transaction/descriptor/verifyTransaction'; import { assertDescriptorWalletAddress, getDescriptorMapFromWallet, isDescriptorWallet } from './descriptor'; -import { - getFullNameFromCoinName, - getMainnetCoinName, - getNetworkFromCoinName, - isMainnetCoin, - UtxoCoinName, - UtxoCoinNameMainnet, -} from './names'; +import { getFullNameFromCoinName, getMainnetCoinName, isMainnetCoin, UtxoCoinName, UtxoCoinNameMainnet } from './names'; import { assertFixedScriptWalletAddress } from './address/fixedScript'; import { ParsedTransaction } from './transaction/types'; import { decodeDescriptorPsbt, decodePsbt, encodeTransaction, stringToBufferTryFormats } from './transaction/decode'; @@ -96,7 +86,7 @@ import { isUtxoWalletData, UtxoWallet } from './wallet'; import { isDescriptorWalletData } from './descriptor/descriptorWallet'; import type { Unspent } from './unspent'; -import ScriptType2Of3 = utxolib.bitgo.outputScripts.ScriptType2Of3; +type ScriptType2Of3 = 'p2sh' | 'p2shP2wsh' | 'p2wsh' | 'p2tr' | 'p2trMusig2'; export type TxFormat = // This is a legacy transaction format based around the bitcoinjs-lib serialization of unsigned transactions @@ -142,28 +132,19 @@ type UtxoCustomSigningFunction = { }): Promise; }; -const { isChainCode, scriptTypeForChain, outputScripts } = bitgo; - /** * Check if a decoded transaction has at least one taproot key path spend (MuSig2) input. - * Works for both utxolib UtxoPsbt and wasm-utxo BitGoPsbt. */ -function hasKeyPathSpendInput( - tx: DecodedTransaction, +function hasKeyPathSpendInput( + tx: fixedScriptWallet.BitGoPsbt, pubs: string[] | undefined, coinName: UtxoCoinName ): boolean { - if (tx instanceof bitgo.UtxoPsbt) { - return bitgo.isTransactionWithKeyPathSpendInput(tx); - } - if (tx instanceof fixedScriptWallet.BitGoPsbt) { - assert(pubs && isTriple(pubs), 'pub triple is required to check for key path spend inputs in wasm-utxo PSBT'); - const rootWalletKeys = fixedScriptWallet.RootWalletKeys.fromXpubs(pubs); - const replayProtection = { publicKeys: getReplayProtectionPubkeys(coinName) }; - const parsed = tx.parseTransactionWithWalletKeys(rootWalletKeys, { replayProtection }); - return parsed.inputs.some((input) => input.scriptType === 'p2trMusig2KeyPath'); - } - return false; + assert(pubs && isTriple(pubs), 'pub triple is required to check for key path spend inputs in wasm-utxo PSBT'); + const rootWalletKeys = fixedScriptWallet.RootWalletKeys.fromXpubs(pubs); + const replayProtection = { publicKeys: getReplayProtectionPubkeys(coinName) }; + const parsed = tx.parseTransactionWithWalletKeys(rootWalletKeys, { replayProtection }); + return parsed.inputs.some((input) => input.scriptType === 'p2trMusig2KeyPath'); } /** @@ -216,8 +197,6 @@ function convertValidationErrorToTxIntentMismatch( export type { DecodedTransaction } from './transaction/types'; -export type RootWalletKeys = bitgo.RootWalletKeys; - export type UtxoCoinSpecific = AddressCoinSpecific | DescriptorAddressCoinSpecific; export interface VerifyAddressOptions extends BaseVerifyAddressOptions { @@ -252,8 +231,6 @@ export interface DecoratedExplainTransactionOptions extends BaseTransactionPrebuild { txInfo?: TransactionInfo; blockHeight?: number; @@ -334,11 +311,6 @@ type UtxoBaseSignTransactionOptions = * When false, creates half-signed transaction with placeholder signatures. */ isLastSignature?: boolean; - /** - * If true, allows signing a non-segwit input with a witnessUtxo instead requiring a previous - * transaction (nonWitnessUtxo) - */ - allowNonSegwitSigningWithoutPrevTx?: boolean; /** * When true, the signed transaction will be converted from PSBT to legacy format before returning. * Set automatically by presignTransaction() when the caller explicitly requested txFormat: 'legacy'. @@ -431,14 +403,6 @@ export abstract class AbstractUtxoCoin extends BaseCoin implements Musig2Partici this.amountType = amountType; } - /** - * @deprecated - will be removed when we drop support for utxolib - * Use `name` property instead. - */ - get network(): utxolib.Network { - return getNetworkFromCoinName(this.name); - } - getChain(): UtxoCoinName { return this.name; } @@ -454,13 +418,8 @@ export abstract class AbstractUtxoCoin extends BaseCoin implements Musig2Partici /** Indicates whether the coin supports a block target */ supportsBlockTarget(): boolean { // FIXME: the SDK does not seem to use this anywhere so it is unclear what the purpose of this method is - switch (getMainnet(this.network)) { - case utxolib.networks.bitcoin: - case utxolib.networks.dogecoin: - return true; - default: - return false; - } + const mainnet = getMainnetCoinName(this.name); + return mainnet === 'btc' || mainnet === 'doge'; } sweepWithSendMany(): boolean { @@ -469,7 +428,7 @@ export abstract class AbstractUtxoCoin extends BaseCoin implements Musig2Partici /** @deprecated */ static get validAddressTypes(): ScriptType2Of3[] { - return [...outputScripts.scriptTypes2Of3]; + return ['p2sh', 'p2shP2wsh', 'p2wsh', 'p2tr', 'p2trMusig2']; } /** @@ -507,15 +466,20 @@ export abstract class AbstractUtxoCoin extends BaseCoin implements Musig2Partici // At the time of writing, the only additional address format is bch cashaddr. const anyFormat = (param as { anyFormat: boolean } | undefined)?.anyFormat ?? true; try { - // Find out if the address is valid for any format. Tries all supported formats by default. - // Throws if address cannot be decoded with any format. - const [format, script] = utxolib.addressFormat.toOutputScriptAndFormat(address, this.network); - // unless anyFormat is set, only 'default' is allowed. - if (!anyFormat && format !== 'default') { - return false; + const script = wasmAddress.toOutputScriptWithCoin(address, this.name); + // Determine which format the input address was in by round-tripping + // through each candidate and checking byte-equality. 'default' is tried + // first so canonical default-format addresses early-exit. + for (const format of ['default', 'cashaddr'] as const) { + try { + if (wasmAddress.fromOutputScriptWithCoin(script, this.name, format) === address) { + return anyFormat || format === 'default'; + } + } catch { + // coin doesn't support this format; try the next one + } } - // make sure that address is in normal representation for given format. - return address === utxolib.addressFormat.fromOutputScriptWithFormat(script, format, this.network); + return false; } catch (e) { return false; } @@ -595,13 +559,9 @@ export abstract class AbstractUtxoCoin extends BaseCoin implements Musig2Partici * @param addressDetails */ static inferAddressType(addressDetails: { chain: number }): ScriptType2Of3 | null { - return isChainCode(addressDetails.chain) ? scriptTypeForChain(addressDetails.chain) : null; - } - - createTransactionFromHex( - hex: string - ): utxolib.bitgo.UtxoTransaction { - return utxolib.bitgo.createTransactionFromHex(hex, this.network, this.amountType); + return fixedScriptWallet.ChainCode.is(addressDetails.chain) + ? (fixedScriptWallet.ChainCode.scriptType(addressDetails.chain) as ScriptType2Of3) + : null; } decodeTransaction(input: Buffer | string): fixedScriptWallet.BitGoPsbt { @@ -753,7 +713,7 @@ export abstract class AbstractUtxoCoin extends BaseCoin implements Musig2Partici * @returns true iff coin supports spending from unspentType */ supportsAddressType(addressType: ScriptType2Of3): boolean { - return utxolib.bitgo.outputScripts.isSupportedScriptType(this.network, addressType); + return fixedScriptWallet.supportsScriptType(this.name, addressType); } /** inherited doc */ @@ -766,7 +726,10 @@ export abstract class AbstractUtxoCoin extends BaseCoin implements Musig2Partici * @return true iff coin supports spending from chain */ supportsAddressChain(chain: number): boolean { - return isChainCode(chain) && this.supportsAddressType(utxolib.bitgo.scriptTypeForChain(chain)); + return ( + fixedScriptWallet.ChainCode.is(chain) && + this.supportsAddressType(fixedScriptWallet.ChainCode.scriptType(chain) as ScriptType2Of3) + ); } keyIdsForSigning(): number[] { @@ -1055,17 +1018,6 @@ export abstract class AbstractUtxoCoin extends BaseCoin implements Musig2Partici } const returnLegacyFormat = (params as Record).txFormat === 'legacy'; - - // In the case that we have a 'psbt-lite' transaction format, we want to indicate in signing to not fail - const txHex = (params.txHex ?? params.txPrebuild?.txHex) as string; - if ( - txHex && - utxolib.bitgo.isPsbt(txHex as string) && - utxolib.bitgo.isPsbtLite(utxolib.bitgo.createPsbtFromHex(txHex, this.network)) && - params.allowNonSegwitSigningWithoutPrevTx === undefined - ) { - return { ...params, allowNonSegwitSigningWithoutPrevTx: true, returnLegacyFormat }; - } return { ...params, returnLegacyFormat }; } diff --git a/modules/abstract-utxo/src/impl/doge/doge.ts b/modules/abstract-utxo/src/impl/doge/doge.ts index 79fe2da15c..f1ba54f030 100644 --- a/modules/abstract-utxo/src/impl/doge/doge.ts +++ b/modules/abstract-utxo/src/impl/doge/doge.ts @@ -1,5 +1,4 @@ import { BitGoBase, HalfSignedUtxoTransaction, SignedTransaction } from '@bitgo/sdk-core'; -import { bitgo } from '@bitgo/utxo-lib'; import { AbstractUtxoCoin, @@ -75,10 +74,6 @@ export class Doge extends AbstractUtxoCoin { /* postProcessPrebuild, isBitGoTaintedUnspent, verifyCustomChangeKeySignatures do not care whether they receive number or bigint */ - createTransactionFromHex(hex: string): bitgo.UtxoTransaction { - return super.createTransactionFromHex(hex); - } - async parseTransaction( params: ParseTransactionOptions ): /* diff --git a/modules/abstract-utxo/src/names.ts b/modules/abstract-utxo/src/names.ts index 555797ae3c..9e1a5c74c2 100644 --- a/modules/abstract-utxo/src/names.ts +++ b/modules/abstract-utxo/src/names.ts @@ -1,5 +1,3 @@ -import * as utxolib from '@bitgo/utxo-lib'; - export const utxoCoinsMainnet = ['btc', 'bch', 'bcha', 'bsv', 'btg', 'dash', 'doge', 'ltc', 'zec'] as const; export const utxoCoinsTestnet = [ 'tbtc', @@ -46,107 +44,6 @@ export function getMainnetCoinName(coinName: UtxoCoinName): UtxoCoinNameMainnet } } -function getNetworkName(n: utxolib.Network): utxolib.NetworkName { - const name = utxolib.getNetworkName(n); - if (!name) { - throw new Error('Unknown network'); - } - return name; -} - -/** - * @deprecated - will be removed when we drop support for utxolib - * @param n - * @returns the family name for a network. Testnets and mainnets of the same coin share the same family name. - */ -export function getFamilyFromNetwork(n: utxolib.Network): UtxoCoinNameMainnet { - switch (getNetworkName(n)) { - case 'bitcoin': - case 'testnet': - case 'bitcoinPublicSignet': - case 'bitcoinTestnet4': - case 'bitcoinBitGoSignet': - return 'btc'; - case 'bitcoincash': - case 'bitcoincashTestnet': - return 'bch'; - case 'ecash': - case 'ecashTest': - return 'bcha'; - case 'bitcoingold': - case 'bitcoingoldTestnet': - return 'btg'; - case 'bitcoinsv': - case 'bitcoinsvTestnet': - return 'bsv'; - case 'dash': - case 'dashTest': - return 'dash'; - case 'dogecoin': - case 'dogecoinTest': - return 'doge'; - case 'litecoin': - case 'litecoinTest': - return 'ltc'; - case 'zcash': - case 'zcashTest': - return 'zec'; - } -} - -/** - * @deprecated - will be removed when we drop support for utxolib - * Get the chain name for a network. - * The chain is different for every network. - */ -export function getCoinName(n: utxolib.Network): UtxoCoinName { - switch (getNetworkName(n)) { - case 'bitcoinPublicSignet': - return 'tbtcsig'; - case 'bitcoinTestnet4': - return 'tbtc4'; - case 'bitcoinBitGoSignet': - return 'tbtcbgsig'; - case 'bitcoin': - case 'testnet': - case 'bitcoincash': - case 'bitcoincashTestnet': - case 'ecash': - case 'ecashTest': - case 'bitcoingold': - case 'bitcoingoldTestnet': - case 'bitcoinsv': - case 'bitcoinsvTestnet': - case 'dash': - case 'dashTest': - case 'dogecoin': - case 'dogecoinTest': - case 'litecoin': - case 'litecoinTest': - case 'zcash': - case 'zcashTest': - const mainnetName = getFamilyFromNetwork(n); - return utxolib.isTestnet(n) ? `t${mainnetName}` : mainnetName; - } -} - -/** - * @deprecated - will be removed when we drop support for utxolib - * @param coinName - the name of the coin (e.g. 'btc', 'bch', 'ltc'). Also called 'chain' in some contexts. - * @returns the network for a coin. This is the mainnet network for the coin. - */ -export function getNetworkFromCoinName(coinName: string): utxolib.Network { - for (const network of utxolib.getNetworkList()) { - if (getCoinName(network) === coinName) { - return network; - } - } - throw new Error(`Unknown coin name ${coinName}`); -} - -/** @deprecated - use getNetworkFromCoinName instead */ -export const getNetworkFromChain = getNetworkFromCoinName; - function getBaseNameFromMainnet(coinName: UtxoCoinNameMainnet): string { switch (coinName) { case 'btc': @@ -189,11 +86,6 @@ export function getFullNameFromCoinName(coinName: UtxoCoinName): string { return prefix + getBaseNameFromMainnet(getMainnetCoinName(coinName)); } -/** @deprecated - use getFullNameFromCoinName instead */ -export function getFullNameFromNetwork(n: utxolib.Network): string { - return getFullNameFromCoinName(getCoinName(n)); -} - export function isTestnetCoin(coinName: UtxoCoinName): boolean { return isUtxoCoinNameTestnet(coinName); } diff --git a/modules/abstract-utxo/src/recovery/backupKeyRecovery.ts b/modules/abstract-utxo/src/recovery/backupKeyRecovery.ts index 8c902d1401..68d3f4b9c1 100644 --- a/modules/abstract-utxo/src/recovery/backupKeyRecovery.ts +++ b/modules/abstract-utxo/src/recovery/backupKeyRecovery.ts @@ -8,7 +8,7 @@ import { krsProviders, Triple, } from '@bitgo/sdk-core'; -import { BIP32, fixedScriptWallet } from '@bitgo/wasm-utxo'; +import { BIP32, fixedScriptWallet, Transaction } from '@bitgo/wasm-utxo'; import { AbstractUtxoCoin } from '../abstractUtxoCoin'; import { signAndVerifyPsbt } from '../transaction/fixedScript/signTransaction'; @@ -172,8 +172,8 @@ async function queryBlockchainUnspentsPath( // json parse won't parse it correctly, so we requery the txid for the tx hex to decode here if (!Number.isSafeInteger(u.value)) { const txHex = await getPrevTx(txid); - const tx = coin.createTransactionFromHex(txHex); - val = tx.outs[vout].value; + const tx = Transaction.fromBytes(Buffer.from(txHex, 'hex')); + val = tx.getOutputs()[vout].value; } } // the api may return cashaddr's instead of legacy for BCH and BCHA diff --git a/modules/abstract-utxo/src/transaction/decode.ts b/modules/abstract-utxo/src/transaction/decode.ts index 556e5e73d4..35f4337582 100644 --- a/modules/abstract-utxo/src/transaction/decode.ts +++ b/modules/abstract-utxo/src/transaction/decode.ts @@ -1,7 +1,6 @@ -import * as utxolib from '@bitgo/utxo-lib'; -import { fixedScriptWallet, hasPsbtMagic, Psbt as WasmPsbt, utxolibCompat } from '@bitgo/wasm-utxo'; +import { fixedScriptWallet, hasPsbtMagic, Psbt as WasmPsbt } from '@bitgo/wasm-utxo'; -import { getNetworkFromCoinName, UtxoCoinName } from '../names'; +import { UtxoCoinName } from '../names'; import { BitGoPsbt } from './types'; @@ -22,20 +21,11 @@ export function stringToBufferTryFormats(input: string, formats: BufferEncoding[ throw new Error('input must be a valid hex or base64 string'); } -function toNetworkName(coinName: UtxoCoinName): utxolibCompat.UtxolibName { - const network = getNetworkFromCoinName(coinName); - const networkName = utxolib.getNetworkName(network); - if (!networkName) { - throw new Error(`Invalid coinName: ${coinName}`); - } - return networkName; -} - export function decodePsbt(psbt: string | Buffer, coinName: UtxoCoinName): BitGoPsbt { if (typeof psbt === 'string') { psbt = Buffer.from(psbt, 'hex'); } - return fixedScriptWallet.BitGoPsbt.fromBytes(psbt, toNetworkName(coinName)); + return fixedScriptWallet.BitGoPsbt.fromBytes(psbt, coinName); } export type PrebuildLike = { diff --git a/modules/abstract-utxo/src/transaction/fixedScript/signTransaction.ts b/modules/abstract-utxo/src/transaction/fixedScript/signTransaction.ts index 49c333c4f0..a9dec08532 100644 --- a/modules/abstract-utxo/src/transaction/fixedScript/signTransaction.ts +++ b/modules/abstract-utxo/src/transaction/fixedScript/signTransaction.ts @@ -33,8 +33,6 @@ export async function signTransaction( txInfo: { unspents?: Unspent[] } | undefined; isLastSignature: boolean; signingStep: 'signerNonce' | 'cosignerNonce' | 'signerSignature' | undefined; - /** deprecated */ - allowNonSegwitSigningWithoutPrevTx: boolean; pubs: string[] | undefined; cosignerPub: string | undefined; /** When true (default), extract finalized PSBT to legacy transaction format. When false, return finalized PSBT. */ diff --git a/modules/abstract-utxo/src/transaction/signTransaction.ts b/modules/abstract-utxo/src/transaction/signTransaction.ts index 23f27de260..7a08d0b79f 100644 --- a/modules/abstract-utxo/src/transaction/signTransaction.ts +++ b/modules/abstract-utxo/src/transaction/signTransaction.ts @@ -65,7 +65,6 @@ export async function signTransaction( txInfo: params.txPrebuild.txInfo, isLastSignature: params.isLastSignature ?? false, signingStep: params.signingStep, - allowNonSegwitSigningWithoutPrevTx: params.allowNonSegwitSigningWithoutPrevTx ?? false, pubs: params.pubs, cosignerPub: params.cosignerPub, extractTransaction: params.extractTransaction, diff --git a/modules/abstract-utxo/test/unit/buildSignSendLegacyFormat.ts b/modules/abstract-utxo/test/unit/buildSignSendLegacyFormat.ts index 2beb751815..a6b064904b 100644 --- a/modules/abstract-utxo/test/unit/buildSignSendLegacyFormat.ts +++ b/modules/abstract-utxo/test/unit/buildSignSendLegacyFormat.ts @@ -11,6 +11,7 @@ import { encryptKeychain, getDefaultWalletKeys, getMinUtxoCoins, + getNetworkForCoinName, getUtxoWallet, keychainsBase58, getScriptTypes, @@ -46,12 +47,17 @@ describe('prebuildAndSign-returnLegacyFormat', function () { const outputAmount = BigInt(inputScripts.length) * BigInt(1e8) - fee; const outputScriptType: utxolib.bitgo.outputScripts.ScriptType = 'p2sh'; const outputChain = utxolib.bitgo.getExternalChainCode(outputScriptType); - const outputAddress = utxolib.bitgo.getWalletAddress(rootWalletKeys, outputChain, 0, coin.network); + const outputAddress = utxolib.bitgo.getWalletAddress( + rootWalletKeys, + outputChain, + 0, + getNetworkForCoinName(coin.name) + ); recipient = { address: outputAddress, amount: outputAmount.toString() }; prebuild = utxolib.testutil.constructPsbt( inputScripts.map((s) => ({ scriptType: s, value: BigInt(1e8) })), [{ scriptType: outputScriptType, value: outputAmount }], - coin.network, + getNetworkForCoinName(coin.name), rootWalletKeys, 'unsigned' ); diff --git a/modules/abstract-utxo/test/unit/customSigner.ts b/modules/abstract-utxo/test/unit/customSigner.ts index 0e673009aa..681c4155ff 100644 --- a/modules/abstract-utxo/test/unit/customSigner.ts +++ b/modules/abstract-utxo/test/unit/customSigner.ts @@ -3,7 +3,14 @@ import nock = require('nock'); import * as sinon from 'sinon'; import { CustomSigningFunction, common } from '@bitgo/sdk-core'; -import { defaultBitGo, getDefaultWalletKeys, getUtxoCoin, getUtxoWallet, assertHasProperty } from './util'; +import { + defaultBitGo, + getDefaultWalletKeys, + getNetworkForCoinName, + getUtxoCoin, + getUtxoWallet, + assertHasProperty, +} from './util'; nock.disableNetConnect(); @@ -56,7 +63,7 @@ describe('UTXO Custom Signer Function', function () { const psbt = utxoLib.testutil.constructPsbt( [{ scriptType: 'taprootKeyPathSpend', value: BigInt(1000) }], [{ scriptType: 'p2sh', value: BigInt(900) }], - basecoin.network, + getNetworkForCoinName(basecoin.name), rootWalletKey, 'unsigned' ); @@ -72,7 +79,7 @@ describe('UTXO Custom Signer Function', function () { const psbt = utxoLib.testutil.constructPsbt( [{ scriptType: 'p2wsh', value: BigInt(1000) }], [{ scriptType: 'p2sh', value: BigInt(900) }], - basecoin.network, + getNetworkForCoinName(basecoin.name), rootWalletKey, 'unsigned' ); diff --git a/modules/abstract-utxo/test/unit/prebuildAndSign.ts b/modules/abstract-utxo/test/unit/prebuildAndSign.ts index e2ae0dd0ec..24910bea5b 100644 --- a/modules/abstract-utxo/test/unit/prebuildAndSign.ts +++ b/modules/abstract-utxo/test/unit/prebuildAndSign.ts @@ -12,6 +12,7 @@ import { defaultBitGo, getDefaultWalletKeys, getMinUtxoCoins, + getNetworkForCoinName, getUtxoWallet, keychainsBase58, getScriptTypes, @@ -62,7 +63,7 @@ function run(coin: AbstractUtxoCoin, inputScripts: ScriptType[]): void { const psbt = utxolib.testutil.constructPsbt( inputs as utxolib.testutil.Input[], outputs, - coin.network, + getNetworkForCoinName(coin.name), rootWalletKeys, 'unsigned', { @@ -178,7 +179,12 @@ function run(coin: AbstractUtxoCoin, inputScripts: ScriptType[]): void { const outputAmount = BigInt(inputScripts.length) * BigInt(1e8) - fee; const outputScriptType: utxolib.bitgo.outputScripts.ScriptType = 'p2sh'; const outputChain = utxolib.bitgo.getExternalChainCode(outputScriptType); - const outputAddress = utxolib.bitgo.getWalletAddress(rootWalletKeys, outputChain, 0, coin.network); + const outputAddress = utxolib.bitgo.getWalletAddress( + rootWalletKeys, + outputChain, + 0, + getNetworkForCoinName(coin.name) + ); recipient = { address: outputAddress, @@ -222,7 +228,7 @@ function run(coin: AbstractUtxoCoin, inputScripts: ScriptType[]): void { nocks.forEach((nock) => assert.ok(nock.isDone())); - assertSignable(res.txHex, inputScripts, coin.network); + assertSignable(res.txHex, inputScripts, getNetworkForCoinName(coin.name)); }); [true, false].forEach((selfSend) => { @@ -254,7 +260,7 @@ function run(coin: AbstractUtxoCoin, inputScripts: ScriptType[]): void { nocks.forEach((nock) => assert.ok(nock.isDone())); - assertSignable(res.txHex, inputScripts, coin.network); + assertSignable(res.txHex, inputScripts, getNetworkForCoinName(coin.name)); }); }); }); diff --git a/modules/abstract-utxo/test/unit/signTransaction.ts b/modules/abstract-utxo/test/unit/signTransaction.ts index 7491ecf82b..f5dfd0e111 100644 --- a/modules/abstract-utxo/test/unit/signTransaction.ts +++ b/modules/abstract-utxo/test/unit/signTransaction.ts @@ -9,7 +9,14 @@ import { common, Triple } from '@bitgo/sdk-core'; import { getReplayProtectionPubkeys, ErrorDeprecatedTxFormat } from '../../src'; import type { Unspent } from '../../src/unspent'; -import { getUtxoWallet, getDefaultWalletKeys, getUtxoCoin, keychainsBase58, defaultBitGo } from './util'; +import { + getUtxoWallet, + getDefaultWalletKeys, + getNetworkForCoinName, + getUtxoCoin, + keychainsBase58, + defaultBitGo, +} from './util'; describe('signTransaction', function () { const bgUrl = common.Environments[defaultBitGo.getEnv()].uri; @@ -21,7 +28,7 @@ describe('signTransaction', function () { const pubs = keychainsBase58.map((v) => v.pub) as Triple; function validatePsbt(txHex: string, targetSigCount: 0 | 1, targetNonceCount?: 1 | 2) { - const psbt = utxolib.bitgo.createPsbtFromHex(txHex, coin.network); + const psbt = utxolib.bitgo.createPsbtFromHex(txHex, getNetworkForCoinName(coin.name)); psbt.data.inputs.forEach((input, index) => { const parsed = utxolib.bitgo.parsePsbtInput(input); if (parsed.scriptType === 'taprootKeyPathSpend') { @@ -38,7 +45,7 @@ describe('signTransaction', function () { } function validateTx(txHex: string, unspents: Unspent[], targetSigCount: 0 | 1) { - const tx = utxolib.bitgo.createTransactionFromHex(txHex, coin.network); + const tx = utxolib.bitgo.createTransactionFromHex(txHex, getNetworkForCoinName(coin.name)); unspents.forEach((u, i) => { const sigCount = utxolib.bitgo.getStrictSignatureCount(tx.ins[i]); const expectedSigCount = utxolib.bitgo.isWalletUnspent(u) && !!targetSigCount ? 1 : 0; @@ -56,7 +63,7 @@ describe('signTransaction', function () { const txHex = tx.toHex(); function nockSignPsbt(psbtHex: string): nock.Scope { - const psbt = utxolib.bitgo.createPsbtFromHex(psbtHex, coin.network); + const psbt = utxolib.bitgo.createPsbtFromHex(psbtHex, getNetworkForCoinName(coin.name)); return nock(bgUrl) .post(`/api/v2/${wallet.coin()}/wallet/${wallet.id()}/tx/signpsbt`, (body) => body.psbt) .reply(200, { psbt: psbt.setAllInputsMusig2NonceHD(rootWalletKeys.bitgo).toHex() }); @@ -147,7 +154,7 @@ describe('signTransaction', function () { .map((scriptType) => ({ scriptType, value: BigInt(1000) })); const unspentSum = inputs.reduce((prev: bigint, curr) => prev + curr.value, BigInt(0)); const outputs: testutil.Output[] = [{ scriptType: 'p2sh', value: unspentSum - BigInt(1000) }]; - const psbt = testutil.constructPsbt(inputs, outputs, coin.network, rootWalletKeys, 'unsigned', { + const psbt = testutil.constructPsbt(inputs, outputs, getNetworkForCoinName(coin.name), rootWalletKeys, 'unsigned', { p2shP2pkKey: replayProtectionKey, }); @@ -163,7 +170,7 @@ describe('signTransaction', function () { .map((scriptType) => ({ scriptType, value: BigInt(1000) })); const unspentSum = inputs.reduce((prev: bigint, cur) => prev + cur.value, BigInt(0)); const outputs: testutil.Output[] = [{ scriptType: 'p2sh', value: unspentSum - BigInt(1000) }]; - const psbt = testutil.constructPsbt(inputs, outputs, coin.network, rootWalletKeys, 'unsigned', { + const psbt = testutil.constructPsbt(inputs, outputs, getNetworkForCoinName(coin.name), rootWalletKeys, 'unsigned', { p2shP2pkKey: replayProtectionKey, }); @@ -181,8 +188,16 @@ describe('signTransaction', function () { })); const unspentSum = inputs.reduce((prev: bigint, curr) => prev + curr.value, BigInt(0)); const outputs: testutil.TxnOutput[] = [{ scriptType: 'p2sh', value: unspentSum - BigInt(1000) }]; - const txBuilder = testutil.constructTxnBuilder(inputs, outputs, coin.network, rootWalletKeys, 'unsigned'); - const unspents = inputs.map((v, i) => testutil.toTxnUnspent(v, i, coin.network, rootWalletKeys)); + const txBuilder = testutil.constructTxnBuilder( + inputs, + outputs, + getNetworkForCoinName(coin.name), + rootWalletKeys, + 'unsigned' + ); + const unspents = inputs.map((v, i) => + testutil.toTxnUnspent(v, i, getNetworkForCoinName(coin.name), rootWalletKeys) + ); // Legacy format transactions are now deprecated and should throw ErrorDeprecatedTxFormat await assert.rejects(async () => { @@ -194,7 +209,7 @@ describe('signTransaction', function () { const inputs: testutil.Input[] = [{ scriptType: 'taprootKeyPathSpend', value: BigInt(1000) }]; const unspentSum = inputs.reduce((prev: bigint, curr) => prev + curr.value, BigInt(0)); const outputs: testutil.Output[] = [{ scriptType: 'p2sh', value: unspentSum - BigInt(1000) }]; - const psbt = testutil.constructPsbt(inputs, outputs, coin.network, rootWalletKeys, 'unsigned'); + const psbt = testutil.constructPsbt(inputs, outputs, getNetworkForCoinName(coin.name), rootWalletKeys, 'unsigned'); await assert.rejects( async () => { diff --git a/modules/abstract-utxo/test/unit/transaction.ts b/modules/abstract-utxo/test/unit/transaction.ts index ed69fa610e..09f8d51201 100644 --- a/modules/abstract-utxo/test/unit/transaction.ts +++ b/modules/abstract-utxo/test/unit/transaction.ts @@ -31,6 +31,7 @@ import { getWalletKeys, defaultBitGo, getMinUtxoCoins, + getNetworkForCoinName, getScriptTypes, } from './util'; @@ -60,7 +61,7 @@ function run( return testutil.toUnspent( { scriptType: t, value: t === 'p2shP2pk' ? BigInt(1000) : BigInt(value) }, index, - coin.network, + getNetworkForCoinName(coin.name), walletKeys ); }); @@ -72,7 +73,7 @@ function run( function getUnspents(): Unspent[] { return inputScripts.map((type, i) => - mockUnspent(coin.network, walletKeys, toTxnInputScriptType(type), i, value) + mockUnspent(getNetworkForCoinName(coin.name), walletKeys, toTxnInputScriptType(type), i, value) ); } @@ -113,7 +114,9 @@ function run( scope = nock(bgUrl) .post(`/api/v2/${wallet.coin()}/wallet/${wallet.id()}/tx/signpsbt`, (body) => body.psbt) .reply(200, (_uri: string, requestBody: unknown) => { - const networkName = utxolib.getNetworkName(coin.network) as fixedScriptWallet.NetworkName; + const networkName = utxolib.getNetworkName( + getNetworkForCoinName(coin.name) + ) as fixedScriptWallet.NetworkName; const reqBytes = Buffer.from((requestBody as { psbt: string }).psbt, 'hex'); const reqPsbt = fixedScriptWallet.BitGoPsbt.fromBytes(reqBytes, networkName); const cosignerWasm = BIP32.fromBase58(cosigner.toBase58()); @@ -166,7 +169,7 @@ function run( const outputs: testutil.Output[] = [ { address: getOutputAddress(getWalletKeys('test')), value: unspentSum - BigInt(1000) }, ]; - const psbt = testutil.constructPsbt(inputs, outputs, coin.network, walletKeys, 'unsigned', { + const psbt = testutil.constructPsbt(inputs, outputs, getNetworkForCoinName(coin.name), walletKeys, 'unsigned', { p2shP2pkKey: getReplayProtectionPubkeys(coin.name)[0], }); utxolib.bitgo.addXpubsToPsbt(psbt, walletKeys); @@ -177,7 +180,11 @@ function run( const prebuild = txFormat === 'psbt' ? createPrebuildPsbt() - : createPrebuildTransaction(coin.network, getUnspents(), getOutputAddress(walletKeys)); + : createPrebuildTransaction( + getNetworkForCoinName(coin.name), + getUnspents(), + getOutputAddress(walletKeys) + ); const halfSignedUserBitGo = await createHalfSignedTransaction(prebuild, walletKeys.user, walletKeys.bitgo); const fullSignedUserBitGo = @@ -225,7 +232,7 @@ function run( ? undefined : v instanceof utxolib.bitgo.UtxoTransaction ? transactionToObj(v) - : transactionHexToObj(v.txHex, coin.network, amountType) + : transactionHexToObj(v.txHex, getNetworkForCoinName(coin.name), amountType) ) as TransactionObjStages; } @@ -240,7 +247,7 @@ function run( }); function testPsbtValidSignatures(tx: HalfSignedUtxoTransaction, signedBy: BIP32Interface[]) { - const psbt = utxolib.bitgo.createPsbtFromHex(tx.txHex, coin.network); + const psbt = utxolib.bitgo.createPsbtFromHex(tx.txHex, getNetworkForCoinName(coin.name)); const unspents = getUnspentsForPsbt(); psbt.data.inputs.forEach((input, index) => { const unspent = unspents[index]; @@ -278,7 +285,7 @@ function run( const transaction = utxolib.bitgo.createTransactionFromBuffer( Buffer.from(tx.txHex, 'hex'), - coin.network, + getNetworkForCoinName(coin.name), { amountType } ); transaction.ins.forEach((input, index) => { diff --git a/modules/abstract-utxo/test/unit/transaction/fixedScript/parsePsbt.ts b/modules/abstract-utxo/test/unit/transaction/fixedScript/parsePsbt.ts index d129f40614..e6c2676073 100644 --- a/modules/abstract-utxo/test/unit/transaction/fixedScript/parsePsbt.ts +++ b/modules/abstract-utxo/test/unit/transaction/fixedScript/parsePsbt.ts @@ -8,10 +8,9 @@ import { fixedScriptWallet } from '@bitgo/wasm-utxo'; import { parseTransaction } from '../../../../src/transaction/fixedScript/parseTransaction'; import { ParsedTransaction } from '../../../../src/transaction/types'; import { UtxoWallet } from '../../../../src/wallet'; -import { getUtxoCoin } from '../../util'; +import { getCoinNameForNetwork, getUtxoCoin } from '../../util'; import { explainPsbtWasm } from '../../../../src/transaction/fixedScript'; import type { TransactionExplanation } from '../../../../src/transaction/fixedScript/explainTransaction'; -import { getCoinName } from '../../../../src/names'; import { TransactionPrebuild } from '../../../../src/abstractUtxoCoin'; function getTxParamsFromExplanation( @@ -78,7 +77,7 @@ function describeParseTransactionWith( let stubExplainTransaction: sinon.SinonStub; before('prepare', async function () { - const coinName = getCoinName(acidTest.network); + const coinName = getCoinNameForNetwork(acidTest.network); coin = getUtxoCoin(coinName); // Create PSBT and explanation diff --git a/modules/abstract-utxo/test/unit/verifyTransaction.ts b/modules/abstract-utxo/test/unit/verifyTransaction.ts index c368366bc2..da14d96cb6 100644 --- a/modules/abstract-utxo/test/unit/verifyTransaction.ts +++ b/modules/abstract-utxo/test/unit/verifyTransaction.ts @@ -1,6 +1,5 @@ import assert from 'assert'; -import * as utxolib from '@bitgo/utxo-lib'; import * as sinon from 'sinon'; import { Wallet } from '@bitgo/sdk-core'; @@ -217,10 +216,6 @@ describe('Verify Transaction', function () { needsCustomChangeKeySignatureVerification: false, }); - const bitcoinMock = sinon - .stub(coin, 'createTransactionFromHex') - .returns({ ins: [] } as unknown as utxolib.bitgo.UtxoTransaction); - const result = await coin.verifyTransaction({ txParams: { walletPassphrase: passphrase, @@ -234,7 +229,6 @@ describe('Verify Transaction', function () { assert.strictEqual(result, true); coinMock.restore(); - bitcoinMock.restore(); }); it('should not allow any implicit external outputs if paygo outputs are disallowed', async () => { @@ -284,10 +278,6 @@ describe('Verify Transaction', function () { needsCustomChangeKeySignatureVerification: false, }); - const bitcoinMock = sinon - .stub(coin, 'createTransactionFromHex') - .returns({ ins: [] } as unknown as utxolib.bitgo.UtxoTransaction); - const result = await coin.verifyTransaction({ txParams: { walletPassphrase: passphrase, @@ -302,7 +292,6 @@ describe('Verify Transaction', function () { assert.strictEqual(result, true); coinMock.restore(); - bitcoinMock.restore(); }); it('should verify a bridging transaction whose implicit external output matches the bridge amount', async () => { @@ -329,10 +318,6 @@ describe('Verify Transaction', function () { needsCustomChangeKeySignatureVerification: false, }); - const bitcoinMock = sinon - .stub(coin, 'createTransactionFromHex') - .returns({ ins: [] } as unknown as utxolib.bitgo.UtxoTransaction); - const result = await coin.verifyTransaction({ txParams: { walletPassphrase: passphrase, @@ -349,7 +334,6 @@ describe('Verify Transaction', function () { assert.strictEqual(result, true); coinMock.restore(); - bitcoinMock.restore(); }); it('should reject a bridging transaction whose implicit external output does not match the bridge amount', async () => { @@ -492,10 +476,6 @@ describe('Verify Transaction', function () { needsCustomChangeKeySignatureVerification: false, }); - const bitcoinMock = sinon - .stub(bigintCoin, 'createTransactionFromHex') - .returns({ ins: [] } as unknown as utxolib.bitgo.UtxoTransaction); - const result = await bigintCoin.verifyTransaction({ txParams: { walletPassphrase: passphrase, @@ -510,6 +490,5 @@ describe('Verify Transaction', function () { assert.strictEqual(result, true); coinMock.restore(); - bitcoinMock.restore(); }); }); diff --git a/modules/abstract-utxo/test/unit/wallet.ts b/modules/abstract-utxo/test/unit/wallet.ts index 7c9b6223e7..4313a70237 100644 --- a/modules/abstract-utxo/test/unit/wallet.ts +++ b/modules/abstract-utxo/test/unit/wallet.ts @@ -5,7 +5,7 @@ import nock = require('nock'); import * as _ from 'lodash'; import { Wallet, ManageUnspentsOptions, common } from '@bitgo/sdk-core'; -import { defaultBitGo, getDefaultWalletKeys, toKeychainObjects, getUtxoCoin } from './util'; +import { defaultBitGo, getDefaultWalletKeys, getNetworkForCoinName, toKeychainObjects, getUtxoCoin } from './util'; const bgUrl = common.Environments[defaultBitGo.getEnv()].uri; const bitgo = defaultBitGo; @@ -35,7 +35,7 @@ describe('manage unspents', function () { utxoLib.testutil.constructPsbt( [{ scriptType, value: BigInt(1000) }], [{ scriptType, value: BigInt(900) }], - basecoin.network, + getNetworkForCoinName(basecoin.name), rootWalletKey, 'unsigned' ) @@ -74,7 +74,7 @@ describe('manage unspents', function () { const psbt = utxoLib.testutil.constructPsbt( [{ scriptType: 'p2wsh', value: BigInt(1000) }], [{ scriptType: 'p2shP2wsh', value: BigInt(900) }], - basecoin.network, + getNetworkForCoinName(basecoin.name), rootWalletKey, 'unsigned' );