bdcontract-doc/source/markdown_BDWare/YJSAPI.md
2021-09-25 01:43:11 +08:00

25 KiB
Raw Blame History

YJS SDK

YJS Build-in API

内置对象 Global

内置对象 requester

该内置对象在export function里面会有值仅当合约调用签名验证通过。

执行合约 executeContract

参数:

action:executeContract; 
contractID:合约的id或名称均可
operation:调用合约的方法名;
arg: 参数格式为JSON字符串有action与arg两个字段。

可选参数:

requestID:字符串类型自行生成用于查询hash

使用示例:


 function testExecutorContract(arg){
    var ret = JSON.parse(executeContract("ElemeProvider","queryDB",arg));
    if (ret.status == "Success"){
      return JSON.parse(ret.result);
    }else return null;
  }

订阅事件主题 subscribe

参数

contractID字符串类型 合约id或名称均可。
event字符串类型
handler方法名该方法必须接受Event内含字段topic和content类型的唯一变量为参数可以不是export方法

使用示例:

export function init(arg) {
    YancloudUtil.subscribe("topic", handler);
    print("Handler: " + handler);
}

function handler(e) {
    print("topic: " + e.topic);
    print("content: " + e.content);
}

发布事件 pubEvent

参数

topic字符串类型发布的事件主题
content字符串类型发布的事件内容

使用示例:

export function pub1(arg) {
    YancloudUtil.pubEvent("topic", arg);
    return "done";
}

也可以在合约开头定义事件,则事件名即为事件主题,此时可直接使用事件作为方法名发布事件

event topic;
export function pub2(arg) {
    topic(arg);
    return "done";
}

该写法与上面的pub1等价。

访问资源文件

通过Global.Resources去加载ypk内部的资源文件。

loadAsInputStream

参数:

path字符串类型 需要加载文件的地址

使用示例:

var file = Global.Resources.loadAsInputStream("/deleteit.txt");

loadAsScanner

参数:

path字符串类型 需要加载文件的地址

使用示例:

var scanner = Global.Resources.loadAsScanner("/local.txt");

YJS Build-in Annotation

@Access

设置合约的调用是否需要签名,这里分为两种,需签名和无签名。 其中,"verified"表示需要签名。其他则表示无需签名。

@Access("verified")
export function easy(arg){
    return "true";
}

@LogType

LogType注解通过参数的方式声明合约或函数的需要记录的日志类型。

其中Arg表示日志中记录合约执行的参数Result表示记录合约执行的返回结果Branch表示记录合约执行分支。

例如 通过如下LogType注解来声明函数

@LogType("Arg","Result","Branch")
export function easy(arg){
    Global.a = "a";
    Global.b = "b";
    if(arg > 0)
        return Global.a;
    else
        return Global.b;
}

@LogLocation

该注解可以修饰contractfunction。 设置日志存储的位置。参数中指定为“dataware”则存储在账本和本地如果没有指定为“dataware”则仅存储在本地。 例如通过如下LogLocation设置存储位置。

在BaaS平台中可以指定账本名称BaaS平台默认账本为default,使用 @LogLocation("bdledger:default")。如想保存到自定义的账本,比如,"abc"账本,就使用 @LogLocation("bdledger:abc")

@LogLocation("dataware")
export function easy(arg){
    Global.a = "a";
}

@Permission

该注解只能修饰contract 设置合约中调用的工具类的权限包括File、Http、MySQL、MongoDB、RocksDB等工具类。如果合约中用到了以上工具类需要在注解中添加对应的授权字段默认只有YJS自带的YancloudUtil;如果没有添加则会抛出"未授权工具类"的异常。 这6种工具类的详细说明在本小节后续中有说明。

@Permission("Http","File")
contract HttpPermission {
    export function main(args){
        var http=HttpUtil.httpGet(args);
        var dir="adf/adfas/";
        var file=FileUtil.getDir(dir);
        return YancloudUtil.currentTimeMillis();
    }
}

