diff --git a/jest.config.js b/jest.config.js index 0996408b..27194f5f 100644 --- a/jest.config.js +++ b/jest.config.js @@ -3,6 +3,7 @@ module.exports = { preset: 'ts-jest', testEnvironment: 'node', testPathIgnorePatterns: ["/node_modules/","/dist/"], + testTimeout: 60000, moduleNameMapper: { '^axios$': require.resolve('axios'), } diff --git a/src/client/TonClient.spec.ts b/src/client/TonClient.spec.ts index 7c6f3c73..ec07bb03 100644 --- a/src/client/TonClient.spec.ts +++ b/src/client/TonClient.spec.ts @@ -43,6 +43,20 @@ describeConditional('TonClient', () => { console.log(info, shardInfo, wcShards); }); + it('should get extra currency info', async () => { + // EC is rolled out only in testned yet + let testClient = new TonClient({ + endpoint: 'https://testnet.toncenter.com/api/v2/jsonRPC' + }); + + let testAddr = Address.parse("0:D36CFC9E0C57F43C1A719CB9F540ED87A694693AE1535B7654B645F52814AFD7"); + + let res = await testClient.getContractState(testAddr); + let expectedEc =res.extra_currencies.find(e => e.id == 100)!; + expect(expectedEc).not.toBeUndefined(); + expect(BigInt(expectedEc.amount)).toBe(10000000n); + }); + it('should locate source/result tx', async () => { let source = Address.parse('UQDDT0TOC4PMp894jtCo3-d1-8ltSjXMX2EuWww_pCNibsUH'); let createdLt = '37508996000002'; diff --git a/src/client/TonClient.ts b/src/client/TonClient.ts index 34cc3af2..6d76a9bd 100644 --- a/src/client/TonClient.ts +++ b/src/client/TonClient.ts @@ -26,7 +26,8 @@ import { TupleItem, TupleReader, StateInit, - OpenedContract + OpenedContract, + ExtraCurrency } from '@ton/core'; import { Maybe } from "../utils/maybe"; @@ -302,6 +303,7 @@ export class TonClient { let state = info.state as 'frozen' | 'active' | 'uninitialized'; return { balance, + extra_currencies: info.extra_currencies, state, code: info.code !== '' ? Buffer.from(info.code, 'base64') : null, data: info.data !== '' ? Buffer.from(info.data, 'base64') : null, @@ -408,6 +410,8 @@ function createProvider(client: TonClient, address: Address, init: StateInit | n let state = await client.getContractState(address); let balance = state.balance; let last = state.lastTransaction ? { lt: BigInt(state.lastTransaction.lt), hash: Buffer.from(state.lastTransaction.hash, 'base64') } : null; + let ecMap: ExtraCurrency | null = null; + let storage: { type: 'uninit'; } | { @@ -436,8 +440,17 @@ function createProvider(client: TonClient, address: Address, init: StateInit | n } else { throw Error('Unsupported state'); } + + if(state.extra_currencies.length > 0) { + ecMap = {}; + for(let ec of state.extra_currencies) { + ecMap[ec.id] = BigInt(ec.amount); + } + } + return { balance, + extracurrency: ecMap, last, state: storage, }; @@ -512,6 +525,7 @@ function createProvider(client: TonClient, address: Address, init: StateInit | n value, bounce, sendMode: message.sendMode, + extracurrency: message.extracurrency, init: neededInit, body }); diff --git a/src/client/TonClient4.spec.ts b/src/client/TonClient4.spec.ts index 226d461b..a50a5d46 100644 --- a/src/client/TonClient4.spec.ts +++ b/src/client/TonClient4.spec.ts @@ -3,6 +3,8 @@ import { TonClient } from './TonClient'; import { TonClient4 } from './TonClient4'; import { backoff } from '../utils/time'; +type ECMap = { [k: number]: bigint }; + let describeConditional = process.env.TEST_CLIENTS ? describe : describe.skip; describeConditional('TonClient', () => { @@ -45,6 +47,35 @@ let describeConditional = process.env.TEST_CLIENTS ? describe : describe.skip; console.log(result); }); + it('should get extra currency info', async () => { + let testAddresses = [ + "-1:0000000000000000000000000000000000000000000000000000000000000000", + "0:C4CAC12F5BC7EEF4CF5EC84EE68CCF860921A06CA0395EC558E53E37B13C3B08", + "0:F5FFA780ACEE2A41663C1E32F50D771327275A42FC9D3FAB4F4D9CDE11CCA897" + ].map(a => Address.parse(a)); + + let knownEc = [239, 4294967279]; + let expectedEc: ECMap[] = [ + {239: 663333333334n, 4294967279: 998444444446n}, + {239: 989097920n}, + {239: 666666666n, 4294967279: 777777777n} + ]; + + for(let i = 0; i < testAddresses.length; i++) { + let res = await backoff(async () => await client.getAccount(seqno, testAddresses[i]), false); + let resLite = await backoff(async () => await client.getAccountLite(seqno, testAddresses[i]), false); + let expected = expectedEc[i]; + + for(let testEc of knownEc) { + let expCur = expected[testEc]; + if(expCur) { + expect(BigInt(res.account.balance.currencies[testEc])).toEqual(expCur); + expect(BigInt(resLite.account.balance.currencies[testEc])).toEqual(expCur); + } + } + } + }); + it('should run method', async () => { let result = await client.runMethod(seqno, testAddress, 'seqno'); console.log(result); diff --git a/src/client/TonClient4.ts b/src/client/TonClient4.ts index 6b5849e0..613c4d89 100644 --- a/src/client/TonClient4.ts +++ b/src/client/TonClient4.ts @@ -7,7 +7,7 @@ */ import axios, { AxiosAdapter, InternalAxiosRequestConfig, AxiosInstance } from "axios"; -import { Address, beginCell, Cell, comment, Contract, ContractProvider, ContractState, external, loadTransaction, openContract, OpenedContract, parseTuple, serializeTuple, StateInit, storeMessage, toNano, Transaction, TupleItem, TupleReader } from "@ton/core"; +import { Address, beginCell, Cell, comment, Contract, ContractProvider, ContractState, external, ExtraCurrency, loadTransaction, openContract, OpenedContract, parseTuple, serializeTuple, StateInit, storeMessage, toNano, Transaction, TupleItem, TupleReader } from "@ton/core"; import { Maybe } from "../utils/maybe"; import { toUrlSafe } from "../utils/toUrlSafe"; import { z } from 'zod'; @@ -364,8 +364,19 @@ function createProvider(client: TonClient4, block: number | null, address: Addre throw Error('Unsupported state'); } + let ecMap: ExtraCurrency | null = null; + + if(state.account.balance.currencies) { + ecMap = {}; + let currencies = state.account.balance.currencies; + for(let [k, v] of Object.entries(currencies)) { + ecMap[Number(k)] = BigInt(v); + } + } + return { balance: BigInt(state.account.balance.coins), + extracurrency: ecMap, last: last, state: storage }; @@ -448,6 +459,7 @@ function createProvider(client: TonClient4, block: number | null, address: Addre await via.send({ to: address, value, + extracurrency: message.extracurrency, bounce, sendMode: message.sendMode, init: neededInit, @@ -561,7 +573,8 @@ const accountCodec = z.object({ z.object({ type: z.literal('frozen'), stateHash: z.string() }) ]), balance: z.object({ - coins: z.string() + coins: z.string(), + currencies: z.record(z.string(), z.string()) }), last: z.union([ z.null(), @@ -589,7 +602,8 @@ const accountLiteCodec = z.object({ z.object({ type: z.literal('frozen'), stateHash: z.string() }) ]), balance: z.object({ - coins: z.string() + coins: z.string(), + currencies: z.record(z.string(), z.string()) }), last: z.union([ z.null(), diff --git a/src/client/api/HttpApi.ts b/src/client/api/HttpApi.ts index be180f6e..7244ba4a 100644 --- a/src/client/api/HttpApi.ts +++ b/src/client/api/HttpApi.ts @@ -24,6 +24,11 @@ const blockIdExt = z.object({ const addressInformation = z.object({ balance: z.union([z.number(), z.string()]), + extra_currencies: z.array(z.object({ + '@type': z.literal("extraCurrency"), + id: z.number(), + amount: z.string() + })), state: z.union([z.literal('active'), z.literal('uninitialized'), z.literal('frozen')]), data: z.string(), code: z.string(), diff --git a/src/utils/testWallets.ts b/src/utils/testWallets.ts new file mode 100644 index 00000000..648fa1ee --- /dev/null +++ b/src/utils/testWallets.ts @@ -0,0 +1,28 @@ +import { OpenedContract } from '@ton/core'; +import { WalletContractV5R1 } from '../wallets/v5r1/WalletContractV5R1'; +import { WalletContractV5Beta } from '../wallets/v5beta/WalletContractV5Beta'; +import { WalletContractV4 } from '../wallets/WalletContractV4'; +import { WalletContractV3R2 } from '../wallets/WalletContractV3R2'; +import { WalletContractV3R1 } from '../wallets/WalletContractV3R1'; +import { WalletContractV2R2 } from '../wallets/WalletContractV2R2'; +import { WalletContractV2R1 } from '../wallets/WalletContractV2R1'; +import { WalletContractV1R2 } from '../wallets/WalletContractV1R2'; +import { WalletContractV1R1 } from '../wallets/WalletContractV1R1'; + + +type WalletContract = WalletContractV5R1 | WalletContractV5Beta | WalletContractV4 | WalletContractV3R2 | WalletContractV3R1 | WalletContractV2R2 | WalletContractV2R1 | WalletContractV1R2 | WalletContractV1R1; + +export const tillNextSeqno = async(wallet: OpenedContract, oldSeqno: number, maxTries: number = 10) => { + let seqNoAfter = oldSeqno; + let tried = 0; + + do { + await new Promise((resolve, reject) => { + setTimeout(resolve, 2000); + }); + seqNoAfter = await wallet.getSeqno(); + if(tried++ > maxTries) { + throw Error("To many retries, transaction likely failed!"); + } + } while(seqNoAfter == oldSeqno); +} diff --git a/src/wallets/WalletContractV1R1.spec.ts b/src/wallets/WalletContractV1R1.spec.ts index 80ab8dcc..b5498b48 100644 --- a/src/wallets/WalletContractV1R1.spec.ts +++ b/src/wallets/WalletContractV1R1.spec.ts @@ -10,6 +10,7 @@ import { randomTestKey } from "../utils/randomTestKey"; import { createTestClient4 } from "../utils/createTestClient4"; import { Address, internal } from "@ton/core"; import { WalletContractV1R1 } from "./WalletContractV1R1"; +import { tillNextSeqno } from "../utils/testWallets"; describe('WalletContractV1R1', () => { @@ -46,5 +47,30 @@ describe('WalletContractV1R1', () => { // Perform transfer await contract.send(transfer); + await tillNextSeqno(contract, seqno); }); -}); \ No newline at end of file + + it('should perform extra currency transfer', async () => { + // Create contract + let client = createTestClient4(); + let key = randomTestKey('v4-treasure'); + let contract = client.open(WalletContractV1R1.create({ workchain: 0, publicKey: key.publicKey })); + + // Prepare transfer + let seqno = await contract.getSeqno(); + let transfer = contract.createTransfer({ + seqno, + secretKey: key.secretKey, + message: internal({ + to: 'kQD6oPnzaaAMRW24R8F0_nlSsJQni0cGHntR027eT9_sgtwt', + value: '0.01', + extracurrency: {100: BigInt(10 ** 6)}, + body: 'Hello, extra currency v1r1!' + }) + }); + + // Perform transfer + await contract.send(transfer); + await tillNextSeqno(contract, seqno); + }); +}); diff --git a/src/wallets/WalletContractV1R1.ts b/src/wallets/WalletContractV1R1.ts index b9d0570d..8e019f3f 100644 --- a/src/wallets/WalletContractV1R1.ts +++ b/src/wallets/WalletContractV1R1.ts @@ -110,6 +110,7 @@ export class WalletContractV1R1 implements Contract { message: internal({ to: args.to, value: args.value, + extracurrency: args.extracurrency, init: args.init, body: args.body, bounce: args.bounce diff --git a/src/wallets/WalletContractV1R2.spec.ts b/src/wallets/WalletContractV1R2.spec.ts index 0e517394..ba75f9d4 100644 --- a/src/wallets/WalletContractV1R2.spec.ts +++ b/src/wallets/WalletContractV1R2.spec.ts @@ -10,6 +10,7 @@ import { randomTestKey } from "../utils/randomTestKey"; import { createTestClient4 } from "../utils/createTestClient4"; import { Address, internal } from "@ton/core"; import { WalletContractV1R2 } from "./WalletContractV1R2"; +import { tillNextSeqno } from "../utils/testWallets"; describe('WalletContractV1R2', () => { it('should has balance and correct address', async () => { @@ -44,5 +45,30 @@ describe('WalletContractV1R2', () => { // Perform transfer await contract.send(transfer); + await tillNextSeqno(contract, seqno); }); -}); \ No newline at end of file + + it('should perform extra currency transfer', async () => { + // Create contract + let client = createTestClient4(); + let key = randomTestKey('v4-treasure'); + let contract = client.open(WalletContractV1R2.create({ workchain: 0, publicKey: key.publicKey })); + + // Prepare transfer + let seqno = await contract.getSeqno(); + let transfer = contract.createTransfer({ + seqno, + secretKey: key.secretKey, + message: internal({ + to: 'kQD6oPnzaaAMRW24R8F0_nlSsJQni0cGHntR027eT9_sgtwt', + value: '0.01', + extracurrency: {100: BigInt(10 ** 6)}, + body: 'Hello, extra currency v1r2!' + }) + }); + + // Perform transfer + await contract.send(transfer); + await tillNextSeqno(contract, seqno); + }); +}); diff --git a/src/wallets/WalletContractV1R2.ts b/src/wallets/WalletContractV1R2.ts index 2c6cb02f..ae961d0e 100644 --- a/src/wallets/WalletContractV1R2.ts +++ b/src/wallets/WalletContractV1R2.ts @@ -111,6 +111,7 @@ export class WalletContractV1R2 implements Contract { message: internal({ to: args.to, value: args.value, + extracurrency: args.extracurrency, init: args.init, body: args.body, bounce: args.bounce diff --git a/src/wallets/WalletContractV2R1.spec.ts b/src/wallets/WalletContractV2R1.spec.ts index dd017615..24b70401 100644 --- a/src/wallets/WalletContractV2R1.spec.ts +++ b/src/wallets/WalletContractV2R1.spec.ts @@ -10,6 +10,7 @@ import { randomTestKey } from "../utils/randomTestKey"; import { createTestClient4 } from "../utils/createTestClient4"; import { Address, internal } from "@ton/core"; import { WalletContractV2R1 } from "./WalletContractV2R1"; +import { tillNextSeqno } from "../utils/testWallets"; describe('WalletContractV2R1', () => { it('should has balance and correct address', async () => { @@ -44,5 +45,30 @@ describe('WalletContractV2R1', () => { // Perform transfer await contract.send(transfer); + await tillNextSeqno(contract, seqno); }); -}); \ No newline at end of file + + it('should perform extra currency transfer', async () => { + // Create contract + let client = createTestClient4(); + let key = randomTestKey('v4-treasure'); + let contract = client.open(WalletContractV2R1.create({ workchain: 0, publicKey: key.publicKey })); + + // Prepare transfer + let seqno = await contract.getSeqno(); + let transfer = contract.createTransfer({ + seqno, + secretKey: key.secretKey, + messages: [internal({ + to: 'kQD6oPnzaaAMRW24R8F0_nlSsJQni0cGHntR027eT9_sgtwt', + value: '0.01', + extracurrency: {100: BigInt(10 ** 6)}, + body: 'Hello, extra currency v2r1!' + })] + }); + + // Perform transfer + await contract.send(transfer); + await tillNextSeqno(contract, seqno); + }); +}); diff --git a/src/wallets/WalletContractV2R1.ts b/src/wallets/WalletContractV2R1.ts index 09b3d42a..a35f2dbf 100644 --- a/src/wallets/WalletContractV2R1.ts +++ b/src/wallets/WalletContractV2R1.ts @@ -114,6 +114,7 @@ export class WalletContractV2R1 implements Contract { messages: [internal({ to: args.to, value: args.value, + extracurrency: args.extracurrency, init: args.init, body: args.body, bounce: args.bounce diff --git a/src/wallets/WalletContractV2R2.spec.ts b/src/wallets/WalletContractV2R2.spec.ts index 460d3967..e9073b85 100644 --- a/src/wallets/WalletContractV2R2.spec.ts +++ b/src/wallets/WalletContractV2R2.spec.ts @@ -10,6 +10,7 @@ import { randomTestKey } from "../utils/randomTestKey"; import { createTestClient4 } from "../utils/createTestClient4"; import { Address, internal } from "@ton/core"; import { WalletContractV2R2 } from "./WalletContractV2R2"; +import { tillNextSeqno } from "../utils/testWallets"; describe('WalletContractV2R2', () => { it('should has balance and correct address', async () => { @@ -44,5 +45,32 @@ describe('WalletContractV2R2', () => { // Perform transfer await contract.send(transfer); + await tillNextSeqno(contract, seqno); }); -}); \ No newline at end of file + + it('should perfrorm extra currency transfer', async () => { + // Create contract + let client = createTestClient4(); + let key = randomTestKey('v4-treasure'); + let contract = client.open(WalletContractV2R2.create({ workchain: 0, publicKey: key.publicKey })); + + // Prepare transfer + let seqno = await contract.getSeqno(); + let transfer = contract.createTransfer({ + seqno, + secretKey: key.secretKey, + messages: [internal({ + to: 'kQD6oPnzaaAMRW24R8F0_nlSsJQni0cGHntR027eT9_sgtwt', + value: '0.01', + extracurrency: {100: BigInt(10 ** 6)}, + body: 'Hello, extra currency v2r2!' + })] + }); + + // Perform transfer + await contract.send(transfer); + await tillNextSeqno(contract, seqno); + + + }); +}); diff --git a/src/wallets/WalletContractV2R2.ts b/src/wallets/WalletContractV2R2.ts index 2603d419..ef3f0fc0 100644 --- a/src/wallets/WalletContractV2R2.ts +++ b/src/wallets/WalletContractV2R2.ts @@ -114,6 +114,7 @@ export class WalletContractV2R2 implements Contract { messages: [internal({ to: args.to, value: args.value, + extracurrency: args.extracurrency, init: args.init, body: args.body, bounce: args.bounce diff --git a/src/wallets/WalletContractV3R1.spec.ts b/src/wallets/WalletContractV3R1.spec.ts index 69bc064f..26371a3c 100644 --- a/src/wallets/WalletContractV3R1.spec.ts +++ b/src/wallets/WalletContractV3R1.spec.ts @@ -10,6 +10,7 @@ import { randomTestKey } from "../utils/randomTestKey"; import { createTestClient4 } from "../utils/createTestClient4"; import { Address, internal } from "@ton/core"; import { WalletContractV3R1 } from "./WalletContractV3R1"; +import { tillNextSeqno } from "../utils/testWallets"; describe('WalletContractV3R1', () => { it('should has balance and correct address', async () => { @@ -44,5 +45,31 @@ describe('WalletContractV3R1', () => { // Perform transfer await contract.send(transfer); + await tillNextSeqno(contract, seqno); }); -}); \ No newline at end of file + + it('should perform extra currency transfer', async () => { + // Create contract + let client = createTestClient4(); + let key = randomTestKey('v4-treasure'); + let contract = client.open(WalletContractV3R1.create({ workchain: 0, publicKey: key.publicKey })); + + // Prepare transfer + let seqno = await contract.getSeqno(); + let transfer = contract.createTransfer({ + seqno, + secretKey: key.secretKey, + messages: [internal({ + to: 'kQD6oPnzaaAMRW24R8F0_nlSsJQni0cGHntR027eT9_sgtwt', + value: '0.05', + extracurrency: {100: BigInt(10 ** 6)}, + body: 'Hello, extra currency v3r1!' + })] + }); + + // Perform transfer + await contract.send(transfer); + await tillNextSeqno(contract, seqno); + }); + +}); diff --git a/src/wallets/WalletContractV3R1.ts b/src/wallets/WalletContractV3R1.ts index 927be6e2..fabb8ac9 100644 --- a/src/wallets/WalletContractV3R1.ts +++ b/src/wallets/WalletContractV3R1.ts @@ -113,6 +113,7 @@ export class WalletContractV3R1 implements Contract { messages: [internal({ to: args.to, value: args.value, + extracurrency: args.extracurrency, init: args.init, body: args.body, bounce: args.bounce diff --git a/src/wallets/WalletContractV3R2.spec.ts b/src/wallets/WalletContractV3R2.spec.ts index 17137db1..2fa5b6bd 100644 --- a/src/wallets/WalletContractV3R2.spec.ts +++ b/src/wallets/WalletContractV3R2.spec.ts @@ -10,6 +10,7 @@ import { randomTestKey } from "../utils/randomTestKey"; import { createTestClient4 } from "../utils/createTestClient4"; import { Address, internal } from "@ton/core"; import { WalletContractV3R2 } from "./WalletContractV3R2"; +import { tillNextSeqno } from "../utils/testWallets"; describe('WalletContractV3R1', () => { @@ -46,5 +47,33 @@ describe('WalletContractV3R1', () => { // Perform transfer await contract.send(transfer); + + await tillNextSeqno(contract, seqno); + }); + + it('should perform extra currency transfer', async () => { + // Create contract + let client = createTestClient4(); + let key = randomTestKey('v4-treasure'); + let contract = client.open(WalletContractV3R2.create({ workchain: 0, publicKey: key.publicKey })); + + // Prepare transfer + let seqno = await contract.getSeqno(); + let transfer = contract.createTransfer({ + seqno, + secretKey: key.secretKey, + messages: [internal({ + to: 'kQD6oPnzaaAMRW24R8F0_nlSsJQni0cGHntR027eT9_sgtwt', + value: '0.05', + extracurrency: {100: BigInt(10 ** 6)}, + body: 'Hello, extra currency v3r2!' + })] + }); + + // Perform transfer + await contract.send(transfer); + + await tillNextSeqno(contract, seqno); + }); -}); \ No newline at end of file +}); diff --git a/src/wallets/WalletContractV3R2.ts b/src/wallets/WalletContractV3R2.ts index 70f72798..573cb8c5 100644 --- a/src/wallets/WalletContractV3R2.ts +++ b/src/wallets/WalletContractV3R2.ts @@ -113,6 +113,7 @@ export class WalletContractV3R2 implements Contract { messages: [internal({ to: args.to, value: args.value, + extracurrency: args.extracurrency, init: args.init, body: args.body, bounce: args.bounce diff --git a/src/wallets/WalletContractV4.spec.ts b/src/wallets/WalletContractV4.spec.ts index 0c69cc11..5748b295 100644 --- a/src/wallets/WalletContractV4.spec.ts +++ b/src/wallets/WalletContractV4.spec.ts @@ -7,6 +7,7 @@ */ import { randomTestKey } from "../utils/randomTestKey"; +import { tillNextSeqno } from "../utils/testWallets"; import { WalletContractV4 } from "./WalletContractV4"; import { createTestClient4 } from "../utils/createTestClient4"; import { Address, internal } from "@ton/core"; @@ -50,5 +51,33 @@ describe('WalletContractV4', () => { // Perform transfer await contract.send(transfer); + // Awaiting update + await tillNextSeqno(contract, seqno); }); -}); \ No newline at end of file + + it('should perform extra currency transfer', async () => { + // Create contract + let client = createTestClient4(); + let key = randomTestKey('v4-treasure'); + let contract = client.open(WalletContractV4.create({ workchain: 0, publicKey: key.publicKey })); + + // Prepare transfer + let seqno = await contract.getSeqno(); + let transfer = contract.createTransfer({ + seqno, + secretKey: key.secretKey, + messages: [internal({ + to: 'kQD6oPnzaaAMRW24R8F0_nlSsJQni0cGHntR027eT9_sgtwt', + value: '0.01', + extracurrency: {100: BigInt(10 ** 6)}, + body: 'Hello extra currency v4' + })] + }); + + // Perform transfer + await contract.send(transfer); + // Awaiting update + await tillNextSeqno(contract, seqno); + + }); +}); diff --git a/src/wallets/WalletContractV4.ts b/src/wallets/WalletContractV4.ts index 5cf40070..b0ab4227 100644 --- a/src/wallets/WalletContractV4.ts +++ b/src/wallets/WalletContractV4.ts @@ -124,6 +124,7 @@ export class WalletContractV4 implements Contract { messages: [internal({ to: args.to, value: args.value, + extracurrency: args.extracurrency, init: args.init, body: args.body, bounce: args.bounce diff --git a/src/wallets/v5beta/WalletContractV5Beta.spec.ts b/src/wallets/v5beta/WalletContractV5Beta.spec.ts index ab4ebe3e..e8a4a0ca 100644 --- a/src/wallets/v5beta/WalletContractV5Beta.spec.ts +++ b/src/wallets/v5beta/WalletContractV5Beta.spec.ts @@ -13,6 +13,7 @@ import {KeyPair, sign} from "@ton/crypto"; import {Buffer} from "buffer"; import {createTestClient4} from "../../utils/createTestClient4"; import {TonClient4} from "../../client/TonClient4"; +import { tillNextSeqno } from "../../utils/testWallets"; const getExtensionsArray = async (wallet: OpenedContract) => { try { @@ -60,8 +61,29 @@ describe('WalletContractV5Beta', () => { }); await wallet.send(transfer); + await tillNextSeqno(wallet, seqno); }); + it('should perform extra currency transfer', async () => { + const seqno = await wallet.getSeqno(); + const transfer = wallet.createTransfer({ + seqno, + secretKey: walletKey.secretKey, + sendMode: SendMode.PAY_GAS_SEPARATELY + SendMode.IGNORE_ERRORS, + messages: [internal({ + bounce: false, + to: 'UQB-2r0kM28L4lmq-4V8ppQGcnO1tXC7FZmbnDzWZVBkp6jE', + value: '0.01', + extracurrency: {100: BigInt(10 ** 6)}, + body: 'Hello extra currency w5beta!' + })] + }); + + await wallet.send(transfer); + await tillNextSeqno(wallet, seqno); + }); + + it('should perform single transfer with async signing', async () => { const seqno = await wallet.getSeqno(); diff --git a/src/wallets/v5beta/WalletContractV5Beta.ts b/src/wallets/v5beta/WalletContractV5Beta.ts index 7438d52c..62760267 100644 --- a/src/wallets/v5beta/WalletContractV5Beta.ts +++ b/src/wallets/v5beta/WalletContractV5Beta.ts @@ -274,6 +274,7 @@ export class WalletContractV5Beta implements Contract { messages: [internal({ to: args.to, value: args.value, + extracurrency: args.extracurrency, init: args.init, body: args.body, bounce: args.bounce diff --git a/src/wallets/v5r1/WalletContractV5R1.spec.ts b/src/wallets/v5r1/WalletContractV5R1.spec.ts index 5bccf395..e04a2dc0 100644 --- a/src/wallets/v5r1/WalletContractV5R1.spec.ts +++ b/src/wallets/v5r1/WalletContractV5R1.spec.ts @@ -13,6 +13,7 @@ import {Buffer} from "buffer"; import {createTestClient4} from "../../utils/createTestClient4"; import {TonClient4} from "../../client/TonClient4"; import {WalletContractV5R1} from "./WalletContractV5R1"; +import { tillNextSeqno } from "../../utils/testWallets"; const getExtensionsArray = async (wallet: OpenedContract) => { try { @@ -63,6 +64,26 @@ describe('WalletContractV5R1', () => { expect(sendMode).toBe(SendMode.PAY_GAS_SEPARATELY + SendMode.IGNORE_ERRORS); await wallet.send(transfer); + await tillNextSeqno(wallet, seqno); + }); + + it('should perform extra currency transfer', async () => { + const seqno = await wallet.getSeqno(); + const transfer = wallet.createTransfer({ + seqno, + secretKey: walletKey.secretKey, + sendMode: SendMode.PAY_GAS_SEPARATELY + SendMode.IGNORE_ERRORS, + messages: [internal({ + bounce: false, + to: 'UQB-2r0kM28L4lmq-4V8ppQGcnO1tXC7FZmbnDzWZVBkp6jE', + value: '0.01', + extracurrency: {100: BigInt(10 ** 6)}, + body: 'Hello extra currency w5r1!' + })] + }); + + await wallet.send(transfer); + await tillNextSeqno(wallet, seqno); }); it('should perform single transfer with async signing', async () => { diff --git a/src/wallets/v5r1/WalletContractV5R1.ts b/src/wallets/v5r1/WalletContractV5R1.ts index 0b8a8e5f..0447d1c3 100644 --- a/src/wallets/v5r1/WalletContractV5R1.ts +++ b/src/wallets/v5r1/WalletContractV5R1.ts @@ -280,6 +280,7 @@ export class WalletContractV5R1 implements Contract { messages: [internal({ to: args.to, value: args.value, + extracurrency: args.extracurrency, init: args.init, body: args.body, bounce: args.bounce