# RCJS **Repository Path**: BTAJL/RCJS ## Basic Information - **Project Name**: RCJS - **Description**: RCJS(RepChain Client library for JavaScript),RepChain的客户端开发包JS语言版本,兼容Node以及Browser环境。 - **Primary Language**: JavaScript - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 1 - **Created**: 2018-08-04 - **Last Updated**: 2023-05-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## RCJS ### 介绍 RCJS(RepChain Client library for JavaScript),是基于JavaScript实现的用于与[RepChain](https://gitee.com/BTAJL/repchain)区块链网络进行交互的工具包,可作为开发RepChain DApp(Decentralized Application)的SDK。 RCJS对调用RepChain的相应Websocket API, Restful API等进行了封装。利用RCJS可较为方便地使DApp与RepChain进行交互。 RCJS兼容浏览器环境以及NodeJS环境,可根据需要在不同环境使用。 > Note: 某些加密算法名称在不同环境可能有差异,需注意 RCJS为开发者提供了以下功能: - 获取RepChain区块链概要信息:获取区块链网络的区块数量、交易数量及最新区块哈希等信息; - 获取RepChain区块数据:支持订阅RepChain出块事件获取区块数据(二进制格式(protobuf序列化)),以及通过Restful API主动获取区块数据(json格式或二进制格式(protobuf序列化)); - 获取RepChain交易数据:通过Restful API获取交易数据(json格式或二进制格式(protobuf序列化)) - 构造RepChain签名交易:提供RepChain交易数据的构造及交易签名功能; - 提交RepChain签名交易:向RepChain区块链网络提交已构造的签名交易数据; - 加密工具:(基于[NodeJS Crypto](https://nodejs.org/docs/latest-v10.x/api/crypto.html) 以及 [jsrsasign](https://github.com/kjur/jsrsasign)实现) + 生成密码学哈希值 + 生成非对称密钥对:支持RSA与EC算法 + 导出/导入密钥:支持生成/解析PEM格式的公钥或私钥 + 对数据进行签名 + 验证签名 + 生成X509证书 + 生成自签名X509证书 + 导出/导入X509证书:支持生成/解析PEM格式证书信息 + 验证证书的签名 + 生成/解析CSR信息: 支持生成以及反解析PEM格式的CSR信息 ### 使用说明 #### 安装 ```bash yarn add rclink ``` 或 ```bash npm i --save rclink ``` 或者在package.json文件中直接使用git地址, 如: ```json "rclink": "https://gitee.com/BTAJL/RCJS.git#v3.0.0" ``` #### API API文档可参考[这里](https://btajl.gitee.io/rcjs/3.0.0) #### 使用示例 ##### 构建签名交易 ```javascript import { TRANSACTION, RCPROTO } from "rclink"; ...... // 构建部署合约交易 const txToDeploy = TRANSACTION.Transaction.create({ // 交易类型为部署合约 type: RCPROTO.rep.proto.Transaction.Type.CHAINCODE_DEPLOY, // 合约名称 chaincodeName: "TestContract", // 合约版本号 chaincodeVersion: 1, // 部署合约参数 chaincodeDeployParams: { // 部署超时设定 timeout: 5000, // 合约源码语言 codeLanguageType: RCPROTO.rep.proto.ChaincodeDeploy.CodeType.CODE_SCALA, // 合约法律条文说明 legalProse: "fake-content", // 合约源码 codePackage: "you_need_input_the_real_sourcecode", }, }); // 对交易进行签名 txToDeploy.sign({ // pem格式私钥 prvKey: prvKeyPEM, // pem格式公钥 pubKey: pubKeyPEM, // 签名算法 alg: "sha256", // 签名者账户标识 creditCode: "identity-net:121000005l35120456", // 签名者账户证书名 certName: "node1", }); // 构建调用合约交易 const txToInvoke = TRANSACTION.Transaction.create({ type: RCPROTO.rep.proto.Transaction.Type.CHAINCODE_INVOKE, chaincodeName: "TestContract", chaincodeVersion: 1, // 调用合约参数 chaincodeInvokeParams: { // 合约方法名 chaincodeFunction: "transfer", // 合约方法参数 chaincodeFunctionArgs: [`{ "from" : "121000005l35120456", "to" : "12110107bi45jh675g", "amount" : 5 }`], }, // 交易唯一标识(可选,未指定时将在签名时自动生成) txid: "some-unique-id", // 执行交易所需资源上限 gasLimit: 1000, // 合约实例标识,默认为"" oid: "some-oid" }); txToInvoke.sign({ prvKey: prvKeyPEM, pubKey: pubKeyPEM, alg: "sha256", creditCode: "identity-net:121000005l35120456", certName: "node1", }); // 构建更改合约有效性状态交易 const txToSetState = TRANSACTION.Transaction.create({ type: RCPROTO.rep.proto.Transaction.Type.CHAINCODE_SET_STATE, chaincodeName: "TestContract", chaincodeVersion: 1, // 更改合约有效性状态参数 chaincodeSetStateParams: { // 欲设定的合约状态,true为有效,false为无效 state: false, }, }); txToSetState.sign({ prvKey: prvKeyPEM, pubKey: pubKeyPEM, alg: "sha256", creditCode: "identity-net:121000005l35120456", certName: "node1", }); ``` ##### 提交签名交易 ```javascript import { CLIENT } from "rclink"; ...... // 欲连接的区块链节点Url const peerUrl = "http://192.168.2.3:9081"; const client = new CLIENT.Client(peerUrl); const txSignedBuffer = Buffer.from(tx.getTxSignedBuffer()); // 以hex编码字符串形式提交签名交易到区块链节点 client.sendTransaction(txSignedBuffer.toString("hex")).then((res) => { if (res.err) { console.error("交易预处理失败: ", res.err); } console.log("已提交交易: ", res.txid); }).catch((err) => { console.error(err); }); // 或者以二进制形式提交签名交易到区块链节点 client.sendTransaction(txSignedBuffer).then((res) => { if (res.err) { console.error("交易预处理失败: ", res.err); } console.log("已提交交易: ", res.txid); }).catch((err) => { console.error(err); }); ``` ##### 获取区块链概要信息 ```javascript import { CLIENT } from "rclink"; ...... // 欲连接的区块链节点Url const peerUrl = "http://192.168.2.3:9081"; const client = new CLIENT.Client(peerUrl); client.chainInfo().then((ci) => { console.log("当前最新区块高度: ", ci.height); console.log("当前交易数量: ", ci.totalTransactions); console.log("当前最新区块哈希: ", ci.currentBlockHash); console.log("前序区块哈希: ", ci.previousBlockHash); console.log("当前世界状态根哈希: ", ci.currentStateHash); }); ``` ##### 获取区块数据 ```javascript import { CLIENT, RCPROTO, EVENTS } from "rclink"; ...... // 欲连接的区块链节点Url const peerUrl = "http://192.168.2.3:9081"; const client = new CLIENT.Client(peerUrl); // 根据高度获取区块数据 client.block(1).then((blkJson) => { console.log("获取Json格式区块数据", blkJson); }); client.block(1, CLIENT.RESPONSE_FORMAT.STREAM).then((blkBuffer) => { console.log("获取二进制格式区块数据"); const blk = RCPROTO.rep.proto.Block.decode(blkBuffer); console.log(blk); }); // 根据哈希值获取区块数据 const blockHash = "BHBJXDSJ7182368129gGYUcbdjs7889" client.block(blockHash).then((blkJson) => { console.log("获取Json格式区块数据", blkJson); }); client.block(blockHash, CLIENT.RESPONSE_FORMAT.STREAM).then((blkBuffer) => { console.log("获取二进制格式区块数据"); const blk = RCPROTO.rep.proto.Block.decode(blkBuffer); console.log(blk); }); // 订阅出块事件,获取区块数据 const peerWebsocketUrl = "ws://192.168.2.3:9081/event"; const et = new EVENTS.EventTube(peerWebsocketUrl, (evt) => { const event = Buffer.from(evt.data); const msg = RCPROTO.rep.proto.Event.decode(event); let block; if (msg.blk) { block = RCPROTO.rep.proto.Block.decode(msg.blk); console.log("订阅获取区块数据", block); } }); ``` ##### 获取交易数据 ```javascript import { CLIENT, RCPROTO, EVENTS } from "rclink"; // 欲连接的区块链节点Url const peerUrl = "http://192.168.2.3:9081"; const client = new CLIENT.Client(peerUrl); const txid = "08329673428abc82389772befff32889090"; client.transaction(txid).then((txJson) => { console.log("获取Json格式交易数据", txJson); }); client.transaction(txid, CLIENT.RESPONSE_FORMAT.STREAM).then((txBuffer) => { console.log("获取二进制格式交易数据"); const tx = RCPROTO.rep.proto.Transaction.decode(txBuffer); console.log(tx); }); client.transaction(txid, CLIENT.RESPONSE_FORMAT.JSON, true).then((txWithBlockHeight) => { console.log("获取带所属区块高度的Json格式交易数据", txWithBlockHeight); }) ...... ``` 另可参考测试用例代码: - 交易构建: [test/transaction.test.ts](test/transaction.test.ts) - 事件订阅:[test/events.test.ts](test/events.test.ts) - 数据查询及交易提交: [test/client.test.ts](test/client.test.ts) - 加密工具:[test/crypto.test.js](test/crypto.test.js) ### 开发 #### 安装依赖 1. 安装node.js和yarn 2. `yarn install` #### 更新protobuf定义 当相应protobuf定义(默认为目录src/protos下的proto文件)需要发生变更时,执行: ```bash yarn build:proto ``` 会在目录src/protos中生成protobuf定义的相应js代码,然后基于生成的代码进行开发 #### 生成lib库 ```bash yarn build ``` #### 生成API文档 ```bash yarn doc ``` 生成静态网页形式的API文档,若文档内容有更新则在进行git提交时会自动将API文档提交到专门的git分支api-docs上 #### 运行测试 1. 建立RepChain开发环境(RepChain v2+, 自动产生交易模式, 且已产生超过1个区块) 2. 运行测试用例: - `yarn test:node` node环境下运行测试用例 - `yarn test:browser` browser环境下运行测试用例 - `yarn test` 在node与browser环境下分别运行测试用例