@Description

该注解可以修饰contractfunction。 传入合约及函数的简介可用于生成说明文档中关于exported函数的介绍。

@Description("返回数据条目,无需参数")
export function count(args){
    var  sql = "select count(*) from data;";
    var conn = getConn();
    var statement = conn.createStatement();
    var resultSet = statement.executeQuery(sql);
    var c = {};
    resultSet.next();
    c.count = resultSet.getLong(1);
    return JSON.stringify(c);
}

@Param

该注解可以修饰function。 提供调用函数的参数示例,也为生成说明文档中的返回结果提供默认参数。

@Param({"offset":0,"count":100})
export function get(args){
    var offset = args.offset;
    var count = args.count;
    ...
}

@MockTemplate

该注解可以修饰function。 提供函数的返回模拟数据模板,用于描述返回值的格式.若加此注解在debug方式调用时返回按照此格式生成的模拟数据。

####支持的字段类型

@integer
@string
@boolean
@date
@time
@datatime
/[a-z][A-Z][0-9]/    (正则表达式)
……
详细格式可以参考http://mockjs.com/examples.html

####注意:模板的格式为{result:模板}

//返回一个1-100之间的整数
@MockTemplate({'result|1-100':1})
//返回
{'result':76}

//返回一个1-5个数的数组
@MockTemplate({'result|1-5':[{'value|1-100':1}]})
//返回
{"result":[{"value":34},{"value":8},{"value":48},{"value":50},{"value":43}]}

//返回一个对象包含如下字段
@MockTemplate({'result':{'id':'@integer','email':'@email','password':'@string','name':'@name'}})
//返回
{"password":"3ZLc","name":"William Young","id":36097783842688,"email":"d.fuunwe@gqnr.to"}


//返回元素个数为1-5个之间的一个数组数组的每个元素都是上述格式的一个对象
{'result|1-5':[{'id':'@integer','email':'@email','password':'@string','name':'@name'}]}
//返回
[
  {"password":"dO]wW","name":"Jeffrey Lopez","id":1783453207480410,"email":"a.ckokgxrga@hgiesugi.bb"},
  {"password":"BQYRL","name":"Brian Moore","id":4310212972071102,"email":"k.lbpxocydrh@msgnjtox.na"},
  {"password":"Gw1","name":"Susan Jackson","id":7766580783668916,"email":"h.zjgusl@htce.cr"}
]
@MockTemplate({'result':{'id':'@integer','email':'@email','password':'@string','name':'@name'}})
export function count(args){
    var  sql = "select count(*) from data;";
    var conn = getConn();
    var statement = conn.createStatement();
    var resultSet = statement.executeQuery(sql);
    var c = {};
    resultSet.next();
    c.count = resultSet.getLong(1);
    return JSON.stringify(c);
}

@Result

该注解可以修饰function。 若没有模拟数据模板,则返回模拟数据时使用该注解的内容 提供函数的返回结果示例,若加此注解则生成说明文档时将直接返回此结果而不使用默认参数调用函数。

@Result(666)
export function count(args){
    var  sql = "select count(*) from data;";
    var conn = getConn();
    var statement = conn.createStatement();
    var resultSet = statement.executeQuery(sql);
    var c = {};
    resultSet.next();
    c.count = resultSet.getLong(1);
    return JSON.stringify(c);
}

IO工具类

概览

IO工具类名称 说明
FileUtil 文件操作相关的类
LedgerUtil 账本操作相关的类
HttpUtil Http接口相关的类
DOIPUtil DoIP相关的类
MySQLUtil 连接mysql数据库
MongoDBUtil MongoDB连接相关的类
RocksDBUtil RocksDB基于本地文件的k-v数据库
BDWareTimeSeriesDBUtil 基于本地文件的时间序列数据库

FileUtil

可以使用@Permission("File")来引入FileUtil对象。

@Permission("File")
contract FileSample {
...
}

