Skip to content

Commit 264e015

Browse files
feat(awm): wiring in backup key clients into recovery flows
Ticket: WCN-363
1 parent 2d9370c commit 264e015

5 files changed

Lines changed: 55 additions & 17 deletions

File tree

src/__tests__/api/advancedWalletManager/postMpcV2Key.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ describe('postMpcV2Key', () => {
4242
clientCertAllowSelfSigned: true,
4343
};
4444

45+
// Restore any existing stub from other test suites before re-stubbing
46+
if (typeof (configModule.initConfig as any).restore === 'function') {
47+
(configModule.initConfig as any).restore();
48+
}
4549
configStub = sinon.stub(configModule, 'initConfig').returns(cfg);
4650

4751
// app setup
@@ -93,7 +97,7 @@ describe('postMpcV2Key', () => {
9397
});
9498

9599
after(() => {
96-
configStub.restore();
100+
configStub?.restore();
97101
});
98102

99103
it('should be able to create a new MPC V2 wallet', async () => {

src/__tests__/api/advancedWalletManager/recoveryMpcV2.test.ts

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ describe('recoveryMpcV2', async () => {
2020
const cosmosLikeCoin = 'tsei';
2121
const accessToken = 'test-token';
2222

23-
// sinon stubs
23+
// sinon sandbox
24+
const sandbox = sinon.createSandbox();
2425
let configStub: sinon.SinonStub;
2526

2627
// key provider nocks setup
@@ -67,7 +68,11 @@ describe('recoveryMpcV2', async () => {
6768
recoveryMode: true,
6869
};
6970

70-
configStub = sinon.stub(configModule, 'initConfig').returns(cfg);
71+
// Restore any existing stub from other test suites before re-stubbing
72+
if (typeof (configModule.initConfig as any).restore === 'function') {
73+
(configModule.initConfig as any).restore();
74+
}
75+
configStub = sandbox.stub(configModule, 'initConfig').returns(cfg);
7176

7277
// app setup
7378
app = advancedWalletManagerApp(cfg);
@@ -79,7 +84,7 @@ describe('recoveryMpcV2', async () => {
7984
});
8085

8186
after(() => {
82-
configStub.restore();
87+
sandbox.restore();
8388
});
8489

8590
// happy path test
@@ -133,15 +138,30 @@ describe('recoveryMpcV2', async () => {
133138
});
134139

135140
it('should route backup key retrieval to backup KMS when configured', async () => {
141+
const kmsUrl = 'http://kms.invalid';
136142
const backupKmsUrl = 'http://backup-kms.invalid';
137143

144+
const mockKmsUserResponse = {
145+
prv: JSON.stringify(userKeyShare),
146+
pub: commonKeychain,
147+
source: 'user',
148+
type: 'tss',
149+
};
150+
151+
const mockKmsBackupResponse = {
152+
prv: JSON.stringify(backupKeyShare),
153+
pub: commonKeychain,
154+
source: 'backup',
155+
type: 'tss',
156+
};
157+
138158
// Reconfigure app with backup KMS URL
139-
configStub.restore();
140159
const dualCfg: AdvancedWalletManagerConfig = {
141160
...cfg,
161+
keyProviderUrl: kmsUrl,
142162
backupKmsUrl,
143163
};
144-
configStub = sinon.stub(configModule, 'initConfig').returns(dualCfg);
164+
configStub.returns(dualCfg);
145165
const dualApp = advancedWalletManagerApp(dualCfg);
146166
const dualAgent = request.agent(dualApp);
147167

src/__tests__/api/advancedWalletManager/recoveryMusigEth.test.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ describe('recoveryMultisigTransaction', () => {
2222
const coin = 'hteth';
2323
const accessToken = 'test-token';
2424

25-
// sinon stubs
25+
// sinon sandbox
26+
const sandbox = sinon.createSandbox();
2627
let configStub: sinon.SinonStub;
2728

2829
before(() => {
@@ -44,7 +45,11 @@ describe('recoveryMultisigTransaction', () => {
4445
recoveryMode: true,
4546
};
4647

47-
configStub = sinon.stub(configModule, 'initConfig').returns(cfg);
48+
// Restore any existing stub from other test suites before re-stubbing
49+
if (typeof (configModule.initConfig as any).restore === 'function') {
50+
(configModule.initConfig as any).restore();
51+
}
52+
configStub = sandbox.stub(configModule, 'initConfig').returns(cfg);
4853

4954
// app setup
5055
app = advancedWalletManagerApp(cfg);
@@ -56,7 +61,7 @@ describe('recoveryMultisigTransaction', () => {
5661
});
5762

5863
after(() => {
59-
configStub.restore();
64+
sandbox.restore();
6065
});
6166

6267
it('should generate a successful txHex from unsigned sweep prebuild data', async () => {
@@ -107,17 +112,18 @@ describe('recoveryMultisigTransaction', () => {
107112
});
108113

109114
it('should route backup key retrieval to backup KMS when configured', async () => {
115+
const kmsUrl = 'http://kms.invalid';
110116
const backupKmsUrl = 'http://backup-kms.invalid';
111117
const { userPub, backupPub, walletContractAddress, userPrv, backupPrv, txHexResult } = awmData;
112118
const unsignedSweepPrebuildTx = unsignedSweepRecJSON as unknown as any;
113119

114120
// Reconfigure app with backup KMS URL
115-
configStub.restore();
116121
const dualCfg: AdvancedWalletManagerConfig = {
117122
...cfg,
123+
keyProviderUrl: kmsUrl,
118124
backupKmsUrl,
119125
};
120-
configStub = sinon.stub(configModule, 'initConfig').returns(dualCfg);
126+
configStub.returns(dualCfg);
121127
const dualApp = advancedWalletManagerApp(dualCfg);
122128
const dualAgent = request.agent(dualApp);
123129

src/advancedWalletManager/handlers/ecdsaMPCV2Recovery.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,15 @@ export async function ecdsaMPCv2Recovery(
5252
);
5353
}
5454

55-
// setup clients and retreive the keys
56-
// TODO: this needs to be segerated if the EBE instance cannot retrieve both keys
57-
const keyProvider = new KeyProviderClient(req.config);
58-
const { prv: userPrv } = await keyProvider.getKey({ pub, source: 'user' });
59-
const { prv: backupPrv } = await keyProvider.getKey({ pub, source: 'backup' });
55+
// setup clients and retrieve the keys
56+
const userKeyProvider = new KeyProviderClient(req.config);
57+
const backupCfg =
58+
req.config.backupKmsUrl
59+
? { ...req.config, keyProviderUrl: req.config.backupKmsUrl }
60+
: req.config;
61+
const backupKeyProvider = new KeyProviderClient(backupCfg);
62+
const { prv: userPrv } = await userKeyProvider.getKey({ pub, source: 'user' });
63+
const { prv: backupPrv } = await backupKeyProvider.getKey({ pub, source: 'backup' });
6064

6165
// construct tx builder
6266
const txHash = await getMessageHash(coin, txHex);

src/advancedWalletManager/handlers/utils/utils.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ export async function retrieveKeyProviderPrvKey({
1616
source: string;
1717
cfg: AdvancedWalletManagerConfig;
1818
}): Promise<string> {
19-
const keyProvider = new KeyProviderClient(cfg);
19+
const effectiveCfg =
20+
source === 'backup' && cfg.backupKmsUrl
21+
? { ...cfg, keyProviderUrl: cfg.backupKmsUrl }
22+
: cfg;
23+
const keyProvider = new KeyProviderClient(effectiveCfg);
2024
// Retrieve the private key from key provider
2125
let prv: string;
2226
try {

0 commit comments

Comments
 (0)