diff --git a/deploy/deploy-gateway/src/main/resources/docs/api_doc_cn_1.4.MD b/deploy/deploy-gateway/src/main/resources/docs/api_doc_cn_1.4.MD
index 017b97d2..c7185bcc 100644
--- a/deploy/deploy-gateway/src/main/resources/docs/api_doc_cn_1.4.MD
+++ b/deploy/deploy-gateway/src/main/resources/docs/api_doc_cn_1.4.MD
@@ -2132,3 +2132,361 @@ http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/contracts
|address.value|合约地址|
|pubKey.value|合约公钥|
|rootHash|合约根Hash|
+
+## 9 用户自定义事件
+
+### 9.1 获取事件账户列表
+
+```http
+GET /ledgers/{ledger}/events/user/accounts?fromIndex={start_index}&count={count}
+```
+
+#### 参数
+
+|请求类型|名称|是否必需|说明|数据类型|
+|---|---|---|---|---|
+|path|ledger|是|账本哈希|字符串|
+|query|start_index|否|查询的起始序号,默认为0|数字|
+|query|count|否|查询返回事件账户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字|
+
+
+#### 请求实例
+```http
+http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/events/user/accounts?fromIndex=0&count=-1
+```
+
+#### 返回实例
+
+```json
+{
+ "data":[
+ {
+ "address":{
+ "value":"LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1"
+ },
+ "pubKey":{
+ "value":"7VeRBi3xDfT1E11vFs9q5Q9gFo23RR7SoobPzivqxw9Uubzq"
+ }
+ }
+ ],
+ "success":true
+}
+```
+
+说明
+
+|名称|说明|
+|---|---|
+|address.value|账户地址|
+|pubKey.value|账户公钥|
+
+### 9.2 获取事件账户
+
+```http
+GET /ledgers/{ledger}/events/user/accounts/{address}
+```
+
+#### 参数
+
+|请求类型|名称|是否必需|说明|数据类型|
+|---|---|---|---|---|
+|path|ledger|是|账本哈希|字符串|
+|address|账户地址|是|事件账户地址|字符串|
+
+
+#### 请求实例
+```http
+http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/events/user/accounts/LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1
+```
+
+#### 返回实例
+
+```json
+{
+ "data":[
+ {
+ "address":{
+ "value":"LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1"
+ },
+ "pubKey":{
+ "value":"7VeRBi3xDfT1E11vFs9q5Q9gFo23RR7SoobPzivqxw9Uubzq"
+ }
+ }
+ ],
+ "success":true
+}
+```
+
+说明
+
+|名称|说明|
+|---|---|
+|address.value|账户地址|
+|pubKey.value|账户公钥|
+
+### 9.3 获取事件账户总数
+
+```http
+GET /ledgers/{ledger}/events/user/accounts/count
+```
+
+#### 参数
+
+|请求类型|名称|是否必需|说明|数据类型|
+|---|---|---|---|---|
+|path|ledger|是|账本哈希|字符串|
+
+
+#### 请求实例
+```http
+http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/events/user/accounts/count
+```
+
+#### 返回实例
+
+```json
+{
+ "data": 1,
+ "success": true
+}
+```
+
+说明
+
+|名称|说明|
+|---|---|
+|data|事件账户数量|
+
+### 9.4 获取事件名数量
+
+```http
+GET /ledgers/{ledger}/events/user/accounts/{address}/names/count
+```
+
+#### 参数
+
+|请求类型|名称|是否必需|说明|数据类型|
+|---|---|---|---|---|
+|path|ledger|是|账本哈希|字符串|
+|path|address|是|事件账户地址|字符串|
+
+
+#### 请求实例
+```http
+http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/events/user/accounts/LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1/names/count
+```
+
+#### 返回实例
+
+```json
+{
+ "data": 2,
+ "success": true
+}
+```
+
+说明
+
+|名称|说明|
+|---|---|
+|data|事件名数量|
+
+### 9.5 获取事件名列表
+
+```http
+GET /ledgers/{ledger}/events/user/accounts/{address}/names?fromIndex={start_index}&count={count}
+```
+
+#### 参数
+
+|请求类型|名称|是否必需|说明|数据类型|
+|---|---|---|---|---|
+|path|ledger|是|账本哈希|字符串|
+|path|address|是|事件账户地址|字符串|
+|query|start_index|否|查询的起始序号,默认为0|数字|
+|query|count|否|查询返回事件账户的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字|
+
+
+#### 请求实例
+```http
+http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/events/user/accounts/LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1/names?fromIndex=0&count=100
+```
+
+#### 返回实例
+
+```json
+{
+ "data": ["test1", "test2"],
+ "success": true
+}
+```
+
+说明
+
+|名称|说明|
+|---|---|
+|data|事件名数量数组|
+
+### 9.6 获取最新事件
+
+```http
+GET /ledgers/{ledger}/events/user/accounts/{address}/names/{event_name}/latest
+```
+
+#### 参数
+
+|请求类型|名称|是否必需|说明|数据类型|
+|---|---|---|---|---|
+|path|ledger|是|账本哈希|字符串|
+|path|address|是|事件账户地址|字符串|
+|path|event_name|是|事件名|字符串|
+
+
+#### 请求实例
+```http
+http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/events/user/accounts/LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1/names/test1/latest
+```
+
+#### 返回实例
+
+```json
+{
+ "data": {
+ "sequence": 0,
+ "transactionSource": {
+ "value": "j5rENX3rsdEgi5toeNUUv7ycUUivjNxAUb9Fme6oLCU851"
+ },
+ "blockHeight": 10,
+ "contractSource": "",
+ "eventAccount": {
+ "value": "LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1"
+ },
+ "name": "test1",
+ "content": {
+ "nil": false,
+ "bytes": {
+ "value": "Ctt6Eur"
+ },
+ "type": "TEXT",
+ "value": "imuge"
+ }
+ },
+ "success": true
+}
+```
+
+说明
+
+|名称|说明|
+|---|---|
+|sequence|事件序列|
+|transactionSource.value|交易哈希|
+|blockHeight|时间产生区块高度|
+|contractSource|合约地址|
+|eventAccount.value|事件账户地址|
+|name|事件名|
+|content.nil|事件内容是否为空|
+|content.bytes.value|事件内容字节|
+|content.type|事件内容类型|
+|content.value|事件内容|
+
+### 9.7 获取事件数量
+
+```http
+GET /ledgers/{ledger}/events/user/accounts/{address}/names/{event_name}/count
+```
+
+#### 参数
+
+|请求类型|名称|是否必需|说明|数据类型|
+|---|---|---|---|---|
+|path|ledger|是|账本哈希|字符串|
+|path|address|是|事件账户地址|字符串|
+|path|event_name|是|事件名|字符串|
+
+
+#### 请求实例
+```http
+http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/events/user/accounts/LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1/names/test1/count
+```
+
+#### 返回实例
+
+```json
+{
+ "data": 1,
+ "success": true
+}
+```
+
+说明
+
+|名称|说明|
+|---|---|
+|data|事件数量|
+
+### 9.8 获取事件列表
+
+```http
+GET /ledgers/{ledger}/events/user/accounts/{address}/names/{event_name}?fromSequence={from_sequence}&count={count}
+```
+
+#### 参数
+
+|请求类型|名称|是否必需|说明|数据类型|
+|---|---|---|---|---|
+|path|ledger|是|账本哈希|字符串|
+|path|address|是|事件账户地址|字符串|
+|path|event_name|是|事件名|字符串|
+|query|from_sequence|否|查询的起始序号,默认为0|数字|
+|query|count|否|查询返回事件的数量,默认最大返回值为100,小于0或大于100均返回最大可返回结果集|数字|
+
+
+#### 请求实例
+```http
+http://localhost/ledgers/657TQAw6ssVoeKniWGwbovk7njvCTvikPambM9eBv6ezs/events/user/accounts/LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1/names/test1?fromSequenct=0&count=100
+```
+
+#### 返回实例
+
+```json
+{
+ "data": [{
+ "sequence": 0,
+ "transactionSource": {
+ "value": "j5rENX3rsdEgi5toeNUUv7ycUUivjNxAUb9Fme6oLCU851"
+ },
+ "blockHeight": 10,
+ "contractSource": "",
+ "eventAccount": {
+ "value": "LdeP1yuk8Medq3Sph5ur9y1yE6nJ71XRVPPx1"
+ },
+ "name": "test1",
+ "content": {
+ "nil": false,
+ "bytes": {
+ "value": "Ctt6Eur"
+ },
+ "type": "TEXT",
+ "value": "imuge"
+ }
+ }],
+ "success": true
+}
+```
+
+说明
+
+|名称|说明|
+|---|---|
+|data|事件列表|
+|sequence|事件序列|
+|transactionSource.value|交易哈希|
+|blockHeight|时间产生区块高度|
+|contractSource|合约地址|
+|eventAccount.value|事件账户地址|
+|name|事件名|
+|content.nil|事件内容是否为空|
+|content.bytes.value|事件内容字节|
+|content.type|事件内容类型|
+|content.value|事件内容|
\ No newline at end of file
diff --git a/deploy/deploy-gateway/src/main/resources/docs/code_example.MD b/deploy/deploy-gateway/src/main/resources/docs/code_example.MD
new file mode 100644
index 00000000..49157dc4
--- /dev/null
+++ b/deploy/deploy-gateway/src/main/resources/docs/code_example.MD
@@ -0,0 +1,357 @@
+# 1. maven坐标
+```java
+
+ com.jd.blockchain
+ sdk-client
+ ${ledger.version}
+
+
+ com.jd.blockchain
+ contract-starter
+ ${ledger.version}
+
+
+ com.jd.blockchain
+ crypto-classic
+ ${ledger.version}
+
+
+
+ com.jd.blockchain
+ crypto-sm
+ ${ledger.version}
+
+```
+# 2. 数据快速上链
+## 2.1. 服务连接
+
+```java
+ //创建服务代理
+ public BlockchainKeypair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate();
+ final String GATEWAY_IP = "127.0.0.1";
+ final int GATEWAY_PORT = 80;
+ final boolean SECURE = false;
+ GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE,
+ CLIENT_CERT);
+ // 创建服务代理;
+ BlockchainService service = serviceFactory.getBlockchainService();
+ HashDigest[] ledgerHashs = service.getLedgerHashs();
+ // 获取当前账本Hash
+ HashDigest ledgerHash = ledgerHashs[0];
+```
+## 2.2. 用户注册
+```java
+ // 创建服务代理;
+ BlockchainService service = serviceFactory.getBlockchainService();
+ // 在本地定义注册账号的 TX;
+ TransactionTemplate txTemp = service.newTransaction(ledgerHash);
+ BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate();
+
+ txTemp.users().register(user.getIdentity());
+
+ // TX 准备就绪;
+ PreparedTransaction prepTx = txTemp.prepare();
+ // 使用私钥进行签名;
+ prepTx.sign(CLIENT_CERT);
+ // 提交交易;
+ prepTx.commit();
+```
+## 2.3. 数据账户注册
+```java
+ // 创建服务代理;
+ BlockchainService service = serviceFactory.getBlockchainService();
+ // 在本地定义注册账号的 TX;
+ TransactionTemplate txTemp = service.newTransaction(ledgerHash);
+ BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate();
+
+ txTemp.dataAccounts().register(dataAccount.getIdentity());
+
+ // TX 准备就绪;
+ PreparedTransaction prepTx = txTemp.prepare();
+ // 使用私钥进行签名;
+ prepTx.sign(CLIENT_CERT);
+
+ // 提交交易;
+ prepTx.commit();
+```
+## 2.4. 写入数据
+```java
+ // 创建服务代理;
+ BlockchainService service = serviceFactory.getBlockchainService();
+
+ // 在本地定义注册账号的 TX;
+ TransactionTemplate txTemp = service.newTransaction(ledgerHash);
+
+ // --------------------------------------
+ // 将商品信息写入到指定的账户中;
+ // 对象将被序列化为 JSON 形式存储,并基于 JSON 结构建立查询索引;
+ String commodityDataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf==";
+ txTemp.dataAccount(commodityDataAccount).setText("ASSET_CODE", "value1", -1);
+
+ // TX 准备就绪;
+ PreparedTransaction prepTx = txTemp.prepare();
+
+ String txHash = Base64Utils.encodeToUrlSafeString(prepTx.getHash().toBytes());
+ // 使用私钥进行签名;
+ prepTx.sign(CLIENT_CERT);
+
+ // 提交交易;
+ prepTx.commit();
+```
+## 2.5. 查询数据
+
+> 注:详细的查询可参考模块sdk-samples中SDK_GateWay_Query_Test_相关测试用例
+
+```java
+ // 创建服务代理;
+ BlockchainService service = serviceFactory.getBlockchainService();
+
+ // 查询区块信息;
+ // 区块高度;
+ long ledgerNumber = service.getLedger(ledgerHash).getLatestBlockHeight();
+ // 最新区块;
+ LedgerBlock latestBlock = service.getBlock(ledgerHash, ledgerNumber);
+ // 区块中的交易的数量;
+ long txCount = service.getTransactionCount(ledgerHash, latestBlock.getHash());
+ // 获取交易列表;
+ LedgerTransaction[] txList = service.getTransactions(ledgerHash, ledgerNumber, 0, 100);
+ // 遍历交易列表
+ for (LedgerTransaction ledgerTransaction : txList) {
+ TransactionContent txContent = ledgerTransaction.getTransactionContent();
+ Operation[] operations = txContent.getOperations();
+ if (operations != null && operations.length > 0) {
+ for (Operation operation : operations) {
+ operation = ClientResolveUtil.read(operation);
+ // 操作类型:数据账户注册操作
+ if (operation instanceof DataAccountRegisterOperation) {
+ DataAccountRegisterOperation daro = (DataAccountRegisterOperation) operation;
+ BlockchainIdentity blockchainIdentity = daro.getAccountID();
+ }
+ // 操作类型:用户注册操作
+ else if (operation instanceof UserRegisterOperation) {
+ UserRegisterOperation uro = (UserRegisterOperation) operation;
+ BlockchainIdentity blockchainIdentity = uro.getUserID();
+ }
+ // 操作类型:账本注册操作
+ else if (operation instanceof LedgerInitOperation) {
+
+ LedgerInitOperation ledgerInitOperation = (LedgerInitOperation)operation;
+ LedgerInitSetting ledgerInitSetting = ledgerInitOperation.getInitSetting();
+
+ ParticipantNode[] participantNodes = ledgerInitSetting.getConsensusParticipants();
+ }
+ // 操作类型:合约发布操作
+ else if (operation instanceof ContractCodeDeployOperation) {
+ ContractCodeDeployOperation ccdo = (ContractCodeDeployOperation) operation;
+ BlockchainIdentity blockchainIdentity = ccdo.getContractID();
+ }
+ // 操作类型:合约执行操作
+ else if (operation instanceof ContractEventSendOperation) {
+ ContractEventSendOperation ceso = (ContractEventSendOperation) operation;
+ }
+ // 操作类型:KV存储操作
+ else if (operation instanceof DataAccountKVSetOperation) {
+ DataAccountKVSetOperation.KVWriteEntry[] kvWriteEntries =
+ ((DataAccountKVSetOperation) operation).getWriteSet();
+ if (kvWriteEntries != null && kvWriteEntries.length > 0) {
+ for (DataAccountKVSetOperation.KVWriteEntry kvWriteEntry : kvWriteEntries) {
+ BytesValue bytesValue = kvWriteEntry.getValue();
+ DataType dataType = bytesValue.getType();
+ Object showVal = ClientResolveUtil.readValueByBytesValue(bytesValue);
+ System.out.println("writeSet.key=" + kvWriteEntry.getKey());
+ System.out.println("writeSet.value=" + showVal);
+ System.out.println("writeSet.type=" + dataType);
+ System.out.println("writeSet.version=" + kvWriteEntry.getExpectedVersion());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // 根据交易的 hash 获得交易;注:客户端生成 PrepareTransaction 时得到交易hash;
+ HashDigest txHash = txList[0].getTransactionContent().getHash();
+ Transaction tx = service.getTransactionByContentHash(ledgerHash, txHash);
+ // 获取数据;
+ String commerceAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf==";
+ String[] objKeys = new String[] { "x001", "x002" };
+ TypedKVEntry[] kvData = service.getDataEntries(ledgerHash, commerceAccount, objKeys);
+
+ long payloadVersion = kvData[0].getVersion();
+
+ // 获取数据账户下所有的KV列表
+ TypedKVEntry[] kvDatas = service.getDataEntries(ledgerHash, commerceAccount, 0, 100);
+ if (kvData != null && kvData.length > 0) {
+ for (TypedKVEntry kvDatum : kvDatas) {
+ System.out.println("kvData.key=" + kvDatum.getKey());
+ System.out.println("kvData.version=" + kvDatum.getVersion());
+ System.out.println("kvData.type=" + kvDatum.getType());
+ System.out.println("kvData.value=" + kvDatum.getValue());
+ }
+ }
+```
+
+## 2.6. 合约发布
+
+```java
+
+ // 创建服务代理;
+ BlockchainService service = serviceFactory.getBlockchainService();
+
+ // 在本地定义TX模板
+ TransactionTemplate txTemp = service.newTransaction(ledgerHash);
+
+ // 合约内容读取
+ byte[] contractBytes = FileUtils.readBytes(new File("CONTRACT_FILE"));
+
+ // 生成用户
+ BlockchainKeypair contractKeyPair = BlockchainKeyGenerator.getInstance().generate();
+
+ // 发布合约
+ txTemp.contracts().deploy(contractKeyPair.getIdentity(), contractBytes);
+
+ // TX 准备就绪;
+ PreparedTransaction prepTx = txTemp.prepare();
+
+ // 使用私钥进行签名;
+ prepTx.sign(CLIENT_CERT);
+
+ // 提交交易;
+ TransactionResponse transactionResponse = prepTx.commit();
+
+ assertTrue(transactionResponse.isSuccess());
+
+ // 打印合约地址
+ System.out.println(contractKeyPair.getIdentity().getAddress().toBase58());
+```
+
+## 2.7. 合约执行
+
+```java
+
+ // 创建服务代理;
+ BlockchainService service = serviceFactory.getBlockchainService();
+
+ // 在本地定义TX模板
+ TransactionTemplate txTemp = service.newTransaction(ledgerHash);
+
+ // 合约地址
+ String contractAddress = "";
+
+ // 使用接口方式调用合约
+ TransferContract transferContract = txTemp.contract(contractAddress, TransferContract.class);
+
+ // 使用decode方式调用合约内部方法(create方法)
+ // 返回GenericValueHolder可通过get方法获取结果,但get方法需要在commit调用后执行
+ String address = "address";
+ String account = "fill account";
+ long money = 100000000L;
+ GenericValueHolder result = ContractReturnValue.decode(transferContract.create(address, account, money));
+
+ PreparedTransaction ptx = txTemp.prepare();
+
+ ptx.sign(CLIENT_CERT);
+
+ TransactionResponse transactionResponse = ptx.commit();
+
+ String cotractExecResult = result.get();
+
+ // TransactionResponse也提供了可供查询结果的接口
+ OperationResult[] operationResults = transactionResponse.getOperationResults();
+
+ // 通过OperationResult获取结果
+ for (int i = 0; i < operationResults.length; i++) {
+ OperationResult opResult = operationResults[i];
+ System.out.printf("Operation[%s].result = %s \r\n",
+ opResult.getIndex(), BytesValueEncoding.decode(opResult.getResult()));
+ }
+```
+
+## 2.8. 事件账户注册
+```java
+ BlockchainService service = serviceFactory.getBlockchainService();
+ TransactionTemplate txTemp = service.newTransaction(ledgerHash);
+
+ BlockchainKeypair eventAccount = BlockchainKeyGenerator.getInstance().generate();
+ txTemp.eventAccounts().register(eventAccount.getIdentity());
+
+ // TX 准备就绪;
+ PreparedTransaction prepTx = txTemp.prepare();
+ // 使用私钥进行签名;
+ prepTx.sign(CLIENT_CERT);
+
+ // 提交交易;
+ prepTx.commit();
+```
+## 2.9. 事件发布
+```java
+ BlockchainService service = serviceFactory.getBlockchainService();
+ TransactionTemplate txTemp = service.newTransaction(ledgerHash);
+
+ // 发布事件到指定的账户中;
+ String eventAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf==";
+ txTemp.eventAccount(eventAccount).publish("event_name", "string", -1)
+ .publish("event_name", 0, 0)
+ .publish("event_name", "bytes".getBytes(), 1);
+
+ // TX 准备就绪;
+ PreparedTransaction prepTx = txTemp.prepare();
+
+ // 使用私钥进行签名;
+ prepTx.sign(CLIENT_CERT);
+
+ // 提交交易;
+ prepTx.commit();
+```
+
+## 2.10. 事件监听
+
+- 系统事件
+> 目前仅支持新区块产生事件
+```java
+ EventListenerHandle handler = blockchainService.monitorUserEvent(ledgerHash, eventAccount.getAddress().toBase58(), eventName, 0, new UserEventListener() {
+ @Override
+ public void onEvent(Event eventMessage, EventContext eventContext) {
+ BytesValue content = eventMessage.getContent();
+ switch (content.getType()) {
+ case TEXT:
+ case XML:
+ case JSON:
+ System.out.println(content.getBytes().toUTF8String());
+ break;
+ case INT64:
+ case TIMESTAMP:
+ System.out.println(BytesUtils.toLong(content.getBytes().toBytes()));
+ break;
+ default:
+ break;
+ }
+
+ // 关闭监听的两种方式:1
+ eventContext.getHandle().cancel();
+ }
+ });
+
+ // 关闭监听的两种方式:2
+ handler.cancel();
+```
+
+- 用户自定义事件
+```java
+ EventListenerHandle handler = blockchainService.monitorSystemEvent(ledgerHash, SystemEvent.NEW_BLOCK_CREATED, 0, new SystemEventListener() {
+ @Override
+ public void onEvents(Event[] eventMessages, EventContext eventContext) {
+ for (Event eventMessage : eventMessages) {
+ BytesValue content = eventMessage.getContent();
+ // content中存放的是当前链上最新高度
+ System.out.println(BytesUtils.toLong(content.getBytes().toBytes()));
+ }
+
+ // 关闭监听的两种方式:1
+ eventContext.getHandle().cancel();
+ }
+ });
+
+ // 关闭监听的两种方式:2
+ handler.cancel();
+```
\ No newline at end of file
diff --git a/samples/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Event_Demo.java b/samples/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Event_Demo.java
new file mode 100644
index 00000000..f4d85dbe
--- /dev/null
+++ b/samples/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDK_Event_Demo.java
@@ -0,0 +1,105 @@
+package com.jd.blockchain.sdk.samples;
+
+import com.jd.blockchain.ledger.BlockchainKeyGenerator;
+import com.jd.blockchain.ledger.BlockchainKeypair;
+import com.jd.blockchain.ledger.BytesValue;
+import com.jd.blockchain.ledger.Event;
+import com.jd.blockchain.ledger.SystemEvent;
+import com.jd.blockchain.ledger.TransactionTemplate;
+import com.jd.blockchain.sdk.EventContext;
+import com.jd.blockchain.sdk.EventListenerHandle;
+import com.jd.blockchain.sdk.SystemEventListener;
+import com.jd.blockchain.sdk.SystemEventPoint;
+import com.jd.blockchain.sdk.UserEventListener;
+import com.jd.blockchain.sdk.UserEventPoint;
+import com.jd.blockchain.utils.io.BytesUtils;
+
+public class SDK_Event_Demo extends SDK_Base_Demo {
+
+ // 注册事件账户
+ private BlockchainKeypair createEventAccount() {
+ BlockchainKeypair eventAccount = BlockchainKeyGenerator.getInstance().generate();
+ TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
+ txTpl.eventAccounts().register(eventAccount.getIdentity());
+ commit(txTpl);
+ return eventAccount;
+ }
+
+ /**
+ * 发布事件
+ *
+ * @param eventAccount 事件账户
+ */
+ private void publishEvent(BlockchainKeypair eventAccount) {
+ TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash);
+ // sequence传递当前事件名链上最新序号,不存在时传-1
+ Event event = blockchainService.getLatestEvent(ledgerHash, eventAccount.getAddress().toBase58(), "name");
+ long sequence = null != event ? event.getSequence() : -1;
+ txTpl.eventAccount(eventAccount.getAddress()).publish("name", "bytes".getBytes(), sequence);
+ txTpl.eventAccount(eventAccount.getAddress()).publish("name", "string", sequence + 1);
+ txTpl.eventAccount(eventAccount.getAddress()).publish("name", 0, sequence + 2);
+ txTpl.eventAccount(eventAccount.getAddress()).publish("name", 1l, sequence + 3);
+ txTpl.eventAccount(eventAccount.getAddress()).publishXML("name", "", sequence + 4);
+ txTpl.eventAccount(eventAccount.getAddress()).publishJSON("name", "{}", sequence + 5);
+ txTpl.eventAccount(eventAccount.getAddress()).publishImage("name", "img".getBytes(), sequence + 6);
+ txTpl.eventAccount(eventAccount.getAddress()).publishTimestamp("name", System.currentTimeMillis(), sequence + 7);
+ commit(txTpl);
+ }
+
+ /**
+ * 监听用户自定义事件
+ *
+ * @param eventAccount 事件账户
+ * @param eventName 事件名
+ */
+ private void monitorUserEvent(BlockchainKeypair eventAccount, String eventName) {
+ EventListenerHandle handler = blockchainService.monitorUserEvent(ledgerHash, eventAccount.getAddress().toBase58(), eventName, 0, new UserEventListener() {
+ @Override
+ public void onEvent(Event eventMessage, EventContext eventContext) {
+ BytesValue content = eventMessage.getContent();
+ switch (content.getType()) {
+ case TEXT:
+ case XML:
+ case JSON:
+ System.out.println(content.getBytes().toUTF8String());
+ break;
+ case INT64:
+ case TIMESTAMP:
+ System.out.println(BytesUtils.toLong(content.getBytes().toBytes()));
+ break;
+ default:
+ break;
+ }
+
+ // 关闭监听的两种方式:1
+ eventContext.getHandle().cancel();
+ }
+ });
+
+ // 关闭监听的两种方式:2
+ handler.cancel();
+ }
+
+ /**
+ * 监听新区块生成事件
+ */
+ private void monitorNewBlockCreatedEvent() {
+ EventListenerHandle handler = blockchainService.monitorSystemEvent(ledgerHash, SystemEvent.NEW_BLOCK_CREATED, 0, new SystemEventListener() {
+ @Override
+ public void onEvents(Event[] eventMessages, EventContext eventContext) {
+ for (Event eventMessage : eventMessages) {
+ BytesValue content = eventMessage.getContent();
+ // content中存放的是当前链上最新高度
+ System.out.println(BytesUtils.toLong(content.getBytes().toBytes()));
+ }
+
+ // 关闭监听的两种方式:1
+ eventContext.getHandle().cancel();
+ }
+ });
+
+ // 关闭监听的两种方式:2
+ handler.cancel();
+ }
+
+}