该对象支持以下方法:

copyTo

可以复制文件和目录。第一个参数是source第二个参数是destination。

参数
序号 参数 说明
1 src 类型为String
2 dest 类型为String
使用示例
var ret = FileUtil.copyTo("./source.txt","./dest.txt");

getContent

获取文件的文本内容,当文件不存在时,返回undefined

参数
序号 参数 说明
1 path 类型为String
使用示例
var ret = FileUtil.getContent("./source.txt");

getDir

获取文件所在的文件夹名,输入参数为字符串。

参数
序号 参数 说明
1 path 类型为String
使用示例
var ret = FileUtil.getDir("./parent/src.txt");
// ret 为 "./parent/";

getFileName

获取文件名。输入参数为字符串。

参数
序号 参数 说明
1 path 类型为String
使用示例
var ret = FileUtil.getFileName("./parent/src.txt");
// ret 为 "src.txt"

openFileAsPrinter

以PrintStream的形式打开文件。 返回结果是java.io.PrintStream类型。

参数
序号 参数 说明
1 path 文件名类型为String
2 isAppend 类型为boolean表示是否往文件末尾添加
使用示例
var ret = FileUtil.openFileAsPrinter("./parent/src.txt",true);
ret.println("hello");
ret.close();

LedgerUtil

可以使用@Permission("Ledger")来引入LedgerUtil对象。

@Permission("Ledger")
contract LedgerExample{
...
}

getClient

获取一个连接客户端,一个参数,为对象类型。 返回结果为LedgerClient类型用于后续的查询账本等操作。

参数
序号 参数 说明
1 address 包含ip和端口两个字段
使用示例
var address = {};
address.ip = "127.0.0.1";
address.port = 18091;
var ledgerClient = LedgerUtil.getClient(address);

queryByHash

根据Hash查询Transaction。 返回结果为对象包含from、to、type和data四个字段均为String类型。 其中data为按utf-8编码解析字节数组如果存证时用的不是utf8编码可能返回乱码。

参数
序号 参数 说明
1 client 通过getClient方法获得的对象
2 info 对象类型有两个字段ledger和hash均为字符串类型
使用示例
// ... ledgerClient = LedgerUtil.getClient(...);
var info = {};
info.ledger = "bdcontract";
info.hash = "4d3b75750835092a50085127702669615b602e53";
var ret = LedgerUtil.queryByHash(ledgerClient,info);
print(ret.from);
print(ret.to);
print(ret.type);
print(ret.data);

sendTransaction

存证数据。

参数
序号 参数 说明
1 client 通过getClient方法获得的对象
2 info 对象类型有from\to\data三个字段均为String类型
使用示例
// ... ledgerClient = LedgerUtil.getClient(...);
var info = {};
info.ledger = "bdcontract";
info.from = "b60e8dd61c5d32be8058bb8eb970870f07233155";
info.to = "b60e8dd61c5d32be8058bb8eb970870f07233155";
info.data = "hello world";
var ret = LedgerUtil.sendTransaction(ledgerClient,info);
//ret为存证的哈希值
print(ret);

HttpUtil

可以使用@Permission("Http")来引入HttpUtil对象。

@Permission("Http")
contract HttpExample{
...
}

createAPIGate

配合手机的元邦使用当手机安装元邦且安装了API 接口后,可成为数据来源。

参数
序号 参数 说明
1 ip 字符串类型ip端口默认为6161
使用示例
var ret = HttpUtil.createAPIGate("192.168.4.4");
ret.get("com.tencent.mm","sendMsg","msg");
print(ret);

createAPIGate

配合手机的元邦使用当手机安装元邦且安装了API 接口后,可成为数据来源。

参数
序号 参数 说明
1 ip 字符串类型ip
2 port 字符串类型,端口
使用示例
var ret = HttpUtil.createAPIGate("192.168.4.4", "6161");
ret.get("com.tencent.mm","sendMsg","msg");
print(ret);

