1. 智能合约SDK使用说明¶
XuperChain为方便用户开发属于自己的智能合约,提供了一整套SDK套件,即XuperCDT(XuperChain Crontract Development Toolkit),包含C++语言、Go语言和Java语言
1.1. C++接口API¶
1.1.1. get_object¶
bool ContextImpl::get_object(const std::string& key, std::string* value)
输入
参数 |
说明 |
---|---|
key |
查询的key值 |
value |
根据key查到的value值 |
输出
参数 |
说明 |
---|---|
true |
key值查询成功,返回value值 |
false |
key值不存在 |
1.1.2. put_object¶
bool ContextImpl::put_object(const std::string& key, const std::string& value)
输入
参数 |
说明 |
---|---|
key |
存入的key值 |
value |
存入key值对应的value值 |
输出
参数 |
说明 |
---|---|
true |
存入db成功 |
false |
存入db失败 |
1.1.3. delete_object¶
bool ContextImpl::delete_object(const std::string& key)
输入
参数 |
说明 |
---|---|
key |
将要删除的key值 |
输出
参数 |
说明 |
---|---|
true |
删除成功 |
false |
删除失败 |
1.1.4. query_tx¶
bool ContextImpl::query_tx(const std::string &txid, Transaction* tx)
输入
参数 |
说明 |
---|---|
txid |
待查询的txid |
tx |
得到此txid的transaction |
输出
参数 |
说明 |
---|---|
true |
查询交易成功 |
false |
查询交易失败 |
1.1.5. query_block¶
bool ContextImpl::query_block(const std::string &blockid, Block* block)
输入
参数 |
说明 |
---|---|
blockid |
待查询的blockid |
block |
得到此blockid的block |
输出
参数 |
说明 |
---|---|
true |
查询block成功 |
false |
查询block失败 |
1.1.6. table¶
1.1.6.1. 定义表格¶
1// 表格定义以proto形式建立,存放目录为contractsdk/cpp/pb
2syntax = "proto3";
3option optimize_for = LITE_RUNTIME;
4package anchor;
5message Entity {
6 int64 id = 1;
7 string name = 2;
8 bytes desc = 3;
9}
10// table名称为Entity,属性分别为id,name,desc
1.1.6.2. 初始化表格¶
1// 定义表格的主键,表格的索引
2struct entity: public anchor::Entity {
3 DEFINE_ROWKEY(name);
4 DEFINE_INDEX_BEGIN(2)
5 DEFINE_INDEX_ADD(0, id, name)
6 DEFINE_INDEX_ADD(1, name, desc)
7 DEFINE_INDEX_END();
8};
9// 声明表格
10xchain::cdt::Table<entity> _entity;
1.1.6.3. put¶
1template <typename T>
2bool Table<T>::put(T t)
输入
参数 |
说明 |
---|---|
t |
待插入的数据项 |
输出
参数 |
说明 |
---|---|
true |
插入成功 |
false |
插入失败 |
样例
1// 参考样例 contractsdk/cpp/example/anchor.cc
2DEFINE_METHOD(Anchor, set) {
3 xchain::Context* ctx = self.context();
4 const std::string& id= ctx->arg("id");
5 const std::string& name = ctx->arg("name");
6 const std::string& desc = ctx->arg("desc");
7 Anchor::entity ent;
8 ent.set_id(std::stoll(id));
9 ent.set_name(name.c_str());
10 ent.set_desc(desc);
11 self.get_entity().put(ent);
12 ctx->ok("done");
13}
1.1.6.4. find¶
1template <typename T>
2bool Table<T>::find(std::initializer_list<PairType> input, T* t)
输入
参数 |
说明 |
---|---|
input |
查询关键字 |
t |
返回的数据项 |
输出
参数 |
说明 |
---|---|
true |
查询成功 |
false |
查询失败 |
样例
1DEFINE_METHOD(Anchor, get) {
2 xchain::Context* ctx = self.context();
3 const std::string& name = ctx->arg("key");
4 Anchor::entity ent;
5 if (self.get_entity().find({{"name", name}}, &ent)) {
6 ctx->ok(ent.to_str());
7 return;
8 }
9 ctx->error("can not find " + name);
10}
1.1.6.5. scan¶
1template <typename T>
2std::unique_ptr<TableIterator<T>> Table<T>::scan(std::initializer_list<PairType> input)
输入
参数 |
说明 |
---|---|
input |
查询关键字 |
输出
参数 |
说明 |
---|---|
TableIterator |
符合条件的迭代器 |
样例
1DEFINE_METHOD(Anchor, scan) {
2 xchain::Context* ctx = self.context();
3 const std::string& name = ctx->arg("name");
4 const std::string& id = ctx->arg("id");
5 // const std::string& desc = ctx->arg("desc");
6 auto it = self.get_entity().scan({{"id", id},{"name", name}});
7 Anchor::entity ent;
8 int i = 0;
9 std::map<std::string, bool> kv;
10 while(it->next()) {
11 if (it->get(&ent)) {
12 /*
13 std::cout << "id: " << ent.id()<< std::endl;
14 std::cout << "name: " << ent.name()<< std::endl;
15 std::cout << "desc: " << ent.desc()<< std::endl;
16 */
17 if (kv.find(ent.name()) != kv.end()) {
18 ctx->error("find duplicated key");
19 return;
20 }
21 kv[ent.name()] = true;
22 i += 1;
23 } else {
24 std::cout << "get error" << std::endl;
25 }
26 }
27 std::cout << i << std::endl;
28 if (it->error()) {
29 std::cout << it->error(true) << std::endl;
30 }
31 ctx->ok(std::to_string(i));
32}
1.1.6.6. del¶
1template <typename T>
2bool Table<T>::del(T t)
输入
参数 |
说明 |
---|---|
t |
一个数据项 |
输出
参数 |
说明 |
---|---|
true |
删除成功 |
false |
删除失败 |
样例
1DEFINE_METHOD(Anchor, del) {
2 xchain::Context* ctx = self.context();
3 const std::string& id= ctx->arg("id");
4 const std::string& name = ctx->arg("name");
5 const std::string& desc = ctx->arg("desc");
6 Anchor::entity ent;
7 ent.set_id(std::stoll(id));
8 ent.set_name(name.c_str());
9 ent.set_desc(desc);
10 self.get_entity().del(ent);
11 ctx->ok("done");
12}
1.1.7. 在合约中使用 JSON¶
XuperChain SDK 包含了 json 相关的库,可以在合约中方便地使用 json 进行序列化和反序列化。 在合约中使用 json 的例子如下
#include "xchain/json/json.h"
#include "xchain/xchain.h"
struct Features : xchain::Contract {
};
DEFINE_METHOD(Features, json_load_dump) {
xchain::Context *ctx = self.context();
const std::string v = ctx->arg("value");
auto j = xchain::json::parse(v);
ctx->ok(j.dump());
}
DEFINE_METHOD(Features, json_literal) {
xchain::Context *ctx = self.context();
xchain::json j = {
{"int", 3},
{"float", 3.14},
{"string", "hello"},
{"array", {"hello", "world"}},
{"object", {{"key", "value"}}},
{"true", true},
{"false", false},
{"null", nullptr},
};
ctx->ok(j.dump());
}
关于 json 库更多的内容可以查看 文档
1.2. Go接口API¶
1.2.1. GetObject¶
func GetObject(key []byte) ([]byte, error)
输入
参数 |
说明 |
---|---|
key |
查询的key值 |
输出
参数 |
说明 |
---|---|
value, nil |
key值查询成功,返回value值 |
_, 非nil |
key值不存在 |
1.2.2. PutObject¶
func PutObject(key []byte, value []byte) error
输入
参数 |
说明 |
---|---|
key |
存入的key值 |
value |
存入key值对应的value值 |
输出
参数 |
说明 |
---|---|
nil |
存入db成功 |
非nil |
存入db失败 |
1.2.3. DeleteObject¶
func DeleteObject(key []byte) error
输入
参数 |
说明 |
---|---|
key |
将要删除的key值 |
输出
参数 |
说明 |
---|---|
nil |
删除成功 |
非nil |
删除失败 |
1.2.4. QueryTx¶
func QueryTx(txid string) (*pb.Transaction, error)
输入
参数 |
说明 |
---|---|
txid |
待查询的txid |
输出
参数 |
说明 |
---|---|
tx, nil |
查询交易成功, 得到此txid的transaction |
_, 非nil |
查询交易失败 |
1.2.5. QueryBlock¶
func QueryBlock(blockid string) (*pb.Block, error)
输入
参数 |
说明 |
---|---|
blockid |
待查询的blockid |
输出
参数 |
说明 |
---|---|
block, nil |
查询block成功, 得到此blockid的block |
_, 非nil |
查询block失败 |
1.2.6. NewIterator¶
func NewIterator(start, limit []byte) Iterator
输入
参数 |
说明 |
---|---|
start |
初始关键字 |
limit |
结束关键字 |
输出
参数 |
说明 |
---|---|
Iterator |
Interator的接口 |
样例
1Key() []byte
2Value() []byte
3Next() bool
4Error() error
5// Iterator 必须在使用完毕后关闭
6Close()
1.3. Java接口API¶
1.3.1. getObject¶
键值获取
public byte[] getObject(byte[] key)
输入
参数 |
说明 |
---|---|
key |
查询的key值 |
输出
参数 |
说明 |
---|---|
value |
key值查询成功,返回value值;为null时,查询失败 |
1.3.2. putObject¶
键值存储
public void putObject(byte[] key, byte[] value)
输入
参数 |
说明 |
---|---|
key |
存入的key值 |
value |
存入key值对应的value值 |
输出
参数 |
说明 |
---|---|
void |
操作失败时,可捕捉异常;否则,成功 |
1.3.3. deleteObject¶
键值删除
public void deleteObject(byte[] key)
输入
参数 |
说明 |
---|---|
key |
将要删除的key值 |
输出
参数 |
说明 |
---|---|
void |
操作失败时,可捕捉异常;否则,成功 |
1.3.4. queryTx¶
交易查询
public Contract.Transaction queryTx(String txid)
输入
参数 |
说明 |
---|---|
txid |
待查询的txid |
输出
参数 |
说明 |
---|---|
tx |
查询交易成功, 得到此txid的transaction;查询失败,抛出异常 |
1.3.5. queryBlock¶
区块查询
public Contract.Block queryBlock(String blockid)
输入
参数 |
说明 |
---|---|
blockid |
待查询的blockid |
输出
1.3.6. newIterator¶
迭代器
public Iterator<ContractIteratorItem> newIterator(byte[] start, byte[] limit)
输入
参数 |
说明 |
---|---|
start |
初始关键字 |
limit |
结束关键字 |
输出
参数 |
说明 |
---|---|
Iterator |
Interator的接口 |
样例
1@ContractMethod
2public Response getList(Context ctx) {
3 byte[] start = ctx.args().get("start");
4 if (start == null) {
5 return Response.error("missing start");
6 }
7
8 byte[] limit = PrefixRange.generateLimit(start);
9 Iterator<ContractIteratorItem> iter = ctx.newIterator(start, limit);
10 int i = 0;
11 while (iter.hasNext()) {
12 ContractIteratorItem item = iter.next();
13 String key = bytesToString(item.getKey());
14 String value = bytesToString(item.getValue());
15 ctx.log("item: " + i + ", key: " + key + ", value: " + value);
16 i++;
17 }
18
19 return Response.ok("ok".getBytes());
20}
1.3.7. transfer¶
从合约向其他地址转账
public void transfer(String to, BigInteger amount)
输入
参数 |
说明 |
---|---|
to |
收款地址 |
amount |
数量 |
输出
1.3.8. transferAmount¶
调用合约方法向合约转账时,获取转账的数量
public BigInteger transferAmount()
输入
无
输出
参数 |
说明 |
---|---|
BigInteger |
数量 |
1.3.9. call¶
跨合约调用
public Response call(String module, String contract, String method, Map<String, byte[]> args)
输入
参数 |
说明 |
---|---|
module |
模块名 |
contract |
合约名 |
method |
合约方法 |
args |
合约参数 |
输出
参数 |
说明 |
---|---|
Response |
合约返回值 |
1.3.10. crossQuery¶
跨链查询
public Response crossQuery(String uri, Map<String, byte[]> args)
输入
参数 |
说明 |
---|---|
uri |
跨链路由地址 |
args |
合约参数 |
输出
参数 |
说明 |
---|---|
Response |
合约返回值 |