44 type EdgeCurrencyWallet ,
55 type EdgeMemoryWallet ,
66 type EdgeSpendInfo ,
7+ type EdgeTokenId ,
78 type EdgeTransaction ,
89 InsufficientFundsError
910} from 'edge-core-js'
@@ -29,6 +30,7 @@ import { CreateWalletSelectCryptoRow } from '../themed/CreateWalletSelectCryptoR
2930import { EdgeText } from '../themed/EdgeText'
3031import { SafeSlider } from '../themed/SafeSlider'
3132import { SceneHeader } from '../themed/SceneHeader'
33+ import type { SweepPrivateKeyCompletionParams } from './SweepPrivateKeyCompletionScene'
3234import type { SweepPrivateKeyItem } from './SweepPrivateKeyProcessingScene'
3335
3436export interface SweepPrivateKeyCalculateFeeParams {
@@ -38,8 +40,13 @@ export interface SweepPrivateKeyCalculateFeeParams {
3840}
3941
4042type Props = EdgeAppSceneProps < 'sweepPrivateKeyCalculateFee' >
43+ type AssetTxState = EdgeTransaction | Error | 'included'
44+ type MakeMaxSpendMethod = ( params : {
45+ tokenIds ?: EdgeTokenId [ ]
46+ spendTargets : Array < { publicAddress : string } >
47+ } ) => Promise < EdgeTransaction >
4148
42- const SweepPrivateKeyCalculateFeeComponent = ( props : Props ) => {
49+ const SweepPrivateKeyCalculateFeeComponent : React . FC < Props > = props => {
4350 const { navigation, route } = props
4451 const { memoryWallet, receivingWallet, sweepPrivateKeyList } = route . params
4552
@@ -66,7 +73,7 @@ const SweepPrivateKeyCalculateFeeComponent = (props: Props) => {
6673 const mounted = React . useRef < boolean > ( true )
6774
6875 const [ transactionState , setTransactionState ] = React . useState <
69- Map < string , EdgeTransaction | Error >
76+ Map < string , AssetTxState >
7077 > ( new Map ( ) )
7178 const [ sliderDisabled , setSliderDisabled ] = React . useState ( true )
7279
@@ -111,6 +118,14 @@ const SweepPrivateKeyCalculateFeeComponent = (props: Props) => {
111118 />
112119 )
113120 }
121+ } else if ( tx === 'included' ) {
122+ rightSide = (
123+ < EdgeText
124+ style = { { color : theme . secondaryText , fontSize : theme . rem ( 0.75 ) } }
125+ >
126+ { lstrings . string_included }
127+ </ EdgeText >
128+ )
114129 } else {
115130 const exchangeDenom = getExchangeDenom (
116131 receivingWallet . currencyConfig ,
@@ -170,22 +185,26 @@ const SweepPrivateKeyCalculateFeeComponent = (props: Props) => {
170185 const unsignedEdgeTransactions : EdgeTransaction [ ] = [ ]
171186 for ( const item of sweepPrivateKeyList ) {
172187 const tx = transactionState . get ( item . key )
173- if ( tx == null || tx instanceof Error ) continue
188+ if ( tx == null || tx instanceof Error || tx === 'included' ) continue
174189 unsignedEdgeTransactions . push ( tx )
175190 }
176- navigation . push ( 'sweepPrivateKeyCompletion' , {
191+ const hasIncludedAssets = sweepPrivateKeyList . some (
192+ item => transactionState . get ( item . key ) === 'included'
193+ )
194+ const completionParams : SweepPrivateKeyCompletionParams = {
177195 memoryWallet,
178196 receivingWallet,
179- unsignedEdgeTransactions
180- } )
197+ sweepPrivateKeyList,
198+ unsignedEdgeTransactions,
199+ hasIncludedAssets
200+ }
201+ navigation . push ( 'sweepPrivateKeyCompletion' , completionParams )
181202 } )
182203
183204 // Create getMaxSpendable/makeSpend promises for each selected asset. We'll group them by wallet first and then execute all of them while keeping
184205 // track of which makeSpends are successful so we can enable the slider. A single failure from any of a wallet's assets will cast them all as failures.
185206 useAsyncEffect (
186207 async ( ) => {
187- let feeTotal = '0'
188-
189208 const tokenItems = [ ...sweepPrivateKeyList ]
190209 const mainnetItem = tokenItems . splice (
191210 sweepPrivateKeyList . length - 1 ,
@@ -195,90 +214,124 @@ const SweepPrivateKeyCalculateFeeComponent = (props: Props) => {
195214 await receivingWallet . getReceiveAddress ( { tokenId : null } )
196215 ) . publicAddress
197216 let enableSlider = false
198-
199- const getMax = async (
200- asset : SweepPrivateKeyItem ,
201- numPendingTxs : number
202- ) => {
203- const fakeEdgeTransaction : EdgeTransaction = {
204- blockHeight : 0 ,
205- currencyCode : '' ,
206- date : 0 ,
207- memos : [ ] ,
208- isSend : true ,
209- nativeAmount : '0' ,
210- networkFee : '0' ,
211- networkFees : [ ] ,
212- ourReceiveAddresses : [ ] ,
213- signedTx : '' ,
214- tokenId : null ,
215- txid : '' ,
216- walletId : ''
217- }
218-
219- const spendInfo : EdgeSpendInfo = {
220- tokenId : asset . tokenId ,
221- spendTargets : [ { publicAddress } ] ,
222- networkFeeOption : 'standard' ,
223- pendingTxs : Array . from (
224- { length : numPendingTxs } ,
225- ( ) => fakeEdgeTransaction
226- )
227- }
228-
217+ if (
218+ ( ( memoryWallet as any ) . otherMethods ?. makeMaxSpend as
219+ | MakeMaxSpendMethod
220+ | undefined ) != null
221+ ) {
229222 try {
230- const maxAmount = await memoryWallet . getMaxSpendable ( spendInfo )
231- if ( maxAmount === '0' ) {
232- throw new InsufficientFundsError ( { tokenId : asset . tokenId } )
233- }
234- let nativeAmount = maxAmount
235- if ( asset . tokenId === null ) {
236- nativeAmount = sub ( nativeAmount , feeTotal )
237- }
238- const maxSpendInfo = {
239- ...spendInfo ,
240- spendTargets : [ { publicAddress, nativeAmount } ]
241- }
242- const edgeTransaction = await memoryWallet . makeSpend ( maxSpendInfo )
243- const txFee =
244- edgeTransaction . parentNetworkFee ?? edgeTransaction . networkFee
223+ const tokenIds = sweepPrivateKeyList . map ( item => item . tokenId )
224+ const edgeTransaction = await (
225+ ( memoryWallet as any ) . otherMethods
226+ . makeMaxSpend as MakeMaxSpendMethod
227+ ) ( {
228+ tokenIds,
229+ spendTargets : [ { publicAddress } ]
230+ } )
245231 setTransactionState (
246- prevState => new Map ( [ ...prevState , [ asset . key , edgeTransaction ] ] )
232+ new Map (
233+ sweepPrivateKeyList . map ( item => [
234+ item . key ,
235+ item . tokenId == null ? edgeTransaction : 'included'
236+ ] )
237+ )
247238 )
248- feeTotal = add ( feeTotal , txFee )
249- // While imperfect, sanity check that the total fee spent so far to send tokens + fee to send mainnet currency is under the total mainnet balance
250- if ( lt ( memoryWallet . balanceMap . get ( null ) ?? '0' , feeTotal ) ) {
251- throw new InsufficientFundsError ( {
252- tokenId : null ,
253- networkFee : feeTotal
254- } )
255- }
256239 enableSlider = true
257240 } catch ( e ) {
258241 const insufficientFundsError = asMaybeInsufficientFundsError ( e )
259- if ( insufficientFundsError != null ) {
260- setTransactionState (
261- prevState =>
262- new Map ( [ ...prevState , [ asset . key , insufficientFundsError ] ] )
242+ const error =
243+ insufficientFundsError ??
244+ Error ( lstrings . migrate_unknown_error_fragment )
245+ setTransactionState (
246+ new Map ( sweepPrivateKeyList . map ( item => [ item . key , error ] ) )
247+ )
248+ }
249+ } else {
250+ let feeTotal = '0'
251+ const getMax = async (
252+ asset : SweepPrivateKeyItem ,
253+ numPendingTxs : number
254+ ) : Promise < void > => {
255+ const fakeEdgeTransaction : EdgeTransaction = {
256+ blockHeight : 0 ,
257+ currencyCode : '' ,
258+ date : 0 ,
259+ memos : [ ] ,
260+ isSend : true ,
261+ nativeAmount : '0' ,
262+ networkFee : '0' ,
263+ networkFees : [ ] ,
264+ ourReceiveAddresses : [ ] ,
265+ signedTx : '' ,
266+ tokenId : null ,
267+ txid : '' ,
268+ walletId : ''
269+ }
270+
271+ const spendInfo : EdgeSpendInfo = {
272+ tokenId : asset . tokenId ,
273+ spendTargets : [ { publicAddress } ] ,
274+ networkFeeOption : 'standard' ,
275+ pendingTxs : Array . from (
276+ { length : numPendingTxs } ,
277+ ( ) => fakeEdgeTransaction
263278 )
264- } else {
279+ }
280+
281+ try {
282+ const maxAmount = await memoryWallet . getMaxSpendable ( spendInfo )
283+ if ( maxAmount === '0' ) {
284+ throw new InsufficientFundsError ( { tokenId : asset . tokenId } )
285+ }
286+ let nativeAmount = maxAmount
287+ if ( asset . tokenId === null ) {
288+ nativeAmount = sub ( nativeAmount , feeTotal )
289+ }
290+ const maxSpendInfo = {
291+ ...spendInfo ,
292+ spendTargets : [ { publicAddress, nativeAmount } ]
293+ }
294+ const edgeTransaction = await memoryWallet . makeSpend ( maxSpendInfo )
295+ const txFee =
296+ edgeTransaction . parentNetworkFee ?? edgeTransaction . networkFee
265297 setTransactionState (
266- prevState =>
267- new Map ( [
268- ...prevState ,
269- [ asset . key , Error ( lstrings . migrate_unknown_error_fragment ) ]
270- ] )
298+ prevState => new Map ( [ ...prevState , [ asset . key , edgeTransaction ] ] )
271299 )
300+ feeTotal = add ( feeTotal , txFee )
301+ // While imperfect, sanity check that the total fee spent so far to send tokens + fee to send mainnet currency is under the total mainnet balance
302+ if ( lt ( memoryWallet . balanceMap . get ( null ) ?? '0' , feeTotal ) ) {
303+ throw new InsufficientFundsError ( {
304+ tokenId : null ,
305+ networkFee : feeTotal
306+ } )
307+ }
308+ enableSlider = true
309+ } catch ( e ) {
310+ const insufficientFundsError = asMaybeInsufficientFundsError ( e )
311+ if ( insufficientFundsError != null ) {
312+ setTransactionState (
313+ prevState =>
314+ new Map ( [ ...prevState , [ asset . key , insufficientFundsError ] ] )
315+ )
316+ } else {
317+ setTransactionState (
318+ prevState =>
319+ new Map ( [
320+ ...prevState ,
321+ [ asset . key , Error ( lstrings . migrate_unknown_error_fragment ) ]
322+ ] )
323+ )
324+ }
272325 }
273326 }
274- }
275327
276- await Promise . all (
277- tokenItems . map ( async ( item , index ) => {
278- await getMax ( item , index )
279- } )
280- )
281- await getMax ( mainnetItem , tokenItems . length )
328+ await Promise . all (
329+ tokenItems . map ( async ( item , index ) => {
330+ await getMax ( item , index )
331+ } )
332+ )
333+ await getMax ( mainnetItem , tokenItems . length )
334+ }
282335
283336 if ( enableSlider && mounted . current ) {
284337 setSliderDisabled ( false )
0 commit comments