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
21 changes: 16 additions & 5 deletions src/__tests__/api/master/ecdsa.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'should';
import nock from 'nock';
import * as sinon from 'sinon';
import {
EcdsaMPCv2Utils,
Environments,
IRequestTracer,
openpgpUtils,
Expand All @@ -13,10 +12,10 @@ import {
TxRequest,
Wallet,
} from '@bitgo-beta/sdk-core';
import { BitGoAPI } from '@bitgo-beta/sdk-api';
import { AdvancedWalletManagerClient } from '../../../masterBitgoExpress/clients/advancedWalletManagerClient';
import { signAndSendEcdsaMPCv2FromTxRequest } from '../../../masterBitgoExpress/handlers/ecdsa';
import { BitGoAPI } from '@bitgo-beta/sdk-api';
import { readKey } from 'openpgp';
import { BitGoAPITestHarness } from './testUtils';

describe('Ecdsa Signing Handler', () => {
let bitgo: BitGoAPI;
Expand Down Expand Up @@ -57,6 +56,7 @@ describe('Ecdsa Signing Handler', () => {
afterEach(() => {
nock.cleanAll();
sinon.restore();
BitGoAPITestHarness.clearConstantsCache();
});

after(() => {
Expand Down Expand Up @@ -84,8 +84,19 @@ describe('Ecdsa Signing Handler', () => {
const userPubKey = 'test-user-pub-key';

const bitgoGpgKey = await openpgpUtils.generateGPGKeyPair('secp256k1');
const pgpKey = await readKey({ armoredKey: bitgoGpgKey.publicKey });
sinon.stub(EcdsaMPCv2Utils.prototype, 'getBitgoMpcv2PublicGpgKey').resolves(pgpKey);
const bitgoEd25519Key = await openpgpUtils.generateGPGKeyPair('ed25519');

nock(bitgoApiUrl)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would this pr introduce any latency for ci test as we now using sdk functions?

Copy link
Copy Markdown
Contributor Author

@danielpeng1 danielpeng1 May 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think so, when running tests locally any latency was not noticeable, and looking at CI shows that the testing job for this PR took 1m 9 seconds, exactly the same time as in this older PR https://github.com/BitGo/advanced-wallets/actions/runs/25590599173/job/75127489578

.persist()
.get('/api/v1/client/constants')
.reply(200, {
constants: {
mpc: {
bitgoMPCv2PublicKey: bitgoGpgKey.publicKey,
bitgoPublicKey: bitgoEd25519Key.publicKey,
},
},
});

// Mock sendSignatureShareV2 calls for each round
const round1SignatureShare: SignatureShareRecord = {
Expand Down
12 changes: 5 additions & 7 deletions src/__tests__/api/master/eddsa.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import nock from 'nock';
import * as sinon from 'sinon';
import {
BitGoBase,
EddsaUtils,
Environments,
IRequestTracer,
openpgpUtils,
Expand All @@ -14,7 +13,7 @@ import {
import { BitGoAPI } from '@bitgo-beta/sdk-api';
import { AdvancedWalletManagerClient as AdvancedWalletManagerClient } from '../../../masterBitgoExpress/clients/advancedWalletManagerClient';
import { handleEddsaSigning } from '../../../masterBitgoExpress/handlers/eddsa';
import { readKey } from 'openpgp';
import { BitGoAPITestHarness } from './testUtils';

describe('Eddsa Signing Handler', () => {
let bitgo: BitGoBase;
Expand Down Expand Up @@ -52,6 +51,7 @@ describe('Eddsa Signing Handler', () => {
afterEach(() => {
nock.cleanAll();
sinon.restore();
BitGoAPITestHarness.clearConstantsCache();
});

after(() => {
Expand Down Expand Up @@ -100,10 +100,10 @@ describe('Eddsa Signing Handler', () => {
const userPubKey = 'test-user-pub-key';

const bitgoGpgKey = await openpgpUtils.generateGPGKeyPair('ed25519');
const getGPGKeysStub = sinon.stub().resolves([{ pub: bitgoGpgKey.publicKey }]);

const pgpKey = await readKey({ armoredKey: bitgoGpgKey.publicKey });
sinon.stub(EddsaUtils.prototype, 'getBitgoPublicGpgKey').resolves(pgpKey);
nock(bitgoApiUrl)
.get('/api/v1/client/constants')
.reply(200, { constants: { mpc: { bitgoPublicKey: bitgoGpgKey.publicKey } } });

// Mock exchangeEddsaCommitments call
const exchangeCommitmentsNock = nock(bitgoApiUrl)
Expand Down Expand Up @@ -226,8 +226,6 @@ describe('Eddsa Signing Handler', () => {
},
});

(bitgo as any).getGPGKeys = getGPGKeysStub;

const result = await handleEddsaSigning(bitgo, wallet, txRequest, awmClient, userPubKey, reqId);

result.should.eql({
Expand Down
58 changes: 23 additions & 35 deletions src/__tests__/api/master/generateWallet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,7 @@ import { Environments } from '@bitgo-beta/sdk-core';
import { BitGoAPI } from '@bitgo-beta/sdk-api';
import * as middleware from '../../../shared/middleware';
import { BitGoRequest } from '../../../types/request';

/**
* This test suite demonstrates how to mock the BitGo SDK's fetchConstants method
* instead of using nock to intercept HTTP requests to the constants endpoint.
*
* By using sinon to stub the fetchConstants method directly, we make the tests more
* focused on behavior rather than implementation details, and less brittle to changes
* in how the constants are fetched.
*/
import { BitGoAPITestHarness } from './testUtils';

function mockWalletResponse(id: string, coinName: string, overrides: Record<string, unknown> = {}) {
return {
Expand Down Expand Up @@ -110,6 +102,7 @@ describe('POST /api/v1/:coin/advancedwallet/generate', () => {
afterEach(() => {
nock.cleanAll();
sinon.restore();
BitGoAPITestHarness.clearConstantsCache();
});

it('should generate an onchain wallet with separate backup AWM (separate-HSM mode)', async () => {
Expand Down Expand Up @@ -352,6 +345,12 @@ describe('POST /api/v1/:coin/advancedwallet/generate', () => {
const backupAwmUrl = 'http://backup-awm.invalid';

sinon.restore();
// Register before new BitGoAPI() so the constructor's background fetchConstants() hits the nock;
// use persist() since the background fetch and the handler may both call the endpoint
nock(bitgoApiUrl)
.persist()
.get('/api/v1/client/constants')
.reply(200, { constants: { mpc: { bitgoPublicKey: 'test-bitgo-public-key' } } });
const backupBitgo = new BitGoAPI({ env: 'test' });
const configWithBackup: MasterExpressConfig = {
appMode: AppMode.MASTER_EXPRESS,
Expand All @@ -378,12 +377,6 @@ describe('POST /api/v1/:coin/advancedwallet/generate', () => {
const app = expressApp(configWithBackup);
const backupAgent = request.agent(app);

sinon.stub(backupBitgo, 'fetchConstants').resolves({
mpc: {
bitgoPublicKey: 'test-bitgo-public-key',
},
});

// User init goes to primary AWM
const userInitNock = nock(advancedWalletManagerUrl)
.post(`/api/${eddsaCoin}/mpc/key/initialize`, {
Expand Down Expand Up @@ -667,12 +660,10 @@ describe('POST /api/v1/:coin/advancedwallet/generate', () => {
});

it('should generate a TSS MPC v1 wallet by calling the advanced wallet manager service', async () => {
// Mock fetchConstants instead of using nock for URL mocking
sinon.stub(bitgo, 'fetchConstants').resolves({
mpc: {
bitgoPublicKey: 'test-bitgo-public-key',
},
});
nock(bitgoApiUrl)
.persist()
.get('/api/v1/client/constants')
.reply(200, { constants: { mpc: { bitgoPublicKey: 'test-bitgo-public-key' } } });

const userInitNock = nock(advancedWalletManagerUrl)
.post(`/api/${eddsaCoin}/mpc/key/initialize`, {
Expand Down Expand Up @@ -991,7 +982,6 @@ describe('POST /api/v1/:coin/advancedwallet/generate', () => {
multisigType: 'tss',
});

// No need to check constantsNock since we're using sinon stub
userInitNock.done();
backupInitNock.done();
bitgoAddKeychainNock.done();
Expand All @@ -1007,6 +997,12 @@ describe('POST /api/v1/:coin/advancedwallet/generate', () => {
const backupAwmUrl = 'http://backup-awm.invalid';

sinon.restore();
// Register before new BitGoAPI() so the constructor's background fetchConstants() hits the nock;
// use persist() since the background fetch and the handler may both call the endpoint
nock(bitgoApiUrl)
.persist()
.get('/api/v1/client/constants')
.reply(200, { constants: { mpc: { bitgoMPCv2PublicKey: 'test-bitgo-public-key' } } });
const backupBitgo = new BitGoAPI({ env: 'test' });
const configWithBackup: MasterExpressConfig = {
appMode: AppMode.MASTER_EXPRESS,
Expand All @@ -1033,12 +1029,6 @@ describe('POST /api/v1/:coin/advancedwallet/generate', () => {
const app = expressApp(configWithBackup);
const backupAgent = request.agent(app);

sinon.stub(backupBitgo, 'fetchConstants').resolves({
mpc: {
bitgoMPCv2PublicKey: 'test-bitgo-public-key',
},
});

// Init: user goes to primary AWM, backup goes to backup AWM
const userInitNock = nock(advancedWalletManagerUrl)
.post(`/api/${ecdsaCoin}/mpcv2/initialize`, { source: 'user' })
Expand Down Expand Up @@ -1641,12 +1631,11 @@ describe('POST /api/v1/:coin/advancedwallet/generate', () => {
});

it('should generate a TSS MPC v2 wallet by calling the advanced wallet manager service', async () => {
// Mock fetchConstants instead of using nock for URL mocking
sinon.stub(bitgo, 'fetchConstants').resolves({
mpc: {
bitgoMPCv2PublicKey: 'test-bitgo-public-key',
},
});
nock(bitgoApiUrl)
.persist()
.get('/api/v1/client/constants')
.reply(200, { constants: { mpc: { bitgoMPCv2PublicKey: 'test-bitgo-public-key' } } });

// init round
const userInitNock = nock(advancedWalletManagerUrl)
.post(`/api/${ecdsaCoin}/mpcv2/initialize`, {
Expand Down Expand Up @@ -2287,7 +2276,6 @@ describe('POST /api/v1/:coin/advancedwallet/generate', () => {
type: 'advanced',
});

// No need to check constantsNock since we're using sinon stub
userInitNock.done();
backupInitNock.done();
userRound1Nock.done();
Expand Down
Loading
Loading