bdcontract-doc/markdown/markdown_ZRYH/YJSAPI.md

1342 lines
30 KiB
Markdown
Raw Permalink Normal View History

2021-09-24 17:43:11 +00:00
# YJS SDK
## YJS Build-in API
### 内置对象 Global
### 内置对象 requester
该内置对象在export function里面会有值仅当合约调用签名验证通过。
### 执行合约 executeContract
参数:
``` bash
action:executeContract;
contractID:合约的id或名称均可
operation:调用合约的方法名;
arg: 参数格式为JSON字符串有action与arg两个字段。
```
可选参数:
```bash
requestID:字符串类型自行生成用于查询hash
```
使用示例:
```javascript
function testExecutorContract(arg){
var ret = JSON.parse(executeContract("ElemeProvider","queryDB",arg));
if (ret.status == "Success"){
return JSON.parse(ret.result);
}else return null;
}
```
### 订阅事件主题 subscribe
参数
``` bash
contractID字符串类型 合约id或名称均可。
event字符串类型
handler方法名该方法必须接受Event内含字段topic和content类型的唯一变量为参数可以不是export方法
```
使用示例:
```javascript
export function init(arg) {
YancloudUtil.subscribe("topic", handler);
print("Handler: " + handler);
}
function handler(e) {
print("topic: " + e.topic);
print("content: " + e.content);
}
```
### 发布事件 pubEvent
参数
``` bash
topic字符串类型发布的事件主题
content字符串类型发布的事件内容
```
使用示例:
```javascript
export function pub1(arg) {
YancloudUtil.pubEvent("topic", arg);
return "done";
}
```
也可以在合约开头声明事件,则事件名即为事件主题,此时可直接使用事件作为方法名发布事件
```javascript
event topic;
export function pub2(arg) {
topic(arg);
return "done";
}
```
该写法与上面的`pub1`等价。
### 发布带语义事件 pubEventConstraint
参数
``` bash
topic字符串类型发布的事件主题
content字符串类型发布的事件内容
semantics枚举类型作为字符串输入事件语义
```
事件语义参数
+ AT_LEAST_ONCE至少一次默认语义
+ AT_MOST_ONCE至多一次
+ ONLY_ONCE只有一次
使用示例:
```javascript
export function pub1(arg) {
YancloudUtil.pubEventConstraint("topic", arg, "AT_MOST_ONCE");
return "done";
}
```
也可以在合约开头声明事件,则事件名即为事件主题,此时可直接使用事件作为方法名按声明的语义发布事件
```javascript
event AT_MOST_ONCE topic;
export function pub2(arg) {
topic(arg);
return "done";
}
```
该写法与上面的`pub1`等价。
事先声明的事件无论是否声明语义都可以用后缀s作为方法名的方式调用发布任意语义的事件
```javascript
event topic;
export function pub3(arg) {
topics(arg, "AT_MOST_ONCE");
return "done";
}
```
该写法与上面的`pub1, pub2`等价。
*不带事件语义声明事件时语义默认为至少一次AT_LEAST_ONCE。*
### 访问资源文件
通过Global.Resources去加载ypk内部的资源文件。
#### loadAsInputStream
参数:
```bash
path字符串类型 需要加载文件的地址
```
使用示例:
```javascript
var file = Global.Resources.loadAsInputStream("/deleteit.txt");
```
#### loadAsScanner
参数:
```bash
path字符串类型 需要加载文件的地址
```
使用示例:
```javascript
var scanner = Global.Resources.loadAsScanner("/local.txt");
```
### YancloudUtil
提供了一些内置的工具方法。
#### getKeyPair
参数:
```
```
使用示例:
```
var keyPair = YancloudUtil.getKeyPair();
//该类型为SM2KeyPair类型
print(keyPair.getPublicKeyStr());
print(keyPair.getPrivateKeyStr());
print(keyPair.toJson());
```
## 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
该注解可以修饰`contract`或`function`。
设置日志存储的位置。参数中指定为“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
该注解可以修饰`contract`或`function`。
传入合约及函数的简介可用于生成说明文档中关于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:模板}
```json
//返回一个对象包含如下字段
@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);
}
```
### @Cost
该注解可以修饰`function`。
提供函数的cpu计量功能。
```
@Cost({"countGas":true})
export function ....
```
## IO工具类
### 概览
|IO工具类名称|说明|
|---|---|
| [FileUtil](./YJSAPI.html#fileutil) | 文件操作相关的类 |
| [LedgerUtil](./YJSAPI.html#ledgerutil) | 账本操作相关的类 |
| [HttpUtil](./YJSAPI.html#httputil) | Http接口相关的类 |
| [DOIPUtil](./YJSAPI.html#doiputil) | DoIP相关的类 |
| [MySQLUtil](./YJSAPI.html#mysqlutil) | 连接mysql数据库 |
| [MongoDBUtil](./YJSAPI.html#mongodbutil) | MongoDB连接相关的类 |
| [RocksDBUtil](./YJSAPI.html#rocksdbutil) | RocksDB基于本地文件的k-v数据库 |
| [BDWareTimeSeriesDBUtil](./YJSAPI.html#BDWareTimeSeriesDBUtil) | 基于本地文件的时间序列数据库 |
### FileUtil
可以使用@Permission("File")来引入FileUtil对象。
```
@Permission("File")
contract FileSample {
...
}
```
该对象支持以下方法:
#### copyTo
可以复制文件和目录。第一个参数是source第二个参数是destination。
##### 参数
| 序号 | 参数 | 说明 |
|---|---|---|
| 1 | src | 类型为String |
| 2 | dest | 类型为String |
##### 使用示例
```javascript
var ret = FileUtil.copyTo("./source.txt","./dest.txt");
```
#### getContent
获取文件的文本内容,当文件不存在时,返回```undefined```。
##### 参数
| 序号 | 参数 | 说明 |
| --- | --- | --- |
| 1 | path | 类型为String |
##### 使用示例
```javascript
var ret = FileUtil.getContent("./source.txt");
```
#### getDir
获取文件所在的文件夹名,输入参数为字符串。
##### 参数
| 序号 | 参数 | 说明 |
|---|---|---|
| 1 | path | 类型为String |
##### 使用示例
```javascript
var ret = FileUtil.getDir("./parent/src.txt");
// ret 为 "./parent/";
```
#### getFileName
获取文件名。输入参数为字符串。
##### 参数
| 序号 | 参数 | 说明 |
|---|---|---|
| 1 | path | 类型为String |
##### 使用示例
```javascript
var ret = FileUtil.getFileName("./parent/src.txt");
// ret 为 "src.txt"
```
#### openFileAsPrinter
以PrintStream的形式打开文件。
返回结果是```java.io.PrintStream```类型。
##### 参数
| 序号 | 参数 | 说明 |
|---|---|---|
| 1 | path | 文件名类型为String |
| 2 | isAppend| 类型为boolean表示是否往文件末尾添加 |
##### 使用示例
```javascript
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和端口两个字段 |
##### 使用示例
```javascript
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均为字符串类型 |
##### 使用示例
```javascript
// ... 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类型 |
##### 使用示例
```javascript
// ... 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 |
##### 使用示例
```javascript
var ret = HttpUtil.createAPIGate("192.168.4.4");
ret.get("com.tencent.mm","sendMsg","msg");
print(ret);
```
#### createAPIGate
配合手机的元邦使用当手机安装元邦且安装了API 接口后,可成为数据来源。
##### 参数
| 序号 | 参数 | 说明 |
|---|---|---|
| 1 | ip | 字符串类型ip|
| 2 | port | 字符串类型,端口 |
##### 使用示例
```javascript
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类型 |
##### 使用示例
```javascript
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为对象类型。|
##### 使用示例
```javascript
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 | 字符串类型, 输入参数字符串|
##### 使用示例
```javascript
var ret = DOIPUtil.call("86.5000.470/do.hello","inputString");
```
#### create
向一个Repository创建一个字符串类型DO
##### 参数
| 序号 | 参数 | 说明 |
|---|---|---|
| 1 | arg0 | 字符串类型, 目标Repo标识|
| 2 | arg1 | 对象类型,包括doID,doBody字段|
##### 使用示例
```javascript
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标识|
##### 使用示例
```javascript
var ret = DOIPUtil.delete("86.5000.470/do.hello","86.5000.470/repo.localTcpRepo");
```
#### hello
获取目标Repository的DOIP服务信息
##### 参数
| 序号 | 参数 | 说明 |
|---|---|---|
| 1 | arg0 | 字符串类型 目标Repo标识|
##### 使用示例
```javascript
var ret = DOIPUtil.hello("86.5000.470/repo.localTcpRepo");
```
#### listOperation
获取目标DO支持的DOIP操作
##### 参数
| 序号 | 参数 | 说明 |
|---|---|---|
| 1 | arg0 | 字符串类型 目标DO标识|
##### 使用示例
```javascript
var ret = DOIPUtil.listOperation("86.5000.470/do.hello");
```
#### register
向LHS注册一个DO返回分配的标识
##### 参数
| 序号 | 参数 | 说明 |
|---|---|---|
| 1 | arg0 | 字符串类型 DO所在Repo标识|
| 2 | arg1 | 字符串类型 DO格式描述字符串|
##### 使用示例
```javascript
var ret = DOIPUtil.register("86.5000.470/repo.localTcpRepo","String");
```
#### reregister
修改LHS中DO的注册信息
##### 参数
| 序号 | 参数 | 说明 |
|---|---|---|
| 1 | arg0 | 字符串类型 目标DO标识|
| 2 | arg1 | 字符串类型 DO所在Repo标识|
| 3 | arg2 | 字符串类型 DO格式描述字符串|
##### 使用示例
```javascript
var ret = DOIPUtil.reregister("86.5000.470/do.hello","86.5000.470/repo.localTcpRepo","String");
```
#### retrieve
获取一个DO
##### 参数
| 序号 | 参数 | 说明 |
|---|---|---|
| 1 | arg0 | 字符串类型 目标DO标识|
##### 使用示例
```javascript
var ret = DOIPUtil.retrieve("86.5000.470/do.hello");
```
### test
测试DOIPUtils是否可用
##### 参数
| 序号 | 参数 | 说明 |
|---|---|---|
| 1 | arg0 | 字符串类型 任意字符串|
##### 使用示例
```javascript
var ret = DOIPUtil.test("hello");
```
#### update
更新目标DO
##### 参数
| 序号 | 参数 | 说明 |
|---|---|---|
| 1 | arg0 | JS对象,包括doID,doBody字段|
##### 使用示例
```javascript
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 | 字符串类型 |
##### 使用示例
```javascript
//使用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 | 字符串类型,密码 |
##### 使用示例
```javascript
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类型**
```javascript
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
生成公私钥。
##### 参数
无参数。
##### 使用示例
```javascript
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 | 字符串类型 公钥 |
##### 使用示例
```javascript
var ret = SM2Util.verify("Hello","....签名","...公钥");
// 验证通过时result为truestatus为success
// 失败时result为failedstatus为failed
print(ret.status);
print(ret.result);
```
#### encrypt
sm2加密。
##### 参数
| 序号 | 参数 | 说明 |
|---|---|---|
| 1 | content | 字符串类型 待验签的内容 |
| 3 | publicKey | 字符串类型 公钥 |
##### 使用示例
```javascript
var ret = SM2Util.encrypt("Hello","...公钥");
print(ret);
```
#### decrypt
sm2解密。
##### 参数
| 序号 | 参数 | 说明 |
|---|---|---|
| 1 | content | 字符串类型 待验签的内容 |
| 3 | privateKey | 字符串类型 公钥 |
##### 使用示例
```javascript
var ret = SM2Util.decrypt("Hello","...私钥");
print(ret);
```
## 多线程工具类
### 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 | 对象 |
##### 使用示例
```javascript
var ret = AsyncUtil.postFunction(a,{"a":"b"});
```
#### setInterval
##### 参数
| 序号 | 参数 | 说明 |
|---|---|---|
| 1 | arg0 | ScriptFunction |
| 2 | arg1 | long |
| 3 | arg2 | long |
| 4 | arg3 | 对象 |
##### 使用示例
```javascript
var ret = AsyncUtil.setInterval(a,100,1000,"abc");
```
#### setTimeOut
##### 参数
| 序号 | 参数 | 说明 |
|---|---|---|
| 1 | arg0 | ScriptFunction |
| 2 | arg1 | long |
| 3 | arg2 | Object |
##### 使用示例
```javascript
var ret = AsyncUtil.setTimeOut(a,100,"abc");
```
#### sleep
##### 参数
| 序号 | 参数 | 说明 |
|---|---|---|
| 1 | arg0 | long |
##### 使用示例
```javascript
var ret = AsyncUtil.sleep();
```
## ECMA5 Build-in Objects
YJS支持ECMAScript6的部分内置对象
* String <https://www.w3schools.com/js/js_strings.asp>
* Number <https://www.w3schools.com/js/js_numbers.asp>
* Math <https://www.w3schools.com/js/js_math.asp>
* Date <https://www.w3schools.com/js/js_dates.asp>
* RegExp <https://www.w3schools.com/js/js_regexp.asp>
* Error <https://www.w3schools.com/js/js_errors.asp>
* JSON <https://www.w3schools.com/js/js_json.asp>
## YJS应用框架
### ypk项目组成
如之前描述ypk中可存放静态资源文件html/css/js)在智能合约中声明loadResource方法可返回静态资源文件。
基于loadResource本项目提供了一个yjs应用框架。
该框架可以将合约ypk中的(html/css/js)文件通过executeContract调用加载至前端并展示。
### 函数约定
| 序号 | 合约函数名 | 说明 |
|---|---|---|
| 1 | needRender | 不会被调用,有该函数表示需要渲染前端 |
| 2 | getMainFrame | 无参数返回结果为String类型表示主页的html文件路径 |
| 3 | loadResource | 参数为String以文本形式返回相对路径下的静态资源文件 |
### 加载流程
前端加载的参数会解析至global.urlparam。
包括以下参数:
```
//global.urlparam对象示例
{
"contract":"TrustedStorage0899", //表示合约ID或是合约的名称
"keys":{ //表示当前登录者的密钥对
"privateKey":"ff38dd04710...",
"publicKey":"04fc228..."
},
"nodeAddr":"022.node.internetapi.cn:21030" //节点的ip+端口
}
```
加载前会先建立与nodeAddr的websocket连接。
连接建立后,加载流程分为两步:
第一步是用当前的publickey-privatekey登录。登录过程详见`BDContract SDK` 的 `合约节点WebSocket接口`
登录之后,会获取合约的信息。
并存放于global.currentContract对象。
第二步是根据global.currentContract对象中是否有needRender方法
如果有,就会进入加载前端代码的流程。
具体为1.执行executeCurrentContract("getMainFrame") 获取页面的htmlappend至mainDIV之后
会解析所有`<script>`,`<link>`2.`fromContract`executeCurrentContract("loadResources")
典型的yjs的loadResources方法如下。3.获取所有script会进行eval,link会当css加载。
```
//在某个yjs文件中声明。
export function loadResource(arg){
return Global.Resources.loadAsString(arg);
}
```
![前端加载流程图](./_static/imgs/clientLoadProcess.png)
### 前端框架预置函数说明
前端的javascript在html中已加载了jquery(使用$.)和vue2。
为避免冲突本版不支持再加载vue2/vue3脚本。
前端通过executeContract/executeCurrentContract与后端交互。
#### executeContract
调用某个合约的某个函数。会自动使用当前的global.sm2Key进行签名。参数说明及示例
```javascript
executeContract(contracID,operation,arg,callback);
//其中contractID为string类型为被调用的合约名称/合约ID。
//operation为string类型合约函数
//arg为string类型表示参数
//callback为函数类型接受返回结果的回调函数。
```
#### executeCurrentContract
执行当前合约的某个函数。会自动使用当前的global.sm2Key进行签名。参数说明及示例
```javascript
executeContract(operation,arg,callback);
//operation为string类型合约函数
//arg为string类型表示参数
//callback为函数类型接受返回结果的回调函数。
```