Skip to content

Commit 9e77a92

Browse files
Merge pull request #6106 from BitGo/WIN-5434
fix: support memoid along with address for send transaction
2 parents 48e4fdb + 6b6d25a commit 9e77a92

File tree

10 files changed

+144
-3
lines changed

10 files changed

+144
-3
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ export class Hbar extends BaseCoin {
248248
const recipients = txParams.recipients.map((recipient) => ({
249249
...recipient,
250250
amount: txParams.type === 'enabletoken' ? '0' : recipient.amount,
251+
address: Utils.getAddressDetails(recipient.address).address,
251252
}));
252253
if (coinConfig.isToken) {
253254
recipients.forEach((recipient) => {

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,26 @@ describe('Hedera Hashgraph:', function () {
478478
.verifyTransaction({ txParams, txPrebuild, memo, wallet: walletObj } as any)
479479
.should.be.rejectedWith('Incorrect token name specified in recipients');
480480
});
481+
482+
it('should success to verify transfer having address with memo id', async function () {
483+
const txParams = newTxParams();
484+
const txPrebuild = newTxPrebuild();
485+
txPrebuild.txHex = TestData.UNSIGNED_TOKEN_ASSOCIATE;
486+
txParams.recipients = [
487+
{
488+
address: '0.0.81320?memoId=1',
489+
amount: '0',
490+
tokenName: 'thbar:usdc',
491+
},
492+
];
493+
const validTransaction = await basecoin.verifyTransaction({
494+
txParams,
495+
txPrebuild,
496+
memo,
497+
wallet: walletObj,
498+
} as any);
499+
validTransaction.should.equal(true);
500+
});
481501
});
482502

483503
describe('Sign Message', () => {

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,10 @@ export class Rune extends CosmosCoin {
9898
const explainedTx = transaction.explainTransaction();
9999

100100
if (txParams.recipients && txParams.recipients.length > 0) {
101-
const filteredRecipients = txParams.recipients?.map((recipient) => _.pick(recipient, ['address', 'amount']));
101+
const filteredRecipients = txParams.recipients.map((recipient) => ({
102+
address: this.getAddressDetails(recipient.address).address,
103+
amount: recipient.amount,
104+
}));
102105
let filteredOutputs = explainedTx.outputs.map((output) => _.pick(output, ['address', 'amount']));
103106

104107
filteredOutputs = filteredOutputs.map((output) => {

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,24 @@ describe('Rune', function () {
154154
isTransactionVerified.should.equal(true);
155155
});
156156

157+
it('should succeed to verify transaction having recipient address has memo', async function () {
158+
const txPrebuild = {
159+
txHex: TEST_SEND_TX.signedTxBase64,
160+
txInfo: {},
161+
};
162+
const txParams = {
163+
recipients: [
164+
{
165+
address: TEST_SEND_TX.recipient + '?memoId=2',
166+
amount: TEST_SEND_TX.sendAmount,
167+
},
168+
],
169+
};
170+
const verification = {};
171+
const isTransactionVerified = await trune.verifyTransaction({ txParams, txPrebuild, verification });
172+
isTransactionVerified.should.equal(true);
173+
});
174+
157175
it('should fail to verify transaction with invalid param', async function () {
158176
const txPrebuild = {};
159177
const txParams = { recipients: undefined };

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,21 @@ export class Ton extends BaseCoin {
9595
return true;
9696
}
9797

98+
getAddressDetails(address: string): { address: string; memoId?: string } {
99+
const addressComponents = address.split('?memoId=');
100+
101+
if (addressComponents.length > 1) {
102+
return {
103+
address: addressComponents[0],
104+
memoId: addressComponents[1],
105+
};
106+
} else {
107+
return {
108+
address: addressComponents[0],
109+
};
110+
}
111+
}
112+
98113
async verifyTransaction(params: VerifyTransactionOptions): Promise<boolean> {
99114
const coinConfig = coins.get(this.getChain());
100115
const { txPrebuild: txPrebuild, txParams: txParams } = params;
@@ -108,8 +123,9 @@ export class Ton extends BaseCoin {
108123
const explainedTx = transaction.explainTransaction();
109124
if (txParams.recipients !== undefined) {
110125
const filteredRecipients = txParams.recipients?.map((recipient) => {
126+
const destination = this.getAddressDetails(recipient.address);
111127
return {
112-
address: new TonWeb.Address(recipient.address).toString(true, true, true),
128+
address: new TonWeb.Address(destination.address).toString(true, true, true),
113129
amount: BigInt(recipient.amount),
114130
};
115131
});

modules/sdk-coin-ton/test/resources/ton.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ export const signedSendTransaction = {
5252
},
5353
};
5454

55+
export const signedSendTransactionForMemoId = {
56+
tx: 'te6cckEBAgEAqQAB4YgBJAxo7vqHF++LJ4bC/kJ8A1uVRskrKlrKJZ8rIB0tF+gCadlSX+hPo2mmhZyi0p3zTVUYVRkcmrCm97cSUFSa2vzvCArM3APg+ww92r3IcklNjnzfKOgysJVQXiCvj9SAaU1NGLsotvRwAAAAMAAcAQBmQgAaRefBOjTi/hwqDjv+7I6nGj9WEAe3ls/rFuBEQvggr5zEtAAAAAAAAAAAAAAAAAAAdfZO7w==',
57+
recipient: {
58+
address: 'EQA0i8-CdGnF_DhUHHf92R1ONH6sIA9vLZ_WLcCIhfBBXwtG?memoId=1234',
59+
amount: '10000000',
60+
},
61+
};
62+
5563
export const signedSingleNominatorWithdrawTransaction = {
5664
tx: 'te6cckECGAEAA8MAAuGIADZN0H0n1tz6xkYgWqJSRmkURKYajjEgXeawBo9cifPIGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACmpoxdJlgLSAAAAAAADgEXAgE0AhYBFP8A9KQT9LzyyAsDAgEgBBECAUgFCALm0AHQ0wMhcbCSXwTgItdJwSCSXwTgAtMfIYIQcGx1Z70ighBkc3RyvbCSXwXgA/pAMCD6RAHIygfL/8nQ7UTQgQFA1yH0BDBcgQEI9ApvoTGzkl8H4AXTP8glghBwbHVnupI4MOMNA4IQZHN0crqSXwbjDQYHAHgB+gD0BDD4J28iMFAKoSG+8uBQghBwbHVngx6xcIAYUATLBSbPFlj6Ahn0AMtpF8sfUmDLPyDJgED7AAYAilAEgQEI9Fkw7UTQgQFA1yDIAc8W9ADJ7VQBcrCOI4IQZHN0coMesXCAGFAFywVQA88WI/oCE8tqyx/LP8mAQPsAkl8D4gIBIAkQAgEgCg8CAVgLDAA9sp37UTQgQFA1yH0BDACyMoHy//J0AGBAQj0Cm+hMYAIBIA0OABmtznaiaEAga5Drhf/AABmvHfaiaEAQa5DrhY/AABG4yX7UTQ1wsfgAWb0kK29qJoQICga5D6AhhHDUCAhHpJN9KZEM5pA+n/mDeBKAG3gQFImHFZ8xhAT48oMI1xgg0x/TH9MfAvgju/Jk7UTQ0x/TH9P/9ATRUUO68qFRUbryogX5AVQQZPkQ8qP4ACSkyMsfUkDLH1Iwy/9SEPQAye1U+A8B0wchwACfbFGTINdKltMH1AL7AOgw4CHAAeMAIcAC4wABwAORMOMNA6TIyx8Syx/L/xITFBUAbtIH+gDU1CL5AAXIygcVy//J0Hd0gBjIywXLAiLPFlAF+gIUy2sSzMzJc/sAyEAUgQEI9FHypwIAcIEBCNcY+gDTP8hUIEeBAQj0UfKnghBub3RlcHSAGMjLBcsCUAbPFlAE+gIUy2oSyx/LP8lz+wACAGyBAQjXGPoA0z8wUiSBAQj0WfKnghBkc3RycHSAGMjLBcsCUAXPFlAD+gITy2rLHxLLP8lz+wAACvQAye1UAFEAAAAAKamjF8DDudwJkyEh7jUbJEjFCjriVxsSlRJFyF872V1eegb4QACPQgAaRefBOjTi/hwqDjv+7I6nGj9WEAe3ls/rFuBEQvggr6A613oAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAHA0/PoUC5EIEyWuPg==',
5765
txBounceable:

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,23 @@ describe('TON:', function () {
166166
.should.rejectedWith('missing required tx prebuild property txHex');
167167
});
168168
});
169+
170+
it('should succeed to verify transaction with recipient having memo', async function () {
171+
const txParams = {
172+
recipients: [testData.signedSendTransactionForMemoId.recipient],
173+
};
174+
const txPrebuild = {
175+
txHex: Buffer.from(testData.signedSendTransactionForMemoId.tx, 'base64').toString('hex'),
176+
txInfo: {},
177+
};
178+
const verification = {};
179+
const isTransactionVerified = await basecoin.verifyTransaction({
180+
txParams,
181+
txPrebuild,
182+
verification,
183+
} as any);
184+
isTransactionVerified.should.equal(true);
185+
});
169186
});
170187

171188
describe('Explain Transaction: ', () => {

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,29 @@ describe('XLM:', function () {
699699
validTransaction.should.equal(true);
700700
});
701701

702+
it('should verify a transaction has recipient having memo', async function () {
703+
const txParams = {
704+
recipients: [
705+
{
706+
address: 'GCNFRU774FPHLV3HAB6CR54XJYFYITOLU6KS2J5BNCLDPYN7I3DOMIPY?memoId=1234567890',
707+
amount: '128000000',
708+
},
709+
],
710+
};
711+
const txPrebuild = {
712+
txBase64: halfSignedTransaction.halfSigned.txBase64,
713+
};
714+
const verification = {
715+
disableNetworking: true,
716+
keychains: {
717+
user: { pub: userKeychain.pub },
718+
backup: { pub: backupKeychain.pub },
719+
},
720+
};
721+
const validTransaction = await basecoin.verifyTransaction({ txParams, txPrebuild, wallet, verification });
722+
validTransaction.should.equal(true);
723+
});
724+
702725
it('should verify a transaction with root key', async function () {
703726
const txParams = {
704727
recipients: [

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ export class Xrp extends BaseCoin {
313313
const expectedOutput = txParams.recipients && txParams.recipients[0];
314314

315315
const comparator = (recipient1, recipient2) => {
316-
if (recipient1.address !== recipient2.address) {
316+
if (utils.getAddressDetails(recipient1.address).address !== utils.getAddressDetails(recipient2.address).address) {
317317
return false;
318318
}
319319
const amount1 = new BigNumber(recipient1.amount);

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,41 @@ describe('XRP:', function () {
489489
};
490490
await token.verifyTransaction({ txParams, txPrebuild }).should.be.rejectedWith('txrp:usd is not supported');
491491
});
492+
493+
it('should verify token transfers with recipoent has dt', async function () {
494+
const txPrebuild = {
495+
txHex:
496+
'{"Account":"rsgg4mwHTGPRP7A4eGUmrpTxTeDZHQrHkQ","Fee":"45","Sequence":1760661,"Flags":2147483648,"TransactionType":"Payment","Destination":"raJ4NmhHr2j2SGkmVFeMqKR5MUSWXjNF9a","Amount":{"value":"0.01","currency":"524C555344000000000000000000000000000000","issuer":"rQhWct2fv4Vc4KRjRgMrxa8xPN9Zx9iLKV"},"DestinationTag":1}',
497+
txInfo: {
498+
Account: 'rsgg4mwHTGPRP7A4eGUmrpTxTeDZHQrHkQ',
499+
TransactionType: 'Payment',
500+
Destination: 'raJ4NmhHr2j2SGkmVFeMqKR5MUSWXjNF9a',
501+
Amount: {
502+
value: '0.01',
503+
currency: '524C555344000000000000000000000000000000',
504+
issuer: 'rQhWct2fv4Vc4KRjRgMrxa8xPN9Zx9iLKV',
505+
},
506+
DestinationTag: 1,
507+
},
508+
coin: 'txrp',
509+
token: 'txrp:rlusd',
510+
};
511+
const txParams = {
512+
coin: 'txrp:rlusd',
513+
recipients: [
514+
{
515+
address: 'raJ4NmhHr2j2SGkmVFeMqKR5MUSWXjNF9a?dt=1',
516+
amount: '10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
517+
},
518+
],
519+
};
520+
521+
const validTransaction = await token.verifyTransaction({
522+
txParams,
523+
txPrebuild,
524+
});
525+
validTransaction.should.equal(true);
526+
});
492527
});
493528

494529
describe('Unit Tests for isWalletAddress function', function () {

0 commit comments

Comments
 (0)