@ton/ton 13.11.2 → 15.0.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.
- package/dist/client/TonClient.js +22 -14
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5 -1
- package/dist/multisig/MultisigWallet.js +1 -1
- package/dist/wallets/WalletContractV3R1.d.ts +2 -7
- package/dist/wallets/WalletContractV3R1.js +2 -9
- package/dist/wallets/WalletContractV3R2.d.ts +2 -7
- package/dist/wallets/WalletContractV3R2.js +2 -9
- package/dist/wallets/WalletContractV3Types.d.ts +12 -0
- package/dist/wallets/WalletContractV3Types.js +2 -0
- package/dist/wallets/WalletContractV4.d.ts +10 -7
- package/dist/wallets/WalletContractV4.js +2 -9
- package/dist/wallets/WalletContractV5Beta.d.ts +3 -0
- package/dist/wallets/WalletContractV5Beta.js +19 -0
- package/dist/wallets/WalletContractV5R1.d.ts +3 -0
- package/dist/wallets/WalletContractV5R1.js +19 -0
- package/dist/wallets/signing/createWalletTransfer.d.ts +24 -15
- package/dist/wallets/signing/createWalletTransfer.js +85 -17
- package/dist/wallets/signing/singer.d.ts +9 -0
- package/dist/wallets/signing/singer.js +21 -0
- package/dist/wallets/v5beta/WalletContractV5Beta.d.ts +130 -0
- package/dist/wallets/v5beta/WalletContractV5Beta.js +211 -0
- package/dist/wallets/v5beta/WalletContractV5Beta.spec.d.ts +8 -0
- package/dist/wallets/v5beta/WalletContractV5Beta.spec.js +298 -0
- package/dist/wallets/v5beta/WalletV5BetaActions.d.ts +6 -0
- package/dist/wallets/v5beta/WalletV5BetaActions.js +92 -0
- package/dist/wallets/v5beta/WalletV5BetaActions.spec.d.ts +1 -0
- package/dist/wallets/v5beta/WalletV5BetaActions.spec.js +166 -0
- package/dist/wallets/v5beta/WalletV5BetaWalletId.d.ts +13 -0
- package/dist/wallets/v5beta/WalletV5BetaWalletId.js +31 -0
- package/dist/wallets/v5beta/WalletV5BetaWalletId.spec.d.ts +1 -0
- package/dist/wallets/v5beta/WalletV5BetaWalletId.spec.js +68 -0
- package/dist/wallets/v5beta/WalletV5OutActions.d.ts +17 -0
- package/dist/wallets/v5beta/WalletV5OutActions.js +11 -0
- package/dist/wallets/v5r1/WalletContractV5R1.d.ts +125 -0
- package/dist/wallets/v5r1/WalletContractV5R1.js +207 -0
- package/dist/wallets/v5r1/WalletContractV5R1.spec.d.ts +8 -0
- package/dist/wallets/v5r1/WalletContractV5R1.spec.js +321 -0
- package/dist/wallets/v5r1/WalletV5R1Actions.d.ts +12 -0
- package/dist/wallets/v5r1/WalletV5R1Actions.js +128 -0
- package/dist/wallets/v5r1/WalletV5R1Actions.spec.d.ts +1 -0
- package/dist/wallets/v5r1/WalletV5R1Actions.spec.js +262 -0
- package/dist/wallets/v5r1/WalletV5R1WalletId.d.ts +47 -0
- package/dist/wallets/v5r1/WalletV5R1WalletId.js +69 -0
- package/dist/wallets/v5r1/WalletV5R1WalletId.spec.d.ts +1 -0
- package/dist/wallets/v5r1/WalletV5R1WalletId.spec.js +72 -0
- package/package.json +1 -1
|
@@ -0,0 +1,211 @@
|
|
|
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.WalletContractV5Beta = void 0;
|
|
11
|
+
const core_1 = require("@ton/core");
|
|
12
|
+
const createWalletTransfer_1 = require("../signing/createWalletTransfer");
|
|
13
|
+
const WalletV5BetaWalletId_1 = require("./WalletV5BetaWalletId");
|
|
14
|
+
/**
|
|
15
|
+
* @deprecated
|
|
16
|
+
* use WalletContractV5R1 instead
|
|
17
|
+
*/
|
|
18
|
+
class WalletContractV5Beta {
|
|
19
|
+
static create(args) {
|
|
20
|
+
const walletId = {
|
|
21
|
+
networkGlobalId: args.walletId?.networkGlobalId ?? -239,
|
|
22
|
+
workchain: args?.walletId?.workchain ?? 0,
|
|
23
|
+
subwalletNumber: args?.walletId?.subwalletNumber ?? 0,
|
|
24
|
+
walletVersion: args?.walletId?.walletVersion ?? 'v5'
|
|
25
|
+
};
|
|
26
|
+
return new WalletContractV5Beta(walletId, args.publicKey);
|
|
27
|
+
}
|
|
28
|
+
constructor(walletId, publicKey) {
|
|
29
|
+
this.walletId = walletId;
|
|
30
|
+
this.publicKey = publicKey;
|
|
31
|
+
this.walletId = walletId;
|
|
32
|
+
// https://github.com/tonkeeper/w5/commit/fa1b372a417a32af104fe1b949b6b31d29cee349 code with library
|
|
33
|
+
let code = core_1.Cell.fromBoc(Buffer.from('te6cckEBAQEAIwAIQgLkzzsvTG1qYeoPK1RH0mZ4WyavNjfbLe7mvNGqgm80Eg3NjhE=', 'base64'))[0];
|
|
34
|
+
let data = (0, core_1.beginCell)()
|
|
35
|
+
.storeInt(0, 33) // Seqno
|
|
36
|
+
.store((0, WalletV5BetaWalletId_1.storeWalletIdV5Beta)(this.walletId))
|
|
37
|
+
.storeBuffer(this.publicKey, 32)
|
|
38
|
+
.storeBit(0) // Empty plugins dict
|
|
39
|
+
.endCell();
|
|
40
|
+
this.init = { code, data };
|
|
41
|
+
this.address = (0, core_1.contractAddress)(this.walletId.workchain, { code, data });
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get Wallet Balance
|
|
45
|
+
*/
|
|
46
|
+
async getBalance(provider) {
|
|
47
|
+
let state = await provider.getState();
|
|
48
|
+
return state.balance;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get Wallet Seqno
|
|
52
|
+
*/
|
|
53
|
+
async getSeqno(provider) {
|
|
54
|
+
let state = await provider.getState();
|
|
55
|
+
if (state.state.type === 'active') {
|
|
56
|
+
let res = await provider.get('seqno', []);
|
|
57
|
+
return res.stack.readNumber();
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
return 0;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get Wallet Extensions
|
|
65
|
+
*/
|
|
66
|
+
async getExtensions(provider) {
|
|
67
|
+
let state = await provider.getState();
|
|
68
|
+
if (state.state.type === 'active') {
|
|
69
|
+
const result = await provider.get('get_extensions', []);
|
|
70
|
+
return result.stack.readCellOpt();
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get Wallet Extensions
|
|
78
|
+
*/
|
|
79
|
+
async getExtensionsArray(provider) {
|
|
80
|
+
const extensions = await this.getExtensions(provider);
|
|
81
|
+
if (!extensions) {
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
const dict = core_1.Dictionary.loadDirect(core_1.Dictionary.Keys.BigUint(256), core_1.Dictionary.Values.BigInt(8), extensions);
|
|
85
|
+
return dict.keys().map(key => {
|
|
86
|
+
const wc = dict.get(key);
|
|
87
|
+
const addressHex = key ^ (wc + 1n);
|
|
88
|
+
return core_1.Address.parseRaw(`${wc}:${addressHex.toString(16).padStart(64, "0")}`);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get is secret-key authentication enabled
|
|
93
|
+
*/
|
|
94
|
+
async getIsSecretKeyAuthEnabled(provider) {
|
|
95
|
+
let res = await provider.get('get_is_signature_auth_allowed', []);
|
|
96
|
+
const result = res.stack.readNumber();
|
|
97
|
+
return result !== 0;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Send signed transfer
|
|
101
|
+
*/
|
|
102
|
+
async send(provider, message) {
|
|
103
|
+
await provider.external(message);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Sign and send transfer
|
|
107
|
+
*/
|
|
108
|
+
async sendTransfer(provider, args) {
|
|
109
|
+
const transfer = await this.createTransfer(args);
|
|
110
|
+
await this.send(provider, transfer);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Sign and send add extension request
|
|
114
|
+
*/
|
|
115
|
+
async sendAddExtension(provider, args) {
|
|
116
|
+
const request = await this.createAddExtension(args);
|
|
117
|
+
await this.send(provider, request);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Sign and send remove extension request
|
|
121
|
+
*/
|
|
122
|
+
async sendRemoveExtension(provider, args) {
|
|
123
|
+
const request = await this.createRemoveExtension(args);
|
|
124
|
+
await this.send(provider, request);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Sign and send actions batch
|
|
128
|
+
*/
|
|
129
|
+
async sendActionsBatch(provider, args) {
|
|
130
|
+
const request = await this.createRequest(args);
|
|
131
|
+
await this.send(provider, request);
|
|
132
|
+
}
|
|
133
|
+
createActions(args) {
|
|
134
|
+
const actions = args.messages.map(message => ({ type: 'sendMsg', mode: args.sendMode, outMsg: message }));
|
|
135
|
+
return actions;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Create signed transfer
|
|
139
|
+
*/
|
|
140
|
+
createTransfer(args) {
|
|
141
|
+
return this.createRequest({
|
|
142
|
+
...args,
|
|
143
|
+
actions: this.createActions({ messages: args.messages, sendMode: args.sendMode })
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Create signed add extension request
|
|
148
|
+
*/
|
|
149
|
+
createAddExtension(args) {
|
|
150
|
+
return this.createRequest({
|
|
151
|
+
...args,
|
|
152
|
+
actions: [{
|
|
153
|
+
type: 'addExtension',
|
|
154
|
+
address: args.extensionAddress
|
|
155
|
+
}]
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Create signed remove extension request
|
|
160
|
+
*/
|
|
161
|
+
createRemoveExtension(args) {
|
|
162
|
+
return this.createRequest({
|
|
163
|
+
...args,
|
|
164
|
+
actions: [{
|
|
165
|
+
type: 'removeExtension',
|
|
166
|
+
address: args.extensionAddress
|
|
167
|
+
}]
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Create signed request or extension auth request
|
|
172
|
+
*/
|
|
173
|
+
createRequest(args) {
|
|
174
|
+
if (args.authType === 'extension') {
|
|
175
|
+
return (0, createWalletTransfer_1.createWalletTransferV5Beta)(args);
|
|
176
|
+
}
|
|
177
|
+
return (0, createWalletTransfer_1.createWalletTransferV5Beta)({
|
|
178
|
+
...args,
|
|
179
|
+
walletId: (0, WalletV5BetaWalletId_1.storeWalletIdV5Beta)(this.walletId)
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Create sender
|
|
184
|
+
*/
|
|
185
|
+
sender(provider, secretKey) {
|
|
186
|
+
return {
|
|
187
|
+
send: async (args) => {
|
|
188
|
+
let seqno = await this.getSeqno(provider);
|
|
189
|
+
let transfer = this.createTransfer({
|
|
190
|
+
seqno,
|
|
191
|
+
secretKey,
|
|
192
|
+
sendMode: args.sendMode ?? core_1.SendMode.PAY_GAS_SEPARATELY + core_1.SendMode.IGNORE_ERRORS,
|
|
193
|
+
messages: [(0, core_1.internal)({
|
|
194
|
+
to: args.to,
|
|
195
|
+
value: args.value,
|
|
196
|
+
init: args.init,
|
|
197
|
+
body: args.body,
|
|
198
|
+
bounce: args.bounce
|
|
199
|
+
})]
|
|
200
|
+
});
|
|
201
|
+
await this.send(provider, transfer);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
exports.WalletContractV5Beta = WalletContractV5Beta;
|
|
207
|
+
WalletContractV5Beta.OpCodes = {
|
|
208
|
+
auth_extension: 0x6578746e,
|
|
209
|
+
auth_signed_external: 0x7369676e,
|
|
210
|
+
auth_signed_internal: 0x73696e74
|
|
211
|
+
};
|
|
@@ -0,0 +1,298 @@
|
|
|
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 WalletContractV5Beta_1 = require("./WalletContractV5Beta");
|
|
13
|
+
const crypto_1 = require("@ton/crypto");
|
|
14
|
+
const createTestClient4_1 = require("../../utils/createTestClient4");
|
|
15
|
+
const getExtensionsArray = async (wallet) => {
|
|
16
|
+
try {
|
|
17
|
+
return await wallet.getExtensionsArray();
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
// Handle toncenter bug. Toncenter incorrectly returns 'list' in the stack in case of empty extensions dict
|
|
21
|
+
if (e && typeof e === 'object' && 'message' in e && e.message === 'Unsupported stack item type: list') {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
throw e;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
describe('WalletContractV5Beta', () => {
|
|
28
|
+
let client;
|
|
29
|
+
let walletKey;
|
|
30
|
+
let wallet;
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
client = (0, createTestClient4_1.createTestClient4)();
|
|
33
|
+
walletKey = (0, randomTestKey_1.randomTestKey)('v5-treasure-1');
|
|
34
|
+
wallet = client.open(WalletContractV5Beta_1.WalletContractV5Beta.create({ walletId: { networkGlobalId: -3 }, publicKey: walletKey.publicKey }));
|
|
35
|
+
});
|
|
36
|
+
it('should has balance and correct address', async () => {
|
|
37
|
+
const balance = await wallet.getBalance();
|
|
38
|
+
expect(wallet.address.equals(core_1.Address.parse('EQAb3OyXDQyjOGf3HOXPXELTF8dhZP0onqMPz6fNQbleRqtY'))).toBeTruthy();
|
|
39
|
+
expect(balance > 0n).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
it('should perform single transfer', async () => {
|
|
42
|
+
const seqno = await wallet.getSeqno();
|
|
43
|
+
const transfer = wallet.createTransfer({
|
|
44
|
+
seqno,
|
|
45
|
+
secretKey: walletKey.secretKey,
|
|
46
|
+
sendMode: core_1.SendMode.PAY_GAS_SEPARATELY + core_1.SendMode.IGNORE_ERRORS,
|
|
47
|
+
messages: [(0, core_1.internal)({
|
|
48
|
+
bounce: false,
|
|
49
|
+
to: 'UQB-2r0kM28L4lmq-4V8ppQGcnO1tXC7FZmbnDzWZVBkp6jE',
|
|
50
|
+
value: '0.01',
|
|
51
|
+
body: 'Hello world single transfer!'
|
|
52
|
+
})]
|
|
53
|
+
});
|
|
54
|
+
await wallet.send(transfer);
|
|
55
|
+
});
|
|
56
|
+
it('should perform single transfer with async signing', async () => {
|
|
57
|
+
const seqno = await wallet.getSeqno();
|
|
58
|
+
const signer = (payload) => new Promise(r => setTimeout(() => {
|
|
59
|
+
const signature = (0, crypto_1.sign)(payload.hash(), walletKey.secretKey);
|
|
60
|
+
r(signature);
|
|
61
|
+
}, 100));
|
|
62
|
+
const transfer = await wallet.createTransfer({
|
|
63
|
+
seqno,
|
|
64
|
+
signer,
|
|
65
|
+
sendMode: core_1.SendMode.PAY_GAS_SEPARATELY + core_1.SendMode.IGNORE_ERRORS,
|
|
66
|
+
messages: [(0, core_1.internal)({
|
|
67
|
+
bounce: false,
|
|
68
|
+
to: 'UQB-2r0kM28L4lmq-4V8ppQGcnO1tXC7FZmbnDzWZVBkp6jE',
|
|
69
|
+
value: '0.01',
|
|
70
|
+
body: 'Hello world single transfer signed async!'
|
|
71
|
+
})]
|
|
72
|
+
});
|
|
73
|
+
await wallet.send(transfer);
|
|
74
|
+
});
|
|
75
|
+
it('should perform double transfer', async () => {
|
|
76
|
+
const seqno = await wallet.getSeqno();
|
|
77
|
+
const transfer = wallet.createTransfer({
|
|
78
|
+
seqno,
|
|
79
|
+
secretKey: walletKey.secretKey,
|
|
80
|
+
sendMode: core_1.SendMode.PAY_GAS_SEPARATELY + core_1.SendMode.IGNORE_ERRORS,
|
|
81
|
+
messages: [(0, core_1.internal)({
|
|
82
|
+
bounce: false,
|
|
83
|
+
to: 'UQB-2r0kM28L4lmq-4V8ppQGcnO1tXC7FZmbnDzWZVBkp6jE',
|
|
84
|
+
value: '0.01',
|
|
85
|
+
body: 'Hello world to extension'
|
|
86
|
+
}), (0, core_1.internal)({
|
|
87
|
+
bounce: false,
|
|
88
|
+
to: 'UQDUyIkKoOR5iZ1Gz60JwKc7wPr3LcdHxOJpVDb9jAKY_pfk',
|
|
89
|
+
value: '0.02',
|
|
90
|
+
body: 'Hello world to relayer'
|
|
91
|
+
})]
|
|
92
|
+
});
|
|
93
|
+
await wallet.send(transfer);
|
|
94
|
+
});
|
|
95
|
+
it('should add extension', async () => {
|
|
96
|
+
const extensionKey = (0, randomTestKey_1.randomTestKey)('v5-treasure-extension');
|
|
97
|
+
const extensionContract = client.open(WalletContractV5Beta_1.WalletContractV5Beta.create({ walletId: { workchain: 0, networkGlobalId: -3 }, publicKey: extensionKey.publicKey }));
|
|
98
|
+
let seqno = await wallet.getSeqno();
|
|
99
|
+
const extensions = await getExtensionsArray(wallet);
|
|
100
|
+
const extensionAlreadyAdded = extensions.some(address => address.equals(extensionContract.address));
|
|
101
|
+
if (!extensionAlreadyAdded) {
|
|
102
|
+
await wallet.sendAddExtension({
|
|
103
|
+
seqno,
|
|
104
|
+
secretKey: walletKey.secretKey,
|
|
105
|
+
extensionAddress: extensionContract.address
|
|
106
|
+
});
|
|
107
|
+
const waitUntilExtensionAdded = async (attempt = 0) => {
|
|
108
|
+
if (attempt >= 20) {
|
|
109
|
+
throw new Error('Extension was not added in 20 blocks');
|
|
110
|
+
}
|
|
111
|
+
const extensions = await getExtensionsArray(wallet);
|
|
112
|
+
const extensionAdded = extensions.some(address => address.equals(extensionContract.address));
|
|
113
|
+
if (extensionAdded) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
await new Promise(r => setTimeout(r, 1500));
|
|
117
|
+
return waitUntilExtensionAdded(attempt + 1);
|
|
118
|
+
};
|
|
119
|
+
await waitUntilExtensionAdded();
|
|
120
|
+
}
|
|
121
|
+
seqno = await wallet.getSeqno();
|
|
122
|
+
const extensionsSeqno = await extensionContract.getSeqno();
|
|
123
|
+
await extensionContract.sendTransfer({
|
|
124
|
+
seqno: extensionsSeqno,
|
|
125
|
+
secretKey: extensionKey.secretKey,
|
|
126
|
+
sendMode: core_1.SendMode.PAY_GAS_SEPARATELY + core_1.SendMode.IGNORE_ERRORS,
|
|
127
|
+
messages: [(0, core_1.internal)({
|
|
128
|
+
to: wallet.address,
|
|
129
|
+
value: '0.02',
|
|
130
|
+
body: wallet.createTransfer({
|
|
131
|
+
seqno: seqno,
|
|
132
|
+
authType: 'extension',
|
|
133
|
+
sendMode: core_1.SendMode.PAY_GAS_SEPARATELY + core_1.SendMode.IGNORE_ERRORS,
|
|
134
|
+
messages: [(0, core_1.internal)({
|
|
135
|
+
bounce: false,
|
|
136
|
+
to: '0QD6oPnzaaAMRW24R8F0_nlSsJQni0cGHntR027eT9_sgoHo',
|
|
137
|
+
value: '0.03',
|
|
138
|
+
body: 'Hello world from plugin'
|
|
139
|
+
})]
|
|
140
|
+
})
|
|
141
|
+
})]
|
|
142
|
+
});
|
|
143
|
+
}, 60000);
|
|
144
|
+
it('should remove extension', async () => {
|
|
145
|
+
const extensionKey = (0, randomTestKey_1.randomTestKey)('v5-treasure-extension');
|
|
146
|
+
const extensionContract = client.open(WalletContractV5Beta_1.WalletContractV5Beta.create({ walletId: { workchain: 0, networkGlobalId: -3 }, publicKey: extensionKey.publicKey }));
|
|
147
|
+
const seqno = await wallet.getSeqno();
|
|
148
|
+
const extensions = await getExtensionsArray(wallet);
|
|
149
|
+
const extensionAlreadyAdded = extensions.some(address => address.equals(extensionContract.address));
|
|
150
|
+
if (extensionAlreadyAdded) {
|
|
151
|
+
await wallet.sendRemoveExtension({
|
|
152
|
+
seqno,
|
|
153
|
+
secretKey: walletKey.secretKey,
|
|
154
|
+
extensionAddress: extensionContract.address
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
it('should send internal transfer via relayer', async () => {
|
|
159
|
+
const relaerKey = (0, randomTestKey_1.randomTestKey)('v5-treasure-relayer');
|
|
160
|
+
const relayerContract = client.open(WalletContractV5Beta_1.WalletContractV5Beta.create({ walletId: { workchain: 0, networkGlobalId: -3 }, publicKey: relaerKey.publicKey }));
|
|
161
|
+
const seqno = await wallet.getSeqno();
|
|
162
|
+
const relayerSeqno = await relayerContract.getSeqno();
|
|
163
|
+
await relayerContract.sendTransfer({
|
|
164
|
+
seqno: relayerSeqno,
|
|
165
|
+
secretKey: relaerKey.secretKey,
|
|
166
|
+
sendMode: core_1.SendMode.PAY_GAS_SEPARATELY + core_1.SendMode.IGNORE_ERRORS,
|
|
167
|
+
messages: [(0, core_1.internal)({
|
|
168
|
+
to: wallet.address,
|
|
169
|
+
value: '0.03',
|
|
170
|
+
body: wallet.createTransfer({
|
|
171
|
+
seqno: seqno,
|
|
172
|
+
secretKey: walletKey.secretKey,
|
|
173
|
+
authType: 'internal',
|
|
174
|
+
sendMode: core_1.SendMode.PAY_GAS_SEPARATELY + core_1.SendMode.IGNORE_ERRORS,
|
|
175
|
+
messages: [(0, core_1.internal)({
|
|
176
|
+
bounce: false,
|
|
177
|
+
to: '0QD2NmD_lH5f5u1Kj3KfGyTvhZSX0Eg6qp2a5IQUKXxOG4so',
|
|
178
|
+
value: '0.04',
|
|
179
|
+
body: 'Hello world from relayer'
|
|
180
|
+
})]
|
|
181
|
+
})
|
|
182
|
+
})]
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
it('should disable secret key auth, send extension-auth tx, and enable it again', async () => {
|
|
186
|
+
/* firstly add an extension that will take the control over the wallet */
|
|
187
|
+
const extensionKey = (0, randomTestKey_1.randomTestKey)('v5-treasure-extension');
|
|
188
|
+
const extensionContract = client.open(WalletContractV5Beta_1.WalletContractV5Beta.create({ walletId: { workchain: 0, networkGlobalId: -3 }, publicKey: extensionKey.publicKey }));
|
|
189
|
+
let seqno = await wallet.getSeqno();
|
|
190
|
+
const extensions = await getExtensionsArray(wallet);
|
|
191
|
+
const extensionAlreadyAdded = extensions.some(address => address.equals(extensionContract.address));
|
|
192
|
+
if (!extensionAlreadyAdded) {
|
|
193
|
+
await wallet.sendAddExtension({
|
|
194
|
+
seqno,
|
|
195
|
+
secretKey: walletKey.secretKey,
|
|
196
|
+
extensionAddress: extensionContract.address
|
|
197
|
+
});
|
|
198
|
+
const waitUntilExtensionAdded = async (attempt = 0) => {
|
|
199
|
+
if (attempt >= 20) {
|
|
200
|
+
throw new Error('Extension was not added in 20 blocks');
|
|
201
|
+
}
|
|
202
|
+
const extensions = await getExtensionsArray(wallet);
|
|
203
|
+
const extensionAdded = extensions.some(address => address.equals(extensionContract.address));
|
|
204
|
+
if (extensionAdded) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
await new Promise(r => setTimeout(r, 1500));
|
|
208
|
+
return waitUntilExtensionAdded(attempt + 1);
|
|
209
|
+
};
|
|
210
|
+
await waitUntilExtensionAdded();
|
|
211
|
+
}
|
|
212
|
+
/* disable secret key auth */
|
|
213
|
+
seqno = await wallet.getSeqno();
|
|
214
|
+
const isInitiallyEnabled = await wallet.getIsSecretKeyAuthEnabled();
|
|
215
|
+
const waitUntilAuthValue = async (target, attempt = 0) => {
|
|
216
|
+
if (attempt >= 20) {
|
|
217
|
+
throw new Error('Auth permissions were not changed in 20 blocks');
|
|
218
|
+
}
|
|
219
|
+
const isEnabledNow = await wallet.getIsSecretKeyAuthEnabled();
|
|
220
|
+
if ((target === 'enabled' && isEnabledNow) || (target === 'disabled' && !isEnabledNow)) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
await new Promise(r => setTimeout(r, 1500));
|
|
224
|
+
return waitUntilAuthValue(target, attempt + 1);
|
|
225
|
+
};
|
|
226
|
+
if (isInitiallyEnabled) {
|
|
227
|
+
await wallet.sendActionsBatch({
|
|
228
|
+
seqno,
|
|
229
|
+
secretKey: walletKey.secretKey,
|
|
230
|
+
actions: [
|
|
231
|
+
{
|
|
232
|
+
type: 'setIsPublicKeyEnabled',
|
|
233
|
+
isEnabled: false
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
});
|
|
237
|
+
await waitUntilAuthValue('disabled');
|
|
238
|
+
}
|
|
239
|
+
/* should fail direct secret-key auth transfer from the wallet */
|
|
240
|
+
seqno = await wallet.getSeqno();
|
|
241
|
+
const transfer = wallet.createTransfer({
|
|
242
|
+
seqno: seqno,
|
|
243
|
+
secretKey: walletKey.secretKey,
|
|
244
|
+
sendMode: core_1.SendMode.PAY_GAS_SEPARATELY + core_1.SendMode.IGNORE_ERRORS,
|
|
245
|
+
messages: [(0, core_1.internal)({
|
|
246
|
+
bounce: false,
|
|
247
|
+
to: 'UQB-2r0kM28L4lmq-4V8ppQGcnO1tXC7FZmbnDzWZVBkp6jE',
|
|
248
|
+
value: '0.01',
|
|
249
|
+
body: 'Hello world single transfer that SHOULD FAIL!'
|
|
250
|
+
})]
|
|
251
|
+
});
|
|
252
|
+
await expect(wallet.send(transfer)).rejects.toThrow();
|
|
253
|
+
/* should perform transfer from the extension and enable auth by secret key */
|
|
254
|
+
const extensionsSeqno = await extensionContract.getSeqno();
|
|
255
|
+
await extensionContract.sendTransfer({
|
|
256
|
+
seqno: extensionsSeqno,
|
|
257
|
+
secretKey: extensionKey.secretKey,
|
|
258
|
+
sendMode: core_1.SendMode.PAY_GAS_SEPARATELY + core_1.SendMode.IGNORE_ERRORS,
|
|
259
|
+
messages: [(0, core_1.internal)({
|
|
260
|
+
to: wallet.address,
|
|
261
|
+
value: '0.03',
|
|
262
|
+
body: wallet.createRequest({
|
|
263
|
+
seqno,
|
|
264
|
+
authType: 'extension',
|
|
265
|
+
actions: [
|
|
266
|
+
{
|
|
267
|
+
type: 'setIsPublicKeyEnabled',
|
|
268
|
+
isEnabled: true
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
type: "sendMsg",
|
|
272
|
+
mode: core_1.SendMode.IGNORE_ERRORS + core_1.SendMode.PAY_GAS_SEPARATELY,
|
|
273
|
+
outMsg: (0, core_1.internal)({
|
|
274
|
+
bounce: false,
|
|
275
|
+
to: '0QD6oPnzaaAMRW24R8F0_nlSsJQni0cGHntR027eT9_sgoHo',
|
|
276
|
+
value: '0.03',
|
|
277
|
+
body: 'Hello world from plugin that controls the wallet!'
|
|
278
|
+
})
|
|
279
|
+
}
|
|
280
|
+
]
|
|
281
|
+
})
|
|
282
|
+
})]
|
|
283
|
+
});
|
|
284
|
+
await waitUntilAuthValue('enabled');
|
|
285
|
+
/* should fail direct secret-key auth transfer from the wallet */
|
|
286
|
+
await wallet.sendTransfer({
|
|
287
|
+
seqno: seqno + 1,
|
|
288
|
+
secretKey: walletKey.secretKey,
|
|
289
|
+
sendMode: core_1.SendMode.PAY_GAS_SEPARATELY + core_1.SendMode.IGNORE_ERRORS,
|
|
290
|
+
messages: [(0, core_1.internal)({
|
|
291
|
+
bounce: false,
|
|
292
|
+
to: 'UQB-2r0kM28L4lmq-4V8ppQGcnO1tXC7FZmbnDzWZVBkp6jE',
|
|
293
|
+
value: '0.01',
|
|
294
|
+
body: 'Hello world single transfer after sk auth enabled!'
|
|
295
|
+
})]
|
|
296
|
+
});
|
|
297
|
+
}, 120000);
|
|
298
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Builder, OutActionSendMsg, Slice } from '@ton/core';
|
|
2
|
+
import { OutActionExtended } from "./WalletV5OutActions";
|
|
3
|
+
export declare function storeOutActionExtendedV5Beta(action: OutActionExtended): (builder: Builder) => void;
|
|
4
|
+
export declare function loadOutActionV5BetaExtended(slice: Slice): OutActionExtended;
|
|
5
|
+
export declare function storeOutListExtendedV5Beta(actions: (OutActionExtended | OutActionSendMsg)[]): (builder: Builder) => void;
|
|
6
|
+
export declare function loadOutListExtendedV5Beta(slice: Slice): (OutActionExtended | OutActionSendMsg)[];
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadOutListExtendedV5Beta = exports.storeOutListExtendedV5Beta = exports.loadOutActionV5BetaExtended = exports.storeOutActionExtendedV5Beta = void 0;
|
|
4
|
+
const core_1 = require("@ton/core");
|
|
5
|
+
const WalletV5OutActions_1 = require("./WalletV5OutActions");
|
|
6
|
+
const outActionSetIsPublicKeyEnabledTag = 0x20cbb95a;
|
|
7
|
+
function storeOutActionSetIsPublicKeyEnabled(action) {
|
|
8
|
+
return (builder) => {
|
|
9
|
+
builder.storeUint(outActionSetIsPublicKeyEnabledTag, 32).storeUint(action.isEnabled ? 1 : 0, 1);
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
const outActionAddExtensionTag = 0x1c40db9f;
|
|
13
|
+
function storeOutActionAddExtension(action) {
|
|
14
|
+
return (builder) => {
|
|
15
|
+
builder.storeUint(outActionAddExtensionTag, 32).storeAddress(action.address);
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
const outActionRemoveExtensionTag = 0x5eaef4a4;
|
|
19
|
+
function storeOutActionRemoveExtension(action) {
|
|
20
|
+
return (builder) => {
|
|
21
|
+
builder.storeUint(outActionRemoveExtensionTag, 32).storeAddress(action.address);
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function storeOutActionExtendedV5Beta(action) {
|
|
25
|
+
switch (action.type) {
|
|
26
|
+
case 'setIsPublicKeyEnabled':
|
|
27
|
+
return storeOutActionSetIsPublicKeyEnabled(action);
|
|
28
|
+
case 'addExtension':
|
|
29
|
+
return storeOutActionAddExtension(action);
|
|
30
|
+
case 'removeExtension':
|
|
31
|
+
return storeOutActionRemoveExtension(action);
|
|
32
|
+
default:
|
|
33
|
+
throw new Error('Unknown action type' + action?.type);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.storeOutActionExtendedV5Beta = storeOutActionExtendedV5Beta;
|
|
37
|
+
function loadOutActionV5BetaExtended(slice) {
|
|
38
|
+
const tag = slice.loadUint(32);
|
|
39
|
+
switch (tag) {
|
|
40
|
+
case outActionSetIsPublicKeyEnabledTag:
|
|
41
|
+
return {
|
|
42
|
+
type: 'setIsPublicKeyEnabled',
|
|
43
|
+
isEnabled: !!slice.loadUint(1)
|
|
44
|
+
};
|
|
45
|
+
case outActionAddExtensionTag:
|
|
46
|
+
return {
|
|
47
|
+
type: 'addExtension',
|
|
48
|
+
address: slice.loadAddress()
|
|
49
|
+
};
|
|
50
|
+
case outActionRemoveExtensionTag:
|
|
51
|
+
return {
|
|
52
|
+
type: 'removeExtension',
|
|
53
|
+
address: slice.loadAddress()
|
|
54
|
+
};
|
|
55
|
+
default:
|
|
56
|
+
throw new Error(`Unknown extended out action tag 0x${tag.toString(16)}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.loadOutActionV5BetaExtended = loadOutActionV5BetaExtended;
|
|
60
|
+
function storeOutListExtendedV5Beta(actions) {
|
|
61
|
+
const [action, ...rest] = actions;
|
|
62
|
+
if (!action || !(0, WalletV5OutActions_1.isOutActionExtended)(action)) {
|
|
63
|
+
if (actions.some(WalletV5OutActions_1.isOutActionExtended)) {
|
|
64
|
+
throw new Error("Can't serialize actions list: all extended actions must be placed before out actions");
|
|
65
|
+
}
|
|
66
|
+
return (builder) => {
|
|
67
|
+
builder
|
|
68
|
+
.storeUint(0, 1)
|
|
69
|
+
.storeRef((0, core_1.beginCell)().store((0, core_1.storeOutList)(actions)).endCell());
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
return (builder) => {
|
|
73
|
+
builder.storeUint(1, 1)
|
|
74
|
+
.store(storeOutActionExtendedV5Beta(action))
|
|
75
|
+
.storeRef((0, core_1.beginCell)().store(storeOutListExtendedV5Beta(rest)).endCell());
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
exports.storeOutListExtendedV5Beta = storeOutListExtendedV5Beta;
|
|
79
|
+
function loadOutListExtendedV5Beta(slice) {
|
|
80
|
+
const actions = [];
|
|
81
|
+
while (slice.loadUint(1)) {
|
|
82
|
+
const action = loadOutActionV5BetaExtended(slice);
|
|
83
|
+
actions.push(action);
|
|
84
|
+
slice = slice.loadRef().beginParse();
|
|
85
|
+
}
|
|
86
|
+
const commonAction = (0, core_1.loadOutList)(slice.loadRef().beginParse());
|
|
87
|
+
if (commonAction.some(i => i.type === 'setCode')) {
|
|
88
|
+
throw new Error("Can't deserialize actions list: only sendMsg actions are allowed for wallet v5");
|
|
89
|
+
}
|
|
90
|
+
return actions.concat(commonAction);
|
|
91
|
+
}
|
|
92
|
+
exports.loadOutListExtendedV5Beta = loadOutListExtendedV5Beta;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|