@tychosdk/disasm 0.1.3 → 0.1.5

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.
@@ -0,0 +1,4 @@
1
+ import { Cell } from "@ton/core";
2
+ export declare function disasmToFift(code: Cell | string, params?: {
3
+ tabWidth?: number;
4
+ }): Promise<string>;
@@ -0,0 +1,460 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.disasmToFift = disasmToFift;
4
+ const core_1 = require("@ton/core");
5
+ const structured_1 = require("./structured");
6
+ async function disasmToFift(code, params = {}) {
7
+ const { root, items } = await (0, structured_1.disasmStructured)(code);
8
+ const codeCells = new CodeCells(code);
9
+ const ctx = new Context(items, codeCells, {
10
+ tabWidth: params.tabWidth != null ? params.tabWidth : 2,
11
+ });
12
+ new State(ctx, 0).disasm(ctx.getCode(root));
13
+ return ctx.output;
14
+ }
15
+ class CodeCells {
16
+ constructor(code) {
17
+ this.hashToCell = new Map();
18
+ const stack = [];
19
+ if (code instanceof core_1.Cell) {
20
+ stack.push(code);
21
+ }
22
+ else {
23
+ stack.push(core_1.Cell.fromBase64(code));
24
+ }
25
+ while (stack.length > 0) {
26
+ const cell = stack[stack.length - 1];
27
+ const reprHash = cell.hash(3).toString("hex");
28
+ if (this.hashToCell.has(reprHash)) {
29
+ stack.pop();
30
+ }
31
+ else {
32
+ this.hashToCell.set(reprHash, cell);
33
+ for (const child of cell.refs) {
34
+ stack.push(child);
35
+ }
36
+ }
37
+ }
38
+ }
39
+ getCell(hash) {
40
+ const res = this.hashToCell.get(hash);
41
+ if (res == null)
42
+ throw new Error("Unknown cell");
43
+ return res;
44
+ }
45
+ }
46
+ class State {
47
+ constructor(ctx, depth) {
48
+ this.ctx = ctx;
49
+ this.depth = depth;
50
+ }
51
+ disasm(block) {
52
+ while (true) {
53
+ for (const opcode of block.opcodes) {
54
+ this.showOp(opcode);
55
+ }
56
+ if (block.tail == null) {
57
+ break;
58
+ }
59
+ else if (block.tail.type === "incomplete") {
60
+ this.writeln("Cannot disassemble");
61
+ break;
62
+ }
63
+ else {
64
+ block = this.ctx.getCode(block.tail.id);
65
+ }
66
+ }
67
+ this.dict = undefined;
68
+ this.flushCont();
69
+ }
70
+ showOp(opcode) {
71
+ // Track consequent dict ops.
72
+ switch (opcode.name) {
73
+ case "DICTPUSHCONST": {
74
+ const [n, dict] = opcode.args;
75
+ (0, structured_1.expectIntArg)(n);
76
+ (0, structured_1.expectSliceArg)(dict);
77
+ this.flushCont();
78
+ this.dict = this.ctx.getJumpTable(dict.id);
79
+ this.showSimpleOp(opcode);
80
+ return;
81
+ }
82
+ case "DICTIGETJMP":
83
+ case "DICTIGETJMPZ":
84
+ case "DICTUGETJMP":
85
+ case "DICTUGETJMPZ":
86
+ case "DICTIGETEXEC":
87
+ case "DICTUGETEXEC": {
88
+ if (this.dict != null) {
89
+ this.flushCont();
90
+ this.showConstDictOp(opcode);
91
+ return;
92
+ }
93
+ break;
94
+ }
95
+ }
96
+ // Reset dict.
97
+ this.dict = undefined;
98
+ // Track consequent cont ops.
99
+ switch (opcode.name) {
100
+ case "PUSHCONT":
101
+ case "PUSHREFCONT": {
102
+ const [cont] = opcode.args;
103
+ (0, structured_1.expectContArg)(cont);
104
+ this.saveContBody(this.ctx.getCode(cont.id));
105
+ return;
106
+ }
107
+ case "REPEAT":
108
+ case "UNTIL":
109
+ case "IF":
110
+ case "IFNOT":
111
+ case "IFJMP":
112
+ case "IFNOTJMP": {
113
+ if (this.contX != null) {
114
+ this.flushContY();
115
+ this.showContOp(opcode.name);
116
+ return;
117
+ }
118
+ break;
119
+ }
120
+ case "IFREF":
121
+ case "IFNOTREF":
122
+ case "IFJMPREF":
123
+ case "IFNOTJMPREF":
124
+ case "CALLREF":
125
+ case "JMPREF": {
126
+ this.flushCont();
127
+ this.showRefOp(opcode);
128
+ return;
129
+ }
130
+ case "WHILE": {
131
+ if (this.contY != null) {
132
+ this.showCont2Op("WHILE", "DO");
133
+ return;
134
+ }
135
+ break;
136
+ }
137
+ case "IFELSE": {
138
+ if (this.contY != null) {
139
+ this.showCont2Op("IF", "ELSE");
140
+ return;
141
+ }
142
+ break;
143
+ }
144
+ case "IFREFELSE": {
145
+ if (this.contX != null) {
146
+ this.showContRefOp(opcode, "IF", "ELSE", false);
147
+ return;
148
+ }
149
+ break;
150
+ }
151
+ case "IFELSEREF": {
152
+ if (this.contX != null) {
153
+ this.showContRefOp(opcode, "IF", "ELSE", true);
154
+ return;
155
+ }
156
+ break;
157
+ }
158
+ case "IFREFELSEREF": {
159
+ this.showRef2Op(opcode, "IF", "ELSE");
160
+ return;
161
+ }
162
+ }
163
+ // Fallback to simple opcode.
164
+ this.flushCont();
165
+ this.showSimpleOp(opcode);
166
+ }
167
+ showSimpleOp(opcode) {
168
+ opcode = this.adjustOpcode(opcode);
169
+ let args = "";
170
+ if (opcode.args != null) {
171
+ for (const arg of opcode.args) {
172
+ args += `${this.ctx.argToString(arg)} `;
173
+ }
174
+ }
175
+ this.writeln(`${args}${opcode.name}`);
176
+ }
177
+ adjustOpcode(opcode) {
178
+ switch (opcode.name) {
179
+ case "SETCP0": {
180
+ if (opcode.args == null || opcode.args.length === 0) {
181
+ return {
182
+ ...opcode,
183
+ name: "SETCP",
184
+ args: [{ type: "int", value: "0" }],
185
+ };
186
+ }
187
+ break;
188
+ }
189
+ case "XCHG": {
190
+ if (opcode.args != null && opcode.args.length === 1) {
191
+ return {
192
+ ...opcode,
193
+ args: [{ type: "stack", idx: 0 }, ...opcode.args],
194
+ };
195
+ }
196
+ break;
197
+ }
198
+ case "LSHIFT": {
199
+ if (opcode.args != null && opcode.args.length > 0) {
200
+ return {
201
+ ...opcode,
202
+ name: "LSHIFT#",
203
+ };
204
+ }
205
+ break;
206
+ }
207
+ case "RSHIFT": {
208
+ if (opcode.args != null && opcode.args.length > 0) {
209
+ return {
210
+ ...opcode,
211
+ name: "RSHIFT#",
212
+ };
213
+ }
214
+ break;
215
+ }
216
+ }
217
+ // Fallback to the original.
218
+ return opcode;
219
+ }
220
+ showRefOp(opcode) {
221
+ this.flushCont();
222
+ const [ref] = opcode.args;
223
+ (0, structured_1.expectCellArg)(ref);
224
+ this.writeln(`${opcode.name.slice(0, -3)}:<{`);
225
+ this.depth += 1;
226
+ this.disasm(this.ctx.getCode(ref.id));
227
+ this.depth -= 1;
228
+ this.writeln("}>");
229
+ if (this.contX != null) {
230
+ throw new Error("Invalid cont state");
231
+ }
232
+ }
233
+ showContRefOp(opcode, prefix, infix, firstIsCont) {
234
+ this.flushContY();
235
+ const [ref] = opcode.args;
236
+ (0, structured_1.expectCellArg)(ref);
237
+ this.writeln(`${prefix}:<{`);
238
+ if (this.contX == null)
239
+ throw new Error("Inconsistent contX state");
240
+ const branches = [this.ctx.getCode(ref.id), this.contX];
241
+ this.contX = undefined;
242
+ this.depth += 1;
243
+ this.disasm(branches[+firstIsCont]);
244
+ this.depth -= 1;
245
+ this.writeln(`}>${infix}<{`);
246
+ this.depth += 1;
247
+ this.disasm(branches[+!firstIsCont]);
248
+ this.depth -= 1;
249
+ this.writeln("}>");
250
+ }
251
+ showRef2Op(opcode, prefix, infix) {
252
+ this.flushCont();
253
+ const [ref1, ref2] = opcode.args;
254
+ (0, structured_1.expectCellArg)(ref1);
255
+ (0, structured_1.expectCellArg)(ref2);
256
+ this.writeln(`${prefix}:<{`);
257
+ this.depth += 1;
258
+ this.disasm(this.ctx.getCode(ref1.id));
259
+ this.depth -= 1;
260
+ this.writeln(`}>${infix}<{`);
261
+ this.depth += 1;
262
+ this.disasm(this.ctx.getCode(ref2.id));
263
+ this.depth -= 1;
264
+ this.writeln("}>");
265
+ if (this.contX != null) {
266
+ throw new Error("Invalid cont state");
267
+ }
268
+ }
269
+ showContOp(prefix) {
270
+ this.showContBody(prefix, ":<{");
271
+ this.writeln("}>");
272
+ if (this.contX != null) {
273
+ throw new Error("Invalid cont state");
274
+ }
275
+ }
276
+ showCont2Op(prefix, infix) {
277
+ this.swapCont();
278
+ this.showContBody(prefix, ":<{");
279
+ this.swapCont();
280
+ this.showContBody(`}>${infix}`, "<{");
281
+ this.writeln("}>");
282
+ if (this.contX != null || this.contY != null) {
283
+ throw new Error("Invalid cont state");
284
+ }
285
+ }
286
+ showConstDictOp(opcode) {
287
+ this.flushCont();
288
+ if (this.dict == null)
289
+ throw new Error("Inconsistent dict state");
290
+ const dictItems = Object.entries(this.dict.items).map(([key, value]) => ({
291
+ key: BigInt(key),
292
+ value,
293
+ }));
294
+ dictItems.sort(({ key: a }, { key: b }) => (a < b ? -1 : a > b ? 1 : 0));
295
+ if (dictItems.length === 0) {
296
+ this.writeln(`${opcode.name} {}`);
297
+ }
298
+ else {
299
+ this.writeln(`${opcode.name} {`);
300
+ this.depth += 1;
301
+ for (const item of dictItems) {
302
+ this.writeln(`${item.key} => <{`);
303
+ new State(this.ctx, this.depth + 1).disasm(this.ctx.getCode(item.value));
304
+ this.writeln("}>");
305
+ }
306
+ this.depth -= 1;
307
+ this.writeln("}");
308
+ }
309
+ this.dict = undefined;
310
+ }
311
+ showContBody(prefix, paren) {
312
+ if (this.contX == null)
313
+ throw new Error("Inconsistent contX state");
314
+ this.writeln(`${prefix}${paren}`);
315
+ new State(this.ctx, this.depth + 1).disasm(this.contX);
316
+ this.contX = undefined;
317
+ }
318
+ flushContX() {
319
+ if (this.contX != null) {
320
+ this.showContOp("CONT");
321
+ }
322
+ }
323
+ flushContY() {
324
+ if (this.contY != null) {
325
+ this.swapCont();
326
+ this.showContOp("CONT");
327
+ this.swapCont();
328
+ }
329
+ }
330
+ flushCont() {
331
+ this.flushContY();
332
+ this.flushContX();
333
+ }
334
+ saveContBody(cont) {
335
+ this.flushContY();
336
+ this.contY = cont;
337
+ this.swapCont();
338
+ }
339
+ swapCont() {
340
+ const contY = this.contY;
341
+ this.contY = this.contX;
342
+ this.contX = contY;
343
+ }
344
+ writeln(data) {
345
+ this.ctx.writeln(this.depth, data);
346
+ }
347
+ }
348
+ class Context {
349
+ constructor(items, cells, params) {
350
+ this.items = items;
351
+ this.cells = cells;
352
+ this.string = "";
353
+ this.tab = " ".repeat(params.tabWidth);
354
+ }
355
+ get output() {
356
+ return this.string;
357
+ }
358
+ writeln(indent, data) {
359
+ this.string += `${this.tab.repeat(indent)}${data}\n`;
360
+ }
361
+ argToString(arg) {
362
+ switch (arg.type) {
363
+ case "int":
364
+ return arg.value;
365
+ case "stack": {
366
+ if (arg.idx < 0) {
367
+ return `s(${arg.idx})`;
368
+ }
369
+ else {
370
+ return `s${arg.idx}`;
371
+ }
372
+ }
373
+ case "reg": {
374
+ return `c${arg.idx}`;
375
+ }
376
+ case "cell": {
377
+ const item = this.items[arg.id];
378
+ let cellHash;
379
+ switch (item.type) {
380
+ case "code": {
381
+ if (item.isInline)
382
+ throw new Error("Unexpected inline cont");
383
+ cellHash = item.cellHash;
384
+ break;
385
+ }
386
+ case "library": {
387
+ cellHash = item.hash;
388
+ break;
389
+ }
390
+ case "dataBlock": {
391
+ if (item.data.type !== "cell")
392
+ throw new Error("Unexpected slice");
393
+ cellHash = core_1.Cell.fromBase64(item.data.boc).hash(3).toString("hex");
394
+ break;
395
+ }
396
+ case "jumpTable": {
397
+ throw new Error("Unexpected jump table");
398
+ }
399
+ }
400
+ return `(${cellHash})`;
401
+ }
402
+ case "slice": {
403
+ const item = this.items[arg.id];
404
+ let bits;
405
+ let refCount;
406
+ switch (item.type) {
407
+ case "code": {
408
+ if (!item.isInline)
409
+ throw new Error("Unexpected non-inline cont");
410
+ const cell = this.getCell(item.cellHash);
411
+ bits = cell.asSlice().skip(item.offsetBits).loadBits(item.bits);
412
+ refCount = item.refs;
413
+ break;
414
+ }
415
+ case "dataBlock": {
416
+ if (item.data.type !== "slice")
417
+ throw new Error("Unexpected cell");
418
+ const slice = core_1.Cell.fromBase64(item.data.boc).asSlice();
419
+ bits = slice.loadBits(item.data.bits);
420
+ refCount = item.data.refs;
421
+ break;
422
+ }
423
+ case "jumpTable": {
424
+ // NOTE: Jump table is always shown like this.
425
+ return "(xC_)";
426
+ }
427
+ case "library": {
428
+ throw new Error("Unexpected library cell");
429
+ }
430
+ }
431
+ if (refCount > 0) {
432
+ return `(${bits.toString()},${refCount})`;
433
+ }
434
+ else {
435
+ return bits.toString();
436
+ }
437
+ }
438
+ }
439
+ }
440
+ getCell(hash) {
441
+ return this.cells.getCell(hash);
442
+ }
443
+ getCode(id) {
444
+ const item = this.items[id];
445
+ if (item.type === "library") {
446
+ throw new Error("Library cells are not supported for now");
447
+ }
448
+ else if (item.type !== "code") {
449
+ throw new Error(`Unexpected item: ${item.type}`);
450
+ }
451
+ return item;
452
+ }
453
+ getJumpTable(id) {
454
+ const item = this.items[id];
455
+ if (item.type !== "jumpTable") {
456
+ throw new Error(`Unexpected item: ${item.type}`);
457
+ }
458
+ return item;
459
+ }
460
+ }
@@ -0,0 +1,160 @@
1
+ import { Cell } from "@ton/core";
2
+ /**
3
+ * All code parts are referenced by a numberic ID.
4
+ */
5
+ export type ItemId = number;
6
+ /**
7
+ * Code is a group of parsed parts and an index from which to start.
8
+ */
9
+ export type Code = {
10
+ root: ItemId;
11
+ items: Item[];
12
+ };
13
+ export type Item = ({
14
+ id: number;
15
+ type: "jumpTable";
16
+ } & JumpTable) | ({
17
+ id: number;
18
+ type: "code";
19
+ } & CodeBlock) | ({
20
+ id: number;
21
+ type: "dataBlock";
22
+ } & DataBlock) | ({
23
+ id: number;
24
+ type: "library";
25
+ } & Library);
26
+ export type ItemType = Item["type"];
27
+ /**
28
+ * Jump table is a dictionary which maps int to some continuations.
29
+ */
30
+ export type JumpTable = {
31
+ cellHash: string;
32
+ keyBits: number;
33
+ items: Record<string, ItemId>;
34
+ isFullCode: boolean;
35
+ };
36
+ /**
37
+ * Parsed continuation.
38
+ */
39
+ export type CodeBlock = {
40
+ cellHash: string;
41
+ isInline: boolean;
42
+ offsetBits: number;
43
+ offsetRefs: number;
44
+ bits: number;
45
+ refs: number;
46
+ opcodes: Opcode[];
47
+ tail?: CodeBlockTail;
48
+ };
49
+ /**
50
+ * What follows the continuation.
51
+ */
52
+ export type CodeBlockTail = {
53
+ type: "incomplete";
54
+ } | {
55
+ type: "child";
56
+ id: ItemId;
57
+ };
58
+ export type CodeBlockTailType = CodeBlockTail["type"];
59
+ /**
60
+ * Parsed opcode.
61
+ */
62
+ export type Opcode = {
63
+ bits: number;
64
+ refs?: number;
65
+ name: string;
66
+ args?: OpcodeArg[];
67
+ gas: number;
68
+ };
69
+ /**
70
+ * Parsed opcode argument.
71
+ */
72
+ export type OpcodeArg = {
73
+ type: "int";
74
+ value: string;
75
+ } | {
76
+ type: "stack";
77
+ idx: number;
78
+ } | {
79
+ type: "reg";
80
+ idx: number;
81
+ } | {
82
+ type: "cell";
83
+ id: ItemId;
84
+ } | {
85
+ type: "slice";
86
+ id: ItemId;
87
+ };
88
+ export type OpcodeArgType = OpcodeArg["type"];
89
+ /**
90
+ * Cell tree parts that are treated as data.
91
+ */
92
+ export type DataBlock = {
93
+ data: Data;
94
+ };
95
+ export type Data = ({
96
+ type: "slice";
97
+ } & DataSlice) | ({
98
+ type: "cell";
99
+ } & DataCell);
100
+ export type DataType = Data["type"];
101
+ export type DataSlice = {
102
+ offsetBits: number;
103
+ offsetRefs: number;
104
+ bits: number;
105
+ refs: number;
106
+ boc: string;
107
+ };
108
+ export type DataCell = {
109
+ boc: string;
110
+ };
111
+ export type Library = {
112
+ hash: string;
113
+ };
114
+ export declare function disasmStructured(code: Cell | string): Promise<Code>;
115
+ export declare function expectJumpTable(item: Item): asserts item is {
116
+ id: ItemId;
117
+ type: "jumpTable";
118
+ } & JumpTable;
119
+ export declare function expectCont(item: Item): asserts item is {
120
+ id: ItemId;
121
+ type: "code";
122
+ } & CodeBlock;
123
+ export declare function expectLibrary(item: Item): asserts item is {
124
+ id: ItemId;
125
+ type: "library";
126
+ } & Library;
127
+ export declare function expectData(item: Item): asserts item is {
128
+ id: ItemId;
129
+ type: "data";
130
+ } & Data;
131
+ export declare function expectDataSlice(item: Data): asserts item is {
132
+ type: "slice";
133
+ } & DataSlice;
134
+ export declare function expectDataCell(item: Data): asserts item is {
135
+ type: "cell";
136
+ } & DataCell;
137
+ export declare function expectIntArg(opcode: OpcodeArg): asserts opcode is {
138
+ type: "int";
139
+ value: "string";
140
+ };
141
+ export declare function expectStackArg(opcode: OpcodeArg): asserts opcode is {
142
+ type: "stack";
143
+ idx: number;
144
+ };
145
+ export declare function expectRegArg(opcode: OpcodeArg): asserts opcode is {
146
+ type: "reg";
147
+ idx: number;
148
+ };
149
+ export declare function expectCellArg(opcode: OpcodeArg): asserts opcode is {
150
+ type: "cell";
151
+ id: ItemId;
152
+ };
153
+ export declare function expectSliceArg(opcode: OpcodeArg): asserts opcode is {
154
+ type: "slice";
155
+ id: ItemId;
156
+ };
157
+ export declare function expectContArg(opcode: OpcodeArg): asserts opcode is {
158
+ type: "cell" | "slice";
159
+ id: ItemId;
160
+ };
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.disasmStructured = disasmStructured;
4
+ exports.expectJumpTable = expectJumpTable;
5
+ exports.expectCont = expectCont;
6
+ exports.expectLibrary = expectLibrary;
7
+ exports.expectData = expectData;
8
+ exports.expectDataSlice = expectDataSlice;
9
+ exports.expectDataCell = expectDataCell;
10
+ exports.expectIntArg = expectIntArg;
11
+ exports.expectStackArg = expectStackArg;
12
+ exports.expectRegArg = expectRegArg;
13
+ exports.expectCellArg = expectCellArg;
14
+ exports.expectSliceArg = expectSliceArg;
15
+ exports.expectContArg = expectContArg;
16
+ const core_1 = require("@ton/core");
17
+ const env_1 = require("../env");
18
+ async function disasmStructured(code) {
19
+ await (0, env_1.wasmLoaded)();
20
+ let boc;
21
+ if (code instanceof core_1.Cell) {
22
+ boc = code.toBoc({ idx: false }).toString("base64");
23
+ }
24
+ else {
25
+ boc = code;
26
+ }
27
+ const res = env_1.wasm.disasm_structured(boc);
28
+ const parsed = JSON.parse(res);
29
+ return parsed;
30
+ }
31
+ // === Expect Item ===
32
+ function expectJumpTable(item) {
33
+ if (item.type !== "jumpTable")
34
+ throw new Error("Expected jump table item");
35
+ }
36
+ function expectCont(item) {
37
+ if (item.type !== "code")
38
+ throw new Error("Expected code item");
39
+ }
40
+ function expectLibrary(item) {
41
+ if (item.type !== "code")
42
+ throw new Error("Expected library item");
43
+ }
44
+ function expectData(item) {
45
+ if (item.type !== "code")
46
+ throw new Error("Expected data item");
47
+ }
48
+ // === Expect Data ===
49
+ function expectDataSlice(item) {
50
+ if (item.type !== "slice")
51
+ throw new Error("Expected slice data");
52
+ }
53
+ function expectDataCell(item) {
54
+ if (item.type !== "cell")
55
+ throw new Error("Expected cell data");
56
+ }
57
+ // === Expect Opcode Arg ===
58
+ function expectIntArg(opcode) {
59
+ if (opcode.type !== "int")
60
+ throw new Error("Expected int arg");
61
+ }
62
+ function expectStackArg(opcode) {
63
+ if (opcode.type !== "stack")
64
+ throw new Error("Expected stack arg");
65
+ }
66
+ function expectRegArg(opcode) {
67
+ if (opcode.type !== "reg")
68
+ throw new Error("Expected reg arg");
69
+ }
70
+ function expectCellArg(opcode) {
71
+ if (opcode.type !== "cell")
72
+ throw new Error("Expected cell arg");
73
+ }
74
+ function expectSliceArg(opcode) {
75
+ if (opcode.type !== "slice")
76
+ throw new Error("Expected slice arg");
77
+ }
78
+ function expectContArg(opcode) {
79
+ if (opcode.type !== "cell" && opcode.type !== "slice")
80
+ throw new Error("Expected slice arg");
81
+ }
package/dist/index.d.ts CHANGED
@@ -1,110 +1,3 @@
1
- import { Cell } from "@ton/core";
2
- /**
3
- * All code parts are referenced by a numberic ID.
4
- */
5
- export type ItemId = number;
6
- /**
7
- * Code is a group of parsed parts and an index from which to start.
8
- */
9
- export type Code = {
10
- root: ItemId;
11
- items: Item[];
12
- };
13
- export type Item = ({
14
- id: number;
15
- type: "jumpTable";
16
- } & JumpTable) | ({
17
- id: number;
18
- type: "code";
19
- } & CodeBlock) | ({
20
- id: number;
21
- type: "dataBlock";
22
- } & DataBlock) | ({
23
- id: number;
24
- type: "library";
25
- } & Library);
26
- export type ItemType = Item["type"];
27
- /**
28
- * Jump table is a dictionary which maps int to some continuations.
29
- */
30
- export type JumpTable = {
31
- cellHash: string;
32
- keyBits: number;
33
- items: Record<string, ItemId>;
34
- isFullCode: boolean;
35
- };
36
- /**
37
- * Parsed continuation.
38
- */
39
- export type CodeBlock = {
40
- cellHash: string;
41
- isInline: boolean;
42
- offsetBits: number;
43
- offsetRefs: number;
44
- bits: number;
45
- refs: number;
46
- opcodes: Opcode[];
47
- tail?: CodeBlockTail;
48
- };
49
- /**
50
- * What follows the continuation.
51
- */
52
- export type CodeBlockTail = {
53
- type: "incomplete";
54
- } | {
55
- type: "child";
56
- id: ItemId;
57
- };
58
- export type CodeBlockTailType = CodeBlockTail["type"];
59
- /**
60
- * Parsed opcode.
61
- */
62
- export type Opcode = {
63
- bits: number;
64
- refs?: number;
65
- name: string;
66
- args: OpcodeArg[];
67
- gas: number;
68
- };
69
- /**
70
- * Parsed opcode argument.
71
- */
72
- export type OpcodeArg = {
73
- type: "int";
74
- value: string;
75
- } | {
76
- type: "stack";
77
- idx: number;
78
- } | {
79
- type: "reg";
80
- idx: number;
81
- } | {
82
- type: "cell";
83
- id: ItemId;
84
- } | {
85
- type: "slice";
86
- id: ItemId;
87
- };
88
- export type OpcodeArgType = OpcodeArg["type"];
89
- /**
90
- * Cell tree parts that are treated as data.
91
- */
92
- export type DataBlock = {
93
- data: Data;
94
- };
95
- export type Data = {
96
- type: "slice";
97
- offsetBits: number;
98
- offsetRefs: number;
99
- bits: number;
100
- refs: number;
101
- boc: string;
102
- } | {
103
- type: "cell";
104
- boc: string;
105
- };
106
- export type DataType = Data["type"];
107
- export type Library = {
108
- hash: string;
109
- };
110
- export declare function disasmStructured(code: Cell | string): Promise<Code>;
1
+ export { disasmStructured, expectCellArg, expectCont, expectContArg, expectData, expectDataCell, expectDataSlice, expectIntArg, expectJumpTable, expectLibrary, expectRegArg, expectSliceArg, expectStackArg, Code, CodeBlock, CodeBlockTail, CodeBlockTailType, Data, DataBlock, DataCell, DataSlice, DataType, Item, ItemId, ItemType, JumpTable, Library, Opcode, OpcodeArg, OpcodeArgType, } from "./disasm/structured";
2
+ export { disasmToFift } from "./disasm/fift";
3
+ export { makeSlice } from "./util/slice";
package/dist/index.js CHANGED
@@ -1,18 +1,21 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.disasmStructured = disasmStructured;
4
- const core_1 = require("@ton/core");
5
- const env_1 = require("./env");
6
- async function disasmStructured(code) {
7
- await (0, env_1.wasmLoaded)();
8
- let boc;
9
- if (code instanceof core_1.Cell) {
10
- boc = code.toBoc({ idx: false }).toString("base64");
11
- }
12
- else {
13
- boc = code;
14
- }
15
- const res = env_1.wasm.disasm_structured(boc);
16
- const parsed = JSON.parse(res);
17
- return parsed;
18
- }
3
+ exports.makeSlice = exports.disasmToFift = exports.expectStackArg = exports.expectSliceArg = exports.expectRegArg = exports.expectLibrary = exports.expectJumpTable = exports.expectIntArg = exports.expectDataSlice = exports.expectDataCell = exports.expectData = exports.expectContArg = exports.expectCont = exports.expectCellArg = exports.disasmStructured = void 0;
4
+ var structured_1 = require("./disasm/structured");
5
+ Object.defineProperty(exports, "disasmStructured", { enumerable: true, get: function () { return structured_1.disasmStructured; } });
6
+ Object.defineProperty(exports, "expectCellArg", { enumerable: true, get: function () { return structured_1.expectCellArg; } });
7
+ Object.defineProperty(exports, "expectCont", { enumerable: true, get: function () { return structured_1.expectCont; } });
8
+ Object.defineProperty(exports, "expectContArg", { enumerable: true, get: function () { return structured_1.expectContArg; } });
9
+ Object.defineProperty(exports, "expectData", { enumerable: true, get: function () { return structured_1.expectData; } });
10
+ Object.defineProperty(exports, "expectDataCell", { enumerable: true, get: function () { return structured_1.expectDataCell; } });
11
+ Object.defineProperty(exports, "expectDataSlice", { enumerable: true, get: function () { return structured_1.expectDataSlice; } });
12
+ Object.defineProperty(exports, "expectIntArg", { enumerable: true, get: function () { return structured_1.expectIntArg; } });
13
+ Object.defineProperty(exports, "expectJumpTable", { enumerable: true, get: function () { return structured_1.expectJumpTable; } });
14
+ Object.defineProperty(exports, "expectLibrary", { enumerable: true, get: function () { return structured_1.expectLibrary; } });
15
+ Object.defineProperty(exports, "expectRegArg", { enumerable: true, get: function () { return structured_1.expectRegArg; } });
16
+ Object.defineProperty(exports, "expectSliceArg", { enumerable: true, get: function () { return structured_1.expectSliceArg; } });
17
+ Object.defineProperty(exports, "expectStackArg", { enumerable: true, get: function () { return structured_1.expectStackArg; } });
18
+ var fift_1 = require("./disasm/fift");
19
+ Object.defineProperty(exports, "disasmToFift", { enumerable: true, get: function () { return fift_1.disasmToFift; } });
20
+ var slice_1 = require("./util/slice");
21
+ Object.defineProperty(exports, "makeSlice", { enumerable: true, get: function () { return slice_1.makeSlice; } });
@@ -0,0 +1,2 @@
1
+ import { Cell, Slice } from "@ton/core";
2
+ export declare function makeSlice(cell: Cell, offsetBits: number, offsetRefs: number, bits: number, refs: number): Slice;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.makeSlice = makeSlice;
4
+ const core_1 = require("@ton/core");
5
+ function makeSlice(cell, offsetBits, offsetRefs, bits, refs) {
6
+ const d = cell.asSlice().skip(offsetBits).loadBits(bits);
7
+ const b = (0, core_1.beginCell)().storeBits(d);
8
+ for (let i = offsetRefs; i < offsetRefs + refs; i++) {
9
+ b.storeRef(cell.refs[i]);
10
+ }
11
+ return b.asSlice();
12
+ }
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tychosdk/disasm",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Tycho TVM disasm",
5
5
  "main": "dist/index.js",
6
6
  "browser": {