Skip to content

Commit 0123e85

Browse files
committed
fix(sdk-coin-xrp): support recovery using issuer address and currency code
TICKET: WIN-3813
1 parent 31e4aeb commit 0123e85

File tree

4 files changed

+40
-11
lines changed

4 files changed

+40
-11
lines changed

modules/sdk-coin-xrp/src/lib/iface.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ export interface RecoveryOptions {
6767
bitgoKey?: string;
6868
walletPassphrase: string;
6969
krsProvider?: string;
70-
tokenName?: string;
70+
issuerAddress?: string;
71+
currencyCode?: string;
7172
}
7273

7374
export interface HalfSignedTransaction {

modules/sdk-coin-xrp/src/lib/utils.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
UnsupportedTokenError,
66
UtilsError,
77
} from '@bitgo/sdk-core';
8-
import { coins, XrpCoin } from '@bitgo/statics';
8+
import { BaseCoin, coins, XrpCoin } from '@bitgo/statics';
99
import * as querystring from 'querystring';
1010
import * as rippleKeypairs from 'ripple-keypairs';
1111
import * as url from 'url';
@@ -14,6 +14,7 @@ import { Amount, IssuedCurrencyAmount } from 'xrpl';
1414
import { VALID_ACCOUNT_SET_FLAGS } from './constants';
1515
import { Address, SignerDetails } from './iface';
1616
import { KeyPair as XrpKeyPair } from './keyPair';
17+
import assert from 'assert';
1718

1819
class Utils implements BaseUtils {
1920
isValidAddress(address: string): boolean {
@@ -267,6 +268,29 @@ class Utils implements BaseUtils {
267268
throw new Error(`Failed to decode transaction: ${error.message}`);
268269
}
269270
}
271+
272+
/**
273+
* Get the statics coin object matching a given Xrp token issuer address and currency code if it exists
274+
*
275+
* @param issuerAddress The token issuer address to match against
276+
* @param currencyCode The token currency code to match against
277+
* @returns statics BaseCoin object for the matching token
278+
*/
279+
public getXrpToken(issuerAddress, currencyCode): Readonly<BaseCoin> | undefined {
280+
const tokens = coins.filter((coin) => {
281+
if (coin instanceof XrpCoin) {
282+
return coin.issuerAddress === issuerAddress && coin.currencyCode === currencyCode;
283+
}
284+
return false;
285+
});
286+
const tokensArray = tokens.map((token) => token);
287+
if (tokensArray.length >= 1) {
288+
// there should never be two tokens with the same issuer address and currency code, so we assert that here
289+
assert(tokensArray.length === 1);
290+
return tokensArray[0];
291+
}
292+
return undefined;
293+
}
270294
}
271295

272296
const utils = new Utils();

modules/sdk-coin-xrp/src/xrp.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -524,8 +524,9 @@ export class Xrp extends BaseCoin {
524524
);
525525
}
526526

527-
const tokenName = params?.tokenName;
528-
if (!!tokenName) {
527+
const issuer = params?.issuerAddress;
528+
const currency = params?.currencyCode;
529+
if (!!issuer && !!currency) {
529530
const tokenParams = {
530531
recoveryDestination: params.recoveryDestination,
531532
recoverableBalance,
@@ -538,9 +539,11 @@ export class Xrp extends BaseCoin {
538539
isUnsignedSweep,
539540
userAddress,
540541
backupAddress,
542+
issuer,
543+
currency,
541544
};
542545

543-
return this.recoverXrpToken(params, tokenName, tokenParams);
546+
return this.recoverXrpToken(params, tokenParams);
544547
}
545548

546549
const factory = new TransactionBuilderFactory(coins.get(this.getChain()));
@@ -596,9 +599,9 @@ export class Xrp extends BaseCoin {
596599
return transactionExplanation;
597600
}
598601

599-
public async recoverXrpToken(params, tokenName, tokenParams) {
600-
const { currency, issuer } = utils.getXrpCurrencyFromTokenName(tokenName);
601-
602+
public async recoverXrpToken(params, tokenParams) {
603+
const { currency, issuer } = tokenParams;
604+
const tokenName = (utils.getXrpToken(issuer, currency) as XrpCoin).name;
602605
const lines = tokenParams.accountLines.body.result.lines;
603606

604607
let amount;

modules/sdk-coin-xrp/test/unit/xrp.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,6 @@ describe('XRP:', function () {
230230

231231
describe('Recover Token Transactions', () => {
232232
const sandBox = sinon.createSandbox();
233-
const tokenName = 'txrp:rlusd';
234233
const destination = 'raBSn6ipeWXYe7rNbNafZSx9dV2fU3zRyP?dt=12345';
235234
const passPhrase = '#Bondiola1234';
236235
let xrplStub;
@@ -286,7 +285,8 @@ describe('XRP:', function () {
286285
rootAddress: testData.keys.rootAddress,
287286
recoveryDestination: destination,
288287
walletPassphrase: passPhrase,
289-
tokenName: tokenName,
288+
issuerAddress: 'rQhWct2fv4Vc4KRjRgMrxa8xPN9Zx9iLKV',
289+
currencyCode: '524C555344000000000000000000000000000000',
290290
});
291291

292292
res.should.not.be.empty();
@@ -351,7 +351,8 @@ describe('XRP:', function () {
351351
rootAddress: 'raGZWRkRBUWdQJsKYEzwXJNbCZMTqX56aA',
352352
recoveryDestination: destination,
353353
walletPassphrase: TestBitGo.V2.TEST_WALLET1_PASSCODE,
354-
tokenName: tokenName,
354+
issuerAddress: 'rQhWct2fv4Vc4KRjRgMrxa8xPN9Zx9iLKV',
355+
currencyCode: '524C555344000000000000000000000000000000',
355356
});
356357

357358
res.should.not.be.empty();

0 commit comments

Comments
 (0)