@@ -42,6 +42,7 @@ import {
4242 isValidPrv ,
4343 isValidXprv ,
4444} from '@bitgo/sdk-core' ;
45+ import { fixedScriptWallet } from '@bitgo/wasm-utxo' ;
4546
4647import {
4748 backupKeyRecovery ,
@@ -68,6 +69,7 @@ import {
6869 verifyTransaction ,
6970} from './transaction' ;
7071import type { TransactionExplanation } from './transaction/fixedScript/explainTransaction' ;
72+ import { Musig2Participant } from './transaction/fixedScript/musig2' ;
7173import {
7274 AggregateValidationError ,
7375 ErrorMissingOutputs ,
@@ -76,8 +78,8 @@ import {
7678import { assertDescriptorWalletAddress , getDescriptorMapFromWallet , isDescriptorWallet } from './descriptor' ;
7779import { getChainFromNetwork , getFamilyFromNetwork , getFullNameFromNetwork } from './names' ;
7880import { assertFixedScriptWalletAddress } from './address/fixedScript' ;
79- import { ParsedTransaction } from './transaction/types' ;
80- import { decodePsbtWith , stringToBufferTryFormats } from './transaction/decode' ;
81+ import { isSdkBackend , ParsedTransaction , SdkBackend } from './transaction/types' ;
82+ import { decodePsbtWith , encodeTransaction , stringToBufferTryFormats } from './transaction/decode' ;
8183import { toBip32Triple , UtxoKeychain } from './keychains' ;
8284import { verifyKeySignature , verifyUserPublicKey } from './verifyKey' ;
8385import { getPolicyForEnv } from './descriptor/validatePolicy' ;
@@ -213,6 +215,7 @@ export interface ExplainTransactionOptions<TNumber extends number | bigint = num
213215 txInfo ?: TransactionInfo < TNumber > ;
214216 feeInfo ?: string ;
215217 pubs ?: Triple < string > ;
218+ decodeWith ?: SdkBackend ;
216219}
217220
218221export interface DecoratedExplainTransactionOptions < TNumber extends number | bigint = number >
@@ -225,6 +228,7 @@ export type UtxoNetwork = utxolib.Network;
225228export interface TransactionPrebuild < TNumber extends number | bigint = number > extends BaseTransactionPrebuild {
226229 txInfo ?: TransactionInfo < TNumber > ;
227230 blockHeight ?: number ;
231+ decodeWith ?: SdkBackend ;
228232}
229233
230234export interface TransactionParams extends BaseTransactionParams {
@@ -284,6 +288,7 @@ type UtxoBaseSignTransactionOptions<TNumber extends number | bigint = number> =
284288 walletId ?: string ;
285289 txHex : string ;
286290 txInfo ?: TransactionInfo < TNumber > ;
291+ decodeWith ?: SdkBackend ;
287292 } ;
288293 /** xpubs triple for wallet (user, backup, bitgo). Required only when txPrebuild.txHex is not a PSBT */
289294 pubs ?: Triple < string > ;
@@ -360,7 +365,10 @@ export interface SignPsbtResponse {
360365 psbt : string ;
361366}
362367
363- export abstract class AbstractUtxoCoin extends BaseCoin {
368+ export abstract class AbstractUtxoCoin
369+ extends BaseCoin
370+ implements Musig2Participant < utxolib . bitgo . UtxoPsbt > , Musig2Participant < fixedScriptWallet . BitGoPsbt >
371+ {
364372 public altScriptHash ?: number ;
365373 public supportAltScriptDestination ?: boolean ;
366374 public readonly amountType : 'number' | 'bigint' ;
@@ -509,7 +517,7 @@ export abstract class AbstractUtxoCoin extends BaseCoin {
509517 if ( _ . isUndefined ( prebuild . blockHeight ) ) {
510518 prebuild . blockHeight = ( await this . getLatestBlockHeight ( ) ) as number ;
511519 }
512- return _ . extend ( { } , prebuild , { txHex : tx . toHex ( ) } ) ;
520+ return _ . extend ( { } , prebuild , { txHex : encodeTransaction ( tx ) . toString ( 'hex' ) } ) ;
513521 }
514522
515523 /**
@@ -526,38 +534,52 @@ export abstract class AbstractUtxoCoin extends BaseCoin {
526534 return utxolib . bitgo . createTransactionFromHex < TNumber > ( hex , this . network , this . amountType ) ;
527535 }
528536
529- decodeTransaction < TNumber extends number | bigint > ( input : Buffer | string ) : DecodedTransaction < TNumber > {
537+ decodeTransaction < TNumber extends number | bigint > (
538+ input : Buffer | string ,
539+ decodeWith ?: SdkBackend
540+ ) : DecodedTransaction < TNumber > {
530541 if ( typeof input === 'string' ) {
531542 const buffer = stringToBufferTryFormats ( input , [ 'hex' , 'base64' ] ) ;
532- return this . decodeTransaction ( buffer ) ;
543+ return this . decodeTransaction ( buffer , decodeWith ) ;
533544 }
534545
535546 if ( utxolib . bitgo . isPsbt ( input ) ) {
536- return decodePsbtWith ( input , this . network , 'utxolib' ) ;
547+ return decodePsbtWith ( input , this . network , decodeWith ?? 'utxolib' ) ;
537548 } else {
549+ if ( decodeWith ?? 'utxolib' !== 'utxolib' ) {
550+ console . error ( 'received decodeWith hint %s, ignoring for legacy transaction' , decodeWith ) ;
551+ }
538552 return utxolib . bitgo . createTransactionFromBuffer ( input , this . network , {
539553 amountType : this . amountType ,
540554 } ) ;
541555 }
542556 }
543557
544- decodeTransactionAsPsbt ( input : Buffer | string ) : utxolib . bitgo . UtxoPsbt {
558+ decodeTransactionAsPsbt ( input : Buffer | string ) : utxolib . bitgo . UtxoPsbt | fixedScriptWallet . BitGoPsbt {
545559 const decoded = this . decodeTransaction ( input ) ;
546- if ( ! ( decoded instanceof utxolib . bitgo . UtxoPsbt ) ) {
547- throw new Error ( 'expected psbt but got transaction' ) ;
560+ if ( decoded instanceof fixedScriptWallet . BitGoPsbt || decoded instanceof utxolib . bitgo . UtxoPsbt ) {
561+ return decoded ;
548562 }
549- return decoded ;
563+ throw new Error ( 'expected psbt but got transaction' ) ;
550564 }
551565
552566 decodeTransactionFromPrebuild < TNumber extends number | bigint > ( prebuild : {
553567 txHex ?: string ;
554568 txBase64 ?: string ;
569+ decodeWith ?: string ;
555570 } ) : DecodedTransaction < TNumber > {
556571 const string = prebuild . txHex ?? prebuild . txBase64 ;
557572 if ( ! string ) {
558573 throw new Error ( 'missing required txHex or txBase64 property' ) ;
559574 }
560- return this . decodeTransaction ( string ) ;
575+ let { decodeWith } = prebuild ;
576+ if ( decodeWith !== undefined ) {
577+ if ( typeof decodeWith !== 'string' || ! isSdkBackend ( decodeWith ) ) {
578+ console . error ( 'decodeWith %s is not a valid value, using default' , decodeWith ) ;
579+ decodeWith = undefined ;
580+ }
581+ }
582+ return this . decodeTransaction ( string , decodeWith ) ;
561583 }
562584
563585 toCanonicalTransactionRecipient ( output : { valueString : string ; address ?: string } ) : {
@@ -720,16 +742,29 @@ export abstract class AbstractUtxoCoin extends BaseCoin {
720742
721743 /**
722744 * @returns input psbt added with deterministic MuSig2 nonce for bitgo key for each MuSig2 inputs.
723- * @param psbtHex all MuSig2 inputs should contain user MuSig2 nonce
745+ * @param psbt all MuSig2 inputs should contain user MuSig2 nonce
724746 * @param walletId
725747 */
726- async getMusig2Nonces ( psbt : utxolib . bitgo . UtxoPsbt , walletId : string ) : Promise < utxolib . bitgo . UtxoPsbt > {
727- const params : SignPsbtRequest = { psbt : psbt . toHex ( ) } ;
748+ async getMusig2Nonces ( psbt : utxolib . bitgo . UtxoPsbt , walletId : string ) : Promise < utxolib . bitgo . UtxoPsbt > ;
749+ async getMusig2Nonces ( psbt : fixedScriptWallet . BitGoPsbt , walletId : string ) : Promise < fixedScriptWallet . BitGoPsbt > ;
750+ async getMusig2Nonces < T extends utxolib . bitgo . UtxoPsbt | fixedScriptWallet . BitGoPsbt > (
751+ psbt : T ,
752+ walletId : string
753+ ) : Promise < T > ;
754+ async getMusig2Nonces < T extends utxolib . bitgo . UtxoPsbt | fixedScriptWallet . BitGoPsbt > (
755+ psbt : T ,
756+ walletId : string
757+ ) : Promise < T > {
758+ const buffer = encodeTransaction ( psbt ) ;
728759 const response = await this . bitgo
729760 . post ( this . url ( '/wallet/' + walletId + '/tx/signpsbt' ) )
730- . send ( params )
761+ . send ( { psbt : buffer . toString ( 'hex' ) } )
731762 . result ( ) ;
732- return this . decodeTransactionAsPsbt ( response . psbt ) ;
763+ if ( psbt instanceof utxolib . bitgo . UtxoPsbt ) {
764+ return decodePsbtWith ( response . psbt , this . network , 'utxolib' ) as T ;
765+ } else {
766+ return decodePsbtWith ( response . psbt , this . network , 'wasm-utxo' ) as T ;
767+ }
733768 }
734769
735770 /**
@@ -739,7 +774,8 @@ export abstract class AbstractUtxoCoin extends BaseCoin {
739774 * @param walletId
740775 */
741776 async signPsbt ( psbtHex : string , walletId : string ) : Promise < SignPsbtResponse > {
742- return { psbt : ( await this . getMusig2Nonces ( this . decodeTransactionAsPsbt ( psbtHex ) , walletId ) ) . toHex ( ) } ;
777+ const psbt = await this . getMusig2Nonces ( this . decodeTransactionAsPsbt ( psbtHex ) , walletId ) ;
778+ return { psbt : encodeTransaction ( psbt ) . toString ( 'hex' ) } ;
743779 }
744780
745781 /**
@@ -749,11 +785,10 @@ export abstract class AbstractUtxoCoin extends BaseCoin {
749785 async signPsbtFromOVC ( ovcJson : Record < string , unknown > ) : Promise < Record < string , unknown > > {
750786 assert ( ovcJson [ 'psbtHex' ] , 'ovcJson must contain psbtHex' ) ;
751787 assert ( ovcJson [ 'walletId' ] , 'ovcJson must contain walletId' ) ;
752- const psbt = await this . getMusig2Nonces (
753- this . decodeTransactionAsPsbt ( ovcJson [ 'psbtHex' ] as string ) ,
754- ovcJson [ 'walletId' ] as string
755- ) ;
756- return _ . extend ( ovcJson , { txHex : psbt . toHex ( ) } ) ;
788+ const hex = ovcJson [ 'psbtHex' ] as string ;
789+ const walletId = ovcJson [ 'walletId' ] as string ;
790+ const psbt = await this . getMusig2Nonces ( this . decodeTransactionAsPsbt ( hex ) , walletId ) ;
791+ return _ . extend ( ovcJson , { txHex : encodeTransaction ( psbt ) . toString ( 'hex' ) } ) ;
757792 }
758793
759794 /**
0 commit comments