三、创建合约
上一节我们创建了钱包,并领取了免费的NAS,现在我们来到DApp化的核心步骤——创建合约。
编写合约
星云链的合约需要用javascript或Typescript编写,一个合约定义了一个javascript对象的构造函数,构造函数里定义了对象所具有的方法。
对于应用开发者,每一个方法就是一个和星云链交互的接口,合约要定义什么样的方法是由应用的需求决定的,也就在在第一节一、一个普通App里面提到的,设计应用之初,应该考虑需要在星云链存储或者获取什么数据。
智能合约例子
这里我们用一个例子来看一个合约包括哪些智能合约-SmartContract
"use strict";
var DepositeContent = function (text) {
if (text) {
var o = JSON.parse(text);
this.balance = new BigNumber(o.balance);
this.expiryHeight = new BigNumber(o.expiryHeight);
} else {
this.balance = new BigNumber(0);
this.expiryHeight = new BigNumber(0);
}
};
DepositeContent.prototype = {
toString: function () {
return JSON.stringify(this);
}
};
var BankVaultContract = function () {
LocalContractStorage.defineMapProperty(this, "bankVault", {
parse: function (text) {
return new DepositeContent(text);
},
stringify: function (o) {
return o.toString();
}
});
};
// save value to contract, only after height of block, users can takeout
BankVaultContract.prototype = {
init: function () {
//TODO:
},
save: function (height) {
var from = Blockchain.transaction.from;
var value = Blockchain.transaction.value;
var bk_height = new BigNumber(Blockchain.block.height);
var orig_deposit = this.bankVault.get(from);
if (orig_deposit) {
value = value.plus(orig_deposit.balance);
}
var deposit = new DepositeContent();
deposit.balance = value;
deposit.expiryHeight = bk_height.plus(height);
this.bankVault.put(from, deposit);
},
takeout: function (value) {
var from = Blockchain.transaction.from;
var bk_height = new BigNumber(Blockchain.block.height);
var amount = new BigNumber(value);
var deposit = this.bankVault.get(from);
if (!deposit) {
throw new Error("No deposit before.");
}
if (bk_height.lt(deposit.expiryHeight)) {
throw new Error("Can not takeout before expiryHeight.");
}
if (amount.gt(deposit.balance)) {
throw new Error("Insufficient balance.");
}
var result = Blockchain.transfer(from, amount);
if (!result) {
throw new Error("transfer failed.");
}
Event.Trigger("BankVault", {
Transfer: {
from: Blockchain.transaction.to,
to: from,
value: amount.toString()
}
});
deposit.balance = deposit.balance.sub(amount);
this.bankVault.put(from, deposit);
},
balanceOf: function () {
var from = Blockchain.transaction.from;
return this.bankVault.get(from);
},
verifyAddress: function (address) {
// 1-valid, 0-invalid
var result = Blockchain.verifyAddress(address);
return {
valid: result == 0 ? false : true
};
}
};
module.exports = BankVaultContract;
这份智能合约定义了5个接口。
init接口是一个合约必须要有的方法。
save, takeout, balanceOf, verifyAddress 分别是存钱,转账,查询合约余额,校验合约地址。
星云链库简介
合约中用到星云链提供的一些库:
-
LocalContractStorage
用来支持星云链上的数据持久化存储。这是一个键值存储系统,可存储的数据类型包括数字、字符串和 JavaScript 对象(需要序列化为字符串)。
LocalContractStorage 支持三个操作:set、get/put和 del,分别实现存储、读取和删除数据功能。
LocalContractStorage 还支持绑定以下两类链上存储空间到合约属性上:单值类型(storage property)和Map类型(storage map)。上面的智能合约就绑定了Map类型存储空间。 -
Blockchain
Blockchain 模块用来获取当前正在执行的合约内的交易和区块信息和一些方法
Blockchain 有两个属性:
1、block 执行合约的当前区块,它具有下列属性:
— timestamp 区块时间戳
— height 区块高度
2、transaction 执行合约的当前交易,它具有下列属性:
— hash 交易哈希值
— from 交易源地址
— to 交易目的地址,对于合约调用就是合约地址
— value 交易数值,字符串, 合约内用BigNumber存储计算
— nonce 交易的 nonce 值
— timestamp 交易时间戳
— gasPrice 交易的 gasPrice,字符串,合约内用 BigNumber 存储计算
— gasLimit 交易的 gasLimit,字符串,合约内用 BigNumber 存储计算
Blockchain 还提供了两个方法:
1、transfer(address, value) 将 NAS 从合约转出到address对应的账户。
· 参数 address:接收 NAS 的 Nebulas 账户地址
· 参数 value:转移数值,一个 BigNumber 对象
返回:0 – 转移成功,1 – 转移失败
2、verifyAddress(address) 验证参数 address 是否为一个有效的 Nebulas 地址。
返回:1 – 地址有效,0 – 地址无效
请参照智能合约的例子编写自己的合约。
部署合约
编写完自己的合约,就可以部署到星云链上来调用了。
打开二、创建钱包里下载的星云钱包的主页web-wallet/index.html,打开Contract页,选择Deploy页面
![](https://img.haomeiwen.com/i2610944/fb4e504eb04db7ee.png)
在code里面粘贴整个合约的源代码,语言选择Javascript,arguments留白,选择钱包keystore文件并输入钱包密码,点击unlock解锁钱包信息。
From Address和To Address都自动填充为钱包地址,Balance显示的是钱包余额,点击Test
![](https://img.haomeiwen.com/i2610944/c05e5c03a225a8d6.png)
显示这样的结果表示合约没有问题,点击Submit就正式部署合约。
![](https://img.haomeiwen.com/i2610944/e64286158c7728b5.png)
txhash是合约哈希,contract_address是合约地址,保存好这两个值。
此时合约部署成功。
调用合约
点击Call来到合约调用页面,此页面供开发者测试合约中的方法,建议在应用中调用合约之前都在此先测试合约方法。
function: 要调用的合约的方法,如智能合约中的 save, takeout, balanceOf。
arguments: 调用的方法的参数,如智能合约中save方法,需要参数[‘1000’],如果方法不需要参数,则不填写。
From Address: 钱包地址
To Address: 合约地址,此处需要注意。
下面测试智能合约中的balanceOf方法
![](https://img.haomeiwen.com/i2610944/bcbd7b55a9c2e2e1.png)
点击Test,返回结果中result为null,对于新创建的合约,还没有在合约地址中存入任何数据,所以查询到的结果为null。
我们尝试先调用save存入数据。
Value/Amount to Send这里的单位是NAS, 所以对于NAS不多的同学来说,这里一定要填小一点的数比如0.000000000000000001或者直接0(如果你的交易数据不是Value/Amount的话),开源节流嘛,如果你的Value/Amount大于你的钱包余额,调用会出现NAS不足的错误。
先单击Test测试合约调用是否正常
![](https://img.haomeiwen.com/i2610944/75aa435c35485088.png)
以上结果说明合约调用正常,再点击Submit提交交易,数据才会真正的存储到星云链。每个交易会返回txhash, 可以在Check TX Status查看交易的状态,只有状态为Success,交易才被存储到了链上。
然后我们再次调用banlanceOf接口,可以看到我们调用save接口存储在星云链上的数据。
![](https://img.haomeiwen.com/i2610944/c3485b28deda3672.png)
合约部署并测试成功了,就可以将我们的应用DApp化了四、DApp化
如果你觉得本教程对你有用,请使用本邀请链接注册星云链星云链注册入口,谢谢!