2.4. 合约 SDK 使用说明

XuperChain 针对不同语言合约开发了合约 SDK,为用户封装链上能力的访问。

当前提供支持使用C++,GO 或着 JAVA 进行进行智能合约开发。

本文档对C++ 合约编程接口做简要说明,GO 合约文档参考 go 合约 SDK 注释 , JAVA 合约文档参考 JAVA 合约SDK注释

2.4.1. C++接口 API

  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. put_object

bool ContextImpl::put_object(const std::string& key, const std::string& value)

输入

参数

说明

key

存入的key值

value

存入key值对应的value值

输出

参数

说明

true

存入db成功

false

存入db失败

  1. delete_object

bool ContextImpl::delete_object(const std::string& key)

输入

参数

说明

key

将要删除的key值

输出

参数

说明

true

删除成功

false

删除失败

  1. 迭代器

std::unique_ptr<Iterator> new_iterator(const std::string& start, const std::string& limit)

输入

迭代器

参数

含义

start

迭代器起始值

limit

迭代器终止值

输出

返回标准迭代器接口 Iterator

  1. 合约调用者
  • 获取合约调用的发起者

const std::string& initiator() const 输入

输出

合约调用的发起者

  • 获取合约的直接调用者

Account& sender()

输入

输出

合约调用者的地址,在跨合约调用中是上一级调用者

  1. 合约权限控制信息
  • int auth_require_size() const

需要获取鉴权账号的数量

  • const std::string& auth_require(int idx) const

第 idx 个需要参与鉴权的账号

4. 跨合约调用 bool call(const std::string& module, const std::string& contract,

const std::string& method, const std::map<std::string, std::string>& args, Response* response);

跨合约调用

参数

含义

module

调用的模块

contract

调用的合约名

method

调用的合约方法

args

合约调用参数

response

合约调用的返回值

  1. 合约日志

void logf(const char* fmt, …);

以格式化的方式打印字符串,格式化方式类似 printf

8. 合约事件 bool emit_event(const std::string& name, const std::string& body)

触发一个合约事件,name 是事件名称,body 是事件的描述

  1. query_tx

bool ContextImpl::query_tx(const std::string &txid, Transaction* tx)

输入

参数

说明

txid

待查询的txid

tx

得到此txid的transaction

输出

参数

说明

true

查询交易成功

false

查询交易失败

  1. query_block

bool ContextImpl::query_block(const std::string &blockid, Block* block)

输入

参数

说明

blockid

待查询的blockid

block

得到此blockid的block

输出

参数

说明

true

查询block成功

false

