@ton/blueprint 0.15.0 → 0.17.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/CHANGELOG.md +26 -0
- package/README.md +40 -5
- package/dist/build.js +9 -5
- package/dist/cli/Runner.d.ts +5 -1
- package/dist/cli/cli.js +8 -2
- package/dist/cli/convert.d.ts +2 -0
- package/dist/cli/convert.js +133 -0
- package/dist/cli/help.js +8 -1
- package/dist/cli/run.js +2 -2
- package/dist/cli/set.d.ts +2 -0
- package/dist/cli/set.js +104 -0
- package/dist/cli/verify.js +83 -7
- package/dist/compile/CompilerConfig.d.ts +5 -2
- package/dist/compile/compile.d.ts +5 -2
- package/dist/compile/compile.js +9 -5
- package/dist/config/Config.d.ts +3 -1
- package/dist/config/CustomNetwork.d.ts +6 -0
- package/dist/config/CustomNetwork.js +2 -0
- package/dist/index.d.ts +4 -3
- package/dist/network/createNetworkProvider.d.ts +2 -1
- package/dist/network/createNetworkProvider.js +65 -32
- package/dist/templates/func/legacy/wrappers/compile.ts.template +7 -0
- package/dist/ui/InquirerUIProvider.d.ts +2 -0
- package/dist/ui/InquirerUIProvider.js +13 -0
- package/dist/ui/UIProvider.d.ts +2 -0
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,32 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.17.0] - 2024-03-01
|
|
9
|
+
|
|
10
|
+
This release contains a breaking change.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Blueprint no longer automatically adds `jsonRPC` to custom v2 endpoints
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- Added `set` command which can currently set func version (run `blueprint set func`)
|
|
19
|
+
- Added `open` and `getTransactions` to `WrappedContractProvider`
|
|
20
|
+
- Added cell hash to build artifacts
|
|
21
|
+
|
|
22
|
+
## [0.16.0] - 2024-02-15
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- Added the `network` entry to the global config, which allows one to specify a custom network to be used instead of having to add `--custom` flags on each run
|
|
27
|
+
- Added the `convert` command which attempts to convert a legacy bash build script into a blueprint `.compile.ts` file
|
|
28
|
+
- Added the ability to pass any user data into the compile hooks
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- Improved the `verify` command
|
|
33
|
+
|
|
8
34
|
## [0.15.0] - 2023-12-15
|
|
9
35
|
|
|
10
36
|
### Added
|
package/README.md
CHANGED
|
@@ -103,26 +103,61 @@ Run in terminal: `npx blueprint help` or `yarn blueprint he
|
|
|
103
103
|
2. Implement a deployment script in `scripts/deploy<CONTRACT>.ts`
|
|
104
104
|
3. Rely on the wrapper TypeScript class from `wrappers/<CONTRACT>.ts` to initialize the contract
|
|
105
105
|
|
|
106
|
-
##
|
|
106
|
+
## Config
|
|
107
|
+
|
|
108
|
+
A config may be created in order to control some of blueprint's features. If a config is needed, create a `blueprint.config.ts` file in the root of your project with something like this:
|
|
109
|
+
```typescript
|
|
110
|
+
import { Config } from '@ton/blueprint';
|
|
111
|
+
|
|
112
|
+
export const config: Config = {
|
|
113
|
+
// config contents
|
|
114
|
+
};
|
|
115
|
+
```
|
|
116
|
+
It is important that the config is exported, is named `config`, and is not `default` exported.
|
|
117
|
+
|
|
118
|
+
Config's features are explained below.
|
|
119
|
+
|
|
120
|
+
### Plugins
|
|
107
121
|
|
|
108
122
|
Blueprint has a plugin system to allow the community to develop their own additions for the ecosystem without the need to change blueprint's code.
|
|
109
123
|
|
|
110
|
-
In order to use plugins,
|
|
124
|
+
In order to use plugins, add a `plugins` array to your config:
|
|
111
125
|
```typescript
|
|
112
126
|
import { Config } from '@ton/blueprint';
|
|
113
127
|
import { ScaffoldPlugin } from 'blueprint-scaffold';
|
|
114
128
|
|
|
115
129
|
export const config: Config = {
|
|
116
|
-
|
|
130
|
+
plugins: [new ScaffoldPlugin()],
|
|
117
131
|
};
|
|
118
132
|
```
|
|
119
133
|
(This example shows how to add the [scaffold](https://github.com/1IxI1/blueprint-scaffold) plugin)
|
|
120
134
|
|
|
121
|
-
It is important that the config is exported, is named `config`, and is not `default` exported.
|
|
122
|
-
|
|
123
135
|
Here are some of the plugins developed by the community:
|
|
124
136
|
- [scaffold](https://github.com/1IxI1/blueprint-scaffold) - allows developers to quickly create a simple dapp automatically using the wrappers' code
|
|
125
137
|
|
|
138
|
+
### Custom network
|
|
139
|
+
|
|
140
|
+
A custom network may be specified by using the `--custom` flags, which you can read about by running `blueprint help run`, but it can be tiresome to use these at all times. Instead, to specify a custom network to always be used (unless `--custom` flags are present), add a `network` object to your config:
|
|
141
|
+
```typescript
|
|
142
|
+
import { Config } from '@ton/blueprint';
|
|
143
|
+
|
|
144
|
+
export const config: Config = {
|
|
145
|
+
network: {
|
|
146
|
+
endpoint: 'https://toncenter.com/api/v2/',
|
|
147
|
+
type: 'mainnet',
|
|
148
|
+
version: 'v2',
|
|
149
|
+
key: 'YOUR_API_KEY',
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The above config parameters are equivalent to the arguments in the following command:
|
|
155
|
+
```bash
|
|
156
|
+
npx blueprint run --custom https://toncenter.com/api/v2/ --custom-version v2 --custom-type mainnet --custom-key YOUR_API_KEY
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Properties of the `network` object have the same semantics as the `--custom` flags with respective names (see `blueprint help run`).
|
|
160
|
+
|
|
126
161
|
## Contributors
|
|
127
162
|
|
|
128
163
|
Special thanks to [@qdevstudio](https://t.me/qdevstudio) for their logo for blueprint.
|
package/dist/build.js
CHANGED
|
@@ -28,13 +28,17 @@ async function buildOne(contract, ui) {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
const cell = result.code;
|
|
31
|
+
const rHash = cell.hash();
|
|
32
|
+
const res = {
|
|
33
|
+
hash: rHash.toString('hex'),
|
|
34
|
+
hashBase64: rHash.toString('base64'),
|
|
35
|
+
hex: cell.toBoc().toString('hex')
|
|
36
|
+
};
|
|
31
37
|
ui?.clearActionPrompt();
|
|
32
|
-
ui?.write('\n✅ Compiled successfully! Cell BOC
|
|
33
|
-
ui?.write(
|
|
38
|
+
ui?.write('\n✅ Compiled successfully! Cell BOC result:\n\n');
|
|
39
|
+
ui?.write(JSON.stringify(res, null, 2));
|
|
34
40
|
await promises_1.default.mkdir(paths_1.BUILD_DIR, { recursive: true });
|
|
35
|
-
await promises_1.default.writeFile(buildArtifactPath, JSON.stringify(
|
|
36
|
-
hex: cell.toBoc().toString('hex'),
|
|
37
|
-
}));
|
|
41
|
+
await promises_1.default.writeFile(buildArtifactPath, JSON.stringify(res));
|
|
38
42
|
ui?.write(`\n✅ Wrote compilation artifact to ${path_1.default.relative(process.cwd(), buildArtifactPath)}`);
|
|
39
43
|
}
|
|
40
44
|
catch (e) {
|
package/dist/cli/Runner.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import arg from 'arg';
|
|
2
2
|
import { UIProvider } from '../ui/UIProvider';
|
|
3
|
+
import { Config } from '../config/Config';
|
|
3
4
|
export declare const argSpec: {};
|
|
4
5
|
export type Args = arg.Result<typeof argSpec>;
|
|
5
|
-
export type
|
|
6
|
+
export type RunnerContext = {
|
|
7
|
+
config?: Config;
|
|
8
|
+
};
|
|
9
|
+
export type Runner = (args: Args, ui: UIProvider, context: RunnerContext) => Promise<void>;
|
package/dist/cli/cli.js
CHANGED
|
@@ -34,8 +34,10 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
34
34
|
const create_1 = require("./create");
|
|
35
35
|
const run_1 = require("./run");
|
|
36
36
|
const build_1 = require("./build");
|
|
37
|
+
const set_1 = require("./set");
|
|
37
38
|
const test_1 = require("./test");
|
|
38
39
|
const verify_1 = require("./verify");
|
|
40
|
+
const convert_1 = require("./convert");
|
|
39
41
|
const help_1 = require("./help");
|
|
40
42
|
const InquirerUIProvider_1 = require("../ui/InquirerUIProvider");
|
|
41
43
|
const Runner_1 = require("./Runner");
|
|
@@ -44,9 +46,11 @@ const runners = {
|
|
|
44
46
|
create: create_1.create,
|
|
45
47
|
run: run_1.run,
|
|
46
48
|
build: build_1.build,
|
|
49
|
+
set: set_1.set,
|
|
47
50
|
test: test_1.test,
|
|
48
51
|
help: help_1.help,
|
|
49
52
|
verify: verify_1.verify,
|
|
53
|
+
convert: convert_1.convert,
|
|
50
54
|
};
|
|
51
55
|
async function main() {
|
|
52
56
|
var _a;
|
|
@@ -59,12 +63,14 @@ async function main() {
|
|
|
59
63
|
process.exit(0);
|
|
60
64
|
}
|
|
61
65
|
let effectiveRunners = {};
|
|
66
|
+
const runnerContext = {};
|
|
62
67
|
try {
|
|
63
68
|
const configModule = await (_a = path_1.default.join(process.cwd(), 'blueprint.config.ts'), Promise.resolve().then(() => __importStar(require(_a))));
|
|
64
69
|
try {
|
|
65
70
|
if ('config' in configModule && typeof configModule.config === 'object') {
|
|
66
71
|
const config = configModule.config;
|
|
67
|
-
|
|
72
|
+
runnerContext.config = config;
|
|
73
|
+
for (const plugin of config.plugins ?? []) {
|
|
68
74
|
for (const runner of plugin.runners()) {
|
|
69
75
|
effectiveRunners[runner.name] = runner.runner;
|
|
70
76
|
help_1.additionalHelpMessages[runner.name] = runner.help;
|
|
@@ -91,7 +97,7 @@ async function main() {
|
|
|
91
97
|
process.exit(1);
|
|
92
98
|
}
|
|
93
99
|
const ui = new InquirerUIProvider_1.InquirerUIProvider();
|
|
94
|
-
await runner(args, ui);
|
|
100
|
+
await runner(args, ui, runnerContext);
|
|
95
101
|
ui.close();
|
|
96
102
|
}
|
|
97
103
|
process.on('SIGINT', () => {
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.convert = void 0;
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const arg_1 = __importDefault(require("arg"));
|
|
10
|
+
const createNetworkProvider_1 = require("../network/createNetworkProvider");
|
|
11
|
+
const template_1 = require("../template");
|
|
12
|
+
const paths_1 = require("../paths");
|
|
13
|
+
function createWrapperName(old) {
|
|
14
|
+
return old
|
|
15
|
+
.split(/[-_]/)
|
|
16
|
+
.map((x) => x.replace(x[0], x[0].toUpperCase()))
|
|
17
|
+
.join('');
|
|
18
|
+
}
|
|
19
|
+
function quoteString(str) {
|
|
20
|
+
const quote = "'";
|
|
21
|
+
const quoted = str.startsWith(quote) && str.endsWith(quote);
|
|
22
|
+
return quoted ? str : quote + str + quote;
|
|
23
|
+
}
|
|
24
|
+
function findFile(dir, filename) {
|
|
25
|
+
const contents = (0, fs_1.readdirSync)(dir);
|
|
26
|
+
let hasFile = contents.includes(filename);
|
|
27
|
+
let foundPath = '';
|
|
28
|
+
if (hasFile) {
|
|
29
|
+
foundPath = path_1.default.join(dir, filename);
|
|
30
|
+
if ((0, fs_1.statSync)(foundPath).isFile()) {
|
|
31
|
+
return foundPath;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
for (let entry of contents) {
|
|
35
|
+
const entryPath = path_1.default.join(dir, entry);
|
|
36
|
+
const stat = (0, fs_1.statSync)(entryPath);
|
|
37
|
+
if (stat.isDirectory()) {
|
|
38
|
+
foundPath = findFile(entryPath, filename);
|
|
39
|
+
if (foundPath !== '') {
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return foundPath;
|
|
45
|
+
}
|
|
46
|
+
function parseCompileString(str, src_dir, ui) {
|
|
47
|
+
// Naive but does the job
|
|
48
|
+
const tokens = str.split(/\\?\s+/).filter((t) => t != '\\');
|
|
49
|
+
const outputIdx = tokens.indexOf('-o');
|
|
50
|
+
if (outputIdx < 0) {
|
|
51
|
+
throw new Error('No output flag (-o) found in command:' + str);
|
|
52
|
+
}
|
|
53
|
+
const outFile = tokens[outputIdx + 1];
|
|
54
|
+
const outputName = outFile.match(/([A-Za-z0-9\-_\\\/]*)/);
|
|
55
|
+
if (outputName === null) {
|
|
56
|
+
throw new Error(`Something went wrong when parsing output from ${outFile}`);
|
|
57
|
+
}
|
|
58
|
+
const wrapperName = createWrapperName(path_1.default.basename(outputName[1]));
|
|
59
|
+
const sourceFiles = tokens.filter((x) => x.match(/\.func|\.fc['"]?$/) !== null).map((t) => t.replace(/['"`]/g, ''));
|
|
60
|
+
if (sourceFiles.length === 0) {
|
|
61
|
+
throw new Error(`No source files found in command:${str}`);
|
|
62
|
+
}
|
|
63
|
+
for (let i = 0; i < sourceFiles.length; i++) {
|
|
64
|
+
const testPath = path_1.default.join(src_dir, sourceFiles[i]);
|
|
65
|
+
if ((0, fs_1.existsSync)(testPath)) {
|
|
66
|
+
sourceFiles[i] = quoteString(testPath);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const foundPath = findFile(src_dir, sourceFiles[i]);
|
|
70
|
+
if (foundPath === '') {
|
|
71
|
+
throw new Error(`${sourceFiles[i]} is not found anywhere`);
|
|
72
|
+
}
|
|
73
|
+
src_dir = path_1.default.dirname(foundPath);
|
|
74
|
+
sourceFiles[i] = quoteString(foundPath);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
name: wrapperName,
|
|
79
|
+
targets: sourceFiles.join(','),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const convert = async (args, ui) => {
|
|
83
|
+
const localArgs = (0, arg_1.default)(createNetworkProvider_1.argSpec);
|
|
84
|
+
let filePath;
|
|
85
|
+
if (localArgs._.length < 2) {
|
|
86
|
+
filePath = await ui.input('Please specify path to convert from:');
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
filePath = localArgs._[1];
|
|
90
|
+
}
|
|
91
|
+
const content = (0, fs_1.readFileSync)(filePath, { encoding: 'utf-8' });
|
|
92
|
+
const srcDir = path_1.default.dirname(filePath);
|
|
93
|
+
const compileStrings = content.replace(/\\[\r?\n]+/g, '').matchAll(/\s?func\s+(.*)\n/g);
|
|
94
|
+
if (compileStrings === null) {
|
|
95
|
+
throw new Error(`No func related commands found in ${filePath}`);
|
|
96
|
+
}
|
|
97
|
+
const templatePath = path_1.default.join(template_1.TEMPLATES_DIR, 'func', 'legacy', 'wrappers', 'compile.ts.template');
|
|
98
|
+
const templateContent = (0, fs_1.readFileSync)(templatePath, { encoding: 'utf-8' });
|
|
99
|
+
if (!(0, fs_1.existsSync)(paths_1.WRAPPERS_DIR)) {
|
|
100
|
+
ui.write('Creating wrappers directory...');
|
|
101
|
+
(0, fs_1.mkdirSync)(paths_1.WRAPPERS_DIR);
|
|
102
|
+
}
|
|
103
|
+
for (let compileStr of compileStrings) {
|
|
104
|
+
let parsed;
|
|
105
|
+
try {
|
|
106
|
+
parsed = parseCompileString(compileStr[1], srcDir, ui);
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
ui.write(e.toString());
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const resTemplate = (0, template_1.executeTemplate)(templateContent, parsed);
|
|
113
|
+
let lineIdx = resTemplate.indexOf('\n');
|
|
114
|
+
const contentIdx = lineIdx + 1;
|
|
115
|
+
if (resTemplate[lineIdx - 1] === '\r') {
|
|
116
|
+
lineIdx--;
|
|
117
|
+
}
|
|
118
|
+
const wrapperName = resTemplate.substring(0, lineIdx);
|
|
119
|
+
const fileName = path_1.default.join(paths_1.WRAPPERS_DIR, wrapperName);
|
|
120
|
+
const content = resTemplate.substring(contentIdx);
|
|
121
|
+
if ((0, fs_1.existsSync)(fileName)) {
|
|
122
|
+
ui.write(`File ${wrapperName} already exists!`);
|
|
123
|
+
const overwrite = await ui.prompt('Do you want to overwrite it?');
|
|
124
|
+
if (!overwrite) {
|
|
125
|
+
ui.write(`Skipping ${wrapperName}`);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
(0, fs_1.writeFileSync)(fileName, content, { encoding: 'utf-8' });
|
|
130
|
+
ui.write(`${wrapperName} wrapper created!`);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
exports.convert = convert;
|
package/dist/cli/help.js
CHANGED
|
@@ -13,9 +13,11 @@ List of available commands:
|
|
|
13
13
|
- create
|
|
14
14
|
- run
|
|
15
15
|
- build
|
|
16
|
+
- custom
|
|
16
17
|
- help
|
|
17
18
|
- test
|
|
18
|
-
- verify
|
|
19
|
+
- verify
|
|
20
|
+
- convert`,
|
|
19
21
|
create: `Usage: blueprint create [contract name] [flags]
|
|
20
22
|
|
|
21
23
|
Creates a new contract together with supporting files according to a template.
|
|
@@ -48,6 +50,9 @@ If contract name is not specified on the command line, the buildable contracts (
|
|
|
48
50
|
|
|
49
51
|
Flags:
|
|
50
52
|
--all - builds all buildable contracts instead of just one.`,
|
|
53
|
+
set: `Usage: blueprint set <key> [value]
|
|
54
|
+
Available keys:
|
|
55
|
+
- func - overrides @ton-community/func-js-bin version, effectively setting the func version. The required version may be passed as the value, otherwise available versions will be displayed.`,
|
|
51
56
|
test: `Usage: blueprint test
|
|
52
57
|
|
|
53
58
|
Just runs \`npm test\`, which by default runs \`jest\`.`,
|
|
@@ -61,6 +66,8 @@ Flags:
|
|
|
61
66
|
--custom-version - specifies the API version to use with the custom API. Options: v2 (defualt), v4.
|
|
62
67
|
--custom-key - specifies the API key to use with the custom API, can only be used with API v2.
|
|
63
68
|
--custom-type - specifies the network type to be indicated to scripts. Options: mainnet, testnet.`,
|
|
69
|
+
convert: `Usage: blueprint convert [path to build script]
|
|
70
|
+
Atempts to convert legacy bash build script to a blueprint compile wrapper.`,
|
|
64
71
|
};
|
|
65
72
|
exports.additionalHelpMessages = {};
|
|
66
73
|
const help = async (args, ui) => {
|
package/dist/cli/run.js
CHANGED
|
@@ -7,7 +7,7 @@ exports.run = void 0;
|
|
|
7
7
|
const createNetworkProvider_1 = require("../network/createNetworkProvider");
|
|
8
8
|
const utils_1 = require("../utils");
|
|
9
9
|
const arg_1 = __importDefault(require("arg"));
|
|
10
|
-
const run = async (args, ui) => {
|
|
10
|
+
const run = async (args, ui, context) => {
|
|
11
11
|
const localArgs = (0, arg_1.default)(createNetworkProvider_1.argSpec);
|
|
12
12
|
const { module: mod } = await (0, utils_1.selectFile)(await (0, utils_1.findScripts)(), {
|
|
13
13
|
ui,
|
|
@@ -16,7 +16,7 @@ const run = async (args, ui) => {
|
|
|
16
16
|
if (typeof mod.run !== 'function') {
|
|
17
17
|
throw new Error('Function `run` is missing!');
|
|
18
18
|
}
|
|
19
|
-
const networkProvider = await (0, createNetworkProvider_1.createNetworkProvider)(ui, localArgs);
|
|
19
|
+
const networkProvider = await (0, createNetworkProvider_1.createNetworkProvider)(ui, localArgs, context.config);
|
|
20
20
|
await mod.run(networkProvider, localArgs._.slice(2));
|
|
21
21
|
};
|
|
22
22
|
exports.run = run;
|
package/dist/cli/set.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.set = void 0;
|
|
7
|
+
const promises_1 = require("fs/promises");
|
|
8
|
+
const node_child_process_1 = require("node:child_process");
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const getVersions = (pkg, ui) => {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
(0, node_child_process_1.exec)(`npm view ${pkg} versions --json`, (error, stdout, stderr) => {
|
|
13
|
+
if (stderr) {
|
|
14
|
+
ui.write(stderr);
|
|
15
|
+
}
|
|
16
|
+
if (stdout) {
|
|
17
|
+
if (error === null) {
|
|
18
|
+
try {
|
|
19
|
+
const resJson = JSON.parse(stdout);
|
|
20
|
+
if (Array.isArray(resJson)) {
|
|
21
|
+
resolve(resJson);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
reject(new TypeError("Expect json array on stdout, but got:\n" + stdout));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
reject(e);
|
|
29
|
+
}
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
ui.write(stdout);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (error) {
|
|
37
|
+
ui.write("Failed to get func-js-bin package versions!");
|
|
38
|
+
reject(error);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
const install = (cmd, ui) => {
|
|
44
|
+
return new Promise((resolve, reject) => {
|
|
45
|
+
(0, node_child_process_1.exec)(cmd, (error, stdout, stderr) => {
|
|
46
|
+
if (stderr) {
|
|
47
|
+
ui.write(stderr);
|
|
48
|
+
}
|
|
49
|
+
if (stdout) {
|
|
50
|
+
ui.write(stdout);
|
|
51
|
+
}
|
|
52
|
+
if (error) {
|
|
53
|
+
reject(error);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
resolve();
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
const set = async (args, ui) => {
|
|
61
|
+
if (args._.length < 2) {
|
|
62
|
+
throw new Error('Please pass a key');
|
|
63
|
+
}
|
|
64
|
+
switch (args._[1]) {
|
|
65
|
+
case 'func': {
|
|
66
|
+
const pkg = '@ton-community/func-js-bin';
|
|
67
|
+
const funcVersions = await getVersions(pkg, ui);
|
|
68
|
+
let version = args._.length > 2 ? args._[2] : '';
|
|
69
|
+
if (!funcVersions.includes(version)) {
|
|
70
|
+
version = await ui.choose('Choose FunC version', funcVersions, (s) => s);
|
|
71
|
+
}
|
|
72
|
+
const packagePath = path_1.default.join(process.cwd(), 'package.json');
|
|
73
|
+
const packageContents = (await (0, promises_1.readFile)(packagePath)).toString('utf-8');
|
|
74
|
+
const parsedPackage = JSON.parse(packageContents);
|
|
75
|
+
const packageManager = await ui.choose('Choose your package manager', ['npm', 'yarn', 'pnpm', 'other'], (s) => s);
|
|
76
|
+
if (packageManager === 'other') {
|
|
77
|
+
ui.write(`Please find out how to override @ton-community/func-js-bin version to ${version} using your package manager, do that, and then install the packages`);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const overrideKey = packageManager === 'yarn' ? 'resolutions' : 'overrides';
|
|
81
|
+
parsedPackage[overrideKey] = {
|
|
82
|
+
...parsedPackage[overrideKey],
|
|
83
|
+
[pkg]: version,
|
|
84
|
+
};
|
|
85
|
+
ui.write('Updating package.json...');
|
|
86
|
+
await (0, promises_1.writeFile)(packagePath, JSON.stringify(parsedPackage, null, 4));
|
|
87
|
+
const installCmd = packageManager === 'yarn' ? 'yarn' : `${packageManager} i`;
|
|
88
|
+
try {
|
|
89
|
+
ui.write('Installing dependencies...');
|
|
90
|
+
await install(installCmd, ui);
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
ui.write('Failed to install dependencies, rolling back package.json');
|
|
94
|
+
await (0, promises_1.writeFile)(packagePath, packageContents);
|
|
95
|
+
throw e;
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
default: {
|
|
100
|
+
throw new Error('Unknown key: ' + args._[1]);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
exports.set = set;
|
package/dist/cli/verify.js
CHANGED
|
@@ -9,6 +9,7 @@ const compile_1 = require("../compile/compile");
|
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
10
|
const createNetworkProvider_1 = require("../network/createNetworkProvider");
|
|
11
11
|
const build_1 = require("./build");
|
|
12
|
+
const utils_1 = require("../utils");
|
|
12
13
|
const arg_1 = __importDefault(require("arg"));
|
|
13
14
|
const backends = {
|
|
14
15
|
mainnet: {
|
|
@@ -57,10 +58,62 @@ class VerifierRegistry {
|
|
|
57
58
|
});
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
|
-
|
|
61
|
+
async function lookupCodeHash(hash, ui, retryCount = 5) {
|
|
62
|
+
let queryResponse;
|
|
63
|
+
let foundAddr;
|
|
64
|
+
let done = false;
|
|
65
|
+
const graphqlUrl = 'https://dton.io/graphql/';
|
|
66
|
+
const query = `{
|
|
67
|
+
account_states(page:0, page_size:1, account_state_state_init_code_hash: "${hash.toString('hex').toUpperCase()}")
|
|
68
|
+
{
|
|
69
|
+
address
|
|
70
|
+
workchain
|
|
71
|
+
}
|
|
72
|
+
}`;
|
|
73
|
+
do {
|
|
74
|
+
try {
|
|
75
|
+
ui.write('Checking if such a contract is already deployed...');
|
|
76
|
+
const resp = await fetch(graphqlUrl, {
|
|
77
|
+
method: 'POST',
|
|
78
|
+
body: JSON.stringify({ query }),
|
|
79
|
+
headers: { 'Content-Type': 'application/json' },
|
|
80
|
+
});
|
|
81
|
+
if (resp.ok) {
|
|
82
|
+
queryResponse = await resp.json();
|
|
83
|
+
const states = queryResponse.data.account_states;
|
|
84
|
+
if (states.length > 0) {
|
|
85
|
+
const state = states[0];
|
|
86
|
+
foundAddr = core_1.Address.parseRaw(`${state.workchain}:${state.address}`).toString();
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
ui.write('No such contract was found!');
|
|
90
|
+
}
|
|
91
|
+
done = true;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
retryCount--;
|
|
95
|
+
}
|
|
96
|
+
// Meh
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
retryCount--;
|
|
100
|
+
if (e.cause) {
|
|
101
|
+
if (e.cause.code == 'ETIMEDOUT') {
|
|
102
|
+
ui.write('API timed out, waiting...');
|
|
103
|
+
await (0, utils_1.sleep)(5000);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
ui.write(e);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
} while (!done && retryCount > 0);
|
|
111
|
+
return foundAddr;
|
|
112
|
+
}
|
|
113
|
+
const verify = async (args, ui, context) => {
|
|
61
114
|
const localArgs = (0, arg_1.default)(createNetworkProvider_1.argSpec);
|
|
62
115
|
const sel = await (0, build_1.selectCompile)(ui, localArgs);
|
|
63
|
-
const networkProvider = await (0, createNetworkProvider_1.createNetworkProvider)(ui, localArgs, false);
|
|
116
|
+
const networkProvider = await (0, createNetworkProvider_1.createNetworkProvider)(ui, localArgs, context.config, false);
|
|
64
117
|
const sender = networkProvider.sender();
|
|
65
118
|
const senderAddress = sender.address;
|
|
66
119
|
if (senderAddress === undefined) {
|
|
@@ -70,8 +123,27 @@ const verify = async (args, ui) => {
|
|
|
70
123
|
if (network === 'custom') {
|
|
71
124
|
throw new Error('Cannot use custom network');
|
|
72
125
|
}
|
|
73
|
-
const addr = await ui.input('Deployed contract address');
|
|
74
126
|
const result = await (0, compile_1.doCompile)(sel.name);
|
|
127
|
+
const resHash = result.code.hash();
|
|
128
|
+
ui.write(`Compiled code hash hex:${resHash.toString('hex')}`);
|
|
129
|
+
ui.write('We can look up the address with such code hash in the blockchain automatically');
|
|
130
|
+
const passManually = await ui.prompt('Do you want to specify the address manually?');
|
|
131
|
+
let addr;
|
|
132
|
+
if (passManually) {
|
|
133
|
+
addr = (await ui.inputAddress('Deployed contract address')).toString();
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
const alreadyDeployed = await lookupCodeHash(resHash, ui);
|
|
137
|
+
if (alreadyDeployed) {
|
|
138
|
+
ui.write(`Contract is already deployed at: ${alreadyDeployed}\nUsing that address.`);
|
|
139
|
+
ui.write(`https://tonscan.org/address/${alreadyDeployed}`);
|
|
140
|
+
addr = alreadyDeployed;
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
ui.write("Please enter the contract's address manually");
|
|
144
|
+
addr = (await ui.inputAddress('Deployed contract address')).toString();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
75
147
|
let src;
|
|
76
148
|
const fd = new FormData();
|
|
77
149
|
if (result.lang === 'func') {
|
|
@@ -149,23 +221,26 @@ const verify = async (args, ui) => {
|
|
|
149
221
|
body: fd,
|
|
150
222
|
});
|
|
151
223
|
if (sourceResponse.status !== 200) {
|
|
152
|
-
throw new Error('Could not compile on backend:\n' + (await sourceResponse.
|
|
224
|
+
throw new Error('Could not compile on backend:\n' + (await sourceResponse.json()));
|
|
153
225
|
}
|
|
154
226
|
const sourceResult = await sourceResponse.json();
|
|
155
227
|
if (sourceResult.compileResult.result !== 'similar') {
|
|
156
|
-
throw new Error(
|
|
228
|
+
throw new Error(sourceResult.compileResult.error);
|
|
157
229
|
}
|
|
158
230
|
let msgCell = sourceResult.msgCell;
|
|
159
231
|
let acquiredSigs = 1;
|
|
160
232
|
while (acquiredSigs < verifier.quorum) {
|
|
161
|
-
const
|
|
233
|
+
const curBackend = removeRandom(remainingBackends);
|
|
234
|
+
ui.write(`Using backend: ${curBackend}`);
|
|
235
|
+
const signResponse = await fetch(curBackend + '/sign', {
|
|
162
236
|
method: 'POST',
|
|
163
237
|
body: JSON.stringify({
|
|
164
238
|
messageCell: msgCell,
|
|
165
239
|
}),
|
|
240
|
+
headers: { 'Content-Type': 'application/json' },
|
|
166
241
|
});
|
|
167
242
|
if (signResponse.status !== 200) {
|
|
168
|
-
throw new Error('Could not
|
|
243
|
+
throw new Error('Could not sign on backend:\n' + (await signResponse.text()));
|
|
169
244
|
}
|
|
170
245
|
const signResult = await signResponse.json();
|
|
171
246
|
msgCell = signResult.msgCell;
|
|
@@ -177,5 +252,6 @@ const verify = async (args, ui) => {
|
|
|
177
252
|
value: (0, core_1.toNano)('0.5'),
|
|
178
253
|
body: c,
|
|
179
254
|
});
|
|
255
|
+
ui.write(`Contract successfully verified at https://verifier.ton.org/${addr}`);
|
|
180
256
|
};
|
|
181
257
|
exports.verify = verify;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { SourceResolver, SourcesMap, SourcesArray } from '@ton-community/func-js';
|
|
2
2
|
import { Cell } from '@ton/core';
|
|
3
3
|
import { ConfigProject } from '@tact-lang/compiler';
|
|
4
|
+
export type HookParams = {
|
|
5
|
+
userData?: any;
|
|
6
|
+
};
|
|
4
7
|
export type CommonCompilerConfig = {
|
|
5
|
-
preCompileHook?: () => Promise<void>;
|
|
6
|
-
postCompileHook?: (code: Cell) => Promise<void>;
|
|
8
|
+
preCompileHook?: (params: HookParams) => Promise<void>;
|
|
9
|
+
postCompileHook?: (code: Cell, params: HookParams) => Promise<void>;
|
|
7
10
|
};
|
|
8
11
|
export type TactCompilerConfig = {
|
|
9
12
|
lang: 'tact';
|
|
@@ -14,5 +14,8 @@ export type TactCompileResult = {
|
|
|
14
14
|
code: Cell;
|
|
15
15
|
};
|
|
16
16
|
export type CompileResult = TactCompileResult | FuncCompileResult;
|
|
17
|
-
export declare function doCompile(name: string): Promise<CompileResult>;
|
|
18
|
-
export
|
|
17
|
+
export declare function doCompile(name: string, opts?: CompileOpts): Promise<CompileResult>;
|
|
18
|
+
export type CompileOpts = {
|
|
19
|
+
hookUserData?: any;
|
|
20
|
+
};
|
|
21
|
+
export declare function compile(name: string, opts?: CompileOpts): Promise<Cell>;
|
package/dist/compile/compile.js
CHANGED
|
@@ -106,20 +106,24 @@ async function doCompileInner(name, config) {
|
|
|
106
106
|
optLevel: config.optLevel,
|
|
107
107
|
});
|
|
108
108
|
}
|
|
109
|
-
async function doCompile(name) {
|
|
109
|
+
async function doCompile(name, opts) {
|
|
110
110
|
const config = await getCompilerConfigForContract(name);
|
|
111
111
|
if (config.preCompileHook !== undefined) {
|
|
112
|
-
await config.preCompileHook(
|
|
112
|
+
await config.preCompileHook({
|
|
113
|
+
userData: opts?.hookUserData,
|
|
114
|
+
});
|
|
113
115
|
}
|
|
114
116
|
const res = await doCompileInner(name, config);
|
|
115
117
|
if (config.postCompileHook !== undefined) {
|
|
116
|
-
await config.postCompileHook(res.code
|
|
118
|
+
await config.postCompileHook(res.code, {
|
|
119
|
+
userData: opts?.hookUserData,
|
|
120
|
+
});
|
|
117
121
|
}
|
|
118
122
|
return res;
|
|
119
123
|
}
|
|
120
124
|
exports.doCompile = doCompile;
|
|
121
|
-
async function compile(name) {
|
|
122
|
-
const result = await doCompile(name);
|
|
125
|
+
async function compile(name, opts) {
|
|
126
|
+
const result = await doCompile(name, opts);
|
|
123
127
|
return result.code;
|
|
124
128
|
}
|
|
125
129
|
exports.compile = compile;
|
package/dist/config/Config.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
export { tonDeepLink, sleep } from './utils';
|
|
2
2
|
export { NetworkProvider } from './network/NetworkProvider';
|
|
3
3
|
export { createNetworkProvider } from './network/createNetworkProvider';
|
|
4
|
-
export { compile } from './compile/compile';
|
|
5
|
-
export { CompilerConfig } from './compile/CompilerConfig';
|
|
4
|
+
export { compile, CompileOpts } from './compile/compile';
|
|
5
|
+
export { CompilerConfig, HookParams } from './compile/CompilerConfig';
|
|
6
6
|
export { UIProvider } from './ui/UIProvider';
|
|
7
7
|
export { Config } from './config/Config';
|
|
8
|
-
export { Args, Runner } from './cli/Runner';
|
|
8
|
+
export { Args, Runner, RunnerContext } from './cli/Runner';
|
|
9
9
|
export { PluginRunner, Plugin } from './config/Plugin';
|
|
10
|
+
export { CustomNetwork } from './config/CustomNetwork';
|
|
10
11
|
export { buildOne, buildAll } from './build';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import arg from 'arg';
|
|
2
2
|
import { UIProvider } from '../ui/UIProvider';
|
|
3
3
|
import { NetworkProvider } from './NetworkProvider';
|
|
4
|
+
import { Config } from '../config/Config';
|
|
4
5
|
export declare const argSpec: {
|
|
5
6
|
'--mainnet': BooleanConstructor;
|
|
6
7
|
'--testnet': BooleanConstructor;
|
|
@@ -18,4 +19,4 @@ export declare const argSpec: {
|
|
|
18
19
|
'--dton': BooleanConstructor;
|
|
19
20
|
};
|
|
20
21
|
export type Args = arg.Result<typeof argSpec>;
|
|
21
|
-
export declare function createNetworkProvider(ui: UIProvider, args: Args, allowCustom?: boolean): Promise<NetworkProvider>;
|
|
22
|
+
export declare function createNetworkProvider(ui: UIProvider, args: Args, config?: Config, allowCustom?: boolean): Promise<NetworkProvider>;
|
|
@@ -13,7 +13,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
13
13
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
15
|
};
|
|
16
|
-
var _SendProviderSender_provider, _WrappedContractProvider_address, _WrappedContractProvider_provider, _WrappedContractProvider_init, _NetworkProviderImpl_tc, _NetworkProviderImpl_sender, _NetworkProviderImpl_network, _NetworkProviderImpl_explorer, _NetworkProviderImpl_ui;
|
|
16
|
+
var _SendProviderSender_provider, _WrappedContractProvider_address, _WrappedContractProvider_provider, _WrappedContractProvider_init, _WrappedContractProvider_factory, _NetworkProviderImpl_tc, _NetworkProviderImpl_sender, _NetworkProviderImpl_network, _NetworkProviderImpl_explorer, _NetworkProviderImpl_ui;
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.createNetworkProvider = exports.argSpec = void 0;
|
|
19
19
|
const utils_1 = require("../utils");
|
|
@@ -63,13 +63,15 @@ class SendProviderSender {
|
|
|
63
63
|
}
|
|
64
64
|
_SendProviderSender_provider = new WeakMap();
|
|
65
65
|
class WrappedContractProvider {
|
|
66
|
-
constructor(address,
|
|
66
|
+
constructor(address, factory, init) {
|
|
67
67
|
_WrappedContractProvider_address.set(this, void 0);
|
|
68
68
|
_WrappedContractProvider_provider.set(this, void 0);
|
|
69
69
|
_WrappedContractProvider_init.set(this, void 0);
|
|
70
|
+
_WrappedContractProvider_factory.set(this, void 0);
|
|
70
71
|
__classPrivateFieldSet(this, _WrappedContractProvider_address, address, "f");
|
|
71
|
-
__classPrivateFieldSet(this, _WrappedContractProvider_provider,
|
|
72
|
+
__classPrivateFieldSet(this, _WrappedContractProvider_provider, factory({ address, init }), "f");
|
|
72
73
|
__classPrivateFieldSet(this, _WrappedContractProvider_init, init, "f");
|
|
74
|
+
__classPrivateFieldSet(this, _WrappedContractProvider_factory, factory, "f");
|
|
73
75
|
}
|
|
74
76
|
async getState() {
|
|
75
77
|
return await __classPrivateFieldGet(this, _WrappedContractProvider_provider, "f").getState();
|
|
@@ -91,8 +93,14 @@ class WrappedContractProvider {
|
|
|
91
93
|
body: typeof args.body === 'string' ? (0, core_1.comment)(args.body) : args.body,
|
|
92
94
|
});
|
|
93
95
|
}
|
|
96
|
+
open(contract) {
|
|
97
|
+
return (0, core_1.openContract)(contract, (params) => new WrappedContractProvider(params.address, __classPrivateFieldGet(this, _WrappedContractProvider_factory, "f"), params.init));
|
|
98
|
+
}
|
|
99
|
+
getTransactions(address, lt, hash, limit) {
|
|
100
|
+
return __classPrivateFieldGet(this, _WrappedContractProvider_provider, "f").getTransactions(address, lt, hash, limit);
|
|
101
|
+
}
|
|
94
102
|
}
|
|
95
|
-
_WrappedContractProvider_address = new WeakMap(), _WrappedContractProvider_provider = new WeakMap(), _WrappedContractProvider_init = new WeakMap();
|
|
103
|
+
_WrappedContractProvider_address = new WeakMap(), _WrappedContractProvider_provider = new WeakMap(), _WrappedContractProvider_init = new WeakMap(), _WrappedContractProvider_factory = new WeakMap();
|
|
96
104
|
class NetworkProviderImpl {
|
|
97
105
|
constructor(tc, sender, network, explorer, ui) {
|
|
98
106
|
_NetworkProviderImpl_tc.set(this, void 0);
|
|
@@ -119,12 +127,8 @@ class NetworkProviderImpl {
|
|
|
119
127
|
return __classPrivateFieldGet(this, _NetworkProviderImpl_tc, "f");
|
|
120
128
|
}
|
|
121
129
|
provider(address, init) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
return new WrappedContractProvider(address, __classPrivateFieldGet(this, _NetworkProviderImpl_tc, "f").provider(address, { code: init?.code ?? new core_1.Cell(), data: init?.data ?? new core_1.Cell() }), init);
|
|
127
|
-
}
|
|
130
|
+
const factory = (params) => __classPrivateFieldGet(this, _NetworkProviderImpl_tc, "f").provider(params.address, params.init);
|
|
131
|
+
return new WrappedContractProvider(address, factory, init);
|
|
128
132
|
}
|
|
129
133
|
async isContractDeployed(address) {
|
|
130
134
|
if (__classPrivateFieldGet(this, _NetworkProviderImpl_tc, "f") instanceof ton_1.TonClient4) {
|
|
@@ -176,7 +180,7 @@ class NetworkProviderImpl {
|
|
|
176
180
|
await this.waitForDeploy(contract.address, waitAttempts);
|
|
177
181
|
}
|
|
178
182
|
open(contract) {
|
|
179
|
-
return (0, core_1.openContract)(contract, (params) => this.provider(params.address, params.init ??
|
|
183
|
+
return (0, core_1.openContract)(contract, (params) => this.provider(params.address, params.init ?? null));
|
|
180
184
|
}
|
|
181
185
|
ui() {
|
|
182
186
|
return __classPrivateFieldGet(this, _NetworkProviderImpl_ui, "f");
|
|
@@ -198,9 +202,10 @@ async function createMnemonicProvider(client, ui) {
|
|
|
198
202
|
});
|
|
199
203
|
}
|
|
200
204
|
class NetworkProviderBuilder {
|
|
201
|
-
constructor(args, ui, allowCustom = true) {
|
|
205
|
+
constructor(args, ui, config, allowCustom = true) {
|
|
202
206
|
this.args = args;
|
|
203
207
|
this.ui = ui;
|
|
208
|
+
this.config = config;
|
|
204
209
|
this.allowCustom = allowCustom;
|
|
205
210
|
}
|
|
206
211
|
async chooseNetwork() {
|
|
@@ -209,14 +214,18 @@ class NetworkProviderBuilder {
|
|
|
209
214
|
testnet: this.args['--testnet'],
|
|
210
215
|
custom: this.args['--custom'] !== undefined,
|
|
211
216
|
});
|
|
212
|
-
if (
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
217
|
+
if (network !== undefined) {
|
|
218
|
+
return network;
|
|
219
|
+
}
|
|
220
|
+
if (this.config?.network !== undefined) {
|
|
221
|
+
return typeof this.config.network === 'string' ? this.config.network : 'custom';
|
|
222
|
+
}
|
|
223
|
+
network = await this.ui.choose('Which network do you want to use?', ['mainnet', 'testnet', 'custom'], (c) => c);
|
|
224
|
+
if (network === 'custom') {
|
|
225
|
+
const defaultCustomEndpoint = 'http://localhost:8081/';
|
|
226
|
+
this.args['--custom'] = (await this.ui.input(`Provide a custom API v2 endpoint (default is ${defaultCustomEndpoint})`)).trim();
|
|
227
|
+
if (this.args['--custom'] === '')
|
|
228
|
+
this.args['--custom'] = defaultCustomEndpoint;
|
|
220
229
|
}
|
|
221
230
|
return network;
|
|
222
231
|
}
|
|
@@ -290,26 +299,50 @@ class NetworkProviderBuilder {
|
|
|
290
299
|
}
|
|
291
300
|
let tc;
|
|
292
301
|
if (network === 'custom') {
|
|
293
|
-
|
|
294
|
-
if (this.
|
|
302
|
+
let configNetwork = undefined;
|
|
303
|
+
if (this.config?.network !== undefined && typeof this.config.network !== 'string') {
|
|
304
|
+
configNetwork = this.config.network;
|
|
305
|
+
}
|
|
306
|
+
if (this.args['--custom'] !== undefined) {
|
|
307
|
+
const inputVer = this.args['--custom-version'];
|
|
308
|
+
let version = undefined;
|
|
309
|
+
if (inputVer !== undefined) {
|
|
310
|
+
version = inputVer.toLowerCase(); // checks come later
|
|
311
|
+
}
|
|
312
|
+
const inputType = this.args['--custom-type'];
|
|
313
|
+
let type = undefined;
|
|
314
|
+
if (inputType !== undefined) {
|
|
315
|
+
type = inputType; // checks come later
|
|
316
|
+
}
|
|
317
|
+
configNetwork = {
|
|
318
|
+
endpoint: this.args['--custom'],
|
|
319
|
+
version,
|
|
320
|
+
key: this.args['--custom-key'],
|
|
321
|
+
type,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
if (configNetwork === undefined) {
|
|
325
|
+
throw new Error('Custom network is (somehow) undefined');
|
|
326
|
+
}
|
|
327
|
+
if (configNetwork.version === undefined || configNetwork.version === 'v2') {
|
|
295
328
|
tc = new ton_1.TonClient({
|
|
296
|
-
endpoint: endpoint
|
|
297
|
-
apiKey:
|
|
329
|
+
endpoint: configNetwork.endpoint,
|
|
330
|
+
apiKey: configNetwork.key,
|
|
298
331
|
});
|
|
299
332
|
}
|
|
300
|
-
else if (
|
|
301
|
-
if (
|
|
333
|
+
else if (configNetwork.version === 'v4') {
|
|
334
|
+
if (configNetwork.key !== undefined) {
|
|
302
335
|
throw new Error('Cannot use a custom API key with a v4 API');
|
|
303
336
|
}
|
|
304
337
|
tc = new ton_1.TonClient4({
|
|
305
|
-
endpoint,
|
|
338
|
+
endpoint: configNetwork.endpoint,
|
|
306
339
|
});
|
|
307
340
|
}
|
|
308
341
|
else {
|
|
309
|
-
throw new Error('Unknown API version: ' +
|
|
342
|
+
throw new Error('Unknown API version: ' + configNetwork.version);
|
|
310
343
|
}
|
|
311
|
-
if (
|
|
312
|
-
const ct =
|
|
344
|
+
if (configNetwork.type !== undefined) {
|
|
345
|
+
const ct = configNetwork.type.toLowerCase();
|
|
313
346
|
if (!['mainnet', 'testnet', 'custom'].includes(ct)) {
|
|
314
347
|
throw new Error('Unknown network type: ' + ct);
|
|
315
348
|
}
|
|
@@ -339,7 +372,7 @@ class NetworkProviderBuilder {
|
|
|
339
372
|
return new NetworkProviderImpl(tc, sender, network, explorer, this.ui);
|
|
340
373
|
}
|
|
341
374
|
}
|
|
342
|
-
async function createNetworkProvider(ui, args, allowCustom = true) {
|
|
343
|
-
return await new NetworkProviderBuilder(args, ui, allowCustom).build();
|
|
375
|
+
async function createNetworkProvider(ui, args, config, allowCustom = true) {
|
|
376
|
+
return await new NetworkProviderBuilder(args, ui, config, allowCustom).build();
|
|
344
377
|
}
|
|
345
378
|
exports.createNetworkProvider = createNetworkProvider;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { UIProvider } from '../ui/UIProvider';
|
|
2
|
+
import { Address } from '@ton/core';
|
|
2
3
|
export declare class InquirerUIProvider implements UIProvider {
|
|
3
4
|
#private;
|
|
4
5
|
constructor();
|
|
5
6
|
write(message: string): void;
|
|
6
7
|
prompt(message: string): Promise<boolean>;
|
|
8
|
+
inputAddress(message: string, fallback?: Address): Promise<Address>;
|
|
7
9
|
input(message: string): Promise<string>;
|
|
8
10
|
choose<T>(message: string, choices: T[], display: (v: T) => string): Promise<T>;
|
|
9
11
|
setActionPrompt(message: string): void;
|
|
@@ -17,6 +17,7 @@ var _InquirerUIProvider_bottomBar;
|
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.InquirerUIProvider = void 0;
|
|
19
19
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
20
|
+
const core_1 = require("@ton/core");
|
|
20
21
|
class DestroyableBottomBar extends inquirer_1.default.ui.BottomBar {
|
|
21
22
|
destroy() {
|
|
22
23
|
this.close();
|
|
@@ -38,6 +39,18 @@ class InquirerUIProvider {
|
|
|
38
39
|
});
|
|
39
40
|
return prompt;
|
|
40
41
|
}
|
|
42
|
+
async inputAddress(message, fallback) {
|
|
43
|
+
const prompt = message + (fallback === undefined ? '' : ` (default: ${fallback})`);
|
|
44
|
+
while (true) {
|
|
45
|
+
const addr = (await this.input(prompt)).trim();
|
|
46
|
+
try {
|
|
47
|
+
return addr === '' && fallback !== undefined ? fallback : core_1.Address.parse(addr);
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
this.write(addr + ' is not valid!\n');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
41
54
|
async input(message) {
|
|
42
55
|
const { val } = await inquirer_1.default.prompt({
|
|
43
56
|
name: 'val',
|
package/dist/ui/UIProvider.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { Address } from '@ton/core';
|
|
1
2
|
export interface UIProvider {
|
|
2
3
|
write(message: string): void;
|
|
3
4
|
prompt(message: string): Promise<boolean>;
|
|
5
|
+
inputAddress(message: string, fallback?: Address): Promise<Address>;
|
|
4
6
|
input(message: string): Promise<string>;
|
|
5
7
|
choose<T>(message: string, choices: T[], display: (v: T) => string): Promise<T>;
|
|
6
8
|
setActionPrompt(message: string): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ton/blueprint",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "Framework for development of TON smart contracts",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": "./dist/cli/cli.js",
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
"format": "prettier --write src"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"@ton/core": "^0.
|
|
22
|
+
"@ton/core": "^0.56.0",
|
|
23
23
|
"@ton/crypto": "^3.2.0",
|
|
24
|
-
"@ton/ton": "^13.
|
|
24
|
+
"@ton/ton": "^13.11.0",
|
|
25
25
|
"@types/inquirer": "^8.2.6",
|
|
26
26
|
"@types/node": "^20.2.5",
|
|
27
27
|
"@types/qrcode-terminal": "^0.12.0",
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"typescript": "^4.9.5"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@ton/core": ">=0.
|
|
32
|
+
"@ton/core": ">=0.56.0",
|
|
33
33
|
"@ton/crypto": ">=3.2.0",
|
|
34
|
-
"@ton/ton": ">=13.
|
|
34
|
+
"@ton/ton": ">=13.11.0"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@orbs-network/ton-access": "^2.3.3",
|