get

发起Http的get请求。 返回结果为对象类型包含response和responseCode两个字段。

参数
序号 参数 说明
1 url 字符串表示url类型
使用示例
var ret = HttpUtil.get("https://www.baidu.com");
print(ret.responseCode);
print(ret.response);

post

发起Http的post请求。 返回结果为对象类型包含response和responseCode两个字段。

参数
序号 参数 说明
1 args 对象类型有urlheaders和data三个字段。其中args.headers为对象类型。
使用示例
var req = {};
req.url = "https://www.baidu.com";
req.data = "hello";
req.header = {};
req.header.Accept = "application/json";
req.header["Content-Type"] = "application/json";
var ret = HttpUtil.post(req);
print(ret.resposeCode);
print(ret.response);

DOIPUtil

可以使用@Permission("DOIP")来引入DOIPUtil对象。

@Permission("DOIP")
contract DOIPExample{
  ...
}

call

调用一个DO

参数
序号 参数 说明
1 arg0 字符串类型, 目标DO标识
2 arg1 字符串类型, 输入参数字符串
使用示例
var ret = DOIPUtil.call("86.5000.470/do.hello","inputString");

create

向一个Repository创建一个字符串类型DO

参数
序号 参数 说明
1 arg0 字符串类型, 目标Repo标识
2 arg1 对象类型,包括doID,doBody字段
使用示例
var digitalObject = JSON.parse("{\"doID\":\"86.5000.470/do.hello\",\"doBody\":\"hello world\"}");
var ret = DOIPUtil.create("86.5000.470/repo.localTcpRepo",digitalObject);

delete

从一个Repository中删除DO

参数
序号 参数 说明
1 arg0 字符串类型 目标DO标识
2 arg1 字符串类型 目标Repo标识
使用示例
var ret = DOIPUtil.delete("86.5000.470/do.hello","86.5000.470/repo.localTcpRepo");

hello

获取目标Repository的DOIP服务信息

参数
序号 参数 说明
1 arg0 字符串类型 目标Repo标识
使用示例
var ret = DOIPUtil.hello("86.5000.470/repo.localTcpRepo");

listOperation

获取目标DO支持的DOIP操作

参数
序号 参数 说明
1 arg0 字符串类型 目标DO标识
使用示例
var ret = DOIPUtil.listOperation("86.5000.470/do.hello");

register

向LHS注册一个DO返回分配的标识

参数
序号 参数 说明
1 arg0 字符串类型 DO所在Repo标识
2 arg1 字符串类型 DO格式描述字符串
使用示例
var ret = DOIPUtil.register("86.5000.470/repo.localTcpRepo","String");

reregister

修改LHS中DO的注册信息

参数
序号 参数 说明
1 arg0 字符串类型 目标DO标识
2 arg1 字符串类型 DO所在Repo标识
3 arg2 字符串类型 DO格式描述字符串
使用示例
var ret = DOIPUtil.reregister("86.5000.470/do.hello","86.5000.470/repo.localTcpRepo","String");

retrieve

获取一个DO

参数
序号 参数 说明
1 arg0 字符串类型 目标DO标识
使用示例
var ret = DOIPUtil.retrieve("86.5000.470/do.hello");

test

测试DOIPUtils是否可用

参数
序号 参数 说明
1 arg0 字符串类型 任意字符串
使用示例
var ret = DOIPUtil.test("hello");

update

更新目标DO

参数
序号 参数 说明
1 arg0 JS对象,包括doID,doBody字段
使用示例
var digitalObject = JSON.parse("{\"doID\":\"86.5000.470/do.hello\",\"doBody\":\"hello world\"}");
var ret = DOIPUtil.update(digitalObject);

MySQLUtil

可以使用@Permission("MySQL")来引入MySQLUtil对象。

@Permission("MySQL")
contract MySQLExample{
...
}

getConnection

