@coolwallet/ton
Version:
561 lines (508 loc) • 20.6 kB
text/typescript
import { CardType, Transport } from '@coolwallet/core';
import { createTransport } from '@coolwallet/transport-jre-http';
import { initialize } from '@coolwallet/testing-library';
import TON from '../src';
import {
SignTransferTokenTxType,
SignTransferTxType,
TransferTokenTransaction,
TransferTransaction,
} from '../src/config/types';
import TonWeb from 'tonweb';
import { getJettonWallet, getKeyPair, getWalletV4R2 } from '../src/utils/tonweb';
type PromiseValue<T> = T extends Promise<infer V> ? V : never;
type Mandatory = PromiseValue<ReturnType<typeof initialize>>;
describe('Test TON SDK', () => {
let transport: Transport;
let cardType: CardType;
let props: Mandatory;
const tonSDK = new TON();
const mnemonic = 'zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo abstract';
beforeAll(async () => {
if (process.env.CARD === 'go') {
cardType = CardType.Go;
} else {
cardType = CardType.Pro;
}
if (cardType === CardType.Go) {
transport = (await createTransport('http://localhost:9527', CardType.Go))!;
} else {
transport = (await createTransport())!;
}
props = await initialize(transport, mnemonic);
});
describe('Test Get Address', () => {
it('index 0 with Non-bounceable', async () => {
const address = await tonSDK.getAddress(transport, props.appPrivateKey, props.appId, 0);
expect(address).toEqual('UQD87WwPU6bw4WJ9vQyfgnxHy6hWbJg0LQRcBxhi95WErCOQ');
});
it('index 0 with bounceable', async () => {
const address = await tonSDK.getAddress(transport, props.appPrivateKey, props.appId, 0, true);
expect(address).toEqual('EQD87WwPU6bw4WJ9vQyfgnxHy6hWbJg0LQRcBxhi95WErH5V');
});
it('index 16 with Non-bounceable', async () => {
const address = await tonSDK.getAddress(transport, props.appPrivateKey, props.appId, 16);
expect(address).toEqual('UQAOh0hSRHguolOxpU5jRa4ICdQVogFMeRivN5x3gHYMTPuS');
});
});
describe('Test Sign Transfer', () => {
async function get_signed_tx_by_coolwallet_sdk(transaction: TransferTransaction, addressIndex: number) {
const signData: SignTransferTxType = {
transport,
appPrivateKey: props.appPrivateKey,
appId: props.appId,
addressIndex,
transaction,
confirmCB: () => {},
authorizedCB: () => {},
};
return await tonSDK.signTransaction(signData);
}
async function get_signed_tx_by_tonweb_sdk(transaction: TransferTransaction, addressIndex: number) {
const { toAddress, amount, seqno, payload, expireAt, sendMode } = transaction;
const { publicKey, secretKey } = await getKeyPair(mnemonic, addressIndex);
return await getWalletV4R2(Buffer.from(publicKey).toString('hex'))
.methods.transfer({
secretKey: secretKey,
toAddress: toAddress,
amount,
seqno,
payload,
expireAt,
sendMode,
})
.getQuery()
.then((message) => message.toBoc(false))
.then(TonWeb.utils.bytesToBase64);
}
async function expect_both_coolwallet_and_tonweb_signed_tx_is_same(transaction: TransferTransaction) {
const addressIndex = 0;
const signedTx1 = await get_signed_tx_by_coolwallet_sdk(transaction, addressIndex);
const signedTx2 = await get_signed_tx_by_tonweb_sdk(transaction, addressIndex);
expect(signedTx1).toEqual(signedTx2);
}
it('transfer to bounceable address', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
toAddress: 'EQAW5QLk3XvW3HMbLqkE9wXkL9NdGpE1555tUxhdea8pVIbJ',
amount: '123000000',
seqno: 20,
payload: 'Hello CoolWallet!',
expireAt: 1716886177,
sendMode: 3,
});
});
it('transfer to non-bounceable address', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
toAddress: 'UQAW5QLk3XvW3HMbLqkE9wXkL9NdGpE1555tUxhdea8pVNsM',
amount: '123000000',
seqno: 20,
payload: 'Hello CoolWallet!',
expireAt: 1716886177,
sendMode: 3,
});
});
it('transfer to hex address', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
toAddress: '0:16e502e4dd7bd6dc731b2ea904f705e42fd35d1a9135e79e6d53185d79af2954',
amount: '123000000',
seqno: 20,
payload: 'Hello CoolWallet!',
expireAt: 1716886177,
sendMode: 3,
});
});
it('transfer with amount 0 will throw error', async () => {
const transaction = {
toAddress: 'EQAW5QLk3XvW3HMbLqkE9wXkL9NdGpE1555tUxhdea8pVIbJ',
amount: '0',
seqno: 20,
expireAt: 1716886177,
sendMode: 130,
};
const addressIndex = 0;
expect(get_signed_tx_by_coolwallet_sdk(transaction, addressIndex)).rejects.toThrowError();
});
it('transfer with amount 1', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
toAddress: 'EQAW5QLk3XvW3HMbLqkE9wXkL9NdGpE1555tUxhdea8pVIbJ',
amount: '1',
seqno: 20,
expireAt: 1716886177,
sendMode: 130,
});
});
it('transfer with amount 99999999', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
toAddress: 'EQAW5QLk3XvW3HMbLqkE9wXkL9NdGpE1555tUxhdea8pVIbJ',
amount: '99999999',
seqno: 20,
expireAt: 1716886177,
sendMode: 130,
});
});
it('transfer with large amount will throw error', async () => {
const transaction = {
toAddress: 'EQAW5QLk3XvW3HMbLqkE9wXkL9NdGpE1555tUxhdea8pVIbJ',
amount: TonWeb.utils.toNano('100000000').toString(), // Pro card not support to display 9 integer digits
seqno: 20,
expireAt: 1716886177,
sendMode: 130,
};
const addressIndex = 0;
expect(get_signed_tx_by_coolwallet_sdk(transaction, addressIndex)).rejects.toThrowError();
});
it('transfer with seqno 0', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
toAddress: 'EQAW5QLk3XvW3HMbLqkE9wXkL9NdGpE1555tUxhdea8pVIbJ',
amount: '123000000',
seqno: 0,
expireAt: 1716886177,
sendMode: 130,
});
});
it('transfer with seqno 100', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
toAddress: 'EQAW5QLk3XvW3HMbLqkE9wXkL9NdGpE1555tUxhdea8pVIbJ',
amount: '123000000',
seqno: 100,
expireAt: 1716886177,
sendMode: 130,
});
});
it('transfer with sendMode 3', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
toAddress: 'EQAW5QLk3XvW3HMbLqkE9wXkL9NdGpE1555tUxhdea8pVIbJ',
amount: '123000000',
seqno: 100,
expireAt: 1716886177,
sendMode: 3,
});
});
it('transfer with sendMode 130', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
toAddress: 'EQAW5QLk3XvW3HMbLqkE9wXkL9NdGpE1555tUxhdea8pVIbJ',
amount: '123000000',
seqno: 100,
expireAt: 1716886177,
sendMode: 130,
});
});
it('transfer without memo', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
toAddress: 'EQAW5QLk3XvW3HMbLqkE9wXkL9NdGpE1555tUxhdea8pVIbJ',
amount: '123000000',
seqno: 100,
expireAt: 1716886177,
sendMode: 130,
payload: '',
});
});
it('transfer with memo', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
toAddress: 'EQAW5QLk3XvW3HMbLqkE9wXkL9NdGpE1555tUxhdea8pVIbJ',
amount: '123000000',
seqno: 100,
expireAt: 1716886177,
sendMode: 130,
payload: 'Hello Hello Hello Hello Hello Hello',
});
});
it('transfer with large memo', async () => {
const transaction = {
toAddress: 'EQAW5QLk3XvW3HMbLqkE9wXkL9NdGpE1555tUxhdea8pVIbJ',
amount: '123000000',
seqno: 20,
expireAt: 1716886177,
sendMode: 130,
payload: 'Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello',
};
const addressIndex = 0;
expect(get_signed_tx_by_coolwallet_sdk(transaction, addressIndex)).rejects.toThrowError();
});
it('transfer with chinese memo', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
toAddress: 'EQAW5QLk3XvW3HMbLqkE9wXkL9NdGpE1555tUxhdea8pVIbJ',
amount: '123000000',
seqno: 100,
expireAt: 1716886177,
sendMode: 130,
payload: '你好',
});
});
});
describe('Test Sign Transfer Token', () => {
async function get_signed_tx_by_coolwallet_sdk(transaction: TransferTokenTransaction, addressIndex: number) {
const signData: SignTransferTokenTxType = {
transport,
appPrivateKey: props.appPrivateKey,
appId: props.appId,
addressIndex,
transaction,
confirmCB: () => {},
authorizedCB: () => {},
};
return await tonSDK.signTransferTokenTransaction(signData);
}
async function get_signed_tx_by_tonweb_sdk(transaction: TransferTokenTransaction, addressIndex: number) {
const { toAddress: fromTokenAccount, amount, seqno, payload, expireAt, sendMode } = transaction;
const { jettonAmount, toAddress, forwardAmount, forwardPayload, responseAddress } = payload;
const { publicKey, secretKey } = await getKeyPair(mnemonic, addressIndex);
const wallet = getWalletV4R2(Buffer.from(publicKey).toString('hex'));
const jettonWallet = await getJettonWallet(fromTokenAccount);
const transferPayload = await jettonWallet.createTransferBody({
jettonAmount,
toAddress: new TonWeb.utils.Address(toAddress),
forwardAmount,
forwardPayload: new Uint8Array([...new Uint8Array(4), ...new TextEncoder().encode(forwardPayload || '')]),
responseAddress: new TonWeb.utils.Address(responseAddress),
} as any);
return await wallet.methods
.transfer({
secretKey: secretKey,
toAddress: fromTokenAccount,
amount,
seqno,
expireAt,
sendMode,
payload: transferPayload,
})
.getQuery()
.then((message) => message.toBoc(false))
.then(TonWeb.utils.bytesToBase64);
}
async function expect_both_coolwallet_and_tonweb_signed_tx_is_same(transaction: TransferTokenTransaction) {
const addressIndex = 0;
const signedTx1 = await get_signed_tx_by_coolwallet_sdk(transaction, addressIndex);
const signedTx2 = await get_signed_tx_by_tonweb_sdk(transaction, addressIndex);
expect(signedTx1).toEqual(signedTx2);
}
const baseTransaction = {
toAddress: 'EQBgGEdG_Uj-c1hcy2zBT6e7ADNpE2KBoXQTKAWSeeLBKHcu',
amount: '50000000',
seqno: 19,
expireAt: 1716886177,
sendMode: 3,
payload: {
jettonAmount: '1234',
toAddress: 'EQAW5QLk3XvW3HMbLqkE9wXkL9NdGpE1555tUxhdea8pVIbJ',
forwardAmount: '1',
forwardPayload: 'Hello',
responseAddress: 'EQAlWnyf_OmGFyJ3wHkP930RGPDtokkcYhphAjId05OOI3Up',
},
tokenInfo: {
symbol: 'USDT',
decimals: 6,
address: 'EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs',
},
};
describe('By diffenent toAddress', () => {
it("transfer: using sender's usdt account", async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
toAddress: 'EQBgGEdG_Uj-c1hcy2zBT6e7ADNpE2KBoXQTKAWSeeLBKHcu',
});
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
toAddress: 'UQBgGEdG_Uj-c1hcy2zBT6e7ADNpE2KBoXQTKAWSeeLBKCrr',
});
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
toAddress: 'EQAlWnyf_OmGFyJ3wHkP930RGPDtokkcYhphAjId05OOI3Up',
});
});
it("transfer: using sender's coin account", async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
toAddress: 'EQAlWnyf_OmGFyJ3wHkP930RGPDtokkcYhphAjId05OOI3Up',
});
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
toAddress: 'UQAlWnyf_OmGFyJ3wHkP930RGPDtokkcYhphAjId05OOIyjs',
});
});
});
describe('By diffenent amount', () => {
it('transfer: using 0 TON will throw error', async () => {
const transaction = { ...baseTransaction, amount: TonWeb.utils.toNano('0').toString() };
const addressIndex = 0;
expect(get_signed_tx_by_coolwallet_sdk(transaction, addressIndex)).rejects.toThrowError();
});
it('transfer: using 0.0000001 TON', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
amount: TonWeb.utils.toNano('0.0000001').toString(),
});
});
it('transfer: using 0.05 TON', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
amount: TonWeb.utils.toNano('0.05').toString(),
});
});
it('transfer: using 10000 TON', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
amount: TonWeb.utils.toNano('10000').toString(),
});
});
});
describe('By diffenent seqno', () => {
it('transfer: seqno is 0', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
seqno: 0,
});
});
it('transfer: seqno is 1', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
seqno: 1,
});
});
it('transfer: seqno is 100', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
seqno: 100,
});
});
});
describe('By diffenent sendMode', () => {
it('transfer: sendMode is 0', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
sendMode: 0,
});
});
it('transfer: sendMode is 3', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
sendMode: 3,
});
});
it('transfer: sendMode is 130', async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
sendMode: 130,
});
});
});
describe('By diffenent jettonAmount', () => {
it('transfer: jettonAmount is 0 will throw error', async () => {
const transaction = { ...baseTransaction, payload: { ...baseTransaction.payload, jettonAmount: '0' } };
const addressIndex = 0;
expect(get_signed_tx_by_coolwallet_sdk(transaction, addressIndex)).rejects.toThrowError();
});
it('transfer: jettonAmount is 1', async () => {
const transaction = { ...baseTransaction, payload: { ...baseTransaction.payload, jettonAmount: '1' } };
await expect_both_coolwallet_and_tonweb_signed_tx_is_same(transaction);
});
it('transfer: jettonAmount is 1000000000000', async () => {
const transaction = {
...baseTransaction,
payload: { ...baseTransaction.payload, jettonAmount: '1000000000000' },
};
await expect_both_coolwallet_and_tonweb_signed_tx_is_same(transaction);
});
it('transfer: jettonAmount is 100000000000000 will do blind transfer', async () => {
const transaction = {
...baseTransaction,
payload: { ...baseTransaction.payload, jettonAmount: '100000000000000' },
};
await expect_both_coolwallet_and_tonweb_signed_tx_is_same(transaction);
});
});
describe('By diffenent receiver', () => {
it("transfer: using receiver's coin account (bounceable)", async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
payload: { ...baseTransaction.payload, toAddress: 'EQAW5QLk3XvW3HMbLqkE9wXkL9NdGpE1555tUxhdea8pVIbJ' },
});
});
it("transfer: using receiver's coin account (non-bounceable)", async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
payload: { ...baseTransaction.payload, toAddress: 'UQAW5QLk3XvW3HMbLqkE9wXkL9NdGpE1555tUxhdea8pVNsM' },
});
});
it("transfer: using receiver's coin account (hex)", async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
payload: {
...baseTransaction.payload,
toAddress: '0:16e502e4dd7bd6dc731b2ea904f705e42fd35d1a9135e79e6d53185d79af2954',
},
});
});
it("transfer: using receiver's usdt account (bounceable)", async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
payload: { ...baseTransaction.payload, toAddress: 'EQCwDGN3dztkodIPeSLNWxB2eMAFUtqrMUhrfKV1BZ7g1hRA' },
});
});
it("transfer: using receiver's usdt account (non-bounceable)", async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
payload: { ...baseTransaction.payload, toAddress: 'UQCwDGN3dztkodIPeSLNWxB2eMAFUtqrMUhrfKV1BZ7g1kmF' },
});
});
it("transfer: using receiver's usdt account (hex)", async () => {
await expect_both_coolwallet_and_tonweb_signed_tx_is_same({
...baseTransaction,
payload: {
...baseTransaction.payload,
toAddress: '0:b00c6377773b64a1d20f7922cd5b107678c00552daab31486b7ca575059ee0d6',
},
});
});
});
describe('By diffenent forwardAmount', () => {
it('transfer: forwardAmount is 0 will throw error', async () => {
const transaction = { ...baseTransaction, payload: { ...baseTransaction.payload, forwardAmount: '0' } };
const addressIndex = 0;
expect(get_signed_tx_by_coolwallet_sdk(transaction, addressIndex)).rejects.toThrowError();
});
it('transfer: forwardAmount is 1', async () => {
const transaction = { ...baseTransaction, payload: { ...baseTransaction.payload, forwardAmount: '1' } };
await expect_both_coolwallet_and_tonweb_signed_tx_is_same(transaction);
});
it('transfer: forwardAmount is 10000000', async () => {
const transaction = { ...baseTransaction, payload: { ...baseTransaction.payload, forwardAmount: '10000000' } };
await expect_both_coolwallet_and_tonweb_signed_tx_is_same(transaction);
});
it('transfer: forwardAmount is 10000000000000000', async () => {
const transaction = {
...baseTransaction,
payload: { ...baseTransaction.payload, forwardAmount: '10000000000000000' },
};
await expect_both_coolwallet_and_tonweb_signed_tx_is_same(transaction);
});
});
describe('By diffenent memo', () => {
it('transfer: without memo', async () => {
const transaction = {
...baseTransaction,
payload: { ...baseTransaction.payload, forwardPayload: '' },
};
await expect_both_coolwallet_and_tonweb_signed_tx_is_same(transaction);
});
it('transfer: with short memo', async () => {
const transaction = {
...baseTransaction,
payload: { ...baseTransaction.payload, forwardPayload: 'Hello Hello Hello Hello Hello Hello' },
};
await expect_both_coolwallet_and_tonweb_signed_tx_is_same(transaction);
});
it('transfer: with long memo', async () => {
const transaction = {
...baseTransaction,
payload: {
...baseTransaction.payload,
forwardPayload: 'Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello',
},
};
const addressIndex = 0;
await expect(get_signed_tx_by_coolwallet_sdk(transaction, addressIndex)).rejects.toThrowError();
});
});
});
});