diff --git a/README.md b/README.md
index 731466b..aa8bfe3 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,10 @@
This is the LemoChain compatible JavaScript SDK which implements the Generic JSON RPC.
-You need to run a local LemoChain node to use this library.
+> You need to run a local or remote LemoChain node with flag `--rpc` to use this library.
+
+[中文版](https://github.com/LemoFoundationLtd/lemo-client/blob/master/README_zh.md)
+[English](https://github.com/LemoFoundationLtd/lemo-client/blob/master/README.md)
## Installing
@@ -25,7 +28,7 @@ yarn add lemo-client
### As Browser module
* Include `lemo-client.min.js` in your html file.
-* Use the `LemoClient` object directly from global namespace:
+* Use the `LemoClient` object directly from global namespace
## Example
@@ -42,63 +45,922 @@ lemo.chain.getBlockByNumber(0)
```
## LemoChain API
-> NOTE: Every API returns a promise, except `watchXXX` which return `watchId` for stop watching
+> Almost every API returns a promise object, except `watchXXX`, `stopWatch` and so on
+> All API available in the console of LemoChain node. But some APIs are not available over remote connection such as http, websocket
-### chain
-methods | description | available on http
----|---|---
-lemo.getBlock(number, withTxList) | Get block by height (only stable block) | ✓
-lemo.getBlock(hash, withTxList) | Get block by block hash | ✓
-lemo.getCurrentBlock(false, withTxList) | Get the newest block | ✓
-lemo.getCurrentBlock(true, withTxList) | Get the newest stable block | ✓
-lemo.getCurrentHeight(false) | Get the newest block height | ✓
-lemo.getCurrentHeight(true) | Get the newest stable block height | ✓
-lemo.getGenesis() | Get the first block | ✓
-lemo.getChainID() | Get the chain ID | ✓
-lemo.getGasPriceAdvice() | Get transaction gas price advice | ✓
-lemo.getNodeVersion() | Get the version of LemoChain node | ✓
-lemo.getSdkVersion() | Get the version of lemo-client | ✓
-lemo.watchBlock(withTxList, callback) | Listen for new block | ✓
-
-### net
-methods | description | available on http
----|---|---
-lemo.net.addPeer(nodeAddr) | Connect to a peer | ✖
-lemo.net.dropPeer(nodeAddr) | Disconnect to a peer | ✖
-lemo.net.getPeers() | Get the connected peer list | ✖
-lemo.net.getPeersCount() | Get the number of connected peers | ✓
-lemo.net.getInfo() | Get the information of current LemoChain node | ✓
-
-### mine
-methods | description | available on http
+API | description | available for remote
---|---|---
-lemo.mine.start() | Start mining | ✖
-lemo.mine.stop() | Stop mining | ✖
-lemo.mine.getMining() | True if current LemoChain node is mining | ✓
-lemo.mine.getLemoBase() | Get the mining benefit account address of current LemoChain node | ✓
+[lemo.getBlock(heightOrHash, withBody)](#submodule-chain-getBlock) | Get block by height or block hash | ✓
+[lemo.getCurrentBlock(stable, withBody)](#submodule-chain-getCurrentBlock) | Get the newest block | ✓
+[lemo.getCurrentHeight(stable)](#submodule-chain-getCurrentHeight) | Get the newest block height | ✓
+[lemo.getGenesis()](#submodule-chain-getGenesis) | Get the first block | ✓
+[lemo.getChainID()](#submodule-chain-getChainID) | Get the chain ID | ✓
+[lemo.getGasPriceAdvice()](#submodule-chain-getGasPriceAdvice) | Get transaction gas price advice | ✓
+[lemo.getNodeVersion()](#submodule-chain-getNodeVersion) | Get the version of LemoChain node | ✓
+[lemo.getSdkVersion()](#submodule-chain-getSdkVersion) | Get the version of lemo-client | ✓
+[lemo.watchBlock(withBody, callback)](#submodule-chain-watchBlock) | Listen for new block | ✓
+[lemo.net.connect(nodeAddr)](#submodule-net-connect) | Connect to a LemoChain node | ✖
+[lemo.net.disconnect(nodeAddr)](#submodule-net-disconnect) | Disconnect to a LemoChain node | ✖
+[lemo.net.getConnections()](#submodule-net-getConnections) | Get the information of connections | ✖
+[lemo.net.getConnectionsCount()](#submodule-net-getConnectionsCount) | Get the count of connections | ✓
+[lemo.net.getInfo()](#submodule-net-getInfo) | Get current node information | ✓
+[lemo.mine.start()](#submodule-mine-start) | Start mining | ✖
+[lemo.mine.stop()](#submodule-mine-stop) | Stop mining | ✖
+[lemo.mine.getMining()](#submodule-mine-getMining) | True if current LemoChain node is mining | ✓
+[lemo.mine.getMiner()](#submodule-mine-getMiner) | Get the mining benefit account address of current LemoChain node | ✓
+[lemo.account.newKeyPair()](#submodule-account-newKeyPair) | Create a private key and account address | ✖
+[lemo.account.getBalance(addr)](#submodule-account-getBalance) | Get the balance of an account | ✓
+[lemo.account.getAccount(addr)](#submodule-account-getAccount) | Get the information of an account | ✓
+[lemo.tx.sendTx(privateKey, txInfo)](#submodule-tx-sendTx) | Sign and send transaction | ✓
+[lemo.tx.sign(privateKey, txInfo)](#submodule-tx-sign) | Sign transaction | ✓
+[lemo.tx.send(signedTxInfo)](#submodule-tx-send) | Send a signed transaction | ✓
+[lemo.tx.watchPendingTx(callback)](#submodule-tx-watchPendingTx) | Listening for new transactions | ✖
+[lemo.stopWatch(watchId)](#submodule-stopWatch) | Stop listening | ✓
+[lemo.isWatching()](#submodule-isWatching) | True if is listening | ✓
+
+---
+
+### Protocol
+Send and receive data by json format, use [JSON-RPC2.0](https://www.jsonrpc.org/specification) standard.
+For convenient, all numbers will be convert to string. So the numbers will never overflow.
+
+#### POST request
+```
+{
+ "jsonrpc": "2.0",
+ "method": "chain_getBlockByHeight",
+ "params": [1, false],
+ "id": 1
+}
+```
+- `jsonrpc` - (string) Always `2.0`
+- `method` - (string) API module name and method name connected by `_`
+- `params` - (Array) API method parameters, object is available
+- `id` - (number) Increasing request id
-### account
-methods | description | available on http
----|---|---
-lemo.account.newKeyPair() | Create a private key and account address | ✖
-lemo.account.getBalance(addr) | Get the balance of an account | ✓
-lemo.account.getAccount(addr) | Get the information of an account | ✓
+#### Success response
+```
+{
+ "jsonrpc": "2.0",
+ "result": {...},
+ "id": 1
+}
+```
+- `jsonrpc` - (string) Always `2.0`
+- `result` - (*) The result could be any type
+- `id` - (number) The id in request
-### tx
-methods | description | available on http
----|---|---
-lemo.tx.sendTx(privateKey, txInfo) | Sign and send transaction | ✓
-lemo.tx.send(signedTxInfo) | Send a signed transaction | ✓
-lemo.tx.sign(privateKey, txInfo) | Sign transaction | ✓
-lemo.tx.watchPendingTx(callback) | Listen for the new Transaction | ✖
+#### Error response
+```
+{
+ "jsonrpc": "2.0",
+ "error": {"code": -32601, "message": "Method not found"},
+ "id": 1
+}
+```
+- `jsonrpc` - (string) Always `2.0`
+- `error` - (object) The error detail. It contains a negtive number `code` and a string `message`.
+- `id` - (number) The id in request
+
+---
+
+### Data structure
+
+
+#### block
+```json
+{
+ "header": {},
+ "transactions": [],
+ "changeLogs": [],
+ "confirms": [],
+ "events": [],
+ "deputyNodes": []
+}
+```
+- `header` The [header](#data-structure-header) of block
+- `transactions` All [Transactions](#data-structure-transaction) in block
+- `changeLogs` The account data [changeLogs](#data-structure-changeLog) by transactions in block
+- `confirms` The [signatures](#data-structure-confirm) from deputies after they verified the block
+- `events` The [contract events](#data-structure-event) from transactions in block
+- `deputyNodes` New [deputy nodes information](#data-structure-deputyNode) If the block is `snapshot block`, or else it is empty
+
+
+#### header
+The header of block
+```json
+{
+ "hash": "0x11d9153b14adb92a14c16b66c3524d62b4742c0e7d375025525e2f131de37a8b",
+ "height": "0",
+ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "miner": "Lemo83GN72GYH2NZ8BA729Z9TCT7KQ5FC3CR6DJG",
+ "signData": "0x",
+ "timestamp": "1535630400",
+ "gasLimit": "105000000",
+ "gasUsed": "0",
+ "eventBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "changeLogRoot": "0x93273cebb4f0728991811d5d7c57ae8f88a83524eedb0af48b3061ed2e8017b8",
+ "deputyRoot": "0x49b613bbdf76be3fe761fd60d1ade6d2835315047c53d6e8199737898b8d9b47",
+ "eventRoot": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "transactionRoot": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+ "versionRoot": "0x1e78c4779248d3d8d3cd9b77bf7b67b4c759ec87d45d52a3e79c928290773f4c",
+ "extraData": "0x"
+}
+```
+- `hash` Block hash
+- `height` Block height
+- `parentHash` Previous block hash
+- `miner` Address of the account who produce this block
+- `signData` Miner's signatue of the block hash
+- `timestamp` The time of block creation in seconds
+- `gasLimit` Max gas limit for all transactions in block
+- `gasUsed` Used gas of all transactions in block
+- `eventBloom` The bloom filter for speed up contract events query. Calculated by `events` in block
+- `changeLogRoot` The root hash of block's `changeLogs` Merkle Trie
+- `deputyRoot` The root hash of block's `deputyNodes` Merkle Trie
+- `eventRoot` The root hash of block's `events` Merkle Trie
+- `transactionRoot` The root hash of block's `transactions` Merkle Trie
+- `versionRoot` The root hash of global `versions` Merkle Patricia Trie. This trie is storing all accounts' newest version
+- `extraData` (optional) The custom data from miner
+
+
+#### transaction
+Signed transaction
+```json
+{
+ "to": "Lemo83JW7TBPA7P2P6AR9ZC2WCQJYRNHZ4NJD4CY",
+ "toName": "",
+ "amount": "100",
+ "data": "0x",
+ "expirationTime": "1541566996",
+ "gasLimit": "2000000",
+ "gasPrice": "3000000000",
+ "hash": "0x6d3062a9f5d4400b2002b436bc69485449891c83e23bf9e27229234da5b25dcf",
+ "message": "",
+ "r": "0xaf5e573f07e4aaa2932b21b90a4b1b1a317b00a83d66908a0053a337319b149d",
+ "s": "0x6c1fbad11a56720fe219ef67c0ada27fa3c76212cc849f519e5fbcbe83a88b6b",
+ "v": "0x20001"
+}
+```
+- `to` Recipient address
+- `toName` (optional) Recipient name. It will be checked with `to` for safe
+- `amount` Amount in `mo`. 1`LEMO`=1000000000000000000`mo`=1e18`mo`
+- `data` (optional) The extra data. It usually using for calling smart contract. It depends on `type` that how to using this field
+- `expirationTime` The expiration time of transaction in seconds. If a transaction's expiration time is more than half hour from now, it may not be packaged in block. It depends on the transactions picking logic from miner
+- `gasLimit` Max gas limit of transaction. The transaction will be fail if it cost more gas than gasLimit. And the gas will not be refunded
+- `gasPrice` Price of every gas in `mo`. The more gas price the more priority
+- `hash` Transaction hash
+- `message` (optional) Extra text message from sender
+- `r` Signature data
+- `s` Signature data
+- `v` This field is combined from transaction `type`, `version`(current is 0), `signature recovery data`, `chainID`
+
+transaction type | description
+---|---
+0 | Normal transaction or smart contract execution transaction
+
+chainID | description
+---|---
+1 | LemoChain main net
+
+
+#### changeLog
+The modification record of data on chain
+```json
+{
+ "address": "Lemo83GN72GYH2NZ8BA729Z9TCT7KQ5FC3CR6DJG",
+ "extra": "",
+ "newValue": "0x8c052b7d2dcc80cd2e40000000",
+ "type": "BalanceLog",
+ "version": "1"
+}
+```
+- `address` The address of account which data is changed
+- `version` The version of account data. Every type data has its own version
+- Depends on different `type`, the `newValue` and `extra` have different functions
+
+type | description | newValue | extra
+---|---|---|---
+BalanceLog | The change of account balance | New balance | -
+StorageLog | The change of storage in contract account | storage value | storage key
+CodeLog | Creation of contract account | Contract's code | -
+AddEventLog | Creation a contract event | Contract event | -
+SuicideLog | Destroying a contract account | - | -
+
+
+#### confirm
+The signature of block hash from a deputy node after him verified the block
+```
+0x1234
+```
+
+#### event
+Smart contract event
+```json
+{
+ "address": "Lemo83GN72GYH2NZ8BA729Z9TCT7KQ5FC3CR6DJG"
+}
+```
-### other
-methods | description | available on http
----|---|---
-lemo.stopWatch(watchId) | Stop watching by watch ID | ✓
-lemo.stopWatch() | Stop all watching | ✓
-lemo.isWatching() | True if is watching some data | ✓
+
+#### deputyNode
+Deputy node information
+```json
+{
+ "ip": "127.0.0.1",
+ "minerAddress": "Lemo83GN72GYH2NZ8BA729Z9TCT7KQ5FC3CR6DJG",
+ "nodeID": "0x5e3600755f9b512a65603b38e30885c98cbac70259c3235c9b3f42ee563b480edea351ba0ff5748a638fe0aeff5d845bf37a3b437831871b48fd32f33cd9a3c0",
+ "port": "7001",
+ "rank": "0",
+ "votes": "50000"
+}
+```
+- `ip` Deputy node ip address
+- `minerAddress` The account address to receive mining benefit
+- `nodeID` The LemoChain node ID, it is from the public key whose private key is using for sign blocks
+- `port` The port to connect other nodes
+- `rank` The rank of all deputy nodes
+- `votes` The votes count
+
+
+#### account
+Account information
+```json
+{
+ "address": "Lemo83GN72GYH2NZ8BA729Z9TCT7KQ5FC3CR6DJG",
+ "balance": "1599999999999999999999999900",
+ "records": {
+ "BalanceLog": {
+ "version": "3",
+ "height": "1"
+ }
+ },
+ "codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "root": "0x0000000000000000000000000000000000000000000000000000000000000000"
+}
+```
+- `address` Account address
+- `balance` Account balance. It is a modified `BigNumber` object. It has a method `toMoney()` to output formatted balance
+- `records` Modification record object of account. The key is type of [ChangeLog](data-structure-changeLog), value is the newest `ChangeLog`'s version and height of the block which contains this newest `ChangeLog`
+- `codeHash` Hash of contract code
+- `root` The hash of contranct storage MPT root
+
+---
+
+### Constructor
+```
+lemo = new LemoClient({
+ host: 'http://127.0.0.1:8001'
+})
+```
+- `host` LemoChain node's http listening address. The default value is `http://127.0.0.1:8001`
+> NOTE: If the cross domain issue appear. Try to use flag `--rpccorsdomain http://[domain of the web page]:[port]` to restart LemoChain node.
+
+---
+
+### chain API
+
+
+#### lemo.getBlock
+```
+lemo.getBlock(heightOrHash [, withBody])
+```
+Get block by height or block hash
+
+##### Parameters
+1. `number|string` - Block height or block hash. If it is block height, only stable blocks will be retrived which confirmed by most deputy nodes
+2. `boolean` - (optional) Enable to get block body such as transactions. Default value is `false`
+
+##### Returns
+`Promise` - Call `then` method to get [block](#data-structure-block) object
+
+##### Example
+```js
+lemo.getBlock(0).then(function(block) {
+ console.log(block.header.hash); // "0x11d9153b14adb92a14c16b66c3524d62b4742c0e7d375025525e2f131de37a8b"
+})
+```
+
+---
+
+
+#### lemo.getCurrentBlock
+```
+lemo.getCurrentBlock([stable [, withBody]])
+```
+Get the newest block
+
+##### Parameters
+1. `boolean` - (optional) If it is true, only stable blocks will be retrived which confirmed by most deputy nodes. Default value is `true`
+2. `boolean` - (optional) Enable to get block body such as transactions. Default value is `false`
+
+##### Returns
+`Promise` - Call `then` method to get [block](#data-structure-block) object
+
+##### Example
+```js
+lemo.getCurrentBlock(true).then(function(block) {
+ console.log(block.header.miner); // "Lemo83GN72GYH2NZ8BA729Z9TCT7KQ5FC3CR6DJG"
+})
+```
+
+---
+
+
+#### lemo.getCurrentHeight
+```
+lemo.getCurrentHeight([stable])
+```
+Get the newest block height
+
+##### Parameters
+1. `boolean` - (optional) If it is true, only stable blocks will be retrived which confirmed by most deputy nodes. Default value is `true`
+
+##### Returns
+`Promise` - Call `then` method to get height string
+
+##### Example
+```js
+lemo.getCurrentHeight(true).then(function(height) {
+ console.log(height); // "100"
+})
+```
+
+---
+
+
+#### lemo.getGenesis
+```
+lemo.getGenesis()
+```
+Get the first block
+
+##### Parameters
+None
+
+##### Returns
+`Promise` - Call `then` method to get [block](#data-structure-block) object
+
+##### Example
+```js
+lemo.getGenesis().then(function(height) {
+ console.log(block.header.parentHash); // "0x0000000000000000000000000000000000000000000000000000000000000000"
+})
+```
+
+---
+
+
+#### lemo.getChainID
+```
+lemo.getChainID()
+```
+Get the chain ID from current connected LemoChain node
+
+##### Parameters
+None
+
+##### Returns
+`Promise` - Call `then` method to get chainID string
+
+##### Example
+```js
+lemo.getChainID().then(function(chainID) {
+ console.log(chainID); // "1"
+})
+```
+
+---
+
+
+#### lemo.getGasPriceAdvice
+```
+lemo.getGasPriceAdvice()
+```
+Get transaction gas price advice
+
+##### Parameters
+None
+
+##### Returns
+`Promise` - Call `then` method to get gas price advice string in uint `mo`
+
+##### Example
+```js
+lemo.getGasPriceAdvice().then(function(gasPrice) {
+ console.log(gasPrice); // "2000000000"
+})
+```
+
+---
+
+
+#### lemo.getNodeVersion
+```
+lemo.getNodeVersion()
+```
+Get the version of LemoChain node
+
+##### Parameters
+None
+
+##### Returns
+`Promise` - Call `then` method to get version string
+
+##### Example
+```js
+lemo.getNodeVersion().then(function(version) {
+ console.log(version); // "1.0.0"
+})
+```
+
+---
+
+
+#### lemo.getSdkVersion
+```
+lemo.getSdkVersion()
+```
+Get the version of lemo-client
+
+##### Parameters
+None
+
+##### Returns
+`Promise` - Call `then` method to get version string
+
+##### Example
+```js
+lemo.getSdkVersion().then(function(version) {
+ console.log(version); // "1.0.0"
+})
+```
+
+---
+
+
+#### lemo.watchBlock
+```
+lemo.watchBlock(withBody, callback)
+```
+Listen for new block. The callback function will be called at the beginning and every times a new stable block produced.
+
+##### Parameters
+1. `boolean` - (optional) Enable to get block body such as transactions. Default value is `false`
+2. `Function` - Used to receive [block](#data-structure-block) object
+
+##### Returns
+`number` - watchId for [stop watching](#submodule-stopWatch)
+
+##### Example
+```js
+lemo.watchBlock(true, function(block) {
+ const d = new Date(1000 * parseInt(block.header.timestamp, 10))
+ console.log(d.toUTCString()); // "Thu, 30 Aug 2018 12:00:00 GMT"
+})
+```
+
+---
+
+### net API
+
+
+#### lemo.net.connect
+```
+lemo.net.connect(nodeAddr)
+```
+Connect to a LemoChain node
+
+##### Parameters
+1. `string` - ip address
+
+##### Returns
+`Promise` - No data input in `then` function
+
+##### Example
+```js
+lemo.net.connect('127.0.0.1:60002')
+```
+
+---
+
+
+#### lemo.net.disconnect
+```
+lemo.net.disconnect(nodeAddr)
+```
+Disconnect to a LemoChain node
+
+##### Parameters
+1. `string` - ip address
+
+##### Returns
+`Promise` - Call `then` method to get boolean
+
+##### Example
+```js
+lemo.net.disconnect('127.0.0.1:60002').then(function(success) {
+ console.log(sucess ? 'success' : 'fail');
+})
+```
+
+---
+
+
+#### lemo.net.getConnections
+```
+lemo.net.getConnections()
+```
+Get the information of connections
+
+##### Parameters
+None
+
+##### Returns
+`Promise` - Call `then` method to get connection information list
+
+##### Example
+```js
+lemo.net.getConnections().then(function(connections) {
+ console.log(connections);
+ // [{
+ // localAddress: "127.0.0.1:50825",
+ // nodeID: "ddb5fc36c415799e4c0cf7046ddde04aad6de8395d777db4f46ebdf258e55ee1d698fdd6f81a950f00b78bb0ea562e4f7de38cb0adf475c5026bb885ce74afb0",
+ // remoteAddress: "127.0.0.1:60002"
+ // }]
+})
+```
+
+---
+
+
+#### lemo.net.getConnectionsCount
+```
+lemo.net.getConnectionsCount()
+```
+Get the count of connections
+
+##### Parameters
+None
+
+##### Returns
+`Promise` - Call `then` method to get connection count
+
+##### Example
+```js
+lemo.net.getConnectionsCount().then(function(count) {
+ console.log(count); // "1"
+})
+```
+
+---
+
+
+#### lemo.net.getInfo
+```
+lemo.net.getInfo()
+```
+Get current node information
+
+##### Parameters
+None
+
+##### Returns
+`Promise` - Call `then` method to get node information
+
+##### Example
+```js
+lemo.net.getInfo().then(function(info) {
+ console.log(info.nodeName); // "Lemo"
+ console.log(info.nodeVersion); // "1.0.0"
+ console.log(info.os); // "windows-amd64"
+ console.log(info.port); // "60001"
+ console.log(info.runtime); // "go1.10.1"
+})
+```
+
+---
+
+### mine API
+
+
+#### lemo.mine.start
+```
+lemo.mine.start()
+```
+Start mining
+
+##### Parameters
+None
+
+##### Returns
+`Promise` - No data input in `then` function
+
+##### Example
+```js
+lemo.mine.start()
+```
+
+---
+
+
+#### lemo.mine.stop
+```
+lemo.mine.stop()
+```
+Stop mining
+
+##### Parameters
+None
+
+##### Returns
+`Promise` - No data input in `then` function
+
+##### Example
+```js
+lemo.mine.stop()
+```
+
+---
+
+
+#### lemo.mine.getMining
+```
+lemo.mine.getMining()
+```
+True if current LemoChain node is mining
+
+##### Parameters
+None
+
+##### Returns
+`Promise` - Call `then` method to get boolean
+
+##### Example
+```js
+lemo.mine.getMining().then(function(isMining) {
+ console.log(isMining ? 'mining' : 'not mining');
+})
+```
+
+---
+
+
+#### lemo.mine.getMiner
+```
+lemo.mine.getMiner()
+```
+Get the account address to receive mining benefit
+
+##### Parameters
+None
+
+##### Returns
+`Promise` - Call `then` method to get account address
+
+##### Example
+```js
+lemo.mine.getMiner()
+ .then(function(miner) {
+ console.log(miner); // "Lemo83GN72GYH2NZ8BA729Z9TCT7KQ5FC3CR6DJG"
+ })
+```
+
+---
+
+### account API
+
+
+#### lemo.account.newKeyPair
+```
+lemo.account.newKeyPair()
+```
+Create a private key and account address
+
+##### Parameters
+None
+
+##### Returns
+`Promise` - Call `then` method to get account key object
+
+##### Example
+```js
+lemo.account.newKeyPair()
+ .then(function(accountKey) {
+ console.log(accountKey.private); // "0xfdbd9978910ce9e1ed276a75132aacb0a12e6c517d9bd0311a736c57a228ee52"
+ console.log(accountKey.address); // "Lemo83BYKZJ4RN4TKC9C78RFW7YHW6S87TPRSH34"
+ })
+```
+
+---
+
+
+#### lemo.account.getBalance
+```
+lemo.account.getBalance(address)
+```
+Get the balance of an account
+
+##### Parameters
+1. `string` - account address
+
+##### Returns
+`Promise` - Call `then` method to get balance `BigNumber` object
+
+##### Example
+```js
+lemo.account.getBalance('Lemo83BYKZJ4RN4TKC9C78RFW7YHW6S87TPRSH34')
+ .then(function(balance) {
+ console.log(balance.toString(10)); // "1600000000000000000000000000"
+ })
+```
+
+---
+
+
+#### lemo.account.getAccount
+```
+lemo.account.getAccount(address)
+```
+Get the information of an account
+
+##### Parameters
+1. `string` - account address
+
+##### Returns
+`Promise` - Call `then` method to get [account](#data-structure-account) information
+
+##### Example
+```js
+lemo.account.getBalance('Lemo83BYKZJ4RN4TKC9C78RFW7YHW6S87TPRSH34')
+ .then(function(account) {
+ console.log(account.balance.toMoney()); // "1600000000 LEMO"
+ })
+```
+
+---
+
+### tx API
+
+
+#### lemo.tx.sendTx
+```
+lemo.tx.sendTx(privateKey, txInfo)
+```
+Sign and send transaction
+
+##### Parameters
+1. `string` - Account private key
+2. `object` - Unsigned transaction
+ - `type` - (number) (optional) Transaction type. Default value is `0`
+ - `version` - (number) (optional) Transaction encode version. Default value is `0`
+ - `chainId` - (number) (optional) ChainID of LemoChain. Default value is `1`, it represents main net
+ - `to` - (string) (optional) Recipient address. Empty `to` represents a contract creation transaction with contract code in `data` field
+ - `toName` - (string) (optional) Recipient name. It will be checked with `to` for safe
+ - `amount` - (number|string) (optional) Amount in `mo`. Default value is `0`
+ - `gasPrice` - (number|string) (optional) Max gas limit of transaction. Default value is `3000000000`
+ - `gasLimit` - (number|string) (optional) Price of every gas in `mo`. Default value is `2000000`
+ - `data` - (Buffer|string) (optional) The extra data. It usually be using for calling smart contract
+ - `expirationTime` - (number) (optional) The expiration time of transaction in seconds. Default is half hour from now
+ - `message` - (string) (optional) Extra text message from sender
+
+##### Returns
+`Promise` - Call `then` method to get transaction hash
+
+##### Example
+```js
+const txInfo = {to: 'Lemo83BYKZJ4RN4TKC9C78RFW7YHW6S87TPRSH34', amount: 100}
+lemo.tx.sendTx('0xfdbd9978910ce9e1ed276a75132aacb0a12e6c517d9bd0311a736c57a228ee52', txInfo)
+ .then(function(txHash) {
+ console.log(txHash);
+ })
+```
+
+---
+
+
+#### lemo.tx.sign
+```
+lemo.tx.sign(privateKey, txInfo)
+```
+Sign transaction and return the signed transaction string
+The API is used for implement safety offline transaction:
+1. Sign transaction on a offline device
+2. Copy the output string ( untamable ) to a online device
+3. Call [`lemo.tx.send`](submodule-tx-send) to send the transaction to LemoChain
+
+##### Parameters
+1. `string` - Account private key
+2. `object` - Unsigned transaction like the same parameter in [`lemo.tx.sendTx`](submodule-tx-sendTx)
+
+##### Returns
+`Promise` - Call `then` method to get signed [transaction](#data-structure-transaction) information string
+
+##### Example
+```js
+const txInfo = {to: 'Lemo83BYKZJ4RN4TKC9C78RFW7YHW6S87TPRSH34', amount: 100}
+lemo.tx.sign('0xfdbd9978910ce9e1ed276a75132aacb0a12e6c517d9bd0311a736c57a228ee52', txInfo)
+ .then(function(signedTx) {
+ console.log(signedTx);
+ // {"amount":"100","expirationTime":"1535632200","gasLimit":"2000000","gasPrice":"3000000000","r":"0xdefbd406e0aed8a01ac33877a0267ca720e8231b7660d790386ae45686cf8781","s":"0x3de9fea170ec8fba0cd2574878554558616733c45ea03975bb41104bab3bd312","to":"Lemo83BYKZJ4RN4TKC9C78RFW7YHW6S87TPRSH34","v":"0x030001"}
+ })
+```
+
+---
+
+
+#### lemo.tx.send
+```
+lemo.tx.send(signedTxInfo)
+```
+Send a signed transaction
+
+##### Parameters
+1. `object|string` - Signed [transaction](#data-structure-transaction) information. It could be a string which returned by [`lemo.tx.sign`](submodule-tx-sign), as well as an object like the same parameter in [`lemo.tx.sendTx`](submodule-tx-sendTx), but it these fields instead of `type`, `version`, `chainId`:
+ - `r` - (Buffer|string) Signature data
+ - `s` - (Buffer|string) Signature data
+ - `v` - (Buffer|string) This field is combined from transaction `type`, `version`(current is 0), `signature recovery data`, `chainID`
+
+##### Returns
+`Promise` - Call `then` method to get transaction hash
+
+##### Example
+```js
+const txInfo = {to: 'Lemo83BYKZJ4RN4TKC9C78RFW7YHW6S87TPRSH34', amount: 100}
+lemo.tx.sign('0xfdbd9978910ce9e1ed276a75132aacb0a12e6c517d9bd0311a736c57a228ee52', txInfo)
+ .then(function(signedTx) {
+ return lemo.tx.send(signedTx)
+ }).then(function(txHash) {
+ console.log(txHash);
+ })
+```
+
+---
+
+
+#### lemo.tx.watchPendingTx
+```
+lemo.tx.watchPendingTx(callback)
+```
+Listen for new transactions. The callback function will be called at the beginning and every times new transactions come. (unimplemented in 1.0.0)
+
+##### Parameters
+1. `Function` - Used to receive [transaction](#data-structure-transaction) list
+
+##### Returns
+`number` - WatchId for [stop watching](#submodule-stopWatch)
+
+##### Example
+```js
+lemo.watchPendingTx(true, function(transactions) {
+ console.log(transactions.length);
+})
+```
+
+---
+
+### other API
+
+
+#### lemo.stopWatch
+```
+lemo.tx.stopWatch(watchId)
+```
+Stop listening
+
+##### Parameters
+1. `number|undefined` - (optional) The id from `lemo.watchXXX`. If is undefined, then stop all watching
+
+##### Returns
+None
+
+##### Example
+```js
+lemo.stopWatch()
+```
+
+---
+
+
+#### lemo.isWatching
+```
+lemo.tx.isWatching()
+```
+True if is listening
+
+##### Parameters
+None
+
+##### Returns
+`boolean` - True if is listening
+
+##### Example
+```js
+console.log(lemo.isWatching() ? 'watching' : 'not watching')
+```
+
+---
## Developing
diff --git a/README_zh.md b/README_zh.md
index a7ecee9..5d88d4b 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -126,8 +126,8 @@ API | 功能 | 可远程使用
### 数据结构
-#### block
+#### block
```json
{
"header": {},
@@ -145,8 +145,8 @@ API | 功能 | 可远程使用
- `events` 该块中所有交易产生的[合约事件](#data-structure-event)列表
- `deputyNodes` 如果该块是一个`快照块`,则这里保存新一代[共识节点信息](#data-structure-deputyNode)的列表。否则为空
-#### header
+#### header
区块头
```json
{
@@ -155,7 +155,7 @@ API | 功能 | 可远程使用
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"miner": "Lemo83GN72GYH2NZ8BA729Z9TCT7KQ5FC3CR6DJG",
"signData": "0x",
- "timestamp": "1535630400"
+ "timestamp": "1535630400",
"gasLimit": "105000000",
"gasUsed": "0",
"eventBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
@@ -183,8 +183,8 @@ API | 功能 | 可远程使用
- `versionRoot` 该块打包时全局账户版本树的根节点hash
- `extraData` (可选) 出块者向区块中添加的自定义信息
-#### transaction
+#### transaction
交易
```json
{
@@ -223,8 +223,8 @@ chainID | 说明
---|---
1 | LemoChain主网
-#### changeLog
+#### changeLog
交易对链上数据的修改记录
```json
{
@@ -247,25 +247,24 @@ CodeLog | 合约账户创建 | 合约code | -
AddEventLog | 产生一条合约日志 | 合约日志 | -
SuicideLog | 合约账户销毁 | - | -
-#### confirm
+#### confirm
共识节点验证区块通过后,对该块hash的签名
```
0x1234
```
-#### event
+#### event
合约事件
```json
{
- "address": "Lemo83GN72GYH2NZ8BA729Z9TCT7KQ5FC3CR6DJG",
- ...
+ "address": "Lemo83GN72GYH2NZ8BA729Z9TCT7KQ5FC3CR6DJG"
}
```
-#### deputyNode
+#### deputyNode
共识节点的信息
```json
{
@@ -280,12 +279,12 @@ SuicideLog | 合约账户销毁 | - | -
- `ip` 节点的ip地址
- `minerAddress` 节点的Lemo收益账号地址
- `nodeID` 节点的ID,即节点对区块签名时的私钥对应的公钥
-- `port` 节点的端口号
+- `port` 与其它节点链接用的端口号
- `rank` 节点的排名
- `votes` 节点的总票数
-#### account
+#### account
账户信息
```json
{
@@ -293,8 +292,8 @@ SuicideLog | 合约账户销毁 | - | -
"balance": "1599999999999999999999999900",
"records": {
"BalanceLog": {
- version: "3",
- height: "1"
+ "version": "3",
+ "height": "1"
}
},
"codeHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
@@ -315,14 +314,15 @@ lemo = new LemoClient({
host: 'http://127.0.0.1:8001'
})
```
-- `host` LemoChain节点的地址。默认值`http://127.0.0.1:8001`
+- `host` LemoChain节点的HTTP连接地址。默认值`http://127.0.0.1:8001`
> 注意: 如果连接后出现跨域问题,则需要用参数`--rpccorsdomain http://sdk所在web的域名:端口号`的方式启动LemoChain节点
+---
### chain模块API
-#### lemo.getBlock
+#### lemo.getBlock
```
lemo.getBlock(heightOrHash [, withBody])
```
@@ -344,8 +344,8 @@ lemo.getBlock(0).then(function(block) {
---
-#### lemo.getCurrentBlock
+#### lemo.getCurrentBlock
```
lemo.getCurrentBlock([stable [, withBody]])
```
@@ -367,8 +367,8 @@ lemo.getCurrentBlock(true).then(function(block) {
---
-#### lemo.getCurrentHeight
+#### lemo.getCurrentHeight
```
lemo.getCurrentHeight([stable])
```
@@ -389,8 +389,8 @@ lemo.getCurrentHeight(true).then(function(height) {
---
-#### lemo.getGenesis
+#### lemo.getGenesis
```
lemo.getGenesis()
```
@@ -411,8 +411,8 @@ lemo.getGenesis().then(function(height) {
---
-#### lemo.getChainID
+#### lemo.getChainID
```
lemo.getChainID()
```
@@ -433,8 +433,8 @@ lemo.getChainID().then(function(chainID) {
---
-#### lemo.getGasPriceAdvice
+#### lemo.getGasPriceAdvice
```
lemo.getGasPriceAdvice()
```
@@ -455,8 +455,8 @@ lemo.getGasPriceAdvice().then(function(gasPrice) {
---
-#### lemo.getNodeVersion
+#### lemo.getNodeVersion
```
lemo.getNodeVersion()
```
@@ -477,8 +477,8 @@ lemo.getNodeVersion().then(function(version) {
---
-#### lemo.getSdkVersion
+#### lemo.getSdkVersion
```
lemo.getSdkVersion()
```
@@ -499,8 +499,8 @@ lemo.getSdkVersion().then(function(version) {
---
-#### lemo.watchBlock
+#### lemo.watchBlock
```
lemo.watchBlock(withBody, callback)
```
@@ -525,8 +525,8 @@ lemo.watchBlock(true, function(block) {
### net模块API
-#### lemo.net.connect
+#### lemo.net.connect
```
lemo.net.connect(nodeAddr)
```
@@ -545,8 +545,8 @@ lemo.net.connect('127.0.0.1:60002')
---
-#### lemo.net.disconnect
+#### lemo.net.disconnect
```
lemo.net.disconnect(nodeAddr)
```
@@ -567,8 +567,8 @@ lemo.net.disconnect('127.0.0.1:60002').then(function(success) {
---
-#### lemo.net.getConnections
+#### lemo.net.getConnections
```
lemo.net.getConnections()
```
@@ -594,8 +594,8 @@ lemo.net.getConnections().then(function(connections) {
---
-#### lemo.net.getConnectionsCount
+#### lemo.net.getConnectionsCount
```
lemo.net.getConnectionsCount()
```
@@ -616,8 +616,8 @@ lemo.net.getConnectionsCount().then(function(count) {
---
-#### lemo.net.getInfo
+#### lemo.net.getInfo
```
lemo.net.getInfo()
```
@@ -627,7 +627,7 @@ lemo.net.getInfo()
无
##### Returns
-`Promise` - 通过`then`可以获取到连接数
+`Promise` - 通过`then`可以获取到节点信息
##### Example
```js
@@ -644,8 +644,8 @@ lemo.net.getInfo().then(function(info) {
### mine模块API
+
#### lemo.mine.start
-
```
lemo.mine.start()
```
@@ -664,8 +664,8 @@ lemo.mine.start()
---
-#### lemo.mine.stop
+#### lemo.mine.stop
```
lemo.mine.stop()
```
@@ -684,8 +684,8 @@ lemo.mine.stop()
---
-#### lemo.mine.getMining
+#### lemo.mine.getMining
```
lemo.mine.getMining()
```
@@ -706,8 +706,8 @@ lemo.mine.getMining().then(function(isMining) {
---
-#### lemo.mine.getMiner
+#### lemo.mine.getMiner
```
lemo.mine.getMiner()
```
@@ -731,8 +731,8 @@ lemo.mine.getMiner()
### account模块API
-#### lemo.account.newKeyPair
+#### lemo.account.newKeyPair
```
lemo.account.newKeyPair()
```
@@ -755,8 +755,8 @@ lemo.account.newKeyPair()
---
-#### lemo.account.getBalance
+#### lemo.account.getBalance
```
lemo.account.getBalance(address)
```
@@ -778,8 +778,8 @@ lemo.account.getBalance('Lemo83BYKZJ4RN4TKC9C78RFW7YHW6S87TPRSH34')
---
-#### lemo.account.getAccount
+#### lemo.account.getAccount
```
lemo.account.getAccount(address)
```
@@ -803,8 +803,8 @@ lemo.account.getBalance('Lemo83BYKZJ4RN4TKC9C78RFW7YHW6S87TPRSH34')
### tx模块API
-#### lemo.tx.sendTx
+#### lemo.tx.sendTx
```
lemo.tx.sendTx(privateKey, txInfo)
```
@@ -812,18 +812,18 @@ lemo.tx.sendTx(privateKey, txInfo)
##### Parameters
1. `string` - 账户私钥
-2. `object` - 签名前的[交易信息](#data-structure-transaction)
- - `type` - `{number}` (选填) 交易类型,默认值为0
- - `version` - `{number}` (选填) 交易编码版本号,默认值为0
- - `chainId` - `{number}` (选填) 区块链的chainID,默认值为1,即LemoChain主链
- - `to` - `{string}` (选填) 交易接收者的账户地址。为空表示这是创建智能合约的交易,必须携带`data`
- - `toName` - `{string}` (选填) 交易接收者的账户名,会与账户地址进行比对校验。类似银行转账时填写的姓名与卡号的关系
- - `amount` - `{number|string}` (选填) 交易金额,单位`mo`,默认值为0
- - `gasPrice` - `{number|string}` (选填) 交易消耗的gas上限,默认值为3000000000
- - `gasLimit` - `{number|string}` (选填) 交易消耗gas的单价,单位为`mo`,默认值为2000000
- - `data` - `{Buffer|string}` (选填) 交易附带的数据,可用于调用智能合约,默认为空
- - `expirationTime` - `{number}` (选填)交易过期时间戳,单位为秒,默认值为半小时后
- - `message` - `{string}` (选填)交易附带的文本消息,默认为空
+2. `object` - 签名前的交易信息
+ - `type` - (number) (选填) 交易类型,默认值为`0`
+ - `version` - (number) (选填) 交易编码版本号,默认值为`0`
+ - `chainId` - (number) (选填) 区块链的chainID,默认值为`1`,即LemoChain主链
+ - `to` - (string) (选填) 交易接收者的账户地址。为空表示这是创建智能合约的交易,必须携带`data`
+ - `toName` - (string) (选填) 交易接收者的账户名,会与账户地址进行比对校验。类似银行转账时填写的姓名与卡号的关系
+ - `amount` - (number|string) (选填) 交易金额,单位`mo`,默认值为`0`
+ - `gasPrice` - (number|string) (选填) 交易消耗的gas上限,默认值为`3000000000`
+ - `gasLimit` - (number|string) (选填) 交易消耗gas的单价,单位为`mo`,默认值为`2000000`
+ - `data` - (Buffer|string) (选填) 交易附带的数据,可用于调用智能合约,默认为空
+ - `expirationTime` - (number) (选填)交易过期时间戳,单位为秒,默认值为半小时后
+ - `message` - (string) (选填)交易附带的文本消息,默认为空
##### Returns
`Promise` - 通过`then`可以获取到交易hash
@@ -839,19 +839,23 @@ lemo.tx.sendTx('0xfdbd9978910ce9e1ed276a75132aacb0a12e6c517d9bd0311a736c57a228ee
---
-#### lemo.tx.sign
+#### lemo.tx.sign
```
lemo.tx.sign(privateKey, txInfo)
```
-签名交易并返回出签名后的交易信息字符串。可以在离线电脑上签名,再将签名后的数据拷到联网电脑上,通过[`lemo.tx.send`](submodule-tx-send)方法发送出去
+签名交易并返回出签名后的交易信息字符串
+该方法用于实现安全的离线交易
+1. 在离线电脑上签名
+2. 将签名后的数据拷贝到联网电脑上
+3. 通过[`lemo.tx.send`](submodule-tx-send)方法发送到LemoChain
##### Parameters
1. `string` - 账户私钥
2. `object` - 签名前的交易信息,细节参考[`lemo.tx.sendTx`](submodule-tx-sendTx)
##### Returns
-`Promise` - 通过`then`可以获取到签名后的交易信息字符串
+`Promise` - 通过`then`可以获取到签名后的[交易](#data-structure-transaction)信息字符串
##### Example
```js
@@ -865,19 +869,19 @@ lemo.tx.sign('0xfdbd9978910ce9e1ed276a75132aacb0a12e6c517d9bd0311a736c57a228ee52
---
-#### lemo.tx.send
+#### lemo.tx.send
```
lemo.tx.send(signedTxInfo)
```
发送已签名的交易
##### Parameters
-1. `object|string` - 签名后的交易信息,可以是对象形式也可以是[`lemo.tx.sign`](submodule-tx-sign)返回的字符串形式
+1. `object|string` - 签名后的[交易](#data-structure-transaction)信息,可以是对象形式也可以是[`lemo.tx.sign`](submodule-tx-sign)返回的字符串形式
相对于[`lemo.tx.sendTx`](submodule-tx-sendTx)中的交易信息少了`type`、`version`、`chainId`字段,并多出了以下字段
- - `r` - `{Buffer|string}` 交易签名字段
- - `s` - `{Buffer|string}` 交易签名字段
- - `v` - `{Buffer|string}` `type`、`version`、交易签名字段、`chainId`这4个字段组合而成的数据
+ - `r` - (Buffer|string) 交易签名字段
+ - `s` - (Buffer|string) 交易签名字段
+ - `v` - (Buffer|string) `type`、`version`、交易签名字段、`chainId`这4个字段组合而成的数据
##### Returns
`Promise` - 通过`then`可以获取到交易hash
@@ -895,8 +899,8 @@ lemo.tx.sign('0xfdbd9978910ce9e1ed276a75132aacb0a12e6c517d9bd0311a736c57a228ee52
---
-#### lemo.tx.watchPendingTx
+#### lemo.tx.watchPendingTx
```
lemo.tx.watchPendingTx(callback)
```
@@ -919,8 +923,8 @@ lemo.watchPendingTx(true, function(transactions) {
### 其它API
-#### lemo.stopWatch
+#### lemo.stopWatch
```
lemo.tx.stopWatch(watchId)
```
@@ -939,8 +943,8 @@ lemo.stopWatch()
---
-#### lemo.isWatching
+#### lemo.isWatching
```
lemo.tx.isWatching()
```