gen-typescript-from-tolk-dev 0.1.0 → 0.2.1
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 +33 -29
- package/dist/abi-types.d.ts +169 -0
- package/dist/abi-types.js +8 -0
- package/dist/abi.d.ts +54 -0
- package/dist/abi.js +13 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +83 -0
- package/dist/codegen-ctx.d.ts +66 -0
- package/dist/codegen-ctx.js +108 -0
- 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/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 +56 -30
- package/bin/generator.js +0 -15
- 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-debug-print.ts +0 -191
- package/src/dynamic-get-methods.ts +0 -454
- package/src/dynamic-serialization.ts +0 -430
- package/src/dynamic-validation.ts +0 -55
- 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
package/README.md
CHANGED
|
@@ -1,47 +1,51 @@
|
|
|
1
|
-
#
|
|
1
|
+
# gen-typescript-from-tolk
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
to emit ABI of a contract, and LSP won't be used in this process.
|
|
3
|
+
Generate production-ready TypeScript wrappers from a prebuilt Tolk ABI.
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
The main entrypoint accepts contract ABI as a JSON string and prints the generated TypeScript wrapper to stdout:
|
|
5
|
+
## Install
|
|
9
6
|
|
|
10
7
|
```bash
|
|
11
|
-
|
|
8
|
+
npm install gen-typescript-from-tolk
|
|
12
9
|
```
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
## Library usage
|
|
15
12
|
|
|
13
|
+
```ts
|
|
14
|
+
import { generateTypeScriptFileForContract } from 'gen-typescript-from-tolk';
|
|
15
|
+
import type { ContractABI } from 'gen-typescript-from-tolk';
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
const abi: ContractABI = getAbiFromSomewhereElse();
|
|
18
|
+
const wrapperSource = generateTypeScriptFileForContract(abi);
|
|
19
|
+
```
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
If a struct can't be serialized (contains `int` for example, not int32/uint64),
|
|
21
|
-
its `fromSlice` and `store` just contain `throw new Error` with a description.
|
|
21
|
+
The generator expects ABI that already contains the contract metadata needed for wrapper emission, including `codeBoc64`.
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
jettonBalance: coins = 0 // <----
|
|
27
|
-
ownerAddress: address
|
|
28
|
-
minterAddress: address
|
|
29
|
-
}
|
|
30
|
-
```
|
|
23
|
+
Generated wrappers import `@ton/core`, so the project that uses the generated wrapper file should have `@ton/core` installed.
|
|
24
|
+
|
|
25
|
+
## CLI usage
|
|
31
26
|
|
|
32
|
-
|
|
27
|
+
Print wrapper code to `stdout`:
|
|
33
28
|
|
|
34
|
-
|
|
29
|
+
```bash
|
|
30
|
+
npx gen-typescript-from-tolk '{"contractName":"MyContract","declarations":[],"storage":{},"incomingMessages":[],"incomingExternal":[],"outgoingMessages":[],"emittedEvents":[],"getMethods":[],"thrownErrors":[],"compilerName":"tolk","compilerVersion":"dev","codeBoc64":"te6ccgEBAQEAAgAAAA=="}'
|
|
35
31
|
```
|
|
36
|
-
|
|
32
|
+
|
|
33
|
+
Write to a file:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx gen-typescript-from-tolk '{"contractName":"MyContract","declarations":[],"storage":{},"incomingMessages":[],"incomingExternal":[],"outgoingMessages":[],"emittedEvents":[],"getMethods":[],"thrownErrors":[],"compilerName":"tolk","compilerVersion":"dev","codeBoc64":"te6ccgEBAQEAAgAAAA=="}' --out ./MyContract.ts
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
You can also pass `-` instead of JSON to read ABI JSON from `stdin`.
|
|
40
40
|
|
|
41
|
+
## Development
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm run build
|
|
45
|
+
npm test
|
|
46
|
+
npm pack --dry-run
|
|
47
|
+
```
|
|
41
48
|
|
|
42
|
-
|
|
49
|
+
Local tests and dev scripts compile `.tolk` files through `@ton/tolk-js`, but that compiler is intentionally not part of the published runtime package.
|
|
43
50
|
|
|
44
|
-
|
|
45
|
-
2. Non-standard keys for maps are unsupported, like `map<Point, ...>`. Only intN/uintN/address are supported (99% use cases). Others can not be represented via `@ton/core` library at all.
|
|
46
|
-
3. Custom serializers for generic structs `fun Some<T>.packToBuilder` not supported (works perfectly for non-generic structs and aliases, but not for generic).
|
|
47
|
-
4. Default values for struct fields, if a field contains a union, not supported.
|
|
51
|
+
Only `dist/` and `README.md` are included in the published npm package.
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
type bigint_as_string = string;
|
|
2
|
+
export type Ty = {
|
|
3
|
+
kind: 'int';
|
|
4
|
+
} | {
|
|
5
|
+
kind: 'intN';
|
|
6
|
+
n: number;
|
|
7
|
+
} | {
|
|
8
|
+
kind: 'uintN';
|
|
9
|
+
n: number;
|
|
10
|
+
} | {
|
|
11
|
+
kind: 'varintN';
|
|
12
|
+
n: number;
|
|
13
|
+
} | {
|
|
14
|
+
kind: 'varuintN';
|
|
15
|
+
n: number;
|
|
16
|
+
} | {
|
|
17
|
+
kind: 'coins';
|
|
18
|
+
} | {
|
|
19
|
+
kind: 'bool';
|
|
20
|
+
} | {
|
|
21
|
+
kind: 'cell';
|
|
22
|
+
} | {
|
|
23
|
+
kind: 'builder';
|
|
24
|
+
} | {
|
|
25
|
+
kind: 'slice';
|
|
26
|
+
} | {
|
|
27
|
+
kind: 'string';
|
|
28
|
+
} | {
|
|
29
|
+
kind: 'remaining';
|
|
30
|
+
} | {
|
|
31
|
+
kind: 'address';
|
|
32
|
+
} | {
|
|
33
|
+
kind: 'addressOpt';
|
|
34
|
+
} | {
|
|
35
|
+
kind: 'addressExt';
|
|
36
|
+
} | {
|
|
37
|
+
kind: 'addressAny';
|
|
38
|
+
} | {
|
|
39
|
+
kind: 'bitsN';
|
|
40
|
+
n: number;
|
|
41
|
+
} | {
|
|
42
|
+
kind: 'nullLiteral';
|
|
43
|
+
} | {
|
|
44
|
+
kind: 'callable';
|
|
45
|
+
} | {
|
|
46
|
+
kind: 'void';
|
|
47
|
+
} | {
|
|
48
|
+
kind: 'unknown';
|
|
49
|
+
} | {
|
|
50
|
+
kind: 'nullable';
|
|
51
|
+
inner: Ty;
|
|
52
|
+
stack_type_id?: number;
|
|
53
|
+
stack_width?: number;
|
|
54
|
+
} | {
|
|
55
|
+
kind: 'cellOf';
|
|
56
|
+
inner: Ty;
|
|
57
|
+
} | {
|
|
58
|
+
kind: 'arrayOf';
|
|
59
|
+
inner: Ty;
|
|
60
|
+
} | {
|
|
61
|
+
kind: 'lispListOf';
|
|
62
|
+
inner: Ty;
|
|
63
|
+
} | {
|
|
64
|
+
kind: 'tensor';
|
|
65
|
+
items: Ty[];
|
|
66
|
+
} | {
|
|
67
|
+
kind: 'shapedTuple';
|
|
68
|
+
items: Ty[];
|
|
69
|
+
} | {
|
|
70
|
+
kind: 'mapKV';
|
|
71
|
+
k: Ty;
|
|
72
|
+
v: Ty;
|
|
73
|
+
} | {
|
|
74
|
+
kind: 'EnumRef';
|
|
75
|
+
enum_name: string;
|
|
76
|
+
} | {
|
|
77
|
+
kind: 'StructRef';
|
|
78
|
+
struct_name: string;
|
|
79
|
+
type_args?: Ty[];
|
|
80
|
+
} | {
|
|
81
|
+
kind: 'AliasRef';
|
|
82
|
+
alias_name: string;
|
|
83
|
+
type_args?: Ty[];
|
|
84
|
+
} | {
|
|
85
|
+
kind: 'genericT';
|
|
86
|
+
name_t: string;
|
|
87
|
+
} | {
|
|
88
|
+
kind: 'union';
|
|
89
|
+
variants: UnionVariant[];
|
|
90
|
+
stack_width: number;
|
|
91
|
+
};
|
|
92
|
+
export interface UnionVariant {
|
|
93
|
+
variant_ty: Ty;
|
|
94
|
+
prefix_str: string;
|
|
95
|
+
prefix_len: number;
|
|
96
|
+
is_prefix_implicit?: boolean;
|
|
97
|
+
stack_type_id: number;
|
|
98
|
+
stack_width: number;
|
|
99
|
+
}
|
|
100
|
+
export type ABIConstExpression = {
|
|
101
|
+
kind: 'int';
|
|
102
|
+
v: bigint_as_string;
|
|
103
|
+
} | {
|
|
104
|
+
kind: 'bool';
|
|
105
|
+
v: boolean;
|
|
106
|
+
} | {
|
|
107
|
+
kind: 'slice';
|
|
108
|
+
hex: string;
|
|
109
|
+
} | {
|
|
110
|
+
kind: 'string';
|
|
111
|
+
str: string;
|
|
112
|
+
} | {
|
|
113
|
+
kind: 'address';
|
|
114
|
+
addr: string;
|
|
115
|
+
} | {
|
|
116
|
+
kind: 'tensor';
|
|
117
|
+
items: ABIConstExpression[];
|
|
118
|
+
} | {
|
|
119
|
+
kind: 'shapedTuple';
|
|
120
|
+
items: ABIConstExpression[];
|
|
121
|
+
} | {
|
|
122
|
+
kind: 'object';
|
|
123
|
+
struct_name: string;
|
|
124
|
+
fields: ABIConstExpression[];
|
|
125
|
+
} | {
|
|
126
|
+
kind: 'castTo';
|
|
127
|
+
inner: ABIConstExpression;
|
|
128
|
+
cast_to: Ty;
|
|
129
|
+
} | {
|
|
130
|
+
kind: 'null';
|
|
131
|
+
};
|
|
132
|
+
export interface ABICustomSerializers {
|
|
133
|
+
pack_to_builder: boolean;
|
|
134
|
+
unpack_from_slice: boolean;
|
|
135
|
+
}
|
|
136
|
+
export interface ABIStruct {
|
|
137
|
+
kind: 'struct';
|
|
138
|
+
name: string;
|
|
139
|
+
type_params?: string[];
|
|
140
|
+
prefix?: {
|
|
141
|
+
prefix_str: string;
|
|
142
|
+
prefix_len: number;
|
|
143
|
+
};
|
|
144
|
+
fields: {
|
|
145
|
+
name: string;
|
|
146
|
+
ty: Ty;
|
|
147
|
+
default_value?: ABIConstExpression;
|
|
148
|
+
description?: string;
|
|
149
|
+
}[];
|
|
150
|
+
custom_pack_unpack?: ABICustomSerializers;
|
|
151
|
+
}
|
|
152
|
+
export interface ABIAlias {
|
|
153
|
+
kind: 'alias';
|
|
154
|
+
name: string;
|
|
155
|
+
target_ty: Ty;
|
|
156
|
+
type_params?: string[];
|
|
157
|
+
custom_pack_unpack?: ABICustomSerializers;
|
|
158
|
+
}
|
|
159
|
+
export interface ABIEnum {
|
|
160
|
+
kind: 'enum';
|
|
161
|
+
name: string;
|
|
162
|
+
encoded_as: Ty;
|
|
163
|
+
members: {
|
|
164
|
+
name: string;
|
|
165
|
+
value: bigint_as_string;
|
|
166
|
+
}[];
|
|
167
|
+
custom_pack_unpack?: ABICustomSerializers;
|
|
168
|
+
}
|
|
169
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
ABI Types — describes the type system and symbols definitions in the Tolk language.
|
|
4
|
+
The goal is to have a full bidirectional mapping from any Tolk struct to ABI:
|
|
5
|
+
all tricky types like generics, aliases, inline unions, etc. should be supported.
|
|
6
|
+
Then, any input could be packed to a cell and unpacked back — exactly as it's done by the compiler.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
package/dist/abi.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Ty, ABIStruct, ABIAlias, ABIEnum, ABIConstExpression } from './abi-types';
|
|
2
|
+
export interface ABIGetMethod {
|
|
3
|
+
tvm_method_id: number;
|
|
4
|
+
name: string;
|
|
5
|
+
parameters: {
|
|
6
|
+
name: string;
|
|
7
|
+
ty: Ty;
|
|
8
|
+
description?: string;
|
|
9
|
+
default_value?: ABIConstExpression;
|
|
10
|
+
}[];
|
|
11
|
+
return_ty: Ty;
|
|
12
|
+
description?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ABIInternalMessage {
|
|
15
|
+
body_ty: Ty;
|
|
16
|
+
description?: string;
|
|
17
|
+
minimal_msg_value?: number;
|
|
18
|
+
preferred_send_mode?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface ABIExternalMessage {
|
|
21
|
+
body_ty: Ty;
|
|
22
|
+
description?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface ABIOutgoingMessage {
|
|
25
|
+
body_ty: Ty;
|
|
26
|
+
description?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface ABIStorage {
|
|
29
|
+
storage_ty?: Ty;
|
|
30
|
+
storage_at_deployment_ty?: Ty;
|
|
31
|
+
}
|
|
32
|
+
export interface ABIThrownError {
|
|
33
|
+
kind: 'plain_int' | 'constant' | 'enum_member';
|
|
34
|
+
name?: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
err_code: number;
|
|
37
|
+
}
|
|
38
|
+
export interface ContractABI {
|
|
39
|
+
contract_name: string;
|
|
40
|
+
author?: string;
|
|
41
|
+
version?: string;
|
|
42
|
+
description?: string;
|
|
43
|
+
declarations: (ABIStruct | ABIAlias | ABIEnum)[];
|
|
44
|
+
storage: ABIStorage;
|
|
45
|
+
incoming_messages: ABIInternalMessage[];
|
|
46
|
+
incoming_external: ABIExternalMessage[];
|
|
47
|
+
outgoing_messages: ABIOutgoingMessage[];
|
|
48
|
+
emitted_events: ABIOutgoingMessage[];
|
|
49
|
+
get_methods: ABIGetMethod[];
|
|
50
|
+
thrown_errors: ABIThrownError[];
|
|
51
|
+
compiler_name: string;
|
|
52
|
+
compiler_version: string;
|
|
53
|
+
codeBoc64: string;
|
|
54
|
+
}
|
package/dist/abi.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
ABI of a contract describes how the contract is "seen" by external observers:
|
|
4
|
+
its get methods, incoming messages, etc.
|
|
5
|
+
Given an ABI, it becomes possible to
|
|
6
|
+
- post messages from a client, since ABI provides sufficient info for serialization
|
|
7
|
+
- generate wrappers for TypeScript and other languages
|
|
8
|
+
- render its storage in the explorer
|
|
9
|
+
- create a UI to interact with a contract from Web/IDE
|
|
10
|
+
- etc.
|
|
11
|
+
The ABI is emitted by the Tolk compiler, along with bytecode.
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.runCli = runCli;
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const generate_ts_wrappers_1 = require("./generate-ts-wrappers");
|
|
10
|
+
function printHelp() {
|
|
11
|
+
const help = [
|
|
12
|
+
`Usage:`,
|
|
13
|
+
` gen-typescript-from-tolk '{"contract_name":"MyContract",...}' --out ./MyContract.ts`,
|
|
14
|
+
`Options:`,
|
|
15
|
+
` --out — output file name; if missing, stdout is used`
|
|
16
|
+
].join('\n');
|
|
17
|
+
process.stdout.write(`${help}\n`);
|
|
18
|
+
}
|
|
19
|
+
function parseArgs(argv) {
|
|
20
|
+
const args = [...argv];
|
|
21
|
+
const options = { showHelp: false };
|
|
22
|
+
while (args.length > 0) {
|
|
23
|
+
const arg = args.shift();
|
|
24
|
+
if (arg === '--help' || arg === '-h') {
|
|
25
|
+
options.showHelp = true;
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (arg === '--out') {
|
|
29
|
+
const outFile = args.shift();
|
|
30
|
+
if (!outFile) {
|
|
31
|
+
throw new Error("Missing value for '--out'");
|
|
32
|
+
}
|
|
33
|
+
options.outFile = outFile;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (arg.startsWith('--')) {
|
|
37
|
+
throw new Error(`Unknown option '${arg}'`);
|
|
38
|
+
}
|
|
39
|
+
if (options.abiJsonArg !== undefined) {
|
|
40
|
+
throw new Error('Only one ABI JSON argument is expected');
|
|
41
|
+
}
|
|
42
|
+
options.abiJsonArg = arg;
|
|
43
|
+
}
|
|
44
|
+
return options;
|
|
45
|
+
}
|
|
46
|
+
function parseAbiJson(rawJson) {
|
|
47
|
+
try {
|
|
48
|
+
return JSON.parse(rawJson);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
throw new Error(`Failed to parse ABI JSON: ${error.message || error}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function writeOutput(output, outFile) {
|
|
55
|
+
if (outFile) {
|
|
56
|
+
fs_1.default.writeFileSync(outFile, output, 'utf-8');
|
|
57
|
+
process.stdout.write(`written ${outFile}\n`);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
process.stdout.write(output);
|
|
61
|
+
}
|
|
62
|
+
function runCli(argv) {
|
|
63
|
+
const options = parseArgs(argv);
|
|
64
|
+
if (options.showHelp) {
|
|
65
|
+
printHelp();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (!options.abiJsonArg) {
|
|
69
|
+
throw new Error("ABI JSON argument is required");
|
|
70
|
+
}
|
|
71
|
+
const abi = parseAbiJson(options.abiJsonArg);
|
|
72
|
+
const generated = (0, generate_ts_wrappers_1.generateTypeScriptFileForContract)(abi);
|
|
73
|
+
writeOutput(generated, options.outFile);
|
|
74
|
+
}
|
|
75
|
+
if (require.main === module) {
|
|
76
|
+
try {
|
|
77
|
+
runCli(process.argv.slice(2));
|
|
78
|
+
}
|
|
79
|
+
catch (ex) {
|
|
80
|
+
process.stderr.write(`${ex.message || ex}\n`);
|
|
81
|
+
process.exitCode = 1;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Ty, ABIStruct, ABIAlias, ABIEnum } from './abi-types';
|
|
2
|
+
export declare const RUNTIME: {
|
|
3
|
+
beginCell: string;
|
|
4
|
+
lookupPrefix: string;
|
|
5
|
+
lookupPrefixAndEat: string;
|
|
6
|
+
throwNonePrefixMatch: string;
|
|
7
|
+
loadAndCheckPrefix32: string;
|
|
8
|
+
loadAndCheckPrefix: string;
|
|
9
|
+
loadTolkBitsN: string;
|
|
10
|
+
storeTolkBitsN: string;
|
|
11
|
+
loadTolkAddressAny: string;
|
|
12
|
+
storeTolkAddressAny: string;
|
|
13
|
+
loadTolkRemaining: string;
|
|
14
|
+
storeTolkRemaining: string;
|
|
15
|
+
loadCellRef: string;
|
|
16
|
+
storeCellRef: string;
|
|
17
|
+
loadArrayOf: string;
|
|
18
|
+
storeArrayOf: string;
|
|
19
|
+
loadLispListOf: string;
|
|
20
|
+
storeLispListOf: string;
|
|
21
|
+
storeTolkNullable: string;
|
|
22
|
+
makeCellFrom: string;
|
|
23
|
+
createDictionaryValue: string;
|
|
24
|
+
registerCustomPackUnpack: string;
|
|
25
|
+
ExtraSendOptions: string;
|
|
26
|
+
StackReader: string;
|
|
27
|
+
};
|
|
28
|
+
export declare class SymTable {
|
|
29
|
+
private structs;
|
|
30
|
+
private aliases;
|
|
31
|
+
private enums;
|
|
32
|
+
constructor(declarations: (ABIStruct | ABIAlias | ABIEnum)[]);
|
|
33
|
+
getStruct(structName: string): ABIStruct;
|
|
34
|
+
getAlias(aliasName: string): ABIAlias;
|
|
35
|
+
getEnum(enumName: string): ABIEnum;
|
|
36
|
+
getAliasTarget(aliasName: string): Ty;
|
|
37
|
+
}
|
|
38
|
+
export declare class CodegenCtx {
|
|
39
|
+
readonly symbols: SymTable;
|
|
40
|
+
intNOccurred: Set<string>;
|
|
41
|
+
uintNOccurred: Set<string>;
|
|
42
|
+
varIntNOccurred: Set<string>;
|
|
43
|
+
bitsNOccurred: Set<string>;
|
|
44
|
+
has_RemainingBitsAndRefs: boolean;
|
|
45
|
+
has_customPackUnpack: boolean;
|
|
46
|
+
has_customDictV: boolean;
|
|
47
|
+
has_implicitUnionPrefix: boolean;
|
|
48
|
+
has_non32Prefixes: boolean;
|
|
49
|
+
has_addressAny: boolean;
|
|
50
|
+
has_arrayOf: boolean;
|
|
51
|
+
has_lispListOf: boolean;
|
|
52
|
+
stackReadsUnknown: boolean;
|
|
53
|
+
stackReadsArrayOf: boolean;
|
|
54
|
+
stackReadsLispListOf: boolean;
|
|
55
|
+
stackReadsSnakeString: boolean;
|
|
56
|
+
stackReadsTuple: boolean;
|
|
57
|
+
stackReadsMapKV: boolean;
|
|
58
|
+
stackReadsBuilder: boolean;
|
|
59
|
+
stackReadsNullable: boolean;
|
|
60
|
+
stackReadsWideNullable: boolean;
|
|
61
|
+
stackReadsUnionType: boolean;
|
|
62
|
+
stackReadsCellRef: boolean;
|
|
63
|
+
stackReadsNullLiteral: boolean;
|
|
64
|
+
constructor(declarations: (ABIStruct | ABIAlias | ABIEnum)[]);
|
|
65
|
+
sortOccurred(occurred: Set<string>): string[];
|
|
66
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CodegenCtx = exports.SymTable = exports.RUNTIME = void 0;
|
|
4
|
+
const unsupported_errors_1 = require("./unsupported-errors");
|
|
5
|
+
// Functions implemented in an output template, used to detect name shadowing.
|
|
6
|
+
exports.RUNTIME = {
|
|
7
|
+
beginCell: 'beginCell',
|
|
8
|
+
lookupPrefix: 'lookupPrefix',
|
|
9
|
+
lookupPrefixAndEat: 'lookupPrefixAndEat',
|
|
10
|
+
throwNonePrefixMatch: 'throwNonePrefixMatch',
|
|
11
|
+
loadAndCheckPrefix32: 'loadAndCheckPrefix32',
|
|
12
|
+
loadAndCheckPrefix: 'loadAndCheckPrefix',
|
|
13
|
+
loadTolkBitsN: 'loadTolkBitsN',
|
|
14
|
+
storeTolkBitsN: 'storeTolkBitsN',
|
|
15
|
+
loadTolkAddressAny: 'loadTolkAddressAny',
|
|
16
|
+
storeTolkAddressAny: 'storeTolkAddressAny',
|
|
17
|
+
loadTolkRemaining: 'loadTolkRemaining',
|
|
18
|
+
storeTolkRemaining: 'storeTolkRemaining',
|
|
19
|
+
loadCellRef: 'loadCellRef',
|
|
20
|
+
storeCellRef: 'storeCellRef',
|
|
21
|
+
loadArrayOf: 'loadArrayOf',
|
|
22
|
+
storeArrayOf: 'storeArrayOf',
|
|
23
|
+
loadLispListOf: 'loadLispListOf',
|
|
24
|
+
storeLispListOf: 'storeLispListOf',
|
|
25
|
+
storeTolkNullable: 'storeTolkNullable',
|
|
26
|
+
makeCellFrom: 'makeCellFrom',
|
|
27
|
+
createDictionaryValue: 'createDictionaryValue',
|
|
28
|
+
registerCustomPackUnpack: 'registerCustomPackUnpack',
|
|
29
|
+
ExtraSendOptions: 'ExtraSendOptions',
|
|
30
|
+
StackReader: 'StackReader',
|
|
31
|
+
};
|
|
32
|
+
// SymTable is an index of top-level declarations.
|
|
33
|
+
class SymTable {
|
|
34
|
+
constructor(declarations) {
|
|
35
|
+
this.structs = new Map();
|
|
36
|
+
this.aliases = new Map();
|
|
37
|
+
this.enums = new Map();
|
|
38
|
+
for (const n of declarations) {
|
|
39
|
+
if (n.kind === 'struct')
|
|
40
|
+
this.structs.set(n.name, n);
|
|
41
|
+
else if (n.kind === 'alias')
|
|
42
|
+
this.aliases.set(n.name, n);
|
|
43
|
+
else if (n.kind === 'enum')
|
|
44
|
+
this.enums.set(n.name, n);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
getStruct(structName) {
|
|
48
|
+
const s = this.structs.get(structName);
|
|
49
|
+
if (s === undefined)
|
|
50
|
+
throw new unsupported_errors_1.SymbolNotFound('struct', structName);
|
|
51
|
+
return s;
|
|
52
|
+
}
|
|
53
|
+
getAlias(aliasName) {
|
|
54
|
+
const a = this.aliases.get(aliasName);
|
|
55
|
+
if (a === undefined)
|
|
56
|
+
throw new unsupported_errors_1.SymbolNotFound('alias', aliasName);
|
|
57
|
+
return a;
|
|
58
|
+
}
|
|
59
|
+
getEnum(enumName) {
|
|
60
|
+
const e = this.enums.get(enumName);
|
|
61
|
+
if (e === undefined)
|
|
62
|
+
throw new unsupported_errors_1.SymbolNotFound('enum', enumName);
|
|
63
|
+
return e;
|
|
64
|
+
}
|
|
65
|
+
getAliasTarget(aliasName) {
|
|
66
|
+
return this.getAlias(aliasName).target_ty;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.SymTable = SymTable;
|
|
70
|
+
// CodegenCtx represents current state of TypeScript code generation.
|
|
71
|
+
// It contains properties that affect final output and help resolve symbols.
|
|
72
|
+
// For example, we want Tolk `int64` not be just TS `bigint`, but
|
|
73
|
+
// to export `type int64 = bigint` and use `int64` directly,
|
|
74
|
+
// that's why we track all occurred intN.
|
|
75
|
+
// Same for other public properties, they are modified while iterating through declarations.
|
|
76
|
+
class CodegenCtx {
|
|
77
|
+
constructor(declarations) {
|
|
78
|
+
this.intNOccurred = new Set(['int8', 'int16', 'int32', 'int256']);
|
|
79
|
+
this.uintNOccurred = new Set(['uint8', 'uint16', 'uint32', 'uint256']);
|
|
80
|
+
this.varIntNOccurred = new Set();
|
|
81
|
+
this.bitsNOccurred = new Set();
|
|
82
|
+
this.has_RemainingBitsAndRefs = false;
|
|
83
|
+
this.has_customPackUnpack = false;
|
|
84
|
+
this.has_customDictV = false;
|
|
85
|
+
this.has_implicitUnionPrefix = false;
|
|
86
|
+
this.has_non32Prefixes = false;
|
|
87
|
+
this.has_addressAny = false;
|
|
88
|
+
this.has_arrayOf = false;
|
|
89
|
+
this.has_lispListOf = false;
|
|
90
|
+
this.stackReadsUnknown = false;
|
|
91
|
+
this.stackReadsArrayOf = false;
|
|
92
|
+
this.stackReadsLispListOf = false;
|
|
93
|
+
this.stackReadsSnakeString = false;
|
|
94
|
+
this.stackReadsTuple = false;
|
|
95
|
+
this.stackReadsMapKV = false;
|
|
96
|
+
this.stackReadsBuilder = false;
|
|
97
|
+
this.stackReadsNullable = false;
|
|
98
|
+
this.stackReadsWideNullable = false;
|
|
99
|
+
this.stackReadsUnionType = false;
|
|
100
|
+
this.stackReadsCellRef = false;
|
|
101
|
+
this.stackReadsNullLiteral = false;
|
|
102
|
+
this.symbols = new SymTable(declarations);
|
|
103
|
+
}
|
|
104
|
+
sortOccurred(occurred) {
|
|
105
|
+
return [...occurred].sort((a, b) => a.length - b.length || a.localeCompare(b));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
exports.CodegenCtx = CodegenCtx;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ABIConstExpression, Ty } from './abi-types';
|
|
2
|
+
import { CodegenCtx } from './codegen-ctx';
|
|
3
|
+
export declare function isDefaultValueSupported(fieldTy: Ty): boolean;
|
|
4
|
+
export declare function emitFieldDefault(ctx: CodegenCtx, expr: ABIConstExpression): string;
|
|
5
|
+
export declare function emitFieldDefaultInComment(expr: ABIConstExpression): string;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isDefaultValueSupported = isDefaultValueSupported;
|
|
4
|
+
exports.emitFieldDefault = emitFieldDefault;
|
|
5
|
+
exports.emitFieldDefaultInComment = emitFieldDefaultInComment;
|
|
6
|
+
const formatting_1 = require("./formatting");
|
|
7
|
+
const types_kernel_1 = require("./types-kernel");
|
|
8
|
+
// Default values of struct fields are also exported to TypeScript unless they are hard to be represented.
|
|
9
|
+
// In practice, all simple values are okay: `f: int = 5`, `f: coins = ton("1")`, etc.
|
|
10
|
+
// But in theory, a field can be a union, for example. It will require a large amount of work to support
|
|
11
|
+
// cases like `f: int8 | slice = 5` or `f: int32 | int64 = 5 as int64` (to generate correct `$` labels).
|
|
12
|
+
// So, if such a field exists, then we just assume it has no default.
|
|
13
|
+
function isDefaultValueSupported(fieldTy) {
|
|
14
|
+
if (fieldTy.kind === 'arrayOf')
|
|
15
|
+
return isDefaultValueSupported(fieldTy.inner);
|
|
16
|
+
if (fieldTy.kind === 'lispListOf')
|
|
17
|
+
return isDefaultValueSupported(fieldTy.inner);
|
|
18
|
+
if (fieldTy.kind === 'tensor')
|
|
19
|
+
return fieldTy.items.every(isDefaultValueSupported);
|
|
20
|
+
if (fieldTy.kind === 'shapedTuple')
|
|
21
|
+
return fieldTy.items.every(isDefaultValueSupported);
|
|
22
|
+
return fieldTy.kind !== 'union' && fieldTy.kind !== 'mapKV';
|
|
23
|
+
}
|
|
24
|
+
// Default values of fields (particularly, in storage) are precalculated by the compiler
|
|
25
|
+
// and stored as "const expression" intermediate representation in ABI.
|
|
26
|
+
// Here we output them to a valid TypeScript expression.
|
|
27
|
+
// Default parameters for get methods follow the same logic, they are also "const expressions".
|
|
28
|
+
function emitFieldDefault(ctx, expr) {
|
|
29
|
+
switch (expr.kind) {
|
|
30
|
+
case 'int': return expr.v + 'n';
|
|
31
|
+
case 'bool': return expr.v ? 'true' : 'false';
|
|
32
|
+
case 'slice': return `new c.Slice(new c.BitReader(new c.BitString(Buffer.from('${expr.hex}', 'hex'), 0, ${expr.hex.length * 4})), [])`;
|
|
33
|
+
case 'string': return JSON.stringify(expr.str);
|
|
34
|
+
case 'address': return `c.Address.parse('${expr.addr}')`;
|
|
35
|
+
case 'tensor': return `[${expr.items.map(i => emitFieldDefault(ctx, i)).join(', ')}]`;
|
|
36
|
+
case 'shapedTuple': return `[${expr.items.map(i => emitFieldDefault(ctx, i)).join(', ')}]`;
|
|
37
|
+
case 'object': {
|
|
38
|
+
const structRef = ctx.symbols.getStruct(expr.struct_name);
|
|
39
|
+
return `{ $: '${structRef.name}', ${[...structRef.fields.map((f, i) => `${(0, formatting_1.safeFieldDecl)(f.name)}: ${emitFieldDefault(ctx, expr.fields[i])}`)].join(', ')} }`;
|
|
40
|
+
}
|
|
41
|
+
case 'castTo': return emitFieldDefault(ctx, expr.inner);
|
|
42
|
+
case 'null': return `null`;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Output a default value not as a TypeScript expression, but as a human-readable one.
|
|
46
|
+
// For instance, "123" instead of bigint "123n".
|
|
47
|
+
// It's inserted inside comments next to fields having defaults.
|
|
48
|
+
function emitFieldDefaultInComment(expr) {
|
|
49
|
+
switch (expr.kind) {
|
|
50
|
+
case 'int': return expr.v;
|
|
51
|
+
case 'bool': return expr.v ? 'true' : 'false';
|
|
52
|
+
case 'slice': return `hex('${expr.hex}')`;
|
|
53
|
+
case 'string': return JSON.stringify(expr.str);
|
|
54
|
+
case 'address': return `address('${expr.addr}')`;
|
|
55
|
+
case 'tensor': return `[${expr.items.map(emitFieldDefaultInComment).join(', ')}]`;
|
|
56
|
+
case 'shapedTuple': return `[${expr.items.map(emitFieldDefaultInComment).join(', ')}]`;
|
|
57
|
+
case 'object': return `${expr.struct_name} { ${expr.fields.map(emitFieldDefaultInComment).join(', ')} }`;
|
|
58
|
+
case 'castTo': return `${emitFieldDefaultInComment(expr.inner)} as ${(0, types_kernel_1.renderTy)(expr.cast_to)}`;
|
|
59
|
+
case 'null': return `null`;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Ty } from './abi-types';
|
|
2
|
+
import { CodegenCtx } from './codegen-ctx';
|
|
3
|
+
export declare function emitLoadExpr(ctx: CodegenCtx, fieldPath: string, ty: Ty): string;
|
|
4
|
+
export declare function emitLoadCallback(ctx: CodegenCtx, fieldPath: string, ty: Ty): string;
|
|
5
|
+
export declare function emitStoreStatement(ctx: CodegenCtx, tsExpr: string, ty: Ty): string;
|
|
6
|
+
export declare function emitStoreCallback(ctx: CodegenCtx, ty: Ty): string;
|
|
7
|
+
export declare function emitMakeCellFromExpr(ctx: CodegenCtx, tsExpr: string, ty: Ty, disableShortHand?: boolean): string;
|
|
8
|
+
export declare function emitCallToCreateMethodExpr(ctx: CodegenCtx, bodyArg: string, ty: Ty): string;
|
|
9
|
+
export declare function emitDictKVSerializers(ctx: CodegenCtx, fieldPath: string, tyK: Ty, tyV: Ty): string;
|