Skip to content

Commit 0efe1d0

Browse files
fix(account-lib): update module imports for Node 22 ESM compatibility
Modified sinon stubbing approach to work with ESM modules by using require() and monkey patching instead of direct imports, which allows tests to function correctly after migrating from ts-node to tsx. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> TICKET: WP-5599
1 parent 4df9c97 commit 0efe1d0

File tree

1 file changed

+43
-20
lines changed
  • modules/account-lib/test/unit/mpc/tss/ecdsa

1 file changed

+43
-20
lines changed

modules/account-lib/test/unit/mpc/tss/ecdsa/ecdsa.ts

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44
import assert from 'assert';
55
import { Hash, randomBytes } from 'crypto';
66
import { Ecdsa, ECDSA, hexToBigInt } from '@bitgo/sdk-core';
7-
import { EcdsaPaillierProof, EcdsaTypes, Schnorr, SchnorrProof } from '@bitgo/sdk-lib-mpc';
7+
import { EcdsaPaillierProof, EcdsaTypes, SchnorrProof } from '@bitgo/sdk-lib-mpc';
88
import * as sinon from 'sinon';
99
import createKeccakHash from 'keccak';
10-
import * as paillierBigint from 'paillier-bigint';
1110
import {
1211
schnorrProofs,
1312
ntildes,
@@ -19,6 +18,12 @@ import {
1918
mockFKeyShare,
2019
} from '../fixtures/ecdsa';
2120

21+
// Need to import and then monkey-patch to make stubbing work with ESM
22+
const paillierBigintModule = require('paillier-bigint');
23+
const paillierBigint = paillierBigintModule;
24+
const schnorrModule = require('@bitgo/sdk-lib-mpc');
25+
const Schnorr = schnorrModule.Schnorr;
26+
2227
describe('TSS ECDSA TESTS', function () {
2328
const MPC = new Ecdsa();
2429
const base = BigInt('0x010000000000000000000000000000000000000000000000000000000000000000'); // 2^256
@@ -30,23 +35,35 @@ describe('TSS ECDSA TESTS', function () {
3035
);
3136
let A: ECDSA.KeyShare, B: ECDSA.KeyShare, C: ECDSA.KeyShare;
3237
before(async () => {
33-
const paillierMock = sinon
34-
.stub(paillierBigint, 'generateRandomKeys')
38+
// Direct monkey patching of the module for ESM compatibility
39+
const originalGenerateRandomKeys = paillierBigint.generateRandomKeys;
40+
41+
const paillierMock = sinon.stub();
42+
paillierMock
3543
.onCall(0)
36-
.resolves(paillerKeys[0] as unknown as paillierBigint.KeyPair)
44+
.resolves(paillerKeys[0])
3745
.onCall(1)
38-
.resolves(paillerKeys[1] as unknown as paillierBigint.KeyPair)
46+
.resolves(paillerKeys[1])
3947
.onCall(2)
40-
.resolves(paillerKeys[2] as unknown as paillierBigint.KeyPair)
48+
.resolves(paillerKeys[2])
4149
.onCall(3)
42-
.resolves(paillerKeys[0] as unknown as paillierBigint.KeyPair)
50+
.resolves(paillerKeys[0])
4351
.onCall(4)
44-
.resolves(paillerKeys[1] as unknown as paillierBigint.KeyPair)
52+
.resolves(paillerKeys[1])
4553
.onCall(5)
46-
.resolves(paillerKeys[2] as unknown as paillierBigint.KeyPair);
54+
.resolves(paillerKeys[2]);
55+
56+
// Replace the function directly on the module
57+
paillierBigint.generateRandomKeys = paillierMock;
58+
59+
// Save references to restore later
60+
(paillierMock as any).originalFn = originalGenerateRandomKeys;
4761

48-
const schnorrProofMock = sinon
49-
.stub(Schnorr, 'createSchnorrProof')
62+
// Apply the same monkey-patching approach for Schnorr
63+
const originalCreateSchnorrProof = Schnorr.createSchnorrProof;
64+
65+
const schnorrProofMock = sinon.stub();
66+
schnorrProofMock
5067
.onCall(0)
5168
.returns(schnorrProofs[0] as unknown as SchnorrProof)
5269
.onCall(1)
@@ -60,6 +77,12 @@ describe('TSS ECDSA TESTS', function () {
6077
.onCall(5)
6178
.returns(schnorrProofs[5] as unknown as SchnorrProof);
6279

80+
// Replace the function directly on the module
81+
Schnorr.createSchnorrProof = schnorrProofMock;
82+
83+
// Save references to restore later
84+
(schnorrProofMock as any).originalFn = originalCreateSchnorrProof;
85+
6386
[A, B, C] = await Promise.all([MPC.keyShare(1, 2, 3), MPC.keyShare(2, 2, 3), MPC.keyShare(3, 2, 3)]);
6487

6588
// Needs to run this serially for testing deterministic key generation
@@ -96,10 +119,13 @@ describe('TSS ECDSA TESTS', function () {
96119
hKeyCombine,
97120
];
98121
commonPublicKey = aKeyCombine.xShare.y;
99-
paillierMock.reset();
100-
paillierMock.restore();
101-
schnorrProofMock.reset();
102-
schnorrProofMock.restore();
122+
// Adding an explicit assertion to check if the stub was used
123+
paillierMock.callCount.should.equal(6, 'paillierMock should be called 6 times');
124+
schnorrProofMock.callCount.should.equal(8, 'schnorrProofMock should be called 6 times');
125+
126+
// Restore original functions
127+
paillierBigint.generateRandomKeys = (paillierMock as any).originalFn;
128+
Schnorr.createSchnorrProof = (schnorrProofMock as any).originalFn;
103129
});
104130

105131
describe('Ecdsa Key Generation Test', function () {
@@ -149,10 +175,7 @@ describe('TSS ECDSA TESTS', function () {
149175
});
150176

151177
it('should pass if seed length is greater than 64', async function () {
152-
const paillierMock = sinon
153-
.stub(paillierBigint, 'generateRandomKeys')
154-
.onCall(0)
155-
.resolves(paillerKeys[0] as unknown as paillierBigint.KeyPair);
178+
const paillierMock = sinon.stub(paillierBigint, 'generateRandomKeys').onCall(0).resolves(paillerKeys[0]);
156179
const seed72Bytes = Buffer.from(
157180
'4f7e914dc9ec696398675d1544aab61cb7a67662ffcbdb4079ec5d682be565d87c1b2de75c943dec14c96586984860268779498e6732473aed9ed9c2538f50bea0af926bdccc0134',
158181
'hex',

0 commit comments

Comments
 (0)