create-ton 0.0.3
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/dist/cli.d.ts +2 -0
- package/dist/cli.js +80 -0
- package/dist/template/.prettierrc +7 -0
- package/dist/template/LICENSE +21 -0
- package/dist/template/README.md +82 -0
- package/dist/template/jest.config.js +4 -0
- package/dist/template/package.json +23 -0
- package/dist/template/tsconfig.json +12 -0
- package/dist/template/variants/counter/contracts/counter.fc +71 -0
- package/dist/template/variants/counter/contracts/imports/stdlib.fc +624 -0
- package/dist/template/variants/counter/scripts/deployCounter.ts +19 -0
- package/dist/template/variants/counter/tests/Counter.spec.ts +93 -0
- package/dist/template/variants/counter/wrappers/Counter.compile.ts +5 -0
- package/dist/template/variants/counter/wrappers/Counter.ts +66 -0
- package/dist/template/variants/empty/contracts/imports/stdlib.fc +624 -0
- package/dist/template/variants/empty/contracts/my_contract.fc +5 -0
- package/dist/template/variants/empty/scripts/deployMyContract.ts +13 -0
- package/dist/template/variants/empty/tests/MyContract.spec.ts +29 -0
- package/dist/template/variants/empty/wrappers/MyContract.compile.ts +5 -0
- package/dist/template/variants/empty/wrappers/MyContract.ts +36 -0
- package/package.json +31 -0
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
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
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const child_process_1 = require("child_process");
|
|
10
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
11
|
+
const PACKAGE_JSON = 'package.json';
|
|
12
|
+
async function main() {
|
|
13
|
+
const { name, variant } = await inquirer_1.default.prompt([
|
|
14
|
+
{
|
|
15
|
+
name: 'name',
|
|
16
|
+
message: 'Project name',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'variant',
|
|
20
|
+
message: 'Choose the project template',
|
|
21
|
+
type: 'list',
|
|
22
|
+
choices: [
|
|
23
|
+
{
|
|
24
|
+
name: 'An empty contract',
|
|
25
|
+
value: 'empty',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: 'A simple counter contract',
|
|
29
|
+
value: 'counter',
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
]);
|
|
34
|
+
if (name.length === 0)
|
|
35
|
+
throw new Error('Cannot initialize a project with an empty name');
|
|
36
|
+
await fs_extra_1.default.mkdir(name);
|
|
37
|
+
const steps = 2;
|
|
38
|
+
console.log(`[1/${steps}] Copying files...`);
|
|
39
|
+
const basePath = path_1.default.join(__dirname, 'template');
|
|
40
|
+
for (const file of await fs_extra_1.default.readdir(basePath)) {
|
|
41
|
+
if (file === PACKAGE_JSON || file === 'variants')
|
|
42
|
+
continue;
|
|
43
|
+
await fs_extra_1.default.copy(path_1.default.join(basePath, file), path_1.default.join(name, file));
|
|
44
|
+
}
|
|
45
|
+
const variantPath = path_1.default.join(basePath, 'variants', variant);
|
|
46
|
+
for (const file of await fs_extra_1.default.readdir(variantPath)) {
|
|
47
|
+
await fs_extra_1.default.copy(path_1.default.join(variantPath, file), path_1.default.join(name, file));
|
|
48
|
+
}
|
|
49
|
+
await fs_extra_1.default.writeFile(path_1.default.join(name, '.gitignore'), `node_modules
|
|
50
|
+
temp
|
|
51
|
+
build`);
|
|
52
|
+
await fs_extra_1.default.writeFile(path_1.default.join(name, PACKAGE_JSON), (await fs_extra_1.default.readFile(path_1.default.join(basePath, PACKAGE_JSON))).toString().replace('{{name}}', name));
|
|
53
|
+
console.log(`[2/${steps}] Installing dependencies...`);
|
|
54
|
+
(0, child_process_1.execSync)('npm i', {
|
|
55
|
+
stdio: 'inherit',
|
|
56
|
+
cwd: name,
|
|
57
|
+
});
|
|
58
|
+
(0, child_process_1.execSync)('git init', {
|
|
59
|
+
stdio: 'inherit',
|
|
60
|
+
cwd: name,
|
|
61
|
+
});
|
|
62
|
+
console.log('\nInitialized git repository.\n');
|
|
63
|
+
console.log(`Success!
|
|
64
|
+
Now you can run the following to run the default tests:
|
|
65
|
+
cd ${name}
|
|
66
|
+
npm run test
|
|
67
|
+
|
|
68
|
+
You can also run the following commands in your project's directory:
|
|
69
|
+
|
|
70
|
+
npx blueprint create MyContract
|
|
71
|
+
creates all the necessary files for a new contract
|
|
72
|
+
|
|
73
|
+
npx blueprint build
|
|
74
|
+
asks you to choose a contract and builds it
|
|
75
|
+
|
|
76
|
+
npx blueprint run
|
|
77
|
+
asks you to choose a script and runs it
|
|
78
|
+
`);
|
|
79
|
+
}
|
|
80
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Tontech
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# TON project template (RFC)
|
|
2
|
+
|
|
3
|
+
Starter template for a new TON project - FunC contracts, unit tests, compilation and deployment scripts.
|
|
4
|
+
|
|
5
|
+
> This repo is a work in progress and is subject to change
|
|
6
|
+
|
|
7
|
+
## Layout
|
|
8
|
+
|
|
9
|
+
- `contracts` - contains the source code of all the smart contracts of the project and their dependencies.
|
|
10
|
+
- `wrappers` - contains the wrapper classes (implementing `Contract` from ton-core) for the contracts, including any [de]serialization primitives and compilation functions.
|
|
11
|
+
- `tests` - tests for the contracts. Would typically use the wrappers.
|
|
12
|
+
- `scripts` - contains scripts used by the project, mainly the deployment scripts.
|
|
13
|
+
|
|
14
|
+
We ask the community to provide any comments on this layout, the wanted/required changes, or even suggestions for entirely different project structures and/or tool concepts.
|
|
15
|
+
|
|
16
|
+
PRs are welcome!
|
|
17
|
+
|
|
18
|
+
## Repo contents / tech stack
|
|
19
|
+
1. Compiling FunC - [https://github.com/ton-community/func-js](https://github.com/ton-community/func-js)
|
|
20
|
+
2. Testing TON smart contracts - [https://github.com/ton-community/sandbox/](https://github.com/ton-community/sandbox/)
|
|
21
|
+
3. Deployment of contracts is supported with [TON Connect 2](https://github.com/ton-connect/), [Tonhub wallet](https://tonhub.com/) or via a direct `ton://` deeplink
|
|
22
|
+
|
|
23
|
+
## How to use
|
|
24
|
+
* Clone this repo
|
|
25
|
+
* Run `yarn install`
|
|
26
|
+
|
|
27
|
+
### Building a contract
|
|
28
|
+
1. Interactively
|
|
29
|
+
1. Run `yarn blueprint build`
|
|
30
|
+
2. Choose the contract you'd like to build
|
|
31
|
+
1. Non-interactively
|
|
32
|
+
1. Run `yarn blueprint build <CONTRACT>`
|
|
33
|
+
2. example: `yarn blueprint build pingpong`
|
|
34
|
+
|
|
35
|
+
### Deploying a contract
|
|
36
|
+
1. Interactively
|
|
37
|
+
1. Run `yarn blueprint run`
|
|
38
|
+
2. Choose the contract you'd like to deploy
|
|
39
|
+
3. Choose whether you're deploying on mainnet or testnet
|
|
40
|
+
4. Choose how to deploy:
|
|
41
|
+
1. With a TON Connect compatible wallet
|
|
42
|
+
2. A `ton://` deep link / QR code
|
|
43
|
+
3. Tonhub wallet
|
|
44
|
+
5. Deploy the contract
|
|
45
|
+
2. Non-interactively
|
|
46
|
+
1. Run `yarn blueprint run <CONTRACT> --<NETWORK> --<DEPLOY_METHOD>`
|
|
47
|
+
2. example: `yarn blueprint run pingpong --mainnet --tonconnect`
|
|
48
|
+
|
|
49
|
+
### Testing
|
|
50
|
+
1. Run `yarn test`
|
|
51
|
+
|
|
52
|
+
## Adding your own contract
|
|
53
|
+
1. Run `yarn blueprint create <CONTRACT>`
|
|
54
|
+
2. example: `yarn blueprint create MyContract`
|
|
55
|
+
|
|
56
|
+
* Write code
|
|
57
|
+
* FunC contracts are located in `contracts/*.fc`
|
|
58
|
+
* Standalone root contracts are located in `contracts/*.fc`
|
|
59
|
+
* Shared imports (when breaking code to multiple files) are in `contracts/imports/*.fc`
|
|
60
|
+
* Tests in TypeScript are located in `test/*.spec.ts`
|
|
61
|
+
* Wrapper classes for interacting with the contract are located in `wrappers/*.ts`
|
|
62
|
+
* Any scripts (including deployers) are located in `scripts/*.ts`
|
|
63
|
+
|
|
64
|
+
* Build
|
|
65
|
+
* Builder configs are located in `wrappers/*.compile.ts`
|
|
66
|
+
* In the root repo dir, run in terminal `yarn blueprint build`
|
|
67
|
+
* Compilation errors will appear on screen, if applicable
|
|
68
|
+
* Resulting build artifacts include:
|
|
69
|
+
* `build/*.compiled.json` - the binary code cell of the compiled contract (for deployment). Saved in a hex format within a json file to support webapp imports
|
|
70
|
+
|
|
71
|
+
* Test
|
|
72
|
+
* In the root repo dir, run in terminal `yarn test`
|
|
73
|
+
* Don't forget to build (or rebuild) before running tests
|
|
74
|
+
* Tests are running inside Node.js by running TVM in web-assembly using [sandbox](https://github.com/ton-community/sandbox)
|
|
75
|
+
|
|
76
|
+
* Deploy
|
|
77
|
+
* Run `yarn blueprint run <deployscript>`
|
|
78
|
+
* Contracts will be rebuilt on each execution
|
|
79
|
+
* Follow the on-screen instructions of the deploy script
|
|
80
|
+
|
|
81
|
+
# License
|
|
82
|
+
MIT
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{name}}",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "jest"
|
|
7
|
+
},
|
|
8
|
+
"devDependencies": {
|
|
9
|
+
"@ton-community/blueprint": "^0.0.2",
|
|
10
|
+
"@ton-community/sandbox": "^0.2.0",
|
|
11
|
+
"@ton-community/test-utils": "^0.0.2",
|
|
12
|
+
"@types/jest": "^29.2.6",
|
|
13
|
+
"@types/node": "^18.11.18",
|
|
14
|
+
"jest": "^29.3.1",
|
|
15
|
+
"prettier": "^2.8.3",
|
|
16
|
+
"ton": "^13.3.0",
|
|
17
|
+
"ton-core": "^0.46.0",
|
|
18
|
+
"ton-crypto": "^3.2.0",
|
|
19
|
+
"ts-jest": "^29.0.5",
|
|
20
|
+
"ts-node": "^10.9.1",
|
|
21
|
+
"typescript": "^4.9.4"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#include "imports/stdlib.fc";
|
|
2
|
+
|
|
3
|
+
const op::increase = "op::increase"c; ;; create an opcode from string using the "c" prefix, this results in 0x7e8764ef opcode in this case
|
|
4
|
+
|
|
5
|
+
;; storage variables
|
|
6
|
+
|
|
7
|
+
;; id is required to be able to create different instances of counters
|
|
8
|
+
;; since addresses in TON depend on the initial state of the contract
|
|
9
|
+
global int ctx_id;
|
|
10
|
+
global int ctx_counter;
|
|
11
|
+
|
|
12
|
+
;; load_data populates storage variables using stored data
|
|
13
|
+
() load_data() impure {
|
|
14
|
+
var ds = get_data().begin_parse();
|
|
15
|
+
|
|
16
|
+
ctx_id = ds~load_uint(32);
|
|
17
|
+
ctx_counter = ds~load_uint(32);
|
|
18
|
+
|
|
19
|
+
ds.end_parse();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
;; save_data stores storage variables as a cell into persistent storage
|
|
23
|
+
() save_data() impure {
|
|
24
|
+
set_data(
|
|
25
|
+
begin_cell()
|
|
26
|
+
.store_uint(ctx_id, 32)
|
|
27
|
+
.store_uint(ctx_counter, 32)
|
|
28
|
+
.end_cell()
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
;; recv_internal is the main function of the contract and is called when it receives a message from other contract's
|
|
33
|
+
() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {
|
|
34
|
+
if (in_msg_body.slice_empty?()) { ;; ignore all empty messages
|
|
35
|
+
return ();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
slice cs = in_msg_full.begin_parse();
|
|
39
|
+
int flags = cs~load_uint(4);
|
|
40
|
+
if (flags & 1) { ;; ignore all bounced messages
|
|
41
|
+
return ();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
load_data(); ;; here we populate the storage variables
|
|
45
|
+
|
|
46
|
+
int op = in_msg_body~load_uint(32); ;; by convention, the first 32 bits of incoming message is the op
|
|
47
|
+
int query_id = in_msg_body~load_uint(64); ;; also by convention, the next 64 bits contain the "query id", although this is not always the case
|
|
48
|
+
|
|
49
|
+
if (op == op::increase) {
|
|
50
|
+
int increase_by = in_msg_body~load_uint(32);
|
|
51
|
+
ctx_counter += increase_by;
|
|
52
|
+
save_data();
|
|
53
|
+
return ();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
throw(0xffff); ;; if the message contains an op that is not known to this contract, we throw
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
;; get methods are a means to conveniently read contract data using, for example, HTTP APIs
|
|
60
|
+
;; they are marked with method_id
|
|
61
|
+
;; note that unlike in many other smart contract VMs, get methods cannot be called by other contracts
|
|
62
|
+
|
|
63
|
+
int get_counter() method_id {
|
|
64
|
+
load_data();
|
|
65
|
+
return ctx_counter;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
int get_id() method_id {
|
|
69
|
+
load_data();
|
|
70
|
+
return ctx_id;
|
|
71
|
+
}
|