Skip to content

Commit

Permalink
Merge pull request #4139 from BitGo/EA-2457-sdk-allow-non-bouncable-r…
Browse files Browse the repository at this point in the history
…eceive-address

fix(sdk-coin-ton): support non-bouncable address as recipient
  • Loading branch information
noel-bitgo authored Dec 11, 2023
2 parents 490a95d + 72270e2 commit 91a1f7d
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 3 deletions.
1 change: 1 addition & 0 deletions modules/sdk-coin-ton/src/lib/iface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export interface TxData {
id: string;
sender: string;
destination: string;
destinationAlias: string;
amount: string;
seqno: number;
expirationTime: number;
Expand Down
2 changes: 2 additions & 0 deletions modules/sdk-coin-ton/src/lib/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ export class Transaction extends BaseTransaction {
}

toJson(): TxData {
const non_bouncable = new TonWeb.Address(this.recipient.address).toString(true, true, false);
return {
id: this._id as string,
sender: this.sender,
destination: this.recipient.address,
destinationAlias: non_bouncable,
amount: this.recipient.amount,
seqno: this.seqno,
expirationTime: this.expireTime,
Expand Down
8 changes: 7 additions & 1 deletion modules/sdk-coin-ton/src/ton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { KeyPair as TonKeyPair } from './lib/keyPair';
import BigNumber from 'bignumber.js';
import * as _ from 'lodash';
import { Transaction, TransactionBuilderFactory, Utils } from './lib';
import TonWeb from 'tonweb';

export interface TonParseTransactionOptions extends ParseTransactionOptions {
txHex: string;
Expand Down Expand Up @@ -83,7 +84,12 @@ export class Ton extends BaseCoin {
transaction.fromRawTransaction(Buffer.from(rawTx, 'hex').toString('base64'));
const explainedTx = transaction.explainTransaction();
if (txParams.recipients !== undefined) {
const filteredRecipients = txParams.recipients?.map((recipient) => _.pick(recipient, ['address', 'amount']));
const filteredRecipients = txParams.recipients?.map((recipient) => {
return {
address: new TonWeb.Address(recipient.address).toString(true, true, true),
amount: recipient.amount,
};
});
const filteredOutputs = explainedTx.outputs.map((output) => _.pick(output, ['address', 'amount']));

if (!_.isEqual(filteredOutputs, filteredRecipients)) {
Expand Down
2 changes: 1 addition & 1 deletion modules/sdk-coin-ton/test/resources/ton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const recipients: Recipient[] = [

export const signedTransaction = {
tx: 'te6cckEBAgEAsQAB4YgAQmy8N765HIcsCkExBYpKsfl7LUuXYW7MvV53d6EqWoADFgjyqp/3qccthFjfvskQ1XUeecHe8JVQ9DFGSmpwRovdPiRamZZ3PR2isMd1i5k+MdQCc9TCP/E5+rfkvMbYQU1NGLsruXHwAAAAgAAcAQB2QgB9Jzc15Nkj1GPyoSR0hIg9lzcoUjVC0MYRF1GRn2tVHpzEtAAAAAAAAAAAAAAAAAAAAAAAAHRlc3SUlVNc',
txId: '',
txId: '9gEyvIsHrA79g8pmEP1EBtO8GlpZ98QnUveSYmEx6fc=',
signable: 'q28coBQ7sbBBAR/hG4eUdDayLDsPC9FKQtA/lSYYaSQ=',
recipient: {
address: 'EQD6Tm5rybJHqMflQkjpCRB7Lm5QpGqFoYwiLqMjPtaqPSdZ',
Expand Down
28 changes: 28 additions & 0 deletions modules/sdk-coin-ton/test/unit/ton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as testData from '../resources/ton';
import { TransactionExplanation } from '@bitgo/sdk-core';
import should from 'should';
import utils from '../../src/lib/utils';
import Tonweb from 'tonweb';

describe('TON:', function () {
const bitgo = TestBitGo.decorate(BitGoAPI, { env: 'mock' });
Expand Down Expand Up @@ -62,6 +63,33 @@ describe('TON:', function () {
.should.rejectedWith('Tx outputs does not match with expected txParams recipients');
});

it('should succeed to verify transaction when recipients amount are numbers', async function () {
const txParamsWithNumberAmounts = JSON.parse(JSON.stringify(txParams));
txParamsWithNumberAmounts.recipients[0].amount = '20000000';
const verification = {};
await basecoin
.verifyTransaction({
txParams: txParamsWithNumberAmounts,
txPrebuild,
verification,
} as any)
.should.rejectedWith('Tx outputs does not match with expected txParams recipients');
});

it('should succeed to verify transaction when recipient address are non bouncable', async function () {
const txParamsWithNumberAmounts = JSON.parse(JSON.stringify(txParams));
txParamsWithNumberAmounts.recipients[0].address = new Tonweb.Address(
txParamsWithNumberAmounts.recipients[0].address
).toString(true, true, false);
const verification = {};
const isVerified = await basecoin.verifyTransaction({
txParams: txParamsWithNumberAmounts,
txPrebuild,
verification,
} as any);
isVerified.should.equal(true);
});

it('should fail to verify transaction with invalid param', async function () {
const txPrebuild = {};
await basecoin
Expand Down
34 changes: 33 additions & 1 deletion modules/sdk-coin-ton/test/unit/transferBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('Ton Transfer Builder', () => {
const jsonTx = builtTx.toJson();
should.equal(builtTx.type, TransactionType.Send);
should.equal(builtTx.signablePayload.toString('base64'), testData.signedTransaction.signable);
// should.equal(builtTx.id, testData.signedTransaction.txId);
should.equal(builtTx.id, testData.signedTransaction.txId);
const builder2 = factory.from(builtTx.toBroadcastFormat());
const builtTx2 = await builder2.build();
should.equal(builtTx2.type, TransactionType.Send);
Expand Down Expand Up @@ -120,4 +120,36 @@ describe('Ton Transfer Builder', () => {
should.equal(Buffer.from(signature).toString('hex'), Buffer.from(signature2).toString('hex'));
should.equal(tx.toBroadcastFormat(), tx2.toBroadcastFormat());
});

it('should build transfer tx for non-bouncable address', async function () {
const txBuilder = factory.getTransferBuilder();
txBuilder.sender(testData.sender.address);
txBuilder.sequenceNumber(0);
txBuilder.publicKey(testData.sender.publicKey);
txBuilder.expireTime(1234567890);
const address = 'UQAWzEKcdnykvXfUNouqdS62tvrp32bCxuKS6eQrS6ISgZ8t';
const amount = '10000000';
txBuilder.send({ address, amount });
txBuilder.setMessage('test');
const tx = await txBuilder.build();
should.equal(tx.type, TransactionType.Send);
tx.inputs.length.should.equal(1);
tx.inputs[0].should.deepEqual({
address: testData.sender.address,
value: amount,
coin: 'tton',
});
tx.outputs.length.should.equal(1);
tx.outputs[0].should.deepEqual({
address,
value: amount,
coin: 'tton',
});
const txJson = tx.toJson();
txJson.destination.should.equal(address);
const builder2 = factory.from(tx.toBroadcastFormat());
const tx2 = await builder2.build();
const txJson2 = tx2.toJson();
txJson2.destinationAlias.should.equal(address);
});
});

0 comments on commit 91a1f7d

Please sign in to comment.