@ton/blueprint 0.23.0 → 0.25.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.
Files changed (29) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +13 -8
  3. package/dist/cli/constants.js +11 -3
  4. package/dist/cli/create.d.ts +0 -4
  5. package/dist/cli/create.js +3 -21
  6. package/dist/compile/CompilerConfig.d.ts +8 -1
  7. package/dist/compile/compile.d.ts +13 -3
  8. package/dist/compile/compile.js +26 -0
  9. package/dist/index.d.ts +1 -1
  10. package/dist/network/createNetworkProvider.d.ts +0 -1
  11. package/dist/network/createNetworkProvider.js +23 -34
  12. package/dist/network/send/MnemonicProvider.d.ts +1 -1
  13. package/dist/network/send/MnemonicProvider.js +2 -0
  14. package/dist/templates/func/common/contracts/imports/stdlib.fc.template +885 -0
  15. package/dist/templates/func/not-separated-common/contracts/imports/stdlib.fc.template +885 -0
  16. package/dist/templates/tolk/common/compilables/compile.ts.template +9 -0
  17. package/dist/templates/tolk/counter/contracts/contract.tolk.template +71 -0
  18. package/dist/templates/tolk/counter/scripts/deploy.ts.template +22 -0
  19. package/dist/templates/tolk/counter/scripts/increment.ts.template +38 -0
  20. package/dist/templates/tolk/counter/tests/spec.ts.template +82 -0
  21. package/dist/templates/tolk/counter/wrappers/wrapper.ts.template +67 -0
  22. package/dist/templates/tolk/empty/contracts/contract.tolk.template +4 -0
  23. package/dist/templates/tolk/empty/scripts/deploy.ts.template +14 -0
  24. package/dist/templates/tolk/empty/tests/spec.ts.template +40 -0
  25. package/dist/templates/tolk/empty/wrappers/wrapper.ts.template +30 -0
  26. package/dist/templates/tolk/not-separated-common/wrappers/compile.ts.template +9 -0
  27. package/package.json +9 -8
  28. package/dist/network/send/TonHubProvider.d.ts +0 -16
  29. package/dist/network/send/TonHubProvider.js +0 -110
