请前往 chainx-org/ChainX 下载 v1.0.7 的最新版本 ChainX v1.0.7-beta.1.
安装 Rust 环境, 详情请参考 rust-lang.org/tools/install.
安装好 Rust 环境后, 安装方便构建合约项目的命令行工具 cargo-contract
. 注意,请安装 chainx-org/cargo-contract ink2.0 branch, 而不是安装 paritytech/cargo-contract
。
$ cargo install --git https://github.com/chainx-org/cargo-contract --branch ink2.0 cargo-contract --force
在基本用法上, chainx-org/cargo-contract
与 paritytech/cargo-contract
一致,区别在于 chainx-org/cargo-contract
使用了定制的 chainx-org/ink
branch ink2.0, 而非 paritytech/ink
。
创建一个 flipper 的示例项目:
$ cargo-contract contract new flipper
运行测试:
$ cd flipper
$ cargo +nightly test
编译 WASM 合约文件:
$ cargo-contract contract build
生成合约 metadata,也就是合约 ABI:
$ cargo-contract contract generate-metadata
在 target/
目录下面会生成一个 metadata.json
文件,其中包含了与合约交互的必要信息。
启动单节点模式:
$ ./chainx --dev --default-log -d <指定数据目录> --log=runtime=debug --no-telemetry --block-construction-execution=native --other-execution=native
关于本地启动节点的更多内容,可以阅读 wiki ChainX-Dev, 一般来说调试合约使用单节点模式即可。
点击 Chainx Extension 安装插件。
如果因为网络无法安装插件,可以在我们的插件发布仓库下载插件压缩包,并通过 Chrome 的 Load unpacked 来加载插件。
安装完成之后
-
将网络切换至测试网
- ChainX当前对于测试网默认提供了
wss://testnet.w1.org.cn/ws
的节点配置 - 如使用
ChainX Dev
模式或者在本地跑了测试网的同步节点,可以添加localhost:ws://localhost:<websocket的端口>
- ChainX当前对于测试网默认提供了
-
新建或者导入账户
流程如下:
-
在导入钱包界面若选择”导入钱包“,在助记词页面右上角有直接导入私钥的选项。
-
在浏览器插件中将网络切换到测试网, 合约功能目前只在测试网开启。
整个过程主要分为 3 个步骤:
- 上传合约(Upload WASM).
- 实例化合约, 或者叫部署合约(Deploy)
- 调用合约
所有步骤可以通过 https://dapps.chainx.org.cn/ 操作,也可以通过 JS-SDK 进行脚本调用。
- 打开 Chainx Wallet,并切换到『上传合约』页面:
- 确保你合约目录的
target
目录存在编译好的wasm
文件和json
文件:
- 点击 UPLOAD WASM,并在表单中上传和填写相应的参数:
-
点击 CONFIRM 之后,会调起插件对该上传交易进行签名,请输入账户密码并确认签名
-
合约成功部署后显示如下(包含该合约所有的方法):
使用 js SDK 上传合约:
const { compactAddLength } = require('@chainx/util');
const code = compactAddLength(fs.readFileSync(path.resolve(__dirname, './erc20.wasm')));
const extrinsic = chainx.api.tx.xContracts.putCode(100000000, code);
let codeHash;
ex.signAndSend(Test, (error, result) => {
console.log(error, result);
if (result && result.result === 'ExtrinsicSuccess') {
// 获取 codeHash
codeHash = result.events.find(e => e.method === 'CodeStored').event.data;
}
});
如果出现上传失败, 可能存在的原因有:
- codehash 已存在,请复制提示的 codehash,并通过『Add existing code hash』上传合约代码
- 账户余额不足,请保证上传帐号有足够多的 PCX
- gasLimit 不够,请尝试提高 gasLimit 并重试
上一步的上传合约,只是简单的将合约代码存储在链上,还没有任何可以操作和调用的功能,所以接下来我们需要将这份合约进行实例化。
- 点击 Deploy 并填写实例化必要的参数:
调起插件之后,输入密码并确认签名即可实例化合约。
- 合约部署成功之后,页面会自动跳转到『合约』页面,该页面如下图所示:
- 若链上已经存在这个合约,可点击
ADD EXISTING CONTRACT
按钮,添加一个已经存在的合约。请注意在添加这个合约实例的时候需要同时提供这个合约的abi.json
,若提供错误的abi,在调用时会造成selector错误,无法调用对应函数。
使用 js SDK 实例化合约:
// 合约 abi
const erc20 = require('./erc20');
// 解析 abi
const Abi = require('@chainx/api-contract');
const abi = new Abi(erc20);
// 5GE7vwvDmKCCPrVLc9XZJAiAspM9LhQWbQjPvZ3QxzBUbhT7
const extrinsic = chainx.api.tx.xContracts.instantiate(
1000,
100000000,
'0x5e71dc66c1527bf4047942c5ada9c5c59941bff8eb8b2d1a6d849306bfd52e93',
abi.constructors[0](...), // 合约的构造函数
);
let contractAddress
ex.signAndSend(Test, (error, result) => {
if (result && result.result === 'ExtrinsicSuccess') {
// 获取 contractAddress
contractAddress = result.events.find(e => e.method === 'Instantiated').event.data[1];
}
});
方法执行成功后会在下方的结果区域显示相应的返回数据:
total_supply
与我们初始化合约的时候一致。至此我们的合约上传部署调用就完成了。
使用 js SDK 调用合约方法:
const abi = new Abi(erc20);
const ex = chainx.api.tx.xContracts.call(
'5GE7vwvDmKCCPrVLc9XZJAiAspM9LhQWbQjPvZ3QxzBUbhT7', // contract address
0, // value
10000000, // gas
// 调用的函数
abi.messages.transfer('5FvHGYk44FHZXznrhoskVyr2zGPYn5CpUXphRKM8eGRJZMtX', 10)
);
ex.signAndSend(Alice, (error, result) => {
console.log(error, result);
});