From 70aa0c38e81b8004c374ef623e1492ab20225d75 Mon Sep 17 00:00:00 2001 From: Celia18305 <32253925+Celia18305@users.noreply.github.com> Date: Mon, 11 Feb 2019 17:17:33 +0800 Subject: [PATCH] fix broken links - 1 (#751) --- en-us/exchange/v2.6.0.md | 698 -------------- en-us/exchange/v2.7.1.md | 813 ----------------- en-us/exchange/v2.7.3.md | 851 ------------------ en-us/exchange/v2.7.4.md | 851 ------------------ en-us/network/private-chain/private-chain.md | 2 +- en-us/node/cli/2.9.2/api.md | 160 ++++ en-us/node/cli/2.9.2/api/dumpprivkey.md | 37 + en-us/node/cli/2.9.2/api/getaccountstate.md | 57 ++ en-us/node/cli/2.9.2/api/getassetstate.md | 59 ++ en-us/node/cli/2.9.2/api/getbalance.md | 93 ++ en-us/node/cli/2.9.2/api/getbestblockhash.md | 30 + en-us/node/cli/2.9.2/api/getblock.md | 86 ++ en-us/node/cli/2.9.2/api/getblock2.md | 86 ++ en-us/node/cli/2.9.2/api/getblockcount.md | 26 + en-us/node/cli/2.9.2/api/getblockhash.md | 30 + en-us/node/cli/2.9.2/api/getblockheader.md | 71 ++ en-us/node/cli/2.9.2/api/getblocksysfee.md | 34 + .../node/cli/2.9.2/api/getconnectioncount.md | 26 + en-us/node/cli/2.9.2/api/getcontractstate.md | 48 + en-us/node/cli/2.9.2/api/getnewaddress.md | 33 + en-us/node/cli/2.9.2/api/getpeers.md | 103 +++ en-us/node/cli/2.9.2/api/getrawmempool.md | 32 + en-us/node/cli/2.9.2/api/getrawtransaction.md | 92 ++ en-us/node/cli/2.9.2/api/getstorage.md | 33 + en-us/node/cli/2.9.2/api/gettxout.md | 37 + en-us/node/cli/2.9.2/api/getvalidators.md | 74 ++ en-us/node/cli/2.9.2/api/getversion.md | 30 + en-us/node/cli/2.9.2/api/getwalletheight.md | 26 + en-us/node/cli/2.9.2/api/invoke.md | 59 ++ en-us/node/cli/2.9.2/api/invokefunction.md | 93 ++ en-us/node/cli/2.9.2/api/invokescript.md | 45 + en-us/node/cli/2.9.2/api/listaddress.md | 48 + en-us/node/cli/2.9.2/api/sendfrom.md | 91 ++ en-us/node/cli/2.9.2/api/sendmany.md | 139 +++ .../node/cli/2.9.2/api/sendrawtransaction.md | 38 + en-us/node/cli/2.9.2/api/sendtoaddress.md | 87 ++ en-us/node/cli/2.9.2/api/validateaddress.md | 60 ++ en-us/node/cli/2.9.3/api.md | 160 ++++ en-us/node/cli/2.9.3/api/dumpprivkey.md | 37 + en-us/node/cli/2.9.3/api/getaccountstate.md | 57 ++ en-us/node/cli/2.9.3/api/getassetstate.md | 59 ++ en-us/node/cli/2.9.3/api/getbalance.md | 93 ++ en-us/node/cli/2.9.3/api/getbestblockhash.md | 30 + en-us/node/cli/2.9.3/api/getblock.md | 86 ++ en-us/node/cli/2.9.3/api/getblock2.md | 86 ++ en-us/node/cli/2.9.3/api/getblockcount.md | 26 + en-us/node/cli/2.9.3/api/getblockhash.md | 30 + en-us/node/cli/2.9.3/api/getblockheader.md | 71 ++ en-us/node/cli/2.9.3/api/getblocksysfee.md | 34 + .../node/cli/2.9.3/api/getconnectioncount.md | 26 + en-us/node/cli/2.9.3/api/getcontractstate.md | 48 + en-us/node/cli/2.9.3/api/getnewaddress.md | 33 + en-us/node/cli/2.9.3/api/getpeers.md | 103 +++ en-us/node/cli/2.9.3/api/getrawmempool.md | 32 + en-us/node/cli/2.9.3/api/getrawtransaction.md | 92 ++ en-us/node/cli/2.9.3/api/getstorage.md | 33 + en-us/node/cli/2.9.3/api/gettxout.md | 37 + en-us/node/cli/2.9.3/api/getvalidators.md | 74 ++ en-us/node/cli/2.9.3/api/getversion.md | 30 + en-us/node/cli/2.9.3/api/getwalletheight.md | 26 + en-us/node/cli/2.9.3/api/invoke.md | 59 ++ en-us/node/cli/2.9.3/api/invokefunction.md | 93 ++ en-us/node/cli/2.9.3/api/invokescript.md | 45 + en-us/node/cli/2.9.3/api/listaddress.md | 48 + en-us/node/cli/2.9.3/api/sendfrom.md | 91 ++ en-us/node/cli/2.9.3/api/sendmany.md | 139 +++ .../node/cli/2.9.3/api/sendrawtransaction.md | 38 + en-us/node/cli/2.9.3/api/sendtoaddress.md | 87 ++ en-us/node/cli/2.9.3/api/validateaddress.md | 60 ++ zh-cn/exchange/v2.6.0.md | 701 --------------- zh-cn/exchange/v2.7.1.md | 802 ----------------- zh-cn/exchange/v2.7.3.md | 841 ----------------- zh-cn/exchange/v2.7.4.md | 839 ----------------- 73 files changed, 3927 insertions(+), 6397 deletions(-) delete mode 100644 en-us/exchange/v2.6.0.md delete mode 100644 en-us/exchange/v2.7.1.md delete mode 100644 en-us/exchange/v2.7.3.md delete mode 100644 en-us/exchange/v2.7.4.md create mode 100644 en-us/node/cli/2.9.2/api.md create mode 100644 en-us/node/cli/2.9.2/api/dumpprivkey.md create mode 100644 en-us/node/cli/2.9.2/api/getaccountstate.md create mode 100644 en-us/node/cli/2.9.2/api/getassetstate.md create mode 100644 en-us/node/cli/2.9.2/api/getbalance.md create mode 100644 en-us/node/cli/2.9.2/api/getbestblockhash.md create mode 100644 en-us/node/cli/2.9.2/api/getblock.md create mode 100644 en-us/node/cli/2.9.2/api/getblock2.md create mode 100644 en-us/node/cli/2.9.2/api/getblockcount.md create mode 100644 en-us/node/cli/2.9.2/api/getblockhash.md create mode 100644 en-us/node/cli/2.9.2/api/getblockheader.md create mode 100644 en-us/node/cli/2.9.2/api/getblocksysfee.md create mode 100644 en-us/node/cli/2.9.2/api/getconnectioncount.md create mode 100644 en-us/node/cli/2.9.2/api/getcontractstate.md create mode 100644 en-us/node/cli/2.9.2/api/getnewaddress.md create mode 100644 en-us/node/cli/2.9.2/api/getpeers.md create mode 100644 en-us/node/cli/2.9.2/api/getrawmempool.md create mode 100644 en-us/node/cli/2.9.2/api/getrawtransaction.md create mode 100644 en-us/node/cli/2.9.2/api/getstorage.md create mode 100644 en-us/node/cli/2.9.2/api/gettxout.md create mode 100644 en-us/node/cli/2.9.2/api/getvalidators.md create mode 100644 en-us/node/cli/2.9.2/api/getversion.md create mode 100644 en-us/node/cli/2.9.2/api/getwalletheight.md create mode 100644 en-us/node/cli/2.9.2/api/invoke.md create mode 100644 en-us/node/cli/2.9.2/api/invokefunction.md create mode 100644 en-us/node/cli/2.9.2/api/invokescript.md create mode 100644 en-us/node/cli/2.9.2/api/listaddress.md create mode 100644 en-us/node/cli/2.9.2/api/sendfrom.md create mode 100644 en-us/node/cli/2.9.2/api/sendmany.md create mode 100644 en-us/node/cli/2.9.2/api/sendrawtransaction.md create mode 100644 en-us/node/cli/2.9.2/api/sendtoaddress.md create mode 100644 en-us/node/cli/2.9.2/api/validateaddress.md create mode 100644 en-us/node/cli/2.9.3/api.md create mode 100644 en-us/node/cli/2.9.3/api/dumpprivkey.md create mode 100644 en-us/node/cli/2.9.3/api/getaccountstate.md create mode 100644 en-us/node/cli/2.9.3/api/getassetstate.md create mode 100644 en-us/node/cli/2.9.3/api/getbalance.md create mode 100644 en-us/node/cli/2.9.3/api/getbestblockhash.md create mode 100644 en-us/node/cli/2.9.3/api/getblock.md create mode 100644 en-us/node/cli/2.9.3/api/getblock2.md create mode 100644 en-us/node/cli/2.9.3/api/getblockcount.md create mode 100644 en-us/node/cli/2.9.3/api/getblockhash.md create mode 100644 en-us/node/cli/2.9.3/api/getblockheader.md create mode 100644 en-us/node/cli/2.9.3/api/getblocksysfee.md create mode 100644 en-us/node/cli/2.9.3/api/getconnectioncount.md create mode 100644 en-us/node/cli/2.9.3/api/getcontractstate.md create mode 100644 en-us/node/cli/2.9.3/api/getnewaddress.md create mode 100644 en-us/node/cli/2.9.3/api/getpeers.md create mode 100644 en-us/node/cli/2.9.3/api/getrawmempool.md create mode 100644 en-us/node/cli/2.9.3/api/getrawtransaction.md create mode 100644 en-us/node/cli/2.9.3/api/getstorage.md create mode 100644 en-us/node/cli/2.9.3/api/gettxout.md create mode 100644 en-us/node/cli/2.9.3/api/getvalidators.md create mode 100644 en-us/node/cli/2.9.3/api/getversion.md create mode 100644 en-us/node/cli/2.9.3/api/getwalletheight.md create mode 100644 en-us/node/cli/2.9.3/api/invoke.md create mode 100644 en-us/node/cli/2.9.3/api/invokefunction.md create mode 100644 en-us/node/cli/2.9.3/api/invokescript.md create mode 100644 en-us/node/cli/2.9.3/api/listaddress.md create mode 100644 en-us/node/cli/2.9.3/api/sendfrom.md create mode 100644 en-us/node/cli/2.9.3/api/sendmany.md create mode 100644 en-us/node/cli/2.9.3/api/sendrawtransaction.md create mode 100644 en-us/node/cli/2.9.3/api/sendtoaddress.md create mode 100644 en-us/node/cli/2.9.3/api/validateaddress.md delete mode 100644 zh-cn/exchange/v2.6.0.md delete mode 100644 zh-cn/exchange/v2.7.1.md delete mode 100644 zh-cn/exchange/v2.7.3.md delete mode 100644 zh-cn/exchange/v2.7.4.md diff --git a/en-us/exchange/v2.6.0.md b/en-us/exchange/v2.6.0.md deleted file mode 100644 index 04e7aa440b..0000000000 --- a/en-us/exchange/v2.6.0.md +++ /dev/null @@ -1,698 +0,0 @@ -# Document for Exchange Developers - -> [!Note] -> -> This document provides information based on [Neo CLI v2.6.0](https://github.com/neo-project/neo-cli/releases/tag/v2.6.0). - -In general, an exchange needs to do the following: - -- [Deploying a NEO Node on Server](#deploying-a-neo-node-on-server) -- [Creating a Wallet and Deposit Addresses](#creating-a-wallet-and-deposit-addresses) -- [Dealing with Global Assets Transactions](#dealing-with-global-assets-transactions) -- [Dealing with NEP-5 Assets Transactions](#dealing-with-nep-5-assets-transactions) -- [(Optional) Distributing GAS to Users](#optional-distributing-gas-to-users) - - - -## Deploying a NEO Node on Server - -To deploy a NEO node on the exchange server, do the following: - -1. Install [.NET Core Runtime](https://www.microsoft.com/net/download/core#/runtime) on the server, 2.0 and the later version. -2. From Github, download the [Neo-CLI](https://github.com/neo-project/neo-cli/releases) program and enable the NEO node. - -For more information, refer to [Installation and deployment of NEO node](../node/cli/setup.md). - -## Creating a Wallet and Deposit Addresses - -### About NEO-CLI - -NEO-CLI is a command-line client (wallet) for developers. Developers have two ways to interact with it: - -- Using the CLI (command-line interface) commands. For example, you can create a wallet, generate an address, etc. -- Using the Remote Procedure Call (RPC). For example, you can transfer to the designated address, acquire the block information of the designated height, acquire the information of the designated trade, etc. - -NEO-CLI provides the following features: - -- As a wallet, manages assets through the command-line. - - To enable the wallet,enter the following command under the NEO-CLI directory: - - ``` - dotnet neo-cli.dll - ``` - - To check all the available commands, enter the following command: - - ``` - help - ``` - - For more information, refer to [CLI Command Reference](../node/cli/cli.md). - -- Provides APIs to retrieve blockchain data from nodes. The interfaces are provided through [JSON-RPC](http://www.jsonrpc.org/specification),and the underlying communications use HTTP/HTTPS protocols. - - To start a node which provides RPC service, enter the following command under the NEO-CLI directory: - - ``` - dotnet neo-cli.dll /rpc - ``` - - For more API information, refer to [API Reference](../node/cli/apigen.md). - - -### Creating a Wallet - -The exchange needs to create an online wallet to manage the deposit addresses of users. A wallet is used to store the information of the accounts (both public keys and private keys) and the contracts. It is the most important proof that the user holds. Users must keep the wallet files and the wallet passwords secure. They must not lose or disclose these data. - -> [!Note] -> -> Exchanges do not have to create a wallet for every address. An online wallet usually keeps all deposit addresses of users. A cold wallet (offline wallet) is another storage option which provides better security. - -To create a wallet, do the following: - -1. enter `create wallet `. - - is the wallet path and wallet file name. The file extension can be any type, for example, create wallet mywallet.db3. - -2. Set a password for the wallet. - -> [!Note] -> -> The wallet must be kept open all the time to respond to the withdrawal requests of users. For security reasons, the wallets should be run in an independent server on which the firewall is configured properly, as shown below. - -| | Mainnet | Testnet | -| ------------------ | ------- | ------- | -| JSON-RPC via HTTPS | 10331 | 20331 | -| JSON-RPC via HTTP | 10332 | 20332 | -| P2P | 10333 | 20333 | -| websocket | 10334 | 20334 | - -### Generating Deposit Addresses - -A wallet can store multiple addresses. The exchange needs to generate a deposit address for each user. - -There are two methods to generate deposit addresses: - -- When the user deposit (NEO/NEO GAS) for the first time, the program dynamically generates a NEO address. The advantage is that there is no need to generate addresses at fixed time intervals, while the disadvantage is you can not backup the wallet. - - To develop the program to dynamically generate addresses, use the NEO-CLI API [getnewaddress Method](../node/cli/2.6.0/api/getnewaddress.md). The created address is returned. - -- The exchange creates a batch of NEO addresses in advance. When the user charges (NEO/NEO GAS) for the first time, the exchange assigns a NEO address to him or her. The advantage is the convenience to backup the wallet, while the disadvantage is the need to generate NEO addresses manually. - To generate addresses in batch, run the NEO- CLI command `create address [n]`. The addresses are exported automatically to the address.txt file. - [n] is optional. Its default value is 1. For example, to generate 100 addresses at a time, enter `create address 100`. - - -> [!Note] -> -> Either way, the exchange must import the addresses into the database and distribute them to users. - -## Dealing with Global Assets Transactions - -### Developing Programs for User Deposits and Withdrawals - -For global assets, the exchange needs to develop programs to fulfil the following functions: - -1. Monitor new blocks through NEO-CLI API ([getblock Method](../node/cli/2.6.0/api/getblock2.md)). -2. Deal with user deposits according to the transaction information. -3. Store the transaction records related to the exchange. - -#### User Deposits - -Regarding user deposits, the exchange needs to note the following: - -- NEO blockchain has only one main chain without side chains, will not fork, and will not have isolated blocks. -- A transaction recorded in NEO blockchain cannot be tampered with, which means a confirmation represents a deposit success. -- In general, the balance of a deposit address in the exchange is not equal to the balance the user has in the exchange. It may because: - - When transferring or withdrawing, the NEO wallet looks through one or more addresses in the wallet, finds the minimal loose change that meets the requirement and adds up to the total sum of the transaction and then serves that as the input, instead of withdrawing from the specified address (unless the exchange rewrites some functions of NEO wallet to meet their own needs). - - Other operations that may lead to balance inequality, for example, the exchange transfers part of the assets to its cold wallets. -- There are more than two assets (NEO and NEO GAS) in a NEO address. More assets issued by users (such as stock or token) can be stored. The exchange should determine the assets type when the user deposits. Neither regard other assets as NEO shares or NEO nor confuse the withdrawal of NEO with NEO GAS. -- NEO wallet is a full node, which needs to stay online to synchronize blocks. You can view the block synchronization status through the show state in the CLI, where the left side is the local block height, and the right side is the node block height. -- In the exchange, the transfer between users should not be recorded through the blockchain. In general, the user's balance are modified in the database directly. Only deposits and withdrawals should be recorded on the blockchain. - -#### Deposit Records - -The exchange needs to write code to monitor every transaction in a block and record all the transactions related to the exchange addresses in the database. If a deposit occurs, the user's balance should be updated. - -Developers can use the `getblock [verbose]` method of NEO-CLI API to retrieve the block information. `` is the block index. `[verbose]` is 0 by default. When `[verbose]` is 0, the method returns the serialized block information in Hexadecimal. You should deserialize the hex string to get the detailed information of the block. When `[verbose]` is 1, the method returns the detailed information of the corresponding block in JSON format. For more information, refer to [getblock Method](../node/cli/2.6.0/api/getblock2.md). - -The block information includes the transactions input and output. The exchange needs to record all its related transactions. The transactions output is in fact the transaction records of the withdrawals of a user. When the exchange sees any of its addresses in the output of the transactions, it updates the NEO/NEO GAS balance of the corresponding user who owns this deposit address. Some exchanges may also do as follows: if it finds an address within the exchange as the output of the transaction, then it records the deposit in its database and modifies the user’s balance after several confirmations (Unless it needs to comply with the operation of other blockchains, this way is not recommended) . - -> [!Note] -> -> - Method getblockcount returns the count of the blocks in the main chain. The first parameter of Method getblock is `` which is the block index. Block index = Block height = The count of the blocks – 1. If getblockcount returns 1234, you should use getblock 1233 to get the information of the latest block. -> - The deposit and withdrawal transactions (NEO/NEO GAS) are all in a type named ContractTransaction. The exchanges only need to care about the ones of ContractTransaction type when they check through the transactions in a block. -> - As the first transaction of every block must be MinerTransaction, you can neglect or jump over it when traversing the blockchain. -> - NEO system takes the transaction as a record unit. -> - -### Dealing with User Withdrawals - -To deal with the user withdrawals for global assets, the exchange needs to do the following: - -1. In NEO-CLI, run `open wallet ` to open the wallet. - -2. Record the user withdrawal transaction and modify the user balance. - -3. (Optional) Customer service deals with withdrawal application. - -4. Send transaction to the user's withdrawal address using the NEO-CLI API method, `sendtoaddress
`. For more information, refer to [sendtoaddress Method](../node/cli/2.6.0/api/sendtoaddress.md). - - - `` :Asset ID - - `
` :Withdrawal address - - `` :Withdrawal amount - - You can also send the transaction to a batch of addresses using API [sendmany Method](../node/cli/2.6.0/api/sendmany.md). - -5. Extract the transaction ID from the returned transaction details in the JSON format, and then record in the database. - -6. Once confirmed by the blockchain, mark the withdrawal transaction as success. - - Similar to deposit monitoring, withdrawals also need to be monitored. If the withdrawal transaction ID is found in the blockchain, it means this transaction has already been confirmed and is a successful withdrawal. - -> [!Note] -> -> - The here refers to the actual amount, instead of the amount multiplied by 10^8. -> - NEO transfer amount must be an integer; otherwise, the blockchain will not confirm it since the loose change in the wallet will be inaccurate. It will be needed to rebuild wallet index, which is to recalculate the transactions and change of the wallet. - -## Dealing with NEP-5 Assets Transactions - -### Receiving User Deposits Notifications - -For NEP-5 assets, the exchange needs to get the notification of users' deposits. The notification for each block is recorded in a JSON file, which includes all information of every NEP-5 transaction. - -To get notification files, run the following command: - -``` -dotnet neo-cli.dll --rpc --record-notifications -``` - -A folder "Notifications" is generated under the root path, as shown below: - - -![1](../../assets/notification_1.jpg) - -#### ![2](../../assets/notification_2.jpg) - - -#### Notifications JSON File - -The following shows an example of the notification file content. - -```json -[ -{ - "txid": "0x65d62a736a73c4d15dc4e4d0bfc1e4bbc4ef220e163625d770eb05577b1afdee", - "contract": "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "state": - { - "type": "Array", - "value": [ - { - "type": "ByteArray", - "value": "7472616e73666572" - }, - { - "type": "ByteArray", - "value": "d336d7eb9975a29b2404fdb28185e277a4b299bc" - }, - { - "type": "ByteArray", - "value": "eab336cac807707295afa7e7da2f4683237f612a" - }, - { - "type": "ByteArray", - "value": "006ad42d100100" - }] - } -}] -``` - -In this file, there is an array of notifications with only one object, which means only one NEP-5 event is triggered in the block. The parameters related to a transaction in the file are the following: - -- **contract**: the script hash of smart contract, by which the exchange can identify assets type. For example, "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9" is the script hash and the unique identification of the RPX asset. - -- The four objects included in the "state" array: - - [event, from account, to account, amount] - - ```json - { - "type": "ByteArray", - "value": "7472616e73666572" - } - ``` - - - The first object with the type "bytearray" and the value "7472616e73666572", as shown in the example, can be converted to the string "transfer". "transfer" is a method in NEP5 that represents an asset transfer. - - The second object in the array is the account address where the asset is transferred from. Its type "bytearray" and the value "d336d7eb9975a29b2404fdb28185e277a4b299bc“ can be converted to "Ab2fvZdmnM4HwDgVbdBrbTLz1wK5TcEyhU". Note that for the hexadecimal string with "0x" prefix, it is processed as big endian; otherwise, it is processed as small endian. - - The third object in the array is the account address where the asset is transferred to. If the address is an exchange account address, it is a deposit transaction. - - The fourth object in the array is the transfer amount. There are two types of amount, integer and bytearray. When dealing with this value, the exchange should pay special attention for transactions of the integer type. - -### Querying User Balance - -To query the user's balance, the exchange needs to do the following: - -1. Construct JSON files to invoke three methods (`balanceOf`, `decimals`, and `symbol`) through the PRC API invokefunction. -2. Send the JSON files to NEO RPC server. -3. Calculate the user balance according to the returned values. - -#### invokefunction - -In JSON, a general invokefunction request body is in the following form: - -``` -{ - "jsonrpc": "2.0", - "method": "invokefunction", - "params": [ - "script hash", - "method name", - [ - { - "optional arguments" - } - ] - ], - "id": 1 -} -``` - -You need to replace these strings when querying the user's balance: - -- script hash - - The script hash of the NEP-5 token you are querying. For example, you can find the script hash of RPX is : *0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9*. - - -- method name - - The name of the method you are invoking. To query the user's balance, you need to invoke these three methods: - - **balanceOf** - - - Syntax: `public static BigInteger balanceOf(byte[] account)` - - Remarks: "balanceOf" returns the token balance of the '''account'''. - - **decimals** - - - Syntax: `public static byte decimals()` - - Remarks: "decimals" returns the number of decimals used by the token. - - **symbol** - - - Syntax: `public static string symbol()` - - Remarks: "symbol" returns the token symbol. - - -- optional arguments - - Optional. If the method you are invoking requires arguments, you can pass them by constructing these parameters into an array. For example, "balanceOf" in NEP-5 returns the token balance of the "account": - - `public static BigInteger balanceOf(byte[] account)` - - So you need to pass the account as an argument in the "balanceOf" method. - -#### Example - -##### **Invoking balanceOf** - -Suppose the account address is AJShjraX4iMJjwVt8WYYzZyGvDMxw6Xfbe, you need to convert it into Hash160 type and construct this parameter as a JSON object: - -```json -{ - "type": "Hash160", - "value": "bfc469dd56932409677278f6b7422f3e1f34481d" -} -``` - -Then you can construct the JSON message as the following: - -Request Body: - -```json -{ - "jsonrpc": "2.0", - "method": "invokefunction", - "params": [ - "ecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "balanceOf", - [ - { - "type": "Hash160", - "value": "bfc469dd56932409677278f6b7422f3e1f34481d" - } - ] - ], - "id": 3 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 3, - "result": { - "state": "HALT, BREAK", - "gas_consumed": "0.338", - "stack": [ - { - "type": "ByteArray", - "value": "00e1f505" - } - ] - } -} -``` - -It returns "00e1f505" which can be converted to interger 100000000. - -##### **Invoking decimals** - -Request Body: - -```json -{ - "jsonrpc": "2.0", - "method": "invokefunction", - "params": [ - "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "decimals", - [] - ], - "id": 2 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 2, - "result": { - "state": "HALT, BREAK", - "gas_consumed": "0.156", - "stack": [ - { - "type": "Integer", - "value": "8" - } - ] - } -} -``` - -It returns integer 8. - -##### **Invoking symbol** - -Request Body: - -```json -{ - "jsonrpc": "2.0", - "method": "invokefunction", - "params": [ - "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "symbol", - [] - ], - "id": 1 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "result": { - "state": "HALT, BREAK", - "gas_consumed": "0.141", - "stack": [ - { - "type": "ByteArray", - "value": "525058" - } - ] - } -} -``` - -It returns "525058" which can be converted to string "RPX". - -##### **Calculating the User Balance** - -According to all the returned values, we can calculate the user balance as follows: -The balance = 100000000/108 RPX = 1 RPX - -### Dealing with User Withdrawals - -The exchange can choose one of the following way to send NEP-5 assets to users: - -- NEO-CLI command: `send` - -- RPC method: `sendtoaddress` -- PRC method: `sendmany` - -#### NEO-CLI Command: send - -##### Syntax - -`send
[fee = 0]` - -##### Parameters - -- txid|script hash: the asset ID. - -- address: the payment address. - -- value: the transfer amount. - -- fee: This parameter can be left empty. The default value is 0. - - -This command verifies the wallet password. - -##### Example - -To transfer 100 RPX to the address *AeSHyuirtXbfZbFik6SiBW2BEj7GK3N62b*, enter the following: - -``` -send 0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9 AeSHyuirtXbfZbFik6SiBW2BEj7GK3N62b 100 -``` - -If you need to send global asset, just change the first parameter to txid. For example, -The txid of NEO: 0Xc56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b -The txid of GAS: 0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7 - -#### RPC Method: sendtoaddress - -The key "params" includes an array of at least three parameters. - -`"params":[script hash, address, amount, fee(optional), change address(optional)]` - -For example, to send 1 RPX to *AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg* , construct a JSON file as follows and send it to RPC server. - -Request Body: - -```json -{ - "jsonrpc":"2.0", - "method":"sendtoaddress", - "params":[ - "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg", - "1", - "0", - "ARkJ8QcVdYL68WRvN3wj3TSvXX8CgmC73Z" - ], - "id":1 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc":"2.0", - "id":1, - "result":{ - "txid":"0xc6d4bf7c62fb47e0b2a6e838c3a1ca297622a1b1df7ceb2d30fa4ef8b7870700", - "size":219, - "type":"InvocationTransaction", - "version":1, - "attributes":[ - { - "usage":"Script", - "data":"5305fbbd4bd5a5e3e859b452b7897157eb20144f" - } - ], - "vin":[ - - ], - "vout":[ - - ], - "sys_fee":"0", - "net_fee":"0", - "scripts":[ - { - "invocation":"4054fbfca678737ae164ebf0e476da0c8215782bc42b67ae08cf4d8a716eeef81fcc17641e7f63893c3e685fb7eb1fb8516161c5257af41630f4508dde3afa3a8c", - "verification":"210331d1feacd79b53aeeeeb9de56018eadcd07948675a50258f9e64a1204b5d58d1ac" - } - ], - "script":"0400e1f50514d710f6f3f0bad2996a09a56d454cfc116a881bfd145305fbbd4bd5a5e3e859b452b7897157eb20144f53c1087472616e7366657267f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ecf166187b7883718089c8", - "gas":"0" - } -} -``` - -#### RPC Method: sendmany - -The key "params" includes an array of at least one parameter: - -`"params":[[], fee(optional), change address(optional)]` - -For example, to send 15.5 RPX and 0.0001 GAS to *AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg* and the `change address` is also *AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg*, you can construct a JSON file as follows and send it to RPC server. - -Request Body: - -```json -{ - "jsonrpc":"2.0", - "method":"sendmany", - "params":[ - [ - { - "asset":"0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "value":"15.5", - "address":"AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - }, - { - "asset":"0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", - "value":"0.0001", - "address":"AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - } - ],"0.00001","AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - ], - "id":1 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "result": { - "txid": "0xe1351c9c9f2205a801d1b04f0df2d65fb4b1692d7d3b06cf41e0712fd1b12c9c", - "size": 373, - "type": "InvocationTransaction", - "version": 1, - "attributes": [ - { - "usage": "Script", - "data": "6d64dc9e50af8e911247436b264c8f7d791ad58c" - } - ], - "vin": [ - { - "txid": "0x9f0a28a912527604ab4b7d5e8b8d1a9b57631fcbab460132811ae7b6ed1ccaff", - "vout": 1 - } - ], - "vout": [ - { - "n": 0, - "asset": "0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", - "value": "0.0001", - "address": "AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - }, - { - "n": 1, - "asset": "0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", - "value": "0.01359", - "address": "AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - } - ], - "sys_fee": "0", - "net_fee": "0.00001", - "scripts": [ - { - "invocation": "40644ab915419dbf855a52d5c75596e80b78c8e928cc0ce91ae6afc3b75a0c31ee54efe1836f9ec232f6c42dcb3ace0bfdc688e626944fa20970a76064975eade9", - "verification": "2103d4b6fc2d116855f86a483d151182f68e88e6ddd13f3f1f3631e36300aac122bfac" - } - ], - "script": "04801f635c14d710f6f3f0bad2996a09a56d454cfc116a881bfd146d64dc9e50af8e911247436b264c8f7d791ad58c53c1087472616e7366657267f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ecf166f871fb30fc859b77", - "gas": "0" - } -} -``` - -### See Also - -[NEP-5 Token Standard](https://github.com/neo-project/proposals/blob/master/nep-5.mediawiki "NEP5") - -[Data Transformation Examples](https://github.com/PeterLinX/NeoDataTransformation) - -## (Optional) Distributing GAS to Users - -The exchange can determine whether to distribute GAS to users. GAS is used to pay to the NEO blockchain for recording and additional services. - -### What is GAS ? - -NeoGas (abbreviated as GAS) represents the right to use the Neo Blockchain. There will be 100 million GAS in total. GASs are generated along with every new block. The issuance will slow down according to a set slowly-decreasing pace, while GAS will go through a generating process to grow from zero to 100 million. Once NEO is acquired, GAS will be generated in the system following the algorithms. - -### Calculating the Available GAS Amount - -- Available *GAS = f(neo_amount, Δt_const)* - - - Δt_const = t_end - t_start - - t_end = the moment that Neo goes into the state of spent - - t_start = the moment that Neo goes into the state of unspent - - Δt_const is fixed, thus the available Gas is of a fixed amount too. And this amount is a function of the amount of Neo held by the user and the duration between the moments that he or she transferred this amount of Neo into and out of his or her address. - - -- Unavailable *GAS = f(neo_amount, Δt_var)* - - - Δt_var = t - t_start - - t is the current time - - t_start = the moment that Neo goes into the state of unspent - - The current time is a variable, so the amount of the unavailable GAS also grows through time, which means it is a variable. - -### Distributing GAS to Users - -Suppose all the exchange addresses are stored in one wallet, the following chart demonstrates the procedure and computational formula how the exchange distributes GAS to the user A. - -![gasflow_en](../sc/assets/gasflow_en.png) - -The shorter the snapshot interval, the more precise the calculation is. If the snapshot interval is not uniform, use the weighted average calculation method. - -### Claiming GAS - -GAS becomes claimable after the user transfer his or her NEO. For example, **someone has NEO in address A and GAS are not claimable, he transfer his NEO to himself (address A) then the NEO GAS are claimable.** - -The following table lists the GAS claiming steps and corresponding commands. - -| # | Steps | Command | -| ---- | :--------------------------------------- | ---------------------------------------- | -| 1 | Run NEO-CLI | `./neo-cli.dll /rpc` | -| 2 | Check the client version | `version` | -| 3 | Check the synchronized height of the client ( Height: height/header height, Nodes: amount of connected nodes). | `show state` | -| 4 | Create a wallet | `create wallet /home/NeoNode/test.db3` | -| 5 | Open the wallet created in the last step | `open wallet /home/NeoNode/test.db3` | -| 6 | Check the address list in the wallet | `list address` | -| 7 | Check the assets in the wallet | `list asset` | -| 8 | Check the GAS balances details in the wallet | `show gas` | -| 9 | Transfer NEO to your address(e.g. AaAHt6Xi51iMCaDaYoDFTFLnGbBN1m75SM 1) to change the status of Gas to be claimable. | `send NEO AaAHt6Xi51iMCaDaYoDFTFLnGbBN1m75SM 1` | -| 10 | Get the details of the balances of GAS in the wallet again. Now the status of all the GAS should be available to claim. | `show gas` | -| 11 | Claim GAS. | `claim gas` | -| 12 | Check balance again. | `list asset` | - diff --git a/en-us/exchange/v2.7.1.md b/en-us/exchange/v2.7.1.md deleted file mode 100644 index 974f1aaf4a..0000000000 --- a/en-us/exchange/v2.7.1.md +++ /dev/null @@ -1,813 +0,0 @@ -# Document for Exchange Developers - -> [!Note] -> -> This document provides information based on [Neo CLI v2.7.1](https://github.com/neo-project/neo-cli/releases/tag/v2.7.1). - -NEO has two types of digital assets: global assets (e.g. NEO, GAS) and contract assets (e.g. NEP-5 assets). That's the main assets exchanges need to deal with for user withdrawals, deposits, and other operations. The NEO-CLI client works as an normal node in the P2P network and meanwhile a cross-platform wallet handling various assets related transactions. - -In general, an exchange needs to do the following: - -- [Deploying a NEO Node on Server](#deploying-a-neo-node-on-server) -- [Using NEO-CLI](#using-neo-cli) -- [Dealing with Global Assets Transactions](#dealing-with-global-assets-transactions) -- [Dealing with NEP-5 Assets Transactions](#dealing-with-nep-5-assets-transactions) -- [Distributing GAS to Users](#distributing-gas-to-users) - -## Deploying a NEO Node on Server - -To deploy a NEO node on the exchange server, do the following: - -1. Install [.NET Core Runtime](https://www.microsoft.com/net/download/core#/runtime) on the server, 2.0 and the later version. -2. From Github, download the [Neo-CLI](https://github.com/neo-project/neo-cli/releases) program and enable the NEO node. - -For more information, refer to [Installation and deployment of NEO node](../node/cli/setup.md). - -## Using NEO-CLI - -### About NEO-CLI - -NEO-CLI is a command-line client (wallet) for developers. Developers have two ways to interact with it: - -- Using the CLI (command-line interface) commands. For example, you can create a wallet, generate an address, etc. -- Using the Remote Procedure Call (RPC). For example, you can transfer to the designated address, acquire the block information of the designated height, acquire the information of the designated trade, etc. - -NEO-CLI provides the following features: - -- As a wallet, manages assets through the command-line. - - To enable the wallet,enter the following command under the NEO-CLI directory: - - ``` - dotnet neo-cli.dll - ``` - - To check all the available commands, enter the following command: - - ``` - help - ``` - - For more information, refer to [CLI Command Reference](../node/cli/cli.md). - -- Provides APIs to retrieve blockchain data from nodes. The interfaces are provided through [JSON-RPC](http://www.jsonrpc.org/specification),and the underlying communications use HTTP/HTTPS protocols. - - To start a node which provides RPC service, enter the following command under the NEO-CLI directory: - - ``` - dotnet neo-cli.dll --rpc - ``` - - For more API information, refer to [API Reference](../node/cli/apigen.md). - - -### Creating a Wallet - -The exchange needs to create an online wallet to manage the deposit addresses of users. A wallet is used to store the information of the accounts (both public keys and private keys) and the contracts. It is the most important proof that the user holds. Users must keep the wallet files and the wallet passwords secure. They must not lose or disclose these data. Exchanges do not have to create a wallet for every address. An online wallet usually keeps all deposit addresses of users. A cold wallet (offline wallet) is another storage option which provides better security. - -> [!Note] -> -> NEO-CLI supports wallets in two formats: the sqlite wallet (.db3) and the new [NEP6 standard](https://github.com/neo-project/proposals/blob/master/nep-6.mediawiki) wallet (.json). For exchanges the sqlite wallet is recommended. - -To create a wallet, do the following: - -1. enter `create wallet `. - - is the wallet path and wallet file name. The file extension can be .db3 or .json, depending on the wallet type you are using, for example, `create wallet /home/mywallet.db3`. If the file extension is not specified, the NEP6 format (.json) is used by default. - -2. Set a password for the wallet. - -> [!Note] -> -> The wallet must be kept open all the time to respond to the withdrawal requests of users. For security reasons, the wallets should be run in an independent server on which the firewall is configured properly, as shown below. - -| | Mainnet | Testnet | -| ------------------ | ------- | ------- | -| JSON-RPC via HTTPS | 10331 | 20331 | -| JSON-RPC via HTTP | 10332 | 20332 | -| P2P | 10333 | 20333 | -| websocket | 10334 | 20334 | - -### Generating Deposit Addresses - -A wallet can store multiple addresses. The exchange needs to generate a deposit address for each user. - -There are two methods to generate deposit addresses: - -- When the user deposit (NEO/NEO GAS) for the first time, the program dynamically generates a NEO address. The advantage is that there is no need to generate addresses at fixed time intervals, while the disadvantage is you can not backup the wallet. - - To develop the program to dynamically generate addresses, use the NEO-CLI API [getnewaddress Method](../node/cli/2.7.1/api/getnewaddress.md). The created address is returned. - -- The exchange creates a batch of NEO addresses in advance. When the user charges (NEO/NEO GAS) for the first time, the exchange assigns a NEO address to him or her. The advantage is the convenience to backup the wallet, while the disadvantage is the need to generate NEO addresses manually. - To generate addresses in batch, run the NEO- CLI command `create address [n]`. The addresses are exported automatically to the address.txt file. - [n] is optional. Its default value is 1. For example, to generate 100 addresses at a time, enter `create address 100`. - - -> [!Note] -> -> Either way, the exchange must import the addresses into the database and distribute them to users. It is generally recommend the exchange use the second way, so as to reduce the external controls and run the wallet more stably. - -## Dealing with Global Assets Transactions - -### Developing Programs for User Deposits and Withdrawals - -For global assets, the exchange needs to develop programs to fulfil the following functions: - -1. Monitor new blocks through NEO-CLI API ([getblock Method](../node/cli/2.7.1/api/getblock2.md)). -2. Deal with user deposits according to the transaction information. -3. Store the transaction records related to the exchange. - -#### User Deposits - -Regarding user deposits, the exchange needs to note the following: - -- NEO blockchain has only one main chain without side chains, will not fork, and will not have isolated blocks. - -- A transaction recorded in NEO blockchain cannot be tampered with, which means a confirmation represents a deposit success. - -- In general, the balance of a deposit address in the exchange is not equal to the balance the user has in the exchange. It may because: - - When transferring or withdrawing, the NEO wallet looks through one or more addresses in the wallet, finds the minimal loose change that meets the requirement and adds up to the total sum of the transaction and then serves that as the input, instead of withdrawing from the specified address (unless the exchange rewrites some functions of NEO wallet to meet their own needs). - - Other operations that may lead to balance inequality, for example, the exchange transfers part of the assets to its cold wallets. - -- There are more than two assets (NEO and NEO GAS) in a NEO address. More assets issued by users (such as stock or token) can be stored. The exchange should determine the assets type when the user deposits. Neither regard other assets as NEO or GAS nor confuse the withdrawal of NEO with GAS. - -- NEO wallet is a full node, which needs to stay online to synchronize blocks. You can view the block synchronization status through the show state in NEO-CLI, for example: - - ``` - ... - neo>show state - Height: 99/99/99, Nodes: 10 - ... - ``` - - That indicates: wallet height is 99/blockchain height is 99/blockchain header height is 99, and number of the connected nodes is 10. - - Suppose this node is fully connected to the P2P network, when the block height gets to the same as the block header height, the node synchronization is completed. Furthermore, when the wallet height, the block height and the block header height are the same, that indicates the node synchronization is completed and the wallet index establishment is completed. - -- In the exchange, the transfer between users should not be recorded through the blockchain. In general, the user's balance are modified in the database directly. Only deposits and withdrawals should be recorded on the blockchain. - -#### Deposit Records - -The exchange needs to write code to monitor every transaction in a block and record all the transactions related to the exchange addresses in the database. If a deposit occurs, the user's balance should be updated. - -Developers can use the `getblock [verbose]` method of NEO-CLI API to retrieve the block information. `` is the block index. `[verbose]` is 0 by default. When `[verbose]` is 0, the method returns the serialized block information in Hexadecimal. You should deserialize the hex string to get the detailed information of the block. When `[verbose]` is 1, the method returns the detailed information of the corresponding block in JSON format. For more information, refer to [getblock Method](../node/cli/2.7.1/api/getblock2.md). - -The block information includes the transactions input and output. The exchange needs to record all its related transactions. The transactions output is in fact the transaction records of the withdrawals of a user. When the exchange sees any of its addresses in the output of the transactions, it updates the NEO/GAS balance of the corresponding user who owns this deposit address. Some exchanges may also do as follows: if it finds an address within the exchange as the output of the transaction, then it records the deposit in its database and modifies the user’s balance after several confirmations (Unless it needs to comply with the operation of other blockchains, this way is not recommended) . - -> [!Note] -> -> - Method getblockcount returns the count of the blocks in the main chain. The first parameter of Method getblock is `` which is the block index. Block index = Block height = The count of the blocks – 1. If getblockcount returns 1234, you should use getblock 1233 to get the information of the latest block. -> - The deposit and withdrawal transactions (NEO/GAS) are all in a type named ContractTransaction. The exchanges only need to care about the ones of ContractTransaction type when they check through the transactions in a block. -> - As the first transaction of every block must be MinerTransaction, you can neglect or jump over it when traversing the blockchain. -> - NEO system takes the transaction as a record unit. -> - -### Dealing with User Withdrawals - -To deal with the user withdrawals for global assets, the exchange needs to do the following: - -1. In NEO-CLI, run `open wallet ` to open the wallet. - -2. Record the user withdrawal transaction and modify the user balance. - -3. (Optional) Customer service deals with withdrawal application. - -4. Send transaction to the user's withdrawal address using the NEO-CLI API method, `sendtoaddress
`. For more information, refer to [sendtoaddress Method](../node/cli/2.7.1/api/sendtoaddress.md). - - - `` :Asset ID - - `
` :Withdrawal address - - `` :Withdrawal amount - - You can also send the transaction to a batch of addresses using API [sendmany Method](../node/cli/2.7.1/api/sendmany.md). - -5. Extract the transaction ID from the returned transaction details in the JSON format, and then record in the database. - -6. Once confirmed by the blockchain, mark the withdrawal transaction as success. - - Similar to deposit monitoring, withdrawals also need to be monitored. If the withdrawal transaction ID is found in the blockchain, it means this transaction has already been confirmed and is a successful withdrawal. - -> [!Note] -> -> - The here refers to the actual amount, instead of the amount multiplied by 10^8. -> - NEO transfer amount must be an integer; otherwise, the transfer will remain unconfirmed although the transaction can be constructed in NEO-CLI, and will thus affect the wallet change status and cause sending failure of other transactions. In this situation, you need to rebuild wallet index, so as to recalculate the transactions and change of the wallet. - -## Dealing with NEP-5 Assets Transactions - -### Receiving User Deposits Notification - -Similar to global assets, the exchange can get the user deposits information of the NEP-5 assets by doing the following: - -1. Get each block details using the `getblock` API, including details of all the transactions in the block. -2. Analyze each transaction type and filter out all transactions of the type "InvocationTransaction". Any transaction other than "InvocationTransaction" can not be a transfer transaction of NEP-5 assets. -3. Invoke the `getapplicationlog` API to get the details of each "InvocationTransaction" transaction and analyze the transaction content to complete the user deposit. - -#### Invoking getapplicationlog - -Before you can use the `getapplicationlog` api to get transaction information, you need to run the following command to open NEO-CLI: - -``` -dotnet neo-cli.dll --rpc --log -``` - -A folder "ApplicationLogs" is generated under the root path. The complete contract log is recorded in this directory, and each NEP-5 transaction is recorded in a JSON file with the named of the transaction txid. - -The following shows an example of the notification file content. - -```JSON -{ - "jsonrpc": "2.0", - "id": 1, - "result": { - "txid": "0xef8957a7bbf83822704f79d63c5f36f3c2b006d928ce978c1d97c23551deb7c8", - "vmstate": "HALT, BREAK", - "gas_consumed": "1.884", - "stack": [], - "notifications": [ - { - "contract": "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "state": { - "type": "Array", - "value": [ - { - "type": "ByteArray", - "value": "7472616e73666572" - }, - { - "type": "ByteArray", - "value": "9393ee15ce6612484ab5be3bbc78c82af8dc0e07" - }, - { - "type": "ByteArray", - "value": "2b41aea9d405fef2e809e3c8085221ce944527a7" - }, - { - "type": "ByteArray", - "value": "00c2eb0b" - } - ] - } - } - ] - } -} -``` - - - -> [!Note] -> -> - The failed NEP-5 transaction can also be recorded in blockchain, so you need to determine whether the vm status parameter "vmstate" is correct. -> - "vmstate" indicates the vm status after it executes the contract. If it contains "FAULT", that means the execution is failed and the transaction is invalid. - -The parameters related to a transaction in the file are the following: - -- **contract**: the script hash of smart contract, by which the exchange can identify assets type. For example, "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9" is the script hash and the unique identification of the RPX asset. - -- The four objects included in the "value" array of "state" are: - - [event, from account, to account, amount] - - - The first object with the type "bytearray" and the value "7472616e73666572", as shown in the example, can be converted to the string "transfer". "transfer" is a method in NEP-5 that represents an asset transfer. - - ```json - { - "type": "ByteArray", - "value": "7472616e73666572" - } - ``` - - - The second object in the array is the account address where the asset is transferred from. Its type "bytearray" and the value "9393ee15ce6612484ab5be3bbc78c82af8dc0e07“ can be converted to "AVECC4AcGXfDjm7cGmfGuxVRGTu6FxoQ7h". Note that for the hexadecimal string with "0x" prefix, it is processed as big endian; otherwise, it is processed as small endian. - - ```json - { - "type": "ByteArray", - "value": "9393ee15ce6612484ab5be3bbc78c82af8dc0e07" - } - ``` - - - The third object in the array is the account address where the asset is transferred to. Its type "bytearray" and the value "2b41aea9d405fef2e809e3c8085221ce944527a7“ can be converted to "AKibPRzkoZpHnPkF6qvuW2Q4hG9gKBwGpR". If the address is an exchange account address, it is a deposit transaction. - - ```json - { - "type": "ByteArray", - "value": "2b41aea9d405fef2e809e3c8085221ce944527a7" - } - ``` - - - The fourth object in the array is the transfer amount. Its type is "bytearray" and the value is 200000000. There are two types of amount, integer and bytearray. Note that when dealing with amount of the interger type, the value conversion method is different than that of the bytearray type. - - ```json - { - "type": "ByteArray", - "value": "00c2eb0b" - } - ``` - -### Querying User Balance - -To query the user's balance, the exchange needs to do the following: - -1. Construct JSON files to invoke three methods (`balanceOf`, `decimals`, and `symbol`) through the PRC API invokefunction. -2. Send the JSON files to NEO RPC server. -3. Calculate the user balance according to the returned values. - -#### invokefunction - -In JSON, a general invokefunction request body is in the following form: - -``` -{ - "jsonrpc": "2.0", - "method": "invokefunction", - "params": [ - "script hash", - "method name", - [ - { - "optional arguments" - } - ] - ], - "id": 1 -} -``` - -You need to replace these strings when querying the user's balance: - -- script hash - - The script hash of the NEP-5 token you are querying. For example, you can find the script hash of RPX is : *0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9*. - - -- method name - - The name of the method you are invoking. To query the user's balance, you need to invoke these three methods: - - **balanceOf** - - - Syntax: `public static BigInteger balanceOf(byte[] account)` - - Remarks: "balanceOf" returns the token balance of the '''account'''. - - **decimals** - - - Syntax: `public static byte decimals()` - - Remarks: "decimals" returns the number of decimals used by the token. - - **symbol** - - - Syntax: `public static string symbol()` - - Remarks: "symbol" returns the token symbol. - - -- optional arguments - - Optional. If the method you are invoking requires arguments, you can pass them by constructing these parameters into an array. For example, "balanceOf" in NEP-5 returns the token balance of the "account": - - `public static BigInteger balanceOf(byte[] account)` - - So you need to pass the account as an argument in the "balanceOf" method. - -#### Example - -##### **Invoking balanceOf** - -Suppose the account address is AJShjraX4iMJjwVt8WYYzZyGvDMxw6Xfbe, you need to convert it into Hash160 type and construct this parameter as a JSON object: - -```json -{ - "type": "Hash160", - "value": "bfc469dd56932409677278f6b7422f3e1f34481d" -} -``` - -Then you can construct the JSON message as the following: - -Request Body: - -```json -{ - "jsonrpc": "2.0", - "method": "invokefunction", - "params": [ - "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "balanceOf", - [ - { - "type": "Hash160", - "value": "0xa7274594ce215208c8e309e8f2fe05d4a9ae412b" - } - ] - ], - "id": 3 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 3, - "result": { - "script": "142b41aea9d405fef2e809e3c8085221ce944527a751c10962616c616e63654f6667f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ec", - "state": "HALT, BREAK", - "gas_consumed": "0.338", - "stack": [ - { - "type": "ByteArray", - "value": "00c2eb0b" - } - ] - } -} -``` - -It returns "00c2eb0b" which can be converted to interger **200000000**. - -##### **Invoking decimals** - -Request Body: - -```json -{ - "jsonrpc": "2.0", - "method": "invokefunction", - "params": [ - "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "decimals", - [] - ], - "id": 2 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 2, - "result": { - "script": "00c108646563696d616c7367f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ec", - "state": "HALT, BREAK", - "gas_consumed": "0.156", - "stack": [ - { - "type": "Integer", - "value": "8" - } - ] - } -} -``` - -It returns integer 8. - -##### **Invoking symbol** - -Request Body: - -```json -{ - "jsonrpc": "2.0", - "method": "invokefunction", - "params": [ - "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "symbol", - [] - ], - "id": 1 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "result": { - "script": "00c10673796d626f6c67f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ec", "state": "HALT, BREAK", - "gas_consumed": "0.141", - "stack": [ - { - "type": "ByteArray", - "value": "525058" - } - ] - } -} -``` - -It returns "525058" which can be converted to string "RPX". - -##### **Calculating the User Balance** - -According to all the returned values, we can calculate the user balance as follows: -The balance = 200000000/108 RPX = 2 RPX - -### Dealing with User Withdrawals - -The exchange can choose one of the following way to send NEP-5 assets to users: - -- NEO-CLI command: `send` -- RPC method: `sendfrom` -- RPC method: `sendtoaddress` -- PRC method: `sendmany` - -> [!Note] -> -> You need to open the wallet in NEO-CLI before you can use these API. - -#### NEO-CLI Command: send - -##### Syntax - -`send
[fee = 0]` - -##### Parameters - -- txid|script hash: the asset ID. - -- address: the payment address. - -- value: the transfer amount. - -- fee: This parameter can be left empty. The default value is 0. - - -This command verifies the wallet password. - -##### Example - -To transfer 100 RPX to the address AeSHyuirtXbfZbFik6SiBW2BEj7GK3N62b, enter the following: - -``` -send 0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9 AeSHyuirtXbfZbFik6SiBW2BEj7GK3N62b 100 -``` - -If you need to send global asset, just change the first parameter to txid. For example, -The txid of NEO: 0xc56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b -The txid of GAS: 0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7 - -#### RPC Method: sendfrom - -The key "params" includes an array of at least four parameters. - -`"params":[script hash, address from, address to, amount, fee(optional), change address(optional)]` - -For example, to send 1 RPX from AKibPRzkoZpHnPkF6qvuW2Q4hG9gKBwGpR to AVECC4AcGXfDjm7cGmfGuxVRGTu6FxoQ7h, construct a JSON file as follows and send it to RPC server. - -Request Body: - -```json -{ - "jsonrpc": "2.0", - "method": "sendfrom", - "params": ["0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9","AKibPRzkoZpHnPkF6qvuW2Q4hG9gKBwGpR","AVECC4AcGXfDjm7cGmfGuxVRGTu6FxoQ7h",1], - "id": 1 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "result": { - "txid": "0xec413354b76fc50a614419f76f131c873da0b17e0fd2dd9170c955b667de08ef", - "size": 219, - "type": "InvocationTransaction", - "version": 1, - "attributes": [ - { - "usage": "Script", - "data": "2b41aea9d405fef2e809e3c8085221ce944527a7" - } - ], - "vin": [], - "vout": [], - "sys_fee": "0", - "net_fee": "0", - "scripts": [ - { - "invocation": "401743a9c3fc91f131aea1c872d166e9c6fae577647884cd8511986041561c2b3e574c1708f662e570688d1a31db7cea281d43615b7fa64d7fa3babf0f6477c31e", - "verification": "2103c532d9335f512e1198ede5c3d35524e6a3b4598f1eb335193b09c4cd52591927ac" - } - ], - "script": "0400e1f505149393ee15ce6612484ab5be3bbc78c82af8dc0e07142b41aea9d405fef2e809e3c8085221ce944527a753c1087472616e7366657267f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ecf166c72745294a433e52", - "gas": "0" - } -} -``` - -#### RPC Method: sendtoaddress - -The key "params" includes an array of at least three parameters. - -`"params":[script hash, address, amount, fee(optional), change address(optional)]` - -For example, to send 1 RPX to AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg , construct a JSON file as follows and send it to RPC server. - -Request Body: - -```json -{ - "jsonrpc":"2.0", - "method":"sendtoaddress", - "params":[ - "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg", - "1", - "0", - "ARkJ8QcVdYL68WRvN3wj3TSvXX8CgmC73Z" - ], - "id":1 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc":"2.0", - "id":1, - "result":{ - "txid":"0xc6d4bf7c62fb47e0b2a6e838c3a1ca297622a1b1df7ceb2d30fa4ef8b7870700", - "size":219, - "type":"InvocationTransaction", - "version":1, - "attributes":[ - { - "usage":"Script", - "data":"5305fbbd4bd5a5e3e859b452b7897157eb20144f" - } - ], - "vin":[ - - ], - "vout":[ - - ], - "sys_fee":"0", - "net_fee":"0", - "scripts":[ - { - "invocation":"4054fbfca678737ae164ebf0e476da0c8215782bc42b67ae08cf4d8a716eeef81fcc17641e7f63893c3e685fb7eb1fb8516161c5257af41630f4508dde3afa3a8c", - "verification":"210331d1feacd79b53aeeeeb9de56018eadcd07948675a50258f9e64a1204b5d58d1ac" - } - ], - "script":"0400e1f50514d710f6f3f0bad2996a09a56d454cfc116a881bfd145305fbbd4bd5a5e3e859b452b7897157eb20144f53c1087472616e7366657267f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ecf166187b7883718089c8", - "gas":"0" - } -} -``` - -#### RPC Method: sendmany - -The key "params" includes an array of at least one parameter: - -`"params":[[], fee(optional), change address(optional)]` - -For example, to send 15.5 RPX and 0.0001 GAS to AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg and the `change address` is also AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg, you can construct a JSON file as follows and send it to RPC server. - -Request Body: - -```json -{ - "jsonrpc":"2.0", - "method":"sendmany", - "params":[ - [ - { - "asset":"0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "value":"15.5", - "address":"AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - }, - { - "asset":"0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", - "value":"0.0001", - "address":"AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - } - ],"0.00001","AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - ], - "id":1 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "result": { - "txid": "0xe1351c9c9f2205a801d1b04f0df2d65fb4b1692d7d3b06cf41e0712fd1b12c9c", - "size": 373, - "type": "InvocationTransaction", - "version": 1, - "attributes": [ - { - "usage": "Script", - "data": "6d64dc9e50af8e911247436b264c8f7d791ad58c" - } - ], - "vin": [ - { - "txid": "0x9f0a28a912527604ab4b7d5e8b8d1a9b57631fcbab460132811ae7b6ed1ccaff", - "vout": 1 - } - ], - "vout": [ - { - "n": 0, - "asset": "0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", - "value": "0.0001", - "address": "AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - }, - { - "n": 1, - "asset": "0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", - "value": "0.01359", - "address": "AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - } - ], - "sys_fee": "0", - "net_fee": "0.00001", - "scripts": [ - { - "invocation": "40644ab915419dbf855a52d5c75596e80b78c8e928cc0ce91ae6afc3b75a0c31ee54efe1836f9ec232f6c42dcb3ace0bfdc688e626944fa20970a76064975eade9", - "verification": "2103d4b6fc2d116855f86a483d151182f68e88e6ddd13f3f1f3631e36300aac122bfac" - } - ], - "script": "04801f635c14d710f6f3f0bad2996a09a56d454cfc116a881bfd146d64dc9e50af8e911247436b264c8f7d791ad58c53c1087472616e7366657267f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ecf166f871fb30fc859b77", - "gas": "0" - } -} -``` - -### See Also - -[NEP-5 Token Standard](https://github.com/neo-project/proposals/blob/master/nep-5.mediawiki "NEP5") - -[Data Transformation Examples](https://github.com/PeterLinX/NeoDataTransformation) - -## Distributing GAS to Users - -The exchange can determine whether to distribute GAS to users. GAS is used to pay to the NEO blockchain for recording and additional services. - -### What is GAS ? - -NeoGas (abbreviated as GAS) represents the right to use the Neo Blockchain. There will be 100 million GAS in total. GASs are generated along with every new block. The issuance will slow down according to a set slowly-decreasing pace, while GAS will go through a generating process to grow from zero to 100 million. Once NEO is acquired, GAS will be generated in the system following the algorithms. - -### Calculating the Available GAS Amount - -- Available *GAS = f(neo_amount, Δt_const)* - - - Δt_const = t_end - t_start - - t_end = the moment that Neo goes into the state of spent - - t_start = the moment that Neo goes into the state of unspent - - Δt_const is fixed, thus the available Gas is of a fixed amount too. And this amount is a function of the amount of Neo held by the user and the duration between the moments that he or she transferred this amount of Neo into and out of his or her address. - - -- Unavailable *GAS = f(neo_amount, Δt_var)* - - - Δt_var = t - t_start - - t is the current time - - t_start = the moment that Neo goes into the state of unspent - - The current time is a variable, so the amount of the unavailable GAS also grows through time, which means it is a variable. - -### Distributing GAS to Users - -Suppose all the exchange addresses are stored in one wallet, the following chart demonstrates the procedure and computational formula how the exchange distributes GAS to the user A. - - -![gasflow_en](../sc/assets/gasflow_en.png) - - -The shorter the snapshot interval, the more precise the calculation is. If the snapshot interval is not uniform, use the weighted average calculation method. - -### Claiming GAS - -GAS becomes claimable after the user transfer his or her NEO. For example, **someone has NEO in address A and GAS are not claimable, he transfer his NEO to himself (address A) then the NEO GAS are claimable.** - -The following table lists the GAS claiming steps and corresponding commands. - -| # | Steps | Command | -| ---- | :----------------------------------------------------------- | ----------------------------------------------- | -| 1 | Run NEO-CLI | `dotnet neo-cli.dll --rpc` | -| 2 | Check the client version | `version` | -| 3 | Check the synchronized height of the client ( Height: height/header height, Nodes: amount of connected nodes). | `show state` | -| 4 | Create a wallet | `create wallet /home/NeoNode/test.db3` | -| 5 | Open the wallet created in the last step | `open wallet /home/NeoNode/test.db3` | -| 6 | Check the address list in the wallet | `list address` | -| 7 | Check the assets in the wallet | `list asset` | -| 8 | Check the GAS balances details in the wallet | `show gas` | -| 9 | Transfer NEO to your address(e.g. AaAHt6Xi51iMCaDaYoDFTFLnGbBN1m75SM 1) to change the status of Gas to be claimable. | `send NEO AaAHt6Xi51iMCaDaYoDFTFLnGbBN1m75SM 1` | -| 10 | Get the details of the balances of GAS in the wallet again. Now the status of all the GAS should be available to claim. | `show gas` | -| 11 | Claim GAS. | `claim gas` | -| 12 | Check balance again. | `list asset` | - diff --git a/en-us/exchange/v2.7.3.md b/en-us/exchange/v2.7.3.md deleted file mode 100644 index 9931581261..0000000000 --- a/en-us/exchange/v2.7.3.md +++ /dev/null @@ -1,851 +0,0 @@ -# Document for Exchange Developers - -> [!Note] -> -> This document provides information based on [Neo CLI v2.7.3](https://github.com/neo-project/neo-cli/releases/tag/v2.7.3). - -NEO has two types of digital assets: global assets (e.g. NEO, GAS) and contract assets (e.g. NEP-5 assets). That's the main assets exchanges need to deal with for user withdrawals, deposits, and other operations. The NEO-CLI client works as an normal node in the P2P network and meanwhile a cross-platform wallet handling various assets related transactions. - -In general, an exchange needs to do the following: - -- [Deploying a NEO Node on Server](#deploying-a-neo-node-on-server) -- [Using NEO-CLI](#using-neo-cli) -- [Dealing with Global Assets Transactions](#dealing-with-global-assets-transactions) -- [Dealing with NEP-5 Assets Transactions](#dealing-with-nep-5-assets-transactions) -- [Distributing GAS to Users](#distributing-gas-to-users) - - - -## Deploying a NEO Node on Server - -To deploy a NEO node on the exchange server, do the following: - -1. Install [.NET Core Runtime](https://www.microsoft.com/net/download/core#/runtime) on the server, 2.0 and the later version. -2. From Github, download the [Neo-CLI](https://github.com/neo-project/neo-cli/releases) program and enable the NEO node. - -For more information, refer to [Installation and deployment of NEO node](../node/cli/setup.md). - -## Using NEO-CLI - -### NEO-CLI Security Policies - -> [!Warning] -> -> The exchange must use a white list or firewall to block external server requests; otherwise there will be a significant security risk. - -NEO-CLI does not provide the function to remotely switching on/off the wallet, and it does not verify the process when opening a wallet. Therefore, exchanges should set their own security policies. The wallet must be kept open all the time to respond to the withdrawal requests of users. For security reasons, the wallets should be run in an independent server on which the firewall is configured properly, as shown below. - -| | Mainnet | Testnet | -| ------------------ | ------- | ------- | -| JSON-RPC via HTTPS | 10331 | 20331 | -| JSON-RPC via HTTP | 10332 | 20332 | -| P2P | 10333 | 20333 | -| websocket | 10334 | 20334 | - -### About NEO-CLI - -NEO-CLI is a command-line client (wallet) for developers. Developers have two ways to interact with it: - -- Using the CLI (command-line interface) commands. For example, you can create a wallet, generate an address, etc. -- Using the Remote Procedure Call (RPC). For example, you can transfer to the designated address, acquire the block information of the designated height, acquire the information of the designated trade, etc. - -NEO-CLI provides the following features: - -- As a wallet, manages assets through the command-line. - - - To enable the wallet,enter the following command under the NEO-CLI directory: - - - ``` - dotnet neo-cli.dll - ``` - - To check all the available commands, enter the following command: - - ``` - help - ``` - - For more information, refer to [CLI Command Reference](../node/cli/cli.md). - -- Provides APIs to retrieve blockchain data from nodes. The interfaces are provided through [JSON-RPC](http://www.jsonrpc.org/specification),and the underlying communications use HTTP/HTTPS protocols. - - To start a node which provides RPC service, enter the following command under the NEO-CLI directory: - - ``` - dotnet neo-cli.dll --rpc - ``` - - For more API information, refer to [API Reference](../node/cli/apigen.md). - - -- Provides transaction information of NEP-5 assets. - - To get the NEP-5 assets transaction information, enter the following: - - ``` - dotnet neo-cli.dll --log - ``` - -- Connects to seed nodes directly - - If the connections number is always 0 after opening the NEO-CLI, you can directly connect seed nodes to synchronize blocks using the following command: - - ``` - dotnet neo-cli.dll --nopeers - ``` - -| # | Function | Command | -| ---- | ------------------------------------------- | -------------------- | -| 1 | Run NEO-CLI | `dotnet neo-cli.dll` | -| 2 | Open RPC | `--rpc` | -| 3 | Log the NEP-5 asset transaction information | `--log` | -| 4 | Connect to seed nodes | `--nopeers` | - -> [!Note] -> -> You can enable multiple functions, for example, to enable all the above functions, enter the following: -> -> ``` -> dotnet neo-cli.dll --rpc --log --nopeers -> ``` - -### Creating a Wallet - -The exchange needs to create an online wallet to manage the deposit addresses of users. A wallet is used to store the information of the accounts (both public keys and private keys) and the contracts. It is the most important proof that the user holds. Users must keep the wallet files and the wallet passwords secure. They must not lose or disclose these data. Exchanges do not have to create a wallet for every address. An online wallet usually keeps all deposit addresses of users. A cold wallet (offline wallet) is another storage option which provides better security. - -> [!Note] -> -> NEO-CLI supports wallets in two formats: the sqlite wallet (.db3) and the new [NEP6 standard](https://github.com/neo-project/proposals/blob/master/nep-6.mediawiki) wallet (.json). For exchanges the sqlite wallet is recommended. - -To create a wallet, do the following: - -1. enter `create wallet `. - - is the wallet path and wallet file name. The file extension can be .db3 or .json, depending on the wallet type you are using, for example, `create wallet /home/mywallet.db3`. If the file extension is not specified, the NEP6 format (.json) is used by default. - -2. Set a password for the wallet. - -### Generating Deposit Addresses - -A wallet can store multiple addresses. The exchange needs to generate a deposit address for each user. - -There are two methods to generate deposit addresses: - -- When the user deposit (NEO/NEO GAS) for the first time, the program dynamically generates a NEO address. The advantage is that there is no need to generate addresses at fixed time intervals, while the disadvantage is you can not backup the wallet. - - To develop the program to dynamically generate addresses, use the NEO-CLI API [getnewaddress Method](../node/cli/2.7.3/api/getnewaddress.md). The created address is returned. - -- The exchange creates a batch of NEO addresses in advance. When the user charges (NEO/NEO GAS) for the first time, the exchange assigns a NEO address to him or her. The advantage is the convenience to backup the wallet, while the disadvantage is the need to generate NEO addresses manually. - To generate addresses in batch, run the NEO- CLI command `create address [n]`. The addresses are exported automatically to the address.txt file. - [n] is optional. Its default value is 1. For example, to generate 100 addresses at a time, enter `create address 100`. - - -> [!Note] -> -> Either way, the exchange must import the addresses into the database and distribute them to users. It is generally recommend the exchange use the second way, so as to reduce the external controls and run the wallet more stably. - -## Dealing with Global Assets Transactions - -### Developing Programs for User Deposits and Withdrawals - -For global assets, the exchange needs to develop programs to fulfil the following functions: - -1. Monitor new blocks through NEO-CLI API ([getblock Method](../node/cli/2.7.3/api/getblock2.md)). -2. Deal with user deposits according to the transaction information. -3. Store the transaction records related to the exchange. - -#### User Deposits - -Regarding user deposits, the exchange needs to note the following: - -- NEO blockchain has only one main chain without side chains, will not fork, and will not have isolated blocks. - -- A transaction recorded in NEO blockchain cannot be tampered with, which means a confirmation represents a deposit success. - -- In general, the balance of a deposit address in the exchange is not equal to the balance the user has in the exchange. It may because: - - When transferring or withdrawing, the NEO wallet looks through one or more addresses in the wallet, finds the minimal loose change that meets the requirement and adds up to the total sum of the transaction and then serves that as the input, instead of withdrawing from the specified address (unless the exchange rewrites some functions of NEO wallet to meet their own needs). - - Other operations that may lead to balance inequality, for example, the exchange transfers part of the assets to its cold wallets. - -- There are more than two assets (NEO and NEO GAS) in a NEO address. More assets issued by users (such as stock or token) can be stored. The exchange should determine the assets type when the user deposits. Neither regard other assets as NEO or GAS nor confuse the withdrawal of NEO with GAS. - -- NEO wallet is a full node, which needs to stay online to synchronize blocks. You can view the block synchronization status through the show state in NEO-CLI, for example: - - ``` - ... - neo>show state - Height: 99/99/99, Nodes: 10 - ... - ``` - - That indicates: wallet height is 99/blockchain height is 99/blockchain header height is 99, and number of the connected nodes is 10. - - Suppose this node is fully connected to the P2P network, when the block height gets to the same as the block header height, the node synchronization is completed. Furthermore, when the wallet height, the block height and the block header height are the same, that indicates the node synchronization is completed and the wallet index establishment is completed. - -- In the exchange, the transfer between users should not be recorded through the blockchain. In general, the user's balance are modified in the database directly. Only deposits and withdrawals should be recorded on the blockchain. - -#### Deposit Records - -The exchange needs to write code to monitor every transaction in a block and record all the transactions related to the exchange addresses in the database. If a deposit occurs, the user's balance should be updated. - -Developers can use the `getblock [verbose]` method of NEO-CLI API to retrieve the block information. `` is the block index. `[verbose]` is 0 by default. When `[verbose]` is 0, the method returns the serialized block information in Hexadecimal. You should deserialize the hex string to get the detailed information of the block. When `[verbose]` is 1, the method returns the detailed information of the corresponding block in JSON format. For more information, refer to [getblock Method](../node/cli/2.7.3/api/getblock2.md). - -The block information includes the transactions input and output. The exchange needs to record all its related transactions. The transactions output is in fact the transaction records of the withdrawals of a user. When the exchange sees any of its addresses in the output of the transactions, it updates the NEO/GAS balance of the corresponding user who owns this deposit address. Some exchanges may also do as follows: if it finds an address within the exchange as the output of the transaction, then it records the deposit in its database and modifies the user’s balance after several confirmations (Unless it needs to comply with the operation of other blockchains, this way is not recommended) . - -> [!Note] -> -> - Method getblockcount returns the count of the blocks in the main chain. The first parameter of Method getblock is `` which is the block index. Block index = Block height = The count of the blocks – 1. If getblockcount returns 1234, you should use getblock 1233 to get the information of the latest block. -> - The deposit and withdrawal transactions (NEO/GAS) are all in a type named ContractTransaction. The exchanges only need to care about the ones of ContractTransaction type when they check through the transactions in a block. -> - As the first transaction of every block must be MinerTransaction, you can neglect or jump over it when traversing the blockchain. -> - NEO system takes the transaction as a record unit. -> - -### Dealing with User Withdrawals - -To deal with the user withdrawals for global assets, the exchange needs to do the following: - -1. In NEO-CLI, run `open wallet ` to open the wallet. - -2. Record the user withdrawal transaction and modify the user balance. - -3. (Optional) Customer service deals with withdrawal application. - -4. Send transaction to the user's withdrawal address using the NEO-CLI API method, `sendtoaddress
`. For more information, refer to [sendtoaddress Method](../node/cli/2.7.3/api/sendtoaddress.md). - - - `` :Asset ID - - `
` :Withdrawal address - - `` :Withdrawal amount - - You can also send the transaction to a batch of addresses using API [sendmany Method](../node/cli/2.7.3/api/sendmany.md). - -5. Extract the transaction ID from the returned transaction details in the JSON format, and then record in the database. - -6. Once confirmed by the blockchain, mark the withdrawal transaction as success. - - Similar to deposit monitoring, withdrawals also need to be monitored. If the withdrawal transaction ID is found in the blockchain, it means this transaction has already been confirmed and is a successful withdrawal. - -> [!Note] -> -> - The here refers to the actual amount, instead of the amount multiplied by 10^8. -> - NEO transfer amount must be an integer; otherwise, the transfer will remain unconfirmed although the transaction can be constructed in NEO-CLI, and will thus affect the wallet change status and cause sending failure of other transactions. In this situation, you need to rebuild wallet index, so as to recalculate the transactions and change of the wallet. - -## Dealing with NEP-5 Assets Transactions - -### Receiving User Deposits Notification - -Similar to global assets, the exchange can get the user deposits information of the NEP-5 assets by doing the following: - -1. Get each block details using the `getblock` API, including details of all the transactions in the block. -2. Analyze each transaction type and filter out all transactions of the type "InvocationTransaction". Any transaction other than "InvocationTransaction" can not be a transfer transaction of NEP-5 assets. -3. Invoke the `getapplicationlog` API to get the details of each "InvocationTransaction" transaction and analyze the transaction content to complete the user deposit. - -#### Invoking getapplicationlog - -Before you can use the `getapplicationlog` api to get transaction information, you need to run the following command to open NEO-CLI: - -``` -dotnet neo-cli.dll --rpc --log -``` - -A folder "ApplicationLogs" is generated under the root path. The complete contract log is recorded in this directory, and each NEP-5 transaction is recorded in a JSON file with the named of the transaction txid. - -The following shows an example of the notification file content. - -```JSON -{ - "jsonrpc": "2.0", - "id": 1, - "result": { - "txid": "0xef8957a7bbf83822704f79d63c5f36f3c2b006d928ce978c1d97c23551deb7c8", - "vmstate": "HALT, BREAK", - "gas_consumed": "1.884", - "stack": [], - "notifications": [ - { - "contract": "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "state": { - "type": "Array", - "value": [ - { - "type": "ByteArray", - "value": "7472616e73666572" - }, - { - "type": "ByteArray", - "value": "9393ee15ce6612484ab5be3bbc78c82af8dc0e07" - }, - { - "type": "ByteArray", - "value": "2b41aea9d405fef2e809e3c8085221ce944527a7" - }, - { - "type": "ByteArray", - "value": "00c2eb0b" - } - ] - } - } - ] - } -} -``` - - - -> [!Note] -> -> - The failed NEP-5 transaction can also be recorded in blockchain, so you need to determine whether the vm status parameter "vmstate" is correct. -> - "vmstate" indicates the vm status after it executes the contract. If it contains "FAULT", that means the execution is failed and the transaction is invalid. - -The parameters related to a transaction in the file are the following: - -- **contract**: the script hash of smart contract, by which the exchange can identify assets type. For example, "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9" is the script hash and the unique identification of the RPX asset. - -- The four objects included in the "value" array of "state" are: - - [event, from account, to account, amount] - - - The first object with the type "bytearray" and the value "7472616e73666572", as shown in the example, can be converted to the string "transfer". "transfer" is a method in NEP-5 that represents an asset transfer. - - ```json - { - "type": "ByteArray", - "value": "7472616e73666572" - } - ``` - - - The second object in the array is the account address where the asset is transferred from. Its type "bytearray" and the value "9393ee15ce6612484ab5be3bbc78c82af8dc0e07“ can be converted to "AVECC4AcGXfDjm7cGmfGuxVRGTu6FxoQ7h". Note that for the hexadecimal string with "0x" prefix, it is processed as big endian; otherwise, it is processed as small endian. - - ```json - { - "type": "ByteArray", - "value": "9393ee15ce6612484ab5be3bbc78c82af8dc0e07" - } - ``` - - - The third object in the array is the account address where the asset is transferred to. Its type "bytearray" and the value "2b41aea9d405fef2e809e3c8085221ce944527a7“ can be converted to "AKibPRzkoZpHnPkF6qvuW2Q4hG9gKBwGpR". If the address is an exchange account address, it is a deposit transaction. - - ```json - { - "type": "ByteArray", - "value": "2b41aea9d405fef2e809e3c8085221ce944527a7" - } - ``` - - - The fourth object in the array is the transfer amount. Its type is "bytearray" and the value is 200000000. There are two types of amount, integer and bytearray. Note that when dealing with amount of the interger type, the value conversion method is different than that of the bytearray type. - - ```json - { - "type": "ByteArray", - "value": "00c2eb0b" - } - ``` - -### Querying User Balance - -To query the user's balance, the exchange needs to do the following: - -1. Construct JSON files to invoke three methods (`balanceOf`, `decimals`, and `symbol`) through the PRC API invokefunction. -2. Send the JSON files to NEO RPC server. -3. Calculate the user balance according to the returned values. - -#### invokefunction - -In JSON, a general invokefunction request body is in the following form: - -``` -{ - "jsonrpc": "2.0", - "method": "invokefunction", - "params": [ - "script hash", - "method name", - [ - { - "optional arguments" - } - ] - ], - "id": 1 -} -``` - -You need to replace these strings when querying the user's balance: - -- script hash - - The script hash of the NEP-5 token you are querying. For example, you can find the script hash of RPX is : *0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9*. - - -- method name - - The name of the method you are invoking. To query the user's balance, you need to invoke these three methods: - - **balanceOf** - - - Syntax: `public static BigInteger balanceOf(byte[] account)` - - Remarks: "balanceOf" returns the token balance of the '''account'''. - - **decimals** - - - Syntax: `public static byte decimals()` - - Remarks: "decimals" returns the number of decimals used by the token. - - **symbol** - - - Syntax: `public static string symbol()` - - Remarks: "symbol" returns the token symbol. - - -- optional arguments - - Optional. If the method you are invoking requires arguments, you can pass them by constructing these parameters into an array. For example, "balanceOf" in NEP-5 returns the token balance of the "account": - - `public static BigInteger balanceOf(byte[] account)` - - So you need to pass the account as an argument in the "balanceOf" method. - -#### Example - -##### **Invoking balanceOf** - -Suppose the account address is AKibPRzkoZpHnPkF6qvuW2Q4hG9gKBwGpR, you need to convert it into Hash160 type and construct this parameter as a JSON object: - -```json -{ - "type": "Hash160", - "value": "0xa7274594ce215208c8e309e8f2fe05d4a9ae412b" -} -``` - -Then you can construct the JSON message as the following: - -Request Body: - -```json -{ - "jsonrpc": "2.0", - "method": "invokefunction", - "params": [ - "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "balanceOf", - [ - { - "type": "Hash160", - "value": "0xa7274594ce215208c8e309e8f2fe05d4a9ae412b" - } - ] - ], - "id": 3 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 3, - "result": { - "script": "142b41aea9d405fef2e809e3c8085221ce944527a751c10962616c616e63654f6667f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ec", - "state": "HALT, BREAK", - "gas_consumed": "0.338", - "stack": [ - { - "type": "ByteArray", - "value": "00c2eb0b" - } - ] - } -} -``` - -It returns "00c2eb0b" which can be converted to interger **200000000**. - -##### **Invoking decimals** - -Request Body: - -```json -{ - "jsonrpc": "2.0", - "method": "invokefunction", - "params": [ - "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "decimals", - [] - ], - "id": 2 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 2, - "result": { - "script": "00c108646563696d616c7367f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ec", - "state": "HALT, BREAK", - "gas_consumed": "0.156", - "stack": [ - { - "type": "Integer", - "value": "8" - } - ] - } -} -``` - -It returns integer 8. - -##### **Invoking symbol** - -Request Body: - -```json -{ - "jsonrpc": "2.0", - "method": "invokefunction", - "params": [ - "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "symbol", - [] - ], - "id": 1 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "result": { - "script": "00c10673796d626f6c67f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ec", "state": "HALT, BREAK", - "gas_consumed": "0.141", - "stack": [ - { - "type": "ByteArray", - "value": "525058" - } - ] - } -} -``` - -It returns "525058" which can be converted to string "RPX". - -##### **Calculating the User Balance** - -According to all the returned values, we can calculate the user balance as follows: -The balance = 200000000/108 RPX = 2 RPX - -### Dealing with User Withdrawals - -The exchange can choose one of the following way to send NEP-5 assets to users: - -- NEO-CLI command: `send` -- RPC method: `sendfrom` -- RPC method: `sendtoaddress` -- PRC method: `sendmany` - -> [!Note] -> -> You need to open the wallet in NEO-CLI before you can use these API. - -#### NEO-CLI Command: send - -##### Syntax - -`send
[fee = 0]` - -##### Parameters - -- txid|script hash: the asset ID. - -- address: the payment address. - -- value: the transfer amount. - -- fee: This parameter can be left empty. The default value is 0. - - -This command verifies the wallet password. - -##### Example - -To transfer 100 RPX to the address AeSHyuirtXbfZbFik6SiBW2BEj7GK3N62b, enter the following: - -``` -send 0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9 AeSHyuirtXbfZbFik6SiBW2BEj7GK3N62b 100 -``` - -If you need to send global asset, just change the first parameter to txid. For example, -The txid of NEO: 0xc56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b -The txid of GAS: 0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7 - -#### RPC Method: sendfrom - -The key "params" includes an array of at least four parameters. - -`"params":[script hash, address from, address to, amount, fee(optional), change address(optional)]` - -For example, to send 1 RPX from AKibPRzkoZpHnPkF6qvuW2Q4hG9gKBwGpR to AVECC4AcGXfDjm7cGmfGuxVRGTu6FxoQ7h, construct a JSON file as follows and send it to RPC server. - -Request Body: - -```json -{ - "jsonrpc": "2.0", - "method": "sendfrom", - "params": ["0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9","AKibPRzkoZpHnPkF6qvuW2Q4hG9gKBwGpR","AVECC4AcGXfDjm7cGmfGuxVRGTu6FxoQ7h",1], - "id": 1 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "result": { - "txid": "0xec413354b76fc50a614419f76f131c873da0b17e0fd2dd9170c955b667de08ef", - "size": 219, - "type": "InvocationTransaction", - "version": 1, - "attributes": [ - { - "usage": "Script", - "data": "2b41aea9d405fef2e809e3c8085221ce944527a7" - } - ], - "vin": [], - "vout": [], - "sys_fee": "0", - "net_fee": "0", - "scripts": [ - { - "invocation": "401743a9c3fc91f131aea1c872d166e9c6fae577647884cd8511986041561c2b3e574c1708f662e570688d1a31db7cea281d43615b7fa64d7fa3babf0f6477c31e", - "verification": "2103c532d9335f512e1198ede5c3d35524e6a3b4598f1eb335193b09c4cd52591927ac" - } - ], - "script": "0400e1f505149393ee15ce6612484ab5be3bbc78c82af8dc0e07142b41aea9d405fef2e809e3c8085221ce944527a753c1087472616e7366657267f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ecf166c72745294a433e52", - "gas": "0" - } -} -``` - -#### RPC Method: sendtoaddress - -The key "params" includes an array of at least three parameters. - -`"params":[script hash, address, amount, fee(optional), change address(optional)]` - -For example, to send 1 RPX to AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg , construct a JSON file as follows and send it to RPC server. - -Request Body: - -```json -{ - "jsonrpc":"2.0", - "method":"sendtoaddress", - "params":[ - "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg", - "1", - "0", - "ARkJ8QcVdYL68WRvN3wj3TSvXX8CgmC73Z" - ], - "id":1 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc":"2.0", - "id":1, - "result":{ - "txid":"0xc6d4bf7c62fb47e0b2a6e838c3a1ca297622a1b1df7ceb2d30fa4ef8b7870700", - "size":219, - "type":"InvocationTransaction", - "version":1, - "attributes":[ - { - "usage":"Script", - "data":"5305fbbd4bd5a5e3e859b452b7897157eb20144f" - } - ], - "vin":[ - - ], - "vout":[ - - ], - "sys_fee":"0", - "net_fee":"0", - "scripts":[ - { - "invocation":"4054fbfca678737ae164ebf0e476da0c8215782bc42b67ae08cf4d8a716eeef81fcc17641e7f63893c3e685fb7eb1fb8516161c5257af41630f4508dde3afa3a8c", - "verification":"210331d1feacd79b53aeeeeb9de56018eadcd07948675a50258f9e64a1204b5d58d1ac" - } - ], - "script":"0400e1f50514d710f6f3f0bad2996a09a56d454cfc116a881bfd145305fbbd4bd5a5e3e859b452b7897157eb20144f53c1087472616e7366657267f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ecf166187b7883718089c8", - "gas":"0" - } -} -``` - -#### RPC Method: sendmany - -The key "params" includes an array of at least one parameter: - -`"params":[[], fee(optional), change address(optional)]` - -For example, to send 15.5 RPX and 0.0001 GAS to AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg and the `change address` is also AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg, you can construct a JSON file as follows and send it to RPC server. - -Request Body: - -```json -{ - "jsonrpc":"2.0", - "method":"sendmany", - "params":[ - [ - { - "asset":"0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "value":"15.5", - "address":"AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - }, - { - "asset":"0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", - "value":"0.0001", - "address":"AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - } - ],"0.00001","AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - ], - "id":1 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "result": { - "txid": "0xe1351c9c9f2205a801d1b04f0df2d65fb4b1692d7d3b06cf41e0712fd1b12c9c", - "size": 373, - "type": "InvocationTransaction", - "version": 1, - "attributes": [ - { - "usage": "Script", - "data": "6d64dc9e50af8e911247436b264c8f7d791ad58c" - } - ], - "vin": [ - { - "txid": "0x9f0a28a912527604ab4b7d5e8b8d1a9b57631fcbab460132811ae7b6ed1ccaff", - "vout": 1 - } - ], - "vout": [ - { - "n": 0, - "asset": "0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", - "value": "0.0001", - "address": "AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - }, - { - "n": 1, - "asset": "0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", - "value": "0.01359", - "address": "AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - } - ], - "sys_fee": "0", - "net_fee": "0.00001", - "scripts": [ - { - "invocation": "40644ab915419dbf855a52d5c75596e80b78c8e928cc0ce91ae6afc3b75a0c31ee54efe1836f9ec232f6c42dcb3ace0bfdc688e626944fa20970a76064975eade9", - "verification": "2103d4b6fc2d116855f86a483d151182f68e88e6ddd13f3f1f3631e36300aac122bfac" - } - ], - "script": "04801f635c14d710f6f3f0bad2996a09a56d454cfc116a881bfd146d64dc9e50af8e911247436b264c8f7d791ad58c53c1087472616e7366657267f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ecf166f871fb30fc859b77", - "gas": "0" - } -} -``` - -### See Also - -[NEP-5 Token Standard](https://github.com/neo-project/proposals/blob/master/nep-5.mediawiki "NEP5") - -[Data Transformation Examples](https://github.com/PeterLinX/NeoDataTransformation) - -## Distributing GAS to Users - -The exchange can determine whether to distribute GAS to users. GAS is used to pay to the NEO blockchain for recording and additional services. - -### What is GAS ? - -NeoGas (abbreviated as GAS) represents the right to use the Neo Blockchain. There will be 100 million GAS in total. GASs are generated along with every new block. The issuance will slow down according to a set slowly-decreasing pace, while GAS will go through a generating process to grow from zero to 100 million. Once NEO is acquired, GAS will be generated in the system following the algorithms. - -### Calculating the Available GAS Amount - -- Available *GAS = f(neo_amount, Δt_const)* - - - Δt_const = t_end - t_start - - t_end = the moment that Neo goes into the state of spent - - t_start = the moment that Neo goes into the state of unspent - - Δt_const is fixed, thus the available Gas is of a fixed amount too. And this amount is a function of the amount of Neo held by the user and the duration between the moments that he or she transferred this amount of Neo into and out of his or her address. - - -- Unavailable *GAS = f(neo_amount, Δt_var)* - - - Δt_var = t - t_start - - t is the current time - - t_start = the moment that Neo goes into the state of unspent - - The current time is a variable, so the amount of the unavailable GAS also grows through time, which means it is a variable. - -### Distributing GAS to Users - -Suppose all the exchange addresses are stored in one wallet, the following chart demonstrates the procedure and computational formula how the exchange distributes GAS to the user A. - - -![gasflow_en](../sc/assets/gasflow_en.png) - - -The shorter the snapshot interval, the more precise the calculation is. If the snapshot interval is not uniform, use the weighted average calculation method. - -### Claiming GAS - -GAS becomes claimable after the user transfer his or her NEO. For example, **someone has NEO in address A and GAS are not claimable, he transfer his NEO to himself (address A) then the NEO GAS are claimable.** - -The following table lists the GAS claiming steps and corresponding commands. - -| # | Steps | Command | -| ---- | :----------------------------------------------------------- | ----------------------------------------------- | -| 1 | Run NEO-CLI | `dotnet neo-cli.dll --rpc` | -| 2 | Check the client version | `version` | -| 3 | Check the synchronized height of the client ( Height: height/header height, Nodes: amount of connected nodes). | `show state` | -| 4 | Create a wallet | `create wallet /home/NeoNode/test.db3` | -| 5 | Open the wallet created in the last step | `open wallet /home/NeoNode/test.db3` | -| 6 | Check the address list in the wallet | `list address` | -| 7 | Check the assets in the wallet | `list asset` | -| 8 | Check the GAS balances details in the wallet | `show gas` | -| 9 | Transfer NEO to your address(e.g. AaAHt6Xi51iMCaDaYoDFTFLnGbBN1m75SM 1) to change the status of Gas to be claimable. | `send NEO AaAHt6Xi51iMCaDaYoDFTFLnGbBN1m75SM 1` | -| 10 | Get the details of the balances of GAS in the wallet again. Now the status of all the GAS should be available to claim. | `show gas` | -| 11 | Claim GAS. | `claim gas` | -| 12 | Check balance again. | `list asset` | - diff --git a/en-us/exchange/v2.7.4.md b/en-us/exchange/v2.7.4.md deleted file mode 100644 index e23eaabb48..0000000000 --- a/en-us/exchange/v2.7.4.md +++ /dev/null @@ -1,851 +0,0 @@ -# Document for Exchange Developers - -> [!Note] -> -> This document provides information based on [Neo CLI v2.7.4](https://github.com/neo-project/neo-cli/releases/tag/v2.7.4). - -NEO has two types of digital assets: global assets (e.g. NEO, GAS) and contract assets (e.g. NEP-5 assets). That's the main assets exchanges need to deal with for user withdrawals, deposits, and other operations. The NEO-CLI client works as an normal node in the P2P network and meanwhile a cross-platform wallet handling various assets related transactions. - -In general, an exchange needs to do the following: - -- [Deploying a NEO Node on Server](#deploying-a-neo-node-on-server) -- [Using NEO-CLI](#using-neo-cli) -- [Dealing with Global Assets Transactions](#dealing-with-global-assets-transactions) -- [Dealing with NEP-5 Assets Transactions](#dealing-with-nep-5-assets-transactions) -- [Distributing GAS to Users](#distributing-gas-to-users) - - - -## Deploying a NEO Node on Server - -To deploy a NEO node on the exchange server, do the following: - -1. Install [.NET Core Runtime](https://www.microsoft.com/net/download/core#/runtime) on the server, 2.0 and the later version. -2. From Github, download the [Neo-CLI](https://github.com/neo-project/neo-cli/releases) program and enable the NEO node. - -For more information, refer to [Installation and deployment of NEO node](../node/cli/setup.md). - -## Using NEO-CLI - -### NEO-CLI Security Policies - -> [!Warning] -> -> The exchange must use a white list or firewall to block external server requests; otherwise there will be a significant security risk. - -NEO-CLI does not provide the function to remotely switching on/off the wallet, and it does not verify the process when opening a wallet. Therefore, exchanges should set their own security policies. The wallet must be kept open all the time to respond to the withdrawal requests of users. For security reasons, the wallets should be run in an independent server on which the firewall is configured properly, as shown below. - -| | Mainnet | Testnet | -| ------------------ | ------- | ------- | -| JSON-RPC via HTTPS | 10331 | 20331 | -| JSON-RPC via HTTP | 10332 | 20332 | -| P2P | 10333 | 20333 | -| websocket | 10334 | 20334 | - -### About NEO-CLI - -NEO-CLI is a command-line client (wallet) for developers. Developers have two ways to interact with it: - -- Using the CLI (command-line interface) commands. For example, you can create a wallet, generate an address, etc. -- Using the Remote Procedure Call (RPC). For example, you can transfer to the designated address, acquire the block information of the designated height, acquire the information of the designated trade, etc. - -NEO-CLI provides the following features: - -- As a wallet, manages assets through the command-line. - - - To enable the wallet,enter the following command under the NEO-CLI directory: - - - ``` - dotnet neo-cli.dll - ``` - - To check all the available commands, enter the following command: - - ``` - help - ``` - - For more information, refer to [CLI Command Reference](../node/cli/cli.md). - -- Provides APIs to retrieve blockchain data from nodes. The interfaces are provided through [JSON-RPC](http://www.jsonrpc.org/specification),and the underlying communications use HTTP/HTTPS protocols. - - To start a node which provides RPC service, enter the following command under the NEO-CLI directory: - - ``` - dotnet neo-cli.dll --rpc - ``` - - For more API information, refer to [API Reference](../node/cli/apigen.md). - - -- Provides transaction information of NEP-5 assets. - - To get the NEP-5 assets transaction information, enter the following: - - ``` - dotnet neo-cli.dll --log - ``` - -- Connects to seed nodes directly - - If the connections number is always 0 after opening the NEO-CLI, you can directly connect seed nodes to synchronize blocks using the following command: - - ``` - dotnet neo-cli.dll --nopeers - ``` - -| # | Function | Command | -| ---- | ------------------------------------------- | -------------------- | -| 1 | Run NEO-CLI | `dotnet neo-cli.dll` | -| 2 | Open RPC | `--rpc` | -| 3 | Log the NEP-5 asset transaction information | `--log` | -| 4 | Connect to seed nodes | `--nopeers` | - -> [!Note] -> -> You can enable multiple functions, for example, to enable all the above functions, enter the following: -> -> ``` -> dotnet neo-cli.dll --rpc --log --nopeers -> ``` - -### Creating a Wallet - -The exchange needs to create an online wallet to manage the deposit addresses of users. A wallet is used to store the information of the accounts (both public keys and private keys) and the contracts. It is the most important proof that the user holds. Users must keep the wallet files and the wallet passwords secure. They must not lose or disclose these data. Exchanges do not have to create a wallet for every address. An online wallet usually keeps all deposit addresses of users. A cold wallet (offline wallet) is another storage option which provides better security. - -> [!Note] -> -> NEO-CLI supports wallets in two formats: the sqlite wallet (.db3) and the new [NEP6 standard](https://github.com/neo-project/proposals/blob/master/nep-6.mediawiki) wallet (.json). For exchanges the sqlite wallet is recommended. - -To create a wallet, do the following: - -1. enter `create wallet `. - - is the wallet path and wallet file name. The file extension can be .db3 or .json, depending on the wallet type you are using, for example, `create wallet /home/mywallet.db3`. If the file extension is not specified, the NEP6 format (.json) is used by default. - -2. Set a password for the wallet. - -### Generating Deposit Addresses - -A wallet can store multiple addresses. The exchange needs to generate a deposit address for each user. - -There are two methods to generate deposit addresses: - -- When the user deposit (NEO/NEO GAS) for the first time, the program dynamically generates a NEO address. The advantage is that there is no need to generate addresses at fixed time intervals, while the disadvantage is you can not backup the wallet. - - To develop the program to dynamically generate addresses, use the NEO-CLI API [getnewaddress Method](../node/cli/2.7.4/api/getnewaddress.md). The created address is returned. - -- The exchange creates a batch of NEO addresses in advance. When the user charges (NEO/NEO GAS) for the first time, the exchange assigns a NEO address to him or her. The advantage is the convenience to backup the wallet, while the disadvantage is the need to generate NEO addresses manually. - To generate addresses in batch, run the NEO- CLI command `create address [n]`. The addresses are exported automatically to the address.txt file. - [n] is optional. Its default value is 1. For example, to generate 100 addresses at a time, enter `create address 100`. - - -> [!Note] -> -> Either way, the exchange must import the addresses into the database and distribute them to users. It is generally recommend the exchange use the second way, so as to reduce the external controls and run the wallet more stably. - -## Dealing with Global Assets Transactions - -### Developing Programs for User Deposits and Withdrawals - -For global assets, the exchange needs to develop programs to fulfil the following functions: - -1. Monitor new blocks through NEO-CLI API ([getblock Method](../node/cli/2.7.4/api/getblock2.md)). -2. Deal with user deposits according to the transaction information. -3. Store the transaction records related to the exchange. - -#### User Deposits - -Regarding user deposits, the exchange needs to note the following: - -- NEO blockchain has only one main chain without side chains, will not fork, and will not have isolated blocks. - -- A transaction recorded in NEO blockchain cannot be tampered with, which means a confirmation represents a deposit success. - -- In general, the balance of a deposit address in the exchange is not equal to the balance the user has in the exchange. It may because: - - When transferring or withdrawing, the NEO wallet looks through one or more addresses in the wallet, finds the minimal loose change that meets the requirement and adds up to the total sum of the transaction and then serves that as the input, instead of withdrawing from the specified address (unless the exchange rewrites some functions of NEO wallet to meet their own needs). - - Other operations that may lead to balance inequality, for example, the exchange transfers part of the assets to its cold wallets. - -- There are more than two assets (NEO and NEO GAS) in a NEO address. More assets issued by users (such as stock or token) can be stored. The exchange should determine the assets type when the user deposits. Neither regard other assets as NEO or GAS nor confuse the withdrawal of NEO with GAS. - -- NEO wallet is a full node, which needs to stay online to synchronize blocks. You can view the block synchronization status through the show state in NEO-CLI, for example: - - ``` - ... - neo>show state - Height: 99/99/99, Nodes: 10 - ... - ``` - - That indicates: wallet height is 99/blockchain height is 99/blockchain header height is 99, and number of the connected nodes is 10. - - Suppose this node is fully connected to the P2P network, when the block height gets to the same as the block header height, the node synchronization is completed. Furthermore, when the wallet height, the block height and the block header height are the same, that indicates the node synchronization is completed and the wallet index establishment is completed. - -- In the exchange, the transfer between users should not be recorded through the blockchain. In general, the user's balance are modified in the database directly. Only deposits and withdrawals should be recorded on the blockchain. - -#### Deposit Records - -The exchange needs to write code to monitor every transaction in a block and record all the transactions related to the exchange addresses in the database. If a deposit occurs, the user's balance should be updated. - -Developers can use the `getblock [verbose]` method of NEO-CLI API to retrieve the block information. `` is the block index. `[verbose]` is 0 by default. When `[verbose]` is 0, the method returns the serialized block information in Hexadecimal. You should deserialize the hex string to get the detailed information of the block. When `[verbose]` is 1, the method returns the detailed information of the corresponding block in JSON format. For more information, refer to [getblock Method](../node/cli/2.7.4/api/getblock2.md). - -The block information includes the transactions input and output. The exchange needs to record all its related transactions. The transactions output is in fact the transaction records of the withdrawals of a user. When the exchange sees any of its addresses in the output of the transactions, it updates the NEO/GAS balance of the corresponding user who owns this deposit address. Some exchanges may also do as follows: if it finds an address within the exchange as the output of the transaction, then it records the deposit in its database and modifies the user’s balance after several confirmations (Unless it needs to comply with the operation of other blockchains, this way is not recommended) . - -> [!Note] -> -> - Method getblockcount returns the count of the blocks in the main chain. The first parameter of Method getblock is `` which is the block index. Block index = Block height = The count of the blocks – 1. If getblockcount returns 1234, you should use getblock 1233 to get the information of the latest block. -> - The deposit and withdrawal transactions (NEO/GAS) are all in a type named ContractTransaction. The exchanges only need to care about the ones of ContractTransaction type when they check through the transactions in a block. -> - As the first transaction of every block must be MinerTransaction, you can neglect or jump over it when traversing the blockchain. -> - NEO system takes the transaction as a record unit. -> - -### Dealing with User Withdrawals - -To deal with the user withdrawals for global assets, the exchange needs to do the following: - -1. In NEO-CLI, run `open wallet ` to open the wallet. - -2. Record the user withdrawal transaction and modify the user balance. - -3. (Optional) Customer service deals with withdrawal application. - -4. Send transaction to the user's withdrawal address using the NEO-CLI API method, `sendtoaddress
`. For more information, refer to [sendtoaddress Method](../node/cli/2.7.4/api/sendtoaddress.md). - - - `` :Asset ID - - `
` :Withdrawal address - - `` :Withdrawal amount - - You can also send the transaction to a batch of addresses using API [sendmany Method](../node/cli/2.7.4/api/sendmany.md). - -5. Extract the transaction ID from the returned transaction details in the JSON format, and then record in the database. - -6. Once confirmed by the blockchain, mark the withdrawal transaction as success. - - Similar to deposit monitoring, withdrawals also need to be monitored. If the withdrawal transaction ID is found in the blockchain, it means this transaction has already been confirmed and is a successful withdrawal. - -> [!Note] -> -> - The here refers to the actual amount, instead of the amount multiplied by 10^8. -> - NEO transfer amount must be an integer; otherwise, the transfer will remain unconfirmed although the transaction can be constructed in NEO-CLI, and will thus affect the wallet change status and cause sending failure of other transactions. In this situation, you need to rebuild wallet index, so as to recalculate the transactions and change of the wallet. - -## Dealing with NEP-5 Assets Transactions - -### Receiving User Deposits Notification - -Similar to global assets, the exchange can get the user deposits information of the NEP-5 assets by doing the following: - -1. Get each block details using the `getblock` API, including details of all the transactions in the block. -2. Analyze each transaction type and filter out all transactions of the type "InvocationTransaction". Any transaction other than "InvocationTransaction" can not be a transfer transaction of NEP-5 assets. -3. Invoke the `getapplicationlog` API to get the details of each "InvocationTransaction" transaction and analyze the transaction content to complete the user deposit. - -#### Invoking getapplicationlog - -Before you can use the `getapplicationlog` api to get transaction information, you need to run the following command to open NEO-CLI: - -``` -dotnet neo-cli.dll --rpc --log -``` - -A folder "ApplicationLogs" is generated under the root path. The complete contract log is recorded in this directory, and each NEP-5 transaction is recorded in a JSON file with the named of the transaction txid. - -The following shows an example of the notification file content. - -```JSON -{ - "jsonrpc": "2.0", - "id": 1, - "result": { - "txid": "0xef8957a7bbf83822704f79d63c5f36f3c2b006d928ce978c1d97c23551deb7c8", - "vmstate": "HALT, BREAK", - "gas_consumed": "1.884", - "stack": [], - "notifications": [ - { - "contract": "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "state": { - "type": "Array", - "value": [ - { - "type": "ByteArray", - "value": "7472616e73666572" - }, - { - "type": "ByteArray", - "value": "9393ee15ce6612484ab5be3bbc78c82af8dc0e07" - }, - { - "type": "ByteArray", - "value": "2b41aea9d405fef2e809e3c8085221ce944527a7" - }, - { - "type": "ByteArray", - "value": "00c2eb0b" - } - ] - } - } - ] - } -} -``` - - - -> [!Note] -> -> - The failed NEP-5 transaction can also be recorded in blockchain, so you need to determine whether the vm status parameter "vmstate" is correct. -> - "vmstate" indicates the vm status after it executes the contract. If it contains "FAULT", that means the execution is failed and the transaction is invalid. - -The parameters related to a transaction in the file are the following: - -- **contract**: the script hash of smart contract, by which the exchange can identify assets type. For example, "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9" is the script hash and the unique identification of the RPX asset. - -- The four objects included in the "value" array of "state" are: - - [event, from account, to account, amount] - - - The first object with the type "bytearray" and the value "7472616e73666572", as shown in the example, can be converted to the string "transfer". "transfer" is a method in NEP-5 that represents an asset transfer. - - ```json - { - "type": "ByteArray", - "value": "7472616e73666572" - } - ``` - - - The second object in the array is the account address where the asset is transferred from. Its type "bytearray" and the value "9393ee15ce6612484ab5be3bbc78c82af8dc0e07“ can be converted to "AVECC4AcGXfDjm7cGmfGuxVRGTu6FxoQ7h". Note that for the hexadecimal string with "0x" prefix, it is processed as big endian; otherwise, it is processed as small endian. - - ```json - { - "type": "ByteArray", - "value": "9393ee15ce6612484ab5be3bbc78c82af8dc0e07" - } - ``` - - - The third object in the array is the account address where the asset is transferred to. Its type "bytearray" and the value "2b41aea9d405fef2e809e3c8085221ce944527a7“ can be converted to "AKibPRzkoZpHnPkF6qvuW2Q4hG9gKBwGpR". If the address is an exchange account address, it is a deposit transaction. - - ```json - { - "type": "ByteArray", - "value": "2b41aea9d405fef2e809e3c8085221ce944527a7" - } - ``` - - - The fourth object in the array is the transfer amount. Its type is "bytearray" and the value is 200000000. There are two types of amount, integer and bytearray. Note that when dealing with amount of the interger type, the value conversion method is different than that of the bytearray type. - - ```json - { - "type": "ByteArray", - "value": "00c2eb0b" - } - ``` - -### Querying User Balance - -To query the user's balance, the exchange needs to do the following: - -1. Construct JSON files to invoke three methods (`balanceOf`, `decimals`, and `symbol`) through the PRC API invokefunction. -2. Send the JSON files to NEO RPC server. -3. Calculate the user balance according to the returned values. - -#### invokefunction - -In JSON, a general invokefunction request body is in the following form: - -``` -{ - "jsonrpc": "2.0", - "method": "invokefunction", - "params": [ - "script hash", - "method name", - [ - { - "optional arguments" - } - ] - ], - "id": 1 -} -``` - -You need to replace these strings when querying the user's balance: - -- script hash - - The script hash of the NEP-5 token you are querying. For example, you can find the script hash of RPX is : *0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9*. - - -- method name - - The name of the method you are invoking. To query the user's balance, you need to invoke these three methods: - - **balanceOf** - - - Syntax: `public static BigInteger balanceOf(byte[] account)` - - Remarks: "balanceOf" returns the token balance of the '''account'''. - - **decimals** - - - Syntax: `public static byte decimals()` - - Remarks: "decimals" returns the number of decimals used by the token. - - **symbol** - - - Syntax: `public static string symbol()` - - Remarks: "symbol" returns the token symbol. - - -- optional arguments - - Optional. If the method you are invoking requires arguments, you can pass them by constructing these parameters into an array. For example, "balanceOf" in NEP-5 returns the token balance of the "account": - - `public static BigInteger balanceOf(byte[] account)` - - So you need to pass the account as an argument in the "balanceOf" method. - -#### Example - -##### **Invoking balanceOf** - -Suppose the account address is AKibPRzkoZpHnPkF6qvuW2Q4hG9gKBwGpR, you need to convert it into Hash160 type and construct this parameter as a JSON object: - -```json -{ - "type": "Hash160", - "value": "0xa7274594ce215208c8e309e8f2fe05d4a9ae412b" -} -``` - -Then you can construct the JSON message as the following: - -Request Body: - -```json -{ - "jsonrpc": "2.0", - "method": "invokefunction", - "params": [ - "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "balanceOf", - [ - { - "type": "Hash160", - "value": "0xa7274594ce215208c8e309e8f2fe05d4a9ae412b" - } - ] - ], - "id": 3 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 3, - "result": { - "script": "142b41aea9d405fef2e809e3c8085221ce944527a751c10962616c616e63654f6667f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ec", - "state": "HALT, BREAK", - "gas_consumed": "0.338", - "stack": [ - { - "type": "ByteArray", - "value": "00c2eb0b" - } - ] - } -} -``` - -It returns "00c2eb0b" which can be converted to interger **200000000**. - -##### **Invoking decimals** - -Request Body: - -```json -{ - "jsonrpc": "2.0", - "method": "invokefunction", - "params": [ - "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "decimals", - [] - ], - "id": 2 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 2, - "result": { - "script": "00c108646563696d616c7367f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ec", - "state": "HALT, BREAK", - "gas_consumed": "0.156", - "stack": [ - { - "type": "Integer", - "value": "8" - } - ] - } -} -``` - -It returns integer 8. - -##### **Invoking symbol** - -Request Body: - -```json -{ - "jsonrpc": "2.0", - "method": "invokefunction", - "params": [ - "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "symbol", - [] - ], - "id": 1 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "result": { - "script": "00c10673796d626f6c67f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ec", "state": "HALT, BREAK", - "gas_consumed": "0.141", - "stack": [ - { - "type": "ByteArray", - "value": "525058" - } - ] - } -} -``` - -It returns "525058" which can be converted to string "RPX". - -##### **Calculating the User Balance** - -According to all the returned values, we can calculate the user balance as follows: -The balance = 200000000/108 RPX = 2 RPX - -### Dealing with User Withdrawals - -The exchange can choose one of the following way to send NEP-5 assets to users: - -- NEO-CLI command: `send` -- RPC method: `sendfrom` -- RPC method: `sendtoaddress` -- PRC method: `sendmany` - -> [!Note] -> -> You need to open the wallet in NEO-CLI before you can use these API. - -#### NEO-CLI Command: send - -##### Syntax - -`send
[fee = 0]` - -##### Parameters - -- txid|script hash: the asset ID. - -- address: the payment address. - -- value: the transfer amount. - -- fee: This parameter can be left empty. The default value is 0. - - -This command verifies the wallet password. - -##### Example - -To transfer 100 RPX to the address AeSHyuirtXbfZbFik6SiBW2BEj7GK3N62b, enter the following: - -``` -send 0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9 AeSHyuirtXbfZbFik6SiBW2BEj7GK3N62b 100 -``` - -If you need to send global asset, just change the first parameter to txid. For example, -The txid of NEO: 0xc56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b -The txid of GAS: 0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7 - -#### RPC Method: sendfrom - -The key "params" includes an array of at least four parameters. - -`"params":[script hash, address from, address to, amount, fee(optional), change address(optional)]` - -For example, to send 1 RPX from AKibPRzkoZpHnPkF6qvuW2Q4hG9gKBwGpR to AVECC4AcGXfDjm7cGmfGuxVRGTu6FxoQ7h, construct a JSON file as follows and send it to RPC server. - -Request Body: - -```json -{ - "jsonrpc": "2.0", - "method": "sendfrom", - "params": ["0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9","AKibPRzkoZpHnPkF6qvuW2Q4hG9gKBwGpR","AVECC4AcGXfDjm7cGmfGuxVRGTu6FxoQ7h",1], - "id": 1 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "result": { - "txid": "0xec413354b76fc50a614419f76f131c873da0b17e0fd2dd9170c955b667de08ef", - "size": 219, - "type": "InvocationTransaction", - "version": 1, - "attributes": [ - { - "usage": "Script", - "data": "2b41aea9d405fef2e809e3c8085221ce944527a7" - } - ], - "vin": [], - "vout": [], - "sys_fee": "0", - "net_fee": "0", - "scripts": [ - { - "invocation": "401743a9c3fc91f131aea1c872d166e9c6fae577647884cd8511986041561c2b3e574c1708f662e570688d1a31db7cea281d43615b7fa64d7fa3babf0f6477c31e", - "verification": "2103c532d9335f512e1198ede5c3d35524e6a3b4598f1eb335193b09c4cd52591927ac" - } - ], - "script": "0400e1f505149393ee15ce6612484ab5be3bbc78c82af8dc0e07142b41aea9d405fef2e809e3c8085221ce944527a753c1087472616e7366657267f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ecf166c72745294a433e52", - "gas": "0" - } -} -``` - -#### RPC Method: sendtoaddress - -The key "params" includes an array of at least three parameters. - -`"params":[script hash, address, amount, fee(optional), change address(optional)]` - -For example, to send 1 RPX to AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg , construct a JSON file as follows and send it to RPC server. - -Request Body: - -```json -{ - "jsonrpc":"2.0", - "method":"sendtoaddress", - "params":[ - "0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg", - "1", - "0", - "ARkJ8QcVdYL68WRvN3wj3TSvXX8CgmC73Z" - ], - "id":1 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc":"2.0", - "id":1, - "result":{ - "txid":"0xc6d4bf7c62fb47e0b2a6e838c3a1ca297622a1b1df7ceb2d30fa4ef8b7870700", - "size":219, - "type":"InvocationTransaction", - "version":1, - "attributes":[ - { - "usage":"Script", - "data":"5305fbbd4bd5a5e3e859b452b7897157eb20144f" - } - ], - "vin":[ - - ], - "vout":[ - - ], - "sys_fee":"0", - "net_fee":"0", - "scripts":[ - { - "invocation":"4054fbfca678737ae164ebf0e476da0c8215782bc42b67ae08cf4d8a716eeef81fcc17641e7f63893c3e685fb7eb1fb8516161c5257af41630f4508dde3afa3a8c", - "verification":"210331d1feacd79b53aeeeeb9de56018eadcd07948675a50258f9e64a1204b5d58d1ac" - } - ], - "script":"0400e1f50514d710f6f3f0bad2996a09a56d454cfc116a881bfd145305fbbd4bd5a5e3e859b452b7897157eb20144f53c1087472616e7366657267f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ecf166187b7883718089c8", - "gas":"0" - } -} -``` - -#### RPC Method: sendmany - -The key "params" includes an array of at least one parameter: - -`"params":[[], fee(optional), change address(optional)]` - -For example, to send 15.5 RPX and 0.0001 GAS to AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg and the `change address` is also AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg, you can construct a JSON file as follows and send it to RPC server. - -Request Body: - -```json -{ - "jsonrpc":"2.0", - "method":"sendmany", - "params":[ - [ - { - "asset":"0xecc6b20d3ccac1ee9ef109af5a7cdb85706b1df9", - "value":"15.5", - "address":"AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - }, - { - "asset":"0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", - "value":"0.0001", - "address":"AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - } - ],"0.00001","AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - ], - "id":1 -} -``` - -After sending the request, you will get the following response: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "result": { - "txid": "0xe1351c9c9f2205a801d1b04f0df2d65fb4b1692d7d3b06cf41e0712fd1b12c9c", - "size": 373, - "type": "InvocationTransaction", - "version": 1, - "attributes": [ - { - "usage": "Script", - "data": "6d64dc9e50af8e911247436b264c8f7d791ad58c" - } - ], - "vin": [ - { - "txid": "0x9f0a28a912527604ab4b7d5e8b8d1a9b57631fcbab460132811ae7b6ed1ccaff", - "vout": 1 - } - ], - "vout": [ - { - "n": 0, - "asset": "0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", - "value": "0.0001", - "address": "AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - }, - { - "n": 1, - "asset": "0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", - "value": "0.01359", - "address": "AbP3FU3YcqBrWh72nc9deyQB99eazG9XUg" - } - ], - "sys_fee": "0", - "net_fee": "0.00001", - "scripts": [ - { - "invocation": "40644ab915419dbf855a52d5c75596e80b78c8e928cc0ce91ae6afc3b75a0c31ee54efe1836f9ec232f6c42dcb3ace0bfdc688e626944fa20970a76064975eade9", - "verification": "2103d4b6fc2d116855f86a483d151182f68e88e6ddd13f3f1f3631e36300aac122bfac" - } - ], - "script": "04801f635c14d710f6f3f0bad2996a09a56d454cfc116a881bfd146d64dc9e50af8e911247436b264c8f7d791ad58c53c1087472616e7366657267f91d6b7085db7c5aaf09f19eeec1ca3c0db2c6ecf166f871fb30fc859b77", - "gas": "0" - } -} -``` - -### See Also - -[NEP-5 Token Standard](https://github.com/neo-project/proposals/blob/master/nep-5.mediawiki "NEP5") - -[Data Transformation Examples](https://github.com/PeterLinX/NeoDataTransformation) - -## Distributing GAS to Users - -The exchange can determine whether to distribute GAS to users. GAS is used to pay to the NEO blockchain for recording and additional services. - -### What is GAS ? - -NeoGas (abbreviated as GAS) represents the right to use the Neo Blockchain. There will be 100 million GAS in total. GASs are generated along with every new block. The issuance will slow down according to a set slowly-decreasing pace, while GAS will go through a generating process to grow from zero to 100 million. Once NEO is acquired, GAS will be generated in the system following the algorithms. - -### Calculating the Available GAS Amount - -- Available *GAS = f(neo_amount, Δt_const)* - - - Δt_const = t_end - t_start - - t_end = the moment that Neo goes into the state of spent - - t_start = the moment that Neo goes into the state of unspent - - Δt_const is fixed, thus the available Gas is of a fixed amount too. And this amount is a function of the amount of Neo held by the user and the duration between the moments that he or she transferred this amount of Neo into and out of his or her address. - - -- Unavailable *GAS = f(neo_amount, Δt_var)* - - - Δt_var = t - t_start - - t is the current time - - t_start = the moment that Neo goes into the state of unspent - - The current time is a variable, so the amount of the unavailable GAS also grows through time, which means it is a variable. - -### Distributing GAS to Users - -Suppose all the exchange addresses are stored in one wallet, the following chart demonstrates the procedure and computational formula how the exchange distributes GAS to the user A. - - -![gasflow_en](../sc/assets/gasflow_en.png) - - -The shorter the snapshot interval, the more precise the calculation is. If the snapshot interval is not uniform, use the weighted average calculation method. - -### Claiming GAS - -GAS becomes claimable after the user transfer his or her NEO. For example, **someone has NEO in address A and GAS are not claimable, he transfer his NEO to himself (address A) then the NEO GAS are claimable.** - -The following table lists the GAS claiming steps and corresponding commands. - -| # | Steps | Command | -| ---- | :----------------------------------------------------------- | ----------------------------------------------- | -| 1 | Run NEO-CLI | `dotnet neo-cli.dll --rpc` | -| 2 | Check the client version | `version` | -| 3 | Check the synchronized height of the client ( Height: height/header height, Nodes: amount of connected nodes). | `show state` | -| 4 | Create a wallet | `create wallet /home/NeoNode/test.db3` | -| 5 | Open the wallet created in the last step | `open wallet /home/NeoNode/test.db3` | -| 6 | Check the address list in the wallet | `list address` | -| 7 | Check the assets in the wallet | `list asset` | -| 8 | Check the GAS balances details in the wallet | `show gas` | -| 9 | Transfer NEO to your address(e.g. AaAHt6Xi51iMCaDaYoDFTFLnGbBN1m75SM 1) to change the status of Gas to be claimable. | `send NEO AaAHt6Xi51iMCaDaYoDFTFLnGbBN1m75SM 1` | -| 10 | Get the details of the balances of GAS in the wallet again. Now the status of all the GAS should be available to claim. | `show gas` | -| 11 | Claim GAS. | `claim gas` | -| 12 | Check balance again. | `list asset` | - diff --git a/en-us/network/private-chain/private-chain.md b/en-us/network/private-chain/private-chain.md index f7ffa68cce..43390a6964 100644 --- a/en-us/network/private-chain/private-chain.md +++ b/en-us/network/private-chain/private-chain.md @@ -25,7 +25,7 @@ Do the following on four virtual machines: ## Creating wallet files 1. Create four wallet files, wallet1.db3 - wallet4.db3, using NEO-CLI or NEO-GUI. The following screenshot shows the creation with NEO-CLI. -2. Record the public keys of four wallets, i.e. directly copy them on the screen and save to a txt file or use `list key` in [CLI Command](../node/cli/cli.md) to view the public key, and then copy it. +2. Record the public keys of four wallets, i.e. directly copy them on the screen and save to a txt file or use `list key` in [CLI Command](../../node/cli/cli.md) to view the public key, and then copy it. 3. Copy the four wallet files into each of the four virtual machines neo-cli folder. ![image](../../../assets/privatechain_3.png) diff --git a/en-us/node/cli/2.9.2/api.md b/en-us/node/cli/2.9.2/api.md new file mode 100644 index 0000000000..c5355a7c15 --- /dev/null +++ b/en-us/node/cli/2.9.2/api.md @@ -0,0 +1,160 @@ +# API Reference + +Each node in the Neo-CLI provides an API interface for obtaining blockchain data from a node, making it easy to develop blockchain applications. The interface is provided via [JSON-RPC](http://wiki.geekdream.com/Specification/json-rpc_2.0.html), and the underlying protocol uses HTTP/HTTPS for communication. To start a node that provides an RPC service, run the following command: + +`dotnet neo-cli.dll /rpc` + +## Configuring the config.json file + +To access the RPC server via HTTPS, you need to modify the configuration file config.json before starting the node and set the domain name, certificate, and password: + +```json +{ + "ApplicationConfiguration": { + "Paths": { + "Chain": "Chain" + }, + "P2P": { + "Port": 10333, + "WsPort": 10334 + }, + "RPC": { + "Port": 10331, + "SslCert": "YourSslCertFile.xxx", + "SslCertPassword": "YourPassword" + } + } +} +``` + +To invoke some API methods that require you to open a wallet, you also need to make the following changes in `config.json` before starting the node: + +- Change the UnlockWallet status `IsActive` to `true`. +- Specify the file name and password of the desired wallet. + +```json +... +"UnlockWallet": { + "Path": "YourWallet.json", + "Password": "YourPassword", + "StartConsensus": false, + "IsActive": true + } +... +``` + +Thereafter, when you open NEO-CLI, the client will automatically open the specified wallet and download the wallet index after it has been synchronized to the latest block height. + +## Listening ports + +After the JSON-RPC server starts, it will monitor the following ports, corresponding to the Main and Test nets: + +For P2P and WebSocket information see [Node/Introduction](../../introduction.md). + +| | Main Net | Test Net | +| -------------- | -------- | -------- | +| JSON-RPC HTTPS | 10331 | 20331 | +| JSON-RPC HTTP | 10332 | 20332 | + +## Command List + +| Command | Reference | Explanation | Comments | +| ----------------------------------------------- | ------------------------------------------- | ------------------------------------------------------------ | ---------------------------- | +| [dumpprivkey](api/dumpprivkey.md) | \
| Exports the private key of the specified address | Need to open the wallet | +| [getaccountstate](api/getaccountstate.md) | \
| Checks account asset information according to account address | | +| [getassetstate](api/getassetstate.md) | \ | Queries asset information according to the specified asset number | | +| [getbalance](api/getbalance.md) | \ | Returns the balance of the corresponding asset in the wallet according to the specified asset number. | Need to open the wallet | +| [getbestblockhash](api/getbestblockhash.md) | | Gets the hash of the tallest block in the main chain | | +| [getblock](api/getblock.md) | \ [verbose=0] | Returns the corresponding block information according to the specified hash value | | +| [getblock](api/getblock2.md) | \ [verbose=0] | Returns the corresponding block information according to the specified index | | +| [getblockcount](api/getblockcount.md) | | Gets the number of blocks in the main chain | | +| [getblockhash](api/getblockhash.md) | \ | Returns the hash value of the corresponding block based on the specified index | | +| [getblockheader](api/getblockheader.md) | \ [verbose=0] | Returns the corresponding block header information according to the specified script hash | | +| [getblocksysfee](api/getblocksysfee.md) | \ | Returns the system fees before the block according to the specified index | | +| [getconnectioncount](api/getconnectioncount.md) | | Gets the current number of connections for the node | | +| [getcontractstate](api/getcontractstate.md) | \ | Returns information about the contract based on the specified script hash | | +| [getnewaddress](api/getnewaddress.md) | | Creates a new address | Need to open the wallet | +| [getrawmempool](api/getrawmempool.md) | | Gets a list of unconfirmed transactions in memory | | +| [getrawtransaction](api/getrawtransaction.md) | \ [verbose=0] | Returns the corresponding transaction information based on the specified hash value | | +| [getstorage](api/getstorage.md) | \ \ | Returns the stored value based on the contract script hash and key | | +| [gettxout](api/gettxout.md) | \ \ | Returns the corresponding transaction output (change) information based on the specified hash and index | | +| [getpeers](api/getpeers.md) | | Gets a list of nodes that are currently connected/disconnected by this node | | +| [getversion](api/getversion.md) | | Gets version information of this node | | +| [getvalidators](api/getvalidators.md) | | Gets NEO consensus nodes information | | +| [getwalletheight](api/getwalletheight.md) | | Gets the current wallet index height. | Need to open the wallet | +| [invoke](api/invoke.md) | \ \ | Invokes a smart contract at specified script hash with the given parameters | | +| [invokefunction](api/invokefunction.md) | \ \ \ | Invokes a smart contract at specified script hash, passing in an operation and its params | | +| [invokescript](api/invokescript.md) | \