package/CHANGELOG.md CHANGED
@@ -5,6 +5,27 @@ 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.25.0] - 2024-11-02
9
+
10
+ ### Added
11
+
12
+ - Support for Tolk, "next-generation FunC", a new language for writing smart contracts in TON. [Tolk overview](https://docs.ton.org/develop/tolk/overview)
13
+
14
+ ## [0.24.0] - 2024-09-16
15
+
16
+ ### Added
17
+
18
+ - Added support for wallet v5 in the Mnemonic provider
19
+
20
+ ### Changed
21
+
22
+ - Changed the default API provider to Toncenter v2 (instead of Orbs TON Access). Rate limited requests are automatically retried
23
+ - Updated dependencies
24
+
25
+ ### Removed
26
+
27
+ - Removed the specialized TonHub connector. Use TON Connect instead
28
+
8
29
  ## [0.23.0] - 2024-09-11
9
30
 
10
31
  ### Changed
package/README.md CHANGED
@@ -39,7 +39,7 @@ npm create ton@latest
39
39
 
40
40
  ## Overview
41
41
 
42
- Blueprint is an all-in-one development environment designed to enhance the process of creating, testing, and deploying smart contracts on TON blockchain using [FunC](https://docs.ton.org/develop/func/overview) and [Tact](https://docs.tact-lang.org/) languages
42
+ Blueprint is an all-in-one development environment designed to enhance the process of creating, testing, and deploying smart contracts on TON blockchain using [FunC](https://docs.ton.org/develop/func/overview), [Tolk](https://docs.ton.org/develop/tolk/overview), and [Tact](https://docs.tact-lang.org/) languages.
43
43
 
44
44
  ### Core features
45
45
 
@@ -51,15 +51,16 @@ Blueprint is an all-in-one development environment designed to enhance the proce
51
51
  ### Tech stack
52
52
 
53
53
  1. Compiling FunC with https://github.com/ton-community/func-js
54
- 2. Compiling Tact with https://github.com/tact-lang/tact
55
- 3. Testing smart contracts with https://github.com/ton-org/sandbox
56
- 4. Deploying smart contracts with [TON Connect 2](https://github.com/ton-connect), [Tonhub wallet](https://tonhub.com/) or a `ton://` deeplink
54
+ 2. Compiling Tolk with https://github.com/ton-blockchain/tolk-js
55
+ 3. Compiling Tact with https://github.com/tact-lang/tact
56
+ 4. Testing smart contracts with https://github.com/ton-org/sandbox
57
+ 5. Deploying smart contracts with [TON Connect 2](https://github.com/ton-connect) or a `ton://` deeplink
57
58
 
58
59
  ### Requirements
59
60
 
60
61
  * [Node.js](https://nodejs.org) with a recent version like v18. Version can be verified with `node -v`
61
62
  * IDE with TON support:
62
- * [Visual Studio Code](https://code.visualstudio.com/) with the [FunC plugin](https://marketplace.visualstudio.com/items?itemName=tonwhales.func-vscode)
63
+ * [Visual Studio Code](https://code.visualstudio.com/) with the [FunC plugin](https://marketplace.visualstudio.com/items?itemName=tonwhales.func-vscode) or [Tolk plugin](https://marketplace.visualstudio.com/items?itemName=ton-core.tolk-vscode)
63
64
  * [IntelliJ IDEA](https://www.jetbrains.com/idea/) with the [TON Development plugin](https://plugins.jetbrains.com/plugin/23382-ton)
64
65
 
65
66
  ## Features overview
@@ -71,7 +72,7 @@ Blueprint is an all-in-one development environment designed to enhance the proce
71
72
 
72
73
  ### Directory structure
73
74
 
74
- * `contracts/` - Source code in [FunC](https://docs.ton.org/develop/func/overview) or [Tact](https://tact-lang.org/) for all smart contracts and their imports
75
+ * `contracts/` - Source code for all smart contracts and their imports
75
76
  * `wrappers/` - TypeScript interface classes for all contracts (implementing `Contract` from [@ton/core](https://www.npmjs.com/package/@ton/core))
76
77
  * include message [de]serialization primitives, getter wrappers and compilation functions
77
78
  * used by the test suite and client code to interact with the contracts from TypeScript
@@ -131,7 +132,7 @@ Before developing, make sure that your current working directory is located in t
131
132
  ### Creating contracts
132
133
 
133
134
  1. Run interactive:    `npx blueprint create`   or   `yarn blueprint create`
134
- 2. Non-interactive: &nbsp; `npx/yarn blueprint create <CONTRACT> --type <TYPE>` (type can be `func-empty`, `func-counter`, `tact-empty`, `tact-counter`)
135
+ 2. Non-interactive: &nbsp; `npx/yarn blueprint create <CONTRACT> --type <TYPE>` (type can be `func-empty`, `tolk-empty`, `tact-empty`, `func-counter`, `tolk-counter`, `tact-counter`)
135
136
  * Example: `yarn blueprint create MyNewContract --type func-empty`
136
137
 
137
138
  ### Writing contract code
@@ -141,8 +142,12 @@ Before developing, make sure that your current working directory is located in t
141
142
  2. Implement shared FunC imports (if breaking code to multiple files) in `contracts/imports/*.fc`
142
143
  3. Implement wrapper TypeScript class in `wrappers/<CONTRACT>.ts` to encode messages and decode getters
143
144
 
145
+ #### Tolk
146
+ 1. Implement the contract in `contracts/<CONTRACT>.tolk`; if you wish, split into multiple files
147
+ 2. Implement wrapper TypeScript class in `wrappers/<CONTRACT>.ts` to encode messages and decode getters
148
+
144
149
  #### Tact
145
- 1. Implement tact contract in `contracts/<CONTRACT>.tact`
150
+ 1. Implement the contract in `contracts/<CONTRACT>.tact`
146
151
  2. Wrappers will be automatically generated in `build/<CONTRACT>/tact_<CONTRACT>.ts`
147
152
 
148
153
  ### Testing contracts
@@ -7,13 +7,21 @@ exports.templateTypes = [
7
7
  value: 'func-empty',
8
8
  },
9
9
  {
10
- name: 'A simple counter contract (FunC)',
11
- value: 'func-counter',
10
+ name: 'An empty contract (Tolk)',
11
+ value: 'tolk-empty',
12
12
  },
13
13
  {
14
14
  name: 'An empty contract (TACT)',
15
15
  value: 'tact-empty',
16
16
  },
17
+ {
18
+ name: 'A simple counter contract (FunC)',
19
+ value: 'func-counter',
20
+ },
21
+ {
22
+ name: 'A simple counter contract (Tolk)',
23
+ value: 'tolk-counter',
24
+ },
17
25
  {
18
26
  name: 'A simple counter contract (TACT)',
19
27
  value: 'tact-counter',
@@ -58,7 +66,7 @@ Flags:
58
66
  --custom-version - specifies the API version to use with the custom API. Options: v2 (defualt), v4.
59
67
  --custom-key - specifies the API key to use with the custom API, can only be used with API v2.
60
68
  --custom-type - specifies the network type to be indicated to scripts. Options: custom (default), mainnet, testnet.
61
- --tonconnect, --tonhub, --deeplink, --mnemonic - specifies the deployer to use when running the script. If not specified on the command line, it will be asked interactively.
69
+ --tonconnect, --deeplink, --mnemonic - specifies the deployer to use when running the script. If not specified on the command line, it will be asked interactively.
62
70
  --tonscan, --tonviewer, --toncx, --dton - specifies the network explorer to use when displaying links to the deployed contracts. Default: tonscan.`,
63
71
  build: `Usage: blueprint build [contract name] [flags]
64
72
 
@@ -1,6 +1,2 @@
1
1
  import { Runner } from './Runner';
2
- export declare const templateTypes: {
3
- name: string;
4
- value: string;
5
- }[];
6
2
  export declare const create: Runner;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.create = exports.templateTypes = void 0;
6
+ exports.create = void 0;
7
7
  const promises_1 = require("fs/promises");
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const template_1 = require("../template");
@@ -47,24 +47,6 @@ async function createFiles(templatePath, realPath, replaces) {
47
47
  }
48
48
  }
49
49
  }
50
- exports.templateTypes = [
51
- {
52
- name: 'An empty contract (FunC)',
53
- value: 'func-empty',
54
- },
55
- {
56
- name: 'A simple counter contract (FunC)',
57
- value: 'func-counter',
58
- },
59
- {
60
- name: 'An empty contract (TACT)',
61
- value: 'tact-empty',
62
- },
63
- {
64
- name: 'A simple counter contract (TACT)',
65
- value: 'tact-counter',
66
- },
67
- ];
68
50
  const create = async (args, ui) => {
69
51
  const localArgs = (0, arg_1.default)({
70
52
  '--type': String,
@@ -81,7 +63,7 @@ const create = async (args, ui) => {
81
63
  throw new Error(`Cannot create a contract with an empty name`);
82
64
  if (name.toLowerCase() === 'contract' || !/^[A-Z][a-zA-Z0-9]*$/.test(name))
83
65
  throw new Error(`Cannot create a contract with the name '${name}'`);
84
- const which = (await (0, utils_1.selectOption)(exports.templateTypes, {
66
+ const which = (await (0, utils_1.selectOption)(constants_1.templateTypes, {
85
67
  ui,
86
68
  msg: 'What type of contract do you want to create?',
87
69
  hint: localArgs['--type'],
@@ -92,7 +74,7 @@ const create = async (args, ui) => {
92
74
  name,
93
75
  loweredName: name.substring(0, 1).toLowerCase() + name.substring(1),
94
76
  snakeName,
95
- contractPath: 'contracts/' + snakeName + '.' + (lang === 'func' ? 'fc' : 'tact'),
77
+ contractPath: 'contracts/' + snakeName + '.' + (lang === 'func' ? 'fc' : (lang === 'tolk' ? 'tolk' : 'tact')),
96
78
  };
97
79
  const config = await (0, utils_2.getConfig)();
98
80
  const commonPath = config?.separateCompilables ? 'common' : 'not-separated-common';
@@ -23,4 +23,11 @@ export type FuncCompilerConfig = {
23
23
  targets?: string[];
24
24
  sources: SourcesArray;
25
25
  });
26
- export type CompilerConfig = (TactCompilerConfig | FuncCompilerConfig) & CommonCompilerConfig;
26
+ export type TolkCompilerConfig = {
27
+ lang: 'tolk';
28
+ entrypoint: string;
29
+ optimizationLevel?: number;
30
+ withStackComments?: boolean;
31
+ experimentalOptions?: string;
32
+ };
33
+ export type CompilerConfig = (TactCompilerConfig | FuncCompilerConfig | TolkCompilerConfig) & CommonCompilerConfig;
@@ -1,14 +1,24 @@
1
1
  /// <reference types="node" />
2
- import { SourcesArray } from '@ton-community/func-js';
3
2
  import { Cell } from '@ton/core';
4
3
  import { TactCompilerConfig } from './CompilerConfig';
5
4
  export declare function getCompilablesDirectory(): Promise<string>;
6
5
  export declare const COMPILE_END = ".compile.ts";
6
+ export type SourceSnapshot = {
7
+ filename: string;
8
+ content: string;
9
+ };
10
+ export type TolkCompileResult = {
11
+ lang: 'tolk';
12
+ stderr: string;
13
+ code: Cell;
14
+ snapshot: SourceSnapshot[];
15
+ version: string;
16
+ };
7
17
  export type FuncCompileResult = {
8
18
  lang: 'func';
9
19
  code: Cell;
10
20
  targets: string[];
11
- snapshot: SourcesArray;
21
+ snapshot: SourceSnapshot[];
12
22
  version: string;
13
23
  };
14
24
  export type TactCompileResult = {
@@ -17,7 +27,7 @@ export type TactCompileResult = {
17
27
  code: Cell;
18
28
  options?: TactCompilerConfig['options'];
19
29
  };
20
- export type CompileResult = TactCompileResult | FuncCompileResult;
30
+ export type CompileResult = TactCompileResult | FuncCompileResult | TolkCompileResult;
21
31
  export declare function doCompile(name: string, opts?: CompileOpts): Promise<CompileResult>;
22
32
  export type CompileOpts = {
23
33
  hookUserData?: any;
@@ -35,6 +35,7 @@ const paths_1 = require("../paths");
35
35
  const Tact = __importStar(require("@tact-lang/compiler"));
36
36
  const OverwritableVirtualFileSystem_1 = require("./OverwritableVirtualFileSystem");
37
37
  const utils_1 = require("../config/utils");
38
+ const tolk_js_1 = require("@ton/tolk-js");
38
39
  async function getCompilablesDirectory() {
39
40
  const config = await (0, utils_1.getConfig)();
40
41
  if (config?.separateCompilables) {
@@ -53,6 +54,22 @@ async function getCompilerConfigForContract(name) {
53
54
  }
54
55
  return mod.compile;
55
56
  }
57
+ async function doCompileTolk(config) {
58
+ const res = await (0, tolk_js_1.runTolkCompiler)(config);
59
+ if (res.status === 'error') {
60
+ throw new Error(res.message);
61
+ }
62
+ return {
63
+ lang: 'tolk',
64
+ stderr: res.stderr,
65
+ code: core_1.Cell.fromBase64(res.codeBoc64),
66
+ snapshot: res.sourcesSnapshot.map((e) => ({
67
+ filename: e.filename,
68
+ content: e.contents,
69
+ })),
70
+ version: await (0, tolk_js_1.getTolkCompilerVersion)(),
71
+ };
72
+ }
56
73
  async function doCompileFunc(config) {
57
74
  const cr = await (0, func_js_1.compileFunc)(config);
58
75
  if (cr.status === 'error')
@@ -126,6 +143,15 @@ async function doCompileInner(name, config) {
126
143
  if (config.lang === 'tact') {
127
144
  return await doCompileTact(config, name);
128
145
  }
146
+ if (config.lang === 'tolk') {
147
+ return await doCompileTolk({
148
+ entrypointFileName: config.entrypoint,
149
+ fsReadCallback: (path) => (0, fs_1.readFileSync)(path).toString(),
150
+ optimizationLevel: config.optimizationLevel,
151
+ withStackComments: config.withStackComments,
152
+ experimentalOptions: config.experimentalOptions,
153
+ });
154
+ }
129
155
  return await doCompileFunc({
130
156
  targets: config.targets,
131
157
  sources: config.sources ?? ((path) => (0, fs_1.readFileSync)(path).toString()),
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { tonDeepLink, sleep } from './utils';
2
2
  export { NetworkProvider } from './network/NetworkProvider';
3
3
  export { createNetworkProvider } from './network/createNetworkProvider';
4
- export { compile, CompileOpts } from './compile/compile';
4
+ export { compile, CompileOpts, SourceSnapshot, TolkCompileResult, FuncCompileResult, TactCompileResult, CompileResult } from './compile/compile';
5
5
  export { CompilerConfig, HookParams } from './compile/CompilerConfig';
6
6
  export { UIProvider } from './ui/UIProvider';
7
7
  export { Config } from './config/Config';
@@ -11,7 +11,6 @@ export declare const argSpec: {
11
11
  '--custom-key': StringConstructor;
12
12
  '--tonconnect': BooleanConstructor;
13
13
  '--deeplink': BooleanConstructor;
14
- '--tonhub': BooleanConstructor;
15
14
  '--mnemonic': BooleanConstructor;
16
15
  '--tonscan': BooleanConstructor;
17
16
  '--tonviewer': BooleanConstructor;
@@ -19,7 +19,6 @@ exports.createNetworkProvider = exports.argSpec = void 0;
19
19
  const utils_1 = require("../utils");
20
20
  const DeeplinkProvider_1 = require("./send/DeeplinkProvider");
21
21
  const TonConnectProvider_1 = require("./send/TonConnectProvider");
22
- const TonHubProvider_1 = require("./send/TonHubProvider");
23
22
  const core_1 = require("@ton/core");
24
23
  const ton_1 = require("@ton/ton");
25
24
  const FSStorage_1 = require("./storage/FSStorage");
@@ -39,7 +38,6 @@ exports.argSpec = {
39
38
  '--custom-key': String,
40
39
  '--tonconnect': Boolean,
41
40
  '--deeplink': Boolean,
42
- '--tonhub': Boolean,
43
41
  '--mnemonic': Boolean,
44
42
  '--tonscan': Boolean,
45
43
  '--tonviewer': Boolean,
@@ -140,7 +138,7 @@ class NetworkProviderImpl {
140
138
  return (await __classPrivateFieldGet(this, _NetworkProviderImpl_tc, "f").getContractState(address)).state === 'active';
141
139
  }
142
140
  }
143
- async waitForDeploy(address, attempts = 10, sleepDuration = 2000) {
141
+ async waitForDeploy(address, attempts = 20, sleepDuration = 2000) {
144
142
  if (attempts <= 0) {
145
143
  throw new Error('Attempt number must be positive');
146
144
  }
@@ -243,7 +241,6 @@ class NetworkProviderBuilder {
243
241
  let deployUsing = (0, utils_1.oneOrZeroOf)({
244
242
  tonconnect: this.args['--tonconnect'],
245
243
  deeplink: this.args['--deeplink'],
246
- tonhub: this.args['--tonhub'],
247
244
  mnemonic: this.args['--mnemonic'],
248
245
  });
249
246
  if (!deployUsing) {
@@ -256,10 +253,6 @@ class NetworkProviderBuilder {
256
253
  name: 'Create a ton:// deep link',
257
254
  value: 'deeplink',
258
255
  },
259
- {
260
- name: 'Tonhub wallet',
261
- value: 'tonhub',
262
- },
263
256
  {
264
257
  name: 'Mnemonic',
265
258
  value: 'mnemonic',
@@ -277,11 +270,6 @@ class NetworkProviderBuilder {
277
270
  throw new Error('Tonkeeper cannot work with custom network.');
278
271
  provider = new TonConnectProvider_1.TonConnectProvider(new FSStorage_1.FSStorage(storagePath), this.ui);
279
272
  break;
280
- case 'tonhub':
281
- if (network === 'custom')
282
- throw new Error('TonHub cannot work with custom network.');
283
- provider = new TonHubProvider_1.TonHubProvider(network, new FSStorage_1.FSStorage(storagePath), this.ui);
284
- break;
285
273
  case 'mnemonic':
286
274
  provider = await createMnemonicProvider(client, this.ui);
287
275
  break;
@@ -355,29 +343,30 @@ class NetworkProviderBuilder {
355
343
  }
356
344
  }
357
345
  else {
358
- tc = new ton_1.TonClient({
359
- endpoint: network === 'mainnet' ? 'https://toncenter.com/api/v2/jsonRPC' : 'https://testnet.toncenter.com/api/v2/jsonRPC',
360
- httpAdapter: async (config) => {
361
- let r;
362
- let delay = INITIAL_DELAY;
363
- let attempts = 0;
364
- while (true) {
365
- r = await (0, axios_1.default)({
366
- ...config,
367
- adapter: undefined,
368
- validateStatus: (status) => (status >= 200 && status < 300) || status === 429,
369
- });
370
- if (r.status !== 429) {
371
- return r;
372
- }
373
- await (0, utils_1.sleep)(delay);
374
- delay *= 2;
375
- attempts++;
376
- if (attempts >= MAX_ATTEMPTS) {
377
- throw new Error('Max attempts reached');
378
- }
346
+ const httpAdapter = async (config) => {
347
+ let r;
348
+ let delay = INITIAL_DELAY;
349
+ let attempts = 0;
350
+ while (true) {
351
+ r = await (0, axios_1.default)({
352
+ ...config,
353
+ adapter: undefined,
354
+ validateStatus: (status) => (status >= 200 && status < 300) || status === 429,
355
+ });
356
+ if (r.status !== 429) {
357
+ return r;
358
+ }
359
+ await (0, utils_1.sleep)(delay);
360
+ delay *= 2;
361
+ attempts++;
362
+ if (attempts >= MAX_ATTEMPTS) {
363
+ throw new Error('Max attempts reached');
379
364
  }
380
365
  }
366
+ };
367
+ tc = new ton_1.TonClient({
368
+ endpoint: network === 'mainnet' ? 'https://toncenter.com/api/v2/jsonRPC' : 'https://testnet.toncenter.com/api/v2/jsonRPC',
369
+ httpAdapter,
381
370
  });
382
371
  }
383
372
  const sendProvider = await this.chooseSendProvider(network, tc);
@@ -3,7 +3,7 @@ import { TonClient, TonClient4 } from '@ton/ton';
3
3
  import { Address, Cell, StateInit } from '@ton/core';
4
4
  import { SendProvider } from './SendProvider';
5
5
  import { UIProvider } from '../../ui/UIProvider';
6
- export type WalletVersion = 'v1r1' | 'v1r2' | 'v1r3' | 'v2r1' | 'v2r2' | 'v3r1' | 'v3r2' | 'v4';
6
+ export type WalletVersion = 'v1r1' | 'v1r2' | 'v1r3' | 'v2r1' | 'v2r2' | 'v3r1' | 'v3r2' | 'v4' | 'v5r1';
7
7
  export declare class MnemonicProvider implements SendProvider {
8
8
  #private;
9
9
  constructor(params: {
@@ -25,6 +25,7 @@ const wallets = {
25
25
  v3r1: ton_1.WalletContractV3R1,
26
26
  v3r2: ton_1.WalletContractV3R2,
27
27
  v4: ton_1.WalletContractV4,
28
+ v5r1: ton_1.WalletContractV5R1,
28
29
  };
29
30
  class MnemonicProvider {
30
31
  constructor(params) {
@@ -69,6 +70,7 @@ class MnemonicProvider {
69
70
  },
70
71
  },
71
72
  ],
73
+ sendMode: core_1.SendMode.PAY_GAS_SEPARATELY,
72
74
  });
73
75
  __classPrivateFieldGet(this, _MnemonicProvider_ui, "f").write('Sent transaction');
74
76
  }