@@ -40,6 +40,7 @@ import {
4040import { KeyPair as XrpKeyPair } from './lib/keyPair' ;
4141import utils from './lib/utils' ;
4242import ripple from './ripple' ;
43+ import { TokenTransferBuilder , TransactionBuilderFactory , TransferBuilder } from './lib' ;
4344
4445export class Xrp extends BaseCoin {
4546 protected _staticsCoin : Readonly < StaticsBaseCoin > ;
@@ -443,6 +444,7 @@ export class Xrp extends BaseCoin {
443444 const balance = new BigNumber ( addressDetails . body . result . account_data . Balance ) ;
444445 const signerLists = addressDetails . body . result . account_data . signer_lists ;
445446 const accountFlags = addressDetails . body . result . account_data . Flags ;
447+ const ownerCount = new BigNumber ( addressDetails . body . result . account_data . OwnerCount ) ;
446448
447449 // make sure there is only one signer list set
448450 if ( signerLists . length !== 1 ) {
@@ -499,15 +501,13 @@ export class Xrp extends BaseCoin {
499501 }
500502
501503 // recover the funds
502- const reserve = baseReserve . plus ( reserveDelta ) ;
504+ const totalReserveDelta = reserveDelta . times ( ownerCount ) ;
505+ const reserve = baseReserve . plus ( totalReserveDelta ) ;
503506 const recoverableBalance = balance . minus ( reserve ) ;
504507
505508 const rawDestination = params . recoveryDestination ;
506509 const destinationDetails = url . parse ( rawDestination ) ;
507- const destinationAddress = destinationDetails . pathname ;
508510
509- // parse destination tag from query
510- let destinationTag : number | undefined ;
511511 if ( destinationDetails . query ) {
512512 const queryDetails = querystring . parse ( destinationDetails . query ) ;
513513 if ( Array . isArray ( queryDetails . dt ) ) {
@@ -516,11 +516,6 @@ export class Xrp extends BaseCoin {
516516 `destination tag can appear at most once, but ${ queryDetails . dt . length } destination tags were found`
517517 ) ;
518518 }
519-
520- const parsedTag = parseInt ( queryDetails . dt as string , 10 ) ;
521- if ( Number . isInteger ( parsedTag ) ) {
522- destinationTag = parsedTag ;
523- }
524519 }
525520
526521 if ( recoverableBalance . toNumber ( ) <= 0 ) {
@@ -532,38 +527,39 @@ export class Xrp extends BaseCoin {
532527 const tokenName = params ?. tokenName ;
533528 if ( ! ! tokenName ) {
534529 const tokenParams = {
535- destinationAddress,
536- destinationTag,
530+ recoveryDestination : params . recoveryDestination ,
537531 recoverableBalance,
538532 currentLedger,
539533 openLedgerFee,
540534 sequenceId,
541535 accountLines,
542536 keys,
543537 isKrsRecovery,
538+ isUnsignedSweep,
544539 userAddress,
545540 backupAddress,
546541 } ;
547542
548543 return this . recoverXrpToken ( params , tokenName , tokenParams ) ;
549544 }
550545
551- const transaction = {
552- TransactionType : 'Payment' ,
553- Account : params . rootAddress , // source address
554- Destination : destinationAddress ,
555- DestinationTag : destinationTag ,
556- Amount : recoverableBalance . toFixed ( 0 ) ,
557- Flags : 2147483648 ,
558- LastLedgerSequence : currentLedger + 1000000 , // give it 1 million ledgers' time (~1 month, suitable for KRS)
559- Fee : openLedgerFee . times ( 3 ) . toFixed ( 0 ) , // the factor three is for the multisigning
560- Sequence : sequenceId ,
561- } ;
562- const txJSON : string = JSON . stringify ( transaction ) ;
546+ const factory = new TransactionBuilderFactory ( coins . get ( this . getChain ( ) ) ) ;
547+ const txBuilder = factory . getTransferBuilder ( ) as TransferBuilder ;
548+ txBuilder
549+ . to ( params . recoveryDestination as string )
550+ . amount ( recoverableBalance . toFixed ( 0 ) )
551+ . sender ( params . rootAddress )
552+ . flags ( 2147483648 )
553+ . lastLedgerSequence ( currentLedger + 1000000 ) // give it 1 million ledgers' time (~1 month, suitable for KRS)
554+ . fee ( openLedgerFee . times ( 3 ) . toFixed ( 0 ) ) // the factor three is for the multisigning
555+ . sequence ( sequenceId ) ;
556+
557+ const tx = await txBuilder . build ( ) ;
558+ const serializedTx = tx . toBroadcastFormat ( ) ;
563559
564560 if ( isUnsignedSweep ) {
565561 return {
566- txHex : txJSON ,
562+ txHex : serializedTx ,
567563 coin : this . getChain ( ) ,
568564 } ;
569565 }
@@ -572,7 +568,7 @@ export class Xrp extends BaseCoin {
572568 throw new Error ( `userKey is not a private key` ) ;
573569 }
574570 const userKey = keys [ 0 ] . privateKey . toString ( 'hex' ) ;
575- const userSignature = ripple . signWithPrivateKey ( txJSON , userKey , { signAs : userAddress } ) ;
571+ const userSignature = ripple . signWithPrivateKey ( serializedTx , userKey , { signAs : userAddress } ) ;
576572
577573 let signedTransaction : string ;
578574
@@ -583,7 +579,7 @@ export class Xrp extends BaseCoin {
583579 throw new Error ( `backupKey is not a private key` ) ;
584580 }
585581 const backupKey = keys [ 1 ] . privateKey . toString ( 'hex' ) ;
586- const backupSignature = ripple . signWithPrivateKey ( txJSON , backupKey , { signAs : backupAddress } ) ;
582+ const backupSignature = ripple . signWithPrivateKey ( serializedTx , backupKey , { signAs : backupAddress } ) ;
587583 signedTransaction = ripple . multisign ( [ userSignature . signedTransaction , backupSignature . signedTransaction ] ) ;
588584 }
589585
@@ -603,8 +599,6 @@ export class Xrp extends BaseCoin {
603599 public async recoverXrpToken ( params , tokenName , tokenParams ) {
604600 const { currency, issuer } = utils . getXrpCurrencyFromTokenName ( tokenName ) ;
605601
606- // const accountLines = JSON.parse(tokenParams.accountLines);
607- // const lines = accountLines.body.result.lines;
608602 const lines = tokenParams . accountLines . body . result . lines ;
609603
610604 let amount ;
@@ -622,33 +616,40 @@ export class Xrp extends BaseCoin {
622616 throw new Error ( `Does not have funds to recover` ) ;
623617 }
624618
619+ const decimalPlaces = coins . get ( tokenName ) . decimalPlaces ;
620+ amount = new BigNumber ( amount ) . shiftedBy ( decimalPlaces ) . toFixed ( ) ;
621+
625622 const FLAG_VALUE = 2147483648 ;
626623
627- const transaction = {
628- TransactionType : 'Payment' ,
629- Amount : {
630- value : amount ,
631- currency,
632- issuer,
633- } , // source address
634- Destination : tokenParams . destinationAddress ,
635- DestinationTag : tokenParams . destinationTag ,
636- Account : params . rootAddress ,
637- Flags : FLAG_VALUE ,
638- LastLedgerSequence : tokenParams . currentLedger + 1000000 , // give it 1 million ledgers' time (~1 month, suitable for KRS)
639- Fee : tokenParams . openLedgerFee . times ( 3 ) . toFixed ( 0 ) , // the factor three is for the multisigning
640- Sequence : tokenParams . sequenceId ,
641- } ;
642- const txJSON : string = JSON . stringify ( transaction ) ;
624+ const factory = new TransactionBuilderFactory ( coins . get ( tokenName ) ) ;
625+ const txBuilder = factory . getTokenTransferBuilder ( ) as TokenTransferBuilder ;
626+ txBuilder
627+ . to ( tokenParams . recoveryDestination )
628+ . amount ( amount )
629+ . sender ( params . rootAddress )
630+ . flags ( FLAG_VALUE )
631+ . lastLedgerSequence ( tokenParams . currentLedger + 1000000 ) // give it 1 million ledgers' time (~1 month, suitable for KRS)
632+ . fee ( tokenParams . openLedgerFee . times ( 3 ) . toFixed ( 0 ) ) // the factor three is for the multisigning
633+ . sequence ( tokenParams . sequenceId ) ;
634+
635+ const tx = await txBuilder . build ( ) ;
636+ const serializedTx = tx . toBroadcastFormat ( ) ;
643637
644- const { keys, isKrsRecovery, userAddress, backupAddress } = tokenParams ;
638+ const { keys, isKrsRecovery, isUnsignedSweep, userAddress, backupAddress } = tokenParams ;
639+
640+ if ( isUnsignedSweep ) {
641+ return {
642+ txHex : serializedTx ,
643+ coin : this . getChain ( ) ,
644+ } ;
645+ }
645646
646647 if ( ! keys [ 0 ] . privateKey ) {
647648 throw new Error ( `userKey is not a private key` ) ;
648649 }
649650
650651 const userKey = keys [ 0 ] . privateKey . toString ( 'hex' ) ;
651- const userSignature = ripple . signWithPrivateKey ( txJSON , userKey , { signAs : userAddress } ) ;
652+ const userSignature = ripple . signWithPrivateKey ( serializedTx , userKey , { signAs : userAddress } ) ;
652653
653654 let signedTransaction : string ;
654655
@@ -659,7 +660,7 @@ export class Xrp extends BaseCoin {
659660 throw new Error ( `backupKey is not a private key` ) ;
660661 }
661662 const backupKey = keys [ 1 ] . privateKey . toString ( 'hex' ) ;
662- const backupSignature = ripple . signWithPrivateKey ( txJSON , backupKey , { signAs : backupAddress } ) ;
663+ const backupSignature = ripple . signWithPrivateKey ( serializedTx , backupKey , { signAs : backupAddress } ) ;
663664 signedTransaction = ripple . multisign ( [ userSignature . signedTransaction , backupSignature . signedTransaction ] ) ;
664665 }
665666
0 commit comments