Skip to content

Commit 59337c2

Browse files
Merge pull request #4947 from BitGo/WIN-3541
build(sdk-coin-xrp): update ripple libs
2 parents 8cc0427 + be7b887 commit 59337c2

File tree

5 files changed

+141
-254
lines changed

5 files changed

+141
-254
lines changed

modules/sdk-coin-xrp/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@
4444
"@bitgo/utxo-lib": "^10.3.0",
4545
"bignumber.js": "^9.0.0",
4646
"lodash": "^4.17.14",
47-
"ripple-address-codec": "~4.1.3",
48-
"ripple-binary-codec": "~0.2.4",
49-
"ripple-keypairs": "^0.11.0",
50-
"ripple-lib": "~1.4.1"
47+
"ripple-address-codec": "^5.0.0",
48+
"ripple-binary-codec": "^2.1.0",
49+
"ripple-keypairs": "^2.0.0",
50+
"xrpl": "^4.0.0"
5151
},
5252
"devDependencies": {
5353
"@bitgo/sdk-api": "^1.54.3",

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

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
/**
66
*/
77
import * as rippleKeypairs from 'ripple-keypairs';
8-
import * as ripple from 'ripple-lib';
8+
import * as xrpl from 'xrpl';
99
import { ECPair } from '@bitgo/utxo-lib';
1010

1111
import * as binary from 'ripple-binary-codec';
12-
import { computeBinaryTransactionHash } from 'ripple-lib/dist/npm/common/hashes';
1312

1413
function computeSignature(tx, privateKey, signAs) {
1514
const signingData = signAs ? binary.encodeForMultisigning(tx, signAs) : binary.encodeForSigning(tx);
@@ -67,12 +66,8 @@ const signWithPrivateKey = function (txHex, privateKey, options) {
6766
const serialized = binary.encode(tx);
6867
return {
6968
signedTransaction: serialized,
70-
id: computeBinaryTransactionHash(serialized),
69+
id: xrpl.hashes.hashSignedTx(serialized),
7170
};
7271
};
7372

74-
export = (params): ripple.RippleAPI => {
75-
const rippleLib = new ripple.RippleAPI(params);
76-
(rippleLib as any).signWithPrivateKey = signWithPrivateKey;
77-
return rippleLib;
78-
};
73+
export = { ...xrpl, signWithPrivateKey };

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

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import * as _ from 'lodash';
88
import * as url from 'url';
99
import * as querystring from 'querystring';
1010

11+
import * as xrpl from 'xrpl';
1112
import * as rippleAddressCodec from 'ripple-address-codec';
1213
import * as rippleBinaryCodec from 'ripple-binary-codec';
13-
import { computeBinaryTransactionHash } from 'ripple-lib/dist/npm/common/hashes';
1414
import * as rippleKeypairs from 'ripple-keypairs';
1515
import {
1616
BaseCoin,
@@ -31,7 +31,7 @@ import {
3131
VerifyTransactionOptions,
3232
} from '@bitgo/sdk-core';
3333

34-
const ripple = require('./ripple');
34+
import ripple from './ripple';
3535

3636
interface Address {
3737
address: string;
@@ -262,9 +262,7 @@ export class Xrp extends BaseCoin {
262262
}
263263
const userAddress = rippleKeypairs.deriveAddress(userKey.publicKey.toString('hex'));
264264

265-
const rippleLib = ripple();
266-
267-
const tx = rippleLib.signWithPrivateKey(txPrebuild.txHex, userPrivateKey.toString('hex'), {
265+
const tx = ripple.signWithPrivateKey(txPrebuild.txHex, userPrivateKey.toString('hex'), {
268266
signAs: userAddress,
269267
});
270268

@@ -319,7 +317,14 @@ export class Xrp extends BaseCoin {
319317
throw new Error('txHex needs to be either hex or JSON string for XRP');
320318
}
321319
}
322-
const id = computeBinaryTransactionHash(txHex as string);
320+
let id: string;
321+
// hashes ids are different for signed and unsigned tx
322+
// first we try to get the hash id as if it is signed, will throw if its not
323+
try {
324+
id = xrpl.hashes.hashSignedTx(txHex);
325+
} catch (e) {
326+
id = xrpl.hashes.hashTx(txHex);
327+
}
323328

324329
if (transaction.TransactionType == 'AccountSet') {
325330
return {
@@ -587,30 +592,31 @@ export class Xrp extends BaseCoin {
587592
coin: this.getChain(),
588593
};
589594
}
590-
const rippleLib = ripple();
595+
591596
if (!keys[0].privateKey) {
592597
throw new Error(`userKey is not a private key`);
593598
}
594599
const userKey = keys[0].privateKey.toString('hex');
595-
const userSignature = rippleLib.signWithPrivateKey(txJSON, userKey, { signAs: userAddress });
600+
const userSignature = ripple.signWithPrivateKey(txJSON, userKey, { signAs: userAddress });
596601

597-
let signedTransaction;
602+
let signedTransaction: string;
598603

599604
if (isKrsRecovery) {
600-
signedTransaction = userSignature;
605+
signedTransaction = userSignature.signedTransaction;
601606
} else {
602607
if (!keys[1].privateKey) {
603608
throw new Error(`backupKey is not a private key`);
604609
}
605610
const backupKey = keys[1].privateKey.toString('hex');
606-
const backupSignature = rippleLib.signWithPrivateKey(txJSON, backupKey, { signAs: backupAddress });
607-
signedTransaction = rippleLib.combine([userSignature.signedTransaction, backupSignature.signedTransaction]);
611+
const backupSignature = ripple.signWithPrivateKey(txJSON, backupKey, { signAs: backupAddress });
612+
signedTransaction = ripple.multisign([userSignature.signedTransaction, backupSignature.signedTransaction]);
608613
}
609614

610615
const transactionExplanation: RecoveryInfo = (await this.explainTransaction({
611-
txHex: signedTransaction.signedTransaction,
616+
txHex: signedTransaction,
612617
})) as any;
613-
transactionExplanation.txHex = signedTransaction.signedTransaction;
618+
619+
transactionExplanation.txHex = signedTransaction;
614620

615621
if (isKrsRecovery) {
616622
transactionExplanation.backupKey = params.backupKey;

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

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import 'should';
33
import { TestBitGo, TestBitGoAPI } from '@bitgo/sdk-test';
44
import { BitGoAPI } from '@bitgo/sdk-api';
55
import { Txrp } from '../../src/txrp';
6-
const ripple = require('../../src/ripple');
6+
import ripple from '../../src/ripple';
77

88
import * as nock from 'nock';
99
import assert from 'assert';
@@ -91,7 +91,7 @@ describe('XRP:', function () {
9191
txHex:
9292
'{"TransactionType":"Payment","Account":"rBSpCz8PafXTJHppDcNnex7dYnbe3tSuFG","Destination":"rfjub8A4dpSD5nnszUFTsLprxu1W398jwc","DestinationTag":0,"Amount":"253481","Flags":2147483648,"LastLedgerSequence":1626225,"Fee":"45","Sequence":7}',
9393
});
94-
unsignedExplanation.id.should.equal('CB36F366F1AC25FCDB38A19F17384ED3509D9B7F063520034597852FB10A1B45');
94+
unsignedExplanation.id.should.equal('37486621138DFB0C55FEF45FD275B565254464651A04CB02EE371F8C4A84D8CA');
9595
signedExplanation.id.should.equal('D52681436CC5B94E9D00BC8172047B1A6F3C028D2D0A5CDFB81680039C48ADFD');
9696
unsignedExplanation.outputAmount.should.equal('253481');
9797
signedExplanation.outputAmount.should.equal('253481');
@@ -122,7 +122,7 @@ describe('XRP:', function () {
122122
txHex:
123123
'{"TransactionType":"AccountSet","Account":"r95xbEHFzDfc9XfmXHaDnj6dHNntT9RNcy","Fee":"45","Sequence":15070378,"LastLedgerSequence":15320391,"MessageKey":"02000000000000000000000000415F8315C9948AD91E2CCE5B8583A36DA431FB61"}',
124124
});
125-
unsignedExplanation.id.should.equal('69E8A046124F15749BF75554D82F19282C1FECAA9785444FCC21107528741EDD');
125+
unsignedExplanation.id.should.equal('A0F2AF7A3E0936BCFEE0D047789502D01518D9A4F1287D50568D66474475B3E7');
126126
unsignedExplanation.accountSet.messageKey.should.equal(
127127
'02000000000000000000000000415F8315C9948AD91E2CCE5B8583A36DA431FB61'
128128
);
@@ -141,17 +141,19 @@ describe('XRP:', function () {
141141
xrpAddress: 'rJBWFy35Ya3qDZD89DuWBwm8oBbYmqb3H9',
142142
};
143143

144-
const rippleLib = ripple();
145-
const fullySigned = rippleLib.signWithPrivateKey(halfSignedTxHex, signer.rawPrv, {
144+
const fullySigned = ripple.signWithPrivateKey(halfSignedTxHex, signer.rawPrv, {
146145
signAs: signer.xrpAddress,
147146
});
148147

149148
const signedTransaction = rippleBinaryCodec.decode(fullySigned.signedTransaction);
150-
signedTransaction.TransactionType.should.equal('Payment');
151-
signedTransaction.Amount.should.equal('14999970');
152-
signedTransaction.Account.should.equal('rBfhJ6HopLW69xK83nyShdNxC3uggjs46K');
153-
signedTransaction.Destination.should.equal('rKuDJCu188nbLDs2zfaT2RNScS6aa63PLC');
154-
signedTransaction.Signers.length.should.equal(2);
149+
signedTransaction.should.containDeep({
150+
TransactionType: 'Payment',
151+
Amount: '14999970',
152+
Account: 'rBfhJ6HopLW69xK83nyShdNxC3uggjs46K',
153+
Destination: 'rKuDJCu188nbLDs2zfaT2RNScS6aa63PLC',
154+
});
155+
assert(Array.isArray(signedTransaction.Signers));
156+
(signedTransaction.Signers as Array<string>).length.should.equal(2);
155157
});
156158

157159
it('should be able to cosign XRP transaction in any form', function () {
@@ -168,11 +170,10 @@ describe('XRP:', function () {
168170
xrpAddress: 'rJBWFy35Ya3qDZD89DuWBwm8oBbYmqb3H9',
169171
};
170172

171-
const rippleLib = ripple();
172-
const coSignedHexTransaction = rippleLib.signWithPrivateKey(unsignedTxHex, signer.rawPrv, {
173+
const coSignedHexTransaction = ripple.signWithPrivateKey(unsignedTxHex, signer.rawPrv, {
173174
signAs: signer.xrpAddress,
174175
});
175-
const coSignedJsonTransaction = rippleLib.signWithPrivateKey(unsignedTxJson, signer.rawPrv, {
176+
const coSignedJsonTransaction = ripple.signWithPrivateKey(unsignedTxJson, signer.rawPrv, {
176177
signAs: signer.xrpAddress,
177178
});
178179
coSignedHexTransaction.signedTransaction.should.equal(coSignedJsonTransaction.signedTransaction);

0 commit comments

Comments
 (0)