查询block失败

  1. 在合约中使用 table
  • 定义表格

    1. 1// 表格定义以proto形式建立,存放目录为contractsdk/cpp/pb
    2. 2syntax = "proto3";
    3. 3option optimize_for = LITE_RUNTIME;
    4. 4package anchor;
    5. 5message Entity {
    6. 6 int64 id = 1;
    7. 7 string name = 2;
    8. 8 bytes desc = 3;
    9. 9}
    10. 10// table名称为Entity,属性分别为id,name,desc
  • 初始化表格

    1. 1// 定义表格的主键,表格的索引
    2. 2struct entity: public anchor::Entity {
    3. 3 DEFINE_ROWKEY(name);
    4. 4 DEFINE_INDEX_BEGIN(2)
    5. 5 DEFINE_INDEX_ADD(0, id, name)
    6. 6 DEFINE_INDEX_ADD(1, name, desc)
    7. 7 DEFINE_INDEX_END();
    8. 8};
    9. 9// 声明表格
    10. 10xchain::cdt::Table<entity> _entity;
  • put

    1. 1template <typename T>
    2. 2bool Table<T>::put(T t)

    输入

    参数

    说明

    t

    待插入的数据项

    输出

    参数

    说明

    true

    插入成功

    false

    插入失败

    样例

    1. 1// 参考样例 contractsdk/cpp/example/anchor.cc
    2. 2DEFINE_METHOD(Anchor, set) {
    3. 3 xchain::Context* ctx = self.context();
    4. 4 const std::string& id= ctx->arg("id");
    5. 5 const std::string& name = ctx->arg("name");
    6. 6 const std::string& desc = ctx->arg("desc");
    7. 7 Anchor::entity ent;
    8. 8 ent.set_id(std::stoll(id));
    9. 9 ent.set_name(name.c_str());
    10. 10 ent.set_desc(desc);
    11. 11 self.get_entity().put(ent);
    12. 12 ctx->ok("done");
    13. 13}
  • find

    1. 1template <typename T>
    2. 2bool Table<T>::find(std::initializer_list<PairType> input, T* t)

    输入

    参数

    说明

    input

    查询关键字

    t

    返回的数据项

    输出

    参数

    说明

    true

    查询成功

    false

    查询失败

    样例

    1. 1DEFINE_METHOD(Anchor, get) {
    2. 2 xchain::Context* ctx = self.context();
    3. 3 const std::string& name = ctx->arg("key");
    4. 4 Anchor::entity ent;
    5. 5 if (self.get_entity().find({{"name", name}}, &ent)) {
    6. 6 ctx->ok(ent.to_str());
    7. 7 return;
    8. 8 }
    9. 9 ctx->error("can not find " + name);
    10. 10}
  • scan

    1. 1template <typename T>
    2. 2std::unique_ptr<TableIterator<T>> Table<T>::scan(std::initializer_list<PairType> input)

    输入

    参数

    说明

    input

    查询关键字

    输出

    参数

    说明

    TableIterator

    符合条件的迭代器

    样例

    1. 1DEFINE_METHOD(Anchor, scan) {
    2. 2 xchain::Context* ctx = self.context();
    3. 3 const std::string& name = ctx->arg("name");
    4. 4 const std::string& id = ctx->arg("id");
    5. 5 // const std::string& desc = ctx->arg("desc");
    6. 6 auto it = self.get_entity().scan({{"id", id},{"name", name}});
    7. 7 Anchor::entity ent;
    8. 8 int i = 0;
    9. 9 std::map<std::string, bool> kv;
    10. 10 while(it->next()) {
    11. 11 if (it->get(&ent)) {
    12. 12 /*
    13. 13 std::cout << "id: " << ent.id()<< std::endl;
    14. 14 std::cout << "name: " << ent.name()<< std::endl;
    15. 15 std::cout << "desc: " << ent.desc()<< std::endl;
    16. 16 */
    17. 17 if (kv.find(ent.name()) != kv.end()) {
    18. 18 ctx->error("find duplicated key");
    19. 19 return;
    20. 20 }
    21. 21 kv[ent.name()] = true;
    22. 22 i += 1;
    23. 23 } else {
    24. 24 std::cout << "get error" << std::endl;
    25. 25 }
    26. 26 }
    27. 27 std::cout << i << std::endl;
    28. 28 if (it->error()) {
    29. 29 std::cout << it->error(true) << std::endl;
    30. 30 }
    31. 31 ctx->ok(std::to_string(i));
    32. 32}
  • del

    1. 1template <typename T>
    2. 2bool Table<T>::del(T t)

    输入

    参数

    说明

    t

    一个数据项

    输出

    参数

    说明

    true

    删除成功

    false

    删除失败

    样例

    1. 1DEFINE_METHOD(Anchor, del) {
    2. 2 xchain::Context* ctx = self.context();
    3. 3 const std::string& id= ctx->arg("id");
    4. 4 const std::string& name = ctx->arg("name");
    5. 5 const std::string& desc = ctx->arg("desc");
    6. 6 Anchor::entity ent;
    7. 7 ent.set_id(std::stoll(id));
    8. 8 ent.set_name(name.c_str());
    9. 9 ent.set_desc(desc);
    10. 10 self.get_entity().del(ent);
    11. 11 ctx->ok("done");
    12. 12}
  1. 在合约中使用 JSON

XuperChain SDK 包含了 json 相关的库,可以在合约中方便地使用 json 进行序列化和反序列化。

在合约中使用 json 的例子如下

  1. #include "xchain/json/json.h"
  2. #include "xchain/xchain.h"
  3. struct Features : xchain::Contract {
  4. };
  5. DEFINE_METHOD(Features, json_load_dump) {
  6. xchain::Context *ctx = self.context();
  7. const std::string v = ctx->arg("value");
  8. auto j = xchain::json::parse(v);
  9. ctx->ok(j.dump());
  10. }
  11. DEFINE_METHOD(Features, json_literal) {
  12. xchain::Context *ctx = self.context();
  13. xchain::json j = {
  14. {"int", 3},
  15. {"float", 3.14},
  16. {"string", "hello"},
  17. {"array", {"hello", "world"}},
  18. {"object", {{"key", "value"}}},
  19. {"true", true},
  20. {"false", false},
  21. {"null", nullptr},
  22. };
  23. ctx->ok(j.dump());
  24. }

关于 json 库更多的内容可以查看 文档