文章目录
一编译链安装
要建立一个能够编译智能合约示例的本地项目,你需要按照以下步骤操作:
-
安装Node.js:确保你的计算机上安装了Node.js,版本至少是16.15.0。你可以通过在终端或命令提示符中运行
node -v
来验证安装。如果还没有安装,你可以从Node.js官网下载并安装。 -
安装软件包管理器:如果你选择了Node.js,那么npm(Node Package Manager)很可能已经随Node.js一起安装了。但在这个教程中,我们推荐使用Yarn作为包管理器。如果你更习惯使用npm,那也是完全可以的。
-
安装集成开发环境(IDE):我们建议使用Visual Studio Code,并安装FunC插件。如果你倾向于使用IntelliJ,也可以找到相应的FunC插件。
一旦你满足了上述要求,就可以开始搭建你的本地项目环境了。
步骤1:创建项目文件夹
在你的计算机上创建一个新的文件夹,命名为my_first_contract
,然后进入这个文件夹:
mkdir my_first_contract && cd my_first_contract
步骤2:初始化package.json
使用Yarn初始化一个新的package.json文件:
yarn init
或者使用npm
npm init
在提示时,你可以直接按回车键接受默认设置。完成后,你的项目目录下将有一个包含基本配置的package.json文件。
![](/qrcode.jpg)
{
"name": "krasha",
"version": "1.0.0",
"description": "first ton learning",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "krasha",
"license": "MIT",
"dependencies": {
"@swc/core": "^1.7.35",
"@types/node": "^22.7.5",
"ts-node": "^10.9.2",
"typescript": "^5.6.3"
}
}
步骤3:安装TypeScript相关库
在项目目录下,运行以下命令来安装TypeScript及其相关库:
yarn add typescript ts-node @types/node @swc/core --dev
这些库将帮助你在项目中使用TypeScript。
或者使用npm
npm add typescript ts-node @types/node @swc/core --dev
步骤4:创建tsconfig.json
在你的项目目录下创建一个名为tsconfig.json
的文件,并添加以下配置:
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"resolveJsonModule": true
},
"ts-node": {
"transpileOnly": true,
"transpiler": "ts-node/transpilers/swc"
}
}
这个配置文件告诉TypeScript编译器如何编译你的代码。
上面的内容的含义为:
这段代码是一个TypeScript配置文件(通常是tsconfig.json
),它定义了TypeScript编译器的编译选项和ts-node
的运行时选项。下面我会逐项解释这些配置项的含义:
-
compilerOptions
: 这是一个对象,包含了TypeScript编译器的配置选项。 -
target
: 这个选项指定了ECMAScript目标版本。在这里设置为"es2020"
,意味着编译后的JavaScript代码将兼容ECMAScript 2020标准。 -
module
: 这个选项指定了模块代码生成的格式。"commonjs"
是Node.js环境中常用的模块系统,它使用require
和module.exports
来导入和导出模块。 -
esModuleInterop
: 当设置为true
时,允许在不使用.default
的情况下,从ES模块中导入CommonJS模块。这使得在TypeScript项目中混合使用CommonJS和ES模块变得更加容易。 -
forceConsistentCasingInFileNames
: 当设置为true
时,TypeScript编译器会强制文件名的大小写与实际文件系统中的大小写一致。这有助于避免在大小写不敏感的文件系统中出现错误。 -
strict
: 当设置为true
时,启用所有严格类型检查选项。这包括noImplicitAny
,noImplicitThis
,alwaysStrict
等,有助于捕获潜在的错误。 -
skipLibCheck
: 当设置为true
时,跳过库文件的类型检查。这可以减少编译时间,但可能会忽略第三方库中的类型错误。 -
resolveJsonModule
: 当设置为true
时,允许直接导入.json
文件,而不是将它们视为仅包含字符串字面量的模块。 -
ts-node
: 这是一个对象,包含了ts-node
的配置选项。 -
transpileOnly
: 当设置为true
时,ts-node
只会转译TypeScript代码,而不会执行类型检查。这通常用于快速开发和测试,因为它可以加快启动时间。 -
transpiler
: 这个选项指定了ts-node
使用的转译器。在这里,它被设置为"ts-node/transpilers/swc"
,意味着使用SWC作为转译器。SWC是一个快速的TypeScript和JavaScript编译器,可以提高ts-node
的执行速度。
总的来说,这个配置文件为TypeScript项目提供了一套现代化的编译选项,同时通过ts-node
的配置优化了开发体验。
步骤5:安装TON相关的库
最后,你需要安装与TON区块链相关的库,包括ton-core
、ton-crypto
和@ton-community/func-js
。运行以下命令来安装这些库:
yarn add @ton/core ton-crypto @ton-community/func-js --dev
或者使用npm
npm add @ton/core ton-crypto @ton-community/func-js --dev
这些库将为你提供TON区块链的核心功能和FunC编译器。
ton-core - 实现 TON 区块链底层基元的核心库。
ton-crypto - 用于为 TON 区块链构建应用程序的加密基元。
@ton-community/func-js - TON FunC 编译器
完成这些步骤后,你的本地项目环境就搭建好了,可以开始编写和编译智能合约了。
FunC(Functional Contract)是一种用于编写TON区块链智能合约的编程语言。下面,我们将通过一个简单的例子来展示如何创建一个FunC智能合约,并编写一个脚本来编译它。
二 第一个func文件
步骤1:创建contracts文件夹并创建FunC文件
首先,我们需要创建一个专门用于存放智能合约的文件夹,并在其中创建一个FunC文件。在终端中运行以下命令:
mkdir contracts && cd contracts && touch main.fc
这条命令会创建一个名为contracts
的文件夹,进入该文件夹,并创建一个名为main.fc
的空文件。
本地编译:编辑FunC文件
接下来,我们需要编辑main.fc
文件,插入一个简单的FunC代码示例。你可以使用任何文本编辑器来完成这个步骤。以下是示例代码:
() recv_internal(int msg_value, cell in_msg, slice in_msg_body) impure {
}
这段代码定义了一个名为recv_internal
的函数,它是TON智能合约中用于处理内部消息的入口点。在这个例子中,函数不接受任何参数,也不执行任何操作,它只是一个空的函数体。
步骤3:编写编译脚本
为了编译这个FunC文件,我们需要编写一个脚本来调用FunC编译器。在项目的根目录下(即contracts
文件夹的上一级目录),创建一个名为build.sh
的脚本文件,并添加以下内容:
#!/bin/bash
# 进入contracts目录
cd contracts
# 调用FunC编译器编译main.fc文件
func main.fc -o main.fif
# 返回项目根目录
cd ..
确保你的系统上安装了FunC编译器,here,并且它已经添加到了环境变量中,这样你才能在脚本中直接调用func
命令。
步骤4:给脚本执行权限并运行
在终端中,给build.sh
脚本文件添加执行权限,并运行它:
chmod +x build.sh
./build.sh
这将执行脚本,脚本会进入contracts
目录,使用FunC编译器编译main.fc
文件,并生成一个名为main.fif
的中间文件。
脚本编译
当然,让我们详细地一步步走过创建编译脚本的过程,并解释每一步的作用。
步骤 1: 创建 scripts 文件夹和 compile.ts 文件
首先,我们在项目根目录下创建一个名为 scripts
的文件夹,这个文件夹将用来存放所有编译和可能的其他脚本。然后,我们在 scripts
文件夹下创建一个名为 compile.ts
的TypeScript文件,这个文件将包含我们的编译脚本。
mkdir scripts && cd scripts && touch compile.ts
这些命令在项目中创建了一个新的目录结构,并且初始化了一个空的TypeScript文件,用于编写我们的编译逻辑。
步骤 2: 在 package.json 中添加脚本快捷方式
接下来,我们在 package.json
文件中添加一个快捷方式,这样我们就可以通过运行 yarn compile
来执行我们的编译脚本。这使得运行编译过程更加方便和快捷。
{
// ...your previous package.json contents
"scripts": {
"compile": "ts-node ./scripts/compile.ts"
}
}
这里,我们定义了一个名为 compile
的脚本,它将调用 ts-node
来执行 scripts
目录下的 compile.ts
文件。
步骤 3: 编写编译脚本
现在,我们开始在 compile.ts
文件中编写编译脚本。我们将逐步添加代码,并解释每一部分的作用。
导入必要的模块
import * as fs from "fs";
import process from "process";
import {
Cell } from "@ton/core";
import {
compileFunc } from "@ton-community/func-js";
fs
模块用于文件系统操作,我们将用它来读取和写入文件。process
模块提供了一些有用的属性和方法,比如process.exit()
,用于在发生错误时退出脚本。Cell
类来自@ton/core
库,用于处理TON区块链的单元(cell)数据结构。compileFunc
函数来自@ton-community/func-js
库,用于编译FunC代码。
定义异步编译函数
async function compileScript() {
// 编译逻辑将在这里
}
compileScript();
我们定义了一个异步函数 compileScript
,因为编译操作是异步的,我们需要等待它完成。然后我们立即调用这个函数。
调用编译函数并处理结果
const compileResult = await compileFunc({
targets: ["./contracts/main.fc"],
sources: (x) => fs.readFileSync(x).toString("utf8"),
});
if (compileResult.status === "error") {
process.exit(1);
}
- 我们调用
compileFunc
并传入一个配置对象,指定要编译的目标文件和源代码的位置。 - 如果编译结果的状态是
error
,我们打印错误信息并退出脚本。
保存编译结果
const hexArtifact = `build/main.compiled.json`;
fs.writeFileSync(
hexArtifact,
JSON.stringify({
hex: Cell.fromBoc(Buffer.from(compileResult.codeBoc, "base64"))[0]
.toBoc()
.toString("hex"),
})
);
- 我们创建了一个
hexArtifact
变量,它将保存编译后的合约的十六进制表示。 - 使用
Cell.fromBoc
方法将编译结果的 BOC(Body of Cell)base64 字符串转换为Cell
对象。 - 然后,我们将
Cell
对象转换为十六进制字符串,并将其保存到一个 JSON 文件中。
添加控制台日志
console.log(
"================================================================="
);
console.log(
"Compile script is running, let's find some FunC code to compile..."
);
// ... 编译逻辑 ...
console.log(" - Compilation successful!");
console.log(" - Compiled code saved to " + hexArtifact);
- 我们在脚本中添加了控制台日志,以提供编译过程的反馈和状态信息。
步骤 4: 运行编译脚本
最后,我们可以通过在项目根目录下运行 yarn compile
npm run compile
来执行我们的编译脚本。这将触发我们在 package.json
中定义的脚本,运行 compile.ts
文件中的编译逻辑。
这个编译脚本与直接使用 func main.fc -o main.fif
命令行工具的主要区别在于:
- 自动化和集成:脚本可以在开发过程中自动运行,而不需要每次都手动调用命令行工具。
- 错误处理:脚本可以捕获和处理编译错误,提供更详细的错误信息。
- 输出格式的灵活性:脚本可以将编译结果保存为不同的格式,例如JSON文件,方便与其他工具或流程集成。
- 扩展性:由于脚本是用TypeScript编写的,你可以轻松地添加更多的功能,例如代码检查、格式化或其他自定义的编译步骤。
通过这种方式,我们可以更灵活地控制编译过程,并将其与其他开发工具和流程集成。