gen-typescript-from-tolk-dev 0.1.0 → 0.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/README.md +53 -27
- package/bin/generator.js +1 -13
- package/dist/abi-types.d.ts +169 -0
- package/dist/abi-types.js +8 -0
- package/dist/abi.d.ts +53 -0
- package/dist/abi.js +13 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +122 -0
- package/dist/codegen-ctx.d.ts +66 -0
- package/dist/codegen-ctx.js +108 -0
- package/dist/dynamic-ctx.d.ts +17 -0
- package/dist/dynamic-ctx.js +39 -0
- package/dist/dynamic-debug-print.d.ts +9 -0
- package/{src/dynamic-debug-print.ts → dist/dynamic-debug-print.js} +57 -65
- package/dist/dynamic-get-methods.d.ts +43 -0
- package/dist/dynamic-get-methods.js +451 -0
- package/dist/dynamic-serialization.d.ts +22 -0
- package/dist/dynamic-serialization.js +453 -0
- package/dist/dynamic-validation.d.ts +8 -0
- package/{src/dynamic-validation.ts → dist/dynamic-validation.js} +19 -18
- package/dist/emit-field-defs.d.ts +5 -0
- package/dist/emit-field-defs.js +61 -0
- package/dist/emit-pack-unpack.d.ts +9 -0
- package/dist/emit-pack-unpack.js +296 -0
- package/dist/emit-stack-rw.d.ts +4 -0
- package/dist/emit-stack-rw.js +232 -0
- package/dist/emit-ts-types.d.ts +6 -0
- package/dist/emit-ts-types.js +74 -0
- package/dist/formatting.d.ts +15 -0
- package/{src/formatting.ts → dist/formatting.js} +26 -28
- package/dist/generate-ts-wrappers.d.ts +7 -0
- package/dist/generate-ts-wrappers.js +444 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +11 -0
- package/dist/out-template.generated.d.ts +1 -0
- package/dist/out-template.generated.js +6 -0
- package/dist/tolk-to-abi.d.ts +2 -0
- package/dist/tolk-to-abi.js +22 -0
- package/dist/types-kernel.d.ts +10 -0
- package/dist/types-kernel.js +212 -0
- package/dist/unsupported-errors.d.ts +28 -0
- package/{src/unsupported-errors.ts → dist/unsupported-errors.js} +33 -39
- package/package.json +73 -27
- package/src/abi-types.ts +0 -157
- package/src/abi.ts +0 -132
- package/src/cli-generate-from-abi-json.ts +0 -21
- package/src/codegen-ctx.ts +0 -115
- package/src/dynamic-ctx.ts +0 -55
- package/src/dynamic-get-methods.ts +0 -454
- package/src/dynamic-serialization.ts +0 -430
- package/src/emit-field-defs.ts +0 -60
- package/src/emit-pack-unpack.ts +0 -280
- package/src/emit-stack-rw.ts +0 -239
- package/src/emit-ts-types.ts +0 -66
- package/src/generate-from-abi-json.ts +0 -22
- package/src/generate-ts-wrappers.ts +0 -477
- package/src/out-template.ts +0 -514
- package/src/tolk-to-abi.ts +0 -5
- package/src/types-kernel.ts +0 -215
- package/tsconfig.json +0 -13
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.StackReader = void 0;
|
|
37
|
+
exports.makeTvmTupleDynamic = makeTvmTupleDynamic;
|
|
38
|
+
exports.callGetMethodDynamic = callGetMethodDynamic;
|
|
39
|
+
const c = __importStar(require("@ton/core"));
|
|
40
|
+
const unsupported_errors_1 = require("./unsupported-errors");
|
|
41
|
+
const dynamic_serialization_1 = require("./dynamic-serialization");
|
|
42
|
+
const types_kernel_1 = require("./types-kernel");
|
|
43
|
+
const dynamic_validation_1 = require("./dynamic-validation");
|
|
44
|
+
class StackReader {
|
|
45
|
+
constructor(tuple) {
|
|
46
|
+
this.tuple = tuple;
|
|
47
|
+
}
|
|
48
|
+
static fromGetMethod(expectedN, getMethodResult) {
|
|
49
|
+
let tuple = [];
|
|
50
|
+
while (getMethodResult.stack.remaining) {
|
|
51
|
+
tuple.push(getMethodResult.stack.pop());
|
|
52
|
+
}
|
|
53
|
+
if (tuple.length !== expectedN) {
|
|
54
|
+
throw new Error(`expected ${expectedN} stack width, got ${tuple.length}`);
|
|
55
|
+
}
|
|
56
|
+
return new StackReader(tuple);
|
|
57
|
+
}
|
|
58
|
+
popExpecting(itemType) {
|
|
59
|
+
const item = this.tuple.shift();
|
|
60
|
+
if (item?.type !== itemType) {
|
|
61
|
+
throw new Error(`not '${itemType}' on a stack`);
|
|
62
|
+
}
|
|
63
|
+
return item;
|
|
64
|
+
}
|
|
65
|
+
readBigInt() {
|
|
66
|
+
return this.popExpecting('int').value;
|
|
67
|
+
}
|
|
68
|
+
readBoolean() {
|
|
69
|
+
return this.popExpecting('int').value !== 0n;
|
|
70
|
+
}
|
|
71
|
+
readCell() {
|
|
72
|
+
return this.popExpecting('cell').cell;
|
|
73
|
+
}
|
|
74
|
+
readSlice() {
|
|
75
|
+
return this.popExpecting('slice').cell.beginParse();
|
|
76
|
+
}
|
|
77
|
+
readBuilder() {
|
|
78
|
+
return c.beginCell().storeSlice(this.popExpecting('builder').cell.beginParse());
|
|
79
|
+
}
|
|
80
|
+
readUnknown() {
|
|
81
|
+
// `unknown` from Tolk is left as a raw tuple item
|
|
82
|
+
return this.tuple.shift();
|
|
83
|
+
}
|
|
84
|
+
readArrayOf(readFn_T) {
|
|
85
|
+
const subItems = this.popExpecting('tuple').items;
|
|
86
|
+
const subReader = new StackReader(subItems);
|
|
87
|
+
// array len N => N subItems => N calls to readFn_T
|
|
88
|
+
return [...subItems].map(_ => readFn_T(subReader));
|
|
89
|
+
}
|
|
90
|
+
readLispListOf(readFn_T) {
|
|
91
|
+
// read `[1 [2 [3 null]]]` to `[1 2 3]`
|
|
92
|
+
let pairReader = this;
|
|
93
|
+
let outArr = [];
|
|
94
|
+
while (true) {
|
|
95
|
+
if (pairReader.tuple[0].type === 'null') {
|
|
96
|
+
pairReader.tuple.shift();
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
let headAndTail = pairReader.popExpecting('tuple').items;
|
|
100
|
+
if (headAndTail.length !== 2) {
|
|
101
|
+
throw new Error(`malformed lisp_list, expected 2 stack width, got ${headAndTail.length}`);
|
|
102
|
+
}
|
|
103
|
+
pairReader = new StackReader(headAndTail);
|
|
104
|
+
outArr.push(readFn_T(pairReader));
|
|
105
|
+
}
|
|
106
|
+
return outArr;
|
|
107
|
+
}
|
|
108
|
+
readSnakeString() {
|
|
109
|
+
return this.readCell().beginParse().loadStringTail();
|
|
110
|
+
}
|
|
111
|
+
readTuple(expectedN, readFn_T) {
|
|
112
|
+
const subItems = this.popExpecting('tuple').items;
|
|
113
|
+
if (subItems.length !== expectedN) {
|
|
114
|
+
throw new Error(`expected ${expectedN} items in a tuple, got ${subItems.length}`);
|
|
115
|
+
}
|
|
116
|
+
return readFn_T(new StackReader(subItems));
|
|
117
|
+
}
|
|
118
|
+
readNullLiteral() {
|
|
119
|
+
this.popExpecting('null');
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
readNullable(readFn_T) {
|
|
123
|
+
if (this.tuple[0].type === 'null') {
|
|
124
|
+
this.tuple.shift();
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
return readFn_T(this);
|
|
128
|
+
}
|
|
129
|
+
readWideNullable(stackW, readFn_T) {
|
|
130
|
+
const slotTypeId = this.tuple[stackW - 1];
|
|
131
|
+
if (slotTypeId?.type !== 'int') {
|
|
132
|
+
throw new Error(`not 'int' on a stack`);
|
|
133
|
+
}
|
|
134
|
+
if (slotTypeId.value === 0n) {
|
|
135
|
+
this.tuple = this.tuple.slice(stackW);
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
const valueT = readFn_T(this);
|
|
139
|
+
this.tuple.shift();
|
|
140
|
+
return valueT;
|
|
141
|
+
}
|
|
142
|
+
readUnionType(stackW, infoForTypeId) {
|
|
143
|
+
const slotTypeId = this.tuple[stackW - 1];
|
|
144
|
+
if (slotTypeId?.type !== 'int') {
|
|
145
|
+
throw new Error(`not 'int' on a stack`);
|
|
146
|
+
}
|
|
147
|
+
const info = infoForTypeId[Number(slotTypeId.value)]; // [stackWidth, label, readFn_T{i}]
|
|
148
|
+
if (info == null) {
|
|
149
|
+
throw new Error(`unexpected UTag=${slotTypeId.value}`);
|
|
150
|
+
}
|
|
151
|
+
const label = info[1];
|
|
152
|
+
this.tuple = this.tuple.slice(stackW - 1 - info[0]);
|
|
153
|
+
const valueT = info[2](this);
|
|
154
|
+
this.tuple.shift();
|
|
155
|
+
return label == null ? valueT : { $: label, value: valueT };
|
|
156
|
+
}
|
|
157
|
+
readCellRef(loadFn_T) {
|
|
158
|
+
return { ref: loadFn_T(this.readCell().beginParse()) };
|
|
159
|
+
}
|
|
160
|
+
readDictionary(keySerializer, valueSerializer) {
|
|
161
|
+
if (this.tuple[0].type === 'null') {
|
|
162
|
+
this.tuple.shift();
|
|
163
|
+
return c.Dictionary.empty(keySerializer, valueSerializer);
|
|
164
|
+
}
|
|
165
|
+
return c.Dictionary.loadDirect(keySerializer, valueSerializer, this.readCell());
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
exports.StackReader = StackReader;
|
|
169
|
+
// When constructing a TVM tuple (when calling a get method), we often need to make cells.
|
|
170
|
+
// For example, given an address, we should result in { type: 'slice', cell: (serialized address) }
|
|
171
|
+
function makeCell(ctx, fieldPath, ty, v) {
|
|
172
|
+
let b = c.beginCell();
|
|
173
|
+
(0, dynamic_serialization_1.dynamicPack)(ctx, fieldPath, ty, v, b); // does validation, throws if invalid, e.g. number instead of address
|
|
174
|
+
return b.endCell();
|
|
175
|
+
}
|
|
176
|
+
// Pack value `v` of type `ty` to a TVM tuple, as an argument of a get method.
|
|
177
|
+
// Parameter `fieldPath` is used for error messages only, e.g. when provided invalid input.
|
|
178
|
+
function dynamicConstruct(ctx, fieldPath, ty, v, tupleIfW = false) {
|
|
179
|
+
if (tupleIfW) { // inside `array<T>` or `[T, ...]`, if T is non-primitive, it's a sub-tuple
|
|
180
|
+
if ((0, types_kernel_1.calcWidthOnStack)(ctx.symbols, ty) === 1) {
|
|
181
|
+
return dynamicConstruct(ctx, fieldPath, ty, v, false);
|
|
182
|
+
}
|
|
183
|
+
return [{ type: 'tuple', items: dynamicConstruct(ctx, fieldPath, ty, v, false) }];
|
|
184
|
+
}
|
|
185
|
+
switch (ty.kind) {
|
|
186
|
+
case 'int':
|
|
187
|
+
case 'intN':
|
|
188
|
+
case 'uintN':
|
|
189
|
+
case 'varintN':
|
|
190
|
+
case 'varuintN':
|
|
191
|
+
case 'coins': {
|
|
192
|
+
(0, dynamic_validation_1.checkIsNumber)(fieldPath, ty, v);
|
|
193
|
+
return [{ type: 'int', value: v }];
|
|
194
|
+
}
|
|
195
|
+
case 'bool': {
|
|
196
|
+
(0, dynamic_validation_1.checkIsBoolean)(fieldPath, ty, v);
|
|
197
|
+
return [{ type: 'int', value: (v ? -1n : 0n) }];
|
|
198
|
+
}
|
|
199
|
+
case 'cell': {
|
|
200
|
+
(0, dynamic_validation_1.checkIsObject)(fieldPath, ty, v);
|
|
201
|
+
return [{ type: 'cell', cell: v }];
|
|
202
|
+
}
|
|
203
|
+
case 'builder': {
|
|
204
|
+
// the call to `makeCell()`, automatically does validation of input (of v)
|
|
205
|
+
return [{ type: 'builder', cell: makeCell(ctx, fieldPath, ty, v) }];
|
|
206
|
+
}
|
|
207
|
+
case 'slice':
|
|
208
|
+
case 'remaining':
|
|
209
|
+
case 'address':
|
|
210
|
+
case 'addressExt':
|
|
211
|
+
case 'addressAny':
|
|
212
|
+
case 'bitsN': {
|
|
213
|
+
return [{ type: 'slice', cell: makeCell(ctx, fieldPath, ty, v) }];
|
|
214
|
+
}
|
|
215
|
+
case 'string': {
|
|
216
|
+
return [{ type: 'cell', cell: makeCell(ctx, fieldPath, ty, v) }];
|
|
217
|
+
}
|
|
218
|
+
case 'addressOpt': {
|
|
219
|
+
if (v === null) {
|
|
220
|
+
return [{ type: 'null' }];
|
|
221
|
+
}
|
|
222
|
+
return [{ type: 'slice', cell: makeCell(ctx, fieldPath, ty, v) }];
|
|
223
|
+
}
|
|
224
|
+
case 'nullLiteral': {
|
|
225
|
+
return [{ type: 'null' }];
|
|
226
|
+
}
|
|
227
|
+
case 'callable': {
|
|
228
|
+
throw new unsupported_errors_1.NotSupportedTypeOnStack(ty, fieldPath);
|
|
229
|
+
}
|
|
230
|
+
case 'void': {
|
|
231
|
+
return [];
|
|
232
|
+
}
|
|
233
|
+
case 'unknown': {
|
|
234
|
+
(0, dynamic_validation_1.checkIsObjectWithProperty)(fieldPath, ty, v, 'type'); // c.TupleItem has 'type'
|
|
235
|
+
return [v];
|
|
236
|
+
}
|
|
237
|
+
case 'nullable': {
|
|
238
|
+
if (ty.stack_type_id) {
|
|
239
|
+
let result = [];
|
|
240
|
+
if (v === null) {
|
|
241
|
+
for (let i = 0; i < ty.stack_width - 1; ++i) {
|
|
242
|
+
result.push({ type: 'null' });
|
|
243
|
+
}
|
|
244
|
+
result.push({ type: 'int', value: 0n });
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
result = dynamicConstruct(ctx, fieldPath, ty.inner, v);
|
|
248
|
+
result.push({ type: 'int', value: BigInt(ty.stack_type_id) });
|
|
249
|
+
}
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
252
|
+
if (v === null) {
|
|
253
|
+
return [{ type: 'null' }];
|
|
254
|
+
}
|
|
255
|
+
return dynamicConstruct(ctx, fieldPath, ty.inner, v);
|
|
256
|
+
}
|
|
257
|
+
case 'cellOf': {
|
|
258
|
+
(0, dynamic_validation_1.checkIsObjectWithProperty)(fieldPath, ty, v, 'ref');
|
|
259
|
+
return [{ type: 'cell', cell: makeCell(ctx, fieldPath, ty.inner, v.ref) }];
|
|
260
|
+
}
|
|
261
|
+
case 'arrayOf': {
|
|
262
|
+
(0, dynamic_validation_1.checkIsArray)(fieldPath, ty, v);
|
|
263
|
+
return [{ type: 'tuple', items: v.map((ith) => dynamicConstruct(ctx, 'ith', ty.inner, ith, true)[0]) }];
|
|
264
|
+
}
|
|
265
|
+
case 'lispListOf': {
|
|
266
|
+
(0, dynamic_validation_1.checkIsArray)(fieldPath, ty, v);
|
|
267
|
+
return [v.reduceRight((tail, head) => ({ type: 'tuple', items: [dynamicConstruct(ctx, 'head', ty.inner, head, true)[0], tail] }), { type: 'null' })];
|
|
268
|
+
}
|
|
269
|
+
case 'tensor': {
|
|
270
|
+
(0, dynamic_validation_1.checkIsArray)(fieldPath, ty, v, ty.items.length);
|
|
271
|
+
return v.flatMap((item, idx) => dynamicConstruct(ctx, `${fieldPath}[${idx}]`, ty.items[idx], item));
|
|
272
|
+
}
|
|
273
|
+
case 'shapedTuple': {
|
|
274
|
+
(0, dynamic_validation_1.checkIsArray)(fieldPath, ty, v, ty.items.length);
|
|
275
|
+
return [{ type: 'tuple', items: v.map((ith, idx) => dynamicConstruct(ctx, `${fieldPath}[${idx}]`, ty.items[idx], ith, true)[0]) }];
|
|
276
|
+
}
|
|
277
|
+
case 'mapKV': {
|
|
278
|
+
(0, dynamic_validation_1.checkIsObject)(fieldPath, ty, v);
|
|
279
|
+
if (v.size === 0) {
|
|
280
|
+
return [{ type: 'null' }];
|
|
281
|
+
}
|
|
282
|
+
let dictKey = (0, dynamic_serialization_1.createTonCoreDictionaryKey)(fieldPath, ty.k);
|
|
283
|
+
let dictValue = (0, dynamic_serialization_1.createTonCoreDictionaryValue)(ctx, fieldPath, ty.v);
|
|
284
|
+
return [{ type: 'cell', cell: c.beginCell().storeDictDirect(v, dictKey, dictValue).endCell() }];
|
|
285
|
+
}
|
|
286
|
+
case 'EnumRef': {
|
|
287
|
+
(0, dynamic_validation_1.checkIsNumber)(fieldPath, ty, v);
|
|
288
|
+
return [{ type: 'int', value: v }];
|
|
289
|
+
}
|
|
290
|
+
case 'StructRef': {
|
|
291
|
+
(0, dynamic_validation_1.checkIsObject)(fieldPath, ty, v);
|
|
292
|
+
let structRef = ctx.symbols.getStruct(ty.struct_name);
|
|
293
|
+
return structRef.fields.flatMap(f => {
|
|
294
|
+
const fTy = ty.type_args ? (0, types_kernel_1.instantiateGenerics)(f.ty, structRef.type_params, ty.type_args) : f.ty;
|
|
295
|
+
return dynamicConstruct(ctx, `${fieldPath}.${f.name}`, fTy, v[f.name]);
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
case 'AliasRef': {
|
|
299
|
+
let aliasRef = ctx.symbols.getAlias(ty.alias_name);
|
|
300
|
+
const targetTy = ty.type_args ? (0, types_kernel_1.instantiateGenerics)(aliasRef.target_ty, aliasRef.type_params, ty.type_args) : aliasRef.target_ty;
|
|
301
|
+
return dynamicConstruct(ctx, fieldPath, targetTy, v);
|
|
302
|
+
}
|
|
303
|
+
case 'union': {
|
|
304
|
+
const variants = (0, types_kernel_1.createLabelsForUnion)(ctx.symbols, ty.variants);
|
|
305
|
+
const hasNull = variants.find(v => v.variant_ty.kind === 'nullLiteral');
|
|
306
|
+
let result = [];
|
|
307
|
+
if (hasNull && v === null) {
|
|
308
|
+
for (let i = 0; i < ty.stack_width - 1; ++i) {
|
|
309
|
+
result.push({ type: 'null' });
|
|
310
|
+
}
|
|
311
|
+
result.push({ type: 'int', value: 0n });
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
(0, dynamic_validation_1.checkIsObjectWithProperty)(fieldPath, ty, v, '$');
|
|
315
|
+
const activeVariant = variants.find(variant => v.$ === variant.labelStr);
|
|
316
|
+
if (!activeVariant) {
|
|
317
|
+
(0, dynamic_validation_1.throwInvalidInput)(fieldPath, ty, `non-existing union variant for $ = '${v.$}'`);
|
|
318
|
+
}
|
|
319
|
+
if (activeVariant.hasValueField && !v.hasOwnProperty('value')) {
|
|
320
|
+
(0, dynamic_validation_1.throwInvalidInput)(fieldPath, ty, `expected {$,value} but field 'value' not provided`);
|
|
321
|
+
}
|
|
322
|
+
for (let i = 0; i < ty.stack_width - 1 - activeVariant.stack_width; ++i) {
|
|
323
|
+
result.push({ type: 'null' });
|
|
324
|
+
}
|
|
325
|
+
let actualValue = activeVariant.hasValueField ? v.value : v;
|
|
326
|
+
result.push(...dynamicConstruct(ctx, `${fieldPath}#${activeVariant.labelStr}`, activeVariant.variant_ty, actualValue));
|
|
327
|
+
result.push({ type: 'int', value: BigInt(activeVariant.stack_type_id) });
|
|
328
|
+
}
|
|
329
|
+
return result;
|
|
330
|
+
}
|
|
331
|
+
case 'genericT': throw new Error(`unexpected genericT=${ty.name_t} at ${fieldPath}`);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
// Parse `ty` from a TVM tuple on a stack, returned as a result of a get method invocation.
|
|
335
|
+
// Parameter `fieldPath` is used for error messages only, e.g. when can't deserialize CellRef<T>.
|
|
336
|
+
function dynamicParse(ctx, r, fieldPath, ty, unTupleIfW = false) {
|
|
337
|
+
if (unTupleIfW) { // inside `array<T>` or `[T, ...]`, if T is non-primitive, it's a sub-tuple
|
|
338
|
+
let wOnStack = (0, types_kernel_1.calcWidthOnStack)(ctx.symbols, ty);
|
|
339
|
+
if (wOnStack !== 1) {
|
|
340
|
+
return r.readTuple(wOnStack, (r) => dynamicParse(ctx, r, fieldPath, ty, false));
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
switch (ty.kind) {
|
|
344
|
+
case 'int':
|
|
345
|
+
case 'intN':
|
|
346
|
+
case 'uintN':
|
|
347
|
+
case 'varintN':
|
|
348
|
+
case 'varuintN':
|
|
349
|
+
case 'coins': return r.readBigInt();
|
|
350
|
+
case 'bool': return r.readBoolean();
|
|
351
|
+
case 'cell': return r.readCell();
|
|
352
|
+
case 'builder': return r.readBuilder();
|
|
353
|
+
case 'slice': return r.readSlice();
|
|
354
|
+
case 'string': return r.readSnakeString();
|
|
355
|
+
case 'remaining': return r.readSlice();
|
|
356
|
+
case 'address': return r.readSlice().loadAddress();
|
|
357
|
+
case 'addressOpt': return dynamicParse(ctx, r, fieldPath, { kind: 'nullable', inner: { kind: 'address' } });
|
|
358
|
+
case 'addressExt': return r.readSlice().loadExternalAddress();
|
|
359
|
+
case 'addressAny': return (0, dynamic_serialization_1.dynamicUnpack)(ctx, fieldPath, ty, r.readSlice());
|
|
360
|
+
case 'bitsN': return r.readSlice();
|
|
361
|
+
case 'nullLiteral': return r.readNullLiteral();
|
|
362
|
+
case 'callable': throw new unsupported_errors_1.NotSupportedTypeOnStack(ty, fieldPath);
|
|
363
|
+
case 'void': return void 0;
|
|
364
|
+
case 'unknown': return r.readUnknown();
|
|
365
|
+
case 'nullable': {
|
|
366
|
+
if (ty.stack_type_id) {
|
|
367
|
+
return r.readWideNullable(ty.stack_width, (r) => dynamicParse(ctx, r, fieldPath, ty.inner));
|
|
368
|
+
}
|
|
369
|
+
return r.readNullable((r) => dynamicParse(ctx, r, fieldPath, ty.inner));
|
|
370
|
+
}
|
|
371
|
+
case 'cellOf': return r.readCellRef((s) => (0, dynamic_serialization_1.dynamicUnpack)(ctx, fieldPath, ty.inner, s));
|
|
372
|
+
case 'arrayOf': return r.readArrayOf((r) => dynamicParse(ctx, r, fieldPath, ty.inner, true));
|
|
373
|
+
case 'lispListOf': return r.readLispListOf((r) => dynamicParse(ctx, r, fieldPath, ty.inner, true));
|
|
374
|
+
case 'tensor': {
|
|
375
|
+
let result = [];
|
|
376
|
+
for (let i = 0; i < ty.items.length; ++i) {
|
|
377
|
+
result.push(dynamicParse(ctx, r, `${fieldPath}[${i}]`, ty.items[i]));
|
|
378
|
+
}
|
|
379
|
+
return result;
|
|
380
|
+
}
|
|
381
|
+
case 'shapedTuple': {
|
|
382
|
+
return r.readTuple(ty.items.length, (r) => {
|
|
383
|
+
let result = [];
|
|
384
|
+
for (let i = 0; i < ty.items.length; ++i) {
|
|
385
|
+
result.push(dynamicParse(ctx, r, `${fieldPath}[${i}]`, ty.items[i], true));
|
|
386
|
+
}
|
|
387
|
+
return result;
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
case 'mapKV': {
|
|
391
|
+
let dictKey = (0, dynamic_serialization_1.createTonCoreDictionaryKey)(fieldPath, ty.k);
|
|
392
|
+
let dictValue = (0, dynamic_serialization_1.createTonCoreDictionaryValue)(ctx, fieldPath, ty.v);
|
|
393
|
+
return r.readDictionary(dictKey, dictValue);
|
|
394
|
+
}
|
|
395
|
+
case 'EnumRef': return r.readBigInt();
|
|
396
|
+
case 'StructRef': {
|
|
397
|
+
const structRef = ctx.symbols.getStruct(ty.struct_name);
|
|
398
|
+
let result = { $: ty.struct_name };
|
|
399
|
+
for (let f of structRef.fields) {
|
|
400
|
+
const fTy = ty.type_args ? (0, types_kernel_1.instantiateGenerics)(f.ty, structRef.type_params, ty.type_args) : f.ty;
|
|
401
|
+
result[f.name] = dynamicParse(ctx, r, `${fieldPath}.${f.name}`, fTy);
|
|
402
|
+
}
|
|
403
|
+
return result;
|
|
404
|
+
}
|
|
405
|
+
case 'AliasRef': {
|
|
406
|
+
const aliasRef = ctx.symbols.getAlias(ty.alias_name);
|
|
407
|
+
const targetTy = ty.type_args ? (0, types_kernel_1.instantiateGenerics)(aliasRef.target_ty, aliasRef.type_params, ty.type_args) : aliasRef.target_ty;
|
|
408
|
+
return dynamicParse(ctx, r, fieldPath, targetTy);
|
|
409
|
+
}
|
|
410
|
+
case 'genericT': throw new Error(`unexpected genericT=${ty.name_t} at ${fieldPath}`);
|
|
411
|
+
case 'union': {
|
|
412
|
+
const variants = (0, types_kernel_1.createLabelsForUnion)(ctx.symbols, ty.variants);
|
|
413
|
+
const infoForTypeId = {};
|
|
414
|
+
for (let v of variants) {
|
|
415
|
+
infoForTypeId[v.stack_type_id] = [v.stack_width, v.hasValueField ? v.labelStr : null,
|
|
416
|
+
(r) => dynamicParse(ctx, r, `${fieldPath}#${v.labelStr}`, v.variant_ty)
|
|
417
|
+
];
|
|
418
|
+
}
|
|
419
|
+
return r.readUnionType(ty.stack_width, infoForTypeId);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Pack any `value` of type `ty` to a TVM tuple.
|
|
425
|
+
* This tuple can be used as a get method argument or debug-printed as human-readable.
|
|
426
|
+
*/
|
|
427
|
+
function makeTvmTupleDynamic(ctx, ty, value) {
|
|
428
|
+
return dynamicConstruct(ctx, 'value', ty, value);
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Invoke any get method taking plain JS variables as arguments and interpreting the resulting TVM tuple according to ABI.
|
|
432
|
+
* Example: `get fun intAndPoint(i: int, p: Point): Point`.
|
|
433
|
+
* Call: `callGetMethodDynamic(provider, ctx, 'intAndPoint', [num, {x: num, y: num}])` returns `{x: num, y: num}`.
|
|
434
|
+
* When input is incorrect (e.g. missing property in a JS object), throws InvalidDynamicInput.
|
|
435
|
+
*/
|
|
436
|
+
async function callGetMethodDynamic(provider, ctx, getMethodName, args) {
|
|
437
|
+
const getM = ctx.findGetMethod(getMethodName);
|
|
438
|
+
if (getM == null) {
|
|
439
|
+
throw new unsupported_errors_1.CantCallGetMethodDynamic(getMethodName, `method not found in contract ${ctx.contractName}`);
|
|
440
|
+
}
|
|
441
|
+
if (getM.parameters.length !== args.length) { // default parameters not supported, dynamic invocation should provide all
|
|
442
|
+
throw new unsupported_errors_1.CantCallGetMethodDynamic(getMethodName, `expected ${getM.parameters.length} arguments, got ${args.length}`);
|
|
443
|
+
}
|
|
444
|
+
const stackIn = [];
|
|
445
|
+
for (let i = 0; i < args.length; ++i) {
|
|
446
|
+
stackIn.push(...dynamicConstruct(ctx, getM.parameters[i].name, getM.parameters[i].ty, args[i]));
|
|
447
|
+
}
|
|
448
|
+
const expectedSlotsOut = (0, types_kernel_1.calcWidthOnStack)(ctx.symbols, getM.return_ty);
|
|
449
|
+
const r = StackReader.fromGetMethod(expectedSlotsOut, await provider.get(getMethodName, stackIn));
|
|
450
|
+
return dynamicParse(ctx, r, 'result', getM.return_ty);
|
|
451
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as c from '@ton/core';
|
|
2
|
+
import type { Ty } from './abi-types';
|
|
3
|
+
import { DynamicCtx } from './dynamic-ctx';
|
|
4
|
+
export declare function createTonCoreDictionaryKey(fieldPath: string, tyK: Ty): c.DictionaryKey<any>;
|
|
5
|
+
export declare function createTonCoreDictionaryValue(ctx: DynamicCtx, fieldPath: string, tyV: Ty): c.DictionaryValue<any>;
|
|
6
|
+
export declare function dynamicPack(ctx: DynamicCtx, fieldPath: string, ty: Ty, v: any, b: c.Builder): void;
|
|
7
|
+
export declare function dynamicUnpack(ctx: DynamicCtx, fieldPath: string, ty: Ty, s: c.Slice): any;
|
|
8
|
+
/**
|
|
9
|
+
* Pack any input to a builder according to an ABI schema.
|
|
10
|
+
* Example: `struct Point { x: int8, y: int8 }`.
|
|
11
|
+
* After being converted, it's stored as ABI.
|
|
12
|
+
* Call: `packToBuilderDynamic(ctx, structTy, { x: 10, y: 20 }, b)` appends 0x0A14.
|
|
13
|
+
* When input is incorrect (e.g. missing property in a JS object), throws InvalidDynamicInput.
|
|
14
|
+
*/
|
|
15
|
+
export declare function packToBuilderDynamic(ctx: DynamicCtx, ty: Ty, value: any, b: c.Builder): void;
|
|
16
|
+
/**
|
|
17
|
+
* Unpack any slice to a JS variable according to an ABI schema.
|
|
18
|
+
* Example: `struct Point { x: int8, y: int8 }`.
|
|
19
|
+
* Call: `unpackFromSliceDynamic(ctx, structTy, hex"0A14")` returns `{ x: 10, y: 20 }`.
|
|
20
|
+
* When ty can't be deserialized, throws CantUnpackDynamic.
|
|
21
|
+
*/
|
|
22
|
+
export declare function unpackFromSliceDynamic(ctx: DynamicCtx, ty: Ty, s: c.Slice): any;
|