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
package/README.md
CHANGED
|
@@ -1,47 +1,73 @@
|
|
|
1
|
-
#
|
|
1
|
+
# gen-typescript-from-tolk-dev
|
|
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-dev
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Library usage
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { generateTypeScriptFileForContract } from 'gen-typescript-from-tolk-dev';
|
|
15
|
+
import type { ContractABI } from 'gen-typescript-from-tolk-dev';
|
|
16
|
+
|
|
17
|
+
const abi: ContractABI = getAbiFromSomewhereElse();
|
|
18
|
+
const wrapperSource = generateTypeScriptFileForContract(abi);
|
|
12
19
|
```
|
|
13
20
|
|
|
14
|
-
|
|
21
|
+
The generator expects ABI that already contains the contract metadata needed for wrapper emission, including `codeBoc64`.
|
|
15
22
|
|
|
23
|
+
Generated wrappers import `@ton/core`, so the project that uses the generated wrapper file should have `@ton/core` installed.
|
|
16
24
|
|
|
17
|
-
|
|
25
|
+
## CLI usage
|
|
18
26
|
|
|
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.
|
|
27
|
+
Print wrapper code to `stdout`:
|
|
22
28
|
|
|
23
|
-
|
|
29
|
+
```bash
|
|
30
|
+
npx gen-typescript-from-tolk-dev '{"contract_name":"MyContract","declarations":[],"storage":{},"incoming_messages":[],"incoming_external":[],"outgoing_messages":[],"emitted_events":[],"get_methods":[],"thrown_errors":[],"compiler_name":"tolk","compiler_version":"dev","codeBoc64":"te6ccgEBAQEAAgAAAA=="}'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Write to a file:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx gen-typescript-from-tolk-dev '{"contract_name":"MyContract","declarations":[],"storage":{},"incoming_messages":[],"incoming_external":[],"outgoing_messages":[],"emitted_events":[],"get_methods":[],"thrown_errors":[],"compiler_name":"tolk","compiler_version":"dev","codeBoc64":"te6ccgEBAQEAAgAAAA=="}' --out ./MyContract.ts
|
|
24
37
|
```
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
38
|
+
|
|
39
|
+
Read ABI JSON from `stdin`:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
cat ./MyContract.abi.json | npx gen-typescript-from-tolk-dev - --out ./MyContract.ts
|
|
30
43
|
```
|
|
31
44
|
|
|
32
|
-
|
|
45
|
+
Read ABI JSON from a file:
|
|
33
46
|
|
|
34
|
-
|
|
47
|
+
```bash
|
|
48
|
+
npx gen-typescript-from-tolk-dev --abi-file ./MyContract.abi.json --out ./MyContract.ts
|
|
35
49
|
```
|
|
36
|
-
|
|
50
|
+
|
|
51
|
+
This matches the `emulator-rs` integration model: `npx <package> '<abi-json>'`, with the generated wrapper emitted to `stdout`.
|
|
52
|
+
|
|
53
|
+
## Acton Compatibility
|
|
54
|
+
|
|
55
|
+
The published package also exposes compatibility subpaths used by `emulator-rs`, for example:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import type { ContractABI } from 'gen-typescript-from-tolk-dev/src/abi';
|
|
59
|
+
import { DynamicCtx } from 'gen-typescript-from-tolk-dev/src/dynamic-ctx';
|
|
60
|
+
import { unpackFromSliceDynamic } from 'gen-typescript-from-tolk-dev/src/dynamic-serialization';
|
|
37
61
|
```
|
|
38
62
|
|
|
39
|
-
|
|
63
|
+
## Development
|
|
40
64
|
|
|
65
|
+
```bash
|
|
66
|
+
npm run build
|
|
67
|
+
npm test
|
|
68
|
+
npm pack --dry-run
|
|
69
|
+
```
|
|
41
70
|
|
|
42
|
-
|
|
71
|
+
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
72
|
|
|
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.
|
|
73
|
+
The published npm package includes `dist/`, `bin/`, and `README.md`.
|
package/bin/generator.js
CHANGED
|
@@ -1,15 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
require('ts-node').register({
|
|
5
|
-
transpileOnly: true,
|
|
6
|
-
project: path.join(__dirname, '..', 'tsconfig.json'),
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
require('../src/cli-generate-from-abi-json')
|
|
10
|
-
.runGeneratorFromAbiCli(process.argv.slice(2))
|
|
11
|
-
.catch((error) => {
|
|
12
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
13
|
-
process.stderr.write(`${message}\n`);
|
|
14
|
-
process.exitCode = 1;
|
|
15
|
-
});
|
|
3
|
+
require('../dist/cli.js').main(process.argv.slice(2));
|
|
@@ -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,53 @@
|
|
|
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
|
+
err_code: number;
|
|
36
|
+
}
|
|
37
|
+
export interface ContractABI {
|
|
38
|
+
contract_name: string;
|
|
39
|
+
author?: string;
|
|
40
|
+
version?: string;
|
|
41
|
+
description?: string;
|
|
42
|
+
declarations: (ABIStruct | ABIAlias | ABIEnum)[];
|
|
43
|
+
storage: ABIStorage;
|
|
44
|
+
incoming_messages: ABIInternalMessage[];
|
|
45
|
+
incoming_external: ABIExternalMessage[];
|
|
46
|
+
outgoing_messages: ABIOutgoingMessage[];
|
|
47
|
+
emitted_events: ABIOutgoingMessage[];
|
|
48
|
+
get_methods: ABIGetMethod[];
|
|
49
|
+
thrown_errors: ABIThrownError[];
|
|
50
|
+
compiler_name: string;
|
|
51
|
+
compiler_version: string;
|
|
52
|
+
codeBoc64: string;
|
|
53
|
+
}
|
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,122 @@
|
|
|
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
|
+
exports.main = main;
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const generate_ts_wrappers_1 = require("./generate-ts-wrappers");
|
|
11
|
+
function printHelp() {
|
|
12
|
+
const help = [
|
|
13
|
+
`Usage:`,
|
|
14
|
+
` gen-typescript-from-tolk-dev '{"contract_name":"MyContract",...}' [--out ./MyContract.ts]`,
|
|
15
|
+
` gen-typescript-from-tolk-dev - [--out ./MyContract.ts]`,
|
|
16
|
+
` gen-typescript-from-tolk-dev --abi-file ./MyContract.abi.json [--out ./MyContract.ts]`,
|
|
17
|
+
`Options:`,
|
|
18
|
+
` --abi-file <path> read ABI JSON from a file`,
|
|
19
|
+
` --out <path> write output to a file; if missing, stdout is used`,
|
|
20
|
+
` - read ABI JSON from stdin`,
|
|
21
|
+
` --help, -h show this help`,
|
|
22
|
+
].join('\n');
|
|
23
|
+
process.stdout.write(`${help}\n`);
|
|
24
|
+
}
|
|
25
|
+
function parseArgs(argv) {
|
|
26
|
+
const args = [...argv];
|
|
27
|
+
const options = { showHelp: false };
|
|
28
|
+
while (args.length > 0) {
|
|
29
|
+
const arg = args.shift();
|
|
30
|
+
if (arg === '--help' || arg === '-h') {
|
|
31
|
+
options.showHelp = true;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (arg === '--abi-file') {
|
|
35
|
+
const abiFile = args.shift();
|
|
36
|
+
if (!abiFile) {
|
|
37
|
+
throw new Error("Missing value for '--abi-file'");
|
|
38
|
+
}
|
|
39
|
+
if (options.abiJsonArg !== undefined || options.abiFile !== undefined) {
|
|
40
|
+
throw new Error('Only one ABI input source is expected');
|
|
41
|
+
}
|
|
42
|
+
options.abiFile = abiFile;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (arg === '--out') {
|
|
46
|
+
const outFile = args.shift();
|
|
47
|
+
if (!outFile) {
|
|
48
|
+
throw new Error("Missing value for '--out'");
|
|
49
|
+
}
|
|
50
|
+
options.outFile = outFile;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (arg.startsWith('--')) {
|
|
54
|
+
throw new Error(`Unknown option '${arg}'`);
|
|
55
|
+
}
|
|
56
|
+
if (options.abiJsonArg !== undefined || options.abiFile !== undefined) {
|
|
57
|
+
throw new Error('Only one ABI input source is expected');
|
|
58
|
+
}
|
|
59
|
+
options.abiJsonArg = arg;
|
|
60
|
+
}
|
|
61
|
+
return options;
|
|
62
|
+
}
|
|
63
|
+
function readAbiInput(options) {
|
|
64
|
+
if (options.abiFile) {
|
|
65
|
+
try {
|
|
66
|
+
return fs_1.default.readFileSync(options.abiFile, 'utf-8');
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
throw new Error(`Failed to read ABI file '${options.abiFile}': ${error.message || error}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (options.abiJsonArg === '-') {
|
|
73
|
+
try {
|
|
74
|
+
return fs_1.default.readFileSync(0, 'utf-8');
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
throw new Error(`Failed to read ABI JSON from stdin: ${error.message || error}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (options.abiJsonArg !== undefined) {
|
|
81
|
+
return options.abiJsonArg;
|
|
82
|
+
}
|
|
83
|
+
throw new Error('ABI JSON argument is required');
|
|
84
|
+
}
|
|
85
|
+
function parseAbiJson(rawJson) {
|
|
86
|
+
try {
|
|
87
|
+
return JSON.parse(rawJson);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
throw new Error(`Failed to parse ABI JSON: ${error.message || error}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function writeOutput(output, outFile) {
|
|
94
|
+
if (outFile) {
|
|
95
|
+
fs_1.default.writeFileSync(outFile, output, 'utf-8');
|
|
96
|
+
process.stdout.write(`written ${outFile}\n`);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
process.stdout.write(output);
|
|
100
|
+
}
|
|
101
|
+
function runCli(argv) {
|
|
102
|
+
const options = parseArgs(argv);
|
|
103
|
+
if (options.showHelp) {
|
|
104
|
+
printHelp();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const abi = parseAbiJson(readAbiInput(options));
|
|
108
|
+
const generated = (0, generate_ts_wrappers_1.generateTypeScriptFileForContract)(abi);
|
|
109
|
+
writeOutput(generated, options.outFile);
|
|
110
|
+
}
|
|
111
|
+
function main(argv = process.argv.slice(2)) {
|
|
112
|
+
try {
|
|
113
|
+
runCli(argv);
|
|
114
|
+
}
|
|
115
|
+
catch (ex) {
|
|
116
|
+
process.stderr.write(`${ex.message || ex}\n`);
|
|
117
|
+
process.exitCode = 1;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (require.main === module) {
|
|
121
|
+
main();
|
|
122
|
+
}
|
|
@@ -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,17 @@
|
|
|
1
|
+
import * as c from '@ton/core';
|
|
2
|
+
import { SymTable } from './codegen-ctx';
|
|
3
|
+
import { ABIGetMethod, ContractABI } from './abi';
|
|
4
|
+
type CustomPackToBuilderFn<T> = (self: T, b: c.Builder) => void;
|
|
5
|
+
type CustomUnpackFromSliceFn<T> = (s: c.Slice) => T;
|
|
6
|
+
export declare class DynamicCtx {
|
|
7
|
+
readonly contractName: string;
|
|
8
|
+
readonly getMethods: ABIGetMethod[];
|
|
9
|
+
readonly symbols: SymTable;
|
|
10
|
+
private customSerializersRegistry;
|
|
11
|
+
constructor(contract: ContractABI);
|
|
12
|
+
registerCustomPackUnpack<T>(typeName: string, packToBuilderFn: CustomPackToBuilderFn<T> | null, unpackFromSliceFn: CustomUnpackFromSliceFn<T> | null): void;
|
|
13
|
+
getCustomPackFnOrThrow(typeName: string, fieldPath: string): CustomPackToBuilderFn<any>;
|
|
14
|
+
getCustomUnpackFnOrThrow(typeName: string, fieldPath: string): CustomUnpackFromSliceFn<any>;
|
|
15
|
+
findGetMethod(getMethodName: string): ABIGetMethod | undefined;
|
|
16
|
+
}
|
|
17
|
+
export {};
|