From 13dad4a467281cc47211c12d3a23b55f71e3ac0b Mon Sep 17 00:00:00 2001 From: Daniel Peng Date: Thu, 18 Sep 2025 11:40:02 -0400 Subject: [PATCH 1/8] test(sdk-core): add consolidate unspent management spoofability test for utxo coins Ticket: WP-5945 --- modules/sdk-coin-btc/test/unit/btc.ts | 70 +++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/modules/sdk-coin-btc/test/unit/btc.ts b/modules/sdk-coin-btc/test/unit/btc.ts index 5aa4ac078d..28860ead86 100644 --- a/modules/sdk-coin-btc/test/unit/btc.ts +++ b/modules/sdk-coin-btc/test/unit/btc.ts @@ -106,4 +106,74 @@ describe('BTC:', () => { ); }); }); + + describe('Unspent management spoofability (BUILD_SIGN_SEND)', () => { + let coin: Tbtc; + let bitgoTest: TestBitGoAPI; + before(() => { + bitgoTest = TestBitGo.decorate(BitGoAPI, { env: 'test' }); + bitgoTest.safeRegister('tbtc', Tbtc.createInstance); + bitgoTest.initializeTestVars(); + coin = bitgoTest.coin('tbtc') as Tbtc; + }); + + it('should detect hex spoofing in BUILD_SIGN_SEND', async (): Promise => { + const { getDefaultWalletKeys, toKeychainObjects } = require('../../../bitgo/test/v2/unit/coins/utxo/util/keychains'); + const rootWalletKey = getDefaultWalletKeys(); + const keysObj = toKeychainObjects(rootWalletKey, 'pass'); + + const { Wallet } = await import('@bitgo/sdk-core'); + const wallet = new Wallet(bitgoTest, coin, { + id: '5b34252f1bf349930e34020a', + coin: 'tbtc', + keys: keysObj.map((k) => k.id), + }); + + const originalPsbt = utxolib.testutil.constructPsbt( + [{ scriptType: 'p2wsh' as const, value: BigInt(10000) }], + [{ address: 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7', value: BigInt(9000) }], + coin.network, + rootWalletKey, + 'unsigned' as const + ); + utxolib.bitgo.addXpubsToPsbt(originalPsbt, rootWalletKey); + + const spoofedPsbt = utxolib.testutil.constructPsbt( + [{ scriptType: 'p2wsh' as const, value: BigInt(10000) }], + [{ address: 'tb1pjgg9ty3s2ztp60v6lhgrw76f7hxydzuk9t9mjsndh3p2gf2ah7gs4850kn', value: BigInt(9000) }], + coin.network, + rootWalletKey, + 'unsigned' as const + ); + utxolib.bitgo.addXpubsToPsbt(spoofedPsbt, rootWalletKey); + const spoofedHex: string = spoofedPsbt.toHex(); + + const bgUrl: string = (bitgoTest as any)._baseUrl; + const nock = require('nock'); + + nock(bgUrl) + .post(`/api/v2/${wallet.coin()}/wallet/${wallet.id()}/consolidateUnspents`) + .reply(200, { txHex: spoofedHex, consolidateId: 'test' }); + + nock(bgUrl) + .post(`/api/v2/${wallet.coin()}/wallet/${wallet.id()}/tx/send`) + .reply((requestBody: any) => { + if (requestBody?.txHex === spoofedHex) { + throw new Error('Spoofed transaction was sent: spoofing protection failed'); + } + return [200, { txid: 'test-txid-123', status: 'signed' }]; + }); + + keysObj.forEach((k, i) => + nock(bgUrl).get(`/api/v2/${wallet.coin()}/key/${wallet.keyIds()[i]}`).reply(200, k) + ); + + await assert.rejects( + wallet.consolidateUnspents({ walletPassphrase: 'pass' }), + (e: any) => + typeof e?.message === 'string' && + e.message.includes('prebuild attempts to spend to unintended external recipients') + ); + }); + }); }); From 4f377a8ded7d252bfaaa2bc2d6eb2ea61ff5420e Mon Sep 17 00:00:00 2001 From: Daniel Peng Date: Thu, 18 Sep 2025 11:49:31 -0400 Subject: [PATCH 2/8] feat(sdk-core): add transaction verification to validate platform built transactions Ticket: WP-5945 --- modules/sdk-core/src/bitgo/wallet/wallet.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/modules/sdk-core/src/bitgo/wallet/wallet.ts b/modules/sdk-core/src/bitgo/wallet/wallet.ts index f29b8670ec..dc96920171 100644 --- a/modules/sdk-core/src/bitgo/wallet/wallet.ts +++ b/modules/sdk-core/src/bitgo/wallet/wallet.ts @@ -735,6 +735,18 @@ export class Wallet implements IWallet { return buildResponse; } + // Validate that the platform-built transaction matches user parameters + const txPrebuilds = Array.isArray(buildResponse) ? buildResponse : [buildResponse]; + for (const txPrebuild of txPrebuilds) { + await this.baseCoin.verifyTransaction({ + txParams: params, + txPrebuild, + wallet: this, + verification: params.verification ?? {}, + reqId, + }); + } + const keychains = (await this.baseCoin .keychains() .getKeysForSigning({ wallet: this, reqId })) as unknown as Keychain[]; @@ -751,8 +763,6 @@ export class Wallet implements IWallet { allowNonSegwitSigningWithoutPrevTx: !!params.bulk, }; - const txPrebuilds = Array.isArray(buildResponse) ? buildResponse : [buildResponse]; - const selectParams = _.pick(params, ['comment', 'otp', 'bulk']); const response = await Promise.all( From 7300cc04e3abf87e8b984a64eb5a1fdc47165bc1 Mon Sep 17 00:00:00 2001 From: Daniel Peng Date: Thu, 18 Sep 2025 12:35:06 -0400 Subject: [PATCH 3/8] fix(sdk-core): use Promise.all for concurrent processing for transaction verifying, linting fixes Ticket: WP-5945 --- modules/sdk-coin-btc/test/unit/btc.ts | 9 +++++---- modules/sdk-core/src/bitgo/wallet/wallet.ts | 20 +++++++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/modules/sdk-coin-btc/test/unit/btc.ts b/modules/sdk-coin-btc/test/unit/btc.ts index 28860ead86..d5e03f6520 100644 --- a/modules/sdk-coin-btc/test/unit/btc.ts +++ b/modules/sdk-coin-btc/test/unit/btc.ts @@ -118,7 +118,10 @@ describe('BTC:', () => { }); it('should detect hex spoofing in BUILD_SIGN_SEND', async (): Promise => { - const { getDefaultWalletKeys, toKeychainObjects } = require('../../../bitgo/test/v2/unit/coins/utxo/util/keychains'); + const { + getDefaultWalletKeys, + toKeychainObjects, + } = require('../../../bitgo/test/v2/unit/coins/utxo/util/keychains'); const rootWalletKey = getDefaultWalletKeys(); const keysObj = toKeychainObjects(rootWalletKey, 'pass'); @@ -164,9 +167,7 @@ describe('BTC:', () => { return [200, { txid: 'test-txid-123', status: 'signed' }]; }); - keysObj.forEach((k, i) => - nock(bgUrl).get(`/api/v2/${wallet.coin()}/key/${wallet.keyIds()[i]}`).reply(200, k) - ); + keysObj.forEach((k, i) => nock(bgUrl).get(`/api/v2/${wallet.coin()}/key/${wallet.keyIds()[i]}`).reply(200, k)); await assert.rejects( wallet.consolidateUnspents({ walletPassphrase: 'pass' }), diff --git a/modules/sdk-core/src/bitgo/wallet/wallet.ts b/modules/sdk-core/src/bitgo/wallet/wallet.ts index dc96920171..d8acb37432 100644 --- a/modules/sdk-core/src/bitgo/wallet/wallet.ts +++ b/modules/sdk-core/src/bitgo/wallet/wallet.ts @@ -737,15 +737,17 @@ export class Wallet implements IWallet { // Validate that the platform-built transaction matches user parameters const txPrebuilds = Array.isArray(buildResponse) ? buildResponse : [buildResponse]; - for (const txPrebuild of txPrebuilds) { - await this.baseCoin.verifyTransaction({ - txParams: params, - txPrebuild, - wallet: this, - verification: params.verification ?? {}, - reqId, - }); - } + await Promise.all( + txPrebuilds.map((txPrebuild) => + this.baseCoin.verifyTransaction({ + txParams: params, + txPrebuild, + wallet: this, + verification: params.verification ?? {}, + reqId, + }) + ) + ); const keychains = (await this.baseCoin .keychains() From ad3c6c47529cbb9e730d3124a33b2b2038064462 Mon Sep 17 00:00:00 2001 From: Daniel Peng Date: Thu, 18 Sep 2025 16:21:54 -0400 Subject: [PATCH 4/8] fix(sdk-core): add keychain info to transaction verification process, fixes unit tests Ticket: WP-5945 --- modules/bitgo/test/v2/unit/wallet.ts | 2 ++ modules/sdk-core/src/bitgo/wallet/wallet.ts | 35 +++++++++++++-------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/modules/bitgo/test/v2/unit/wallet.ts b/modules/bitgo/test/v2/unit/wallet.ts index f1f68c02ec..8cb194d00a 100644 --- a/modules/bitgo/test/v2/unit/wallet.ts +++ b/modules/bitgo/test/v2/unit/wallet.ts @@ -1589,6 +1589,7 @@ describe('V2 Wallet:', function () { 'unsigned' ) ); + psbts.forEach((psbt) => utxoLib.bitgo.addXpubsToPsbt(psbt, rootWalletKey)); const txHexes = psbts.map((psbt) => ({ txHex: psbt.toHex() })); const nocks: nock.Scope[] = []; @@ -1627,6 +1628,7 @@ describe('V2 Wallet:', function () { rootWalletKey, 'unsigned' ); + utxoLib.bitgo.addXpubsToPsbt(psbt, rootWalletKey); const nocks: nock.Scope[] = []; nocks.push( diff --git a/modules/sdk-core/src/bitgo/wallet/wallet.ts b/modules/sdk-core/src/bitgo/wallet/wallet.ts index d8acb37432..11c8653ef2 100644 --- a/modules/sdk-core/src/bitgo/wallet/wallet.ts +++ b/modules/sdk-core/src/bitgo/wallet/wallet.ts @@ -735,24 +735,33 @@ export class Wallet implements IWallet { return buildResponse; } + const keychains = (await this.baseCoin + .keychains() + .getKeysForSigning({ wallet: this, reqId })) as unknown as Keychain[]; + // Validate that the platform-built transaction matches user parameters const txPrebuilds = Array.isArray(buildResponse) ? buildResponse : [buildResponse]; await Promise.all( - txPrebuilds.map((txPrebuild) => - this.baseCoin.verifyTransaction({ - txParams: params, - txPrebuild, - wallet: this, - verification: params.verification ?? {}, - reqId, - }) - ) + txPrebuilds + .filter((txPrebuild) => txPrebuild.txHex) + .map((txPrebuild) => + this.baseCoin.verifyTransaction({ + txParams: params, + txPrebuild, + wallet: this, + verification: { + ...(params.verification ?? {}), + keychains: { + user: keychains[0], + backup: keychains[1], + bitgo: keychains[2], + }, + }, + reqId, + }) + ) ); - const keychains = (await this.baseCoin - .keychains() - .getKeysForSigning({ wallet: this, reqId })) as unknown as Keychain[]; - const transactionParams = { ...params, keychain: keychains[0], From 571714799d7c9f467ec2b216595e020f645e336b Mon Sep 17 00:00:00 2001 From: Daniel Peng Date: Fri, 19 Sep 2025 16:51:22 -0400 Subject: [PATCH 5/8] fix(sdk-core): remove filter from prebuild validation Ticket: WP-5945 --- modules/bitgo/test/v2/unit/unspents.ts | 1 + modules/sdk-core/src/bitgo/wallet/wallet.ts | 32 ++++++++++----------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/modules/bitgo/test/v2/unit/unspents.ts b/modules/bitgo/test/v2/unit/unspents.ts index 5d6b707143..0d2ed310d6 100644 --- a/modules/bitgo/test/v2/unit/unspents.ts +++ b/modules/bitgo/test/v2/unit/unspents.ts @@ -60,6 +60,7 @@ describe('Verify string type is used for value of unspent', function () { ); sinon.stub(wallet, 'signTransaction').resolves({}); + sinon.stub(wallet.baseCoin, 'verifyTransaction').resolves(); const sendScope = nock(bgUrl) .post(`/api/v2/${wallet.coin()}/wallet/${wallet.id()}/tx/send`, { type: manageUnspentType }) diff --git a/modules/sdk-core/src/bitgo/wallet/wallet.ts b/modules/sdk-core/src/bitgo/wallet/wallet.ts index 11c8653ef2..41e104168b 100644 --- a/modules/sdk-core/src/bitgo/wallet/wallet.ts +++ b/modules/sdk-core/src/bitgo/wallet/wallet.ts @@ -742,24 +742,22 @@ export class Wallet implements IWallet { // Validate that the platform-built transaction matches user parameters const txPrebuilds = Array.isArray(buildResponse) ? buildResponse : [buildResponse]; await Promise.all( - txPrebuilds - .filter((txPrebuild) => txPrebuild.txHex) - .map((txPrebuild) => - this.baseCoin.verifyTransaction({ - txParams: params, - txPrebuild, - wallet: this, - verification: { - ...(params.verification ?? {}), - keychains: { - user: keychains[0], - backup: keychains[1], - bitgo: keychains[2], - }, + txPrebuilds.map((txPrebuild) => + this.baseCoin.verifyTransaction({ + txParams: params, + txPrebuild, + wallet: this, + verification: { + ...(params.verification ?? {}), + keychains: { + user: keychains[0], + backup: keychains[1], + bitgo: keychains[2], }, - reqId, - }) - ) + }, + reqId, + }) + ) ); const transactionParams = { From a1726a6df1d43da2bea9d286a3a37c655bb436bf Mon Sep 17 00:00:00 2001 From: Simon Vutov Date: Thu, 18 Sep 2025 16:01:12 -0400 Subject: [PATCH 6/8] feat(sdk-coin-btc): add transaction validation for fanout unspent management - Add test case for fanout spoofing detection in btc.ts Ticket WP-5955 TICKET: WP-5955 --- modules/sdk-coin-btc/test/unit/btc.ts | 73 ++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/modules/sdk-coin-btc/test/unit/btc.ts b/modules/sdk-coin-btc/test/unit/btc.ts index d5e03f6520..b2b7d40960 100644 --- a/modules/sdk-coin-btc/test/unit/btc.ts +++ b/modules/sdk-coin-btc/test/unit/btc.ts @@ -107,7 +107,7 @@ describe('BTC:', () => { }); }); - describe('Unspent management spoofability (BUILD_SIGN_SEND)', () => { + describe('Unspent management spoofability - Consolidation (BUILD_SIGN_SEND)', () => { let coin: Tbtc; let bitgoTest: TestBitGoAPI; before(() => { @@ -177,4 +177,75 @@ describe('BTC:', () => { ); }); }); + + describe('Unspent management spoofability - Fanout (BUILD_SIGN_SEND)', () => { + let coin: Tbtc; + let bitgoTest: TestBitGoAPI; + before(() => { + bitgoTest = TestBitGo.decorate(BitGoAPI, { env: 'test' }); + bitgoTest.safeRegister('tbtc', Tbtc.createInstance); + bitgoTest.initializeTestVars(); + coin = bitgoTest.coin('tbtc') as Tbtc; + }); + + it('should detect hex spoofing in fanout BUILD_SIGN_SEND', async (): Promise => { + const { + getDefaultWalletKeys, + toKeychainObjects, + } = require('../../../bitgo/test/v2/unit/coins/utxo/util/keychains'); + const rootWalletKey = getDefaultWalletKeys(); + const keysObj = toKeychainObjects(rootWalletKey, 'pass'); + + const { Wallet } = await import('@bitgo/sdk-core'); + const wallet = new Wallet(bitgoTest, coin, { + id: '5b34252f1bf349930e34020a', + coin: 'tbtc', + keys: keysObj.map((k) => k.id), + }); + + const originalPsbt = utxolib.testutil.constructPsbt( + [{ scriptType: 'p2wsh' as const, value: BigInt(10000) }], + [{ address: 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7', value: BigInt(9000) }], + coin.network, + rootWalletKey, + 'unsigned' as const + ); + utxolib.bitgo.addXpubsToPsbt(originalPsbt, rootWalletKey); + + const spoofedPsbt = utxolib.testutil.constructPsbt( + [{ scriptType: 'p2wsh' as const, value: BigInt(10000) }], + [{ address: 'tb1pjgg9ty3s2ztp60v6lhgrw76f7hxydzuk9t9mjsndh3p2gf2ah7gs4850kn', value: BigInt(9000) }], + coin.network, + rootWalletKey, + 'unsigned' as const + ); + utxolib.bitgo.addXpubsToPsbt(spoofedPsbt, rootWalletKey); + const spoofedHex: string = spoofedPsbt.toHex(); + + const bgUrl: string = (bitgoTest as any)._baseUrl; + const nock = require('nock'); + + nock(bgUrl) + .post(`/api/v2/${wallet.coin()}/wallet/${wallet.id()}/fanoutUnspents`) + .reply(200, { txHex: spoofedHex, fanoutId: 'test' }); + + nock(bgUrl) + .post(`/api/v2/${wallet.coin()}/wallet/${wallet.id()}/tx/send`) + .reply((requestBody: any) => { + if (requestBody?.txHex === spoofedHex) { + throw new Error('Spoofed transaction was sent: spoofing protection failed'); + } + return [200, { txid: 'test-txid-123', status: 'signed' }]; + }); + + keysObj.forEach((k, i) => nock(bgUrl).get(`/api/v2/${wallet.coin()}/key/${wallet.keyIds()[i]}`).reply(200, k)); + + await assert.rejects( + wallet.fanoutUnspents({ walletPassphrase: 'pass' }), + (e: any) => + typeof e?.message === 'string' && + e.message.includes('prebuild attempts to spend to unintended external recipients') + ); + }); + }); }); From 958eb5a0e2d99538904338307efdfe34f1025f76 Mon Sep 17 00:00:00 2001 From: Simon Vutov Date: Mon, 22 Sep 2025 10:37:06 -0400 Subject: [PATCH 7/8] refactor(sdk-coin-btc): move require to top move require getDefaultWalletKeys, toKeychainObjects to top TICKET: WP-5955 --- modules/sdk-coin-btc/test/unit/btc.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/modules/sdk-coin-btc/test/unit/btc.ts b/modules/sdk-coin-btc/test/unit/btc.ts index b2b7d40960..225f20e88a 100644 --- a/modules/sdk-coin-btc/test/unit/btc.ts +++ b/modules/sdk-coin-btc/test/unit/btc.ts @@ -8,6 +8,8 @@ import { Tbtc } from '../../src'; import { BitGoAPI } from '@bitgo/sdk-api'; import * as utxolib from '@bitgo/utxo-lib'; +const { getDefaultWalletKeys, toKeychainObjects } = require('../../../bitgo/test/v2/unit/coins/utxo/util/keychains'); + describe('BTC:', () => { let bitgo: TestBitGoAPI; @@ -118,10 +120,6 @@ describe('BTC:', () => { }); it('should detect hex spoofing in BUILD_SIGN_SEND', async (): Promise => { - const { - getDefaultWalletKeys, - toKeychainObjects, - } = require('../../../bitgo/test/v2/unit/coins/utxo/util/keychains'); const rootWalletKey = getDefaultWalletKeys(); const keysObj = toKeychainObjects(rootWalletKey, 'pass'); @@ -189,10 +187,6 @@ describe('BTC:', () => { }); it('should detect hex spoofing in fanout BUILD_SIGN_SEND', async (): Promise => { - const { - getDefaultWalletKeys, - toKeychainObjects, - } = require('../../../bitgo/test/v2/unit/coins/utxo/util/keychains'); const rootWalletKey = getDefaultWalletKeys(); const keysObj = toKeychainObjects(rootWalletKey, 'pass'); From 91cf2153c3c859cb641d859f7e68b238b549da53 Mon Sep 17 00:00:00 2001 From: Daniel Peng Date: Wed, 24 Sep 2025 08:27:22 -0400 Subject: [PATCH 8/8] fix(sdk-coin-btc): quick refactor for wallet key handling in BTC tests TICKET: WP-5945 --- modules/sdk-coin-btc/test/unit/btc.ts | 41 ++++++++++++++++++--------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/modules/sdk-coin-btc/test/unit/btc.ts b/modules/sdk-coin-btc/test/unit/btc.ts index 225f20e88a..ae9a35e949 100644 --- a/modules/sdk-coin-btc/test/unit/btc.ts +++ b/modules/sdk-coin-btc/test/unit/btc.ts @@ -5,10 +5,10 @@ import { btcBackupKey } from './fixtures'; import { type TestBitGoAPI, TestBitGo } from '@bitgo/sdk-test'; import { Tbtc } from '../../src'; -import { BitGoAPI } from '@bitgo/sdk-api'; +import { BitGoAPI, encrypt } from '@bitgo/sdk-api'; import * as utxolib from '@bitgo/utxo-lib'; -const { getDefaultWalletKeys, toKeychainObjects } = require('../../../bitgo/test/v2/unit/coins/utxo/util/keychains'); +import { Wallet } from '@bitgo/sdk-core'; describe('BTC:', () => { let bitgo: TestBitGoAPI; @@ -120,14 +120,14 @@ describe('BTC:', () => { }); it('should detect hex spoofing in BUILD_SIGN_SEND', async (): Promise => { - const rootWalletKey = getDefaultWalletKeys(); - const keysObj = toKeychainObjects(rootWalletKey, 'pass'); + const keyTriple = utxolib.testutil.getKeyTriple('default'); + const rootWalletKey = new utxolib.bitgo.RootWalletKeys(keyTriple); + const [user] = keyTriple; - const { Wallet } = await import('@bitgo/sdk-core'); const wallet = new Wallet(bitgoTest, coin, { id: '5b34252f1bf349930e34020a', coin: 'tbtc', - keys: keysObj.map((k) => k.id), + keys: ['user', 'backup', 'bitgo'], }); const originalPsbt = utxolib.testutil.constructPsbt( @@ -138,7 +138,6 @@ describe('BTC:', () => { 'unsigned' as const ); utxolib.bitgo.addXpubsToPsbt(originalPsbt, rootWalletKey); - const spoofedPsbt = utxolib.testutil.constructPsbt( [{ scriptType: 'p2wsh' as const, value: BigInt(10000) }], [{ address: 'tb1pjgg9ty3s2ztp60v6lhgrw76f7hxydzuk9t9mjsndh3p2gf2ah7gs4850kn', value: BigInt(9000) }], @@ -165,7 +164,15 @@ describe('BTC:', () => { return [200, { txid: 'test-txid-123', status: 'signed' }]; }); - keysObj.forEach((k, i) => nock(bgUrl).get(`/api/v2/${wallet.coin()}/key/${wallet.keyIds()[i]}`).reply(200, k)); + const pubs = keyTriple.map((k) => k.neutered().toBase58()); + const responses = [ + { pub: pubs[0], encryptedPrv: encrypt('pass', user.toBase58()) }, + { pub: pubs[1] }, + { pub: pubs[2] }, + ]; + wallet + .keyIds() + .forEach((id, i) => nock(bgUrl).get(`/api/v2/${wallet.coin()}/key/${id}`).reply(200, responses[i])); await assert.rejects( wallet.consolidateUnspents({ walletPassphrase: 'pass' }), @@ -187,14 +194,14 @@ describe('BTC:', () => { }); it('should detect hex spoofing in fanout BUILD_SIGN_SEND', async (): Promise => { - const rootWalletKey = getDefaultWalletKeys(); - const keysObj = toKeychainObjects(rootWalletKey, 'pass'); + const keyTriple = utxolib.testutil.getKeyTriple('default'); + const rootWalletKey = new utxolib.bitgo.RootWalletKeys(keyTriple); + const [user] = keyTriple; - const { Wallet } = await import('@bitgo/sdk-core'); const wallet = new Wallet(bitgoTest, coin, { id: '5b34252f1bf349930e34020a', coin: 'tbtc', - keys: keysObj.map((k) => k.id), + keys: ['user', 'backup', 'bitgo'], }); const originalPsbt = utxolib.testutil.constructPsbt( @@ -232,7 +239,15 @@ describe('BTC:', () => { return [200, { txid: 'test-txid-123', status: 'signed' }]; }); - keysObj.forEach((k, i) => nock(bgUrl).get(`/api/v2/${wallet.coin()}/key/${wallet.keyIds()[i]}`).reply(200, k)); + const pubs = keyTriple.map((k) => k.neutered().toBase58()); + const responses = [ + { pub: pubs[0], encryptedPrv: encrypt('pass', user.toBase58()) }, + { pub: pubs[1] }, + { pub: pubs[2] }, + ]; + wallet + .keyIds() + .forEach((id, i) => nock(bgUrl).get(`/api/v2/${wallet.coin()}/key/${id}`).reply(200, responses[i])); await assert.rejects( wallet.fanoutUnspents({ walletPassphrase: 'pass' }),