参数
序号 参数 说明
1 URL 字符串类型jdbc连接
2 usrName 字符串类型,用户名
3 pwd 字符串类型,密码
使用示例
var url = "jdbc:mysql://xx.xx.xx:port/tableName";
var usrName = "xxx";
var pwd = "xxx";
//配置好用户名和密码url格式为ip或域名+端口,中间以”:”隔开。
var conn = MySQLUtil.getConnection(url,usrName,pwd);
//获取数据库连接
var sql = "select * from newele.data";
//创建查询语句
var statement = conn.createStatement();
var resultSet = statement.executeQuery(sql);
var waimailist  = [];
//解析查询结果
var meta = resultSet.getMetaData();
for (;resultSet.next();){
  var line = {};
  for (var j=1;j<=meta.getColumnCount();j++){
    line[meta.getColumnName(j)] = resultSet.getString(j);
  }
	waimailist.push(line);
}

其中getConnection方法返回的对象通过反射机制绑定到了Java的一个java.util.Connection对象。因此可以查看 https://docs.oracle.com/javase/7/docs/api/java/sql/Connection.html 以了解如何进行Mysql数据库操作。

MongoDBUtil

可以使用@Permission("MongoDB")来引入MongoDBUtil对象。

@Permission("MongoDB")
contract MongoDBExample{
...
}

getConnection

参数
序号 参数 说明
1 URL 字符串类型 数据库的URL
2 port 整数类型 端口号
3 dbName 字符串类型 数据库的名称
4 usrName 字符串类型 数据库的用户名
5 pwd 字符串类型 数据库的密码
使用示例

注意port为整型其他参数为String类型

var client = MongoDBUtil.getConnection(url,port,dbName,usrName,pwd);
//获取数据库对象
var db = client.getDatabase("yancloud");
var collection = db.getCollection("containers");
var iter = collection.find().iterator();
var ret ="";
for (;iter.hasNext();){
	ret+=iter.next().toJson();
	ret+="\n";
}

其中getMongoDBClient对象通过反射机制绑定到了Java的一个com.mongodb.MongoClient对象。因此可以查看 https://mongodb.github.io/mongo-java-driver/3.4/javadoc/com/mongodb/MongoClient.html

以了解该对象的更多方法和使用方式。

RocksDBUtil

使用@Permission("RocksDB")来引入RocksDBUtil对象。

@Permission("RocksDB")
contract RocksDBSample {
...
}

loadDB

通过loadDB来加载一个RocksDB数据库。 加载后可进行get/delete/put等操作。

参数
序号 参数 说明
1 path 字符串类型 数据库部署的路径
2 readOnly 布尔类型 数据库只读
使用示例
@Permission("RocksDB")
@Description("这是个使用RocksDB的参考代码")
contract RocksDBSample{
  function onCreate(){
    Global.rocksdb = RocksDBUtil.loadDB("./dbdir/","false");
  }
  @Description("示例参数: {\"key\":\"abc\",\"value\":\"def\"}")
  export function put(arg){
    arg = JSON.parse(arg);
    Global.rocksdb.put(arg.key,arg.value);
    return "success";
  }
  @Description("示例参数: \"abc\"}")
  export function get(arg){
    return Global.rocksdb.get(arg);
    return "failed";
  }
  @Description("示例参数: \"abc\"")
  export function deleteKey(arg){
    return Global.rocksdb.delete(arg);
  }
  @Description("遍历KV库无需参数")
  export function iter(arg){
    var iter = Global.rocksdb.newIterator();
    var obj = undefined;
    var ret = {
    };
    for (iter.seekToFirst();(obj=Global.rocksdb.getNext(iter))!=undefined;){
      ret[obj.key]=obj.value;
    }
    return JSON.stringify(ret)
  }
}

BDWareTimeSeriesDBUtil

使用示例

