@ton/ton 13.5.1 → 13.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/client/TonClient.d.ts +1 -19
  2. package/dist/client/TonClient.js +49 -24
  3. package/dist/client/TonClient4.d.ts +843 -0
  4. package/dist/client/TonClient4.js +138 -8
  5. package/dist/client/TonClient4.spec.js +7 -1
  6. package/dist/client/api/HttpApi.d.ts +17 -0
  7. package/dist/client/api/HttpApi.js +5 -2
  8. package/dist/config/ConfigParser.d.ts +622 -0
  9. package/dist/config/ConfigParser.js +711 -0
  10. package/dist/config/ConfigParser.spec.d.ts +8 -0
  11. package/dist/config/ConfigParser.spec.js +97 -0
  12. package/dist/elector/ElectorContract.d.ts +51 -0
  13. package/dist/elector/ElectorContract.js +192 -0
  14. package/dist/elector/ElectorContract.spec.d.ts +8 -0
  15. package/dist/elector/ElectorContract.spec.js +104 -0
  16. package/dist/index.d.ts +3 -0
  17. package/dist/index.js +44 -1
  18. package/dist/multisig/MultisigWallet.d.ts +1 -0
  19. package/dist/multisig/MultisigWallet.js +14 -0
  20. package/dist/multisig/MultisigWallet.spec.js +18 -0
  21. package/dist/utils/fees.d.ts +25 -0
  22. package/dist/utils/fees.js +105 -0
  23. package/dist/utils/fees.spec.d.ts +1 -0
  24. package/dist/utils/fees.spec.js +83 -0
  25. package/dist/wallets/WalletContractV5.d.ts +111 -0
  26. package/dist/wallets/WalletContractV5.js +197 -0
  27. package/dist/wallets/WalletContractV5.spec.d.ts +8 -0
  28. package/dist/wallets/WalletContractV5.spec.js +151 -0
  29. package/dist/wallets/WalletV5Utils.d.ts +31 -0
  30. package/dist/wallets/WalletV5Utils.js +115 -0
  31. package/dist/wallets/WalletV5Utils.spec.d.ts +1 -0
  32. package/dist/wallets/WalletV5Utils.spec.js +192 -0
  33. package/dist/wallets/signing/createWalletTransfer.d.ts +7 -1
  34. package/dist/wallets/signing/createWalletTransfer.js +33 -1
  35. package/package.json +4 -4
  36. package/CHANGELOG.md +0 -133
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.computeMessageForwardFees = exports.computeExternalMessageFees = exports.computeGasPrices = exports.computeFwdFees = exports.computeStorageFees = void 0;
4
+ const core_1 = require("@ton/core");
5
+ //
6
+ // Source: https://github.com/ton-foundation/ton/blob/ae5c0720143e231c32c3d2034cfe4e533a16d969/crypto/block/transaction.cpp#L425
7
+ //
8
+ function computeStorageFees(data) {
9
+ const { lastPaid, now, storagePrices, storageStat, special, masterchain } = data;
10
+ if (now <= lastPaid || storagePrices.length === 0 || now < storagePrices[0].utime_since || special) {
11
+ return BigInt(0);
12
+ }
13
+ let upto = Math.max(lastPaid, storagePrices[0].utime_since);
14
+ let total = BigInt(0);
15
+ for (let i = 0; i < storagePrices.length && upto < now; i++) {
16
+ let valid_until = (i < storagePrices.length - 1 ? Math.min(now, storagePrices[i + 1].utime_since) : now);
17
+ let payment = BigInt(0);
18
+ if (upto < valid_until) {
19
+ let delta = valid_until - upto;
20
+ payment += (BigInt(storageStat.cells) * (masterchain ? storagePrices[i].mc_cell_price_ps : storagePrices[i].cell_price_ps));
21
+ payment += (BigInt(storageStat.bits) * (masterchain ? storagePrices[i].mc_bit_price_ps : storagePrices[i].bit_price_ps));
22
+ payment = payment * BigInt(delta);
23
+ }
24
+ upto = valid_until;
25
+ total += payment;
26
+ }
27
+ return shr16ceil(total);
28
+ }
29
+ exports.computeStorageFees = computeStorageFees;
30
+ //
31
+ // Source: https://github.com/ton-foundation/ton/blob/ae5c0720143e231c32c3d2034cfe4e533a16d969/crypto/block/transaction.cpp#L1218
32
+ //
33
+ function computeFwdFees(msgPrices, cells, bits) {
34
+ return msgPrices.lumpPrice + (shr16ceil(msgPrices.bitPrice * bits + (msgPrices.cellPrice * cells)));
35
+ }
36
+ exports.computeFwdFees = computeFwdFees;
37
+ //
38
+ // Source: https://github.com/ton-foundation/ton/blob/ae5c0720143e231c32c3d2034cfe4e533a16d969/crypto/block/transaction.cpp#L761
39
+ //
40
+ function computeGasPrices(gasUsed, prices) {
41
+ if (gasUsed <= prices.flatLimit) {
42
+ return prices.flatPrice;
43
+ }
44
+ else {
45
+ // td::rshift(gas_price256 * (gas_used - cfg.flat_gas_limit), 16, 1) + cfg.flat_gas_price
46
+ return prices.flatPrice + ((prices.price * (gasUsed - prices.flatLimit)) >> 16n);
47
+ }
48
+ }
49
+ exports.computeGasPrices = computeGasPrices;
50
+ //
51
+ // Source: https://github.com/ton-foundation/ton/blob/ae5c0720143e231c32c3d2034cfe4e533a16d969/crypto/block/transaction.cpp#L530
52
+ //
53
+ function computeExternalMessageFees(msgPrices, cell) {
54
+ // Collect stats
55
+ let storageStats = collectCellStats(cell);
56
+ storageStats.bits -= cell.bits.length;
57
+ storageStats.cells -= 1;
58
+ return computeFwdFees(msgPrices, BigInt(storageStats.cells), BigInt(storageStats.bits));
59
+ }
60
+ exports.computeExternalMessageFees = computeExternalMessageFees;
61
+ function computeMessageForwardFees(msgPrices, cell) {
62
+ let msg = (0, core_1.loadMessageRelaxed)(cell.beginParse());
63
+ let storageStats = { bits: 0, cells: 0 };
64
+ // Init
65
+ if (msg.init) {
66
+ const rawBuilder = new core_1.Cell().asBuilder();
67
+ (0, core_1.storeStateInit)(msg.init)(rawBuilder);
68
+ const raw = rawBuilder.endCell();
69
+ let c = collectCellStats(raw);
70
+ c.bits -= raw.bits.length;
71
+ c.cells -= 1;
72
+ storageStats.bits += c.bits;
73
+ storageStats.cells += c.cells;
74
+ }
75
+ // Body
76
+ let bc = collectCellStats(msg.body);
77
+ bc.bits -= msg.body.bits.length;
78
+ bc.cells -= 1;
79
+ storageStats.bits += bc.bits;
80
+ storageStats.cells += bc.cells;
81
+ // NOTE: Extra currencies are ignored for now
82
+ let fees = computeFwdFees(msgPrices, BigInt(storageStats.cells), BigInt(storageStats.bits));
83
+ let res = (fees * BigInt(msgPrices.firstFrac)) >> 16n;
84
+ let remaining = fees - res;
85
+ return { fees: res, remaining };
86
+ }
87
+ exports.computeMessageForwardFees = computeMessageForwardFees;
88
+ function collectCellStats(cell) {
89
+ let bits = cell.bits.length;
90
+ let cells = 1;
91
+ for (let ref of cell.refs) {
92
+ let r = collectCellStats(ref);
93
+ cells += r.cells;
94
+ bits += r.bits;
95
+ }
96
+ return { bits, cells };
97
+ }
98
+ function shr16ceil(src) {
99
+ let rem = src % 65536n;
100
+ let res = src >> 16n;
101
+ if (rem !== 0n) {
102
+ res += 1n;
103
+ }
104
+ return res;
105
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const fees_1 = require("./fees");
4
+ const core_1 = require("@ton/core");
5
+ const WalletContractV4_1 = require("../wallets/WalletContractV4");
6
+ describe('estimateFees', () => {
7
+ it('should estimate fees correctly', () => {
8
+ const config = {
9
+ storage: [{ utime_since: 0, bit_price_ps: BigInt(1), cell_price_ps: BigInt(500), mc_bit_price_ps: BigInt(1000), mc_cell_price_ps: BigInt(500000) }],
10
+ workchain: {
11
+ gas: { flatLimit: BigInt(100), flatGasPrice: BigInt(100000), price: BigInt(65536000) },
12
+ message: { lumpPrice: BigInt(1000000), bitPrice: BigInt(65536000), cellPrice: BigInt(6553600000), firstFrac: 21845 }
13
+ },
14
+ };
15
+ const storageStats = [{
16
+ lastPaid: 1696792239, duePayment: null,
17
+ used: { bits: 6888, cells: 14, publicCells: 0 }
18
+ }];
19
+ const gasUsageByOutMsgs = { 1: 3308, 2: 3950, 3: 4592, 4: 5234 };
20
+ const contract = WalletContractV4_1.WalletContractV4.create({ workchain: 0, publicKey: Buffer.from('MUP3GpbKCQu64L4PIU0QprZxmSUygHcaYKuo2tZYA1c=', 'base64') });
21
+ const body = (0, core_1.comment)('Test message fees estimation');
22
+ const testAddress = core_1.Address.parse('EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N');
23
+ // Create transfer
24
+ let intMessage = (0, core_1.internal)({
25
+ to: testAddress,
26
+ value: 1400000000n,
27
+ bounce: true,
28
+ body,
29
+ });
30
+ let transfer = contract.createTransfer({
31
+ seqno: 14,
32
+ secretKey: Buffer.alloc(64),
33
+ sendMode: core_1.SendMode.IGNORE_ERRORS | core_1.SendMode.PAY_GAS_SEPARATELY,
34
+ messages: [intMessage]
35
+ });
36
+ const externalMessage = (0, core_1.external)({
37
+ to: contract.address,
38
+ body: transfer,
39
+ init: null
40
+ });
41
+ let inMsg = new core_1.Cell().asBuilder();
42
+ (0, core_1.storeMessage)(externalMessage)(inMsg);
43
+ let outMsg = new core_1.Cell().asBuilder();
44
+ (0, core_1.storeMessageRelaxed)(intMessage)(outMsg);
45
+ // Storage fees
46
+ let storageFees = BigInt(0);
47
+ for (let storageStat of storageStats) {
48
+ if (storageStat) {
49
+ const computed = (0, fees_1.computeStorageFees)({
50
+ lastPaid: storageStat.lastPaid,
51
+ masterchain: false,
52
+ now: 1697445678,
53
+ special: false,
54
+ storagePrices: config.storage,
55
+ storageStat: {
56
+ bits: storageStat.used.bits,
57
+ cells: storageStat.used.cells,
58
+ publicCells: storageStat.used.publicCells
59
+ }
60
+ });
61
+ storageFees = storageFees + computed;
62
+ }
63
+ }
64
+ expect((0, core_1.fromNano)(storageFees)).toBe('0.000138473');
65
+ // Calculate import fees
66
+ let importFees = (0, fees_1.computeExternalMessageFees)(config.workchain.message, inMsg.endCell());
67
+ expect((0, core_1.fromNano)(importFees)).toBe('0.001772');
68
+ // Any transaction use this amount of gas
69
+ const gasUsed = gasUsageByOutMsgs[1];
70
+ let gasFees = (0, fees_1.computeGasPrices)(BigInt(gasUsed), { flatLimit: config.workchain.gas.flatLimit, flatPrice: config.workchain.gas.flatGasPrice, price: config.workchain.gas.price });
71
+ expect((0, core_1.fromNano)(gasFees)).toBe('0.003308');
72
+ // Total
73
+ let total = BigInt(0);
74
+ total += storageFees;
75
+ total += importFees;
76
+ total += gasFees;
77
+ // Forward fees
78
+ let fwdFees = (0, fees_1.computeMessageForwardFees)(config.workchain.message, outMsg.endCell());
79
+ expect((0, core_1.fromNano)(fwdFees.fees)).toBe('0.000333328');
80
+ total += fwdFees.fees;
81
+ expect((0, core_1.fromNano)(total)).toBe('0.005551801');
82
+ });
83
+ });
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Copyright (c) Whales Corp.
3
+ * All Rights Reserved.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ /// <reference types="node" />
9
+ import { Address, Cell, Contract, ContractProvider, MessageRelaxed, OutAction, Sender, SendMode } from "@ton/core";
10
+ import { Maybe } from "../utils/maybe";
11
+ import { OutActionExtended, WalletId } from "./WalletV5Utils";
12
+ export declare type Wallet5BasicSendArgs = {
13
+ seqno: number;
14
+ sendMode?: Maybe<SendMode>;
15
+ timeout?: Maybe<number>;
16
+ };
17
+ export declare type SingedAuthWallet5SendArgs = Wallet5BasicSendArgs & {
18
+ secretKey: Buffer;
19
+ };
20
+ export declare type ExtensionAuthWallet5SendArgs = Wallet5BasicSendArgs & {};
21
+ export declare type Wallet5SendArgs = SingedAuthWallet5SendArgs | ExtensionAuthWallet5SendArgs;
22
+ export declare class WalletContractV5 implements Contract {
23
+ readonly walletId: WalletId;
24
+ readonly publicKey: Buffer;
25
+ static opCodes: {
26
+ auth_extension: number;
27
+ auth_signed: number;
28
+ };
29
+ static create(args: {
30
+ walletId?: Partial<WalletId>;
31
+ publicKey: Buffer;
32
+ }): WalletContractV5;
33
+ readonly address: Address;
34
+ readonly init: {
35
+ data: Cell;
36
+ code: Cell;
37
+ };
38
+ private constructor();
39
+ /**
40
+ * Get Wallet Balance
41
+ */
42
+ getBalance(provider: ContractProvider): Promise<bigint>;
43
+ /**
44
+ * Get Wallet Seqno
45
+ */
46
+ getSeqno(provider: ContractProvider): Promise<number>;
47
+ /**
48
+ * Get Wallet Extensions
49
+ */
50
+ getExtensions(provider: ContractProvider): Promise<Cell | null>;
51
+ /**
52
+ * Get Wallet Extensions
53
+ */
54
+ getExtensionsArray(provider: ContractProvider): Promise<Address[]>;
55
+ /**
56
+ * Send signed transfer
57
+ */
58
+ send(provider: ContractProvider, message: Cell): Promise<void>;
59
+ /**
60
+ * Sign and send transfer
61
+ */
62
+ sendTransfer(provider: ContractProvider, args: Wallet5SendArgs & {
63
+ messages: MessageRelaxed[];
64
+ }): Promise<void>;
65
+ /**
66
+ * Sign and send add extension request
67
+ */
68
+ sendAddExtension(provider: ContractProvider, args: Wallet5SendArgs & {
69
+ extensionAddress: Address;
70
+ }): Promise<void>;
71
+ /**
72
+ * Sign and send remove extension request
73
+ */
74
+ sendRemoveExtension(provider: ContractProvider, args: Wallet5SendArgs & {
75
+ extensionAddress: Address;
76
+ }): Promise<void>;
77
+ /**
78
+ * Sign and send request
79
+ */
80
+ sendRequest(provider: ContractProvider, args: Wallet5SendArgs & {
81
+ actions: (OutAction | OutActionExtended)[];
82
+ }): Promise<void>;
83
+ /**
84
+ * Create signed transfer
85
+ */
86
+ createTransfer(args: Wallet5SendArgs & {
87
+ messages: MessageRelaxed[];
88
+ }): Cell;
89
+ /**
90
+ * Create signed add extension request
91
+ */
92
+ createAddExtension(args: Wallet5SendArgs & {
93
+ extensionAddress: Address;
94
+ }): Cell;
95
+ /**
96
+ * Create signed remove extension request
97
+ */
98
+ createRemoveExtension(args: Wallet5SendArgs & {
99
+ extensionAddress: Address;
100
+ }): Cell;
101
+ /**
102
+ * Create signed request
103
+ */
104
+ createRequest(args: Wallet5SendArgs & {
105
+ actions: (OutAction | OutActionExtended)[];
106
+ }): Cell;
107
+ /**
108
+ * Create sender
109
+ */
110
+ sender(provider: ContractProvider, secretKey: Buffer): Sender;
111
+ }
@@ -0,0 +1,197 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) Whales Corp.
4
+ * All Rights Reserved.
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.WalletContractV5 = void 0;
11
+ const core_1 = require("@ton/core");
12
+ const createWalletTransfer_1 = require("./signing/createWalletTransfer");
13
+ const WalletV5Utils_1 = require("./WalletV5Utils");
14
+ class WalletContractV5 {
15
+ constructor(walletId, publicKey) {
16
+ this.walletId = walletId;
17
+ this.publicKey = publicKey;
18
+ this.walletId = walletId;
19
+ // Build initial code and data
20
+ let code = core_1.Cell.fromBoc(Buffer.from('te6cckEBAQEAIwAIQgLND3fEdsoVqej99mmdJbaOAOcmH9K3vkNG64R7FPAsl9kimVw=', 'base64'))[0];
21
+ let data = (0, core_1.beginCell)()
22
+ .storeUint(0, 32) // Seqno
23
+ .store((0, WalletV5Utils_1.storeWalletId)(this.walletId))
24
+ .storeBuffer(this.publicKey)
25
+ .storeBit(0) // Empty plugins dict
26
+ .endCell();
27
+ this.init = { code, data };
28
+ this.address = (0, core_1.contractAddress)(this.walletId.workChain, { code, data });
29
+ }
30
+ static create(args) {
31
+ const walletId = {
32
+ networkGlobalId: args.walletId?.networkGlobalId ?? -239,
33
+ workChain: args?.walletId?.workChain ?? 0,
34
+ subwalletNumber: args?.walletId?.subwalletNumber ?? 0,
35
+ walletVersion: args?.walletId?.walletVersion ?? 'v5'
36
+ };
37
+ return new WalletContractV5(walletId, args.publicKey);
38
+ }
39
+ /**
40
+ * Get Wallet Balance
41
+ */
42
+ async getBalance(provider) {
43
+ let state = await provider.getState();
44
+ return state.balance;
45
+ }
46
+ /**
47
+ * Get Wallet Seqno
48
+ */
49
+ async getSeqno(provider) {
50
+ let state = await provider.getState();
51
+ if (state.state.type === 'active') {
52
+ let res = await provider.get('seqno', []);
53
+ return res.stack.readNumber();
54
+ }
55
+ else {
56
+ return 0;
57
+ }
58
+ }
59
+ /**
60
+ * Get Wallet Extensions
61
+ */
62
+ async getExtensions(provider) {
63
+ let state = await provider.getState();
64
+ if (state.state.type === 'active') {
65
+ const result = await provider.get('get_extensions', []);
66
+ return result.stack.readCellOpt();
67
+ }
68
+ else {
69
+ return null;
70
+ }
71
+ }
72
+ /**
73
+ * Get Wallet Extensions
74
+ */
75
+ async getExtensionsArray(provider) {
76
+ const extensions = await this.getExtensions(provider);
77
+ if (!extensions) {
78
+ return [];
79
+ }
80
+ const dict = core_1.Dictionary.loadDirect(core_1.Dictionary.Keys.BigUint(256), core_1.Dictionary.Values.BigInt(8), extensions);
81
+ return dict.keys().map(key => {
82
+ const wc = dict.get(key);
83
+ const addressHex = key ^ (wc + 1n);
84
+ return core_1.Address.parseRaw(`${wc}:${addressHex.toString(16)}`);
85
+ });
86
+ }
87
+ /**
88
+ * Send signed transfer
89
+ */
90
+ async send(provider, message) {
91
+ await provider.external(message);
92
+ }
93
+ /**
94
+ * Sign and send transfer
95
+ */
96
+ async sendTransfer(provider, args) {
97
+ const transfer = this.createTransfer(args);
98
+ await this.send(provider, transfer);
99
+ }
100
+ /**
101
+ * Sign and send add extension request
102
+ */
103
+ async sendAddExtension(provider, args) {
104
+ const request = this.createAddExtension(args);
105
+ await this.send(provider, request);
106
+ }
107
+ /**
108
+ * Sign and send remove extension request
109
+ */
110
+ async sendRemoveExtension(provider, args) {
111
+ const request = this.createRemoveExtension(args);
112
+ await this.send(provider, request);
113
+ }
114
+ /**
115
+ * Sign and send request
116
+ */
117
+ async sendRequest(provider, args) {
118
+ const request = this.createRequest(args);
119
+ await this.send(provider, request);
120
+ }
121
+ /**
122
+ * Create signed transfer
123
+ */
124
+ createTransfer(args) {
125
+ const { messages, ...rest } = args;
126
+ const sendMode = args.sendMode ?? core_1.SendMode.PAY_GAS_SEPARATELY;
127
+ const actions = messages.map(message => ({ type: 'sendMsg', mode: sendMode, outMsg: message }));
128
+ return this.createRequest({
129
+ ...rest,
130
+ actions
131
+ });
132
+ }
133
+ /**
134
+ * Create signed add extension request
135
+ */
136
+ createAddExtension(args) {
137
+ const { extensionAddress, ...rest } = args;
138
+ return this.createRequest({
139
+ actions: [{
140
+ type: 'addExtension',
141
+ address: extensionAddress
142
+ }],
143
+ ...rest
144
+ });
145
+ }
146
+ /**
147
+ * Create signed remove extension request
148
+ */
149
+ createRemoveExtension(args) {
150
+ const { extensionAddress, ...rest } = args;
151
+ return this.createRequest({
152
+ actions: [{
153
+ type: 'removeExtension',
154
+ address: extensionAddress
155
+ }],
156
+ ...rest
157
+ });
158
+ }
159
+ /**
160
+ * Create signed request
161
+ */
162
+ createRequest(args) {
163
+ return (0, createWalletTransfer_1.createWalletTransferV5)({
164
+ ...args,
165
+ sendMode: args.sendMode ?? core_1.SendMode.PAY_GAS_SEPARATELY,
166
+ walletId: (0, WalletV5Utils_1.storeWalletId)(this.walletId)
167
+ });
168
+ }
169
+ /**
170
+ * Create sender
171
+ */
172
+ sender(provider, secretKey) {
173
+ return {
174
+ send: async (args) => {
175
+ let seqno = await this.getSeqno(provider);
176
+ let transfer = this.createTransfer({
177
+ seqno,
178
+ secretKey,
179
+ sendMode: args.sendMode,
180
+ messages: [(0, core_1.internal)({
181
+ to: args.to,
182
+ value: args.value,
183
+ init: args.init,
184
+ body: args.body,
185
+ bounce: args.bounce
186
+ })]
187
+ });
188
+ await this.send(provider, transfer);
189
+ }
190
+ };
191
+ }
192
+ }
193
+ exports.WalletContractV5 = WalletContractV5;
194
+ WalletContractV5.opCodes = {
195
+ auth_extension: 0x6578746e,
196
+ auth_signed: 0x7369676e
197
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Copyright (c) Whales Corp.
3
+ * All Rights Reserved.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ export {};
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) Whales Corp.
4
+ * All Rights Reserved.
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ const randomTestKey_1 = require("../utils/randomTestKey");
11
+ const core_1 = require("@ton/core");
12
+ const WalletContractV5_1 = require("./WalletContractV5");
13
+ const createTestClient_1 = require("../utils/createTestClient");
14
+ const getExtensionsArray = async (wallet) => {
15
+ try {
16
+ return await wallet.getExtensionsArray();
17
+ }
18
+ catch (e) {
19
+ // Handle toncenter bug. Toncenter incorrectly returns 'list' in the stack in case of empty extensions dict
20
+ if (e instanceof Error && e.message === 'Unsupported stack item type: list') {
21
+ return [];
22
+ }
23
+ throw e;
24
+ }
25
+ };
26
+ describe('WalletContractV5', () => {
27
+ let client;
28
+ let walletKey;
29
+ let wallet;
30
+ beforeEach(() => {
31
+ client = (0, createTestClient_1.createTestClient)();
32
+ walletKey = (0, randomTestKey_1.randomTestKey)('v5-treasure');
33
+ wallet = client.open(WalletContractV5_1.WalletContractV5.create({ walletId: { networkGlobalId: -3 }, publicKey: walletKey.publicKey }));
34
+ });
35
+ it('should has balance and correct address', async () => {
36
+ const balance = await wallet.getBalance();
37
+ expect(wallet.address.equals(core_1.Address.parse('EQDv2B0jPmJZ1j-ne3Ko64eGqfYZRHGQbfSE5pUWVvUdQmDH'))).toBeTruthy();
38
+ expect(balance > 0n).toBe(true);
39
+ });
40
+ it('should perform single transfer', async () => {
41
+ const seqno = await wallet.getSeqno();
42
+ const transfer = wallet.createTransfer({
43
+ seqno,
44
+ secretKey: walletKey.secretKey,
45
+ messages: [(0, core_1.internal)({
46
+ to: 'EQDQ0PRYSWmW-v6LVHNYq5Uelpr5f7Ct7awG7Lao2HImrCzn',
47
+ value: '0.01',
48
+ body: 'Hello world single transfer!'
49
+ })]
50
+ });
51
+ await wallet.send(transfer);
52
+ });
53
+ it('should perform double transfer', async () => {
54
+ const seqno = await wallet.getSeqno();
55
+ const transfer = wallet.createTransfer({
56
+ seqno,
57
+ secretKey: walletKey.secretKey,
58
+ messages: [(0, core_1.internal)({
59
+ to: 'EQDQ0PRYSWmW-v6LVHNYq5Uelpr5f7Ct7awG7Lao2HImrCzn',
60
+ value: '0.01',
61
+ body: 'Hello world to extension'
62
+ }), (0, core_1.internal)({
63
+ to: 'EQAtHiE_vEyAogU1rHcz3uzp64h-yqeFJ2S2ChkKNwygLMk3',
64
+ value: '0.02',
65
+ body: 'Hello world to relayer'
66
+ })]
67
+ });
68
+ await wallet.send(transfer);
69
+ });
70
+ it('should add extension', async () => {
71
+ const extensionKey = (0, randomTestKey_1.randomTestKey)('v5-treasure-extension');
72
+ const extensionContract = client.open(WalletContractV5_1.WalletContractV5.create({ walletId: { workChain: 0, networkGlobalId: -3 }, publicKey: extensionKey.publicKey }));
73
+ const seqno = await wallet.getSeqno();
74
+ const extensions = await getExtensionsArray(wallet);
75
+ const extensionAlreadyAdded = extensions.some(address => address.equals(extensionContract.address));
76
+ if (!extensionAlreadyAdded) {
77
+ await wallet.sendAddExtension({
78
+ seqno,
79
+ secretKey: walletKey.secretKey,
80
+ extensionAddress: extensionContract.address
81
+ });
82
+ const waitUntilExtensionAdded = async (attempt = 0) => {
83
+ if (attempt >= 10) {
84
+ throw new Error('Extension was not added in 10 blocks');
85
+ }
86
+ const extensions = await getExtensionsArray(wallet);
87
+ const extensionAdded = extensions.some(address => address.equals(extensionContract.address));
88
+ if (extensionAdded) {
89
+ return;
90
+ }
91
+ await new Promise(r => setTimeout(r, 1500));
92
+ return waitUntilExtensionAdded(attempt + 1);
93
+ };
94
+ await waitUntilExtensionAdded();
95
+ }
96
+ const extensionsSeqno = await extensionContract.getSeqno();
97
+ await extensionContract.sendTransfer({
98
+ seqno: extensionsSeqno,
99
+ secretKey: extensionKey.secretKey,
100
+ messages: [(0, core_1.internal)({
101
+ to: wallet.address,
102
+ value: '0.1',
103
+ body: wallet.createTransfer({
104
+ seqno: seqno + 1,
105
+ messages: [(0, core_1.internal)({
106
+ to: 'kQD6oPnzaaAMRW24R8F0_nlSsJQni0cGHntR027eT9_sgtwt',
107
+ value: '0.03',
108
+ body: 'Hello world from plugin'
109
+ })]
110
+ })
111
+ })]
112
+ });
113
+ }, 60000);
114
+ it('should remove extension', async () => {
115
+ const extensionKey = (0, randomTestKey_1.randomTestKey)('v5-treasure-extension');
116
+ const extensionContract = client.open(WalletContractV5_1.WalletContractV5.create({ walletId: { workChain: 0, networkGlobalId: -3 }, publicKey: extensionKey.publicKey }));
117
+ const seqno = await wallet.getSeqno();
118
+ const extensions = await getExtensionsArray(wallet);
119
+ const extensionAlreadyAdded = extensions.some(address => address.equals(extensionContract.address));
120
+ if (extensionAlreadyAdded) {
121
+ await wallet.sendRemoveExtension({
122
+ seqno,
123
+ secretKey: walletKey.secretKey,
124
+ extensionAddress: extensionContract.address
125
+ });
126
+ }
127
+ });
128
+ it('should send internal transfer via relayer', async () => {
129
+ const relaerKey = (0, randomTestKey_1.randomTestKey)('v5-treasure-relayer');
130
+ const relayerContract = client.open(WalletContractV5_1.WalletContractV5.create({ walletId: { workChain: 0, networkGlobalId: -3 }, publicKey: relaerKey.publicKey }));
131
+ const seqno = await wallet.getSeqno();
132
+ const relayerSeqno = await relayerContract.getSeqno();
133
+ await relayerContract.sendTransfer({
134
+ seqno: relayerSeqno,
135
+ secretKey: relaerKey.secretKey,
136
+ messages: [(0, core_1.internal)({
137
+ to: wallet.address,
138
+ value: '0.1',
139
+ body: wallet.createTransfer({
140
+ seqno: seqno,
141
+ secretKey: walletKey.secretKey,
142
+ messages: [(0, core_1.internal)({
143
+ to: 'kQD6oPnzaaAMRW24R8F0_nlSsJQni0cGHntR027eT9_sgtwt',
144
+ value: '0.04',
145
+ body: 'Hello world from relayer'
146
+ })]
147
+ })
148
+ })]
149
+ });
150
+ });
151
+ });
@@ -0,0 +1,31 @@
1
+ /// <reference types="node" />
2
+ import { Address, Builder, Cell, OutAction, Slice } from '@ton/core';
3
+ export interface OutActionSetData {
4
+ type: 'setData';
5
+ newData: Cell;
6
+ }
7
+ export interface OutActionAddExtension {
8
+ type: 'addExtension';
9
+ address: Address;
10
+ }
11
+ export interface OutActionRemoveExtension {
12
+ type: 'removeExtension';
13
+ address: Address;
14
+ }
15
+ export declare type OutActionExtended = OutActionSetData | OutActionAddExtension | OutActionRemoveExtension;
16
+ export declare function storeOutActionExtended(action: OutActionExtended): (builder: Builder) => void;
17
+ export declare function loadOutActionExtended(slice: Slice): OutActionExtended;
18
+ export declare function isOutActionExtended(action: OutAction | OutActionExtended): action is OutActionExtended;
19
+ export declare function storeOutListExtended(actions: (OutActionExtended | OutAction)[]): (builder: Builder) => void;
20
+ export declare function loadOutListExtended(slice: Slice): (OutActionExtended | OutAction)[];
21
+ export interface WalletId {
22
+ readonly walletVersion: 'v5';
23
+ /**
24
+ * -239 is mainnet, -3 is testnet
25
+ */
26
+ readonly networkGlobalId: number;
27
+ readonly workChain: number;
28
+ readonly subwalletNumber: number;
29
+ }
30
+ export declare function loadWalletId(value: bigint | Buffer | Slice): WalletId;
31
+ export declare function storeWalletId(walletId: WalletId): (builder: Builder) => void;