@@ -101,8 +101,21 @@ export class Wallets implements IWallets {
101101 throw new Error ( 'missing required string parameter label' ) ;
102102 }
103103
104- // no need to pass keys for (single) custodial wallets
105- if ( params . type !== 'custodial' ) {
104+ // Validate referenceWalletId parameter
105+ if ( params . referenceWalletId ) {
106+ if ( ! _ . isString ( params . referenceWalletId ) ) {
107+ throw new Error ( 'invalid referenceWalletId argument, expecting string' ) ;
108+ }
109+ if ( ! this . baseCoin . isEVM ( ) ) {
110+ throw new Error ( 'referenceWalletId is only supported for EVM chains' ) ;
111+ }
112+ }
113+
114+ // For wallets with referenceWalletId, skip multisig validation as configuration is inherited
115+ if ( params . referenceWalletId ) {
116+ // Skip all multisig validation - configuration will be inherited from reference wallet
117+ } else if ( params . type !== 'custodial' ) {
118+ // Standard validation for non-custodial wallets without referenceWalletId
106119 if ( Array . isArray ( params . keys ) === false || ! _ . isNumber ( params . m ) || ! _ . isNumber ( params . n ) ) {
107120 throw new Error ( 'invalid argument' ) ;
108121 }
@@ -272,9 +285,10 @@ export class Wallets implements IWallets {
272285 throw new Error ( 'missing required string parameter label' ) ;
273286 }
274287
275- const { type = 'hot' , label, passphrase, enterprise, isDistributedCustody } = params ;
288+ const { type = 'hot' , label, passphrase, enterprise, isDistributedCustody, referenceWalletId } = params ;
276289 const isTss = params . multisigType === 'tss' && this . baseCoin . supportsTss ( ) ;
277290 const canEncrypt = ! ! passphrase && typeof passphrase === 'string' ;
291+ const isEVMWithReference = this . baseCoin . isEVM ( ) && referenceWalletId ;
278292
279293 const walletParams : SupplementGenerateWalletOptions = {
280294 label : label ,
@@ -284,6 +298,11 @@ export class Wallets implements IWallets {
284298 type : ! ! params . userKey && params . multisigType !== 'onchain' ? 'cold' : type ,
285299 } ;
286300
301+ // Add referenceWalletId to walletParams if provided for EVM chains
302+ if ( isEVMWithReference ) {
303+ walletParams . referenceWalletId = referenceWalletId ;
304+ }
305+
287306 if ( ! _ . isUndefined ( params . passcodeEncryptionCode ) ) {
288307 if ( ! _ . isString ( params . passcodeEncryptionCode ) ) {
289308 throw new Error ( 'passcodeEncryptionCode must be a string' ) ;
@@ -297,15 +316,59 @@ export class Wallets implements IWallets {
297316 walletParams . enterprise = enterprise ;
298317 }
299318
319+ // Validate referenceWalletId for EVM keyring
320+ if ( ! _ . isUndefined ( referenceWalletId ) ) {
321+ if ( ! _ . isString ( referenceWalletId ) ) {
322+ throw new Error ( 'invalid referenceWalletId argument, expecting string' ) ;
323+ }
324+ if ( ! this . baseCoin . isEVM ( ) ) {
325+ throw new Error ( 'referenceWalletId is only supported for EVM chains' ) ;
326+ }
327+ }
328+
300329 // EVM TSS wallets must use wallet version 3, 5 and 6
330+ // Skip this validation for EVM keyring wallets as they inherit version from reference wallet
301331 if (
302332 isTss &&
303333 this . baseCoin . isEVM ( ) &&
334+ ! referenceWalletId &&
304335 ! ( params . walletVersion === 3 || params . walletVersion === 5 || params . walletVersion === 6 )
305336 ) {
306337 throw new Error ( 'EVM TSS wallets are only supported for wallet version 3, 5 and 6' ) ;
307338 }
308339
340+ // Handle EVM keyring wallet creation with referenceWalletId
341+ if ( isEVMWithReference ) {
342+ // For EVM keyring wallets, multisigType will be inferred from the reference wallet
343+ // No need to explicitly validate TSS requirement here as it will be handled by bgms
344+
345+ // For EVM keyring wallets, we use the add method directly with referenceWalletId
346+ // This bypasses the normal key generation process since keys are shared via keyring
347+ const addWalletParams = {
348+ label,
349+ referenceWalletId,
350+ } ;
351+
352+ const newWallet = await this . bitgo . post ( this . baseCoin . url ( '/wallet/add' ) ) . send ( addWalletParams ) . result ( ) ;
353+
354+ // For EVM keyring wallets, we need to get the keychains from the reference wallet
355+ const userKeychain = this . baseCoin . keychains ( ) . get ( { id : newWallet . keys [ KeyIndices . USER ] } ) ;
356+ const backupKeychain = this . baseCoin . keychains ( ) . get ( { id : newWallet . keys [ KeyIndices . BACKUP ] } ) ;
357+ const bitgoKeychain = this . baseCoin . keychains ( ) . get ( { id : newWallet . keys [ KeyIndices . BITGO ] } ) ;
358+
359+ const [ userKey , backupKey , bitgoKey ] = await Promise . all ( [ userKeychain , backupKeychain , bitgoKeychain ] ) ;
360+
361+ const result : WalletWithKeychains = {
362+ wallet : new Wallet ( this . bitgo , this . baseCoin , newWallet ) ,
363+ userKeychain : userKey ,
364+ backupKeychain : backupKey ,
365+ bitgoKeychain : bitgoKey ,
366+ responseType : 'WalletWithKeychains' ,
367+ } ;
368+
369+ return result ;
370+ }
371+
309372 if ( isTss ) {
310373 if ( ! this . baseCoin . supportsTss ( ) ) {
311374 throw new Error ( `coin ${ this . baseCoin . getFamily ( ) } does not support TSS at this time` ) ;
0 commit comments