Skip to content

Commit 19679cf

Browse files
committed
refactor: wallet generation handler to use new sdk callback
Ticket: WCN-684
1 parent 460224a commit 19679cf

6 files changed

Lines changed: 258 additions & 184 deletions

File tree

package-lock.json

Lines changed: 202 additions & 70 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
"@bitgo-beta/abstract-cosmos": "1.0.1-beta.1741",
3434
"@bitgo-beta/abstract-eth": "1.0.2-beta.2004",
3535
"@bitgo-beta/abstract-utxo": "1.1.1-beta.2007",
36-
"@bitgo-beta/sdk-api": "1.10.1-beta.1773",
36+
"@bitgo-beta/sdk-api": "1.10.1-beta.1812",
3737
"@bitgo-beta/sdk-coin-ada": "2.3.14-beta.1758",
3838
"@bitgo-beta/sdk-coin-algo": "2.8.9-beta.238",
3939
"@bitgo-beta/sdk-coin-apt": "1.0.1-beta.1200",
@@ -101,7 +101,7 @@
101101
"@bitgo-beta/sdk-coin-zec": "1.1.1-beta.1984",
102102
"@bitgo-beta/sdk-coin-zeta": "1.0.1-beta.1675",
103103
"@bitgo-beta/sdk-coin-zketh": "1.0.1-beta.1540",
104-
"@bitgo-beta/sdk-core": "8.2.1-beta.1775",
104+
"@bitgo-beta/sdk-core": "8.2.1-beta.1815",
105105
"@bitgo-beta/sdk-lib-mpc": "8.2.0-beta.1770",
106106
"@bitgo-beta/statics": "15.1.1-beta.1782",
107107
"@bitgo/wasm-miniscript": "2.0.0-beta.7",
@@ -122,7 +122,7 @@
122122
"zod": "^3.25.48"
123123
},
124124
"overrides": {
125-
"@bitgo-beta/sdk-core": "8.2.1-beta.1775",
125+
"@bitgo-beta/sdk-core": "8.2.1-beta.1815",
126126
"@bitgo-beta/statics": "15.1.1-beta.1782",
127127
"elliptic": "^6.6.1",
128128
"expo": "^48.0.0",

src/__tests__/api/master/generateWallet.test.ts

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ describe('POST /api/v1/:coin/advancedwallet/generate', () => {
6464
const ecdsaCoin = 'hteth';
6565
const accessToken = 'test-token';
6666

67+
// Valid BIP32 extended public keys required by the SDK's isValidPub check
68+
const validUserPub =
69+
'xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8';
70+
const validBackupPub =
71+
'xpub661MyMwAqRbcGczjuMoRm6dXaLDEhW1u34gKenbeYqAix21mdUKJyuyu5F1rzYGVxyL6tmgBUAEPrEz92mBXjByMRiJdba9wpnN37RLLAXa';
72+
6773
let bitgo: BitGoAPI;
6874

6975
before(() => {
@@ -144,7 +150,7 @@ describe('POST /api/v1/:coin/advancedwallet/generate', () => {
144150
source: 'user',
145151
})
146152
.reply(200, {
147-
pub: 'xpub_user',
153+
pub: validUserPub,
148154
source: 'user',
149155
type: 'independent',
150156
});
@@ -155,33 +161,37 @@ describe('POST /api/v1/:coin/advancedwallet/generate', () => {
155161
source: 'backup',
156162
})
157163
.reply(200, {
158-
pub: 'xpub_backup',
164+
pub: validBackupPub,
159165
source: 'backup',
160166
type: 'independent',
161167
});
162168

163169
const bitgoAddUserKeyNock = nock(bitgoApiUrl)
164170
.post(`/api/v2/${coin}/key`, {
165-
pub: 'xpub_user',
171+
pub: validUserPub,
166172
keyType: 'independent',
167173
source: 'user',
168174
})
169175
.matchHeader('any', () => true)
170-
.reply(200, { id: 'user-key-id', pub: 'xpub_user' });
176+
.reply(200, { id: 'user-key-id', pub: validUserPub, source: 'user', type: 'independent' });
171177

172178
const bitgoAddBackupKeyNock = nock(bitgoApiUrl)
173179
.post(`/api/v2/${coin}/key`, {
174-
pub: 'xpub_backup',
180+
pub: validBackupPub,
175181
keyType: 'independent',
176182
source: 'backup',
177183
})
178184
.matchHeader('any', () => true)
179-
.reply(200, { id: 'backup-key-id', pub: 'xpub_backup' });
185+
.reply(200, {
186+
id: 'backup-key-id',
187+
pub: validBackupPub,
188+
source: 'backup',
189+
type: 'independent',
190+
});
180191

181192
const bitgoAddBitGoKeyNock = nock(bitgoApiUrl)
182193
.post(`/api/v2/${coin}/key`, {
183194
source: 'bitgo',
184-
keyType: 'independent',
185195
enterprise: 'test_enterprise',
186196
})
187197
.reply(200, {
@@ -235,7 +245,7 @@ describe('POST /api/v1/:coin/advancedwallet/generate', () => {
235245
source: 'user',
236246
})
237247
.reply(200, {
238-
pub: 'xpub_user',
248+
pub: validUserPub,
239249
source: 'user',
240250
type: 'independent',
241251
});
@@ -245,33 +255,37 @@ describe('POST /api/v1/:coin/advancedwallet/generate', () => {
245255
source: 'backup',
246256
})
247257
.reply(200, {
248-
pub: 'xpub_backup',
258+
pub: validBackupPub,
249259
source: 'backup',
250260
type: 'independent',
251261
});
252262

253263
const bitgoAddUserKeyNock = nock(bitgoApiUrl)
254264
.post(`/api/v2/${coin}/key`, {
255-
pub: 'xpub_user',
265+
pub: validUserPub,
256266
keyType: 'independent',
257267
source: 'user',
258268
})
259269
.matchHeader('any', () => true)
260-
.reply(200, { id: 'user-key-id', pub: 'xpub_user' });
270+
.reply(200, { id: 'user-key-id', pub: validUserPub, source: 'user', type: 'independent' });
261271

262272
const bitgoAddBackupKeyNock = nock(bitgoApiUrl)
263273
.post(`/api/v2/${coin}/key`, {
264-
pub: 'xpub_backup',
274+
pub: validBackupPub,
265275
keyType: 'independent',
266276
source: 'backup',
267277
})
268278
.matchHeader('any', () => true)
269-
.reply(200, { id: 'backup-key-id', pub: 'xpub_backup' });
279+
.reply(200, {
280+
id: 'backup-key-id',
281+
pub: validBackupPub,
282+
source: 'backup',
283+
type: 'independent',
284+
});
270285

271286
const bitgoAddBitGoKeyNock = nock(bitgoApiUrl)
272287
.post(`/api/v2/${coin}/key`, {
273288
source: 'bitgo',
274-
keyType: 'independent',
275289
enterprise: 'test_enterprise',
276290
})
277291
.reply(200, {
@@ -288,8 +302,6 @@ describe('POST /api/v1/:coin/advancedwallet/generate', () => {
288302
.post(`/api/v2/${coin}/wallet/add`, {
289303
label: 'test_wallet',
290304
enterprise: 'test_enterprise',
291-
multisigType: 'onchain',
292-
coin: coin,
293305
m: 2,
294306
n: 3,
295307
keys: ['user-key-id', 'backup-key-id', 'bitgo-key-id'],
@@ -331,8 +343,8 @@ describe('POST /api/v1/:coin/advancedwallet/generate', () => {
331343
multisigType: 'onchain',
332344
type: 'advanced',
333345
});
334-
response.body.should.have.propertyByPath('userKeychain', 'pub').eql('xpub_user');
335-
response.body.should.have.propertyByPath('backupKeychain', 'pub').eql('xpub_backup');
346+
response.body.should.have.propertyByPath('userKeychain', 'pub').eql(validUserPub);
347+
response.body.should.have.propertyByPath('backupKeychain', 'pub').eql(validBackupPub);
336348
response.body.should.have.propertyByPath('bitgoKeychain', 'pub').eql('xpub_bitgo');
337349

338350
userKeychainNock.done();

src/advancedWalletManager/keyProviderClient/keyProviderClient.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ export class KeyProviderClient extends BaseHttpClient {
7777
);
7878
}
7979

80-
const { pub, coin, source } = response.body;
81-
return { pub, coin, source } as PostKeyResponse;
80+
const { pub, coin, source, type } = response.body;
81+
return { pub, coin, source, type } as PostKeyResponse;
8282
}
8383

8484
async getKey(params: GetKeyParams): Promise<GetKeyResponse> {

src/masterBitgoExpress/handlers/handleGenerateWallet.ts

Lines changed: 8 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
import {
2-
AddKeychainOptions,
3-
Keychain,
4-
KeychainsTriplet,
5-
promiseProps,
62
RequestTracer,
73
SupplementGenerateWalletOptions,
84
Wallet,
@@ -14,6 +10,7 @@ import { orchestrateEcdsaKeyGen } from './ecdsa';
1410
import { orchestrateEddsaKeyGen } from './eddsa';
1511
import coinFactory from '../../shared/coinFactory';
1612
import { BadRequestError } from '../../shared/errors';
13+
import { createOnchainKeyGenCallback } from './walletGenerationCallbacks';
1714

1815
/**
1916
* Request handler for generating an advanced wallet.
@@ -43,98 +40,18 @@ async function handleGenerateOnChainWallet(
4340
const bitgo = req.bitgo;
4441
const baseCoin = await coinFactory.getCoin(req.params.coin, bitgo);
4542

46-
// The awmClient is now available from the request
47-
const awmClient = req.awmUserClient;
48-
const awmBackupClient = req.awmBackupClient;
43+
const createKeychainCallback = createOnchainKeyGenCallback(
44+
req.awmUserClient,
45+
req.awmBackupClient,
46+
);
4947

50-
const reqId = new RequestTracer();
51-
52-
const { label, enterprise } = req.decoded;
53-
54-
// Create wallet parameters
55-
const walletParams = {
48+
const result = await baseCoin.wallets().generateWallet({
5649
...req.decoded,
57-
label: label,
58-
m: 2,
59-
n: 3,
60-
keys: [],
61-
type: 'advanced',
50+
type: 'advanced' as 'cold',
6251
multisigType: 'onchain',
63-
} as SupplementGenerateWalletOptions;
64-
65-
if (!_.isUndefined(enterprise)) {
66-
if (!_.isString(enterprise)) {
67-
throw new Error('invalid enterprise argument, expecting string');
68-
}
69-
walletParams.enterprise = enterprise;
70-
}
71-
72-
const userKeychainPromise = async (): Promise<Keychain> => {
73-
const userKeychain = await awmClient.createIndependentKeychain({
74-
source: 'user',
75-
coin: req.params.coin,
76-
type: 'independent',
77-
});
78-
const userKeychainParams: AddKeychainOptions = {
79-
pub: userKeychain.pub,
80-
keyType: userKeychain.type,
81-
source: userKeychain.source,
82-
reqId,
83-
};
84-
85-
const newUserKeychain = await baseCoin.keychains().add(userKeychainParams);
86-
return _.extend({}, newUserKeychain, userKeychain);
87-
};
88-
89-
const backupKeychainPromise = async (): Promise<Keychain> => {
90-
const backupKeychain = await awmBackupClient.createIndependentKeychain({
91-
source: 'backup',
92-
coin: req.params.coin,
93-
type: 'independent',
94-
});
95-
const backupKeychainParams: AddKeychainOptions = {
96-
pub: backupKeychain.pub,
97-
keyType: backupKeychain.type,
98-
source: backupKeychain.source,
99-
reqId,
100-
};
101-
102-
const newBackupKeychain = await baseCoin.keychains().add(backupKeychainParams);
103-
return _.extend({}, newBackupKeychain, backupKeychain);
104-
};
105-
106-
const { userKeychain, backupKeychain, bitgoKeychain }: KeychainsTriplet = await promiseProps({
107-
userKeychain: userKeychainPromise(),
108-
backupKeychain: backupKeychainPromise(),
109-
bitgoKeychain: baseCoin.keychains().createBitGo({
110-
enterprise: req.decoded.enterprise,
111-
keyType: 'independent',
112-
reqId,
113-
isDistributedCustody: req.decoded.isDistributedCustody,
114-
}),
52+
createKeychainCallback,
11553
});
11654

117-
walletParams.keys = [userKeychain.id, backupKeychain.id, bitgoKeychain.id];
118-
119-
const keychains = {
120-
userKeychain,
121-
backupKeychain,
122-
bitgoKeychain,
123-
};
124-
125-
const finalWalletParams = await baseCoin.supplementGenerateWallet(walletParams, keychains);
126-
127-
bitgo.setRequestTracer(reqId);
128-
const newWallet = await bitgo.post(baseCoin.url('/wallet/add')).send(finalWalletParams).result();
129-
130-
const result: WalletWithKeychains = {
131-
wallet: new Wallet(bitgo, baseCoin, newWallet),
132-
userKeychain: userKeychain,
133-
backupKeychain: backupKeychain,
134-
bitgoKeychain: bitgoKeychain,
135-
responseType: 'WalletWithKeychains',
136-
};
137-
13855
return { ...result, wallet: result.wallet.toJSON() };
13956
}
14057

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { CreateKeychainCallback } from '@bitgo-beta/sdk-core';
2+
import { AdvancedWalletManagerClient } from '../clients/advancedWalletManagerClient';
3+
4+
export function createOnchainKeyGenCallback(
5+
awmUserClient: AdvancedWalletManagerClient,
6+
awmBackupClient: AdvancedWalletManagerClient,
7+
): CreateKeychainCallback {
8+
return async ({ source, coin }) => {
9+
const client = source === 'user' ? awmUserClient : awmBackupClient;
10+
const keychain = await client.createIndependentKeychain({ source, coin, type: 'independent' });
11+
return keychain as { pub: string; type: 'independent'; source: typeof source };
12+
};
13+
}

0 commit comments

Comments
 (0)