# 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`等价。 ### 访问资源文件 通过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"); ``` ## 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 /[a-z][A-Z][0-9]/ (正则表达式) …… 详细格式可以参考http://mockjs.com/examples.html ``` ####注意:模板的格式为{‘result’:模板} ```json //返回一个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](./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 | 对象类型,有url,headers和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); ``` ### MySQLUtil 可以使用@Permission("MySQL")来引入MySQLUtil对象。 ``` @Permission("MySQL") contract MySQLExample{ ... } ``` #### 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 = 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对象。因此,可以查看: 以了解如何进行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对象。因此,可以查看: 以了解该对象的更多方法和使用方式。 ### 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.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.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为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 * Number * Math * Date * RegExp * Error * JSON