@@ -18,6 +18,7 @@ import {
1818 EDDSAMethods ,
1919 EDDSAMethodTypes ,
2020 Environments ,
21+ getEddsaSigningMaterial ,
2122 KeyPair ,
2223 MPCAlgorithm ,
2324 MPCRecoveryOptions ,
@@ -32,6 +33,7 @@ import {
3233 ParseTransactionOptions as BaseParseTransactionOptions ,
3334 PublicKey ,
3435 RecoveryTxRequest ,
36+ signEddsaMpcV2RecoveryTx ,
3537 SignedTransaction ,
3638 SignTransactionOptions as BaseSignTransactionOptions ,
3739 TokenEnablementConfig ,
@@ -365,6 +367,7 @@ export class Near extends BaseCoin {
365367 }
366368 const bitgoKey = params . bitgoKey . replace ( / \s / g, '' ) ;
367369 const isUnsignedSweep = ! params . userKey && ! params . backupKey && ! params . walletPassphrase ;
370+ const isMpcV2 = await this . isMpcv2SigningMaterial ( params . userKey , params . backupKey , params . walletPassphrase ) ;
368371 const MPC = await EDDSAMethods . getInitializedMpcInstance ( ) ;
369372 const { storageAmountPerByte, transferCost, receiptConfig } = await this . getProtocolConfig ( ) ;
370373 let isStorageDepositEnabled = false ;
@@ -440,7 +443,8 @@ export class Near extends BaseCoin {
440443 bitgoKey ,
441444 isStorageDepositEnabled ,
442445 availableTokenBalance ,
443- isUnsignedSweep
446+ isUnsignedSweep ,
447+ isMpcV2
444448 ) ;
445449 }
446450
@@ -474,7 +478,7 @@ export class Near extends BaseCoin {
474478 const unsignedTransaction = ( await txBuilder . build ( ) ) as Transaction ;
475479 let serializedTx = unsignedTransaction . toBroadcastFormat ( ) ;
476480 if ( ! isUnsignedSweep ) {
477- serializedTx = await this . signRecoveryTransaction ( txBuilder , params , currPath , accountId ) ;
481+ serializedTx = await this . signRecoveryTransaction ( txBuilder , params , currPath , accountId , isMpcV2 ) ;
478482 } else {
479483 return this . buildUnsignedSweepTransaction (
480484 txBuilder ,
@@ -514,7 +518,8 @@ export class Near extends BaseCoin {
514518 bitgoKey : string ,
515519 isStorageDepositEnabled : boolean ,
516520 availableTokenBalance : BigNumber ,
517- isUnsignedSweep : boolean
521+ isUnsignedSweep : boolean ,
522+ isMpcV2 = false
518523 ) : Promise < MPCTx | MPCSweepTxs > {
519524 const factory = new TransactionBuilderFactory ( token ) ;
520525 const bs58EncodedPublicKey = nearAPI . utils . serialize . base_encode ( new Uint8Array ( Buffer . from ( senderAddress , 'hex' ) ) ) ;
@@ -549,7 +554,7 @@ export class Near extends BaseCoin {
549554 token
550555 ) ;
551556 } else {
552- const serializedTx = await this . signRecoveryTransaction ( txBuilder , params , derivationPath , senderAddress ) ;
557+ const serializedTx = await this . signRecoveryTransaction ( txBuilder , params , derivationPath , senderAddress , isMpcV2 ) ;
553558 return { serializedTx : serializedTx , scanIndex : idx } ;
554559 }
555560 }
@@ -631,12 +636,11 @@ export class Near extends BaseCoin {
631636 txBuilder : TransactionBuilder ,
632637 params : MPCRecoveryOptions ,
633638 derivationPath : string ,
634- senderAddress : string
639+ senderAddress : string ,
640+ isMpcV2 = false
635641 ) : Promise < string > {
636642 const unsignedTransaction = ( await txBuilder . build ( ) ) as Transaction ;
637- // Sign the txn
638- /* ***************** START **************************************/
639- // TODO(BG-51092): This looks like a common part which can be extracted out too
643+
640644 if ( ! params . userKey ) {
641645 throw new Error ( 'missing userKey' ) ;
642646 }
@@ -647,49 +651,68 @@ export class Near extends BaseCoin {
647651 throw new Error ( 'missing wallet passphrase' ) ;
648652 }
649653
650- // Clean up whitespace from entered values
651654 const userKey = params . userKey . replace ( / \s / g, '' ) ;
652655 const backupKey = params . backupKey . replace ( / \s / g, '' ) ;
653656
654- // Decrypt private keys from KeyCard values
655- let userPrv ;
656- try {
657- userPrv = await this . bitgo . decrypt ( {
658- input : userKey ,
659- password : params . walletPassphrase ,
657+ let signatureHex : Buffer ;
658+ if ( isMpcV2 ) {
659+ signatureHex = await signEddsaMpcV2RecoveryTx ( {
660+ message : unsignedTransaction . signablePayload ,
661+ userKey,
662+ backupKey,
663+ walletPassphrase : params . walletPassphrase ,
664+ bitgoKey : params . bitgoKey . replace ( / \s / g, '' ) ,
665+ derivationPath,
666+ bitgo : this . bitgo ,
660667 } ) ;
661- } catch ( e ) {
662- throw new Error ( `Error decrypting user keychain: ${ e . message } ` ) ;
663- }
664- /** TODO BG-52419 Implement Codec for parsing */
665- const userSigningMaterial = JSON . parse ( userPrv ) as EDDSAMethodTypes . UserSigningMaterial ;
668+ } else {
669+ let userPrv ;
670+ try {
671+ userPrv = await this . bitgo . decrypt ( {
672+ input : userKey ,
673+ password : params . walletPassphrase ,
674+ } ) ;
675+ } catch ( e ) {
676+ throw new Error ( `Error decrypting user keychain: ${ e . message } ` ) ;
677+ }
678+ const userSigningMaterial = JSON . parse ( userPrv ) as EDDSAMethodTypes . UserSigningMaterial ;
666679
667- let backupPrv ;
668- try {
669- backupPrv = await this . bitgo . decrypt ( {
670- input : backupKey ,
671- password : params . walletPassphrase ,
672- } ) ;
673- } catch ( e ) {
674- throw new Error ( `Error decrypting backup keychain: ${ e . message } ` ) ;
675- }
676- const backupSigningMaterial = JSON . parse ( backupPrv ) as EDDSAMethodTypes . BackupSigningMaterial ;
677- /* ********************** END ***********************************/
678-
679- // add signature
680- const signatureHex = await EDDSAMethods . getTSSSignature (
681- userSigningMaterial ,
682- backupSigningMaterial ,
683- derivationPath ,
684- unsignedTransaction
685- ) ;
686- const publicKeyObj = { pub : senderAddress } ;
687- txBuilder . addSignature ( publicKeyObj as PublicKey , signatureHex ) ;
680+ let backupPrv ;
681+ try {
682+ backupPrv = await this . bitgo . decrypt ( {
683+ input : backupKey ,
684+ password : params . walletPassphrase ,
685+ } ) ;
686+ } catch ( e ) {
687+ throw new Error ( `Error decrypting backup keychain: ${ e . message } ` ) ;
688+ }
689+ const backupSigningMaterial = JSON . parse ( backupPrv ) as EDDSAMethodTypes . BackupSigningMaterial ;
690+
691+ signatureHex = await EDDSAMethods . getTSSSignature (
692+ userSigningMaterial ,
693+ backupSigningMaterial ,
694+ derivationPath ,
695+ unsignedTransaction
696+ ) ;
697+ }
688698
699+ txBuilder . addSignature ( { pub : senderAddress } as PublicKey , signatureHex ) ;
689700 const completedTransaction = await txBuilder . build ( ) ;
690701 return completedTransaction . toBroadcastFormat ( ) ;
691702 }
692703
704+ private async isMpcv2SigningMaterial (
705+ userKey ?: string ,
706+ backupKey ?: string ,
707+ walletPassphrase ?: string
708+ ) : Promise < boolean > {
709+ if ( ! walletPassphrase ) return false ;
710+ if ( ! userKey ) throw new Error ( 'missing userKey' ) ;
711+ if ( ! backupKey ) throw new Error ( 'missing backupKey' ) ;
712+ const material = await getEddsaSigningMaterial ( userKey . replace ( / \s / g, '' ) , walletPassphrase , this . bitgo ) ;
713+ return material . version === 'v2' ;
714+ }
715+
693716 async createBroadcastableSweepTransaction ( params : MPCSweepRecoveryOptions ) : Promise < MPCTxs > {
694717 const req = params . signatureShares ;
695718 const broadcastableTransactions : MPCTx [ ] = [ ] ;
0 commit comments