仔细思考一下上传的合约就是普通应用后台程序,LocalContractStorage就是他的数据库,只不过他们都具有区块链的特性,程序是用 js 或者 ts 写的不用多说,先看一下LocalContractStorage这个数据库怎么用,然后再看交互这样的一个学习思路
智能合约储存区
基本用法
//LocalContractStorage存储数据
// 存储数据,数据会被json序列化成字符串保存
LocalContractStorage.put(key, value);
// 或者
LocalContractStorage.set(key, value);
//LocalContractStorage读取数据
// 获取数据
LocalContractStorage.get(key);
//LocalContractStorage删除数据
// 删除数据, 数据删除后无法读取
LocalContractStorage.del(key);
// 或者
LocalContractStorage.delete(key);
可以直接在测试网络n1oBLAQpy2ws1WQPKQa1GEm7VsLKeWrwdVo这个地址上直接试
'use strict';
var SampleContract = function () {
};
SampleContract.prototype = {
init: function () {
},
set: function (name, value) {
// 存储字符串
LocalContractStorage.set("name",name);
// 存储数字
LocalContractStorage.set("value", value);
// 存储对象
LocalContractStorage.set("obj", {name:name,value:value});
},
get: function () {
var name = LocalContractStorage.get("name");
console.log("name:"+name)
var value = LocalContractStorage.get("value");
console.log("value:"+value)
var obj = LocalContractStorage.get("obj");
console.log("obj:"+JSON.stringify(obj))
},
del: function () {
var result = LocalContractStorage.del("name");
console.log("del result:"+result)
}
};
module.exports = SampleContract;
高级用法
LocalContractStorage除了基本的set,get,del方法,还提供方法来绑定合约属性。对绑定过的合约属性的读写将直接在LocalContractStorage上读写,而无需调用get和set方法。
'use strict';
var SampleContract = function () {
// SampleContract的`size`属性为存储属性,对`size`的读写会存储到链上,
// 此处的`descriptor`设置为null,将使用默认的JSON.stringify()和JSON.parse()
LocalContractStorage.defineMapProperty(this, "size", null);
// SampleContract的`value`属性为存储属性,对`value`的读写会存储到链上,
// 此处的`descriptor`自定义实现,存储时直接转为字符串,读取时获得Bignumber对象
LocalContractStorage.defineMapProperty(this, "value", {
stringify: function (obj) {
return obj.toString();
},
parse: function (str) {
return new BigNumber(str);
}
});
// SampleContract的多个属性批量设置为存储属性,对应的descriptor默认使用JSON序列化
LocalContractStorage.defineProperties(this, {
name: null,
count: null
});
};
SampleContract.prototype = {
// 合约部署时调用,部署后无法二次调用
init: function (name, count, size, value) {
// 在部署合约时将数据存储到链上
this.name = name;
this.count = count;
this.size = size;
this.value = value;
},
testStorage: function (balance) {
// 使用value时会从存储中读取链上数据,并根据descriptor设置自动转换为Bignumber
var amount = this.value.plus(new BigNumber(2));
if (amount.lessThan(new BigNumber(balance))) {
return 0
}
}
};
module.exports = SampleContract;
保存 map
'use strict';
var SampleContract = function () {
// 为`SampleContract`定义`userMap`的属性集合,数据可以通过`userMap`存储到链上
LocalContractStorage.defineMapProperty(this, "userMap");
// 为`SampleContract`定义`userBalanceMap`的属性集合,并且存储和读取序列化方法自定义
LocalContractStorage.defineMapProperty(this, "userBalanceMap", {
stringify: function (obj) {
return obj.toString();
},
parse: function (str) {
return new BigNumber(str);
}
});
// 为`SampleContract`定义多个集合
LocalContractStorage.defineMapProperties(this,{
key1Map: null,
key2Map: null
});
};
SampleContract.prototype = {
init: function () {
},
testStorage: function () {
// 将数据存储到userMap中,并序列化到链上
this.userMap.set("robin","1");
// 将数据存储到userBalanceMap中,使用自定义序列化函数,保存到链上
this.userBalanceMap.set("robin",new BigNumber(1));
},
testRead: function () {
//读取存储数据
var balance = this.userBalanceMap.get("robin");
this.key1Map.set("robin", balance.toString());
this.key2Map.set("robin", balance.toString());
}
};
module.exports = SampleContract;
map遍历
就是单独开一个 map 存 index 和 key,遍历 index 取 key 在用 key 取 value
"use strict";
var SampleContract = function () {
LocalContractStorage.defineMapProperty(this, "arrayMap");
LocalContractStorage.defineMapProperty(this, "dataMap");
LocalContractStorage.defineProperty(this, "size");
};
SampleContract.prototype = {
init: function () {
this.size = 0;
},
set: function (key, value) {
var index = this.size;
this.arrayMap.set(index, key);
this.dataMap.set(key, value);
this.size +=1;
},
get: function (key) {
return this.dataMap.get(key);
},
len:function(){
return this.size;
},
forEach: function(limit, offset){
limit = parseInt(limit);
offset = parseInt(offset);
if(offset>this.size){
throw new Error("offset is not valid");
}
var number = offset+limit;
if(number > this.size){
number = this.size;
}
var result = "";
for(var i=offset;i<number;i++){
var key = this.arrayMap.get(i);
var object = this.dataMap.get(key);
result += "index:"+i+" key:"+ key + " value:" +object+"_";
}
return result;
}
};
module.exports = SampleContract;
rpc 接口
现在,星云节点的所有的接口被分为两个模块:API和Admin。
API:提供所有和用户私钥无关的接口
Admin:提供所有和用户私钥相关的接口
建议星云节点对外提供服务时,可以把API接口开放给公众,而将Admin接口开放给授权用户。 (注:星云官方的testnet及mainnet的admin相关api不支持远程访问 需要用 nebjs)
再开一篇文章通过例子学习交互,并写一个 Dapp
接口文档
星云 Dapp 开发1星云 Dapp 开发1