@Permission("BDWareTimeSeriesDB")
contract BDWareTimeDBExample{
  function onCreate(arg){
    Global.dbutil = BDWareTimeSeriesDBUtil.getConnection();
  }

  export function put(arg){
    //第一个参数为表名第二个参数为要放的value时间戳自动打。
    Global.dbutil.put("defaultTable",arg);
    return "success";
  }
  @Param
  export function getCount(arg){
    return Global.dbutil.getCount("defaultTable");
  }
  @Param(1617254937373)
  export function queryByStartTime(arg){
    var startDate = java.lang.Long.valueOf(arg);
    //查询从开始时刻startDate到最新的数据
    var list = Global.dbutil.query("defaultTable",startDate);
    var ret=[];
    print("DBUtil"+Global.dbutil+" list:"+list+" list.size"+list.size());
    var i=0;
    for (i=0;i<list.size();i++){
      print(i+"-->"+list.get(i));
      ret.push(list.get(i));
    }
    return ret;
  }
  
  @Description("示例参数: {\"offset\":1,\"len\":1}")
  @Param({"offset":1,"len":1})
  export function queryByOffset(arg){
    var offsetLen = JSON.parse(arg);
    //可配合getCount使用查询第offset至offset+len条数据
    var list = Global.dbutil.queryByOffset("defaultTable",offsetLen.offset,offsetLen.len);
    var ret=[];
    print("DBUtil"+Global.dbutil+" list:"+list+" list.size"+list.size());
    var i=0;
    for (i=0;i<list.size();i++){
      print(i+"-->"+list.get(i));
      ret.push(list.get(i));
    }
    return ret;
  }
}

加解密工具类

SM2

可以使用@Permission("SM2")来引入SM2Util对象。

@Permission("SM2")
contract SM2Sample {
...
}

generateKeyPair

生成公私钥。

参数

无参数。

使用示例
var ret = SM2Util.generateKeyPair();
print(ret.publicKey);
print(ret.privateKey);
return JSON.stringify(ret);

sign

签名。

参数
序号 参数 说明
1 content 字符串类型 要进行签名的内容
2 keyPair sm2
使用示例
var keypair = SM2Util.generateKeyPair();
var ret = SM2Util.sign("Hello",keypair);
print(ret.status);
//如果status是success
print(ret.signature);
//如果status是failed
print(ret.message);

verify

验签。

参数
序号 参数 说明
1 content 字符串类型 待验签的内容
2 signature 字符串类型 签名
3 publicKey 字符串类型 公钥
使用示例
var ret = SM2Util.verify("Hello","....签名","...公钥");
// 验证通过时result为truestatus为success
// 失败时result为failedstatus为failed
print(ret.status);
print(ret.result);

多线程工具类

AsyncUtil

可以使用@Permission("Async")来引入AsyncUtil对象。

@Permission("Async")
contract AsyncExample{
  export function longTimeTask(arg){
    var a = {
    };
    a.count = 100;
    AsyncUtil.postFunction(taskFun,a);
  }
  function taskFun(arg){
    Global.progress = 0;
    for (var i=0;i<arg.count;i++){
      AsyncUtil.sleep(100);
      Global.progress++;
    }
  }
  export function getProgress(arg){
    return Global.progress;
  }
}

postFunction

参数
序号 参数 说明
1 arg0 ScriptFunction
2 arg1 对象
使用示例
var ret = AsyncUtil.postFunction(a,{"a":"b"});

setInterval

参数
序号 参数 说明
1 arg0 ScriptFunction
2 arg1 long
3 arg2 long
4 arg3 对象
使用示例
var ret = AsyncUtil.setInterval(a,100,1000,"abc");

setTimeOut

参数
序号 参数 说明
1 arg0 ScriptFunction
2 arg1 long
3 arg2 Object
使用示例
var ret = AsyncUtil.setTimeOut(a,100,"abc");

sleep

参数
序号 参数 说明
1 arg0 long
使用示例
var ret = AsyncUtil.sleep();

ECMA5 Build-in Objects

YJS支持ECMAScript6的部分内置对象