11import { MasterApiSpecRouteRequest } from '../routers/masterApiSpec' ;
22import logger from '../../../logger' ;
3- import { isSolCoin } from '../../../shared/coinUtils' ;
4- import { MPCTx } from 'bitgo' ;
3+ import { BaseCoin , MPCConsolidationRecoveryOptions , MPCTx , RecoveryTxRequest } from 'bitgo' ;
54import { RecoveryTransaction } from '@bitgo/sdk-coin-trx' ;
5+ import { BitGoBase } from '@bitgo/sdk-core' ;
6+ import { CoinFamily } from '@bitgo/statics' ;
7+ import type { Sol , SolConsolidationRecoveryOptions , Tsol } from '@bitgo/sdk-coin-sol' ;
8+ import type { Trx , ConsolidationRecoveryOptions , Ttrx } from '@bitgo/sdk-coin-trx' ;
9+ import type { Sui , Tsui } from '@bitgo/sdk-coin-sui' ;
10+ import type { Ada , Tada } from '@bitgo/sdk-coin-ada' ;
11+ import type { Dot , Tdot } from '@bitgo/sdk-coin-dot' ;
12+ import type { Tao , Ttao } from '@bitgo/sdk-coin-tao' ;
13+
14+ type RecoveryConsolidationParams =
15+ | ConsolidationRecoveryOptions
16+ | SolConsolidationRecoveryOptions
17+ | MPCConsolidationRecoveryOptions ;
18+
19+ type RecoveryConsolidationResult = {
20+ transactions ?: ( RecoveryTransaction | MPCTx ) [ ] ;
21+ txRequests ?: RecoveryTxRequest [ ] ;
22+ } ;
23+
24+ export async function recoveryConsolidateWallets (
25+ sdk : BitGoBase ,
26+ baseCoin : BaseCoin ,
27+ params : RecoveryConsolidationParams ,
28+ ) : Promise < RecoveryConsolidationResult > {
29+ const family = baseCoin . getFamily ( ) ;
30+
31+ switch ( family ) {
32+ case CoinFamily . SOL : {
33+ const { register } = await import ( '@bitgo/sdk-coin-sol' ) ;
34+ register ( sdk ) ;
35+ const solCoin = baseCoin as unknown as Sol | Tsol ;
36+ return await solCoin . recoverConsolidations ( params as SolConsolidationRecoveryOptions ) ;
37+ }
38+ case CoinFamily . TRX : {
39+ const { register } = await import ( '@bitgo/sdk-coin-trx' ) ;
40+ register ( sdk ) ;
41+ const trxCoin = baseCoin as unknown as Trx | Ttrx ;
42+ return await trxCoin . recoverConsolidations ( params as ConsolidationRecoveryOptions ) ;
43+ }
44+ default : {
45+ const [
46+ { register : registerSui } ,
47+ { register : registerAda } ,
48+ { register : registerDot } ,
49+ { register : registerTao } ,
50+ ] = await Promise . all ( [
51+ import ( '@bitgo/sdk-coin-sui' ) ,
52+ import ( '@bitgo/sdk-coin-ada' ) ,
53+ import ( '@bitgo/sdk-coin-dot' ) ,
54+ import ( '@bitgo/sdk-coin-tao' ) ,
55+ ] ) ;
56+ registerAda ( sdk ) ;
57+ registerSui ( sdk ) ;
58+ registerDot ( sdk ) ;
59+ registerTao ( sdk ) ;
60+ const coin = baseCoin as unknown as Sui | Tsui | Ada | Tada | Dot | Tdot | Tao | Ttao ;
61+ return await coin . recoverConsolidations ( params as MPCConsolidationRecoveryOptions ) ;
62+ }
63+ }
64+ }
665
766// Handler for recovery from receive addresses (consolidation sweeps)
867export async function handleRecoveryConsolidationsOnPrem (
@@ -12,48 +71,67 @@ export async function handleRecoveryConsolidationsOnPrem(
1271 const coin = req . decoded . coin ;
1372 const enclavedExpressClient = req . enclavedExpressClient ;
1473
15- const { userPub , backupPub , bitgoKey } = req . decoded ;
74+ const isMPC = true ;
1675
17- const sdkCoin = bitgo . coin ( coin ) ;
18- let txs : MPCTx [ ] | RecoveryTransaction [ ] = [ ] ;
19- // 1. Build unsigned consolidations
20- if ( isSolCoin ( sdkCoin ) && ! req . decoded . durableNonces ) {
21- throw new Error ( 'durableNonces is required for Solana consolidation recovery' ) ;
76+ const { commonKeychain, apiKey } = req . decoded ;
77+ let { userPub, backupPub, bitgoPub } = req . decoded ;
78+
79+ if ( isMPC ) {
80+ if ( ! commonKeychain ) {
81+ throw new Error ( 'Missing required key: commonKeychain' ) ;
82+ }
83+
84+ userPub = commonKeychain ;
85+ backupPub = commonKeychain ;
86+ bitgoPub = commonKeychain ;
2287 }
2388
24- if ( typeof ( sdkCoin as any ) . recoverConsolidations !== 'function' ) {
25- throw new Error ( `recoverConsolidations is not supported for coin: ${ coin } ` ) ;
89+ if ( ! userPub || ! backupPub || ! bitgoPub ) {
90+ throw new Error ( 'Missing required keys: userPub, backupPub, bitgoPub' ) ;
2691 }
2792
93+ const sdkCoin = bitgo . coin ( coin ) ;
94+ let txs : ( RecoveryTransaction | MPCTx | RecoveryTxRequest ) [ ] = [ ] ;
95+
2896 // Use type assertion to access recoverConsolidations
29- const result = await ( sdkCoin as any ) . recoverConsolidations ( {
97+ const result = await recoveryConsolidateWallets ( bitgo , sdkCoin , {
3098 ...req . decoded ,
31- userKey : userPub ,
32- backupKey : backupPub ,
33- bitgoKey,
34- durableNonces : req . decoded . durableNonces ,
99+ userKey : ! isMPC ? userPub : '' ,
100+ backupKey : ! isMPC ? backupPub : '' ,
101+ bitgoKey : bitgoPub ,
35102 } ) ;
36103
37- if ( 'transactions' in result ) {
104+ console . log ( `Recovery consolidations result: ${ JSON . stringify ( result ) } ` ) ;
105+
106+ if ( result . transactions ) {
38107 txs = result . transactions ;
39- } else if ( 'txRequests' in result ) {
108+ } else if ( result . txRequests ) {
40109 txs = result . txRequests ;
41110 } else {
42111 throw new Error ( 'recoverConsolidations did not return expected transactions' ) ;
43112 }
44113
45114 logger . debug ( `Found ${ txs . length } unsigned consolidation transactions` ) ;
46115
47- // 2. For each unsigned sweep, get it signed by EBE (using recoveryMultisig)
48116 const signedTxs = [ ] ;
49117 try {
50118 for ( const tx of txs ) {
51- const signedTx = await enclavedExpressClient . recoveryMultisig ( {
52- userPub,
53- backupPub,
54- unsignedSweepPrebuildTx : tx ,
55- walletContractAddress : '' ,
56- } ) ;
119+ const signedTx = isMPC
120+ ? await enclavedExpressClient . recoveryMPC ( {
121+ userPub,
122+ backupPub,
123+ apiKey,
124+ unsignedSweepPrebuildTx : tx as MPCTx | RecoveryTxRequest ,
125+ coinSpecificParams : { } ,
126+ walletContractAddress : '' ,
127+ } )
128+ : await enclavedExpressClient . recoveryMultisig ( {
129+ userPub,
130+ backupPub,
131+ unsignedSweepPrebuildTx : tx as RecoveryTransaction ,
132+ walletContractAddress : '' ,
133+ } ) ;
134+
57135 signedTxs . push ( signedTx ) ;
58136 }
59137
0 commit comments