@ton/blueprint 0.10.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 +146 -0
- package/README.md +114 -0
- package/dist/cli/build.d.ts +4 -0
- package/dist/cli/build.js +68 -0
- package/dist/cli/cli.d.ts +7 -0
- package/dist/cli/cli.js +106 -0
- package/dist/cli/create.d.ts +6 -0
- package/dist/cli/create.js +96 -0
- package/dist/cli/help.d.ts +2 -0
- package/dist/cli/help.js +55 -0
- package/dist/cli/run.d.ts +2 -0
- package/dist/cli/run.js +18 -0
- package/dist/cli/test.d.ts +2 -0
- package/dist/cli/test.js +9 -0
- package/dist/compile/CompilerConfig.d.ts +21 -0
- package/dist/compile/CompilerConfig.js +2 -0
- package/dist/compile/OverwritableVirtualFileSystem.d.ts +10 -0
- package/dist/compile/OverwritableVirtualFileSystem.js +24 -0
- package/dist/compile/compile.d.ts +14 -0
- package/dist/compile/compile.js +115 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +10 -0
- package/dist/network/NetworkProvider.d.ts +22 -0
- package/dist/network/NetworkProvider.js +2 -0
- package/dist/network/createNetworkProvider.d.ts +3 -0
- package/dist/network/createNetworkProvider.js +282 -0
- package/dist/network/send/DeeplinkProvider.d.ts +10 -0
- package/dist/network/send/DeeplinkProvider.js +44 -0
- package/dist/network/send/MnemonicProvider.d.ts +19 -0
- package/dist/network/send/MnemonicProvider.js +80 -0
- package/dist/network/send/SendProvider.d.ts +6 -0
- package/dist/network/send/SendProvider.js +2 -0
- package/dist/network/send/TonConnectProvider.d.ts +12 -0
- package/dist/network/send/TonConnectProvider.js +108 -0
- package/dist/network/send/TonHubProvider.d.ts +16 -0
- package/dist/network/send/TonHubProvider.js +110 -0
- package/dist/network/storage/FSStorage.d.ts +8 -0
- package/dist/network/storage/FSStorage.js +53 -0
- package/dist/network/storage/Storage.d.ts +18 -0
- package/dist/network/storage/Storage.js +2 -0
- package/dist/paths.d.ts +12 -0
- package/dist/paths.js +19 -0
- package/dist/template.d.ts +4 -0
- package/dist/template.js +15 -0
- package/dist/templates/func/common/wrappers/compile.ts.template +7 -0
- package/dist/templates/func/counter/contracts/contract.fc.template +72 -0
- package/dist/templates/func/counter/scripts/deploy.ts.template +22 -0
- package/dist/templates/func/counter/scripts/increment.ts.template +38 -0
- package/dist/templates/func/counter/tests/spec.ts.template +81 -0
- package/dist/templates/func/counter/wrappers/wrapper.ts.template +67 -0
- package/dist/templates/func/empty/contracts/contract.fc.template +6 -0
- package/dist/templates/func/empty/scripts/deploy.ts.template +14 -0
- package/dist/templates/func/empty/tests/spec.ts.template +39 -0
- package/dist/templates/func/empty/wrappers/wrapper.ts.template +30 -0
- package/dist/templates/tact/common/wrappers/compile.ts.template +7 -0
- package/dist/templates/tact/common/wrappers/wrapper.ts.template +2 -0
- package/dist/templates/tact/counter/contracts/contract.tact.template +29 -0
- package/dist/templates/tact/counter/scripts/deploy.ts.template +23 -0
- package/dist/templates/tact/counter/scripts/increment.ts.template +45 -0
- package/dist/templates/tact/counter/tests/spec.ts.template +82 -0
- package/dist/templates/tact/empty/contracts/contract.tact.template +8 -0
- package/dist/templates/tact/empty/scripts/deploy.ts.template +23 -0
- package/dist/templates/tact/empty/tests/spec.ts.template +41 -0
- package/dist/ui/InquirerUIProvider.d.ts +12 -0
- package/dist/ui/InquirerUIProvider.js +70 -0
- package/dist/ui/UIProvider.d.ts +8 -0
- package/dist/ui/UIProvider.js +2 -0
- package/dist/utils.d.ts +39 -0
- package/dist/utils.js +122 -0
- package/package.json +51 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Address, Cell, StateInit } from 'ton-core';
|
|
2
|
+
import { SendProvider } from './SendProvider';
|
|
3
|
+
import { Storage } from '../storage/Storage';
|
|
4
|
+
import { UIProvider } from '../../ui/UIProvider';
|
|
5
|
+
export declare class TonConnectProvider implements SendProvider {
|
|
6
|
+
#private;
|
|
7
|
+
constructor(storage: Storage, ui: UIProvider);
|
|
8
|
+
connect(): Promise<void>;
|
|
9
|
+
address(): Address | undefined;
|
|
10
|
+
private connectWallet;
|
|
11
|
+
sendTransaction(address: Address, amount: bigint, payload?: Cell, stateInit?: StateInit): Promise<import("@tonconnect/sdk").SendTransactionResponse>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
+
};
|
|
8
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
var _TonConnectStorage_inner, _TonConnectProvider_connector, _TonConnectProvider_ui;
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.TonConnectProvider = void 0;
|
|
19
|
+
const qrcode_terminal_1 = __importDefault(require("qrcode-terminal"));
|
|
20
|
+
const sdk_1 = __importDefault(require("@tonconnect/sdk"));
|
|
21
|
+
const ton_core_1 = require("ton-core");
|
|
22
|
+
class TonConnectStorage {
|
|
23
|
+
constructor(inner) {
|
|
24
|
+
_TonConnectStorage_inner.set(this, void 0);
|
|
25
|
+
__classPrivateFieldSet(this, _TonConnectStorage_inner, inner, "f");
|
|
26
|
+
}
|
|
27
|
+
async setItem(key, value) {
|
|
28
|
+
return await __classPrivateFieldGet(this, _TonConnectStorage_inner, "f").setItem(key, value);
|
|
29
|
+
}
|
|
30
|
+
async getItem(key) {
|
|
31
|
+
return await __classPrivateFieldGet(this, _TonConnectStorage_inner, "f").getItem(key);
|
|
32
|
+
}
|
|
33
|
+
async removeItem(key) {
|
|
34
|
+
return await __classPrivateFieldGet(this, _TonConnectStorage_inner, "f").removeItem(key);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
_TonConnectStorage_inner = new WeakMap();
|
|
38
|
+
function isRemote(walletInfo) {
|
|
39
|
+
return 'universalLink' in walletInfo && 'bridgeUrl' in walletInfo;
|
|
40
|
+
}
|
|
41
|
+
class TonConnectProvider {
|
|
42
|
+
constructor(storage, ui) {
|
|
43
|
+
_TonConnectProvider_connector.set(this, void 0);
|
|
44
|
+
_TonConnectProvider_ui.set(this, void 0);
|
|
45
|
+
__classPrivateFieldSet(this, _TonConnectProvider_connector, new sdk_1.default({
|
|
46
|
+
storage: new TonConnectStorage(storage),
|
|
47
|
+
manifestUrl: 'https://raw.githubusercontent.com/ton-defi-org/tonconnect-manifest-temp/main/tonconnect-manifest.json',
|
|
48
|
+
}), "f");
|
|
49
|
+
__classPrivateFieldSet(this, _TonConnectProvider_ui, ui, "f");
|
|
50
|
+
}
|
|
51
|
+
async connect() {
|
|
52
|
+
await this.connectWallet();
|
|
53
|
+
__classPrivateFieldGet(this, _TonConnectProvider_ui, "f").write(`Connected to wallet at address: ${ton_core_1.Address.parse(__classPrivateFieldGet(this, _TonConnectProvider_connector, "f").wallet.account.address).toString()}\n`);
|
|
54
|
+
}
|
|
55
|
+
address() {
|
|
56
|
+
if (!__classPrivateFieldGet(this, _TonConnectProvider_connector, "f").wallet)
|
|
57
|
+
return undefined;
|
|
58
|
+
return ton_core_1.Address.parse(__classPrivateFieldGet(this, _TonConnectProvider_connector, "f").wallet.account.address);
|
|
59
|
+
}
|
|
60
|
+
async connectWallet() {
|
|
61
|
+
const wallets = (await __classPrivateFieldGet(this, _TonConnectProvider_connector, "f").getWallets()).filter(isRemote);
|
|
62
|
+
await __classPrivateFieldGet(this, _TonConnectProvider_connector, "f").restoreConnection();
|
|
63
|
+
if (__classPrivateFieldGet(this, _TonConnectProvider_connector, "f").wallet) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const wallet = await __classPrivateFieldGet(this, _TonConnectProvider_ui, "f").choose('Choose your wallet', wallets, (w) => w.name);
|
|
67
|
+
__classPrivateFieldGet(this, _TonConnectProvider_ui, "f").setActionPrompt('Connecting to wallet...');
|
|
68
|
+
const url = __classPrivateFieldGet(this, _TonConnectProvider_connector, "f").connect({
|
|
69
|
+
universalLink: wallet.universalLink,
|
|
70
|
+
bridgeUrl: wallet.bridgeUrl,
|
|
71
|
+
});
|
|
72
|
+
__classPrivateFieldGet(this, _TonConnectProvider_ui, "f").write('\n');
|
|
73
|
+
qrcode_terminal_1.default.generate(url, { small: true }, (qr) => __classPrivateFieldGet(this, _TonConnectProvider_ui, "f").write(qr));
|
|
74
|
+
__classPrivateFieldGet(this, _TonConnectProvider_ui, "f").write('\n' + url + '\n\n');
|
|
75
|
+
__classPrivateFieldGet(this, _TonConnectProvider_ui, "f").setActionPrompt('Scan the QR code in your wallet or open the link...');
|
|
76
|
+
return new Promise((resolve, reject) => {
|
|
77
|
+
__classPrivateFieldGet(this, _TonConnectProvider_connector, "f").onStatusChange((w) => {
|
|
78
|
+
if (w) {
|
|
79
|
+
resolve();
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
reject('Wallet is not connected');
|
|
83
|
+
}
|
|
84
|
+
}, reject);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
async sendTransaction(address, amount, payload, stateInit) {
|
|
88
|
+
__classPrivateFieldGet(this, _TonConnectProvider_ui, "f").setActionPrompt('Sending transaction. Approve in your wallet...');
|
|
89
|
+
const result = await __classPrivateFieldGet(this, _TonConnectProvider_connector, "f").sendTransaction({
|
|
90
|
+
validUntil: Date.now() + 5 * 60 * 1000,
|
|
91
|
+
messages: [
|
|
92
|
+
{
|
|
93
|
+
address: address.toString(),
|
|
94
|
+
amount: amount.toString(),
|
|
95
|
+
payload: payload?.toBoc().toString('base64'),
|
|
96
|
+
stateInit: stateInit
|
|
97
|
+
? (0, ton_core_1.beginCell)().storeWritable((0, ton_core_1.storeStateInit)(stateInit)).endCell().toBoc().toString('base64')
|
|
98
|
+
: undefined,
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
});
|
|
102
|
+
__classPrivateFieldGet(this, _TonConnectProvider_ui, "f").clearActionPrompt();
|
|
103
|
+
__classPrivateFieldGet(this, _TonConnectProvider_ui, "f").write('Sent transaction');
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exports.TonConnectProvider = TonConnectProvider;
|
|
108
|
+
_TonConnectProvider_connector = new WeakMap(), _TonConnectProvider_ui = new WeakMap();
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Address, Cell, StateInit } from 'ton-core';
|
|
2
|
+
import { SendProvider } from './SendProvider';
|
|
3
|
+
import { Storage } from '../storage/Storage';
|
|
4
|
+
import { UIProvider } from '../../ui/UIProvider';
|
|
5
|
+
export declare class TonHubProvider implements SendProvider {
|
|
6
|
+
#private;
|
|
7
|
+
constructor(network: 'mainnet' | 'testnet', storage: Storage, ui: UIProvider);
|
|
8
|
+
private getExistingSession;
|
|
9
|
+
private getSession;
|
|
10
|
+
connect(): Promise<void>;
|
|
11
|
+
address(): Address | undefined;
|
|
12
|
+
sendTransaction(address: Address, amount: bigint, payload?: Cell, stateInit?: StateInit): Promise<{
|
|
13
|
+
type: "success";
|
|
14
|
+
response: string;
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
+
};
|
|
8
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
var _TonHubProvider_connector, _TonHubProvider_storage, _TonHubProvider_ui, _TonHubProvider_session;
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.TonHubProvider = void 0;
|
|
19
|
+
const ton_core_1 = require("ton-core");
|
|
20
|
+
const ton_x_1 = require("ton-x");
|
|
21
|
+
const qrcode_terminal_1 = __importDefault(require("qrcode-terminal"));
|
|
22
|
+
const KEY_NAME = 'tonhub_session';
|
|
23
|
+
class TonHubProvider {
|
|
24
|
+
constructor(network, storage, ui) {
|
|
25
|
+
_TonHubProvider_connector.set(this, void 0);
|
|
26
|
+
_TonHubProvider_storage.set(this, void 0);
|
|
27
|
+
_TonHubProvider_ui.set(this, void 0);
|
|
28
|
+
_TonHubProvider_session.set(this, void 0);
|
|
29
|
+
__classPrivateFieldSet(this, _TonHubProvider_connector, new ton_x_1.TonhubConnector({
|
|
30
|
+
network,
|
|
31
|
+
}), "f");
|
|
32
|
+
__classPrivateFieldSet(this, _TonHubProvider_storage, storage, "f");
|
|
33
|
+
__classPrivateFieldSet(this, _TonHubProvider_ui, ui, "f");
|
|
34
|
+
}
|
|
35
|
+
async getExistingSession() {
|
|
36
|
+
const sessionString = await __classPrivateFieldGet(this, _TonHubProvider_storage, "f").getItem(KEY_NAME);
|
|
37
|
+
if (sessionString === null)
|
|
38
|
+
return undefined;
|
|
39
|
+
let session = JSON.parse(sessionString);
|
|
40
|
+
const state = await __classPrivateFieldGet(this, _TonHubProvider_connector, "f").getSessionState(session.id);
|
|
41
|
+
if (state.state === 'ready') {
|
|
42
|
+
session = {
|
|
43
|
+
...state,
|
|
44
|
+
id: session.id,
|
|
45
|
+
seed: session.seed,
|
|
46
|
+
};
|
|
47
|
+
await __classPrivateFieldGet(this, _TonHubProvider_storage, "f").setItem(KEY_NAME, JSON.stringify(session));
|
|
48
|
+
return session;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async getSession() {
|
|
52
|
+
const existing = await this.getExistingSession();
|
|
53
|
+
if (existing !== undefined)
|
|
54
|
+
return existing;
|
|
55
|
+
const createdSession = await __classPrivateFieldGet(this, _TonHubProvider_connector, "f").createNewSession({
|
|
56
|
+
name: 'TON template project',
|
|
57
|
+
url: 'https://example.com/',
|
|
58
|
+
});
|
|
59
|
+
__classPrivateFieldGet(this, _TonHubProvider_ui, "f").setActionPrompt('Connecting to wallet...\n');
|
|
60
|
+
__classPrivateFieldGet(this, _TonHubProvider_ui, "f").write('\n');
|
|
61
|
+
qrcode_terminal_1.default.generate(createdSession.link, { small: true }, (qr) => __classPrivateFieldGet(this, _TonHubProvider_ui, "f").write(qr));
|
|
62
|
+
__classPrivateFieldGet(this, _TonHubProvider_ui, "f").write('\n' + createdSession.link + '\n\n');
|
|
63
|
+
__classPrivateFieldGet(this, _TonHubProvider_ui, "f").setActionPrompt('Scan the QR code in your wallet or open the link...');
|
|
64
|
+
const state = await __classPrivateFieldGet(this, _TonHubProvider_connector, "f").awaitSessionReady(createdSession.id, 5 * 60 * 1000);
|
|
65
|
+
if (state.state === 'ready') {
|
|
66
|
+
const session = {
|
|
67
|
+
...state,
|
|
68
|
+
id: createdSession.id,
|
|
69
|
+
seed: createdSession.seed,
|
|
70
|
+
};
|
|
71
|
+
await __classPrivateFieldGet(this, _TonHubProvider_storage, "f").setItem(KEY_NAME, JSON.stringify(session));
|
|
72
|
+
return session;
|
|
73
|
+
}
|
|
74
|
+
throw new Error('Could not create new session');
|
|
75
|
+
}
|
|
76
|
+
async connect() {
|
|
77
|
+
__classPrivateFieldSet(this, _TonHubProvider_session, await this.getSession(), "f");
|
|
78
|
+
__classPrivateFieldGet(this, _TonHubProvider_ui, "f").write(`Connected to wallet at address: ${ton_core_1.Address.parse(__classPrivateFieldGet(this, _TonHubProvider_session, "f").wallet.address).toString()}\n`);
|
|
79
|
+
}
|
|
80
|
+
address() {
|
|
81
|
+
if (!__classPrivateFieldGet(this, _TonHubProvider_session, "f"))
|
|
82
|
+
return undefined;
|
|
83
|
+
return ton_core_1.Address.parse(__classPrivateFieldGet(this, _TonHubProvider_session, "f").wallet.address);
|
|
84
|
+
}
|
|
85
|
+
async sendTransaction(address, amount, payload, stateInit) {
|
|
86
|
+
if (!__classPrivateFieldGet(this, _TonHubProvider_session, "f"))
|
|
87
|
+
throw new Error('TonhubProvider is not connected');
|
|
88
|
+
const request = {
|
|
89
|
+
seed: __classPrivateFieldGet(this, _TonHubProvider_session, "f").seed,
|
|
90
|
+
appPublicKey: __classPrivateFieldGet(this, _TonHubProvider_session, "f").wallet.appPublicKey,
|
|
91
|
+
to: address.toString(),
|
|
92
|
+
value: amount.toString(),
|
|
93
|
+
timeout: 5 * 60 * 1000,
|
|
94
|
+
payload: payload ? payload.toBoc().toString('base64') : undefined,
|
|
95
|
+
stateInit: stateInit
|
|
96
|
+
? (0, ton_core_1.beginCell)().storeWritable((0, ton_core_1.storeStateInit)(stateInit)).endCell().toBoc().toString('base64')
|
|
97
|
+
: undefined,
|
|
98
|
+
};
|
|
99
|
+
__classPrivateFieldGet(this, _TonHubProvider_ui, "f").setActionPrompt('Sending transaction. Approve it in your wallet...');
|
|
100
|
+
const response = await __classPrivateFieldGet(this, _TonHubProvider_connector, "f").requestTransaction(request);
|
|
101
|
+
if (response.type !== 'success') {
|
|
102
|
+
throw new Error(`Tonhub transaction request was not successful (${response.type})`);
|
|
103
|
+
}
|
|
104
|
+
__classPrivateFieldGet(this, _TonHubProvider_ui, "f").clearActionPrompt();
|
|
105
|
+
__classPrivateFieldGet(this, _TonHubProvider_ui, "f").write('Sent transaction');
|
|
106
|
+
return response;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
exports.TonHubProvider = TonHubProvider;
|
|
110
|
+
_TonHubProvider_connector = new WeakMap(), _TonHubProvider_storage = new WeakMap(), _TonHubProvider_ui = new WeakMap(), _TonHubProvider_session = new WeakMap();
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Storage } from './Storage';
|
|
2
|
+
export declare class FSStorage implements Storage {
|
|
3
|
+
#private;
|
|
4
|
+
constructor(path: string);
|
|
5
|
+
setItem(key: string, value: string): Promise<void>;
|
|
6
|
+
getItem(key: string): Promise<string | null>;
|
|
7
|
+
removeItem(key: string): Promise<void>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
+
};
|
|
8
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
var _FSStorage_instances, _FSStorage_path, _FSStorage_readObject, _FSStorage_writeObject;
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.FSStorage = void 0;
|
|
19
|
+
const path_1 = __importDefault(require("path"));
|
|
20
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
21
|
+
class FSStorage {
|
|
22
|
+
constructor(path) {
|
|
23
|
+
_FSStorage_instances.add(this);
|
|
24
|
+
_FSStorage_path.set(this, void 0);
|
|
25
|
+
__classPrivateFieldSet(this, _FSStorage_path, path, "f");
|
|
26
|
+
}
|
|
27
|
+
async setItem(key, value) {
|
|
28
|
+
const obj = await __classPrivateFieldGet(this, _FSStorage_instances, "m", _FSStorage_readObject).call(this);
|
|
29
|
+
obj[key] = value;
|
|
30
|
+
await __classPrivateFieldGet(this, _FSStorage_instances, "m", _FSStorage_writeObject).call(this, obj);
|
|
31
|
+
}
|
|
32
|
+
async getItem(key) {
|
|
33
|
+
const obj = await __classPrivateFieldGet(this, _FSStorage_instances, "m", _FSStorage_readObject).call(this);
|
|
34
|
+
return obj[key] ?? null;
|
|
35
|
+
}
|
|
36
|
+
async removeItem(key) {
|
|
37
|
+
const obj = await __classPrivateFieldGet(this, _FSStorage_instances, "m", _FSStorage_readObject).call(this);
|
|
38
|
+
delete obj[key];
|
|
39
|
+
await __classPrivateFieldGet(this, _FSStorage_instances, "m", _FSStorage_writeObject).call(this, obj);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.FSStorage = FSStorage;
|
|
43
|
+
_FSStorage_path = new WeakMap(), _FSStorage_instances = new WeakSet(), _FSStorage_readObject = async function _FSStorage_readObject() {
|
|
44
|
+
try {
|
|
45
|
+
return JSON.parse((await promises_1.default.readFile(__classPrivateFieldGet(this, _FSStorage_path, "f"))).toString('utf-8'));
|
|
46
|
+
}
|
|
47
|
+
catch (e) {
|
|
48
|
+
return {};
|
|
49
|
+
}
|
|
50
|
+
}, _FSStorage_writeObject = async function _FSStorage_writeObject(obj) {
|
|
51
|
+
await promises_1.default.mkdir(path_1.default.dirname(__classPrivateFieldGet(this, _FSStorage_path, "f")), { recursive: true });
|
|
52
|
+
await promises_1.default.writeFile(__classPrivateFieldGet(this, _FSStorage_path, "f"), JSON.stringify(obj));
|
|
53
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface Storage {
|
|
2
|
+
/**
|
|
3
|
+
* Saves the `value` to the storage. Value can be accessed later by the `key`. Implementation may use backend as a storage due to the fact that the function returns a promise.
|
|
4
|
+
* @param key key to access to the value later.
|
|
5
|
+
* @param value value to save.
|
|
6
|
+
*/
|
|
7
|
+
setItem(key: string, value: string): Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Reads the `value` from the storage. Implementation may use backend as a storage due to the fact that the function returns a promise.
|
|
10
|
+
* @param key key to access the value.
|
|
11
|
+
*/
|
|
12
|
+
getItem(key: string): Promise<string | null>;
|
|
13
|
+
/**
|
|
14
|
+
* Removes the `value` from the storage. Implementation may use backend as a storage due to the fact that the function returns a promise.
|
|
15
|
+
* @param key key to access the value.
|
|
16
|
+
*/
|
|
17
|
+
removeItem(key: string): Promise<void>;
|
|
18
|
+
}
|
package/dist/paths.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const CONTRACTS = "contracts";
|
|
2
|
+
export declare const TESTS = "tests";
|
|
3
|
+
export declare const WRAPPERS = "wrappers";
|
|
4
|
+
export declare const SCRIPTS = "scripts";
|
|
5
|
+
export declare const TEMP = "temp";
|
|
6
|
+
export declare const BUILD = "build";
|
|
7
|
+
export declare const WRAPPERS_DIR: string;
|
|
8
|
+
export declare const SCRIPTS_DIR: string;
|
|
9
|
+
export declare const BUILD_DIR: string;
|
|
10
|
+
export declare const TEMP_DIR: string;
|
|
11
|
+
export declare const CONTRACTS_DIR: string;
|
|
12
|
+
export declare const TESTS_DIR: string;
|
package/dist/paths.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
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.TESTS_DIR = exports.CONTRACTS_DIR = exports.TEMP_DIR = exports.BUILD_DIR = exports.SCRIPTS_DIR = exports.WRAPPERS_DIR = exports.BUILD = exports.TEMP = exports.SCRIPTS = exports.WRAPPERS = exports.TESTS = exports.CONTRACTS = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
exports.CONTRACTS = 'contracts';
|
|
9
|
+
exports.TESTS = 'tests';
|
|
10
|
+
exports.WRAPPERS = 'wrappers';
|
|
11
|
+
exports.SCRIPTS = 'scripts';
|
|
12
|
+
exports.TEMP = 'temp';
|
|
13
|
+
exports.BUILD = 'build';
|
|
14
|
+
exports.WRAPPERS_DIR = path_1.default.join(process.cwd(), exports.WRAPPERS);
|
|
15
|
+
exports.SCRIPTS_DIR = path_1.default.join(process.cwd(), exports.SCRIPTS);
|
|
16
|
+
exports.BUILD_DIR = path_1.default.join(process.cwd(), exports.BUILD);
|
|
17
|
+
exports.TEMP_DIR = path_1.default.join(process.cwd(), exports.TEMP);
|
|
18
|
+
exports.CONTRACTS_DIR = path_1.default.join(process.cwd(), exports.CONTRACTS);
|
|
19
|
+
exports.TESTS_DIR = path_1.default.join(process.cwd(), exports.TESTS);
|
package/dist/template.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
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.executeTemplate = exports.TEMPLATES_DIR = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
exports.TEMPLATES_DIR = path_1.default.join(__dirname, 'templates');
|
|
9
|
+
function executeTemplate(contents, replaces) {
|
|
10
|
+
for (const k in replaces) {
|
|
11
|
+
contents = contents.replaceAll(`{{${k}}}`, replaces[k]);
|
|
12
|
+
}
|
|
13
|
+
return contents;
|
|
14
|
+
}
|
|
15
|
+
exports.executeTemplate = executeTemplate;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{{snakeName}}.fc
|
|
2
|
+
#include "imports/stdlib.fc";
|
|
3
|
+
|
|
4
|
+
const op::increase = "op::increase"c; ;; create an opcode from string using the "c" prefix, this results in 0x7e8764ef opcode in this case
|
|
5
|
+
|
|
6
|
+
;; storage variables
|
|
7
|
+
|
|
8
|
+
;; id is required to be able to create different instances of counters
|
|
9
|
+
;; since addresses in TON depend on the initial state of the contract
|
|
10
|
+
global int ctx_id;
|
|
11
|
+
global int ctx_counter;
|
|
12
|
+
|
|
13
|
+
;; load_data populates storage variables using stored data
|
|
14
|
+
() load_data() impure {
|
|
15
|
+
var ds = get_data().begin_parse();
|
|
16
|
+
|
|
17
|
+
ctx_id = ds~load_uint(32);
|
|
18
|
+
ctx_counter = ds~load_uint(32);
|
|
19
|
+
|
|
20
|
+
ds.end_parse();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
;; save_data stores storage variables as a cell into persistent storage
|
|
24
|
+
() save_data() impure {
|
|
25
|
+
set_data(
|
|
26
|
+
begin_cell()
|
|
27
|
+
.store_uint(ctx_id, 32)
|
|
28
|
+
.store_uint(ctx_counter, 32)
|
|
29
|
+
.end_cell()
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
;; recv_internal is the main function of the contract and is called when it receives a message from other contracts
|
|
34
|
+
() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {
|
|
35
|
+
if (in_msg_body.slice_empty?()) { ;; ignore all empty messages
|
|
36
|
+
return ();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
slice cs = in_msg_full.begin_parse();
|
|
40
|
+
int flags = cs~load_uint(4);
|
|
41
|
+
if (flags & 1) { ;; ignore all bounced messages
|
|
42
|
+
return ();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
load_data(); ;; here we populate the storage variables
|
|
46
|
+
|
|
47
|
+
int op = in_msg_body~load_uint(32); ;; by convention, the first 32 bits of incoming message is the op
|
|
48
|
+
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
|
|
49
|
+
|
|
50
|
+
if (op == op::increase) {
|
|
51
|
+
int increase_by = in_msg_body~load_uint(32);
|
|
52
|
+
ctx_counter += increase_by;
|
|
53
|
+
save_data();
|
|
54
|
+
return ();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
throw(0xffff); ;; if the message contains an op that is not known to this contract, we throw
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
;; get methods are a means to conveniently read contract data using, for example, HTTP APIs
|
|
61
|
+
;; they are marked with method_id
|
|
62
|
+
;; note that unlike in many other smart contract VMs, get methods cannot be called by other contracts
|
|
63
|
+
|
|
64
|
+
int get_counter() method_id {
|
|
65
|
+
load_data();
|
|
66
|
+
return ctx_counter;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
int get_id() method_id {
|
|
70
|
+
load_data();
|
|
71
|
+
return ctx_id;
|
|
72
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
deploy{{name}}.ts
|
|
2
|
+
import { toNano } from 'ton-core';
|
|
3
|
+
import { {{name}} } from '../wrappers/{{name}}';
|
|
4
|
+
import { compile, NetworkProvider } from '@ton-community/blueprint';
|
|
5
|
+
|
|
6
|
+
export async function run(provider: NetworkProvider) {
|
|
7
|
+
const {{loweredName}} = provider.open(
|
|
8
|
+
{{name}}.createFromConfig(
|
|
9
|
+
{
|
|
10
|
+
id: Math.floor(Math.random() * 10000),
|
|
11
|
+
counter: 0,
|
|
12
|
+
},
|
|
13
|
+
await compile('{{name}}')
|
|
14
|
+
)
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
await {{loweredName}}.sendDeploy(provider.sender(), toNano('0.05'));
|
|
18
|
+
|
|
19
|
+
await provider.waitForDeploy({{loweredName}}.address);
|
|
20
|
+
|
|
21
|
+
console.log('ID', await {{loweredName}}.getID());
|
|
22
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
increment{{name}}.ts
|
|
2
|
+
import { Address, toNano } from 'ton-core';
|
|
3
|
+
import { {{name}} } from '../wrappers/{{name}}';
|
|
4
|
+
import { NetworkProvider, sleep } from '@ton-community/blueprint';
|
|
5
|
+
|
|
6
|
+
export async function run(provider: NetworkProvider, args: string[]) {
|
|
7
|
+
const ui = provider.ui();
|
|
8
|
+
|
|
9
|
+
const address = Address.parse(args.length > 0 ? args[0] : await ui.input('{{name}} address'));
|
|
10
|
+
|
|
11
|
+
if (!(await provider.isContractDeployed(address))) {
|
|
12
|
+
ui.write(`Error: Contract at address ${address} is not deployed!`);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const {{loweredName}} = provider.open({{name}}.createFromAddress(address));
|
|
17
|
+
|
|
18
|
+
const counterBefore = await {{loweredName}}.getCounter();
|
|
19
|
+
|
|
20
|
+
await {{loweredName}}.sendIncrease(provider.sender(), {
|
|
21
|
+
increaseBy: 1,
|
|
22
|
+
value: toNano('0.05'),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
ui.write('Waiting for counter to increase...');
|
|
26
|
+
|
|
27
|
+
let counterAfter = await {{loweredName}}.getCounter();
|
|
28
|
+
let attempt = 1;
|
|
29
|
+
while (counterAfter === counterBefore) {
|
|
30
|
+
ui.setActionPrompt(`Attempt ${attempt}`);
|
|
31
|
+
await sleep(2000);
|
|
32
|
+
counterAfter = await {{loweredName}}.getCounter();
|
|
33
|
+
attempt++;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
ui.clearActionPrompt();
|
|
37
|
+
ui.write('Counter increased successfully!');
|
|
38
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{{name}}.spec.ts
|
|
2
|
+
import { Blockchain, SandboxContract } from '@ton-community/sandbox';
|
|
3
|
+
import { Cell, toNano } from 'ton-core';
|
|
4
|
+
import { {{name}} } from '../wrappers/{{name}}';
|
|
5
|
+
import '@ton-community/test-utils';
|
|
6
|
+
import { compile } from '@ton-community/blueprint';
|
|
7
|
+
|
|
8
|
+
describe('{{name}}', () => {
|
|
9
|
+
let code: Cell;
|
|
10
|
+
|
|
11
|
+
beforeAll(async () => {
|
|
12
|
+
code = await compile('{{name}}');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
let blockchain: Blockchain;
|
|
16
|
+
let {{loweredName}}: SandboxContract<{{name}}>;
|
|
17
|
+
|
|
18
|
+
beforeEach(async () => {
|
|
19
|
+
blockchain = await Blockchain.create();
|
|
20
|
+
|
|
21
|
+
{{loweredName}} = blockchain.openContract(
|
|
22
|
+
{{name}}.createFromConfig(
|
|
23
|
+
{
|
|
24
|
+
id: 0,
|
|
25
|
+
counter: 0,
|
|
26
|
+
},
|
|
27
|
+
code
|
|
28
|
+
)
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const deployer = await blockchain.treasury('deployer');
|
|
32
|
+
|
|
33
|
+
const deployResult = await {{loweredName}}.sendDeploy(deployer.getSender(), toNano('0.05'));
|
|
34
|
+
|
|
35
|
+
expect(deployResult.transactions).toHaveTransaction({
|
|
36
|
+
from: deployer.address,
|
|
37
|
+
to: {{loweredName}}.address,
|
|
38
|
+
deploy: true,
|
|
39
|
+
success: true,
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should deploy', async () => {
|
|
44
|
+
// the check is done inside beforeEach
|
|
45
|
+
// blockchain and {{loweredName}} are ready to use
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should increase counter', async () => {
|
|
49
|
+
const increaseTimes = 3;
|
|
50
|
+
for (let i = 0; i < increaseTimes; i++) {
|
|
51
|
+
console.log(`increase ${i + 1}/${increaseTimes}`);
|
|
52
|
+
|
|
53
|
+
const increaser = await blockchain.treasury('increaser' + i);
|
|
54
|
+
|
|
55
|
+
const counterBefore = await {{loweredName}}.getCounter();
|
|
56
|
+
|
|
57
|
+
console.log('counter before increasing', counterBefore);
|
|
58
|
+
|
|
59
|
+
const increaseBy = Math.floor(Math.random() * 100);
|
|
60
|
+
|
|
61
|
+
console.log('increasing by', increaseBy);
|
|
62
|
+
|
|
63
|
+
const increaseResult = await {{loweredName}}.sendIncrease(increaser.getSender(), {
|
|
64
|
+
increaseBy,
|
|
65
|
+
value: toNano('0.05'),
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
expect(increaseResult.transactions).toHaveTransaction({
|
|
69
|
+
from: increaser.address,
|
|
70
|
+
to: {{loweredName}}.address,
|
|
71
|
+
success: true,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const counterAfter = await {{loweredName}}.getCounter();
|
|
75
|
+
|
|
76
|
+
console.log('counter after increasing', counterAfter);
|
|
77
|
+
|
|
78
|
+
expect(counterAfter).toBe(counterBefore + increaseBy);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
});
|