@meow-laika/ton-lite-client 3.2.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/LICENSE +22 -0
- package/README.md +80 -0
- package/dist/client.d.ts +121 -0
- package/dist/client.js +548 -0
- package/dist/engines/engine.d.ts +31 -0
- package/dist/engines/engine.js +12 -0
- package/dist/engines/roundRobin.d.ts +27 -0
- package/dist/engines/roundRobin.js +115 -0
- package/dist/engines/single.d.ts +37 -0
- package/dist/engines/single.js +186 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +16 -0
- package/dist/liteClientProvider.d.ts +12 -0
- package/dist/liteClientProvider.js +211 -0
- package/dist/main.d.ts +8 -0
- package/dist/main.js +80 -0
- package/dist/parser/parseShards.d.ts +11 -0
- package/dist/parser/parseShards.js +46 -0
- package/dist/schema.d.ts +554 -0
- package/dist/schema.gen.d.ts +8 -0
- package/dist/schema.gen.js +17 -0
- package/dist/schema.js +1595 -0
- package/dist/types.d.ts +70 -0
- package/dist/types.js +2 -0
- package/dist/utils/arrays.d.ts +2 -0
- package/dist/utils/arrays.js +11 -0
- package/dist/utils/bigint.d.ts +3 -0
- package/dist/utils/bigint.js +28 -0
- package/dist/utils/crc16.d.ts +9 -0
- package/dist/utils/crc16.js +56 -0
- package/package.json +36 -0
package/dist/client.js
ADDED
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright
|
|
4
|
+
* (c) 2022 Whales Corp.
|
|
5
|
+
* (c) 2023 TrueCarry <truecarry@gmail.com>
|
|
6
|
+
* All Rights Reserved.
|
|
7
|
+
*
|
|
8
|
+
* This source code is licensed under the MIT license found in the
|
|
9
|
+
* LICENSE file in the root directory of this source tree.
|
|
10
|
+
*/
|
|
11
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
12
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
13
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
14
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
15
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
16
|
+
};
|
|
17
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
18
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
19
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
20
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
21
|
+
};
|
|
22
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
23
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
24
|
+
};
|
|
25
|
+
var _LiteClient_blockLockup, _LiteClient_shardsLockup, _LiteClient_blockHeader, _LiteClient_accounts;
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.LiteClient = void 0;
|
|
28
|
+
const core_1 = require("@ton/core");
|
|
29
|
+
const parseShards_1 = require("./parser/parseShards");
|
|
30
|
+
const schema_1 = require("./schema");
|
|
31
|
+
const dataloader_1 = __importDefault(require("dataloader"));
|
|
32
|
+
const crc16_1 = require("./utils/crc16");
|
|
33
|
+
const liteClientProvider_1 = require("./liteClientProvider");
|
|
34
|
+
const lru_map_1 = require("lru_map");
|
|
35
|
+
const arrays_1 = require("./utils/arrays");
|
|
36
|
+
const ZERO = 0n;
|
|
37
|
+
//
|
|
38
|
+
// Ops
|
|
39
|
+
//
|
|
40
|
+
const lookupBlockByID = async (engine, props, queryArgs) => {
|
|
41
|
+
return await engine.query(schema_1.Functions.liteServer_lookupBlock, {
|
|
42
|
+
kind: 'liteServer.lookupBlock',
|
|
43
|
+
mode: 1,
|
|
44
|
+
id: {
|
|
45
|
+
kind: 'tonNode.blockId',
|
|
46
|
+
seqno: props.seqno,
|
|
47
|
+
shard: props.shard,
|
|
48
|
+
workchain: props.workchain
|
|
49
|
+
},
|
|
50
|
+
lt: null,
|
|
51
|
+
utime: null
|
|
52
|
+
}, queryArgs);
|
|
53
|
+
};
|
|
54
|
+
const lookupBlockByUtime = async (engine, props, queryArgs) => {
|
|
55
|
+
return await engine.query(schema_1.Functions.liteServer_lookupBlock, {
|
|
56
|
+
kind: 'liteServer.lookupBlock',
|
|
57
|
+
mode: 4,
|
|
58
|
+
id: {
|
|
59
|
+
kind: 'tonNode.blockId',
|
|
60
|
+
seqno: 0,
|
|
61
|
+
shard: props.shard,
|
|
62
|
+
workchain: props.workchain
|
|
63
|
+
},
|
|
64
|
+
lt: null,
|
|
65
|
+
utime: props.utime
|
|
66
|
+
}, queryArgs);
|
|
67
|
+
};
|
|
68
|
+
const lookupBlockByLt = async (engine, props, queryArgs) => {
|
|
69
|
+
return await engine.query(schema_1.Functions.liteServer_lookupBlock, {
|
|
70
|
+
kind: 'liteServer.lookupBlock',
|
|
71
|
+
mode: 2,
|
|
72
|
+
id: {
|
|
73
|
+
kind: 'tonNode.blockId',
|
|
74
|
+
seqno: 0,
|
|
75
|
+
shard: props.shard,
|
|
76
|
+
workchain: props.workchain
|
|
77
|
+
},
|
|
78
|
+
lt: props.lt.toString(),
|
|
79
|
+
utime: null,
|
|
80
|
+
}, queryArgs);
|
|
81
|
+
};
|
|
82
|
+
const getAllShardsInfo = async (engine, props, queryArgs) => {
|
|
83
|
+
let res = (await engine.query(schema_1.Functions.liteServer_getAllShardsInfo, { kind: 'liteServer.getAllShardsInfo', id: props }, queryArgs));
|
|
84
|
+
let parsed = (0, parseShards_1.parseShards)(core_1.Cell.fromBoc(res.data)[0].beginParse());
|
|
85
|
+
let shards = {};
|
|
86
|
+
for (let p of parsed) {
|
|
87
|
+
shards[p[0].toString()] = {};
|
|
88
|
+
for (let p2 of p[1]) {
|
|
89
|
+
shards[p[0].toString()][p2[0]] = p2[1];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
id: res.id,
|
|
94
|
+
shards,
|
|
95
|
+
raw: res.data,
|
|
96
|
+
proof: res.proof
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
const getBlockHeader = async (engine, props, queryArgs) => {
|
|
100
|
+
return await engine.query(schema_1.Functions.liteServer_getBlockHeader, {
|
|
101
|
+
kind: 'liteServer.getBlockHeader',
|
|
102
|
+
mode: 1,
|
|
103
|
+
id: {
|
|
104
|
+
kind: 'tonNode.blockIdExt',
|
|
105
|
+
seqno: props.seqno,
|
|
106
|
+
shard: props.shard,
|
|
107
|
+
workchain: props.workchain,
|
|
108
|
+
rootHash: props.rootHash,
|
|
109
|
+
fileHash: props.fileHash
|
|
110
|
+
}
|
|
111
|
+
}, queryArgs);
|
|
112
|
+
};
|
|
113
|
+
function getCacheMap(mapKind, mapOptions) {
|
|
114
|
+
if (typeof mapOptions === 'function') {
|
|
115
|
+
return mapOptions(mapKind);
|
|
116
|
+
}
|
|
117
|
+
if (typeof mapOptions === 'number') {
|
|
118
|
+
return new lru_map_1.LRUMap(mapOptions);
|
|
119
|
+
}
|
|
120
|
+
return new lru_map_1.LRUMap(1000);
|
|
121
|
+
}
|
|
122
|
+
class LiteClient {
|
|
123
|
+
constructor(opts) {
|
|
124
|
+
_LiteClient_blockLockup.set(this, void 0);
|
|
125
|
+
_LiteClient_shardsLockup.set(this, void 0);
|
|
126
|
+
_LiteClient_blockHeader.set(this, void 0);
|
|
127
|
+
_LiteClient_accounts.set(this, void 0);
|
|
128
|
+
//
|
|
129
|
+
// Sending
|
|
130
|
+
//
|
|
131
|
+
this.sendMessage = async (src) => {
|
|
132
|
+
let res = await this.engine.query(schema_1.Functions.liteServer_sendMessage, { kind: 'liteServer.sendMessage', body: src }, { timeout: 5000 });
|
|
133
|
+
return {
|
|
134
|
+
status: res.status
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
//
|
|
138
|
+
// State
|
|
139
|
+
//
|
|
140
|
+
this.getMasterchainInfo = async (queryArgs) => {
|
|
141
|
+
return this.engine.query(schema_1.Functions.liteServer_getMasterchainInfo, { kind: 'liteServer.masterchainInfo' }, queryArgs);
|
|
142
|
+
};
|
|
143
|
+
this.getMasterchainInfoExt = async (queryArgs) => {
|
|
144
|
+
return this.engine.query(schema_1.Functions.liteServer_getMasterchainInfoExt, { kind: 'liteServer.masterchainInfoExt', mode: 0 }, queryArgs);
|
|
145
|
+
};
|
|
146
|
+
this.getCurrentTime = async (queryArgs) => {
|
|
147
|
+
return (await this.engine.query(schema_1.Functions.liteServer_getTime, { kind: 'liteServer.getTime' }, queryArgs)).now;
|
|
148
|
+
};
|
|
149
|
+
this.getVersion = async (queryArgs) => {
|
|
150
|
+
return (await this.engine.query(schema_1.Functions.liteServer_getVersion, { kind: 'liteServer.getVersion' }, queryArgs));
|
|
151
|
+
};
|
|
152
|
+
this.getConfig = async (block, queryArgs) => {
|
|
153
|
+
let res = await this.engine.query(schema_1.Functions.liteServer_getConfigAll, {
|
|
154
|
+
kind: 'liteServer.getConfigAll',
|
|
155
|
+
id: {
|
|
156
|
+
kind: 'tonNode.blockIdExt',
|
|
157
|
+
seqno: block.seqno,
|
|
158
|
+
shard: block.shard,
|
|
159
|
+
workchain: block.workchain,
|
|
160
|
+
fileHash: block.fileHash,
|
|
161
|
+
rootHash: block.rootHash
|
|
162
|
+
},
|
|
163
|
+
mode: 0
|
|
164
|
+
}, queryArgs);
|
|
165
|
+
const configProof = core_1.Cell.fromBoc(res.configProof)[0];
|
|
166
|
+
const configCell = configProof.refs[0];
|
|
167
|
+
const cs = configCell.beginParse();
|
|
168
|
+
let shardState = (0, core_1.loadShardStateUnsplit)(cs);
|
|
169
|
+
if (!shardState.extras) {
|
|
170
|
+
throw Error('Invalid response');
|
|
171
|
+
}
|
|
172
|
+
return shardState.extras;
|
|
173
|
+
};
|
|
174
|
+
//
|
|
175
|
+
// Account
|
|
176
|
+
//
|
|
177
|
+
this.getAccountState = async (src, block) => {
|
|
178
|
+
return __classPrivateFieldGet(this, _LiteClient_accounts, "f").load({
|
|
179
|
+
address: src,
|
|
180
|
+
seqno: block.seqno,
|
|
181
|
+
shard: block.shard,
|
|
182
|
+
workchain: block.workchain,
|
|
183
|
+
fileHash: block.fileHash,
|
|
184
|
+
rootHash: block.rootHash
|
|
185
|
+
});
|
|
186
|
+
};
|
|
187
|
+
this.getAccountStateRaw = async (src, block, queryArgs) => {
|
|
188
|
+
let res = await this.engine.query(schema_1.Functions.liteServer_getAccountState, {
|
|
189
|
+
kind: 'liteServer.getAccountState',
|
|
190
|
+
id: {
|
|
191
|
+
kind: 'tonNode.blockIdExt',
|
|
192
|
+
seqno: block.seqno,
|
|
193
|
+
shard: block.shard,
|
|
194
|
+
workchain: block.workchain,
|
|
195
|
+
fileHash: block.fileHash,
|
|
196
|
+
rootHash: block.rootHash
|
|
197
|
+
},
|
|
198
|
+
account: {
|
|
199
|
+
kind: 'liteServer.accountId',
|
|
200
|
+
workchain: src.workChain,
|
|
201
|
+
id: src.hash
|
|
202
|
+
}
|
|
203
|
+
}, queryArgs);
|
|
204
|
+
let account = null;
|
|
205
|
+
let balance = { coins: ZERO };
|
|
206
|
+
let lastTx = null;
|
|
207
|
+
if (res.state.length > 0) {
|
|
208
|
+
const accountSlice = core_1.Cell.fromBoc(res.state)[0].asSlice();
|
|
209
|
+
if (accountSlice.loadBit()) {
|
|
210
|
+
account = (0, core_1.loadAccount)(accountSlice);
|
|
211
|
+
if (account) {
|
|
212
|
+
balance = account.storage.balance;
|
|
213
|
+
let shardState = (0, core_1.loadShardStateUnsplit)(core_1.Cell.fromBoc(res.proof)[1].refs[0].beginParse());
|
|
214
|
+
let hashId = BigInt('0x' + src.hash.toString('hex'));
|
|
215
|
+
if (shardState.accounts) {
|
|
216
|
+
let pstate = shardState.accounts.get(hashId);
|
|
217
|
+
if (pstate) {
|
|
218
|
+
lastTx = { hash: pstate.shardAccount.lastTransactionHash, lt: pstate.shardAccount.lastTransactionLt };
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
state: account,
|
|
226
|
+
lastTx,
|
|
227
|
+
balance,
|
|
228
|
+
raw: res.state,
|
|
229
|
+
proof: res.proof,
|
|
230
|
+
block: res.id,
|
|
231
|
+
shardBlock: res.shardblk,
|
|
232
|
+
shardProof: res.shardProof
|
|
233
|
+
};
|
|
234
|
+
};
|
|
235
|
+
this.getAccountStatePrunned = async (src, block, queryArgs) => {
|
|
236
|
+
let res = (await this.engine.query(schema_1.Functions.liteServer_getAccountStatePrunned, {
|
|
237
|
+
kind: 'liteServer.getAccountStatePrunned',
|
|
238
|
+
id: {
|
|
239
|
+
kind: 'tonNode.blockIdExt',
|
|
240
|
+
seqno: block.seqno,
|
|
241
|
+
shard: block.shard,
|
|
242
|
+
workchain: block.workchain,
|
|
243
|
+
fileHash: block.fileHash,
|
|
244
|
+
rootHash: block.rootHash
|
|
245
|
+
},
|
|
246
|
+
account: {
|
|
247
|
+
kind: 'liteServer.accountId',
|
|
248
|
+
workchain: src.workChain,
|
|
249
|
+
id: src.hash
|
|
250
|
+
}
|
|
251
|
+
}, queryArgs));
|
|
252
|
+
let stateHash = null;
|
|
253
|
+
if (res.state.length > 0) {
|
|
254
|
+
let stateCell = core_1.Cell.fromBoc(res.state)[0];
|
|
255
|
+
if (!stateCell.isExotic) {
|
|
256
|
+
throw new Error('Prunned state is not exotic');
|
|
257
|
+
}
|
|
258
|
+
stateHash = core_1.Cell.fromBoc(res.state)[0].bits.subbuffer(8, 256);
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
stateHash,
|
|
262
|
+
raw: res.state,
|
|
263
|
+
proof: res.proof,
|
|
264
|
+
block: res.id,
|
|
265
|
+
shardBlock: res.shardblk,
|
|
266
|
+
shardProof: res.shardProof
|
|
267
|
+
};
|
|
268
|
+
};
|
|
269
|
+
this.getAccountTransaction = async (src, lt, block, queryArgs) => {
|
|
270
|
+
return await this.engine.query(schema_1.Functions.liteServer_getOneTransaction, {
|
|
271
|
+
kind: 'liteServer.getOneTransaction',
|
|
272
|
+
id: block,
|
|
273
|
+
account: {
|
|
274
|
+
kind: 'liteServer.accountId',
|
|
275
|
+
workchain: src.workChain,
|
|
276
|
+
id: src.hash
|
|
277
|
+
},
|
|
278
|
+
lt: lt
|
|
279
|
+
}, queryArgs);
|
|
280
|
+
};
|
|
281
|
+
this.getAccountTransactions = async (src, lt, hash, count, queryArgs) => {
|
|
282
|
+
let loaded = await this.engine.query(schema_1.Functions.liteServer_getTransactions, {
|
|
283
|
+
kind: 'liteServer.getTransactions',
|
|
284
|
+
count,
|
|
285
|
+
account: {
|
|
286
|
+
kind: 'liteServer.accountId',
|
|
287
|
+
workchain: src.workChain,
|
|
288
|
+
id: src.hash
|
|
289
|
+
},
|
|
290
|
+
lt: lt,
|
|
291
|
+
hash: hash
|
|
292
|
+
}, queryArgs);
|
|
293
|
+
return {
|
|
294
|
+
ids: loaded.ids,
|
|
295
|
+
transactions: loaded.transactions
|
|
296
|
+
};
|
|
297
|
+
};
|
|
298
|
+
this.runMethod = async (src, method, params, block, queryArgs) => {
|
|
299
|
+
let res = await this.engine.query(schema_1.Functions.liteServer_runSmcMethod, {
|
|
300
|
+
kind: 'liteServer.runSmcMethod',
|
|
301
|
+
mode: 4,
|
|
302
|
+
id: {
|
|
303
|
+
kind: 'tonNode.blockIdExt',
|
|
304
|
+
seqno: block.seqno,
|
|
305
|
+
shard: block.shard,
|
|
306
|
+
workchain: block.workchain,
|
|
307
|
+
rootHash: block.rootHash,
|
|
308
|
+
fileHash: block.fileHash
|
|
309
|
+
},
|
|
310
|
+
account: {
|
|
311
|
+
kind: 'liteServer.accountId',
|
|
312
|
+
workchain: src.workChain,
|
|
313
|
+
id: src.hash
|
|
314
|
+
},
|
|
315
|
+
methodId: (((0, crc16_1.crc16)(method) & 0xffff) | 0x10000) + '',
|
|
316
|
+
params
|
|
317
|
+
}, queryArgs);
|
|
318
|
+
return {
|
|
319
|
+
exitCode: res.exitCode,
|
|
320
|
+
result: res.result ? res.result.toString('base64') : null,
|
|
321
|
+
block: {
|
|
322
|
+
seqno: res.id.seqno,
|
|
323
|
+
shard: res.id.shard,
|
|
324
|
+
workchain: res.id.workchain,
|
|
325
|
+
rootHash: res.id.rootHash,
|
|
326
|
+
fileHash: res.id.fileHash
|
|
327
|
+
},
|
|
328
|
+
shardBlock: {
|
|
329
|
+
seqno: res.shardblk.seqno,
|
|
330
|
+
shard: res.shardblk.shard,
|
|
331
|
+
workchain: res.shardblk.workchain,
|
|
332
|
+
rootHash: res.shardblk.rootHash,
|
|
333
|
+
fileHash: res.shardblk.fileHash
|
|
334
|
+
},
|
|
335
|
+
};
|
|
336
|
+
};
|
|
337
|
+
//
|
|
338
|
+
// Block
|
|
339
|
+
//
|
|
340
|
+
this.lookupBlockByID = async (block) => {
|
|
341
|
+
return await __classPrivateFieldGet(this, _LiteClient_blockLockup, "f").load({ ...block, mode: 'id' });
|
|
342
|
+
};
|
|
343
|
+
this.lookupBlockByUtime = async (block) => {
|
|
344
|
+
return await __classPrivateFieldGet(this, _LiteClient_blockLockup, "f").load({ ...block, mode: 'utime' });
|
|
345
|
+
};
|
|
346
|
+
this.lookupBlockByLt = async (block) => {
|
|
347
|
+
return await __classPrivateFieldGet(this, _LiteClient_blockLockup, "f").load({ ...block, mode: 'lt' });
|
|
348
|
+
};
|
|
349
|
+
this.getBlockHeader = async (block) => {
|
|
350
|
+
return __classPrivateFieldGet(this, _LiteClient_blockHeader, "f").load(block);
|
|
351
|
+
};
|
|
352
|
+
this.getAllShardsInfo = async (block) => {
|
|
353
|
+
return __classPrivateFieldGet(this, _LiteClient_shardsLockup, "f").load(block);
|
|
354
|
+
};
|
|
355
|
+
this.listBlockTransactions = async (block, args, queryArgs) => {
|
|
356
|
+
let mode = args?.mode || 1 + 2 + 4;
|
|
357
|
+
let count = args?.count || 100;
|
|
358
|
+
let after = args && args.after ? args.after : null;
|
|
359
|
+
return await this.engine.query(schema_1.Functions.liteServer_listBlockTransactions, {
|
|
360
|
+
kind: 'liteServer.listBlockTransactions',
|
|
361
|
+
id: {
|
|
362
|
+
kind: 'tonNode.blockIdExt',
|
|
363
|
+
seqno: block.seqno,
|
|
364
|
+
shard: block.shard,
|
|
365
|
+
workchain: block.workchain,
|
|
366
|
+
rootHash: block.rootHash,
|
|
367
|
+
fileHash: block.fileHash
|
|
368
|
+
},
|
|
369
|
+
mode,
|
|
370
|
+
count,
|
|
371
|
+
reverseOrder: null,
|
|
372
|
+
after,
|
|
373
|
+
wantProof: null
|
|
374
|
+
}, queryArgs);
|
|
375
|
+
};
|
|
376
|
+
this.listBlockTransactionsExt = async (block, args, queryArgs) => {
|
|
377
|
+
let mode = args?.mode || 1 + 2 + 4;
|
|
378
|
+
let count = args?.count || 100;
|
|
379
|
+
let after = args && args.after ? args.after : null;
|
|
380
|
+
return await this.engine.query(schema_1.Functions.liteServer_listBlockTransactionsExt, {
|
|
381
|
+
kind: 'liteServer.listBlockTransactionsExt',
|
|
382
|
+
id: {
|
|
383
|
+
kind: 'tonNode.blockIdExt',
|
|
384
|
+
seqno: block.seqno,
|
|
385
|
+
shard: block.shard,
|
|
386
|
+
workchain: block.workchain,
|
|
387
|
+
rootHash: block.rootHash,
|
|
388
|
+
fileHash: block.fileHash
|
|
389
|
+
},
|
|
390
|
+
mode,
|
|
391
|
+
count,
|
|
392
|
+
reverseOrder: null,
|
|
393
|
+
after,
|
|
394
|
+
wantProof: null
|
|
395
|
+
}, queryArgs);
|
|
396
|
+
};
|
|
397
|
+
this.getFullBlock = async (seqno) => {
|
|
398
|
+
// MC Blocks
|
|
399
|
+
let [mcBlockId, mcBlockPrevId] = await Promise.all([
|
|
400
|
+
this.lookupBlockByID({ workchain: -1, shard: '-9223372036854775808', seqno: seqno }),
|
|
401
|
+
this.lookupBlockByID({ workchain: -1, shard: '-9223372036854775808', seqno: seqno - 1 })
|
|
402
|
+
]);
|
|
403
|
+
// Shards
|
|
404
|
+
let [mcShards, mcShardsPrev] = await Promise.all([
|
|
405
|
+
this.getAllShardsInfo(mcBlockId.id),
|
|
406
|
+
this.getAllShardsInfo(mcBlockPrevId.id)
|
|
407
|
+
]);
|
|
408
|
+
// Extract shards
|
|
409
|
+
let shards = [];
|
|
410
|
+
shards.push({ seqno, workchain: -1, shard: '-9223372036854775808' });
|
|
411
|
+
// Extract shards
|
|
412
|
+
for (let wcs in mcShards.shards) {
|
|
413
|
+
let wc = parseInt(wcs, 10);
|
|
414
|
+
let currShards = mcShards.shards[wcs];
|
|
415
|
+
let prevShards = mcShardsPrev.shards[wcs] || {};
|
|
416
|
+
const currShardIds = Object.keys(currShards);
|
|
417
|
+
const prevShardIds = Object.keys(prevShards);
|
|
418
|
+
const bothBlockShards = (0, arrays_1.findIntersection)(currShardIds, prevShardIds);
|
|
419
|
+
const currBlockShards = (0, arrays_1.findOnlyOnFirst)(currShardIds, prevShardIds);
|
|
420
|
+
// const prevBlockShards = findElementsInArray1NotInArray2(prevShardIds, currShardIds)
|
|
421
|
+
// If shard is present in both blocks - add difference
|
|
422
|
+
for (let shs of bothBlockShards) {
|
|
423
|
+
let seqno = currShards[shs];
|
|
424
|
+
let prevSeqno = prevShards[shs] || seqno;
|
|
425
|
+
for (let s = prevSeqno + 1; s <= seqno; s++) {
|
|
426
|
+
shards.push({ seqno: s, workchain: wc, shard: shs });
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
// Shards present only in current block, just add them to list
|
|
430
|
+
// todo: check if prev shard block exists?
|
|
431
|
+
for (const shs of currBlockShards) {
|
|
432
|
+
shards.push({ seqno: currShards[shs], workchain: wc, shard: shs });
|
|
433
|
+
}
|
|
434
|
+
// Shards present only in prev block.
|
|
435
|
+
// todo: check if newer blocks for given shards are present
|
|
436
|
+
// for (const shs of prevBlockShards) {
|
|
437
|
+
// shards.push({ seqno: currShards[shs], workchain: wc, shard: shs });
|
|
438
|
+
// }
|
|
439
|
+
}
|
|
440
|
+
// Fetch transactions and blocks
|
|
441
|
+
let shards2 = await Promise.all(shards.map(async (shard) => {
|
|
442
|
+
let blockId = await this.lookupBlockByID(shard);
|
|
443
|
+
let transactions = [];
|
|
444
|
+
let after = null;
|
|
445
|
+
while (true) {
|
|
446
|
+
let tr = await this.listBlockTransactions(blockId.id, {
|
|
447
|
+
count: 128,
|
|
448
|
+
mode: 1 + 2 + 4 + (after ? 128 : 0),
|
|
449
|
+
after
|
|
450
|
+
});
|
|
451
|
+
for (let t of tr.ids) {
|
|
452
|
+
transactions.push(t);
|
|
453
|
+
}
|
|
454
|
+
if (!tr.incomplete) {
|
|
455
|
+
break;
|
|
456
|
+
}
|
|
457
|
+
after = { kind: 'liteServer.transactionId3', account: tr.ids[tr.ids.length - 1].account, lt: tr.ids[tr.ids.length - 1].lt };
|
|
458
|
+
}
|
|
459
|
+
let mapped = transactions.map((t) => ({ hash: t.hash, lt: t.lt, account: t.account }));
|
|
460
|
+
return {
|
|
461
|
+
...shard,
|
|
462
|
+
rootHash: blockId.id.rootHash,
|
|
463
|
+
fileHash: blockId.id.fileHash,
|
|
464
|
+
transactions: mapped
|
|
465
|
+
};
|
|
466
|
+
}));
|
|
467
|
+
return {
|
|
468
|
+
shards: shards2
|
|
469
|
+
};
|
|
470
|
+
};
|
|
471
|
+
this.getLibraries = async (hashes, queryArgs) => {
|
|
472
|
+
return this.engine.query(schema_1.Functions.liteServer_getLibraries, {
|
|
473
|
+
kind: 'liteServer.getLibraries',
|
|
474
|
+
libraryList: hashes
|
|
475
|
+
}, queryArgs);
|
|
476
|
+
};
|
|
477
|
+
this.engine = opts.engine;
|
|
478
|
+
let batchSize = typeof opts.batchSize === 'number' ? opts.batchSize : 100;
|
|
479
|
+
__classPrivateFieldSet(this, _LiteClient_blockLockup, new dataloader_1.default(async (s) => {
|
|
480
|
+
return await Promise.all(s.map((v) => {
|
|
481
|
+
if (v.mode === 'utime') {
|
|
482
|
+
return lookupBlockByUtime(this.engine, v);
|
|
483
|
+
}
|
|
484
|
+
if (v.mode === 'lt') {
|
|
485
|
+
return lookupBlockByLt(this.engine, v);
|
|
486
|
+
}
|
|
487
|
+
return lookupBlockByID(this.engine, v);
|
|
488
|
+
}));
|
|
489
|
+
}, {
|
|
490
|
+
maxBatchSize: batchSize, cacheKeyFn: (s) => {
|
|
491
|
+
if (s.mode === 'id') {
|
|
492
|
+
return `block::${s.workchain}::${s.shard}::${s.seqno}`;
|
|
493
|
+
}
|
|
494
|
+
else if (s.mode === 'lt') {
|
|
495
|
+
return `block::${s.workchain}::${s.shard}::lt-${s.lt}`;
|
|
496
|
+
}
|
|
497
|
+
else {
|
|
498
|
+
return `block::${s.workchain}::${s.shard}::utime-${s.utime}`;
|
|
499
|
+
}
|
|
500
|
+
},
|
|
501
|
+
cacheMap: getCacheMap('block', opts.cacheMap),
|
|
502
|
+
}), "f");
|
|
503
|
+
__classPrivateFieldSet(this, _LiteClient_blockHeader, new dataloader_1.default(async (s) => {
|
|
504
|
+
return await Promise.all(s.map((v) => getBlockHeader(this.engine, v)));
|
|
505
|
+
}, {
|
|
506
|
+
maxBatchSize: batchSize,
|
|
507
|
+
cacheKeyFn: (s) => `header::${s.workchain}::${s.shard}::${s.seqno}`,
|
|
508
|
+
cacheMap: getCacheMap('header', opts.cacheMap),
|
|
509
|
+
}), "f");
|
|
510
|
+
__classPrivateFieldSet(this, _LiteClient_shardsLockup, new dataloader_1.default(async (s) => {
|
|
511
|
+
return await Promise.all(s.map((v) => getAllShardsInfo(this.engine, v)));
|
|
512
|
+
}, {
|
|
513
|
+
maxBatchSize: batchSize,
|
|
514
|
+
cacheKeyFn: (s) => `shard::${s.workchain}::${s.shard}::${s.seqno}`,
|
|
515
|
+
cacheMap: getCacheMap('shard', opts.cacheMap),
|
|
516
|
+
}), "f");
|
|
517
|
+
__classPrivateFieldSet(this, _LiteClient_accounts, new dataloader_1.default(async (s) => {
|
|
518
|
+
return await Promise.all(s.map((v) => this.getAccountStateRaw(v.address, {
|
|
519
|
+
fileHash: v.fileHash,
|
|
520
|
+
rootHash: v.rootHash,
|
|
521
|
+
seqno: v.seqno,
|
|
522
|
+
shard: v.shard,
|
|
523
|
+
workchain: v.workchain,
|
|
524
|
+
})));
|
|
525
|
+
}, {
|
|
526
|
+
maxBatchSize: batchSize,
|
|
527
|
+
cacheKeyFn: (s) => `account::${s.workchain}::${s.shard}::${s.seqno}::${s.address.toRawString()}`,
|
|
528
|
+
cacheMap: getCacheMap('account', opts.cacheMap),
|
|
529
|
+
}), "f");
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Open a contract
|
|
533
|
+
* @param contract
|
|
534
|
+
*/
|
|
535
|
+
open(contract) {
|
|
536
|
+
return (0, core_1.openContract)(contract, (args) => (0, liteClientProvider_1.createLiteClientProvider)(this, null, args.address, args.init));
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Create a new contract provider
|
|
540
|
+
* @param address
|
|
541
|
+
* @param init
|
|
542
|
+
*/
|
|
543
|
+
provider(address, init) {
|
|
544
|
+
return (0, liteClientProvider_1.createLiteClientProvider)(this, null, address, init ?? null);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
exports.LiteClient = LiteClient;
|
|
548
|
+
_LiteClient_blockLockup = new WeakMap(), _LiteClient_shardsLockup = new WeakMap(), _LiteClient_blockHeader = new WeakMap(), _LiteClient_accounts = new WeakMap();
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright
|
|
3
|
+
* (c) 2022 Whales Corp.
|
|
4
|
+
* (c) 2023 TrueCarry <truecarry@gmail.com>
|
|
5
|
+
* All Rights Reserved.
|
|
6
|
+
*
|
|
7
|
+
* This source code is licensed under the MIT license found in the
|
|
8
|
+
* LICENSE file in the root directory of this source tree.
|
|
9
|
+
*/
|
|
10
|
+
import { TLFunction } from "ton-tl";
|
|
11
|
+
export interface LiteEngine {
|
|
12
|
+
query<REQ, RES>(f: TLFunction<REQ, RES>, req: REQ, args?: {
|
|
13
|
+
timeout?: number;
|
|
14
|
+
awaitSeqno?: number;
|
|
15
|
+
}): Promise<RES>;
|
|
16
|
+
close(): void;
|
|
17
|
+
isClosed(): boolean;
|
|
18
|
+
isReady(): boolean;
|
|
19
|
+
emit(event: 'connect'): boolean;
|
|
20
|
+
emit(event: 'ready'): boolean;
|
|
21
|
+
emit(event: 'close'): boolean;
|
|
22
|
+
emit(event: 'error', error: Error): boolean;
|
|
23
|
+
on(event: 'connect', listener: () => void): this;
|
|
24
|
+
on(event: 'ready', listener: () => void): this;
|
|
25
|
+
on(event: 'close', listener: () => void): this;
|
|
26
|
+
on(event: 'error', listener: (error: Error, close: boolean) => void): this;
|
|
27
|
+
once(event: 'connect', listener: () => void): this;
|
|
28
|
+
once(event: 'ready', listener: () => void): this;
|
|
29
|
+
once(event: 'close', listener: () => void): this;
|
|
30
|
+
once(event: 'error', listener: (error: Error, close: boolean) => void): this;
|
|
31
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright
|
|
4
|
+
* (c) 2022 Whales Corp.
|
|
5
|
+
* (c) 2023 TrueCarry <truecarry@gmail.com>
|
|
6
|
+
* All Rights Reserved.
|
|
7
|
+
*
|
|
8
|
+
* This source code is licensed under the MIT license found in the
|
|
9
|
+
* LICENSE file in the root directory of this source tree.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright
|
|
3
|
+
* (c) 2022 Whales Corp.
|
|
4
|
+
* (c) 2023 TrueCarry <truecarry@gmail.com>
|
|
5
|
+
* All Rights Reserved.
|
|
6
|
+
*
|
|
7
|
+
* This source code is licensed under the MIT license found in the
|
|
8
|
+
* LICENSE file in the root directory of this source tree.
|
|
9
|
+
*/
|
|
10
|
+
/// <reference types="node" />
|
|
11
|
+
import EventEmitter from "events";
|
|
12
|
+
import { TLFunction } from "ton-tl";
|
|
13
|
+
import { LiteEngine } from "./engine";
|
|
14
|
+
export declare class LiteRoundRobinEngine extends EventEmitter implements LiteEngine {
|
|
15
|
+
#private;
|
|
16
|
+
private allEngines;
|
|
17
|
+
private readyEngines;
|
|
18
|
+
constructor(engines: LiteEngine[]);
|
|
19
|
+
addSingleEngine(engine: LiteEngine): void;
|
|
20
|
+
query<REQ, RES>(f: TLFunction<REQ, RES>, req: REQ, args?: {
|
|
21
|
+
timeout?: number;
|
|
22
|
+
awaitSeqno?: number;
|
|
23
|
+
}): Promise<RES>;
|
|
24
|
+
close(): void;
|
|
25
|
+
isClosed(): boolean;
|
|
26
|
+
isReady(): boolean;
|
|
27
|
+
}
|