11import { SignFinalOptions } from '@bitgo/abstract-eth' ;
2- import { HalfSignedUtxoTransaction , MethodNotImplementedError } from 'bitgo' ;
2+ import { AbstractUtxoCoin } from '@bitgo/abstract-utxo' ;
3+ import { HalfSignedUtxoTransaction , MethodNotImplementedError , TransactionRecipient } from 'bitgo' ;
34import { EnclavedApiSpecRouteRequest } from '../../../enclavedBitgoExpress/routers/enclavedApiSpec' ;
5+ import { EnvironmentName } from '../../../initConfig' ;
46import logger from '../../../logger' ;
57import {
68 isEthLikeCoin ,
@@ -9,12 +11,11 @@ import {
911} from '../../../shared/coinUtils' ;
1012import {
1113 addEthLikeRecoveryExtras ,
12- getDefaultMusigEthGasParams ,
14+ DEFAULT_MUSIG_ETH_GAS_PARAMS ,
1315 getReplayProtectionOptions ,
1416} from '../../../shared/recoveryUtils' ;
1517import { SignedEthLikeRecoveryTx } from '../../../types/transaction' ;
1618import { retrieveKmsPrvKey } from '../utils' ;
17- import { AbstractUtxoCoin } from '@bitgo/abstract-utxo' ;
1819
1920export async function recoveryMultisigTransaction (
2021 req : EnclavedApiSpecRouteRequest < 'v1.multisig.recovery' , 'post' > ,
@@ -43,9 +44,13 @@ export async function recoveryMultisigTransaction(
4344 const walletKeys = unsignedSweepPrebuildTx . xpubxWithDerivationPath ;
4445 const pubs = [ walletKeys ?. user ?. xpub , walletKeys ?. backup ?. xpub , walletKeys ?. bitgo ?. xpub ] ;
4546 const { gasPrice, gasLimit, maxFeePerGas, maxPriorityFeePerGas } =
46- getDefaultMusigEthGasParams ( ) ;
47+ DEFAULT_MUSIG_ETH_GAS_PARAMS ;
4748
4849 try {
50+ checkIfNoRecipients ( {
51+ recipients : unsignedSweepPrebuildTx . recipients ,
52+ coin : req . decoded . coin ,
53+ } ) ;
4954 const halfSignedTxBase = await baseCoin . signTransaction ( {
5055 isLastSignature : false ,
5156 prv : userPrv ,
@@ -61,6 +66,7 @@ export async function recoveryMultisigTransaction(
6166 maxPriorityFeePerGas,
6267 } ,
6368 replayProtectionOptions : getReplayProtectionOptions (
69+ bitgo . env as EnvironmentName ,
6470 unsignedSweepPrebuildTx . replayProtectionOptions ,
6571 ) ,
6672 txPrebuild : {
@@ -72,13 +78,15 @@ export async function recoveryMultisigTransaction(
7278 maxPriorityFeePerGas,
7379 } ,
7480 replayProtectionOptions : getReplayProtectionOptions (
81+ bitgo . env as EnvironmentName ,
7582 unsignedSweepPrebuildTx . replayProtectionOptions ,
7683 ) ,
7784 } ,
7885 walletContractAddress,
7986 } ) ;
8087
8188 const halfSignedTx = addEthLikeRecoveryExtras ( {
89+ env : bitgo . env as EnvironmentName ,
8290 signedTx : halfSignedTxBase as SignedEthLikeRecoveryTx ,
8391 transaction : unsignedSweepPrebuildTx ,
8492 isLastSignature : false ,
@@ -108,6 +116,7 @@ export async function recoveryMultisigTransaction(
108116 maxPriorityFeePerGas,
109117 } ,
110118 replayProtectionOptions : getReplayProtectionOptions (
119+ bitgo . env as EnvironmentName ,
111120 halfSignedTx ?. replayProtectionOptions ,
112121 ) ,
113122 } as unknown as SignFinalOptions ,
@@ -159,3 +168,17 @@ export async function recoveryMultisigTransaction(
159168 throw new MethodNotImplementedError ( 'Unsupported coin type for recovery: ' + baseCoin ) ;
160169 }
161170}
171+
172+ function checkIfNoRecipients ( {
173+ recipients,
174+ coin,
175+ } : {
176+ recipients ?: TransactionRecipient [ ] ;
177+ coin : string ;
178+ } ) {
179+ if ( ! recipients || recipients . length === 0 ) {
180+ const errorMsg = `Recovery tx for coin ${ coin } must have at least one recipient.` ;
181+ logger . error ( errorMsg ) ;
182+ throw new Error ( errorMsg ) ;
183+ }
184+ }
0 commit comments