@@ -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,13 @@ 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 (
558+ txBuilder ,
559+ params ,
560+ derivationPath ,
561+ senderAddress ,
562+ isMpcV2
563+ ) ;
553564 return { serializedTx : serializedTx , scanIndex : idx } ;
554565 }
555566 }
@@ -631,12 +642,11 @@ export class Near extends BaseCoin {
631642 txBuilder : TransactionBuilder ,
632643 params : MPCRecoveryOptions ,
633644 derivationPath : string ,
634- senderAddress : string
645+ senderAddress : string ,
646+ isMpcV2 = false
635647 ) : Promise < string > {
636648 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
649+
640650 if ( ! params . userKey ) {
641651 throw new Error ( 'missing userKey' ) ;
642652 }
@@ -647,49 +657,68 @@ export class Near extends BaseCoin {
647657 throw new Error ( 'missing wallet passphrase' ) ;
648658 }
649659
650- // Clean up whitespace from entered values
651660 const userKey = params . userKey . replace ( / \s / g, '' ) ;
652661 const backupKey = params . backupKey . replace ( / \s / g, '' ) ;
653662
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 ,
663+ let signatureHex : Buffer ;
664+ if ( isMpcV2 ) {
665+ signatureHex = await signEddsaMpcV2RecoveryTx ( {
666+ message : unsignedTransaction . signablePayload ,
667+ userKey,
668+ backupKey,
669+ walletPassphrase : params . walletPassphrase ,
670+ bitgoKey : params . bitgoKey . replace ( / \s / g, '' ) ,
671+ derivationPath,
672+ bitgo : this . bitgo ,
660673 } ) ;
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 ;
674+ } else {
675+ let userPrv ;
676+ try {
677+ userPrv = await this . bitgo . decrypt ( {
678+ input : userKey ,
679+ password : params . walletPassphrase ,
680+ } ) ;
681+ } catch ( e ) {
682+ throw new Error ( `Error decrypting user keychain: ${ e . message } ` ) ;
683+ }
684+ const userSigningMaterial = JSON . parse ( userPrv ) as EDDSAMethodTypes . UserSigningMaterial ;
666685
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 ) ;
686+ let backupPrv ;
687+ try {
688+ backupPrv = await this . bitgo . decrypt ( {
689+ input : backupKey ,
690+ password : params . walletPassphrase ,
691+ } ) ;
692+ } catch ( e ) {
693+ throw new Error ( `Error decrypting backup keychain: ${ e . message } ` ) ;
694+ }
695+ const backupSigningMaterial = JSON . parse ( backupPrv ) as EDDSAMethodTypes . BackupSigningMaterial ;
688696
697+ signatureHex = await EDDSAMethods . getTSSSignature (
698+ userSigningMaterial ,
699+ backupSigningMaterial ,
700+ derivationPath ,
701+ unsignedTransaction
702+ ) ;
703+ }
704+
705+ txBuilder . addSignature ( { pub : senderAddress } as PublicKey , signatureHex ) ;
689706 const completedTransaction = await txBuilder . build ( ) ;
690707 return completedTransaction . toBroadcastFormat ( ) ;
691708 }
692709
710+ private async isMpcv2SigningMaterial (
711+ userKey ?: string ,
712+ backupKey ?: string ,
713+ walletPassphrase ?: string
714+ ) : Promise < boolean > {
715+ if ( ! walletPassphrase ) return false ;
716+ if ( ! userKey ) throw new Error ( 'missing userKey' ) ;
717+ if ( ! backupKey ) throw new Error ( 'missing backupKey' ) ;
718+ const material = await getEddsaSigningMaterial ( userKey . replace ( / \s / g, '' ) , walletPassphrase , this . bitgo ) ;
719+ return material . version === 'v2' ;
720+ }
721+
693722 async createBroadcastableSweepTransaction ( params : MPCSweepRecoveryOptions ) : Promise < MPCTxs > {
694723 const req = params . signatureShares ;
695724 const broadcastableTransactions : MPCTx [ ] = [ ] ;
0 commit comments