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等价。

发布带语义事件 pubEventConstraint

参数

topic:字符串类型,发布的事件主题
content:字符串类型,发布的事件内容
semantics:枚举类型,作为字符串输入,事件语义

事件语义参数 + AT_LEAST_ONCE:至少一次,默认语义 + AT_MOST_ONCE:至多一次 + ONLY_ONCE:只有一次

使用示例:

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

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

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

该写法与上面的pub1等价。

事先声明的事件无论是否声明语义,都可以用后缀s作为方法名的方式调用,发布任意语义的事件:

event topic;
export function pub3(arg) {
    topics(arg, "AT_MOST_ONCE");
    return "done";
}

该写法与上面的pub1, pub2等价。

不带事件语义声明事件时,语义默认为至少一次(AT_LEAST_ONCE)。

访问资源文件

通过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
@word 单词  @cword 中文单词
@first @last 英文姓,名
@cfirst @clast @cname 中文姓,名,全名
@url @domin @ip @email
@region @province @city @county 地区,省,市,县
……
详细格式可以参考http://mockjs.com/examples.html

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

//返回一个对象包含如下字段
@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:raw-latex:to:raw-latex:`\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

对象类型,有url,headers和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);

SQLUtil

可以使用@Permission(“SQL”)来引入SQLUtil对象。 可支持MySQL/PostgreSQL/Oracle/GuassDB200等SQL数据库。 需要将对应的jdbc的jar上传到项目中。 例如,要使用mysql,可上传mysql-connector-java-8.0.24.jar

@Permission("SQL")
oracle MySQLExample{
...
}

initDriver

参数

序号

参数

说明

1

driverClass

字符串类型

使用示例
//使用mysql
SQLUtil.initDriver("com.mysql.cj.jdbc.Driver");
//使用postgresql
SQLUtil.initDriver("org.postgresql.Driver");
//使用oracle
SQLUtil.initDriver("oracle.jdbc.OracleDriver");

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 = SQLUtil.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为true,status为success
// 失败时,result为failed,status为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();

YJS应用框架

加载流程

函数约定(getMainFrame)

前端函数说明

executeCurrentContract/….. 如何loadScript/loadCss..

后端函数约定

getMainFrame