@@ -20,6 +20,49 @@ import { BitGoRequest } from '../../../types/request';
2020 * in how the constants are fetched.
2121 */
2222
23+ function mockWalletResponse ( id : string , coinName : string , overrides : Record < string , unknown > = { } ) {
24+ return {
25+ id,
26+ users : [ { user : 'user-id' , permissions : [ 'admin' , 'spend' , 'view' ] } ] ,
27+ coin : coinName ,
28+ label : 'test_wallet' ,
29+ m : 2 ,
30+ n : 3 ,
31+ keys : [ 'user-key-id' , 'backup-key-id' , 'bitgo-key-id' ] ,
32+ keySignatures : { } ,
33+ enterprise : 'test_enterprise' ,
34+ organization : 'org-id' ,
35+ bitgoOrg : 'BitGo Inc' ,
36+ tags : [ id , 'test_enterprise' ] ,
37+ disableTransactionNotifications : false ,
38+ freeze : { } ,
39+ deleted : false ,
40+ approvalsRequired : 1 ,
41+ isCold : false ,
42+ coinSpecific : { } ,
43+ admin : { } ,
44+ allowBackupKeySigning : false ,
45+ clientFlags : [ ] ,
46+ recoverable : false ,
47+ startDate : '2025-01-01T00:00:00.000Z' ,
48+ hasLargeNumberOfAddresses : false ,
49+ config : { } ,
50+ balanceString : '0' ,
51+ confirmedBalanceString : '0' ,
52+ spendableBalanceString : '0' ,
53+ receiveAddress : {
54+ id : 'addr-id' ,
55+ address : '0xexampleaddress' ,
56+ chain : 0 ,
57+ index : 0 ,
58+ coin : coinName ,
59+ wallet : id ,
60+ coinSpecific : { } ,
61+ } ,
62+ ...overrides ,
63+ } ;
64+ }
65+
2366describe ( 'POST /api/v1/:coin/advancedwallet/generate' , ( ) => {
2467 let agent : request . SuperAgentTest ;
2568 const advancedWalletManagerUrl = 'http://advancedwalletmanager.invalid' ;
@@ -136,54 +179,24 @@ describe('POST /api/v1/:coin/advancedwallet/generate', () => {
136179 type : 'advanced' ,
137180 } )
138181 . matchHeader ( 'any' , ( ) => true )
139- . reply ( 200 , {
140- id : 'new-wallet-id' ,
141- users : [
142- {
143- user : 'user-id' ,
144- permissions : [ 'admin' , 'spend' , 'view' ] ,
182+ . reply (
183+ 200 ,
184+ mockWalletResponse ( 'new-wallet-id' , coin , {
185+ isCold : true ,
186+ pendingApprovals : [ ] ,
187+ receiveAddress : {
188+ id : 'addr-id' ,
189+ address : 'tb1qexampleaddress000000000000000000000' ,
190+ chain : 20 ,
191+ index : 0 ,
192+ coin : coin ,
193+ wallet : 'new-wallet-id' ,
194+ coinSpecific : { } ,
145195 } ,
146- ] ,
147- coin : coin ,
148- label : 'test_wallet' ,
149- m : 2 ,
150- n : 3 ,
151- keys : [ 'user-key-id' , 'backup-key-id' , 'bitgo-key-id' ] ,
152- keySignatures : { } ,
153- enterprise : 'test_enterprise' ,
154- organization : 'org-id' ,
155- bitgoOrg : 'BitGo Inc' ,
156- tags : [ 'new-wallet-id' , 'test_enterprise' ] ,
157- disableTransactionNotifications : false ,
158- freeze : { } ,
159- deleted : false ,
160- approvalsRequired : 1 ,
161- isCold : true ,
162- coinSpecific : { } ,
163- admin : { } ,
164- pendingApprovals : [ ] ,
165- allowBackupKeySigning : false ,
166- clientFlags : [ ] ,
167- recoverable : false ,
168- startDate : '2025-01-01T00:00:00.000Z' ,
169- hasLargeNumberOfAddresses : false ,
170- config : { } ,
171- balanceString : '0' ,
172- confirmedBalanceString : '0' ,
173- spendableBalanceString : '0' ,
174- receiveAddress : {
175- id : 'addr-id' ,
176- address : 'tb1qexampleaddress000000000000000000000' ,
177- chain : 20 ,
178- index : 0 ,
179- coin : coin ,
180- wallet : 'new-wallet-id' ,
181- coinSpecific : { } ,
182- } ,
183- // optional-ish fields used in assertions
184- multisigType : 'onchain' ,
185- type : 'advanced' ,
186- } ) ;
196+ multisigType : 'onchain' ,
197+ type : 'advanced' ,
198+ } ) ,
199+ ) ;
187200
188201 const response = await agent
189202 . post ( `/api/v1/${ coin } /advancedwallet/generate` )
@@ -1283,4 +1296,75 @@ describe('POST /api/v1/:coin/advancedwallet/generate', () => {
12831296 response . status . should . equal ( 400 ) ;
12841297 response . body . details . should . equal ( 'MPC wallet generation is not supported for coin tbtc' ) ;
12851298 } ) ;
1299+
1300+ it ( 'should skip calls to AWM and use existing keychains when evmKeyRingReferenceWalletId is provided' , async ( ) => {
1301+ /** GET mocks for Key Retrieval */
1302+ const userKeyNock = nock ( bitgoApiUrl )
1303+ . get ( `/api/v2/${ ecdsaCoin } /key/user-key-id` )
1304+ . reply ( 200 , { id : 'user-key-id' , source : 'user' , type : 'independent' } ) ;
1305+
1306+ const backupKeyNock = nock ( bitgoApiUrl )
1307+ . get ( `/api/v2/${ ecdsaCoin } /key/backup-key-id` )
1308+ . reply ( 200 , { id : 'backup-key-id' , source : 'backup' , type : 'independent' } ) ;
1309+
1310+ const bitgoKeyNock = nock ( bitgoApiUrl ) . get ( `/api/v2/${ ecdsaCoin } /key/bitgo-key-id` ) . reply ( 200 , {
1311+ id : 'bitgo-key-id' ,
1312+ source : 'bitgo' ,
1313+ type : 'independent' ,
1314+ isBitGo : true ,
1315+ isTrust : false ,
1316+ hsmType : 'institutional' ,
1317+ } ) ;
1318+
1319+ /** POST mock for the actual wallet creation */
1320+ const walletAddNock = nock ( bitgoApiUrl )
1321+ . post ( `/api/v2/${ ecdsaCoin } /wallet/add` , {
1322+ label : 'test_wallet' ,
1323+ evmKeyRingReferenceWalletId : '59cd72485007a239fb00282ed480da1f' ,
1324+ } )
1325+ . matchHeader ( 'any' , ( ) => true )
1326+ . reply (
1327+ 200 ,
1328+ mockWalletResponse ( 'new-keyring-wallet-id' , ecdsaCoin , {
1329+ multisigType : 'tss' ,
1330+ type : 'advanced' ,
1331+ } ) ,
1332+ ) ;
1333+
1334+ const response = await agent
1335+ . post ( `/api/v1/${ ecdsaCoin } /advancedwallet/generate` )
1336+ . set ( 'Authorization' , `Bearer ${ accessToken } ` )
1337+ . send ( {
1338+ label : 'test_wallet' ,
1339+ enterprise : 'test_enterprise' ,
1340+ multisigType : 'tss' ,
1341+ evmKeyRingReferenceWalletId : '59cd72485007a239fb00282ed480da1f' ,
1342+ } ) ;
1343+
1344+ response . status . should . equal ( 200 ) ;
1345+ response . body . wallet . id . should . equal ( 'new-keyring-wallet-id' ) ;
1346+
1347+ /** AWM was never called — if it had been, nock would've thrown since we never mocked POST AWM calls */
1348+ walletAddNock . done ( ) ;
1349+ userKeyNock . done ( ) ;
1350+ backupKeyNock . done ( ) ;
1351+ bitgoKeyNock . done ( ) ;
1352+ } ) ;
1353+
1354+ it ( 'should fail when evmKeyRingReferenceWalletId is provided for a non-EVM coin' , async ( ) => {
1355+ const response = await agent
1356+ . post ( `/api/v1/${ coin } /advancedwallet/generate` )
1357+ . set ( 'Authorization' , `Bearer ${ accessToken } ` )
1358+ . send ( {
1359+ label : 'test_wallet' ,
1360+ enterprise : 'test_enterprise' ,
1361+ multisigType : 'onchain' ,
1362+ evmKeyRingReferenceWalletId : '59cd72485007a239fb00282ed480da1f' ,
1363+ } ) ;
1364+
1365+ response . status . should . equal ( 400 ) ;
1366+ response . body . details . should . containEql (
1367+ 'EVM keyring wallet generation is not supported for coin tbtc' ,
1368+ ) ;
1369+ } ) ;
12861370} ) ;
0 commit comments