From db8a5a90e82ee4403f2f42cb3f28f772655b8ade Mon Sep 17 00:00:00 2001 From: nswbmw Date: Fri, 20 Jul 2018 23:41:09 +0800 Subject: [PATCH] docs: migrate to asch-docs --- README.md | 5 +- docs/README.md | 32 - docs/asch_cli_usage.md | 1344 ------- docs/asch_cli_usage_de.md | 906 ----- docs/asch_cli_usage_en.md | 907 ----- docs/asch_dapp_default_api.md | 681 ---- docs/asch_dapp_default_api_en.md | 1146 ------ docs/asch_dapps_introduction.md | 62 - docs/asch_dapps_introduction_de.md | 85 - docs/asch_dapps_introduction_en.md | 84 - docs/asch_delegate_forging.md | 46 - docs/asch_delegate_forging_en.md | 64 - docs/asch_dev_windows_install.md | 141 - docs/asch_http_interface.md | 3560 ----------------- docs/asch_http_interface_de.md | 1976 --------- docs/asch_http_interface_en.md | 1979 --------- docs/asch_install.md | 207 - docs/asch_install_de.md | 172 - docs/asch_install_en.md | 170 - docs/asch_js_api.md | 994 ----- docs/asch_js_api_en.md | 1042 ----- docs/asch_sdk_api.md | 621 --- docs/asch_sdk_api_en.md | 1017 ----- docs/asch_whitepaper.md | 265 -- docs/asch_whitepaper_de.md | 1 - docs/asch_whitepaper_en.md | 164 - docs/assets/dapp/cctime_file.png | Bin 68119 -> 0 bytes docs/assets/dapp/custom_api_example.png | Bin 52146 -> 0 bytes .../dapp/dapp_variables_article_max_id.png | Bin 28699 -> 0 bytes docs/assets/forging-secret.png | Bin 7784 -> 0 bytes docs/assets/inbuilt-modules.png | Bin 20739 -> 0 bytes docs/assets/process-structure.png | Bin 16085 -> 0 bytes docs/assets/sidechain-deploy.png | Bin 18839 -> 0 bytes docs/assets/win_install/gcc.png | Bin 39948 -> 0 bytes docs/assets/win_install/gcc_verify.png | Bin 37197 -> 0 bytes docs/assets/win_install/install.png | Bin 19470 -> 0 bytes docs/assets/win_install/node.png | Bin 1621 -> 0 bytes docs/assets/win_install/python.png | Bin 1578 -> 0 bytes docs/assets/win_install/run.png | Bin 93888 -> 0 bytes docs/assets/win_install/sqlite3.png | Bin 39951 -> 0 bytes docs/assets/win_install/sqlite3_verify.png | Bin 3750 -> 0 bytes docs/assets/win_install/win10.net.png | Bin 45240 -> 0 bytes docs/dapp_docs/1_hello.md | 316 -- docs/dapp_docs/1_hello_de.md | 167 - docs/dapp_docs/1_hello_en.md | 400 -- docs/dapp_docs/dapp_dev_tutorials.md | 545 --- .../XAS_integration_in_exchange_CN.md | 268 -- .../XCT_integration_in_exchange_CN.md | 345 -- docs/whitepaper/assets/chart.png | Bin 29796 -> 0 bytes docs/whitepaper/assets/chart2.png | Bin 45085 -> 0 bytes docs/whitepaper/assets/math.png | Bin 76160 -> 0 bytes docs/whitepaper/assets/score.png | Bin 1470 -> 0 bytes docs/whitepaper/assets/wechat.png | Bin 30218 -> 0 bytes docs/whitepaper/cctime.md | 248 -- docs/whitepaper/cctime_en.md | 312 -- docs/whitepaper/index.md | 265 -- docs/whitepaper/index_en.md | 164 - 57 files changed, 4 insertions(+), 20697 deletions(-) delete mode 100644 docs/README.md delete mode 100644 docs/asch_cli_usage.md delete mode 100644 docs/asch_cli_usage_de.md delete mode 100644 docs/asch_cli_usage_en.md delete mode 100644 docs/asch_dapp_default_api.md delete mode 100644 docs/asch_dapp_default_api_en.md delete mode 100644 docs/asch_dapps_introduction.md delete mode 100644 docs/asch_dapps_introduction_de.md delete mode 100644 docs/asch_dapps_introduction_en.md delete mode 100644 docs/asch_delegate_forging.md delete mode 100644 docs/asch_delegate_forging_en.md delete mode 100644 docs/asch_dev_windows_install.md delete mode 100644 docs/asch_http_interface.md delete mode 100644 docs/asch_http_interface_de.md delete mode 100644 docs/asch_http_interface_en.md delete mode 100644 docs/asch_install.md delete mode 100644 docs/asch_install_de.md delete mode 100644 docs/asch_install_en.md delete mode 100644 docs/asch_js_api.md delete mode 100644 docs/asch_js_api_en.md delete mode 100644 docs/asch_sdk_api.md delete mode 100644 docs/asch_sdk_api_en.md delete mode 100644 docs/asch_whitepaper.md delete mode 100644 docs/asch_whitepaper_de.md delete mode 100644 docs/asch_whitepaper_en.md delete mode 100644 docs/assets/dapp/cctime_file.png delete mode 100644 docs/assets/dapp/custom_api_example.png delete mode 100644 docs/assets/dapp/dapp_variables_article_max_id.png delete mode 100644 docs/assets/forging-secret.png delete mode 100644 docs/assets/inbuilt-modules.png delete mode 100644 docs/assets/process-structure.png delete mode 100644 docs/assets/sidechain-deploy.png delete mode 100644 docs/assets/win_install/gcc.png delete mode 100644 docs/assets/win_install/gcc_verify.png delete mode 100644 docs/assets/win_install/install.png delete mode 100644 docs/assets/win_install/node.png delete mode 100644 docs/assets/win_install/python.png delete mode 100644 docs/assets/win_install/run.png delete mode 100644 docs/assets/win_install/sqlite3.png delete mode 100644 docs/assets/win_install/sqlite3_verify.png delete mode 100644 docs/assets/win_install/win10.net.png delete mode 100644 docs/dapp_docs/1_hello.md delete mode 100644 docs/dapp_docs/1_hello_de.md delete mode 100644 docs/dapp_docs/1_hello_en.md delete mode 100644 docs/dapp_docs/dapp_dev_tutorials.md delete mode 100644 docs/exchange/XAS_integration_in_exchange_CN.md delete mode 100644 docs/exchange/XCT_integration_in_exchange_CN.md delete mode 100644 docs/whitepaper/assets/chart.png delete mode 100644 docs/whitepaper/assets/chart2.png delete mode 100644 docs/whitepaper/assets/math.png delete mode 100644 docs/whitepaper/assets/score.png delete mode 100644 docs/whitepaper/assets/wechat.png delete mode 100644 docs/whitepaper/cctime.md delete mode 100644 docs/whitepaper/cctime_en.md delete mode 100644 docs/whitepaper/index.md delete mode 100644 docs/whitepaper/index_en.md diff --git a/README.md b/README.md index 7b46fd3..5a5d122 100755 --- a/README.md +++ b/README.md @@ -52,6 +52,10 @@ git clone https://github.com/AschPlatform/asch && cd asch && chmod u+x aschd npm install ``` +## Documentation + +[asch-docs](https://github.com/AschPlatform/asch-docs) + ## Web Wallet ``` @@ -130,7 +134,6 @@ node app.js --help ## Releated projects -- [asch-docs](https://github.com/AschPlatform/asch/tree/master/docs) - [asch-cli](https://github.com/AschPlatform/asch-cli) - [asch-js](https://github.com/AschPlatform/asch-js) - [asch-sandbox](https://github.com/AschPlatform/asch-sandbox-dist) diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index cb1c176..0000000 --- a/docs/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# asch_docs -Asch documents - -## 文档索引 - -- [白皮书](./asch_whitepaper.md) -- [节点安装](./asch_install.md) -- [受托人锻造及收益机制](./asch_delegate_forging.md) -- [命令行客户端](./asch_cli_usage.md) -- [Http接口](./asch_http_interface.md) -- [Dapp开发](./asch_dapps_introduction.md) - -## Documents index - -- [Whitepaper](./asch_whitepaper_en.md) -- [Install](./asch_install_en.md) -- [Delegate & forging](./asch_delegate_forging_en.md) -- [Command line interface](./asch_cli_usage_en.md) -- [Http interface](./asch_http_interface_en.md) -- Dapp / Sidechain - - [Dapp Javascript SDK](./asch_sdk_api_en.md) - - [Dapp Http API](./asch_dapp_default_api_en.md) - - [Dapp development tutorial](./asch_dapps_introduction_en.md) - -## Inhaltsverzeichnis - -- [Whitepaper](./asch_whitepaper_de.md) -- [Installation](./asch_install_de.md) -- [Delegation & Schmiede](./asch_delegate_forging_de.md) -- [Command Line Interface](./asch_cli_usage_de.md) -- [Http Interface](./asch_http_interface_de.md) -- [Dapp Entwicklung](./asch_dapps_introduction_de.md) \ No newline at end of file diff --git a/docs/asch_cli_usage.md b/docs/asch_cli_usage.md deleted file mode 100644 index 39c1c86..0000000 --- a/docs/asch_cli_usage.md +++ /dev/null @@ -1,1344 +0,0 @@ -Table of Contents -================= - - * [ASCH-CLI说明](#asch-cli说明) - * [0 asch-cli简介](#0-asch-cli简介) - * [1 asch-cli的安装](#1-asch-cli的安装) - * [2 asch-cli使用说明](#2-asch-cli使用说明) - * [3 asch-cli支持的选项](#3-asch-cli支持的选项) - * [3.1 打印帮助文档](#31-打印帮助文档) - * [3.2 打印asch-cli版本号](#32-打印asch-cli版本号) - * [3.3 指定要连接的asch服务器主机名或者ip](#33-指定要连接的asch服务器主机名或者ip) - * [3.4 指定要连接的asch服务器的端口](#34-指定要连接的asch服务器的端口) - * [3.5 指定主链](#35-指定主链) - * [4 asch-cli支持的命令](#4-asch-cli支持的命令) - * [4.1 区块链blockchain](#41-区块链blockchain) - * [4.1.1 查看区块链高度](#411-查看区块链高度) - * [4.1.2 查看区块链状态](#412-查看区块链状态) - * [4.1.3 查看节点信息](#413-查看节点信息) - * [4.1.4 全网节点状态](#414-全网节点状态) - * [4.1.5 全网受托人状态](#415-全网受托人状态) - * [4.1.6 查看全网节点的ip归属](#416-查看全网节点的ip归属) - * [4.1.7 创建创世块文件](#417-创建创世块文件) - * [4.2 账户account](#42-账户account) - * [4.2.1 根据密码查看账户信息](#421--根据密码查看账户信息) - * [4.2.2 根据公钥查看账户信息](#422-根据公钥查看账户信息) - * [4.2.3 根据地址查看账户余额](#423-根据地址查看账户余额) - * [4.2.4 根据地址查看账户信息](#424-根据地址查看账户信息) - * [4.2.5 查看账户地址投了哪些受托人](#425-查看账户地址投了哪些受托人) - * [4.2.6 加密相关](#426-加密相关) - * [4.2.7 账户锁仓](#427-账户锁仓) - * [4.3 受托人delegate](#43-受托人delegate) - * [4.3.1 查看全部受托人个数](#431-查看全部受托人个数) - * [4.3.2 查看受托人详情并排序](#432-查看受托人详情并排序) - * [4.3.3 根据受托人公钥查看都是谁为他投了票](#433-根据受托人公钥查看都是谁为他投了票) - * [4.3.4 根据公钥查看受托人详情](#434-根据公钥查看受托人详情) - * [4.3.5 根据名字查看受托人详情](#435-根据名字查看受托人详情) - * [4.3.5 注册受托人](#435-注册受托人) - * [4.3.6 给受托人投票](#436-给受托人投票) - * [4.3.7 给受托人取消投票](#437-给受托人取消投票) - * [4.4 区块block](#44-区块block) - * [4.4.1 查看(分析)全网区块信息](#441-查看分析全网区块信息) - * [4.4.2 根据区块id查看区块详情](#442-根据区块id查看区块详情) - * [4.4.3 根据区块高度查看区块详情](#443-根据区块高度查看区块详情) - * [4.4.4 根据区块id查看区块详情-包含交易信息](#444-根据区块id查看区块详情-包含交易信息) - * [4.4.5 根据区块高度查看区块详情-包含交易信息](#445-根据区块高度查看区块详情-包含交易信息) - * [4.4.6 验证区块文件字节](#446-验证区块文件字节) - * [4.4.7 验证区块文件payloadhash](#447-验证区块文件payloadhash) - * [4.4.8 验证区块文件区块id](#448-验证区块文件区块id) - * [4.4.8 验证区块签名是否通过](#448-验证区块签名是否通过) - * [4.5 交易transaction](#45-交易transaction) - * [4.5.1 根据公钥查看未确认的交易](#451-根据公钥查看未确认的交易) - * [4.5.2 查看(分析)全网交易信息](#452-查看分析全网交易信息) - * [4.5.3 根据交易id查看交易详情](#453-根据交易id查看交易详情) - * [4.5.4 转账](#454-转账) - * [4.5.5 设置二级密码](#455-设置二级密码) - * [4.5.6 验证交易文件bytes](#456-验证交易文件bytes) - * [4.5.7 验证交易文件id](#457-验证交易文件id) - * [4.4.8 验证交易签名是否通过](#448-验证交易签名是否通过) - * [4.6 侧链dapp](#46-侧链dapp) - * [4.6.1 注册dapp](#461-注册dapp) - * [4.6.2 dapp充值](#462-dapp充值) - * [4.6.3 智能合约的增删](#463--智能合约的增删) - * [4.6.4 dapp交易](#464-dapp交易) - * [4.6.5 dapp创建安装相关](#465--dapp创建安装相关) - -Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc) - - -# ASCH-CLI说明 - - -## 0 asch-cli简介 -以下内容引用自 [Asch白皮书](/asch_whitepaper.md) - ->asch-cli是Asch系统提供了一个命令行工具,只需要根据提示输入一些配置项,就可以快速的建立一个侧链,并可在侧链上开发任意类型的应用。其次,系统还提供了一系列的 api 帮助用户构建复杂的智能合约应用,这些 api 涵盖共识、强随机数、数据库、密码学等方面。 - - -## 1 asch-cli的安装 -sudo apt-get install npm #安装js软件包管理器npm - -npm install -g asch-cli #国内服务器可以考虑加上 “--registry=http://registry.npm.taobao.org” 参数加快安装速度 - -## 2 asch-cli使用说明 -asch-cli [选项] [命令] - -## 3 asch-cli支持的选项 -### 3.1 打印帮助文档 -参数值: -h, --help - -返回值: asch-cli命令或者子命令的帮助文档 - -使用方法:asch-cli -h(查看asch-cli帮助文档);asch-cli 子命令 -h(查看子命令的帮助文档) - -示例: - -``` -root@asch:~# asch-cli -h #查看asch-cli帮助信息 - Usage: asch-cli [options] [command] - Commands: - - getheight get block height - getblockstatus get block status - openaccount [secret] open your account and get the infomation by secret - openaccountbypublickey [publickey] open your account and get the infomation by publickey - getbalance [address] get balance by address - getaccount [address] get account by address - getvoteddelegates [options] [address] get delegates voted by address - getdelegatescount get delegates count - getdelegates [options] get delegates - getvoters [publicKey] get voters of a delegate by public key - getdelegatebypublickey [publicKey] get delegate by public key - getdelegatebyusername [username] get delegate by username - getblocks [options] get blocks - getblockbyid [id] get block by id - getblockbyheight [height] get block by height - getpeers [options] get peers - getunconfirmedtransactions [options] get unconfirmed transactions - gettransactions [options] get transactions - gettransaction [id] get transactions - sendmoney [options] send money to some address - registerdelegate [options] register delegate - upvote [options] vote for delegates - downvote [options] cancel vote for delegates - setsecondsecret [options] set second secret - registerdapp [options] register a dapp - contract [options] contract operations - crypto [options] crypto operations - dapps [options] manage your dapps - creategenesis [options] create genesis block - peerstat analyze block height of all peers - delegatestat analyze delegates status - ipstat analyze peer ip info - - Options: - - -h, --help output usage information - -V, --version output the version number - -H, --host Specify the hostname or ip of the node, default: 127.0.0.1 - -P, --port Specify the port of the node, default: 4096 - -M, --main Specify the mainnet, default: false - -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getvoteddelegates -h #查看子命令帮助 - Usage: getvoteddelegates [options] [address] - get delegates voted by address - Options: - - -h, --help output usage information - -o, --offset - -l, --limit -``` - -### 3.2 打印asch-cli版本号 -参数值: -V, --version - -返回值: asch-cli命令的版本号 - -使用方法:asch-cli -V - -示例: - -``` -root@asch:~# asch-cli -V -1.0.0 -``` - -### 3.3 指定要连接的asch服务器主机名或者ip -参数值: -H, --host 默认:127.0.0.1 - -返回值: 无 - -使用方法:asch-cli -H 45.32.248.33 [子命令] - -示例: - -``` -root@asch:~# asch-cli -H 45.32.248.33 getheight #查看45.32.248.33服务器最新的区块高度 -101236 -``` - -### 3.4 指定要连接的asch服务器的端口 -参数值: -P, --port 默认:4096 - -返回值: 无 - -使用方法:asch-cli -P 4096 [子命令] - -示例: - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getheight -102313 -``` - -### 3.5 指定主链 -参数值: -M, --main 默认:测试链 - -返回值: 无 - -使用方法:asch-cli -H 45.32.248.33 -P 8192 -M [子命令] - -示例: - -``` -root@asch:~# asch-cli -M -H *.*.*.105 -P 8192 getheight #查看asch主链区块高度 -9388 -``` - - -## 4 asch-cli支持的命令 -### 4.1 区块链blockchain -#### 4.1.1 查看区块链高度 -命令值: getheight - -返回值: 区块链高度 - -使用方法:asch-cli getheight - -示例: - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getheight -105387 -``` - -#### 4.1.2 查看区块链状态 -命令值: getblockstatus - -返回值: json字符串,包含区块链高度、交易费、里程碑、受托人每块奖励、当前总量 - -使用方法:asch-cli getblockstatus - -示例: - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getblockstatus -{ - "success": true, - "height": 105392, - "fee": 10000000, - "milestone": 0, - "reward": 350000000, - "supply": 10036887200000000 -} -``` - -#### 4.1.3 查看节点信息 -命令值: getpeers [options] - -返回值: 列表,包含节点ip、端口、os、asch版本等信息 - -使用方法:asch-cli getpeers -o 偏移量数字 -l限制个数数字 -t 状态值 -s 排序 -v 版本 -p 端口 --os os版本 #详情请参考asch-cli getpeers -h帮助信息 - -示例: - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getpeers -o 1 -l 2 -[ - { - "ip": "45.32.62.184", - "port": 4096, - "state": 2, - "os": "linux3.13.0-87-generic", - "version": "1.0.0" - }, - { - "ip": "45.32.22.78", - "port": 4096, - "state": 2, - "os": "linux3.13.0-87-generic", - "version": "1.0.0" - } -] -``` - - -#### 4.1.4 获取本机连接的所有节点信息 -命令值: peerstat - -返回值: 节点信息,包含节点ip、端口、版本、区块高度等信息 - -备注:展示节点只是和本机有连接的节点,并不是全网所有的节点 - -使用方法:asch-cli peerstat - -示例: - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 peerstat -45.32.248.33:4096 1.0.0 106036 -45.32.62.184:4096 1.0.0 106036 -45.32.19.241:4096 1.0.0 106036 -``` - -#### 4.1.5 全网受托人状态 -命令值: delegatestat - -返回值: 受托人信息,包含全网受托人的名字、地址、投票、生产率、区块生成个数、区块高度、id、上一次生成区块的时间等信息 - -使用方法:asch-cli - -示例: - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 delegatestat -name address rate approval productivity produced height id time -nayimoliuguang 3331976396377269399 93 88.36% 98.39% 1037 105618 12962348710289833740 2016/08/17 21:07:20(1 hour ago) -jack 3705405381126069457 86 88.36% 99.41% 506 105628 5876778147855073736 2016/08/17 21:09:00(1 hour ago) -node_3 12796761013870716784 81 88.36% 80.51% 814 105784 4575518649204137595 2016/08/17 21:38:10(40 mins ago) -wgl_003 9961157415582672274 2 98.65% 99.24% 1047 105852 11175724889329116017 2016/08/17 21:49:40(28 mins ago) -xihulongjing 12676662200687508271 59 88.36% 76.92% 150 105853 15273855606472618453 2016/08/17 21:49:50(28 mins ago) -liangpeili 4514546945474752928 50 88.37% 99.68% 627 105855 3771943180359756069 2016/08/17 21:50:10(28 mins ago) -asch_tea1 8812460086240160222 4 98.58% 98.79% 1059 105857 14968719538781965695 2016/08/17 21:50:30(27 mins ago) -intmaster 7321911740133937168 97 88.36% 100% 1032 105871 6757656887343300317 2016/08/17 21:52:50(25 mins ago) -mode_6 9248745407080572308 8 88.48% 100% 1060 105873 3777454410915098884 2016/08/17 21:53:10(25 mins ago) -``` - -#### 4.1.6 查看全网节点的ip归属 -命令值: ipstat - -返回值: 节点ip归属地 - -使用方法:asch-cli ipstat - -示例: - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 ipstat -美国 US -美国 US -美国 US -日本 JP -中国 CN -中国 CN -中国 CN -中国 CN -中国 CN -中国 CN -``` - -#### 4.1.7 创建创世块文件 -命令值: creategenesis [options] - -返回值: 在当前目录生成genesisBlock.json创世块文件、genGenesisBlock.log创世块日志 - -使用方法:asch-cli creategenesis - -示例: - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 creategenesis -root@asch:~# more genesisBlock.json -{ - "version": 0, - "totalAmount": 10000000000000000, - "totalFee": 0, - "reward": 0, - "payloadHash": "baebdb59d0c19a07c2440e22c0512b4efe9794565b352375195c9e7e8a3817b0", - "timestamp": 0, - "numberOfTransactions": 103, -... -} -``` - -### 4.2 账户account -#### 4.2.1 根据密码查看账户信息 -命令值: openaccount [secret] - -返回值: json字符串,含地址、余额、公钥、二级公钥等信息 - -使用方法:asch-cli openaccount "密码" - -示例: - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 openaccount "fault still attack alley expand music basket purse later educate follow ride" -{ - "address": "16723473400748954103", - "unconfirmedBalance": 20000000000, - "balance": 20000000000, - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9", - "unconfirmedSignature": false, - "secondSignature": false, - "secondPublicKey": "", - "multisignatures": [], - "u_multisignatures": [] -} -``` - -#### 4.2.2 根据公钥查看账户信息 -命令值: openaccountbypublickey [publickey] - -返回值: json字符串,含地址、余额、二级公钥等信息 - -使用方法:asch-cli openaccountbypublickey "公钥" - -示例: - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 openaccountbypublickey "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9" -{ - "address": "16723473400748954103", - "unconfirmedBalance": 20000000000, - "balance": 20000000000, - "unconfirmedSignature": false, - "secondSignature": false, - "secondPublicKey": "", - "multisignatures": [], - "u_multisignatures": [] -} -``` - -#### 4.2.3 根据地址查看账户余额 -命令值: getbalance [address] - -返回值: 整型数字,除以100000000后为大家平时所说的余额 - -使用方法:asch-cli getbalance 账户地址 - -示例: - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getbalance 16723473400748954103 -20000000000 -``` - -#### 4.2.4 根据地址查看账户信息 -命令值: getaccount [address] - -返回值: json字符串,含地址、余额、公钥、二级公钥等信息 - -使用方法:asch-cli getaccount 账户地址 - -示例: - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getaccount 16723473400748954103 -{ - "address": "16723473400748954103", - "unconfirmedBalance": 20000000000, - "balance": 20000000000, - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9", - "unconfirmedSignature": false, - "secondSignature": false, - "secondPublicKey": "", - "multisignatures": [], - "u_multisignatures": [] -} -``` - -#### 4.2.5 查看账户地址投了哪些受托人 -命令值: getvoteddelegates [options] [address] - -返回值: 列表 - -使用方法:asch-cli getvoteddelegates 账户地址 -o 偏移量数字 -l 限制打印的受托人个数数字 - -示例: - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getvoteddelegates 15745540293890213312 -o 1 -l 2 -{ success: true, - delegates: - [ { username: 'wgl_002', - address: '14636456069025293113', - publicKey: 'ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7', - vote: 8902736443247261, - producedblocks: 1041, - missedblocks: 6, - rate: 1, - approval: '88.70', - productivity: '99.42' }, - { username: 'wgl_003', - address: '9961157415582672274', - publicKey: 'c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2', - vote: 8902736443247261, - producedblocks: 1043, - missedblocks: 8, - rate: 2, - approval: '88.70', - productivity: '99.23' }] -``` - -#### 4.2.6 加密相关 -命令值: crypto [操作选项] - -返回值: 列表 - -使用方法:asch-cli -p(根据密码生成公钥);asch-cli -g(生成新账户) - -示例: - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 crypto -g -? Enter number of accounts to generate 1 -[ { address: '16723473400748954103', - secret: 'fault still attack alley expand music basket purse later educate follow ride', - publicKey: 'bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9' } ] -Done -``` - -#### 4.2.7 账户锁仓 -命令值: lock [操作选项] -返回值: 锁仓交易id -使用方法:asch-cli -e "一级密码" -s "二级密码" -h 锁仓高度 -备注:锁仓后且区块高度未达到锁仓高度,则该账户不能执行如下操作: -|交易类型type|备注| -|----|----| -|0|主链XAS转账| -|6|Dapp充值| -|7|Dapp提现| -|8|存储小文件| -|9|发行商注册| -|10|资产注册| -|13|资发行产| -|14|主链uia转账| - -示例: -``` -// 锁仓到高度4340 -password="found knife gather faith wrestle private various fame cover response security predict" -asch-cli lock -e "$password" -h 4340 -a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf -``` - -### 4.3 受托人delegate -#### 4.3.1 查看全部受托人个数 -命令值: getdelegatescount - -返回值: 整型数字 - -使用方法:asch-cli getdelegatescount - -示例: - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getdelegatescount -232 -``` - -#### 4.3.2 查看受托人详情并排序 -命令值: getdelegates [options] - -返回值: 列表 - -使用方法:asch-cli getdelegates -o 偏移量数字 -l 限制打印的受托人个数数字 -s rate:asc #rate:asc代表根据投票数正向排序,其它排序规则请参考asch-cli getdelegates -h帮助信息 - -示例: - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getdelegates -o 1 -l 1 -s rate:asc -[ - { - "username": "wgl_003", - "address": "9961157415582672274", - "publicKey": "c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2", - "vote": 9901544836887660, - "producedblocks": 1044, - "missedblocks": 8, - "fees": 12150495022, - "rewards": 161000000000, - "rate": 2, - "approval": 98.65, - "productivity": 99.24, - "forged": "173150495022" - } -] -``` - -#### 4.3.3 根据受托人公钥查看都是谁为他投了票 -命令值: getvoters [publicKey] - -返回值: 列表 - -使用方法:asch-cli getvoters "受托人公钥" - -示例: - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getvoters "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7" -[ - { - "address": "2918354313445278349", - "publicKey": "4fde4c49f1297d5d3a24b1494204543c4281aff17917ff7ff8ff32da3b4b222f", - "balance": 1215522376203, - "weight": 0.012110398031994424 - }, - { - "address": "1523444724068322527", - "publicKey": "8a6a61c28dc47541aadf1eecec2175c8f768f2331eea3472b1593bf1aa4e1fb4", - "balance": 2109297623765, - "weight": 0.02101519008767971 - }] -``` - -#### 4.3.4 根据公钥查看受托人详情 -命令值: getdelegatebypublickey [publicKey] - -返回值: json字符串,包含受托人名字、地址、投票数、生成的block数、锻造收益等 - -使用方法:asch-cli getdelegatebypublickey "受托人公钥" - -示例: - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getdelegatebypublickey "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7" -{ - "username": "wgl_002", - "address": "14636456069025293113", - "publicKey": "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7", - "vote": 9901546586887660, - "producedblocks": 1042, - "missedblocks": 6, - "fees": 12383762523, - "rewards": 161700000000, - "rate": 1, - "approval": 98.65, - "productivity": 99.43, - "forged": "174083762523" -} -``` -#### 4.3.5 根据名字查看受托人详情 -命令值: getdelegatebyusername [username] - -返回值: json字符串,受托人详情 - -使用方法:asch-cli getdelegatebyusername "受托人名字" - -示例: - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getdelegatebyusername "wgl_002" -{ - "username": "wgl_002", - "address": "14636456069025293113", - "publicKey": "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7", - "vote": 9901546586887660, - "producedblocks": 1042, - "missedblocks": 6, - "fees": 12383762523, - "rewards": 161700000000, - "rate": 1, - "approval": 98.65, - "productivity": 99.43, - "forged": "174083762523" -} -``` - -#### 4.3.5 注册受托人 -命令值: registerdelegate [options] - -返回值: 结果状态值,true或者报错信息 - -使用方法:asch-cli registerdelegate -e "密码" -s "二级密码" -u "受托人名字" - -示例: - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 registerdelegate -e "fault still attack alley expand music basket purse later educate follow ride" -u "delegate_register" -true -``` - -#### 4.3.6 给受托人投票 -命令值: upvote [options] - -返回值: 结果状态值,true或者报错信息 - -使用方法:asch-cli upvote -e "密码" -s "二级密码" -p "受托人公钥" - -示例: - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 upvote -e "fault still attack alley expand music basket purse later educate follow ride" -p "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9" -true -``` - -#### 4.3.7 给受托人取消投票 -命令值: downvote [options] - -返回值: 结果状态值,true或者报错信息 - -使用方法:asch-cli downvote -e "密码" -s "二级密码" -p "受托人公钥" - -示例: - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 downvote -e "fault still attack alley expand music basket purse later educate follow ride" -p "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9" -true -``` - -### 4.4 区块block -#### 4.4.1 查看(分析)全网区块信息 -命令值: getblocks [options] - -返回值: json字符串,包含查询状态、符合查询要求的区块信息 - -使用方法:asch-cli getblocks -o 偏移量数字 -l 限制的个数数字 -r 奖励 -f 费用 -a 总量 -g 生成区块的公钥 -s 排序规则 - -示例: - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getblocks -o 1 -l 1 -r 350000000 -{ - "success": true, - "blocks": [ - { - "id": "5533619110613125681", - "version": 0, - "timestamp": 3914630, - "height": 60481, - "previousBlock": "11174102253820291084", - "numberOfTransactions": 0, - "totalAmount": 0, - "totalFee": 0, - "reward": 350000000, - "payloadLength": 0, - "payloadHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "generatorPublicKey": "68b28341605a24f6684df81882df1b13f421ec1cbba7d9aaa68f6c079705b258", - "generatorId": "10651956562526682705", - "blockSignature": "77115fdaab3215039bcf2bf8b3a461b3b7cafca7adae07e271a1a953ca6531a9e93f985bbec8544d596a568595661f1da742e20797b827d5b20aa75e8d80cc0b", - "confirmations": "45349", - "totalForged": 350000000 - } - ], - "count": 45350 -} -``` -#### 4.4.2 根据区块id查看区块详情 -命令值: getblockbyid [id] - -返回值: json字符串,包含区块id、区块高度、前一个blockid、交易数、总额、费用、奖励、哈希值、区块生成者公钥、id、区块签名、确认数等信息 - -使用方法:asch-cli getblockbyid 区块id - -示例: - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getblockbyid 1425942128040906871 #查看创世块 -{ - "id": "1425942128040906871", - "version": 0, - "timestamp": 0, - "height": 1, - "previousBlock": "", - "numberOfTransactions": 103, - "totalAmount": 10000000000000000, - "totalFee": 0, - "reward": 0, - "payloadLength": 19417, - "payloadHash": "dd5cd3186d32145b01f8fd0bd23e3b3d72414b59b162d2e664e759db8fe60d46", - "generatorPublicKey": "2af8566f8555bafb25df5a50e2e22b91a8577ceabc05d47dbd921572d28330e8", - "generatorId": "1170992220085500484", - "blockSignature": "a8ed06bfbfd1b630b1628e97a5c7c9383337c4ce32825969fad830890e0af981312be635b775ff46eea4f739da043f668a70efd5a940429e39fe5063852f4a01", - "confirmations": "105901", - "totalForged": 0 -} -``` - -#### 4.4.3 根据区块高度查看区块详情 -命令值: getblockbyheight [height] - -返回值: json字符串,包含区块id、区块高度、前一个blockid、交易数、总额、费用、奖励、哈希值、区块生成者公钥、id、区块签名、确认数等信息 - -使用方法:asch-cli getblockbyheight 区块高度 - -示例: - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getblockbyheight 1 -{ - "id": "1425942128040906871", - "version": 0, - "timestamp": 0, - "height": 1, - "previousBlock": "", - "numberOfTransactions": 103, - "totalAmount": 10000000000000000, - "totalFee": 0, - "reward": 0, - "payloadLength": 19417, - "payloadHash": "dd5cd3186d32145b01f8fd0bd23e3b3d72414b59b162d2e664e759db8fe60d46", - "generatorPublicKey": "2af8566f8555bafb25df5a50e2e22b91a8577ceabc05d47dbd921572d28330e8", - "generatorId": "1170992220085500484", - "blockSignature": "a8ed06bfbfd1b630b1628e97a5c7c9383337c4ce32825969fad830890e0af981312be635b775ff46eea4f739da043f668a70efd5a940429e39fe5063852f4a01", - "confirmations": "105922", - "totalForged": 0 -} -``` - -#### 4.4.4 根据区块id查看区块详情-包含交易信息 -命令值: getfullblockbyid [blockid] - -返回值: json字符串,包含区块id、区块高度、前一个blockid、交易数、总额、费用、奖励、哈希值、区块生成者公钥、id、区块签名、确认数、交易详情数组 等信息 - -使用方法:asch-cli getfullblockbyid 区块id -备注:比getblockbyid返回的结果多交易信息(交易信息数组) - -示例: - -``` -asch-cli getfullblockbyid 61e5c7c17a365e079d536dcf7d23acca30b927434ca474df8ce28547e3abbdc4 -{ - "id": "61e5c7c17a365e079d536dcf7d23acca30b927434ca474df8ce28547e3abbdc4", - "version": 0, - "timestamp": 40458800, - "height": 4330, - "previousBlock": "ddc0bb392da3b1d22ac4e2c50d1a30a7adabe35e221fc0aeb80e3c6aaa509f68", - "numberOfTransactions": 1, - "totalAmount": 0, - "totalFee": 10000000, - "reward": 350000000, - "payloadLength": 121, - "payloadHash": "a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf", - "generatorPublicKey": "0ae2e3bcd8c959bccc34445a9473eab1bece60300f3aa00d89612923470dee75", - "generatorId": "4354832300657989346", - "blockSignature": "6b09f19c21574c065015c026eaba049c25827b7008db071f7ac59e4f50538bbd70301dcf2cd9d3bada77e7a4279740fddb55ec72cce7de886517d74bdc1a0d0b", - "totalForged": 360000000, - "transactions": [ // 该区块包含的交易详情数组 - { - "id": "a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf", - "height": 4330, - "blockId": "61e5c7c17a365e079d536dcf7d23acca30b927434ca474df8ce28547e3abbdc4", - "type": 100, // 交易类型为100代表锁仓 - "timestamp": 40458794, - "senderPublicKey": "2856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec4", - "requesterPublicKey": "", - "senderId": "ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M", - "recipientId": "", - "amount": 0, - "fee": 10000000, - "signature": "efd9a349eb2bc0a022461401c312001a5cd9f4f4f2c1e554e5bda465e19d1f0da7b229b68fbcdda81d85e34c3cd331e968f27cc398908e7acd527d27ae7e230a", - "signSignature": "", - "signatures": null, - "args": [ - "4340" // 锁仓高度 - ], - "message": "", - "asset": {} - } - ] -} -``` - -#### 4.4.5 根据区块高度查看区块详情-包含交易信息 -命令值: getfullblockbyheight [blockheight] -返回值: json字符串,包含区块id、区块高度、前一个blockid、交易数、总额、费用、奖励、哈希值、区块生成者公钥、id、区块签名、确认数、交易详情数组 等信息 -使用方法:asch-cli getfullblockbyheight 区块高度 -备注:比getblockbyheight返回的结果多交易信息(交易信息数组) - -示例: - -``` -asch-cli getfullblockbyheight 4330 -{ - "id": "61e5c7c17a365e079d536dcf7d23acca30b927434ca474df8ce28547e3abbdc4", - "version": 0, - "timestamp": 40458800, - "height": 4330, - "previousBlock": "ddc0bb392da3b1d22ac4e2c50d1a30a7adabe35e221fc0aeb80e3c6aaa509f68", - "numberOfTransactions": 1, - "totalAmount": 0, - "totalFee": 10000000, - "reward": 350000000, - "payloadLength": 121, - "payloadHash": "a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf", - "generatorPublicKey": "0ae2e3bcd8c959bccc34445a9473eab1bece60300f3aa00d89612923470dee75", - "generatorId": "4354832300657989346", - "blockSignature": "6b09f19c21574c065015c026eaba049c25827b7008db071f7ac59e4f50538bbd70301dcf2cd9d3bada77e7a4279740fddb55ec72cce7de886517d74bdc1a0d0b", - "totalForged": 360000000, - "transactions": [ // 该区块包含的交易详情数组 - { - "id": "a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf", - "height": 4330, - "blockId": "61e5c7c17a365e079d536dcf7d23acca30b927434ca474df8ce28547e3abbdc4", - "type": 100, // 交易类型为100代表锁仓 - "timestamp": 40458794, - "senderPublicKey": "2856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec4", - "requesterPublicKey": "", - "senderId": "ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M", - "recipientId": "", - "amount": 0, - "fee": 10000000, - "signature": "efd9a349eb2bc0a022461401c312001a5cd9f4f4f2c1e554e5bda465e19d1f0da7b229b68fbcdda81d85e34c3cd331e968f27cc398908e7acd527d27ae7e230a", - "signSignature": "", - "signatures": null, - "args": [ - "4340" // 锁仓高度 - ], - "message": "", - "asset": {} - } - ] -} -``` - -#### 4.4.6 验证区块文件字节 -命令值: getblockbytes [-f block_file] -返回值: 区块文件字节,hex格式数据 -使用方法:asch-cli getblockbytes -f 区块文件 -备注: 下面这几个命令主要是验证区块文件,通过修改fullblock数据来和区块链上的数据进行对比是否一致 - -示例: - -``` -asch-cli getfullblockbyheight 4330 > blockfile -cat blockfile -{ - "id": "61e5c7c17a365e079d536dcf7d23acca30b927434ca474df8ce28547e3abbdc4", - "version": 0, - "timestamp": 40458800, - "height": 4330, - "previousBlock": "ddc0bb392da3b1d22ac4e2c50d1a30a7adabe35e221fc0aeb80e3c6aaa509f68", - "numberOfTransactions": 1, - "totalAmount": 0, - "totalFee": 10000000, - "reward": 350000000, - "payloadLength": 121, - "payloadHash": "a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf", - "generatorPublicKey": "0ae2e3bcd8c959bccc34445a9473eab1bece60300f3aa00d89612923470dee75", - "generatorId": "4354832300657989346", - "blockSignature": "6b09f19c21574c065015c026eaba049c25827b7008db071f7ac59e4f50538bbd70301dcf2cd9d3bada77e7a4279740fddb55ec72cce7de886517d74bdc1a0d0b", - "totalForged": 360000000, - "transactions": [ - { - "id": "a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf", - "height": 4330, - "blockId": "61e5c7c17a365e079d536dcf7d23acca30b927434ca474df8ce28547e3abbdc4", - "type": 100, - "timestamp": 40458794, - "senderPublicKey": "2856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec4", - "requesterPublicKey": "", - "senderId": "ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M", - "recipientId": "", - "amount": 0, - "fee": 10000000, - "signature": "efd9a349eb2bc0a022461401c312001a5cd9f4f4f2c1e554e5bda465e19d1f0da7b229b68fbcdda81d85e34c3cd331e968f27cc398908e7acd527d27ae7e230a", - "signSignature": "", - "signatures": null, - "args": [ - "4340" - ], - "message": "", - "asset": {} - } - ] -} - -asch-cli getblockbytes -f blockfile -00000000305a69026464633062623339326461336231643232616334653263353064316133306137616461626533356532323166633061656238306533633661616135303966363801000000000000000000000080969800000000008093dc140000000079000000a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf0ae2e3bcd8c959bccc34445a9473eab1bece60300f3aa00d89612923470dee75 -``` - -#### 4.4.7 验证区块文件payloadhash -命令值: getblockpayloadhash [-f blockfile] - -返回值: 该区块的paylaod hash - -使用方法:asch-cli getblockpayloadhash -f 区块文件 - -示例: - -``` -asch-cli getfullblockbyheight 4330 > blockfile - -asch-cli getblockpayloadhash -f blockfile -a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf -``` - -#### 4.4.8 验证区块文件区块id -命令值: getblockid [-f blockfile] -返回值: 该区块文件的blockid -使用方法:asch-cli getblockid -f 区块文件 - -示例: -``` -asch-cli getfullblockbyheight 4330 > blockfile - -asch-cli getblockid -f blockfile -61e5c7c17a365e079d536dcf7d23acca30b927434ca474df8ce28547e3abbdc4 -``` - -#### 4.4.8 验证区块签名是否通过 -命令值: verifybytes [options] -返回值: true or false -使用方法:asch-cli verifybytes -b 区块hex字节数据 -s 区块签名 -p 区块生成者公钥 - -示例: -``` -asch-cli getfullblockbyheight 4330 -{ - "id": "61e5c7c17a365e079d536dcf7d23acca30b927434ca474df8ce28547e3abbdc4", - "version": 0, - "timestamp": 40458800, - "height": 4330, - "previousBlock": "ddc0bb392da3b1d22ac4e2c50d1a30a7adabe35e221fc0aeb80e3c6aaa509f68", - "numberOfTransactions": 1, - "totalAmount": 0, - "totalFee": 10000000, - "reward": 350000000, - "payloadLength": 121, - "payloadHash": "a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf", - "generatorPublicKey": "0ae2e3bcd8c959bccc34445a9473eab1bece60300f3aa00d89612923470dee75", // 区块生成者公钥 - "generatorId": "4354832300657989346", - "blockSignature": "6b09f19c21574c065015c026eaba049c25827b7008db071f7ac59e4f50538bbd70301dcf2cd9d3bada77e7a4279740fddb55ec72cce7de886517d74bdc1a0d0b", // 区块签名 - "totalForged": 360000000, - "transactions": [ - { - "id": "a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf", - "height": 4330, - "blockId": "61e5c7c17a365e079d536dcf7d23acca30b927434ca474df8ce28547e3abbdc4", - "type": 100, - "timestamp": 40458794, - "senderPublicKey": "2856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec4", - "requesterPublicKey": "", - "senderId": "ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M", - "recipientId": "", - "amount": 0, - "fee": 10000000, - "signature": "efd9a349eb2bc0a022461401c312001a5cd9f4f4f2c1e554e5bda465e19d1f0da7b229b68fbcdda81d85e34c3cd331e968f27cc398908e7acd527d27ae7e230a", - "signSignature": "", - "signatures": null, - "args": [ - "4340" - ], - "message": "", - "asset": {} - } - ] -} - -asch-cli getblockbytes -f blockfile // 生成区块hex数据 -00000000305a69026464633062623339326461336231643232616334653263353064316133306137616461626533356532323166633061656238306533633661616135303966363801000000000000000000000080969800000000008093dc140000000079000000a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf0ae2e3bcd8c959bccc34445a9473eab1bece60300f3aa00d89612923470dee75 - -asch-cli verifybytes -b 00000000305a69026464633062623339326461336231643232616334653263353064316133306137616461626533356532323166633061656238306533633661616135303966363801000000000000000000000080969800000000008093dc140000000079000000a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf0ae2e3bcd8c959bccc34445a9473eab1bece60300f3aa00d89612923470dee75 -s 6b09f19c21574c065015c026eaba049c25827b7008db071f7ac59e4f50538bbd70301dcf2cd9d3bada77e7a4279740fddb55ec72cce7de886517d74bdc1a0d0b -p 0ae2e3bcd8c959bccc34445a9473eab1bece60300f3aa00d89612923470dee75 -// 对hex进行签名验证 -true // 结果为true - -// 将上面的hex数据略做改动则验证不会被通过 -asch-cli verifybytes -b 10000000305a69026464633062623339326461336231643232616334653263353064316133306137616461626533356532323166633061656238306533633661616135303966363801000000000000000000000080969800000000008093dc140000000079000000a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf0ae2e3bcd8c959bccc34445a9473eab1bece60300f3aa00d89612923470dee75 -s 6b09f19c21574c065015c026eaba049c25827b7008db071f7ac59e4f50538bbd70301dcf2cd9d3bada77e7a4279740fddb55ec72cce7de886517d74bdc1a0d0b -p 0ae2e3bcd8c959bccc34445a9473eab1bece60300f3aa00d89612923470dee75 -false // 将hex首位改成1则验证不通过 -``` - -### 4.5 交易transaction -#### 4.5.1 根据公钥查看未确认的交易 -命令值: getunconfirmedtransactions [options] - -返回值: 列表,包含所有未确认的交易详情 - -使用方法:asch-cli getunconfirmedtransactions -k "发送者公钥" -a 接收者地址 - -示例: - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getunconfirmedtransactions -k "d39d6f26869067473d685da742339d1a9117257fe14b3cc7261e3f2ed5a339e3" -[ - { - "type": 0, - "timestamp": 4385190, - "senderPublicKey": "d39d6f26869067473d685da742339d1a9117257fe14b3cc7261e3f2ed5a339e3", - "signature": "98d65df3109802c707eeed706e90a907f337bddab58cb4c1fbe6ec2179aa1c85ec2903cc0cf44bf0092926829aa5a0a6ec99458f65b6ebd11f0988772e58740e", - "recipientId": "16723473400748954103", - "senderId": "15745540293890213312", - "amount": 10000000000, - "fee": 10000000, - "signatures": [], - "id": "17192581936339156329", - "height": 0, - "asset": {} - } -] -``` - -#### 4.5.2 查看(分析)全网交易信息 -命令值: gettransactions [options] - -返回值: 列表,包含所有符合查询条件的交易详情 - -使用方法:asch-cli gettransactions -b 区块id -o 偏移量数字 -l 限制个数数字 #其他参数请参考sch-cli gettransactions -h查看帮助信息 - -示例: - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 gettransactions -o 1 -l 2 #查看全网前2个交易 -[ - { - "id": "10169086766604015960", - "height": "1", - "blockId": "1425942128040906871", - "type": 2, - "timestamp": 0, - "senderPublicKey": "991e0dda00d2c33ce68dd99471de8ebea7b58711f22a2e55236b8864c6d24c84", - "senderId": "3331250159865474723", - "recipientId": "", - "amount": 0, - "fee": 0, - "signature": "60bf38e7a3515aeaa2cac491f7737c94087f448a862099408b90c2cf96d3fe4f709e22e6471dd4e37aca111d8573beeb7b6cff4ef451633d9aaf74ab97ce8d02", - "signSignature": "", - "signatures": null, - "confirmations": "105988", - "asset": {} - }, - { - "id": "10375311635154792515", - "height": "1", - "blockId": "1425942128040906871", - "type": 2, - "timestamp": 0, - "senderPublicKey": "1674ae566c633cde3e01db8f04a02ea087081a270de2dd53e0e0b97c029106fb", - "senderId": "9948352853509008057", - "recipientId": "", - "amount": 0, - "fee": 0, - "signature": "f09c1693cc26c4028c642cb1711cf71c2dee090a50904d1590c74d865b2f5f3ba720ed792704f5379ec9c4a20b018c5e95f325ea179236777a28cddffe8c580d", - "signSignature": "", - "signatures": null, - "confirmations": "105988", - "asset": {} - } -] -``` - -#### 4.5.3 根据交易id查看交易详情 -命令值: gettransaction [id] - -返回值: json字符串,包含交易id、区块高度、区块id、时间戳、发送者公钥、接收者地址、金额、费用、签名、确认数、资产等信息 - -使用方法:asch-cli gettransaction 交易id - -示例: - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 gettransaction 17192581936339156329 -{ - "id": "17192581936339156329", - "height": "105951", - "blockId": "15051364118100195665", - "type": 0, - "timestamp": 4385190, - "senderPublicKey": "d39d6f26869067473d685da742339d1a9117257fe14b3cc7261e3f2ed5a339e3", - "senderId": "15745540293890213312", - "recipientId": "16723473400748954103", - "amount": 10000000000, - "fee": 10000000, - "signature": "98d65df3109802c707eeed706e90a907f337bddab58cb4c1fbe6ec2179aa1c85ec2903cc0cf44bf0092926829aa5a0a6ec99458f65b6ebd11f0988772e58740e", - "signSignature": "", - "signatures": null, - "confirmations": "17", - "asset": {} -} -``` - -#### 4.5.4 转账 -命令值: sendmoney [选项] - -返回值: 结果状态值,true或者报错信息 - -使用方法:asch-cli -e "发送者密码" -t 接收者地址 -a 转账金额 [-s "二级密码"] - -示例: - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 sendmoney -e "motion group blossom coral upper warrior pattern fragile sister misery palm admin" -t 16723473400748954103 -a 100 -true -``` - - -#### 4.5.5 设置二级密码 -命令值: setsecondsecret [options] - -返回值: 结果状态值,true或者报错信息 - -使用方法:asch-cli setsecondsecret -e "密码" -s "二级密码" - -示例: - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 setsecondsecret -e "fault still attack alley expand music basket purse later educate follow ride" -s "ce shi er ji mi ma" -true -``` - -#### 4.5.6 验证交易文件bytes -命令值: gettransactionbytes [-f transaction_file] -返回值: 交易bytes,hex格式数据 -使用方法:asch-cli gettransactionbytes -f 交易数据文件 - -示例: -``` -asch-cli gettransaction a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf > transactionfile -cat transactionfile -{ - "id": "a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf", - "height": "4330", - "blockId": "61e5c7c17a365e079d536dcf7d23acca30b927434ca474df8ce28547e3abbdc4", - "type": 100, - "timestamp": 40458794, - "senderPublicKey": "2856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec4", - "senderId": "ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M", - "recipientId": "", - "amount": 0, - "fee": 10000000, - "signature": "efd9a349eb2bc0a022461401c312001a5cd9f4f4f2c1e554e5bda465e19d1f0da7b229b68fbcdda81d85e34c3cd331e968f27cc398908e7acd527d27ae7e230a", - "signSignature": "", - "signatures": null, - "confirmations": "413", - "args": [ - "4340" - ], - "message": "", - "asset": {} -} - -asch-cli gettransactionbytes -f transactionfile -642a5a69022856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec40000000000000000000000000000000034333430 -``` - -#### 4.5.7 验证交易文件id -命令值: gettransactionid [-f transaction_file] -返回值: 交易id - -使用方法:asch-cli gettransactionid -f 交易数据文件 - -示例: -``` -asch-cli gettransaction a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf > transactionfile - -asch-cli gettransactionid -f transactionfile -a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf -``` - -#### 4.4.8 验证交易签名是否通过 -命令值: verifybytes [options] -返回值: true or false -使用方法:asch-cli verifybytes -b 交易hex字节数据 -s 交易签名 -p 发送者公钥 - -示例: -``` -asch-cli gettransaction a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf > transactionfile -cat transactionfile -{ - "id": "a533d303f90e3ca9e685c2bd7088b93ae2ff721eafbea61027b7e353bfc2babf", - "height": "4330", - "blockId": "61e5c7c17a365e079d536dcf7d23acca30b927434ca474df8ce28547e3abbdc4", - "type": 100, - "timestamp": 40458794, - "senderPublicKey": "2856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec4", // 发送者公钥 - "senderId": "ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M", - "recipientId": "", - "amount": 0, - "fee": 10000000, - "signature": "efd9a349eb2bc0a022461401c312001a5cd9f4f4f2c1e554e5bda465e19d1f0da7b229b68fbcdda81d85e34c3cd331e968f27cc398908e7acd527d27ae7e230a", // 交易签名 - "signSignature": "", - "signatures": null, - "confirmations": "413", - "args": [ - "4340" - ], - "message": "", - "asset": {} -} - -asch-cli gettransactionbytes -f transactionfile // hex格式交易数据 -642a5a69022856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec40000000000000000000000000000000034333430 - -asch-cli verifybytes -b 642a5a69022856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec40000000000000000000000000000000034333430 -s efd9a349eb2bc0a022461401c312001a5cd9f4f4f2c1e554e5bda465e19d1f0da7b229b68fbcdda81d85e34c3cd331e968f27cc398908e7acd527d27ae7e230a -p 2856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec4 -// 对hex交易数据进行签名验证 -true // 结果为true - -// 对hex交易数据略作修改则签名验证不会通过 -asch-cli verifybytes -b 142a5a69022856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec40000000000000000000000000000000034333430 -s efd9a349eb2bc0a022461401c312001a5cd9f4f4f2c1e554e5bda465e19d1f0da7b229b68fbcdda81d85e34c3cd331e968f27cc398908e7acd527d27ae7e230a -p 2856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec4 -false // 将hex数据首位修改为1 - -``` - -### 4.6 侧链dapp -#### 4.6.1 注册dapp -命令值: registerdapp [options] - -返回值: 生成的dapp id - -使用方法:asch-cli registerdapp -e "密码" -s "二级密码" -f dapp元信息文件 - -示例: -``` -root@asch:~$ asch-cli registerdapp -f dapp.json -e "found knife gather faith wrestle private various fame cover response security predict" -d352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1 -``` - -#### 4.6.2 dapp充值 -命令值: deposit [options] - -返回值: 充值交易id - -使用方法: asch-cli deposit -e "密码" -s "二级密码" -d dappid -c 待充值资产名称 -a 充值数量 - -示例: -``` -dappid=d352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1 -password="elite brush pave enable history risk ankle shrimp debate witness ski trend" - -asch-cli -H 45.32.22.78 -P 4096 deposit -e "$password" -d $dappid -c "CCTime.XCT" -a "100000000" // 给dapp充值 1 CCTime.XCT -e5684046c87bef58e32ac64ea01a97e8323e6fe695e2dc186ca7ee6a55a9dbf5 -``` - -#### 4.6.3 智能合约的增删 -命令值: contract [options] - -返回值: - -使用方法:asch-cli contract -a(创建合约);asch-cli contract -d(删除合约) - -示例: -``` - -``` - -#### 4.6.4 dapp交易 -命令值: dapptransaction [options] - -返回值: dapp交易id - -使用方法: asch-cli dapptransaction -e "密码" -d dappid -t 智能合约编号 -a 数据字符串参数 -f 手续费(暂时是固定的10000000) - -示例: -``` -dappid=d352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1 -password="elite brush pave enable history risk ankle shrimp debate witness ski trend" - -asch-cli -H 45.32.22.78 -P 4096 dapptransaction -e "$password" -d $dappid -t 2 -a '["CCTime.XCT","100000000"]' -f 10000000 // 从dapp里面提现 1 CCTime.XCT -24a0b6b08f38882bac2791255e71437c5de4c37b619f5086a0bf32484cd8cf5b - -asch-cli -H 45.32.22.78 -P 4096 dapptransaction -e "$password" -d $dappid -t 3 -a '["CCTime.XCT","100000000","ADimyhJa99XFzVrbnTYsCqPB4TKQNdjCWw"]' -f 10000000 // 给ADimyhJa99XFzVrbnTYsCqPB4TKQNdjCWw在dapp内部转账1 CCTime.XCT -4a33e538f54b418bc89ac4484f954e51a749a94004aaf15939b4148991fac21c - -asch-cli -H 45.32.22.78 -P 4096 dapptransaction -e "$password" -d $dappid -t 4 -a '["zhenxi"]' -f 10000000 // 给该账户设置昵称“zhenxi” -1234b6b08f38882bac2791255e71437c5de4c37b619f5086a0bf32484cd8cf5b -``` - -#### 4.6.5 dapp创建安装相关 -命令值: dapps [options] -返回值: -使用方法:asch-cli dapps -a -示例 -``` - -``` - diff --git a/docs/asch_cli_usage_de.md b/docs/asch_cli_usage_de.md deleted file mode 100644 index 9a6cf8d..0000000 --- a/docs/asch_cli_usage_de.md +++ /dev/null @@ -1,906 +0,0 @@ -# Asch-CLI Dokumentation ---- -Inhaltsverzeichnis -================= - -- [Asch-CLI Dokumentation](#asch-cli-dokumentation) - - [0 Asch-CLI Übersicht](#0-asch-cli-%C3%9Cbersicht) - - [1 Asch-CLI Installation](#1-asch-cli-installation) - - [2 Asch-CLI Zusammenfassung](#2-asch-cli-zusammenfassung) - - [3 Asch-CLI Parameter](#3-asch-cli-parameter) - - [3.1 Zeige die Hilfsinformationen](#31-zeige-die-hilfsinformationen) - - [3.2 Zeige die Version der Asch-CLI](#32-zeige-die-version-der-asch-cli) - - [3.3 Spezifiziere eine IP-Adresse oder einen Hostnamen für den Asch-Zielserver](#33-spezifiziere-eine-ip-adresse-oder-einen-hostnamen-f%C3%BCr-den-asch-zielserver) - - [3.4 Spezifiziere eine Portnummer auf dem Asch-Zielserver](#34-spezifiziere-eine-portnummer-auf-dem-asch-zielserver) - - [3.5 Verwende die Haupt-Blockchain](#35-verwende-die-haupt-blockchain) - - [4 Asch-CLI unterstützte Parameter](#4-asch-cli-unterst%C3%BCtzte-parameter) - - [4.1 Zeige die Höhe der Blockchain](#41-zeige-die-h%C3%B6he-der-blockchain) - - [4.2 Zeige den Status der Blockchain](#42-zeige-den-status-der-blockchain) - - [4.3 Zeige Kontoinformationen mittels Passwort](#43-zeige-kontoinformationen-mittels-passwort) - - [4.4 Zeige Kontoinformationen anhand eines öffentlichen Schlüssels](#44-zeige-kontoinformationen-anhand-eines-%C3%B6ffentlichen-schl%C3%BCssels) - - [4.5 Zeige ein Kontosaldo anhand einer Kontoadresse](#45-zeige-ein-kontosaldo-anhand-einer-kontoadresse) - - [4.6 Zeige Kontoinformationen anhand einer Kontoadresse](#46-zeige-kontoinformationen-anhand-einer-kontoadresse) - - [4.7 Zeige alle Stimmabgaben für Delegate anhand einer öffentlichen Adresse](#47-zeige-alle-stimmabgaben-f%C3%BCr-delegate-anhand-einer-%C3%B6ffentlichen-adresse) - - [4.8 Zeige die Anzahl aller Delegate](#48-zeige-die-anzahl-aller-delegate) - - [4.9 Zeige Informationen zu Delegaten und sortiere nach bestimmten Feldern](#49-zeige-informationen-zu-delegaten-und-sortiere-nach-bestimmten-feldern) - - [4.10 Zeige die Knoten die für ein Delegat gestimmt haben, anhand des öffentlichen Schlüssels des Delegats](#410-zeige-die-knoten-die-f%C3%BCr-ein-delegat-gestimmt-haben-anhand-des-%C3%B6ffentlichen-schl%C3%BCssels-des-delegats) - - [4.11 Zeige die Informationen zu einem Delegat anhand seines öffentlichen Schlüssels an](#411-zeige-die-informationen-zu-einem-delegat-anhand-seines-%C3%B6ffentlichen-schl%C3%BCssels-an) - - [4.12 Zeige die Informationen zu einem Delegat anhand seines Namens](#412-zeige-die-informationen-zu-einem-delegat-anhand-seines-namens) - - [4.13 Zeige die Information zu einem oder mehreren Blöcken im Netzwerk an](#413-zeige-die-information-zu-einem-oder-mehreren-bl%C3%B6cken-im-netzwerk-an) - - [4.14 Überprüfe Blockinformationen mit einer BlockID](#414-%C3%9Cberpr%C3%BCfe-blockinformationen-mit-einer-blockid) - - [4.15 Zeige Informationen zu einem Block anhand der Blockhöhe](#415-zeige-informationen-zu-einem-block-anhand-der-blockh%C3%B6he) - - [4.16 Zeige den Netzwerkstatus / den Status der Peers an](#416-zeige-den-netzwerkstatus-den-status-der-peers-an) - - [4.17 Zeige unbestätigte Transaktionen anhand einer öffentlichen Adresse](#417-zeige-unbest%C3%A4tigte-transaktionen-anhand-einer-%C3%B6ffentlichen-adresse) - - [4.18 Zeige / analysiere Transaktionsinformationen für das gesamte Netzwerk](#418-zeige-analysiere-transaktionsinformationen-f%C3%BCr-das-gesamte-netzwerk) - - [4.19 Zeige Transaktionsdetails anhand einer Transaktions-ID](#419-zeige-transaktionsdetails-anhand-einer-transaktions-id) - - [4.20 Geld überweisen](#420-geld-%C3%BCberweisen) - - [4.21 Ein Delegat registrieren](#421-ein-delegat-registrieren) - - [4.22 Für ein Delegat abstimmen](#422-f%C3%BCr-ein-delegat-abstimmen) - - [4.23 Die Stimmabgabe für ein Delegat zurückziehen](#423-die-stimmabgabe-f%C3%BCr-ein-delegat-zur%C3%BCckziehen) - - [4.24 Ein zweites Passwort setzen](#424-ein-zweites-passwort-setzen) - - [4.25 Eine Dapp registrieren (dezentrale Applikation)](#425-eine-dapp-registrieren-dezentrale-applikation) - - [4.26 Verträge](#426-vertr%C3%A4ge) - - [4.27 Verschlüsselung](#427-verschl%C3%BCsselung) - - [4.28 Dapp Befehle](#428-dapp-befehle) - - [4.29 Erstelle den ersten Block der Blockchain (Genesisblock)](#429-erstelle-den-ersten-block-der-blockchain-genesisblock) - - [4.30 Überprüfe den Status aller Knoten / Peers im Netzwerk](#430-%C3%9Cberpr%C3%BCfe-den-status-aller-knoten-peers-im-netzwerk) - - [4.31 Überprüfe den Status aller Delegate](#431-%C3%9Cberpr%C3%BCfe-den-status-aller-delegate) - - [4.32 Zeige das Land aus dem ursprünglich die IP-Adresse des Knotens registriert wurde](#432-zeige-das-land-aus-dem-urspr%C3%BCnglich-die-ip-adresse-des-knotens-registriert-wurde) - -Inhaltsverzeichnis mittels [markdown-toc](https://github.com/AlanWalk/markdown-toc) erstellt ---- - -## 0 Asch-CLI Übersicht -Aus dem [Asch Whitepaper](/asch_whitepaper_de.md) -> Asch-CLI ist eine Asch Kommandozeile (CLI steht für command-line interface). Mit Hilfe der Asch-CLI können Entwickler ohne große Mühe eine Sidechain erstellen und auf dieser entwickeln. Das System bietet eine Vielzahl an APIs welche das Erstellen von intelligenten Verträgen (Smart Contracts) ermöglicht. Diese APIs umfassen die Möglichkeit für Konsens, Zufallszahlen, Datenbank-Zugriff, Kryptographie und vieles mehr. - -## 1 Asch-CLI Installation -- Installiere den node Paket-Manager **npm** `sudo apt-get install npm` - -- Installiere die Asch-CLI `npm install -g asch-cli` Hinweis: Wenn dein Standort China ist, versuche den folgenden Parameter um die Installation zu beschleunigen. `--registry=http://registry.npm.taobao.org` - - -## 2 Asch-CLI Zusammenfassung -`asch-cli [option] [command]` - -## 3 Asch-CLI Parameter -### 3.1 Zeige die Hilfsinformationen -**Parameter:** -h, --help -**Rückgabe:** Eine Übersicht über alle Parameter und Subparameter -**Verwendung:** - - ```asch-cli -h``` #zeige Asch-CLI Hilfsinformationen - - ```asch-cli [commands] -h``` #zeige Hilfsinformationen zu einem bestimmten Parameter - -**Beispiel:** -``` -root@asch:~# asch-cli -h #zeige die Hilfe an - Usage: asch-cli [options] [command] - Commands: - - getheight get block height - getblockstatus get block status - openaccount [secret] open your account and get the infomation by secret - openaccountbypublickey [publickey] open your account and get the infomation by publickey - getbalance [address] get balance by address - getaccount [address] get account by address - getvoteddelegates [options] [address] get delegates voted by address - getdelegatescount get delegates count - getdelegates [options] get delegates - getvoters [publicKey] get voters of a delegate by public key - getdelegatebypublickey [publicKey] get delegate by public key - getdelegatebyusername [username] get delegate by username - getblocks [options] get blocks - getblockbyid [id] get block by id - getblockbyheight [height] get block by height - getpeers [options] get peers - getunconfirmedtransactions [options] get unconfirmed transactions - gettransactions [options] get transactions - gettransaction [id] get transactions - sendmoney [options] send money to some address - registerdelegate [options] register delegate - upvote [options] vote for delegates - downvote [options] cancel vote for delegates - setsecondsecret [options] set second secret - registerdapp [options] register a dapp - contract [options] contract operations - crypto [options] crypto operations - dapps [options] manage your dapps - creategenesis [options] create genesis block - peerstat analyze block height of all peers - delegatestat analyze delegates status - ipstat analyze peer ip info - - Options: - - -h, --help output usage information - -V, --version output the version number - -H, --host Specify the hostname or ip of the node, default: 127.0.0.1 - -P, --port Specify the port of the node, default: 4096 - -M, --main Specify the mainnet, default: false - -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getvoteddelegates -h #print Asch-CLI command help information - Usage: getvoteddelegates [options] [address] - get delegates voted by address - Options: - - -h, --help output usage information - -o, --offset - -l, --limit -``` - -### 3.2 Zeige die Version der Asch-CLI -**Parameter:** -V, --version -**Rückgabe:** Die verwendete Version -**Verwendung:** `asch-cli -V` - -**Beispiel:** - -``` -root@asch:~# asch-cli -V -1.0.0 -``` - -### 3.3 Spezifiziere eine IP-Adresse oder einen Hostnamen für den Asch-Zielserver -**Parameter:** -H, --host <host> [command] *(Default: 127.0.0.1)* - -**Rückgabe:** keine - -**Verwendung:** `asch-cli -H 45.32.248.33 [command]` - -**Beispiel:** -``` -root@asch:~# asch-cli -H 45.32.248.33 getheight #zeige die Blockhöhe des Asch-Servers auf 45.32.248.33 -101236 -``` - -### 3.4 Spezifiziere eine Portnummer auf dem Asch-Zielserver -**Parameter:** -P, --port <port> [command] *(Default: 4096)* - -**Rückgabe:** keine - -**Verwendung:** ```asch-cli -P 4096``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getheight -102313 -``` - -### 3.5 Verwende die Haupt-Blockchain -**Parameter:** -M, --main *(Default: testchain)* - -**Rückgabe:** keine - -**Verwendung:** ```asch-cli -M``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -M -H *.*.*.105 -P 8192 getheight #zeige die Blockhöhe der Asch-Hauptblockchain -``` - -## 4 Asch-CLI unterstützte Parameter -### 4.1 Zeige die Höhe der Blockchain -**Befehl:** getheight - -**Rückgabe:** Die Höhe der Blockchain (die Anzahl der Blöcke seit dem Ursprungsblock) - -**Verwendung:** ```asch-cli getheight``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getheight -105387 -``` - -### 4.2 Zeige den Status der Blockchain -**Befehl:** getblockstatus - -**Rückgabe:** Ein JSON formattierter String der folgende Informationen beinhaltet: Blockchain-Höhe, die Transaktionsgebühr, den Milestone, die Belohnung für jedes Delegat und das gesamte Volumen - -**Verwendung:** ```asch-cli getblockstatus``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getblockstatus -{ - "success": true, - "height": 105392, - "fee": 10000000, - "milestone": 0, - "reward": 350000000, - "supply": 10036887200000000 -} -``` - -### 4.3 Zeige Kontoinformationen mittels Passwort -**Befehl:** openaccount [secret] - -**Rückgabe:** Ein JSON-String mit folgenden Konto-Informationen: Adresse, Saldo, öffentlicher Schlüssel, zweiter öffentlicher Schlüssel etc. - -**Verwendung:** ```asch-cli openaccount "password"``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 openaccount "fault still attack alley expand music basket purse later educate follow ride" -{ - "address": "16723473400748954103", - "unconfirmedBalance": 20000000000, - "balance": 20000000000, - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9", - "unconfirmedSignature": false, - "secondSignature": false, - "secondPublicKey": "", - "multisignatures": [], - "u_multisignatures": [] -} -``` - -### 4.4 Zeige Kontoinformationen anhand eines öffentlichen Schlüssels -**Befehl:** openaccountbypublickey [publickey] - -**Rückgabe:** Ein JSON-String mit folgenden Informationen: Adresse, Saldo, öffentlicher Schlüssel, zweiter öffentlicher Schlüssel etc. - -**Verwendung:** ```asch-cli openaccountbypublickey "public key"``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 openaccountbypublickey "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9" -{ - "address": "16723473400748954103", - "unconfirmedBalance": 20000000000, - "balance": 20000000000, - "unconfirmedSignature": false, - "secondSignature": false, - "secondPublicKey": "", - "multisignatures": [], - "u_multisignatures": [] -} -``` - -### 4.5 Zeige ein Kontosaldo anhand einer Kontoadresse -**Befehl:** getbalance [address] - -**Rückgabe:** Eine Ganzzahl welche durch das Dividieren von 100000000 zustande kommt. - -**Verwendung:** ```asch-cli getbalance [account address]``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getbalance 16723473400748954103 -20000000000 -``` - -### 4.6 Zeige Kontoinformationen anhand einer Kontoadresse -**Befehl:** getaccount [address] - -**Rückgabe:** Ein JSON-String mit folgenden Informationen: Addresse, Saldo, öffentlicher Schlüssel, zweiter öffentlicher Schlüssel etc. - -**Verwendung:** ```asch-cli getaccount [account address]``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getaccount 16723473400748954103 -{ - "address": "16723473400748954103", - "unconfirmedBalance": 20000000000, - "balance": 20000000000, - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9", - "unconfirmedSignature": false, - "secondSignature": false, - "secondPublicKey": "", - "multisignatures": [], - "u_multisignatures": [] -} -``` - -### 4.7 Zeige alle Stimmabgaben für Delegate anhand einer öffentlichen Adresse -**Befehl:** getvoteddelegates [options] [address] - -**Rückgabe:** Eine Liste von allen Stimmabgaben die eine Adresse abgegeben hat - -**Verwendung:** ```asch-cli getvoteddelegates [account address] -o offset -l [an integer that indicates the maximum delegates that can be printed]``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getvoteddelegates 15745540293890213312 -o 1 -l 2 -{ success: true, - delegates: - [ { username: 'wgl_002', - address: '14636456069025293113', - publicKey: 'ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7', - vote: 8902736443247261, - producedblocks: 1041, - missedblocks: 6, - rate: 1, - approval: '88.70', - productivity: '99.42' }, - { username: 'wgl_003', - address: '9961157415582672274', - publicKey: 'c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2', - vote: 8902736443247261, - producedblocks: 1043, - missedblocks: 8, - rate: 2, - approval: '88.70', - productivity: '99.23' }] -``` - -### 4.8 Zeige die Anzahl aller Delegate -**Befehl:** getdelegatescount - -**Rückgabe:** Eine Ganzzahl mit der Anzahl aller Delegate im System - -**Verwendung:** ```asch-cli getdelegatescount``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getdelegatescount -232 -``` - -### 4.9 Zeige Informationen zu Delegaten und sortiere nach bestimmten Feldern -**Befehl:** getdelegates [options] - -**Rückgabe:** Eine Liste mit Informationen zu Delegaten - -**Verwendung:** ```asch-cli getdelegates -o [offset number] -l [an integer that indicates the maximum delegates that can be printed] -s rate:asc``` - -**HINWEIS:** ```rate:asc``` bedeutet, dass man aufsteigend (asc=aufsteigend, desc=absteigend) nach Stimmabgaben sortieren kann. Um alle Sortieroptionen zu sehen tippe `asch-cli getdelegates -h` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getdelegates -o 1 -l 1 -s rate:asc -[ - { - "username": "wgl_003", - "address": "9961157415582672274", - "publicKey": "c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2", - "vote": 9901544836887660, - "producedblocks": 1044, - "missedblocks": 8, - "fees": 12150495022, - "rewards": 161000000000, - "rate": 2, - "approval": 98.65, - "productivity": 99.24, - "forged": "173150495022" - } -] -``` - -### 4.10 Zeige die Knoten die für ein Delegat gestimmt haben, anhand des öffentlichen Schlüssels des Delegats -**Befehl:** getvoters [publicKey] - -**Rückgabe:** Eine Liste mit allen Wählern - -**Verwendung:** ```asch-cli getvoters "delegate's public key"``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getvoters "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7" -[ - { - "address": "2918354313445278349", - "publicKey": "4fde4c49f1297d5d3a24b1494204543c4281aff17917ff7ff8ff32da3b4b222f", - "balance": 1215522376203, - "weight": 0.012110398031994424 - }, - { - "address": "1523444724068322527", - "publicKey": "8a6a61c28dc47541aadf1eecec2175c8f768f2331eea3472b1593bf1aa4e1fb4", - "balance": 2109297623765, - "weight": 0.02101519008767971 - }] -``` - -### 4.11 Zeige die Informationen zu einem Delegat anhand seines öffentlichen Schlüssels an -**Befehl:** getdelegatebypublickey [publicKey] - -**Rückgabe:** Ein JSON-String mit folgenden Informationen zu einem Delegat: Name, Adresse, Wahlstimmen, produzierter Blöcke, forging reward etc. - -**Verwendung:** asch-cli getdelegatebypublickey "delegate's public key" - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getdelegatebypublickey "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7" -{ - "username": "wgl_002", - "address": "14636456069025293113", - "publicKey": "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7", - "vote": 9901546586887660, - "producedblocks": 1042, - "missedblocks": 6, - "fees": 12383762523, - "rewards": 161700000000, - "rate": 1, - "approval": 98.65, - "productivity": 99.43, - "forged": "174083762523" -} -``` -### 4.12 Zeige die Informationen zu einem Delegat anhand seines Namens -**Befehl:** getdelegatebyusername [username] - -**Rückgabe:** Ein JSON-String mit allen Details zu einem Delegat - -**Verwendung:** ```asch-cli getdelegatebyusername "delegate's name"``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getdelegatebyusername "wgl_002" -{ - "username": "wgl_002", - "address": "14636456069025293113", - "publicKey": "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7", - "vote": 9901546586887660, - "producedblocks": 1042, - "missedblocks": 6, - "fees": 12383762523, - "rewards": 161700000000, - "rate": 1, - "approval": 98.65, - "productivity": 99.43, - "forged": "174083762523" -} -``` - -### 4.13 Zeige die Information zu einem oder mehreren Blöcken im Netzwerk an -**Befehl:** getblocks [options] - -**Rückgabe:** Ein JSON-String mit den gewünschten Blöcken - -**Verwendung:** ```asch-cli getblocks -o [offset number] -l [an integer that indicates the maximum return data] -r [reward amount] -f [fee] -a [total amount] -g [public key that generates blocks] -s [sort rule]``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getblocks -o 1 -l 1 -r 350000000 -{ - "success": true, - "blocks": [ - { - "id": "5533619110613125681", - "version": 0, - "timestamp": 3914630, - "height": 60481, - "previousBlock": "11174102253820291084", - "numberOfTransactions": 0, - "totalAmount": 0, - "totalFee": 0, - "reward": 350000000, - "payloadLength": 0, - "payloadHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "generatorPublicKey": "68b28341605a24f6684df81882df1b13f421ec1cbba7d9aaa68f6c079705b258", - "generatorId": "10651956562526682705", - "blockSignature": "77115fdaab3215039bcf2bf8b3a461b3b7cafca7adae07e271a1a953ca6531a9e93f985bbec8544d596a568595661f1da742e20797b827d5b20aa75e8d80cc0b", - "confirmations": "45349", - "totalForged": 350000000 - } - ], - "count": 45350 -} -``` -### 4.14 Überprüfe Blockinformationen mit einer BlockID -**Befehl:** getblockbyid [id] - -**Rückgabe:** Ein JSON-String mit folgenden Feldern: BlockID, Blockhöhe, BlockID des vorhergehenden Blocks, Anzahl der Transaktionen, Gesamtbetrag, Transaktionsgebühr, Belohnungen, Hash, der öffentliche Schlüssel des Blockgenerators und dessen ID, Blocksignatur, Anzahl der Bestätigungen etc. - -**Verwendung:** ```asch-cli getblockbyid [block ID]``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getblockbyid 1425942128040906871 #zeige den Genesisblock an (erster Block in der Blockchain) -{ - "id": "1425942128040906871", - "version": 0, - "timestamp": 0, - "height": 1, - "previousBlock": "", - "numberOfTransactions": 103, - "totalAmount": 10000000000000000, - "totalFee": 0, - "reward": 0, - "payloadLength": 19417, - "payloadHash": "dd5cd3186d32145b01f8fd0bd23e3b3d72414b59b162d2e664e759db8fe60d46", - "generatorPublicKey": "2af8566f8555bafb25df5a50e2e22b91a8577ceabc05d47dbd921572d28330e8", - "generatorId": "1170992220085500484", - "blockSignature": "a8ed06bfbfd1b630b1628e97a5c7c9383337c4ce32825969fad830890e0af981312be635b775ff46eea4f739da043f668a70efd5a940429e39fe5063852f4a01", - "confirmations": "105901", - "totalForged": 0 -} -``` - -### 4.15 Zeige Informationen zu einem Block anhand der Blockhöhe -**Befehl:** getblockbyheight [height] - -**Rückgabe:** Ein JSON-String mit folgenden Feldern: BlockID, Blockhöhe, BlockID des vorhergehenden Blocks, Anzahl der Transaktionen, Gesamtbetrag, Transaktionsgebühren, Belohnungen, der öffentliche Schlüssel des Blockgenerators und dessen ID, Blocksignatur, Anzahl der Bestätigungen etc. - -**Verwendung:** ```asch-cli getblockbyheight [block height]``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getblockbyheight 1 -{ - "id": "1425942128040906871", - "version": 0, - "timestamp": 0, - "height": 1, - "previousBlock": "", - "numberOfTransactions": 103, - "totalAmount": 10000000000000000, - "totalFee": 0, - "reward": 0, - "payloadLength": 19417, - "payloadHash": "dd5cd3186d32145b01f8fd0bd23e3b3d72414b59b162d2e664e759db8fe60d46", - "generatorPublicKey": "2af8566f8555bafb25df5a50e2e22b91a8577ceabc05d47dbd921572d28330e8", - "generatorId": "1170992220085500484", - "blockSignature": "a8ed06bfbfd1b630b1628e97a5c7c9383337c4ce32825969fad830890e0af981312be635b775ff46eea4f739da043f668a70efd5a940429e39fe5063852f4a01", - "confirmations": "105922", - "totalForged": 0 -} -``` - -### 4.16 Zeige den Netzwerkstatus / den Status der Peers an -**Befehl:** getpeers [options] - -**Rückgabe:** Ein JSON-String mit folgenden Feldern: IP-Adresse des Peer-Computers, das verwendete Betriebssystem, die Asch-Version etc. - -**Verwendung:** ```asch-cli getpeers -o [offset] -l [an integer that indicates the maximum return data] -t [status value] -s [sort type] -v [version] -p [port number] --os [OS version]``` - -**HINWEIS:** Für weitere Informationen, tippe `asch-cli getpeers -h` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getpeers -o 1 -l 2 -[ - { - "ip": "45.32.62.184", - "port": 4096, - "state": 2, - "os": "linux3.13.0-87-generic", - "version": "1.0.0" - }, - { - "ip": "45.32.22.78", - "port": 4096, - "state": 2, - "os": "linux3.13.0-87-generic", - "version": "1.0.0" - } -] -``` - -### 4.17 Zeige unbestätigte Transaktionen anhand einer öffentlichen Adresse -**Befehl:** getunconfirmedtransactions [options] - -**Rückgabe:** Eine Liste mit sämtlichen Details zu allen noch unbestätigten Transaktionen - -**Verwendung:** ```asch-cli getunconfirmedtransactions -p "sender's public key" -a [recipient's address]``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getunconfirmedtransactions -k "d39d6f26869067473d685da742339d1a9117257fe14b3cc7261e3f2ed5a339e3" -[ - { - "type": 0, - "timestamp": 4385190, - "senderPublicKey": "d39d6f26869067473d685da742339d1a9117257fe14b3cc7261e3f2ed5a339e3", - "signature": "98d65df3109802c707eeed706e90a907f337bddab58cb4c1fbe6ec2179aa1c85ec2903cc0cf44bf0092926829aa5a0a6ec99458f65b6ebd11f0988772e58740e", - "recipientId": "16723473400748954103", - "senderId": "15745540293890213312", - "amount": 10000000000, - "fee": 10000000, - "signatures": [], - "id": "17192581936339156329", - "height": 0, - "asset": {} - } -] -``` - -### 4.18 Zeige / analysiere Transaktionsinformationen für das gesamte Netzwerk -**Befehl:** gettransactions [options] - -**Rückgabe:** Eine Liste mit allen Transaktionsdetails - -**Verwendung:** ```asch-cli gettransactions -b [block ID] -o [offset] -l [an integer that indicates the maximum return data]``` - -**HINWEIS:** Versuche `asch-cli gettransactions -h` um Informationen zu anderen Parameteroptionen anzuzeigen. - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 gettransactions -o 1 -l 2 #zeige die Information zu den ersten zwei Transaktionen in der Blockchain an -[ - { - "id": "10169086766604015960", - "height": "1", - "blockId": "1425942128040906871", - "type": 2, - "timestamp": 0, - "senderPublicKey": "991e0dda00d2c33ce68dd99471de8ebea7b58711f22a2e55236b8864c6d24c84", - "senderId": "3331250159865474723", - "recipientId": "", - "amount": 0, - "fee": 0, - "signature": "60bf38e7a3515aeaa2cac491f7737c94087f448a862099408b90c2cf96d3fe4f709e22e6471dd4e37aca111d8573beeb7b6cff4ef451633d9aaf74ab97ce8d02", - "signSignature": "", - "signatures": null, - "confirmations": "105988", - "asset": {} - }, - { - "id": "10375311635154792515", - "height": "1", - "blockId": "1425942128040906871", - "type": 2, - "timestamp": 0, - "senderPublicKey": "1674ae566c633cde3e01db8f04a02ea087081a270de2dd53e0e0b97c029106fb", - "senderId": "9948352853509008057", - "recipientId": "", - "amount": 0, - "fee": 0, - "signature": "f09c1693cc26c4028c642cb1711cf71c2dee090a50904d1590c74d865b2f5f3ba720ed792704f5379ec9c4a20b018c5e95f325ea179236777a28cddffe8c580d", - "signSignature": "", - "signatures": null, - "confirmations": "105988", - "asset": {} - } -] -``` - -### 4.19 Zeige Transaktionsdetails anhand einer Transaktions-ID -**Befehl:** gettransaction [id] - -**Rückgabe:** Ein JSON-String mit folgenden Feldern: Transaktions-ID, Blockhöhe, BlockID, Zeitstempel, Öffentliche Adresse des Versenders, Empfangsadresse, Gesamtbetrag, Signatur, Anzahl der Bestätigungen, Assets etc. - -**Verwendung:** ```asch-cli gettransaction [transactionID]``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 gettransaction 17192581936339156329 -{ - "id": "17192581936339156329", - "height": "105951", - "blockId": "15051364118100195665", - "type": 0, - "timestamp": 4385190, - "senderPublicKey": "d39d6f26869067473d685da742339d1a9117257fe14b3cc7261e3f2ed5a339e3", - "senderId": "15745540293890213312", - "recipientId": "16723473400748954103", - "amount": 10000000000, - "fee": 10000000, - "signature": "98d65df3109802c707eeed706e90a907f337bddab58cb4c1fbe6ec2179aa1c85ec2903cc0cf44bf0092926829aa5a0a6ec99458f65b6ebd11f0988772e58740e", - "signSignature": "", - "signatures": null, - "confirmations": "17", - "asset": {} -} -``` - -### 4.20 Geld überweisen -**Befehl:** sendmoney [option] - -**Rückgabe:** Bei erfolgreicher Ausführung wird "True" zurückgegeben, ansonsten kommt eine Fehlermeldung. - -**Verwendung:** ```asch-cli sendmoney -e "[sender's password]" -t [recipient's address] -a [transfer amount] -s "[second password]"``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 sendmoney -e "motion group blossom coral upper warrior pattern fragile sister misery palm admin" -t 16723473400748954103 -a 100 -true -``` - -### 4.21 Ein Delegat registrieren -**Befehl:** registerdelegate [options] - -**Rückgabe:** Bei erfolgreicher Ausführung wird "True" zurückgegeben, ansonsten kommt eine Fehlermeldung - -**Verwendung:** ```asch-cli registerdelegate -e "[password]" -s "[second password]" -u "[delegate's name]"``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 registerdelegate -e "fault still attack alley expand music basket purse later educate follow ride" -u "delegate_register" -true -``` - -### 4.22 Für ein Delegat abstimmen -**Befehl:** upvote [options] - -**Rückgabe:** Für ein Delegat abstimmen. Bei erfolgreicher Ausführung wird "True" zurückgegeben, ansonsten kommt eine Fehlermeldung - -**Verwendung:** ```asch-cli upvote -e "[password]" -s "[second password]" -p "delegate's public key"``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 upvote -e "fault still attack alley expand music basket purse later educate follow ride" -p "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9" -true -``` - -### 4.23 Die Stimmabgabe für ein Delegat zurückziehen -**Befehl:** downvote [options] - -**Rückgabe:** Die Stimmabgabe für ein Delegat zurückziehen. Bei einer erfolgrechen Ausführung wird "True" zurückgegeben, ansonsten kommt eine Fehlermeldung - -**Verwendung:** ```asch-cli downvote -e "[password]" -s "[second password]" -p "delegate's public key"``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 downvote -e "fault still attack alley expand music basket purse later educate follow ride" -p "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9" -true -``` - -### 4.24 Ein zweites Passwort setzen -**Befehl:** setsecondsecret [options] - -**Rückgabe:** Wenn erfolgreich ein zweites Passwort gesetz wurde kommt eine Bestätigung. Ansonsten kommt eine Fehlermeldung - -**Verwendung:** ```asch-cli setsecondsecret -e "[password]" -s "[second password]"``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 setsecondsecret -e "fault still attack alley expand music basket purse later educate follow ride" -s "ce shi er ji mi ma" -true -``` - -### 4.25 Eine Dapp registrieren (dezentrale Applikation) -**Befehl:** registerdapp [options] - -**Rückgabe:** keine - -**Verwendung:** ```asch-cli registerdapp -e "[password]" -s "[second password]" -f [Dapp meta file]``` - -**Beispiel:** - - - -### 4.26 Verträge -**Befehl:** contract [options] - -**Rückgabe:** keine - -**Verwendung:** - - ```asch-cli contract -a``` # einen Vertrag erstellen - - ```asch-cli contract -d``` # einen Vertrag löschen - -**Beispiel:** - - -### 4.27 Verschlüsselung -**Befehl:** crypto [option] - -**Rückgabe:** Eine Liste - -**Verwendung:** -- ```asch-cli -p``` # Erzeuge einen öffentlichen Schlüssel anhand eines Passworts -- ```asch-cli -g``` # Erstelle ein oder mehrere Konten - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 crypto -g -? Enter number of accounts to generate 1 -[ { address: '16723473400748954103', - secret: 'fault still attack alley expand music basket purse later educate follow ride', - publicKey: 'bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9' } ] -Done -``` - -### 4.28 Dapp Befehle -**Befehl:** dapps [options] - -**Rückgabe:** keine - -**Verwendung:** ```asch-cli dapps -a``` - -**Beispiel:** - -### 4.29 Erstelle den ersten Block der Blockchain (Genesisblock) -**Befehl:** creategenesis [options] - -**Rückgabe:** Dieser Befehl erzeugt eine Genesisblock-Datei (genesisBlock.json) und die zugehörige Logdatei (genGenesisBlock.log) im aktuellen Verzeichnis - -**Verwendung:** ```asch-cli creategenesis``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 creategenesis -root@asch:~# more genesisBlock.json -{ - "version": 0, - "totalAmount": 10000000000000000, - "totalFee": 0, - "reward": 0, - "payloadHash": "baebdb59d0c19a07c2440e22c0512b4efe9794565b352375195c9e7e8a3817b0", - "timestamp": 0, - "numberOfTransactions": 103, -... -} -``` - -### 4.30 Überprüfe den Status aller Knoten / Peers im Netzwerk -**Befehl:** peerstat - -**Rückgabe:** Informationen zu den einzelnen Peers wie: Die IP-Adresse, Port, Asch-Version, die Block-Höhe etc. - -**Verwendung:** ```asch-cli peerstat``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 peerstat -45.32.248.33:4096 1.0.0 106036 -45.32.62.184:4096 1.0.0 106036 -45.32.19.241:4096 1.0.0 106036 -``` - -### 4.31 Überprüfe den Status aller Delegate -**Befehl:** delegatestat - -**Rückgabe:** Eine Tabelle mit folgenden Informationen über alle Delegate: Name, Adresse, Zustimmung, Produktivität, Anzahl der generierten Blöcke, Blockhöhe, BlockID, Datum des zuletzt generierten Blocks, etc. - -**Verwendung:** ```asch-cli delegatestat``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 delegatestat -name address rate approval productivity produced height id time -nayimoliuguang 3331976396377269399 93 88.36% 98.39% 1037 105618 12962348710289833740 2016/08/17 21:07:20(1 hour ago) -jack 3705405381126069457 86 88.36% 99.41% 506 105628 5876778147855073736 2016/08/17 21:09:00(1 hour ago) -node_3 12796761013870716784 81 88.36% 80.51% 814 105784 4575518649204137595 2016/08/17 21:38:10(40 mins ago) -wgl_003 9961157415582672274 2 98.65% 99.24% 1047 105852 11175724889329116017 2016/08/17 21:49:40(28 mins ago) -xihulongjing 12676662200687508271 59 88.36% 76.92% 150 105853 15273855606472618453 2016/08/17 21:49:50(28 mins ago) -liangpeili 4514546945474752928 50 88.37% 99.68% 627 105855 3771943180359756069 2016/08/17 21:50:10(28 mins ago) -asch_tea1 8812460086240160222 4 98.58% 98.79% 1059 105857 14968719538781965695 2016/08/17 21:50:30(27 mins ago) -intmaster 7321911740133937168 97 88.36% 100% 1032 105871 6757656887343300317 2016/08/17 21:52:50(25 mins ago) -mode_6 9248745407080572308 8 88.48% 100% 1060 105873 3777454410915098884 2016/08/17 21:53:10(25 mins ago) -``` - -### 4.32 Zeige das Land aus dem ursprünglich die IP-Adresse des Knotens registriert wurde -**Befehl:** ipstat - -**Rückgabe:** Das ursprüngliche Land aus dem die IP-Adresse stammte - -**Verwendung:** ```asch-cli ipstat``` - -**Beispiel:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 ipstat -美国 US -美国 US -美国 US -日本 JP -中国 CN -中国 CN -中国 CN -中国 CN -中国 CN -中国 CN -``` diff --git a/docs/asch_cli_usage_en.md b/docs/asch_cli_usage_en.md deleted file mode 100644 index d48a6ff..0000000 --- a/docs/asch_cli_usage_en.md +++ /dev/null @@ -1,907 +0,0 @@ -# Asch-CLI User Guide ---- -Index -================= - - [Asch-CLI Instruction](#asch-cli-instruction) - - [0 Asch-CLI Overview](#0-asch-cli-overview) - - [1 Asch-CLI Installation](#1-asch-cli-installation) - - [2 Asch-CLI Synopsis](#2-asch-cli-synopsis) - - [3 Asch-CLI Option Description](#3-asch-cli-option-description) - - [3.1 Print help information](#31-print-help-information) - - [3.2 Print Asch-CLI version information](#32-print-asch-cli-version-information) - - [3.3 Appoint the host name or IP address of target Asch Server](#33-appoint-the-host-name-or-ip-address-of-target-asch-server) - - [3.4 Appoint the port number of target Asch server](#34-appoint-the-port-number-of-target-asch-server) - - [3.5 Appoint the main chain](#35-appoint-the-main-chain) - - [4 Asch-CLI supported commands](#4-asch-cli-supported-commands) - - [4.1 Check the blockchain height](#41-check-the-blockchain-height) - - [4.2 Check the blockchain status](#42-check-the-blockchain-status) - - [4.3 Check account information by password](#43-check-account-information-by-password) - - [4.4 Check account information by public key](#44-check-account-information-by-public-key) - - [4.5 Check account balance by account address](##45-check-account-balance-by-account-address) - - [4.6 Check account information by account address](#46-check-account-information-by-account-address) - - [4.7 Check delegates voted by the account address](#47-check-delegates-voted-by-the-account-address) - - [4.8 Check the whole number of delegates](#48-check-the-whole-number-of-delegates) - - [4.9 Check delegates information and sort out](#49-check-delegates-information-and-sort-out) - - [4.10 Check the voters of the delegate by his public key](#410-check-the-voters-of-the-delegate-by-his-public-key) - - [4.11 Check detail information of delegate by public key](#411-check-detail-information-of-delegate-by-public-key) - - [4.12 Check the detail information of delegate by the name](#412-check-the-detail-information-of-delegate-by-the-name) - - [4.13 Check/analyse block information in whole network](#413-checkanalyze-block-information-in-whole-network) - - [4.14 Check block information by block ID](#414-check-block-information-by-block-id) - - [4.15 Check block information by block height](#415-check-block-information-by-block-height) - - [4.16 Check the peer/node status](#416-check-the-peernode-status) - - [4.17 Check unconfirmed transaction by public key](#417-check-unconfirmed-transaction-by-public-key) - - [4.18 Check/analyse transaction information in the whole network](#418-checkanalyse-transaction-information-in-the-whole-network) - - [4.19 Check transaction detail inforamtion by transaction ID](#419-check-transaction-detail-inforamtion-by-transaction-id) - - [4.20 Transfer money](#420-transfer-money) - - [4.21 Register delegate](#421-register-delegate) - - [4.22 Vote for delegate](#422-vote-for-delegate) - - [4.23 Cancel the vote for delegate](#423-cancel-the-vote-for-delegate) - - [4.24 Set second password (secret)](#424-set-second-password-secret) - - [4.25 Register Dapp (decentralized application)](#425-register-dapp-decentralized-application) - - [4.26 Contract related command](#426-contract-related-command) - - [4.27 Encrypt related command](#427-encrypt-related-command) - - [4.28 Dapp related command](#428-dapp-related-command) - - [4.29 Create genesis block file](#429-create-genesis-block-file) - - [4.30 Check the status of all nodes/peers of the whole network](#430-check-the-status-of-all-nodespeers-of-the-whole-network) - - [4.31 Check delegates' status in the whole network](#431-check-delegates-status-in-the-whole-network) - - [4.32 Check the original place of all nodes/peers' IP address in the whole network](#432-check-the-original-place-of-all-nodespeers-ip-address-in-the-whole-network) - -Index created with [markdown-toc](https://github.com/AlanWalk/markdown-toc) ---- - -## 0 Asch-CLI Overview -From [Asch Whitepaper](/asch_whitepaper_en.md) -> Asch-CLI is a command line interface provided by Asch system. Within the Asch-CLI, developers can rapidly establish a sidechain by making some simple configurations according to instructions and then create any kind of applications on this sidechain. The system also provides a series of APIs to help developers to create complicate smart contract applications. The functions of these APIs include consensus, strong random numbers, database, and cryptology and so on. - -## 1 Asch-CLI Installation -- Install nodejs package manager **npm** -`sudo apt-get install npm` - -- Install Asch-CLI -`npm install -g asch-cli` -NOTICE: if you install it in China, try parameter `--registry=http://registry.npm.taobao.org` to accelerate the installation. - -## 2 Asch-CLI Synopsis -`asch-cli [option] [command]` - -## 3 Asch-CLI Option Description -### 3.1 Print help information -**Parameter:** -h, --help -**Return:** Help document of Asch-CLI commands or sub-commands -**Usage:** - - asch-cli -h #print help information of asch-cli itself - - asch-cli [commands] -h #print help information of Asch-CLI command - -**Examples:** -``` -root@asch:~# asch-cli -h #print asch-cli help information - Usage: asch-cli [options] [command] - Commands: - - getheight get block height - getblockstatus get block status - openaccount [secret] open your account and get the infomation by secret - openaccountbypublickey [publickey] open your account and get the infomation by publickey - getbalance [address] get balance by address - getaccount [address] get account by address - getvoteddelegates [options] [address] get delegates voted by address - getdelegatescount get delegates count - getdelegates [options] get delegates - getvoters [publicKey] get voters of a delegate by public key - getdelegatebypublickey [publicKey] get delegate by public key - getdelegatebyusername [username] get delegate by username - getblocks [options] get blocks - getblockbyid [id] get block by id - getblockbyheight [height] get block by height - getpeers [options] get peers - getunconfirmedtransactions [options] get unconfirmed transactions - gettransactions [options] get transactions - gettransaction [id] get transactions - sendmoney [options] send money to some address - registerdelegate [options] register delegate - upvote [options] vote for delegates - downvote [options] cancel vote for delegates - setsecondsecret [options] set second secret - registerdapp [options] register a dapp - contract [options] contract operations - crypto [options] crypto operations - dapps [options] manage your dapps - creategenesis [options] create genesis block - peerstat analyze block height of all peers - delegatestat analyze delegates status - ipstat analyze peer ip info - - Options: - - -h, --help output usage information - -V, --version output the version number - -H, --host Specify the hostname or ip of the node, default: 127.0.0.1 - -P, --port Specify the port of the node, default: 4096 - -M, --main Specify the mainnet, default: false - -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getvoteddelegates -h #print Asch-CLI command help information - Usage: getvoteddelegates [options] [address] - get delegates voted by address - Options: - - -h, --help output usage information - -o, --offset - -l, --limit -``` - -### 3.2 Print Asch-CLI version information -**Parameter:** -V, --version -**Return:** Output the version information -**Usage:** `asch-cli -V` - -**Example:** - -``` -root@asch:~# asch-cli -V -1.0.0 -``` - -### 3.3 Appoint the host name or IP address of target Asch Server -**Parameter:** -H, --host <host> [command] *(Default: 127.0.0.1)* - -**Return:** none - -**Usage:** `asch-cli -H 45.32.248.33 [command]` - -**Example:** -``` -root@asch:~# asch-cli -H 45.32.248.33 getheight #check block height of Asch server whose IP is 45.32.248.33 -101236 -``` - -### 3.4 Appoint the port number of target Asch server -**Parameter:** -P, --port <port> [command] *(Default: 4096)* - -**Return:** none - -**Usage:** asch-cli -P 4096 - -**Example:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getheight -102313 -``` - -### 3.5 Appoint the main chain -**Parameter:** -M, --main *(Default: test chain)* - -**Return:** none - -**Usage:** asch-cli -M - -**Example:** - -``` -root@asch:~# asch-cli -M -H *.*.*.105 -P 8192 getheight #check the block height of Asch main chain -9388 -``` - -## 4 Asch-CLI supported commands -### 4.1 Check the blockchain height -**Command:** getheight - -**Return:** blockchain height - -**Usage:** asch-cli getheight - -**Example:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getheight -105387 -``` - -### 4.2 Check the blockchain status -**Command:** getblockstatus - -**Return:** a JSON format string including blockchain height, transaction fee, milestone, the reward of each delegate's block and the whole current volume - -**Usage:** asch-cli getblockstatus - -**Example:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getblockstatus -{ - "success": true, - "height": 105392, - "fee": 10000000, - "milestone": 0, - "reward": 350000000, - "supply": 10036887200000000 -} -``` - -### 4.3 Check account information by password -**Command:** openaccount [secret] - -**Return:** A JSON string containing account information such as address, balance, public key, and second public key and so on. - -**Usage:**asch-cli openaccount "password" - -**Example:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 openaccount "fault still attack alley expand music basket purse later educate follow ride" -{ - "address": "16723473400748954103", - "unconfirmedBalance": 20000000000, - "balance": 20000000000, - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9", - "unconfirmedSignature": false, - "secondSignature": false, - "secondPublicKey": "", - "multisignatures": [], - "u_multisignatures": [] -} -``` - -### 4.4 Check account information by public key -**Command:** openaccountbypublickey [publickey] - -**Return:** A JSON string containing account information such as address, balance, public key, and second public key and so on. - -**Usage:** asch-cli openaccountbypublickey "public key" - -**Example:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 openaccountbypublickey "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9" -{ - "address": "16723473400748954103", - "unconfirmedBalance": 20000000000, - "balance": 20000000000, - "unconfirmedSignature": false, - "secondSignature": false, - "secondPublicKey": "", - "multisignatures": [], - "u_multisignatures": [] -} -``` - -### 4.5 Check account balance by account address -**Command:** getbalance [address] - -**Return:** A integer number that will be the account balance when divided by 100000000 - -**Usage:** asch-cli getbalance [account address] - -**Example:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getbalance 16723473400748954103 -20000000000 -``` - -### 4.6 Check account information by account address -**Command:** getaccount [address] - -**Return:** A JSON string containing account information such as address, balance, public key, and second public key and so on. - -**Usage:** asch-cli getaccount [account address] - -**Example:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getaccount 16723473400748954103 -{ - "address": "16723473400748954103", - "unconfirmedBalance": 20000000000, - "balance": 20000000000, - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9", - "unconfirmedSignature": false, - "secondSignature": false, - "secondPublicKey": "", - "multisignatures": [], - "u_multisignatures": [] -} -``` - -### 4.7 Check delegates voted by the account address -**Command:** getvoteddelegates [options] [address] - -**Return:** A list containing the delegates voted by this account - -**Usage:**asch-cli getvoteddelegates [account address] -o offset -l [a number indicates maximum delegates that can be printed] - -**Example:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getvoteddelegates 15745540293890213312 -o 1 -l 2 -{ success: true, - delegates: - [ { username: 'wgl_002', - address: '14636456069025293113', - publicKey: 'ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7', - vote: 8902736443247261, - producedblocks: 1041, - missedblocks: 6, - rate: 1, - approval: '88.70', - productivity: '99.42' }, - { username: 'wgl_003', - address: '9961157415582672274', - publicKey: 'c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2', - vote: 8902736443247261, - producedblocks: 1043, - missedblocks: 8, - rate: 2, - approval: '88.70', - productivity: '99.23' }] -``` - -### 4.8 Check the whole number of delegates -**Command:** getdelegatescount - -**Return:** An integer number indicates the count of all delegates - -**Usage:** asch-cli getdelegatescount - -**Example:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getdelegatescount -232 -``` - -### 4.9 Check delegates information and sort out -**Command:**getdelegates [options] - -**Return:** A list containing all delegates' information - -**Usage:** asch-cli getdelegates -o [offset number] -l [a number indicates maximum delegates that can be printed] -s rate:asc - -**NOTICE:** rate:asc means ascending sort according to votes. Check other sort types with `asch-cli getdelegates -h` - -**Example:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 getdelegates -o 1 -l 1 -s rate:asc -[ - { - "username": "wgl_003", - "address": "9961157415582672274", - "publicKey": "c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2", - "vote": 9901544836887660, - "producedblocks": 1044, - "missedblocks": 8, - "fees": 12150495022, - "rewards": 161000000000, - "rate": 2, - "approval": 98.65, - "productivity": 99.24, - "forged": "173150495022" - } -] -``` - -### 4.10 Check the voters of the delegate by his public key -**Command:** getvoters [publicKey] - -**Return:** A list containing all the voters - -**Usage:**asch-cli getvoters "delegate's public key" - -**Example:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getvoters "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7" -[ - { - "address": "2918354313445278349", - "publicKey": "4fde4c49f1297d5d3a24b1494204543c4281aff17917ff7ff8ff32da3b4b222f", - "balance": 1215522376203, - "weight": 0.012110398031994424 - }, - { - "address": "1523444724068322527", - "publicKey": "8a6a61c28dc47541aadf1eecec2175c8f768f2331eea3472b1593bf1aa4e1fb4", - "balance": 2109297623765, - "weight": 0.02101519008767971 - }] -``` - -### 4.11 Check detail information of delegate by public key -**Command:** getdelegatebypublickey [publicKey] - -**Return:** A JSON string containing delegate's detail information such as name, address, votes, produced blocks, and forging reward and so on. - -**Usage:** asch-cli getdelegatebypublickey "delegate's public key" - -**Example:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getdelegatebypublickey "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7" -{ - "username": "wgl_002", - "address": "14636456069025293113", - "publicKey": "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7", - "vote": 9901546586887660, - "producedblocks": 1042, - "missedblocks": 6, - "fees": 12383762523, - "rewards": 161700000000, - "rate": 1, - "approval": 98.65, - "productivity": 99.43, - "forged": "174083762523" -} -``` -### 4.12 Check the detail information of delegate by the name -**Command:** getdelegatebyusername [username] - -**Return:** A JSON string containing delegate's detail - -**Usage:** asch-cli getdelegatebyusername "delegate's name" - -**Example:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getdelegatebyusername "wgl_002" -{ - "username": "wgl_002", - "address": "14636456069025293113", - "publicKey": "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7", - "vote": 9901546586887660, - "producedblocks": 1042, - "missedblocks": 6, - "fees": 12383762523, - "rewards": 161700000000, - "rate": 1, - "approval": 98.65, - "productivity": 99.43, - "forged": "174083762523" -} -``` - -### 4.13 Check/analyse block information in whole network -**Command:** getblocks [options] - -**Return:** A JSON string containing query result status and queried block information - -**Usage:** asch-cli getblocks -o [offset number] -l [an integer that indicate maximum return data] -r [reward amount] -f [fee] -a [total amount] -g [public key that generates blocks] -s [sort rule] - -**Example:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getblocks -o 1 -l 1 -r 350000000 -{ - "success": true, - "blocks": [ - { - "id": "5533619110613125681", - "version": 0, - "timestamp": 3914630, - "height": 60481, - "previousBlock": "11174102253820291084", - "numberOfTransactions": 0, - "totalAmount": 0, - "totalFee": 0, - "reward": 350000000, - "payloadLength": 0, - "payloadHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "generatorPublicKey": "68b28341605a24f6684df81882df1b13f421ec1cbba7d9aaa68f6c079705b258", - "generatorId": "10651956562526682705", - "blockSignature": "77115fdaab3215039bcf2bf8b3a461b3b7cafca7adae07e271a1a953ca6531a9e93f985bbec8544d596a568595661f1da742e20797b827d5b20aa75e8d80cc0b", - "confirmations": "45349", - "totalForged": 350000000 - } - ], - "count": 45350 -} -``` -### 4.14 Check block information by block ID -**Command:** getblockbyid [id] - -**Return:** A JSON string containing block ID, block height, previous block ID, total transaction number, total amount, transaction fee, reward, hash, block generator public key and ID, block signature, quantity of confirmation and so on. -**Usage:**asch-cli getblockbyid [block ID] - -**Example:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getblockbyid 1425942128040906871 #check the genesis block -{ - "id": "1425942128040906871", - "version": 0, - "timestamp": 0, - "height": 1, - "previousBlock": "", - "numberOfTransactions": 103, - "totalAmount": 10000000000000000, - "totalFee": 0, - "reward": 0, - "payloadLength": 19417, - "payloadHash": "dd5cd3186d32145b01f8fd0bd23e3b3d72414b59b162d2e664e759db8fe60d46", - "generatorPublicKey": "2af8566f8555bafb25df5a50e2e22b91a8577ceabc05d47dbd921572d28330e8", - "generatorId": "1170992220085500484", - "blockSignature": "a8ed06bfbfd1b630b1628e97a5c7c9383337c4ce32825969fad830890e0af981312be635b775ff46eea4f739da043f668a70efd5a940429e39fe5063852f4a01", - "confirmations": "105901", - "totalForged": 0 -} -``` - -### 4.15 Check block information by block height -**Command:** getblockbyheight [height] - -**Return:** A JSON string containing block ID, block height, previous block ID, total transaction number, total amount, transaction fee, reward, hash, block generator public key and ID, block signature, quantity of confirmation and so on. - -**Usage:**asch-cli getblockbyheight [block height] - -**Example:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getblockbyheight 1 -{ - "id": "1425942128040906871", - "version": 0, - "timestamp": 0, - "height": 1, - "previousBlock": "", - "numberOfTransactions": 103, - "totalAmount": 10000000000000000, - "totalFee": 0, - "reward": 0, - "payloadLength": 19417, - "payloadHash": "dd5cd3186d32145b01f8fd0bd23e3b3d72414b59b162d2e664e759db8fe60d46", - "generatorPublicKey": "2af8566f8555bafb25df5a50e2e22b91a8577ceabc05d47dbd921572d28330e8", - "generatorId": "1170992220085500484", - "blockSignature": "a8ed06bfbfd1b630b1628e97a5c7c9383337c4ce32825969fad830890e0af981312be635b775ff46eea4f739da043f668a70efd5a940429e39fe5063852f4a01", - "confirmations": "105922", - "totalForged": 0 -} -``` - -### 4.16 Check the peer/node status -**Command:** getpeers [options] - -**Return:** A list containing peer ip, port, operation system, and Asch version, and so on. - -**Usage:**asch-cli getpeers -o [offset] -l [an integer that indicate maximum return data] -t [status value] -s [sort type] -v [version] -p [port number] --os [OS version] - -**NOTICE:** For further information, try `asch-cli getpeers -h` - -**Example:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getpeers -o 1 -l 2 -[ - { - "ip": "45.32.62.184", - "port": 4096, - "state": 2, - "os": "linux3.13.0-87-generic", - "version": "1.0.0" - }, - { - "ip": "45.32.22.78", - "port": 4096, - "state": 2, - "os": "linux3.13.0-87-generic", - "version": "1.0.0" - } -] -``` - -### 4.17 Check unconfirmed transaction by public key -**Command:** getunconfirmedtransactions [options] - -**Return:** A list containing details of all transactions that are not confirmed yet - -**Usage:** asch-cli getunconfirmedtransactions -p "sender's public key" -a [recipient's address] - -**Example:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 getunconfirmedtransactions -k "d39d6f26869067473d685da742339d1a9117257fe14b3cc7261e3f2ed5a339e3" -[ - { - "type": 0, - "timestamp": 4385190, - "senderPublicKey": "d39d6f26869067473d685da742339d1a9117257fe14b3cc7261e3f2ed5a339e3", - "signature": "98d65df3109802c707eeed706e90a907f337bddab58cb4c1fbe6ec2179aa1c85ec2903cc0cf44bf0092926829aa5a0a6ec99458f65b6ebd11f0988772e58740e", - "recipientId": "16723473400748954103", - "senderId": "15745540293890213312", - "amount": 10000000000, - "fee": 10000000, - "signatures": [], - "id": "17192581936339156329", - "height": 0, - "asset": {} - } -] -``` - -### 4.18 Check/analyse transaction information in the whole network -**Command:** gettransactions [options] - -**Return:** A list containing all selected transaction's detail information - -**Usage:** asch-cli gettransactions -b [block ID] -o [offset] -l [an integer that indicate maximum return data] - -**NOTICE:** try `asch-cli gettransactions -h` to get the information for other parameters. - -**Example:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 gettransactions -o 1 -l 2 #check the first two transactions' information in the whole network -[ - { - "id": "10169086766604015960", - "height": "1", - "blockId": "1425942128040906871", - "type": 2, - "timestamp": 0, - "senderPublicKey": "991e0dda00d2c33ce68dd99471de8ebea7b58711f22a2e55236b8864c6d24c84", - "senderId": "3331250159865474723", - "recipientId": "", - "amount": 0, - "fee": 0, - "signature": "60bf38e7a3515aeaa2cac491f7737c94087f448a862099408b90c2cf96d3fe4f709e22e6471dd4e37aca111d8573beeb7b6cff4ef451633d9aaf74ab97ce8d02", - "signSignature": "", - "signatures": null, - "confirmations": "105988", - "asset": {} - }, - { - "id": "10375311635154792515", - "height": "1", - "blockId": "1425942128040906871", - "type": 2, - "timestamp": 0, - "senderPublicKey": "1674ae566c633cde3e01db8f04a02ea087081a270de2dd53e0e0b97c029106fb", - "senderId": "9948352853509008057", - "recipientId": "", - "amount": 0, - "fee": 0, - "signature": "f09c1693cc26c4028c642cb1711cf71c2dee090a50904d1590c74d865b2f5f3ba720ed792704f5379ec9c4a20b018c5e95f325ea179236777a28cddffe8c580d", - "signSignature": "", - "signatures": null, - "confirmations": "105988", - "asset": {} - } -] -``` - -### 4.19 Check transaction detail inforamtion by transaction ID -**Command:** gettransaction [id] - -**Return:** A JSON string containing transaction ID, block height, block ID, time stamp, sender's public key, recipient's address, total amount, fee, signature, confirmation quantity, assets, and etc. - -**Usage:**asch-cli gettransaction [transactionID] - -**Example:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 gettransaction 17192581936339156329 -{ - "id": "17192581936339156329", - "height": "105951", - "blockId": "15051364118100195665", - "type": 0, - "timestamp": 4385190, - "senderPublicKey": "d39d6f26869067473d685da742339d1a9117257fe14b3cc7261e3f2ed5a339e3", - "senderId": "15745540293890213312", - "recipientId": "16723473400748954103", - "amount": 10000000000, - "fee": 10000000, - "signature": "98d65df3109802c707eeed706e90a907f337bddab58cb4c1fbe6ec2179aa1c85ec2903cc0cf44bf0092926829aa5a0a6ec99458f65b6ebd11f0988772e58740e", - "signSignature": "", - "signatures": null, - "confirmations": "17", - "asset": {} -} -``` - -### 4.20 Transfer money -**Command:** sendmoney [option] - -**Return:** transaction result. true=success, otherwise error message - -**Usage:** asch-cli sendmoney -e "[sender's password]" -t [recipient's address] -a [transfer amount] [-s "second password"] - -**Example:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 sendmoney -e "motion group blossom coral upper warrior pattern fragile sister misery palm admin" -t 16723473400748954103 -a 100 -true -``` - -### 4.21 Register delegate -**Command:** registerdelegate [options] - -**Return:** Registering result,ture=success, otherwise error message - -**Usage:** asch-cli registerdelegate -e "[password]" -s "[second password]" -u "[delegate's name]" - -**Example:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 registerdelegate -e "fault still attack alley expand music basket purse later educate follow ride" -u "delegate_register" -true -``` - -### 4.22 Vote for delegate -**Command:** upvote [options] - -**Return:** Voting result, ture=success, otherwise error message - -**Usage:** asch-cli upvote -e "[password]" -s "[second password]" -p "delegate's public key" - -**Example:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 upvote -e "fault still attack alley expand music basket purse later educate follow ride" -p "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9" -true -``` - -### 4.23 Cancel the vote for delegate -**Command:**downvote [options] - -**Return:** Cancelling vote result, ture=success, otherwise error message - -**Usage:** asch-cli downvote -e "[password]" -s "[second password]" -p "delegate's public key" - -**Example:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 downvote -e "fault still attack alley expand music basket purse later educate follow ride" -p "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9" -true -``` - -### 4.24 Set second password (secret) -**Command:** setsecondsecret [options] - -**Return:** Setting up result, ture=success, otherwise error message - -**Usage:** asch-cli setsecondsecret -e "[password]" -s "[second password]" - -**Example:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 setsecondsecret -e "fault still attack alley expand music basket purse later educate follow ride" -s "ce shi er ji mi ma" -true -``` - -### 4.25 Register Dapp (decentralized application) -**Command:** registerdapp [options] - -**Return:** - -**Usage:** asch-cli registerdapp -e "[password]" -s "[second password]" -f [Dapp meta file] - -**Example:** - - - -### 4.26 Contract related command -**Command:** contract [options] - -**Return:** - -**Usage:** - - asch-cli contract -a # create a contract - - asch-cli contract -d # delete a contract - -**Example:** - - -###4.27 Encrypt related command -**Command:** crypto [option] - -**Return:** A list - -**Usage:** -- asch-cli -p # generate public key according to password -- asch-cli -g # create one or more new account - -**Example:** - -``` -root@asch:~# asch-cli -H 45.32.248.33 -P 4096 crypto -g -? Enter number of accounts to generate 1 -[ { address: '16723473400748954103', - secret: 'fault still attack alley expand music basket purse later educate follow ride', - publicKey: 'bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9' } ] -Done -``` - -### 4.28 Dapp related command -**Command:** dapps [options] - -**Return:** - -**Usage:** asch-cli dapps -a - -**Example:** - -###4.29 Create genesis block file -**Command:** creategenesis [options] - -**Return:** to create a genesis block file (genesisBlock.json) and log file (genGenesisBlock.log) in the current folder - -**Usage:** asch-cli creategenesis - -**Example:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 creategenesis -root@asch:~# more genesisBlock.json -{ - "version": 0, - "totalAmount": 10000000000000000, - "totalFee": 0, - "reward": 0, - "payloadHash": "baebdb59d0c19a07c2440e22c0512b4efe9794565b352375195c9e7e8a3817b0", - "timestamp": 0, - "numberOfTransactions": 103, -... -} -``` - -### 4.30 Check the status of all nodes/peers of the whole network -**Command:** peerstat - -**Return:** The peer's information, containing peer IP address, port, version and block height and etc. - -**Usage:**asch-cli peerstat - -**Example:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 peerstat -45.32.248.33:4096 1.0.0 106036 -45.32.62.184:4096 1.0.0 106036 -45.32.19.241:4096 1.0.0 106036 -``` - -### 4.31 Check delegates' status in the whole network -**Command:** delegatestat - -**Return:** Delegates' information, containing delegates' name, address, approval votes, productivity, the amount of generated blocks, block height, ID, and the time of last block generated and so on. - -**Usage:** asch-cli delegatestat - -**Example:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 delegatestat -name address rate approval productivity produced height id time -nayimoliuguang 3331976396377269399 93 88.36% 98.39% 1037 105618 12962348710289833740 2016/08/17 21:07:20(1 hour ago) -jack 3705405381126069457 86 88.36% 99.41% 506 105628 5876778147855073736 2016/08/17 21:09:00(1 hour ago) -node_3 12796761013870716784 81 88.36% 80.51% 814 105784 4575518649204137595 2016/08/17 21:38:10(40 mins ago) -wgl_003 9961157415582672274 2 98.65% 99.24% 1047 105852 11175724889329116017 2016/08/17 21:49:40(28 mins ago) -xihulongjing 12676662200687508271 59 88.36% 76.92% 150 105853 15273855606472618453 2016/08/17 21:49:50(28 mins ago) -liangpeili 4514546945474752928 50 88.37% 99.68% 627 105855 3771943180359756069 2016/08/17 21:50:10(28 mins ago) -asch_tea1 8812460086240160222 4 98.58% 98.79% 1059 105857 14968719538781965695 2016/08/17 21:50:30(27 mins ago) -intmaster 7321911740133937168 97 88.36% 100% 1032 105871 6757656887343300317 2016/08/17 21:52:50(25 mins ago) -mode_6 9248745407080572308 8 88.48% 100% 1060 105873 3777454410915098884 2016/08/17 21:53:10(25 mins ago) -``` - -### 4.32 Check the original place of all nodes/peers' IP address in the whole network -**Command:** ipstat - -**Return:** the original place of each peer's IP address - -**Usage:** asch-cli ipstat - -**Example:** - -``` -root@asch:~# asch-cli -H 101.200.162.236 -P 4096 ipstat -美国 US -美国 US -美国 US -日本 JP -中国 CN -中国 CN -中国 CN -中国 CN -中国 CN -中国 CN -``` diff --git a/docs/asch_dapp_default_api.md b/docs/asch_dapp_default_api.md deleted file mode 100644 index 16ae7d3..0000000 --- a/docs/asch_dapp_default_api.md +++ /dev/null @@ -1,681 +0,0 @@ -Table of Contents -================= - - * [Asch dapp默认接口文档](#asch-dapp默认接口文档) - * [1 区块blocks](#1-区块blocks) - * [1.1 获取dapp区块高度](#11-获取dapp区块高度) - * [1.2 获取dapp区块数据](#12-获取dapp区块数据) - * [2 账户accounts](#2-账户accounts) - * [2.1 根据地址获取dapp内账户信息](#21-根据地址获取dapp内账户信息) - * [3 事务transactions](#3-事务transactions) - * [3.1 签名交易](#31-签名交易) - * [3.1.1 客户端签名交易(signed)-更安全](#311-客户端签名交易signed-更安全) - * [3.1.1.1 dapp充值](#3111-dapp充值) - * [3.1.1.2 dapp提现,type=2](#3112-dapp提现type2) - * [3.1.1.2 dapp内部转账,type=3](#3112-dapp内部转账type3) - * [3.1.1.2 dapp设置昵称,type=4](#3112-dapp设置昵称type4) - * [3.1.2 服务器端签名交易(unsigned)](#312-服务器端签名交易unsigned) - * [3.1.2.1 dapp充值](#3121-dapp充值) - * [3.1.2.2 dapp提现,type=2](#3122-dapp提现type2) - * [3.1.2.2 dapp内部转账,type=3](#3122-dapp内部转账type3) - * [3.1.2.2 dapp设置昵称,type=4](#3122-dapp设置昵称type4) - * [3.2 获取未确认的交易](#32-获取未确认的交易) - * [3.3 获取已确认的交易](#33-获取已确认的交易) - * [3.4 根据交易id获取交易详情](#34-根据交易id获取交易详情) - * [3.5 根据查询条件获取交易](#35-根据查询条件获取交易) - * [4 智能合约contracts](#4-智能合约contracts) - * [4.1 获取dapp内的所有智能合约](#41-获取dapp内的所有智能合约) - -Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc) - - -# Asch dapp默认接口文档 - -下面这些是每个dapp都有的通用(默认)api,由asch-sandbox提供支持。 - - -## **1 区块blocks** -### **1.1 获取dapp区块高度** -接口地址:/api/dapps/dappID/blocks/height -请求方式:GET -支持格式:urlencode - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|height|integer |dapp区块高度 | - -请求示例: -```bash -curl -k -H "Content-Type: application/json" -X GET http://localhost:4096/api/dapps/bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024/blocks/height && echo -``` - -JSON返回示例: -```js -{ - height: 10, - success: true -} -``` - - -### **1.2 获取dapp区块数据** -接口地址:/api/dapps/dappID/blocks -请求方式:GET -支持格式:urlencode -接口说明:不加参数则获取全网区块详情 -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|limit |integer |N |限制结果集个数,最小值:0,最大值:100 | -|orderBy|string |N |根据表中字段排序,如height:desc | -|offset|integer |N |偏移量,最小值0 | -|generatorPublicKey|string |N |区块生成者公钥 | -|totalAmount|integer |N |交易总额,最小值:0,最大值:10000000000000000 | -|totalFee|integer |N |手续费总额,最小值:0,最大值:10000000000000000 | -|previousBlock|string |N |上一个区块 | -|height|integer |N |区块高度 | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|count|integer |符合条件的总结果数目 | -|blocks|Array |每个元素是一个block对象,对象里面包含block的id、height、产块受托人公钥等信息| - -请求示例: -```bash -curl -k -H "Content-Type: application/json" -X GET http://localhost:4096/api/dapps/bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024/blocks?limit=1 && echo -``` - -JSON返回示例: -```js -{ - blocks: [{ - id: "451dd17f273ea5fbd240238178c1343b11031a1d309ee8b29e8b1a5838473ec6", - timestamp: 0, - height: 1, - payloadLength: 103, - payloadHash: "995f4749e1924af55f1cdefd202efd0b37b2aa70553982378c037bc6015d5634", - prevBlockId: "", - pointId: "", - pointHeight: 0, - delegate: "8065a105c785a08757727fded3a06f8f312e73ad40f1f3502e0232ea42e67efd", - signature: "b1d0171494ce6c0621902c6005f7a85e15f3509a68ac6106b166abf711ced73efaeaf1eae0cdf594143854e27b417b253485cf98b3cc9f7aa967a929b717020b", - count: 1 - }], - count: 133, - success: true -} -``` - -## **2 账户accounts** -### **2.1 根据地址获取dapp内账户信息** -接口地址:/api/dapps/dappID/accounts/:address -请求方式:GET -支持格式:urlencode -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|address |string | Y |asch地址 | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|account|字典 |账户详情,包含dapp内该账户拥有的所有资产及余额,是否受托人,额外信息 | - - -请求示例: -```bash -curl -k -H "Content-Type: application/json" -X GET http://192.168.2.115:4096/api/dapps/bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024/accounts/ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M && echo -``` - -JSON返回示例: -```js -{ - account: { - balances: [{ - currency: "XAS", // dapp该账户拥有xas(通过自行充值或者他人dapp内转账获得) - balance: "10000000000" // 100XAS - }], - extra: null, - isDelegate: false // 是否受托人:否 - }, - success: true -} -``` - - -## **3 事务transactions** -### **3.1 签名交易** -http接口又分为signed和unsigned,他们的区别是交易在本地还是服务端签名,后者需要将密码通过http传输给服务器进行签名。 - -#### **3.1.1 客户端签名交易(signed)-更安全** -/peer相关的api,在请求时都需要设置一个header - - - key为magic,testnet value:594fe0f3, mainnet value:5f5b3cf5 - - key为version,value为'' - -asch系统的所有写操作都是通过发起一个交易来完成的。 -交易数据通过一个叫做asch-js的库来创建,然后再通过一个POST接口发布出去。 -POST接口规格如下: - -|事项 |说明 | -|--- |--- | -|接口地址|/peer/transactions | -|payload|asch-js创建出来的交易数据 | -|请求方式|post/put等 | -|支持格式|json | - -##### **3.1.1.1 dapp充值** -接口地址:/peer/transactions -请求方式:POST -支持格式:json -备注:充值时在主链发生type=6的交易(intransfer),dapp内部会自动调用编号为1的智能合约进行dapp内部充值 -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|transaction|json|Y|aschJS.transfer.createInTransfer生成的交易数据| - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transactionId|string |交易id | - -请求示例: -```bash -var aschJS = require('asch-js'); -var dappid = "bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024"; -var currency = "XAS"; -var amount = 10*100000000 ; -var secret = "found knife gather faith wrestle private various fame cover response security predict"; -var secondSecret = ""; -var transaction = aschJS.transfer.createInTransfer(dappid, currency, amount, secret, secondSecret || undefined); - -console.log(JSON.stringify(transaction)); -{"type":6,"amount":1000000000,"fee":10000000,"recipientId":null,"senderPublicKey":"2856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec4","timestamp":39721503,"asset":{"inTransfer":{"dappId":"bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024","currency":"XAS"}},"signature":"8cefc8fa933e4d5e8699828dc8cd5d1b4737ffa82175c744fd681bad0b1a6b68526e0783e85d7979f894fc38850bd2ed0a983ce3cb3f5d16b68fd37dfb9dfb0a","id":"4b580f8f61f4586920a4c0d37b6fad21daf3453fe9ccc5426c2cae7a263c160c"} // type=6表示dapp充值,这里的type指主链的交易类型,非dapp合约编号 - -// 将上面生成的“充值”交易数据通过post提交给asch server -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":6,"amount":1000000000,"fee":10000000,"recipientId":null,"senderPublicKey":"2856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec4","timestamp":39721503,"asset":{"inTransfer":{"dappId":"bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024","currency":"XAS"}},"signature":"8cefc8fa933e4d5e8699828dc8cd5d1b4737ffa82175c744fd681bad0b1a6b68526e0783e85d7979f894fc38850bd2ed0a983ce3cb3f5d16b68fd37dfb9dfb0a","id":"4b580f8f61f4586920a4c0d37b6fad21daf3453fe9ccc5426c2cae7a263c160c"}}' http://localhost:4096/peer/transactions && echo - -``` - -JSON返回示例: -```js -{ - "success": true, - "transactionId": "4b580f8f61f4586920a4c0d37b6fad21daf3453fe9ccc5426c2cae7a263c160c" -} -``` - -##### **3.1.1.2 dapp提现,type=2** -接口地址:/api/dapps/dappID/transactions/signed -请求方式:PUT -支持格式:json -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|dappID|string|Y|dapp的id | -|transaction|json|Y|aschJS.dapp.createInnerTransaction生成的交易数据| - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transactionId|string |提币交易id | - -请求示例: -```bash -var aschJS = require('asch-js'); -var fee = String(0.1 * 100000000); -var type = 2; -var options = {fee: fee, type: type, args: '["CCTime.XCT", "100000000"]'}; -var secret = "elite brush pave enable history risk ankle shrimp debate witness ski trend"; -var transaction = aschJS.dapp.createInnerTransaction(options, secret); - -console.log(JSON.stringify(transaction)); -{"fee":"10000000","timestamp":40384202,"senderPublicKey":"aa4e4ac1336a1e9db1ee5ce537a59d3fcb0f068cb4b25aac9f48e0e8bc6259c9","type":2,"args":"[\"CCTime.XCT\", \"100000000\"]","signature":"05dba744705fd1dbc1854b415392364cdbae11778671be8eb5fdbce57855a87b3dde5bf2d0219059411253fb304497758422c8d1546ec45eb5521b4a6577d507"} - -// 将上面生成的“提现”交易数据通过post提交给asch server -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X PUT -d '{"transaction":{"fee":"10000000","timestamp":40384202,"senderPublicKey":"aa4e4ac1336a1e9db1ee5ce537a59d3fcb0f068cb4b25aac9f48e0e8bc6259c9","type":2,"args":"[\"CCTime.XCT\", \"100000000\"]","signature":"05dba744705fd1dbc1854b415392364cdbae11778671be8eb5fdbce57855a87b3dde5bf2d0219059411253fb304497758422c8d1546ec45eb5521b4a6577d507"}}' http://45.32.22.78:4096/api/dapps/d352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1/transactions/signed && echo - -``` - -JSON返回示例: -```js -{ - "success": true, - "transactionId": "8bcae742206bf236214b9972efaca0bbe29f3703b4055a14cc8b095546880dc4" -} -``` - -##### **3.1.1.2 dapp内部转账,type=3** -接口地址:/api/dapps/dappID/transactions/signed -请求方式:PUT -支持格式:json -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|dappID|string|Y|dapp的id | -|transaction|json|Y|aschJS.dapp.createInnerTransaction生成的交易数据| - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transactionId|string |内部转账交易id | - -请求示例: -```bash -var aschJS = require('asch-js'); -var fee = String(0.1 * 100000000); -var type = 3; -var options = {fee: fee, type: type, args: '["CCTime.XCT", "100000000", "A6H9rawJ7qvE2rKwQfdtBHdeYVehB8gFzC"]'}; -var secret = "elite brush pave enable history risk ankle shrimp debate witness ski trend"; -var transaction = aschJS.dapp.createInnerTransaction(options, secret); - -console.log(JSON.stringify(transaction)); -{"fee":"10000000","timestamp":40387708,"senderPublicKey":"aa4e4ac1336a1e9db1ee5ce537a59d3fcb0f068cb4b25aac9f48e0e8bc6259c9","type":3,"args":"[\"CCTime.XCT\", \"100000000\", \"A6H9rawJ7qvE2rKwQfdtBHdeYVehB8gFzC\"]","signature":"e2364534b8c4b0735a85c68ba17fddf5321fc48af04d483ad05531d4993058eaa35ff44d913a03b6d7278890ff7f42435f8313e08ce70c523dfc256b4de9e303"} - -// 将上面生成的“提现”交易数据通过post提交给asch server -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X PUT -d '{"transaction":{"fee":"10000000","timestamp":40387708,"senderPublicKey":"aa4e4ac1336a1e9db1ee5ce537a59d3fcb0f068cb4b25aac9f48e0e8bc6259c9","type":3,"args":"[\"CCTime.XCT\", \"100000000\", \"A6H9rawJ7qvE2rKwQfdtBHdeYVehB8gFzC\"]","signature":"e2364534b8c4b0735a85c68ba17fddf5321fc48af04d483ad05531d4993058eaa35ff44d913a03b6d7278890ff7f42435f8313e08ce70c523dfc256b4de9e303"}}' http://45.32.22.78:4096/api/dapps/d352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1/transactions/signed && echo - -``` - -JSON返回示例: -```js -{ - "success": true, - "transactionId": "e2687a471ac2ddbbdd919266e58b0b652c55f74402b27be850d767fa44162c79" -} -``` - -##### **3.1.1.2 dapp设置昵称,type=4** -接口地址:/api/dapps/dappID/transactions/signed -请求方式:PUT -支持格式:json -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|dappID|string|Y|dapp的id | -|transaction|json|Y|aschJS.dapp.createInnerTransaction生成的交易数据| - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transactionId|string |设置昵称的交易id | - -请求示例: -```bash -var aschJS = require('asch-js'); -var fee = String(0.1 * 100000000); -var type = 4; -var options = {fee: fee, type: type, args: '["Nickname"]'}; // Nickname即昵称 -var secret = "elite brush pave enable history risk ankle shrimp debate witness ski trend"; -var transaction = aschJS.dapp.createInnerTransaction(options, secret); - -console.log(JSON.stringify(transaction)); -{"fee":"10000000","timestamp":40388287,"senderPublicKey":"aa4e4ac1336a1e9db1ee5ce537a59d3fcb0f068cb4b25aac9f48e0e8bc6259c9","type":4,"args":"[\"Nickname\"]","signature":"be08cdb2f4d1a0f2f2e5b02e33e67fdf43e403703ce35cb42a2dc7338c7a352adca56dc61e3be0fedc1727c1adc0101f1a9e1a3e67ac0623602bf872deb80802"} - -// 将上面生成的“提现”交易数据通过post提交给asch server -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X PUT -d '{"transaction":{"fee":"10000000","timestamp":40388287,"senderPublicKey":"aa4e4ac1336a1e9db1ee5ce537a59d3fcb0f068cb4b25aac9f48e0e8bc6259c9","type":4,"args":"[\"Nickname\"]","signature":"be08cdb2f4d1a0f2f2e5b02e33e67fdf43e403703ce35cb42a2dc7338c7a352adca56dc61e3be0fedc1727c1adc0101f1a9e1a3e67ac0623602bf872deb80802"}}' http://45.32.22.78:4096/api/dapps/d352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1/transactions/signed && echo - -``` - -JSON返回示例: -```js -{ - "success": true, - "transactionId": "7teae742206bf236214b9972efaca0bbe29f3703b4055a14cc8b095546880dc4" -} -``` - -#### **3.1.2 服务器端签名交易(unsigned)** -##### **3.1.2.1 dapp充值** -##### **3.1.2.2 dapp提现,type=2** -接口地址:/api/dapps/dappId/transactions/unsigned -请求方式:PUT -支持格式:json -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|secret|string|Y|asch密码 | -|fee|string|Y|交易手续费,目前固定为10000000 | -|type|integer|Y|智能合约编号 | -|args|json字符串数组|Y|对应合约编号需要传入的参数 | - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transactionId|string |提现交易id | - -请求示例: -```bash -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X PUT -d '{"secret":"elite brush pave enable history risk ankle shrimp debate witness ski trend","fee":"10000000","type":2,"args":"[\"CCTime.XCT\",\"100000000\"]"}' 'http://45.32.22.78:4096/api/dapps/d352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1/transactions/unsigned' && echo - -``` - -JSON返回示例: -```js -{ - "success": true, - "transactionId": "f59d365cbc8ea29f5d3798af795dc66dbdda00e2f1ae6677d5c7239180f3e98a" -} -``` - -##### **3.1.2.2 dapp内部转账,type=3** -接口地址:/api/dapps/dappId/transactions/unsigned -请求方式:PUT -支持格式:json -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|secret|string|Y|asch密码 | -|fee|string|Y|交易手续费,目前固定为10000000 | -|type|integer|Y|智能合约编号 | -|args|json字符串数组|Y|对应合约编号需要传入的参数 | - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transactionId|string |内部转账交易id | - -请求示例: -```bash -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X PUT -d '{"secret":"elite brush pave enable history risk ankle shrimp debate witness ski trend","fee":"10000000","type":3,"args":"[\"CCTime.XCT\",\"1000000000\",\"ADimyhJa99XFzVrbnTYsCqPB4TKQNdjCWw\"]"}' 'http://45.32.22.78:4096/api/dapps/d352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1/transactions/unsigned' && echo - -``` - -JSON返回示例: -```js -{ - "success": true, - "transactionId": "96d886b7d724e6a00cc8c52c24b674ec8a9fc7fd8145a326bf69983fdc74a006" -} -``` - -##### **3.1.2.2 dapp设置昵称,type=4** -接口地址:/api/dapps/dappId/transactions/unsigned -请求方式:PUT -支持格式:json -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|secret|string|Y|asch密码 | -|fee|string|Y|交易手续费,目前固定为10000000 | -|type|integer|Y|智能合约编号 | -|args|json字符串数组|Y|对应合约编号需要传入的参数,这里是昵称 | - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transactionId|string |设置昵称交易id | - -请求示例: -```bash -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X PUT -d '{"secret":"minor borrow display rebel depart core buzz right distance avocado immense push","fee":"10000000","type":4,"args":"[\"zhenxi\"]"}' 'http://45.32.22.78:4096/api/dapps/d352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1/transactions/unsigned' && echo -``` - -JSON返回示例: -```js -{ - "success": true, - "transactionId": "7b5d9d13cf718ee28efde6bae85fbefbcd0eca3d6c0c6fff1421a1102d730669" -} -``` - -### **3.2 获取未确认的交易** -接口地址:/api/dapps/dappID/transactions/unconfirmed -请求方式:GET -支持格式:urlencode - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transactions|array |未确认交易列表 | - - -请求示例: -```bash -curl -k -X GET http://localhost:4096/api/dapps/bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024/transactions/unconfirmed && echo -``` - -JSON返回示例: -```js -{ - "transactions": [], - "success": true -} -``` - -### **3.3 获取已确认的交易** -接口地址:/api/dapps/dappID/transactions -请求方式:GET -支持格式:urlencode -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|senderId |string |N |发送者地址 | -|type |interger |N |合约编号 | -|limit |interger |N |限制返回的条数,默认值是100 | -|offset |interger |N |偏移量 | - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transactions|array |交易列表 | -|count|integer |符合查询条件的总交易条数 | - -请求示例: -```bash -curl -k -X GET http://localhost:4096/api/dapps/bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024/transactions?senderId=AJTGR8EGsprrF7r63D2XLDftGAKUu1Ucjn && echo -``` - -JSON返回示例: -```js -{ - "transactions": [{ - "id": "b12b144b3dbb76b70cd62f97e3d3b0606d97c0f402bba1fb973dd2d3ab604a16", - "timestamp": 0, - "senderId": "AJTGR8EGsprrF7r63D2XLDftGAKUu1Ucjn", - "senderPublicKey": "27823f51a3dddd475943fb8142380d2f8722b0f6c651f6ac37930b63666c7803", - "fee": "0", - "signature": "22739bb762ff0135a0c4199507e3c45a8615c467bfeb4efa5110802033959698588e39b76d037445e02959ee67b483ac4d24f12304181f4955871cdcd28e3001", - "type": 3, - "args": "[\"CNY\",\"100000000000000\",\"A8QCwz5Vs77UGX9YqBg9kJ6AZmsXQBC8vj\"]", - "height": 1 - }], - "count": 1, - "success": true -} -``` - -### **3.4 根据交易id获取交易详情** -接口地址:/api/dapps/dappID/transactions/:id -请求方式:GET -支持格式:urlencode -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|id |string |Y |交易id | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transaction|dict |该交易id对应的交易详情 | - - -请求示例: -```bash -curl -k -X GET http://localhost:4096/api/dapps/bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024/transactions/7088c67edd43326276453b833727677df6f312271b824564a6a934371265f0dc && echo -``` - -JSON返回示例: -```js -{ - "transaction": { - "id": "7088c67edd43326276453b833727677df6f312271b824564a6a934371265f0dc", - "timestamp": 39709980, - "senderId": "ADYGpYHmgkbukqByZ2JzwFXZM6wYfMXCaR", - "senderPublicKey": "55ad778a8ff0ce4c25cb7a45735c9e55cf1daca110cfddee30e789cb07c8c9f3", - "fee": "0", - "signature": "bd51295c3373da2a92c77b6a96a0edbda75cdcde5fd7824ff326c366ed0ec5778e1d02e7d9c280a219d6c815d9bfdbc2d03bb960a0f5d8d35458e4bda87d6104", - "type": 1, - "args": "[\"XAS\",\"10000000000\",\"2f1db0014483ffef85289e086af321e374944668dd7fb4f156c70609276ed903\",\"ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M\"]", - "height": 637 - }, - "success": true -} -``` - -### **3.5 根据查询条件获取dapp转帐记录** -接口地址:/api/dapps/dappID/transfers -请求方式:GET -支持格式:urlencode -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|ownerId |string |N |发送者地址,ownerId和currency必须有一个或者两个都存在 | -|currency |string |N |代币名称,ownerId和currency必须有一个或者两个都存在 | -|limit |interger |N |限制返回的条数,默认值是10 | -|offset |interger |N |偏移量,默认0 | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transfers|array |符合查询条件的交易列表 | -|count|integer |符合查询条件的条数 | - -请求示例: -```bash -curl -k -X GET http://localhost:4096/api/dapps/bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024/transfers?ownerid=ADYGpYHmgkbukqByZ2JzwFXZM6wYfMXCaR && echo -``` - -JSON返回示例: -```js -{ - "count": 1, - "transfers": [{ - "tid": "b12b144b3dbb76b70cd62f97e3d3b0606d97c0f402bba1fb973dd2d3ab604a16", - "senderId": "AJTGR8EGsprrF7r63D2XLDftGAKUu1Ucjn", - "recipientId": "A8QCwz5Vs77UGX9YqBg9kJ6AZmsXQBC8vj", - "currency": "CNY", - "amount": "100000000000000", - "t_timestamp": 0, - "t_type": 3, - "t_height": 1 - }], - "success": true -} -``` - -## **4 智能合约contracts** -### **4.1 获取dapp内的所有智能合约** -接口地址:/api/dapps/dappID/contracts -请求方式:GET -支持格式:urlencode - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|contracts|array |每个元素都是一个字典,由合约编号、合约名字组成,其中core开头的合约为每个dapp通用的内置合约 | - - -请求示例: -```bash -// 下面是 -curl -k -H "Content-Type: application/json" -X GET http://192.168.2.115:4096/api/dapps/bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024/contracts && echo -``` - -JSON返回示例: -```js -{ - contracts: [{ - type: "1", - name: "core.deposit" // 系统内置合约,充值(从主链往dapp内进行资产充值),普通用户不能直接调用(受托人可以调用但不能通过其它节点的校验),当主链有type=9(intransfer)的交易类型发生时会自动调用该智能合约进行dapp充值 - }, - { - type: "2", - name: "core.withdrawal" // 系统内置合约,提现(将资产从dapp内转出到主链上) - }, - { - type: "3", - name: "core.transfer" // 系统内置合约,dapp内部转账,包括XAS和UIA - }, - { - type: "4", - name: "core.setNickname" // 系统内置合约,dapp内给地址设置昵称 - }, - { - type: "1000", - name: "cctime.postArticle" // dapp自定义合约,发布文章 - }, - { - type: "1001", - name: "cctime.postComment" // dapp自定义合约,发布评论 - }, - { - type: "1002", - name: "cctime.voteArticle" // dapp自定义合约,给文章进行投票 - }, - { - type: "1003", - name: "cctime.likeComment" // dapp自定义合约,对评论进行打赏 - }, - { - type: "1004", - name: "cctime.report" // dapp自定义合约,举报文章 - }], - success: true -} -``` - - - diff --git a/docs/asch_dapp_default_api_en.md b/docs/asch_dapp_default_api_en.md deleted file mode 100644 index 14c6121..0000000 --- a/docs/asch_dapp_default_api_en.md +++ /dev/null @@ -1,1146 +0,0 @@ -Table of Contents -================= - - - - -- [Asch Dapp Default API](#asch-dapp-default-api) - - [**1 Blocks**](#1-blocks) - - [**1.1 Get the Dapp Block Height**](#11-get-the-dapp-block-height) - - [**1.2 Get Dapp Block Data**](#12-get-dapp-block-data) - - [**2 Accounts**](#2-accounts) - - [**2.1 Get Information to a Single Account**](#21-get-information-to-a-single-account) - - [**3 Transactions**](#3-transactions) - - [**3.1 Signature**](#31-signature) - - [**3.1.1 Client signed transaction - more secure**](#311-client-signed-transaction---more-secure) - - [**3.1.1.1 Dapp Recharge**](#3111-dapp-recharge) - - [**3.1.1.2 Dapp Withdraw Money, Type=2**](#3112-dapp-withdraw-money-type2) - - [**3.1.1.2 Dapp Internal Transfer,Type=3**](#3112-dapp-internal-transfertype3) - - [**3.1.1.2 Dapp set a Nickname, Type=4**](#3112-dapp-set-a-nickname-type4) - - [**3.1.2 Server Side Signed Transaction (unsigned)**](#312-server-side-signed-transaction-unsigned) - - [**3.1.2.1 Dapp recharge**](#3121-dapp-recharge) - - [**3.1.2.2 Dapp Withdraw money, Type=2**](#3122-dapp-withdraw-money-type2) - - [**3.1.2.2 Dapp Internal Transfer, Type=3**](#3122-dapp-internal-transfer-type3) - - [**3.1.2.2 set a dapp nickname, type=4**](#3122-set-a-dapp-nickname-type4) - - [**3.2 Get unconfirmed transactions**](#32-get-unconfirmed-transactions) - - [**3.3 Get already confirmed transactions**](#33-get-already-confirmed-transactions) - - [**3.4 Get transaction details for one transaction by id**](#34-get-transaction-details-for-one-transaction-by-id) - - [**3.5 Obtain dapp transfer records**](#35-obtain-dapp-transfer-records) - - [**4 Smart Contract**](#4-smart-contract) - - [**4.1 Get all smart contracts for one Dapp**](#41-get-all-smart-contracts-for-one-dapp) - - [**4.2 Access Custom Dapp Interface**](#42-access-custom-dapp-interface) - - - - -# Asch Dapp Default API - -This documents describes the default API that every Dapp inherits from the asch-sandbox. - -## **1 Blocks** -### **1.1 Get the Dapp Block Height** -__API Endpoint:__ /api/dapps/dappID/blocks/height -__HTTP Header:__ GET -__Supported Format:__ urlencode - -Return Parameter: - -|Name |Type |Description | -|------ |----- |---- | -|success|boolean|Was the operation successful | -|height |integer|Dapp Block Height | - -Javscript Request: -```js -const axios = require('axios') - -let dappId = 'bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024' -let url = `http://localhost:4096/api/dapps/${dappId}/blocks/height` - -axios.get(url) - .then((response) => { - console.log(JSON.stringify(response.data)) - }) - .catch((error) => { - console.log(error.message) - }) -``` - -Bash Request: -```bash -curl -k -H "Content-Type: application/json" -X GET http://localhost:4096/api/dapps/bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024/blocks/height && echo -``` - -JSON Response -```json -{ - "height": 10, - "success": true -} -``` - - -### **1.2 Get Dapp Block Data** -__API Endpoint:__ /api/dapps/dappID/blocks -__HTTP Header:__ GET -__Supported Format:__ urlencode -__Endpoint Description:__ Get all blocks from the Dapp - -Request Parameters: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|limit |integer |No |Limit the number of results, Minimum: 0, Maximum: 100 | -|orderBy|string |No |Sort by a field of the table, e.g. height:desc (sorts after height descending) | -|offset|integer |No |Offset, Minimum: 0 | -|generatorPublicKey|string |No |The public key of the generator (delegate) of this block. | -|totalAmount|integer |No |Total amount of transactions, Minimum: 0, Maximum: 10000000000000000 | -|totalFee|integer |No |Total fee, Minimum: 0,Maximum: 10000000000000000 | -|previousBlock|string |No |Previous Block | -|height|integer |No |Block height | - -Return Parameter: - -|Name |Type |Description | -|------ |----- |---- | -|success|boolean |Was the request successful? | -|count|integer |The total number of blocks that met the query condition| -|blocks|Array |Each element of the returned array carries the data of one block, like id, height and other information| - - -Javascript Request: -```js -const axios = require('axios') - -let parameters = { - params: { - limit: 1 - } -} - -let dappId = 'bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024' -let url = `http://localhost:4096/api/dapps/${dappId}/blocks` - -axios.get(url, parameters) - .then((response) => { - console.log(JSON.stringify(response.data)) - }) - .catch((error) => { - console.log(error.message) - }) -``` - -Bash Request: -```bash -curl -k -H "Content-Type: application/json" -X GET http://localhost:4096/api/dapps/bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024/blocks?limit=1 && echo -``` - -JSON Response: -```json -{ - "blocks": [{ - "id": "451dd17f273ea5fbd240238178c1343b11031a1d309ee8b29e8b1a5838473ec6", - "timestamp": 0, - "height": 1, - "payloadLength": 103, - "payloadHash": "995f4749e1924af55f1cdefd202efd0b37b2aa70553982378c037bc6015d5634", - "prevBlockId": "", - "pointId": "", - "pointHeight": 0, - "delegate": "8065a105c785a08757727fded3a06f8f312e73ad40f1f3502e0232ea42e67efd", - "signature": "b1d0171494ce6c0621902c6005f7a85e15f3509a68ac6106b166abf711ced73efaeaf1eae0cdf594143854e27b417b253485cf98b3cc9f7aa967a929b717020b", - "count": 1 - }], - "count": 133, - "success": true -} -``` - -## **2 Accounts** -### **2.1 Get Information to a Single Account** -__API Endpoint:__ /api/dapps/dappID/accounts/:address -__HTTP Header:__ GET -__Supported Format:__ urlencode - -Request Parameter: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|address |string|Yes |Asch Address| - -Return Parameter: - -|Name |Type |Description | -|------ |----- |---- | -|success|boolean |Was the request successful? | -|account|json |All information regarding one account such as: Asset balances, is the address a delegate? and other information| - - -Javascript Request: -```js -const axios = require('axios') - -let address = 'ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M' - -let dappId = 'bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024' -let url = `http://localhost:4096/api/dapps/${dappId}/accounts/${address}` - -axios.get(url) - .then((response) => { - console.log(JSON.stringify(response.data)) - }) - .catch((error) => { - console.log(error.message) - }) -``` - -Bash Request: -```bash -curl -k -H "Content-Type: application/json" -X GET http://localhost:4096/api/dapps/bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024/accounts/ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M && echo -``` - -JSON Response: -```js -{ - "success": true, - "account": { - "balances": [{ - "currency": "XAS", // this account has a XAS balance (either through a recharge or an internal dapp transfer) - "balance": "10000000000" // 100 XAS - }], - "extra": null, - "isDelegate": false // is not a delegate - } -} -``` - - -## **3 Transactions** -### **3.1 Signature** -The HTTP Endpoint is divided into ___signed___ und ___unsigned___. Either will the transaction be signed locally and then send to the server (signed) or the secret must be send to the server and there the transaction will be signed (unsigned). - -#### **3.1.1 Client signed transaction - more secure** -Peer related API, you need to set the a header at a request. - - - key is magic: - - testnet: 594fe0f3 - - mainnet: 5f5b3cf5 - - key version is '' (empty) - -All write operations in Asch start with a transaction. -The transaction data is created through a library called [asch-js](https://github.com/AschPlatform/asch-js) and then published via a POST interface. -The HTTP-POST API specification are as follows: - -|Matter |Description | -|--- |--- | -|API Endpoint|/peer/transactions | -|payload|transaction data that were created with `asch-js`| -|HTTP Method|post/put etc.| -|Supported format|json | - -##### **3.1.1.1 Dapp Recharge** -__API Endpoint:__ /peer/transactions -__HTTP Header:__ POST -__Supported Format:__ json -Note: When the recharge occurs in the main chain (mainchain-transaction-type 6, intransfer) then the Dapp will automatically call the dapp smart contract number 1 for a dapp internal recharge. - -Info: -A Dapp Recharge is necessary if you want to spend XAS or an other currency in the Dapp. If you have 2000 XAS on your mainchain account that doesn't mean that you can spend 2000 XAS in the Dapp. You have to first "recharge" the Dapp with money. You send some XAS to the Dapp and the balance will be credited on your Dapp account. - -Request Parameter: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|transaction|json|Yes|A transaction generated with a function call to `aschJS.transfer.createInTransfer` | - - -Return Parameter: - -|Name |Type |Description | -|------ |----- |---- | -|success|boolean |Was the request successful? | -|transactionId|string |Transaction id| - -Javascript Request: -```js -// this account must have enough XAS on the mainchain -const aschJS = require('asch-js') -const axios = require('axios') - -let dappid = "bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024" -let secret = 'found knife gather faith wrestle private various fame cover response security predict' - -let currency = 'XAS' -let amount = 500 * 1e8 -let transaction = aschJS.transfer.createInTransfer(dappid, currency, amount, secret, secondSecret || undefined) - -let data = { - transaction: transaction -} - -let headers = { - headers: { - magic: '594fe0f3', - version: '' - } -} - -let url = 'http://localhost:4096/peer/transactions' - -axios.post(url, data, headers) - .then((response) => { - console.log(JSON.stringify(response.data)) - }) - .catch((error) => { - console.log(error.message) - }) - - -``` - -Bash Request -```bash -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":6,"amount":1000000000,"fee":10000000,"recipientId":null,"senderPublicKey":"2856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec4","timestamp":39721503,"asset":{"inTransfer":{"dappId":"bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024","currency":"XAS"}},"signature":"8cefc8fa933e4d5e8699828dc8cd5d1b4737ffa82175c744fd681bad0b1a6b68526e0783e85d7979f894fc38850bd2ed0a983ce3cb3f5d16b68fd37dfb9dfb0a","id":"4b580f8f61f4586920a4c0d37b6fad21daf3453fe9ccc5426c2cae7a263c160c"}}' http://localhost:4096/peer/transactions && echo -``` - -JSON Response: -```js -{ - "success": true, - "transactionId": "4b580f8f61f4586920a4c0d37b6fad21daf3453fe9ccc5426c2cae7a263c160c" -} -``` - -##### **3.1.1.2 Dapp Withdraw Money, Type=2** -__API Endpoint:__ /api/dapps/dappID/transactions/signed -__HTTP Header:__ PUT -__Supported Format:__ json - -Info: -This operation is the opposite to [**3.1.1.1 Dapp Recharge**](#3111-dapp-recharge). This operation withdraws money from the Dapp to the mainchain. - - -Request Parameter: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|dappID|string|Yes|Dapp Id| -|transaction|json|Yes|Transaction data generated by a function call to `aschJS.dapp.createInnerTransaction`| - - -Return Parameter: - -|Name |Type |Description | -|------ |----- |---- | -|success|boolean |Was the request successful? | -|transactionId|string |Transaction Id| - - -Example: -```js -// you need at least 1 CCTime.XCT on your sidechain account -const aschJS = require('asch-js') -const axios = require('axios') - -let fee = String(0.1 * 100000000) -let type = 2 // withdraw money to mainchain -let options = { - fee: fee, - type: type, - args: JSON.stringify(['CCTime.XCT', '100000000']) -} -let secret = "elite brush pave enable history risk ankle shrimp debate witness ski trend" -let transaction = aschJS.dapp.createInnerTransaction(options, secret) - -let dappId = 'b12906bcb8de449e8d41fada9227f1cde206daca17f9bc366666c206ad4d7e20' - -let url = `http://localhost:4096/api/dapps/${dappId}/transactions/signed` -let data = { - transaction: transaction -} -let headers = { - magic: '594fe0f3', - version: '' -} - -axios.put(url, data, headers) - .then((response) => { - console.log(JSON.stringify(response.data)) - }) - .catch((error) => { - console.log(error.message) - }) -``` - -Bash Request: -```bash -# The Money withdraw transaction (type=2) is send to the server -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X PUT -d '{"transaction":{"fee":"10000000","timestamp":40384202,"senderPublicKey":"aa4e4ac1336a1e9db1ee5ce537a59d3fcb0f068cb4b25aac9f48e0e8bc6259c9","type":2,"args":"[\"CCTime.XCT\", \"100000000\"]","signature":"05dba744705fd1dbc1854b415392364cdbae11778671be8eb5fdbce57855a87b3dde5bf2d0219059411253fb304497758422c8d1546ec45eb5521b4a6577d507"}}' http://localhost:4096/api/dapps/d352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1/transactions/signed && echo -``` - -JSON Response: -```js -{ - "success": true, - "transactionId": "8bcae742206bf236214b9972efaca0bbe29f3703b4055a14cc8b095546880dc4" -} -``` - -##### **3.1.1.2 Dapp Internal Transfer,Type=3** -__API Endpoint:__ /api/dapps/dappID/transactions/signed -__HTTP Header:__ PUT -__Supported Format:__ JSON - -Info: -This operation transfers money (XAS or other currencies) only between Dapp accounts. - -Request Parameter: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|dappID|string|Yes|Dapp Id| -|transaction|json|Yes|Transaction data generated by a function call to `aschJS.dapp.createInnerTransaction`| - - -Return Parameter: - -|Name |Type |Description | -|------ |----- |---- | -|success|boolean |Was the request successful?| -|transactionId|string |Internal Transfer Transaction Id| - -Example: -```js -// you need at least 1 CCTime.XCT on your sidechain account -const aschJS = require('asch-js') -const axios = require('axios') - -let fee = String(0.1 * 1e8) -let type = 3 // internal transfer -let options = { - fee: fee, - type: type, - args: JSON.stringify(['CCTime.XCT', '100000000', 'A6H9rawJ7qvE2rKwQfdtBHdeYVehB8gFzC']) -} -let secret = 'elite brush pave enable history risk ankle shrimp debate witness ski trend' -let transaction = aschJS.dapp.createInnerTransaction(options, secret) - -let dappId = 'd352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1' -let url = `http://localhost:4096/api/dapps/${dappId}/transactions/signed` -let data = { - transaction: transaction -} -let headers = { - magic: '594fe0f3', - version: '' -} - -axios.put(url, data, headers) - .then((response) => { - console.log(JSON.stringify(response.data)) - }) - .catch((error) => { - console.log(error.message) - }) -``` - -Bash Response: -```bash -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X PUT -d '{"transaction":{"fee":"10000000","timestamp":40387708,"senderPublicKey":"aa4e4ac1336a1e9db1ee5ce537a59d3fcb0f068cb4b25aac9f48e0e8bc6259c9","type":3,"args":"[\"CCTime.XCT\", \"100000000\", \"A6H9rawJ7qvE2rKwQfdtBHdeYVehB8gFzC\"]","signature":"e2364534b8c4b0735a85c68ba17fddf5321fc48af04d483ad05531d4993058eaa35ff44d913a03b6d7278890ff7f42435f8313e08ce70c523dfc256b4de9e303"}}' http://localhost:4096/api/dapps/d352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1/transactions/signed && echo -``` - -JSON Response: -```json -{ - "success": true, - "transactionId": "e2687a471ac2ddbbdd919266e58b0b652c55f74402b27be850d767fa44162c79" -} -``` - -##### **3.1.1.2 Dapp set a Nickname, Type=4** -__API Endpoint:__ /api/dapps/dappID/transactions/signed -__HTTP Header:__ PUT -__Supported Format:__ json - -Request Parameter: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|dappID|string|Yes|Dapp Id| -|transaction|json|Yes|Transaction data generated by a function call to `aschJS.dapp.createInnerTransaction`| - - -Return Parameter: - -|Name |Type |Description | -|------ |----- |---- | -|success|boolean |Was the request successful? | -|transactionId|string |The TransactionId for the set nickname operation| - -Javascript Example: -```js -const aschJS = require('asch-js') -const axios = require('axios') - -let fee = String(0.1 * 1e8) -let type = 4 // set nickname -let options = { - fee: fee, - type: type, - args: JSON.stringify(['Nickname']) -} - -let secret = 'elite brush pave enable history risk ankle shrimp debate witness ski trend' -let transaction = aschJS.dapp.createInnerTransaction(options, secret) - -let dappId = 'd352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1' -let url = `http://localhost:4096/api/dapps/${dappId}/transactions/signed` -let data = { - transaction: transaction -} -let headers = { - magic: '594fe0f3', - version: '' -} - -axios.put(url, data, headers) - .then((response) => { - console.log(JSON.stringify(response.data)) - }) - .catch((error) => { - console.log(error.message) - }) -``` -Bash Request: -```bash -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X PUT -d '{"transaction":{"fee":"10000000","timestamp":40388287,"senderPublicKey":"aa4e4ac1336a1e9db1ee5ce537a59d3fcb0f068cb4b25aac9f48e0e8bc6259c9","type":4,"args":"[\"Nickname\"]","signature":"be08cdb2f4d1a0f2f2e5b02e33e67fdf43e403703ce35cb42a2dc7338c7a352adca56dc61e3be0fedc1727c1adc0101f1a9e1a3e67ac0623602bf872deb80802"}}' http://localhost:4096/api/dapps/d352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1/transactions/signed && echo -``` - -JSON Response: -```json -{ - "success": true, - "transactionId": "7teae742206bf236214b9972efaca0bbe29f3703b4055a14cc8b095546880dc4" -} -``` - -#### **3.1.2 Server Side Signed Transaction (unsigned)** -##### **3.1.2.1 Dapp recharge** -##### **3.1.2.2 Dapp Withdraw money, Type=2** -__API Endpoint:__ /api/dapps/dappId/transactions/unsigned -__HTTP Header:__ PUT -__Supported Format:__ JSON - -Info: -This operation is the opposite to the `Dapp recharge`. This operation withdraws money from the Dapp to the mainchain. - -Request Parameter: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|secret|string|Yes|Asch secret| -|fee|string|Yes|Transaction fee, currently fixed at 10000000 | -|type|integer|Yes|Smart contract type | -|args|string Array|Yes|The string Array must contain the contract type| - - -Return Parameter: - -|Name |Type |Description | -|------ |----- |---- | -|success|boolean |Was the request successful? | -|transactionId|string |Withdrawal transaction Id | - -Example: -```js -const axios = require('axios') - -let headers = { - magic: '594fe0f3', - version: '' -} - -let dappId = 'd352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1' -let url = `http://localhost:4096/api/dapps/${dappId}/transactions/unsigned` - -let data = { - secret: 'elite brush pave enable history risk ankle shrimp debate witness ski trend', - fee: '10000000', - type: 2, // withdraw money to mainchain - args: JSON.stringify(['CCTime.XCT', '100000000']) -} - -axios.put(url, data, headers) - .then((result) => { - console.log(JSON.stringify(result.data)) - }) - .catch((error) => { - console.log(error.message) - }) -``` - -```bash -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X PUT -d '{"secret":"elite brush pave enable history risk ankle shrimp debate witness ski trend","fee":"10000000","type":2,"args":"[\"CCTime.XCT\",\"100000000\"]"}' 'http://localhost:4096/api/dapps/d352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1/transactions/unsigned' && echo - -``` -JSON Response: -```json -{ - "success": true, - "transactionId": "f59d365cbc8ea29f5d3798af795dc66dbdda00e2f1ae6677d5c7239180f3e98a" -} -``` - -##### **3.1.2.2 Dapp Internal Transfer, Type=3** -__API Endpoint:__ /api/dapps/dappId/transactions/unsigned -__HTTP Header:__ PUT -__Supported Format:__ JSON - -Info: See [**3.1.1.2 Dapp Internal Transfer,Type=3**](#3112-dapp-internal-transfertype3) - -Request Parameter: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|secret|string|Yes|Asch secret | -|fee|string|Yes| | -|type|integer|Yes|The number of the smart contract | -|args|string array|Yes|The corresponding contract number needs to be passed in | - - -Return Parameter: - -|Name |Type |Description | -|------ |----- |---- | -|success|boolean |Was the request successful? | -|transactionId|string |Internal transfer transacation Id| - -Javascript Request: -```js -const axios = require('axios') - -let headers = { - magic: '594fe0f3', - version: '' -} - -let data = { - secret: 'elite brush pave enable history risk ankle shrimp debate witness ski trend', - fee: '10000000', - type: 3, // internal transfer - args: JSON.stringify(['CCTime.XCT', '1000000000', 'ADimyhJa99XFzVrbnTYsCqPB4TKQNdjCWw']) -} - -let dappId = 'd352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1' -let url = `http://localhost:4096/api/dapps/${dappId}/transactions/unsigned` - -axios.put(url, data, headers) - .then((result) => { - console.log(JSON.stringify(result.data)) - }) - .catch((error) => { - console.log(error.message) - }) -``` - -Bash Request: -```bash -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X PUT -d '{"secret":"elite brush pave enable history risk ankle shrimp debate witness ski trend","fee":"10000000","type":3,"args":"[\"CCTime.XCT\",\"1000000000\",\"ADimyhJa99XFzVrbnTYsCqPB4TKQNdjCWw\"]"}' 'http://localhost:4096/api/dapps/d352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1/transactions/unsigned' && echo -``` - -JSON Response: -```json -{ - "success": true, - "transactionId": "96d886b7d724e6a00cc8c52c24b674ec8a9fc7fd8145a326bf69983fdc74a006" -} -``` - -##### **3.1.2.2 set a dapp nickname, type=4** -__API Endpoint:__ /api/dapps/dappId/transactions/unsigned -__HTTP Header:__ PUT -__Supported Format:__ JSON - -Request Parameter: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|secret|string|Yes|asch password | -|fee|string|Yes|Transaction fee, currently 10000000| -|type|integer|Yes|Smart contract number | -|args|string array|Yes|Pass the nickname as a string in an array, see further below for example | - - -Return Parameter: - -|Name |Type |Description | -|------ |----- |---- | -|success|boolean |Was the request successful?| -|transactionId|string |Set nickname transaction id| - -Javascript Request: -```js -const axios = require('axios') - -let headers = { - magic: '594fe0f3', - version: '' -} - -let data = { - secret: 'minor borrow display rebel depart core buzz right distance avocado immense push', - fee: '10000000', - type: 4, // set nickname - args: JSON.stringify(['zhenxi']) -} - -let dappId = 'd352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1' -let url = `http://localhost:4096/api/dapps/${dappId}/transactions/unsigned` - -axios.put(url, data, headers) - .then((response) => { - console.log(JSON.stringify(response.data)) - }) - .catch((error) => { - console.log(error.message) - }) -``` - -Bash Request: -```bash -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X PUT -d '{"secret":"minor borrow display rebel depart core buzz right distance avocado immense push","fee":"10000000","type":4,"args":"[\"zhenxi\"]"}' 'http://localhost:4096/api/dapps/d352263c517195a8b612260971c7af869edca305bb64b471686323817e57b2c1/transactions/unsigned' && echo -``` - -JSON Response: -```json -{ - "success": true, - "transactionId": "7b5d9d13cf718ee28efde6bae85fbefbcd0eca3d6c0c6fff1421a1102d730669" -} -``` - -### **3.2 Get unconfirmed transactions** -__API Endpoint:__ /api/dapps/dappID/transactions/unconfirmed -__HTTP Header:__ GET -__Supported Format:__ urlencode - -Return Parameter: - -|Name |Type |Description | -|------ |----- |---- | -|success|boolean |Was the request successful? | -|transactions|array |A list of unconfirmed transactions| - - -Javascript Example: -```js -const axios = require('axios') - -let dappId = 'bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024' -let url = `http://localhost:4096/api/dapps/${dappId}/transactions/unconfirmed` - -axios.get(url) - .then((response) => { - console.log(JSON.stringify(response.data)) - }) - .catch((error) => { - console.log(error.message) - }) -``` - -Bash Example: -```bash -curl -k -X GET http://localhost:4096/api/dapps/bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024/transactions/unconfirmed && echo -``` - -JSON Response: -```json -{ - "transactions": [], - "success": true -} -``` - -### **3.3 Get already confirmed transactions** -__API Endpoint:__ /api/dapps/dappID/transactions -__HTTP Header:__ GET -__Supported Format:__ urlencode - -Request Parameter: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|senderId |string |No|Address of sender | -|type |interger |No|contract number | -|limit |interger |No|Limit the result set, default is 100| -|offset |interger |No|Offset | - - -Return Parameter: - -|Name |Type |Description | -|------ |----- |---- | -|success|boolean |Was the request successful?| -|transactions|array |List of confirmed transactions| -|count|integer |The total number of transactions that met the query conditions| - - -Javascript Request: -```js -const axios = require('axios') - -const parameters = { - params: { - senderId: 'AJTGR8EGsprrF7r63D2XLDftGAKUu1Ucjn' - } -} - -let dappId = 'bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024' -let url = `http://localhost:4096/api/dapps/${dappId}/transactions` - -axios.get(url, parameters) - .then((response) => { - console.log(JSON.stringify(response.data)) - }) - .catch((error) => { - console.log(error.message) - }) -``` - -Bash Request: -```bash -curl -k -X GET http://localhost:4096/api/dapps/bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024/transactions?senderId=AJTGR8EGsprrF7r63D2XLDftGAKUu1Ucjn && echo -``` - -JSON Response: -```json -{ - "count": 1, - "success": true, - "transactions": [{ - "id": "b12b144b3dbb76b70cd62f97e3d3b0606d97c0f402bba1fb973dd2d3ab604a16", - "timestamp": 0, - "senderId": "AJTGR8EGsprrF7r63D2XLDftGAKUu1Ucjn", - "senderPublicKey": "27823f51a3dddd475943fb8142380d2f8722b0f6c651f6ac37930b63666c7803", - "fee": "0", - "signature": "22739bb762ff0135a0c4199507e3c45a8615c467bfeb4efa5110802033959698588e39b76d037445e02959ee67b483ac4d24f12304181f4955871cdcd28e3001", - "type": 3, - "args": "[\"CNY\",\"100000000000000\",\"A8QCwz5Vs77UGX9YqBg9kJ6AZmsXQBC8vj\"]", - "height": 1 - }] -} -``` - -### **3.4 Get transaction details for one transaction by id** -__API Endpoint:__ /api/dapps/dappID/transactions/:id -__HTTP Header:__ GET -__Supported Format:__ urlencode - -Request Parameter: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|id |string |Yes|Transaction Id| - -Return Parameter: - -|Name |Type |Description| -|------ |----- |---- | -|success|boolean |Was the request successful?| -|transaction|object |The requested transaction| - - -Javascript Request: - -```js -const axios = require('axios') - -let transactionId = '7088c67edd43326276453b833727677df6f312271b824564a6a934371265f0dc' - -let dappId = 'bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024' -let url = `http://localhost:4096/api/dapps/${dappId}/transactions/${transactionId}` - -axios.get(url) - .then((response) => { - console.log(JSON.stringify(response.data)) - }) - .catch((error) => { - console.log(error.message) - }) -``` - -Bash Request: - -```bash -curl -k -X GET http://localhost:4096/api/dapps/bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024/transactions/7088c67edd43326276453b833727677df6f312271b824564a6a934371265f0dc && echo -``` - -JSON Response: -```json -{ - "success": true, - "transaction": { - "id": "7088c67edd43326276453b833727677df6f312271b824564a6a934371265f0dc", - "timestamp": 39709980, - "senderId": "ADYGpYHmgkbukqByZ2JzwFXZM6wYfMXCaR", - "senderPublicKey": "55ad778a8ff0ce4c25cb7a45735c9e55cf1daca110cfddee30e789cb07c8c9f3", - "fee": "0", - "signature": "bd51295c3373da2a92c77b6a96a0edbda75cdcde5fd7824ff326c366ed0ec5778e1d02e7d9c280a219d6c815d9bfdbc2d03bb960a0f5d8d35458e4bda87d6104", - "type": 1, - "args": "[\"XAS\",\"10000000000\",\"2f1db0014483ffef85289e086af321e374944668dd7fb4f156c70609276ed903\",\"ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M\"]", - "height": 637 - } -} -``` - -### **3.5 Obtain dapp transfer records** -__API Endpoint:__ /api/dapps/dappID/transfers -__HTTP Header:__ GET -__Supported Format:__ urlencode - -Info: -Get the records of sended or received transfers. - -Request Parameter: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|ownerId |string |No|At least one of the following have to exists: Sender-Address, OwnerId, Currency| -|currency |string |No|At least one of the following have to exist: Token name, OwnerId, Currency| -|limit |interger |No|Limits the return list, default is 10| -|offset |interger |No|Offset, default 0| - -Return Parameter: - -|Name |Type |Description| -|------ |----- |---- | -|success|boolean|Was the request successful?| -|transfers|array|Get the transfers that met the query| -|count|integer|The total number of transfers that met the query conditions| - -Javascript Request: -```js -const axios = require('axios') - -let dappId = 'bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024' -let url = `http://localhost:4096/api/dapps/${dappId}/transfers` - -let parameters = { - ownerid: 'ADYGpYHmgkbukqByZ2JzwFXZM6wYfMXCaR' -} - -axios.get(url, parameters) - .then((response) => { - console.log(JSON.stringify(response.data)) - }) - .catch((error) => { - console.log(error.message) - }) -``` - -Bash Request: -```bash -curl -k -X GET http://localhost:4096/api/dapps/bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024/transfers?ownerid=ADYGpYHmgkbukqByZ2JzwFXZM6wYfMXCaR && echo -``` - -JSON Response: -```json -{ - "success": true, - "count": 1, - "transfers": [{ - "tid": "b12b144b3dbb76b70cd62f97e3d3b0606d97c0f402bba1fb973dd2d3ab604a16", - "senderId": "AJTGR8EGsprrF7r63D2XLDftGAKUu1Ucjn", - "recipientId": "A8QCwz5Vs77UGX9YqBg9kJ6AZmsXQBC8vj", - "currency": "CNY", - "amount": "100000000000000", - "t_timestamp": 0, - "t_type": 3, - "t_height": 1 - }] -} -``` - -## **4 Smart Contract** -### **4.1 Get all smart contracts for one Dapp** -__API Endpoint:__ /api/dapps/dappID/contracts -__HTTP Header:__ GET -__Supported Format:__ urlencode - -Return Parameter: - -|Name |Type |Description | -|------ |----- |---- | -|success|boolean |Was the request successful?| -|contracts|array |Each element is a object with the following properties: type (number), contract name (string)| - - -Javascript Request: -```js -const axios = require('axios') - -let dappId = 'bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024' -let url = `http://localhost:4096/api/dapps/${dappId}/contracts` - -axios.get(url) - .then((response) => { - console.log(JSON.stringify(response.data)) - }) - .catch((error) => { - console.log(error.message) - }) -``` - -Bash Request: -```bash -curl -k -H "Content-Type: application/json" -X GET http://localhost:4096/api/dapps/bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024/contracts && echo -``` - -JSON Response: -```js -{ - success: true, - contracts: [{ - type: "1", - name: "core.deposit" // built-in contract, recharge (from the main chain to dapp within the asset reload), ordinary users can not be called directly (the trustee can call this contract but the operation can not be verified by other nodes), when the main chain transaction-type=9 (intransfer) the smart contract will automatically call app recharge - }, - { - type: "2", - name: "core.withdrawal" // built-in contract, this operation transfers the asset from the dapp-sidechain to the mainchain - }, - { - type: "3", - name: "core.transfer" // built-in contract, dapp internal transfers including XAS and UIA - }, - { - type: "4", - name: "core.setNickname" // built-in contract, set nickname for dapp address - }, - { - type: "1000", - name: "cctime.postArticle" // custom contract, publish article - }, - { - type: "1001", - name: "cctime.postComment" // custom contract, post a comment - }, - { - type: "1002", - name: "cctime.voteArticle" // custom contract, vote for an article - }, - { - type: "1003", - name: "cctime.likeComment" // custom contract, reward for comments - }, - { - type: "1004", - name: "cctime.report" // custom contract, report articles - }] -} -``` - - -### **4.2 Access Custom Dapp Interface** - -To borrow an example from [aschplatform/cctime](https://github.com/AschPlatform/cctime/blob/master/interface/index.js). It is possible to register custom API endpoints for your Dapp. This makes especially sense if you create a new entity like `articles` (which becomes a table in the sidechain SQL database). Through the new custom api endpoint your frontend can access articles. - -![alt](./assets/dapp/custom_api_example.png) - -```js -// filename interface/index.js - -app.route.get('/articles/:id', async (req) => { - let id = req.params.id - let key = 'article_' + id - if (app.custom.cache.has(key)) { - return app.custom.cache.get(key) - } - let article = await app.model.Article.findOne({ - condition: { id: id } - }) - if (!article) { - throw new Error('Article not found') - } - if (article.reports >= 3) { - throw new Error('Article not allowed') - } - let account = await app.model.Account.findOne({ - condition: { address: article.authorId } - }) - if (account) { - article.nickname = account.str1 - } - let result = { article: article } - app.custom.cache.set(key, result) - return result -}) - -// ommitted other functions -``` - - - -This API Endpoint exposes articles by id. - -__API Endpoint:__ /api/dapps/dappID/articles/:id -__HTTP Header:__ GET - -Request Parameter: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|id |integer |Yes|The id of the desired article| - - -Return Paramter: - -|Name |Type |Description | -|------ |----- |---- | -|id|number |Auto incremented intenger article identifier | -|tid|string |TransactionId, id of transaction in which the article was published | -|authorId|string|Asch Address of publisher| -|timestamp|number|Timestamp of article publication| -|title|string|Title of article| -|url|string|Url that points to other ressource on the internet | -|text|string|Text of article| -|tags|string|tags under which the article should be categorized| -|votes|number|How many times other users voted for the article| -|comments|number|How many comments do this article have?| -|reports|number|How often was this article reported?| - - - -Javascript Request: -```js -const axios = require('axios') - -let articleId = 33 - -let dappId = 'bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024' -let url = `http://localhost:4096/api/dapps/${dappId}/articles/${articleId}` - -axios.get(url) - .then((response) => { - console.log(JSON.stringify(response)) - }) - .catch((error) => { - console.log(error.message) - }) -``` - -JSON Response: -```json -{ - "id": "33", - "tid" "e4a95e133b76af2c1c6bf55ecb8ba8d6d007fc5d1bb353edac688577f0ca19a0", - "authorId": "AHMCKebuL2nRYDgszf9J2KjVZzAw95WUyB", - "timestamp": "62515470", - "title": "How to develop Dapps", - "url": null, - "text": "This is a very long text...", - "tags": "sidechain,dapps,aschplatform", - "votes": 58, - "comments": 4, - "reports": 0 -} -``` diff --git a/docs/asch_dapps_introduction.md b/docs/asch_dapps_introduction.md deleted file mode 100644 index 48adc2d..0000000 --- a/docs/asch_dapps_introduction.md +++ /dev/null @@ -1,62 +0,0 @@ -# Asch Dapp开发介绍 - -我们在白皮书里提到过,asch使用的是不同于以太坊和比特币的侧链架构,dapp是运行在侧链上的,每条侧链对应一个dapp。(Asch主链类比IOS生态系统,每个节点都是一部iphone,所有的dapp组成了appstore,每个节点可以自由选择安装哪些dapp) - -## 侧链的独立性 - -侧链架构的好处是代码和数据独立,不增加主链的负担,避免数据过度膨胀,实际上是一种天然的分片机制。 -侧链有独立的区块链(具有和一般区块链相同的特征属性),有独立的受托人或者说见证人,同时也有独立的节点网络,就是说一个侧链产生的区块只会在所有安装了该侧链的节点之间进行广播。 - -独立性既是优点,也是缺点。开发者完成了dapp的开发工作之后,还要考虑运维,也就是说要寻找足够的节点来运行它(Asch侧链默认用的DPOS共识算法,对运行节点的受托人会给予一定的token奖励,类比BTC的挖矿,所以找人去运行dapp是很容易的事情),否则难以维持足够的安全性。 -从这一点来看,与以太坊相比,是缺陷,以太坊上一旦发布一个dapp,所有的节点都可以为它工作,并为它提供安全保障。 - -## 侧链的灵活性 - -但是侧链架构依然有存在的必要性,因为并非所有的应用都需要那么高的安全性。Asch给用户提供了一种可以选择的灵活性。 -比方说,假设asch有1000个节点,那么其中有的dapp比较重要,需要500个节点来运行它,有的dapp不那么重要,可能只需要100个节点,这完全是由用户和开发者决定的。 -在以太坊上,则只能选择一种,即全部节点都来运行它。据说以太坊也打算实现一种分片的机制,实际上这在asch系统中是一个早就解决了的问题。 -另外,对于比较重要的、安全性要求较高的应用,我们依然可以选择在主链上开发(就是像以太坊那样dapp运行在所有的Asch主链的节点上),但是不可能对所有开发者开放这种权力,还是为了避免主链的膨胀和不可控(DAO事件)。 - -侧链的灵活性还表现在,所有的区块链参数是可以定制的,简单的比如区块间隔、区块奖励、交易费的去向等,高级用户还可以修改共识算法(默认是DPOS共识算法)。 -不过最重要的还是业务逻辑,侧链上可以轻易的开发出与你的业务相关的交易类型或者智能合约。 -这一点是与侧链的发明者blockstreams不同,blockstreams的侧链,只是一个不同的货币系统而已,开发新型交易和智能合约很不容易。 - -如下图所示 -黑色的圆圈代表一个节点,64个节点组成了主链的网络。红色方框之内的是1号侧链,其侧链网络是由12个节点组成。蓝色方框之内的是2号侧链,其网络是由36个节点组成。 - -![sidechain deploy architecture](./assets/sidechain-deploy.png) - -## 主链与侧链的互利关系 - -Asch的主链与侧链之间是互惠互利的关系,asch为侧链提供基础设施,比如数据库写入的api,网络通讯api,加密api等等,侧链则可以为asch主链补充更多的节点,以壮大整个系统。 -侧链的开发者不需要提供所有的机器,可以利用已经存在主链节点,只需要节点主人安装该应用即可。 -另外,主链的代币XAS可以转入侧链中,由于XAS可以在交易所交易,就相当于为侧链的资产提供了一种价值的媒介。 -开发者在侧链发行一种资产后,可以直接与XAS兑换,不需要考虑交易平台的问题。 - -## 解决生产力问题 - -我们在[ASCH_DAPP_SDK](./asch_sdk_api.md)中为侧链提供了一套模板,或者说脚手架,也可以叫做开发框架,侧链的大部分底层功能都是写好的,dapp开发者只需要关心具体的业务逻辑,在这一点上,与以太坊的dapp开发难度相当。 -Asch的侧链框架使用的语言是nodejs,我们内置了不少常用的库让开发者直接使用,当然开发者也可以自行安装所需要的,有一个庞大的javascript社区作为后盾。 - -下面是asch内置的模块 - -![inbuilt modules](./assets/inbuilt-modules.png) - -## 解决安全问题 - -这里的安全问题与上面提到的因为节点不足导致的问题不一样,这里说的安全问题是指侧链代码对安装者造成侵犯的问题。 -我们希望每一个asch节点都能安装一个侧链,而且asch节点的主人无需信任侧链的开发者。这就需要提供一种安全防范的措施,比如,防止侧链代码肆意读取文件系统、进行网络操作。 -在asch系统中,侧链代码会以子进程的方式启动,子进程首先加载一个使用沙箱机制隔离的javascript虚拟机,这个js虚拟机就是没有```require```以及任何多余模块的裸体虚拟机。 -然后我们为这个虚拟机植入一个定制的```require```和一些常用且安全的模块, 最后再加载侧链的代码。 -我们还通过进程间通讯的方式提供一系列的api。 -这样,侧链的框架就拥有了足够多的api,同时侧链的安装者也没有任何风险。 - -![process structure](./assets/process-structure.png) - -## 实例教程 - -接下来我们会提供一个由浅入深的教程,帮助开发者快速入门。 - -- [Dapp开发教程一 Asch Dapp Hello World](./dapp_docs/1_hello.md) - 这个文档会教你如何创建并发布一个基础的侧链应用,并介绍侧链框架的源码结构 -- [Dapp案例一 CCTime的后端源码](https://github.com/AschPlatform/cctime) 这是基于[ASCH_DAPP_SDK](./asch_sdk_api.md)开发的第一个Dapp,开发者可以当做示例代码阅读,[前端代码链接](https://github.com/AschPlatform/cctime-frontend) \ No newline at end of file diff --git a/docs/asch_dapps_introduction_de.md b/docs/asch_dapps_introduction_de.md deleted file mode 100644 index 5edb63d..0000000 --- a/docs/asch_dapps_introduction_de.md +++ /dev/null @@ -1,85 +0,0 @@ -# Einführung in die Asch Dapp Entwicklung -Wie bereits im Whitepaper erwähnt, verwendet Asche eine Sidechain-Architektur, welche sich von Währungen wie Ethereum oder Bitcoin dadurch entscheidet, dass die dezentralen Applikationen (Dapp) auf Sidechains laufen. Eine Sidechain für jede Dapp. - -## Die Unabhängigkeit einer Sidechain - -Die Vorteile eines Sidechain-Frameworks ist, dass der Programmcode und die Daten unabhängig von der Hauptchain sind. So bleiben die Daten an einem Ort und nicht über die ganze Blockchain verteilt sind. Dies könnte man als natürlichen Partitionsmechanismus bezeichnen. -Eine Sidechain hat ihre eigene Blockchain, ihre eigenen Delegate und ihre eigenen Knoten. Dies bedeutet, dass ein auf der Sidechain erzeugter Block zu allen Knoten der Sidechain gesendet werden kann. - -Jede Münze hat zwei Seiten, so auch die Unabhängigkeit der Sidechain. Wenn eine Dapp fertig entwickelt ist, dann muss auch die Wartung als Kriterium herangezogen werden. Um die Sicherheit der Dapp zu gewährleisten müssen genug Knoten zur Ausführen der Dapp zur Verfügung stehen. - -Von dieser Perspektive ist der Sidechain-Mechanismus nicht so gut wie bei Ethereum. Ist eine Dapp erst einmal auf Ethereum deployed, so können alle Knoten für diese arbeiten als auch die Sicherheit garantieren. - - -## Die Flexibilität der Sidechain - -Der Sidechain-Mechanismus hat seine Stärken, denn nicht jede Applikation benötigt das größte Maß an Sicherheit. Asch, welches auf dem Sidechain-Mechanismus basiert, kann seinen Nutzern eine größere Flexibilität bieten. - -Dies soll anhand eines Beispiels gzeigt werden: Angenommen es gibt 1000 Knoten im System. Eine kritische Dapp benötigt 500 dieser Knoten. Eine andere, nicht so kritische Dapp benötigt nur 100 Knoten. Dies liegt ganz im Ermessen der Benutzer und Entwickler. - -Im Vergleich dazu bietet Ethereum nur eine Möglichkeit: Eine Applikation läuft auf allen Knoten. Es wird jedoch gesagt, dass in Zukunft Ethereum auch eine Möglichkeit zur Partitionierung von Dapps bekommt. Eine Funktion welche Asch bereits besitzt. - -Für Anwendungen welche ein Höchstmaß an Sicherheit benötigen, bietet Asch die Möglichkeit, dass diese Dapps auf der Mainchain ausgeführt werden. Dieses Privileg kann jedoch nicht allen Entwicklern zugänglich gemacht werden. Dies liegt einerseits daran, dass dann eine Applikation beliebig groß wachsen kann, andererseits wäre die Unsicherheit zu groß (siehe [DAO Problem](https://en.wikipedia.org/wiki/The_DAO_(organization)#Risks)). - -Die Flexibilität einer Sidechain lässt sich auch daran zeigen, dass alle Parameter ihrer Blockchain konfigurierbar sind. Es können z.B.: Block-Interval, Block-Belohnung, Transaktionsgebühr oder sogar der Konsensus-Algorithmus geändert werden. - - -Das Wichtigste ist die Business-Logik, welche sich leicht auf der Sidechain entwickeln lässt, egal ob es sich um eine Business-Transaktion handelt oder um einen smart contract. - -Beachte, dass Asch sich von [Blockstream](https://en.wikipedia.org/wiki/Blockstream) unterscheidet. Blockstream hat die Sidechaintechnologie entwickelt, ist aber auch zugleich der Betreiber ihrer eigenen Sidechain auf der es aber schwierig ist ein neues Transaktionssystem und neue intelligente Verträge zu entwickeln. - -Schauen wir uns den folgendne Absatz an: - -Jeder Kreis repräsentiert einen Knoten im System. Alle 64 Knoten bilden das Netzwerk der Mainchain. Im roten Rahmen ist die Sidechain Nr.1, welche aus 12 Knoten besteht. Sidechain Nr.2 wird durch den blauen Rahmen repräsentiert und besteht aus 36 Knoten. - -![sidechain deploy architecture](./assets/sidechain-deploy.png) - -## Die Wechselwirkung zwischen Mainchain und Sidechain - -Es existiert eine wechselseitige Beziehung zwischen der Asch Mainchain und den Sidechains. Asch bietet jeder Sidechain den Zugriff auf verschiedene APIs: Datenbank, Netzwerkkommunikation als auch Verschlüsselung. Ein positiver Nebeneffekt der Sidechain ist, dass diese zusätzliche Knoten zum Netzwerk hinzufügt werden und somit das ganze Asch System verstärken. - -Zwangsläufig muss ein Entwickler nicht alle Knoten die er für eine Sidechain benötigt zur Verfügung stellen. Es besteht auch die Möglichkeit, dass Besitzer von bestehenden Knoten die neue entwickelte Applikation auf ihrem Knoten ausführen. - -XAS, die Währung der Asch Mainchain, kann zu jeder Sidechain transferiert werden. XAS wird auf Crypto-Marktplätzen gehandelt. Die Währung einer Sidechain muss nicht zwangsläufig auf einem Crypto-Marktplatz gehandelt werden, sie kann einfach gegen XAS getauscht werden. So hat man als neue Sidechain nicht mit dem "wie bekomme ich meine Währung auf den Marktplatz?" Problem zu kämpfen. Die neue Währung kann direkt in XAS gewechselt werden. - -## Produktivität - -Wir bieten eine Fülle von Vorlagen (oder besser gesagt ein Gerüst zum Entwickeln) für die Entwicklung von Sidechains. Die größten Entwicklungsaufgaben an den Sidechains wurden bereits bewältig. Als Entwickler reicht es, dass man sich nur auf die Business-Logik konzentriert. Zu diesem Zeitpunkt ist das Entwickeln auf Asch gleich schwer wie auf Ethereum. - -Zum Entwickeln von Sidechain wird die Sprache Node.js verwendet. Darauf basierend stellen wir weitere Bibliotheken für Entwickler zur Verfügung. Entwickler können alle Module hinzufügen die sie brauchen, da die Javascript-Community genug Hilfestellung bietet. - - -Die folgenden Module sind von vorhinein in Asch integriert: - -![inbuilt modules](./assets/inbuilt-modules.png) - -## Sicherheitslösung - -Anders als die oben angesprochenen Probleme, geht es im folgenden nicht um den Mangel an Knoten, sondern um das Problem des Ausführens von schädlichem Programm-Code welcher Benutzer von Asch-Dapps angreift. - -Das Ziel ist es, dass jeder Asch-Knoten unterschiedliche Sidechain-Dapps installieren kann, ohne dass er dem Code bedingungslos vertrauen muss. Deshalb bedarf es eines Sicherheitsmechanismuses, welcher den Knoten vor dem Auslesen des Dateisystems oder dem Manipulieren des Netzwerktverkehrs bewahrt. - -Um dieses Problem zu lösen, wird im Asch-System jeder Sidechain-Programm-Code als ein Kindprozess geladen. Dieser Kindprozess ladet eine virtuelle Javascript-Sandbox welche komplett vom restlichen System isoliert ist. Diese Javascript-Sandbox besitzt keine `require` Funktionalität und bekommt keine unnötigen Module mitgeliefert. - -Danach wird eine individuell angepasste `require` Funktion geladen inklusive häufig benutzter und sicherer Javascript-Module. Als letzter Schritt wird der Sidechain-Code geladen. Weiters bieten wir eine API für IPC (inter-process communication) an. Alle diese Schritte gewährleisten, dass der Sidechain-Code genügend APIs zur Verfügung hat, aber auch, dass der Knoten welcher den Sidechain-Code installiert kein Sicherheitsrisiko eingehen muss. - -![process structure](./assets/process-structure.png) - -## Tutorials - -Hier folgen einige Tutorials welche einen schnellen Start für Entwickler ermöglichen sollen. - -- [Dapp Entwicklungs Tutorial 1: Asch Dapp Hello World](./dapp_docs/1_hello_en.md) - Dieses Tutorial zeigt wie man eine einfache Sidechain-Applikation erstellt und veröffentlicht. Desweiteren wird die Code-Struktur des Sidechain-Frameworks beleuchtet. - -- [Dapp Entwicklungs Tutorial 2: Asch Dapp Asset](./dapp_docs/2_asset_en.md) - Dieses Tutorial zeigt wie man ein Asset auf der Sidechain erstellt. Weiters wird die Kommunikation zwischen Front- und Backend analysiert. - -- [Dapp Entwicklungs Tutorial 3: Asch Dapp Mini DAO](./dapp_docs/3_mini_dao_en.md) - Dieses Tutorial zeigt wie man eine Typtransaktion oder einen intelligenten Vertrag erstellt. Dies wird anhand eines kleinen DAO-Projekts (DAO=Dezentrale Autonome Organisation) mit Projekt Management und Voting Funktion erläutert. - -- [Dapp Entwicklungs Tutorial 4: Asch Dapp Dice Game](./dapp_docs/4_dice_game_en.md) - Dieses Tutorial zeigt wie man kompliziertere Transaktionen und intelligente Verträge erstellt, als auch wie man solch einen Vertrag auf Basis von historischen Daten ausführt. Desweiteren wird die Realisierung eine Würfelspiels demonstriert. - -- [Dapp Entwicklungs Tutorial 5: Eine Dapp veröffentlichen](./dapp_docs/5_dapp_publish_en.md) - Dieses Tutorial zeigt wie man eine Applikation online registriert (Testchain, Hauptchain) und wie man diese installiert / deinstalliert. diff --git a/docs/asch_dapps_introduction_en.md b/docs/asch_dapps_introduction_en.md deleted file mode 100644 index fccc058..0000000 --- a/docs/asch_dapps_introduction_en.md +++ /dev/null @@ -1,84 +0,0 @@ -# Introducing Asch Dapp Development -As we mentioned in whitepaper, not like Etherum or Bitcoin, Asch is using a sidechain framework as a platform for decentralised applications (DApp). Usually, each DApp runs on its own sidechain. - -## The Independency of Sidechain - -The advantage of sidechain framework is that both the code and data are independent from main blockchain, hence data over-dilation can be avoided. In fact this is a nature partition mechanism. -A sidechain has its own blockchain, delegates and nodes network, which means a block generated from a sidechain will be able to broadcast among the nodes belong to this sidechain. - -Every coin has two sides, so does independency of sidechain. After finishing the developement of DApp, developers still need to consider the operating and maintenance. In detail, it is necessary for developers to guarntee enough nodes to maintain acceptable security. - -From this perspective, the sidechain mechanism is not as good as Ethereum. Once a DApp is deployed on Ethereum, all the nodes in Ethereum can work for it, as well as promise the security. - - -## The Flexibility of Sidechain - -Sidechain mechanism, however, has its own value of existence since not every application needs such a high level security. Based on sidechain mechanism, Asch can provide a more flexible choice to users. - -For example, let's say Asch system has 1000 nodes. And under this circumstance some DApps are important so that they need 500 nodes to run. But some others may not be such crucial and only 100 nodes can meet their requirements. The point is that all of these choices are totally up to users and developers. - -Comparily, only one option is available in Ethereum, which is all nodes are occupied to run this application. It is said that Ethereum is also about to provide a partition mechanism, which is a solution that Asch system has already had. - -And obviously for those crucial applications that require high level security, Asch system still allows to develop on main blockchain. But this priority cannot be granted to all the developers because of unlimited dilations of main blockchain and potential risk of uncertainty (such as [DAO issue](https://en.wikipedia.org/wiki/The_DAO_(organization)#Risks)) - -The flexibility of sidechain is also reflected in that all paramaters of its blockchain can be customized. You can configure some common ones like block interval, block reward, or transaction fee's destination, or if you are an advanced user, you can even revise the consensus algorithm. - -But the most important thing is business logic, which can be easily developed on sidechain platform, no matter whether it is the business related transactions or smart contracts. Note that Asch is different with blockstreams, the inventor of sidechain, because the blockstreams' sidechain is just another cryptocurrency system on which it is difficult to develop new generation transaction system and smart contracts. - -Let's see the following graph - -Each black circus presents a node, and all 64 nodes constitute the network of main blockchain. In the red frame is sidechain No.1, whose sidechain network is composed by 12 nodes. Sidechain No.2 is represented by the blue frame, which contains 36 nodes. - -![sidechain deploy architecture](./assets/sidechain-deploy.png) - -## The Reciprocity of Main Chain and Sidechain - -There is a reciprocity relationship between the Asch main chain and the sidechains. Asch provides the essential foundation to sidechain as all kinds of API such as database writing , network communication or encrytion. Meanwhile, sidechain brings more nodes to supply hence strengthen the whole Asch system. - -It is unnecessary for sidechain developers to provides all required machines. Oppositely, they can utilized existed nodes as long as the owners of those nodes allow to install the applications on them. - -In addition, XAS, the currency of Asch main chain, can be transferred to sidechain. Because of the characteristic of XAS that is able to trade in exchanges, it can be a reliable media of value that is suitable for the assets existed in sidechain. Developers do not need to concern the trading platform problems when they issue an asset in sidechain because they can exchange it with XAS directly. - - -## Solution of Productivity - -We provide a set of templates, (or we can say scaffold or development framework) for sidechain in the SDK. Most of the fundamental functionalities of sidechain have been already completed, and all DApp developers needs to concern is just real business logic. At this point, DApp development on Asch platform has the same difficulty as on the Ethereum framework. - -The development language used in Asch sidechain framework is nodejs, upon which we built many common libraries that can be directly used by developers. Also developers can install anything they need since there is a large Javascript community providing enough supports. - -The following is modules built in Asch platform. - -![inbuilt modules](./assets/inbuilt-modules.png) - -## Solution of Security - -Different with those nodes deficiency issues we mentioned above, the security problems here we discuss are those sidechain codes intrude on DApp users of Asch platform. - -We hope each Asch node has its own sidechain installed, and the owner of this node does not have to trust the sidechain developer. It means that a security mechanism is required to provide some protection measures such as preventing sidechain from reading file system or manipulating network. - -To sovle this problem, sidechain code within Asch system is launched as a child-process, which firstly loads a Javascript virtual machine isolated by sandbox mechanism that is a purely clean virtual machine without `require` function and any unnecessary modules. - -Then we inplant a customized `require` and some common and secure modules, and then load the sidechain code. We also provide a set of API via IPC (inter-process communication). All of these measures ensure that the sidechain framework has enough API to use, as well as application users of sidechain will not need to suffer any risk. - - -![process structure](./assets/process-structure.png) - -## Tutorials - -Here are some tutorials from the begining which will be helpful to the developers to rapidly develop applications. - -- [Dapp Development Tutorial 1: Asch Dapp Hello World](./dapp_docs/1_hello_en.md) - This tutorial shows how to create and publish a basic sidechain application, as well as introduces the source code structure of sidechain framework. - -- [Dapp Development Tutorial 2: Asch Dapp Asset](./dapp_docs/2_asset_en.md) - This tutorial shows how to designate a built-in asset to sidechain and then analyse communication interface between the front end and back end. - - -- [Dapp Development Tutorial 3: Asch Dapp Mini DAO](./dapp_docs/3_mini_dao_en.md) - This tutorial shows how to create a new type transaction or smart contract, and demostrates a mini decentralized autonomous organization (dao) project with project management and voting function. - -- [Dapp Development Tutorial 4: Asch Dapp Dice Game](./dapp_docs/4_dice_game_en.md) - This tutorial shows how to crate more complicate transaction or smart contract, how to establish the connection among contracts, and how to carry out the contract based on historic data. The tutorial also demostrates a dice game. - -- [Dapp Development Tutorial 5: Publish Dapp online](./dapp_docs/5_dapp_publish_en.md) - This tutorial shows how to register the application to online system (testnet, mainnet and how to install/uninstall it. diff --git a/docs/asch_delegate_forging.md b/docs/asch_delegate_forging.md deleted file mode 100644 index cd4edb8..0000000 --- a/docs/asch_delegate_forging.md +++ /dev/null @@ -1,46 +0,0 @@ -# Asch 受托人与锻造 - -Asch系统中每个账户都可以注册成为受托人(需要支付100XAS)。
-成为受托人以后可以接受任意持币人的投票,当得票率排名进入前101时,可以获得记账权(即生产区块的权利,相当于比特币中的矿工),并获取一定的奖励。 -生产区块的过程叫做锻造(forging)。
-锻造不像比特币挖矿那样需要很强的算力,普通电脑即可进行,验证记账权的算法综合了时间片验证、受托人随机排名、受托人签名以及pbft算法等,具体可以参考[asch的共识协议](http://blog.asch.so/2016/08/11/asch-consensus-and-fault-tolerance/) -排名前101的受托人按照时间顺序轮流产生区块,区块间隔为10秒。当轮班受托人出现异常无法生产区块时,则延期到下一个10秒,由下一个受托人继续生产。
-每101个区块为一个周期,每个周期的受托人锻造顺序随机变换,每个周期的最后一个区块产出的时候,会进行该周期的收益结算,同时刷新新的排名。
-因为宕机、网络错误等原因无法生产区块的受托人无法获得该周期的收益,并且会降低生产率。生产率是衡量一个受托人稳定性的指标,生产率过低会影响得票率。
-正常生产区块的受托人则平分收益,收益包括区块奖励和交易费,排名和得票率的高低并不影响收益的多少,进入前101名的受托人收益率是相同的。
- -## 区块奖励 - -区块奖励会随着时间递减,具体时间则以未来的某一区块高度为准。
-Asch系统的区块奖励从464500块开始,初始奖励3.5币,每300万块递减一次,大约为1年。
-从15464500块以后,奖励不再递减,每年有略小于1.5%的通胀率。
-下面是各个阶段的区块奖励 - -|奖励|起始高度|结束高度| -|-----|------|-------| -|3.5|464500|3464500| -|3|3464500|6464500| -|2.5|6464500|9464500| -|2|9464500|12464500| -|1|12464500|15464500| -|0.5|15464500|---| - -## 交易费 - -除了区块奖励,受托人可以获得系统的交易费,或者手续费,手续费有以下种类。 - -|类型|费用XAS| -|----|---| -|普通转账|0.1| -|投票|0.1| -|二级密码|5| -|注册受托人|100| -|注册dapp|100| -|dapp充值|0.1| -|dapp提现|0.1| -|多重签名|(n+1)*0.5| -|小文件存储|(size / 200 + 1) * 0.1| -|资产发行商注册|100| -|资产注册|500| -|资产发行|0.1| -|资产转账|0.1| diff --git a/docs/asch_delegate_forging_en.md b/docs/asch_delegate_forging_en.md deleted file mode 100644 index 15c9eba..0000000 --- a/docs/asch_delegate_forging_en.md +++ /dev/null @@ -1,64 +0,0 @@ -title: Delegators and forging of Asch ---- - -Each account in Asch system can be registered as a delegator (100XAS is payable). - -A delegator can accept any votes from coin holders. When the rate of vote reaches into top 101, -the delegators can obtain the right to account(that is, the right of block production, which is -equivalent to miners in Bitcoin. ) and get certain reward. The process of block production is -called forging. - -Forging does not need strong computing power like Bitcoin mining. Even the ordinary computer -can be carried out to verify the algorithm of accounting right, which combines time slice -verification, delegators random ranking, delegators signatures and pbft algorithm. More -details refer to Asch consensus agreement. The delegators of top 101 are in turn to produce -blocks in chronological order with a block interval of 10 seconds.When delegators in turn can -not produce blocks because of exceptions, it will be postponed to next 10 seconds and produce -by the next delegator. - -Each 101 blocks as a cycle, forging order of the delegators will be random changed in each cycle. -When the last block is produced, the benefit will be settled in this cycle and the ranking will -also be refreshed. -If delegators can not produce blocks because of the downtime, network errors and other reasons, -they can not only get the benefits of the cycle, but also reduce productivity. Productivity is -an indicator of the stability of a delegator, and lower productivity will affect the vote. - -The delegators of the normal block production divide the benefit equally, including block rewards -and transaction fees. The rankings and the votes do not affect the amount of the benefit. The benefit -rate of the top 101 delegators is the same. - -# 1 Block rewards - -Block rewards will decrease over time, and the specific time will be based on the height of a future block. -The block rewards of Asch system start from the beginning of 464500 block. The initial reward is 3.5 coins. -Every 3 million block decreases once and it lasts about 1 year. -After 15464500 block, the reward is no longer decreasing and each year has slightly less than 1.5% inflation rate. - -The following are the various stages of the block reward - -|reward|initial height|end height| -|-----|------|-------| -|3.5|464500|3464500| -|3|3464500|6464500| -|2.5|6464500|9464500| -|2|9464500|12464500| -|1|12464500|15464500| -|0.5|15464500|---| - -# 2 transaction fee - -In addition to the block rewards, the delegators can obtain the system transaction fee, or the handling fee. -The handling fee has the following kinds. - - -|type|fee| -|----|---| -|transaction|0.1| -|vote|0.1| -|the second password|5| -|registed delegator|100| -|registed dapp|100| -|dapp deposit|0.1| -|dapp withdraw|0.1| -|multiple signatures|(n+1)*0.5| -|small file storage (not yet online)|(size / 200 + 1) * 0.1| diff --git a/docs/asch_dev_windows_install.md b/docs/asch_dev_windows_install.md deleted file mode 100644 index f135a51..0000000 --- a/docs/asch_dev_windows_install.md +++ /dev/null @@ -1,141 +0,0 @@ -# Asch 本地开发环境搭建(Windows) - -## 1 系统要求 - -- Windows操作系统(7/8/10) - -## 2 安装nodejs -[安装nodejs](https://nodejs.org/en/download/) 配置环境变量,版本V6.3以上(以下的没有验证过),如下所示: - -![nodejs环境](assets/win_install/node.png) - -## 3 安装Python -[安装Python](https://www.python.org/downloads/release/python-2713/) 并配置环境变量,版本2.5到3.0之间(最好2.7,3.0以及以上版本不支持),如下所示: - -![python](assets/win_install/python.png) - -## 4 安装.NET Framework 4.5.1 -[下载](https://www.microsoft.com/en-us/download/details.aspx?id=42779) 并安装.NET Framework 4.5.1,如果系统已经安装了可以忽略此步骤(至少4.5版本),win7系统可以直接打开控制**面板》程序》程序和功能** 查看 -是否已经安装,win10系统默认已经安装好了,查看方式如下图所示: - -![python](assets/win_install/win10.net.png) - -## 5 安装 VC++ Build Tools Technical Preview -[下载](http://go.microsoft.com/fwlink/?LinkId=691126)并安装VC++ Build Tools Technical Preview,全部选择默认安装就行了,安装时间可能有点久(10分钟左右) - -[参考](https://stackoverflow.com/questions/21069699/node-packages-not-building-on-windows-8-1-missing-microsoft-cpp-default-props) - -## 6 安装git -[下载](https://git-scm.com/)并安装git,应为asch使用gulp构建工具,其中包含一部分linux命令(如 cp、mv等),所以后面执行命令的时候需要用到git bash - -## 7 安装sqlite3 -[下载](https://pan.baidu.com/s/1WvQYSCCr-n7N5HMCRGqwLA)已经打包好的sqlie3压缩文件,解压放到任意位置,然后添加环境变量,如下所示: - -![sqlite3](assets/win_install/sqlite3.png) - -打开命令行验证如下: - -![sqlite3](assets/win_install/sqlite3_verify.png) - -## 8 安装gcc, g++ -这里有如下两种方式: -* [下载mingw-get-setup](https://sourceforge.net/projects/mingw/files/Installer/),然后再线安装所有依赖包,但是可能会比较慢 -* 下载我已经下载好的依赖包,解压缩后放到任意盘,然后配置环境变量,如下所示: - -![sqlite3](assets/win_install/gcc.png) - -安装完成后分别执行一下命令查看是否成功: -``` -gcc -v -g++ -v -``` - -如下所示: - -![sqlite3](assets/win_install/gcc_verify.png) - -## 9 安装OpenSSL -[下载](http://slproweb.com/products/Win32OpenSSL.html)并安装OpenSSL,全部默认安装即可. - -## 10 npm配置 -首先执行以下命令配置淘宝镜像,这样使用npm下载的时候会更快一些 -``` -npm config set registry https://registry.npm.taobao.org - -##验证 -npm info npm -``` - -执行以下命令配置**msvs** -``` -npm config set msvs_version 2015 --global -``` - -最后安装asch需要的一些依赖,执行以下命令: -``` -npm i -g gulp -npm i -g yarn -``` - -### 11 运行代码 -> 运行前查看之前的 VC++ Build Tools Technical Preview 是否已经安装完成 - -注:运行代码之前需要说明一下,在asch3.0版本之前,用的椭圆曲线加密依赖为ed25519,而3.0以后使用的是sodium, -3.0之前的代码直接安装完依赖就可以运行,但是目前的3.0之后的源码需要改变几行代码,但是asch的所有功能都能正常运行,方便Windows用户本地开发调试使用。 - -修改以下两个文件的内容: -* src\utils\ed.js -* package.json - -package.js: -```json -##原依赖 -"sodium": "^2.0.3", - -## 换成ed25519 -"ed25519": "^0.0.4", -``` - -ed.js: -``` -## 将文件所有内容换成如下代码 -const ed = require('ed25519'); -module.exports = { - MakeKeypair: ed.MakeKeypair, - - Sign: ed.Sign, - - Verify: ed.Verify -}; -``` - -修改完文件以后安装依赖: -``` -npm install -``` - -因为Windows控制台本身的原因,安装过程中如果出现停顿可以按几下回车,如果出现以下步骤则说明前面一些安装成功了: - -![install](assets/win_install/install.png) - -最后执行 **node app.js** 即可正常运行,如下图所示: - -![run](assets/win_install/run.png) - -## 12 编译前端项目 -前端项目具体编译打包操作可以参考 [前端项目的操作说明](../public/README.md),不过这里需要注意一点, -所有的命令都要在 **git bash** 中进行,原因已经在之前安装git的时候说明了,依次执行以下命令即可: -``` -cd public -yarn install -gulp build-test -``` - -## 13 软件下载 -考虑到部分软件可能因为网络原因无法下载,在这里提供一个所有依赖的软件的 [下载地址](https://pan.baidu.com/s/1WLSH9M0Hwp16CPYOgZ_6GQ) - - - - - - diff --git a/docs/asch_http_interface.md b/docs/asch_http_interface.md deleted file mode 100644 index 9ba1652..0000000 --- a/docs/asch_http_interface.md +++ /dev/null @@ -1,3560 +0,0 @@ -Table of Contents -================= - - * [ASCH HTTP API文档](#asch-http-api文档) - * [1 API使用说明](#1-api使用说明) - * [1.1 请求过程说明](#11-请求过程说明) - * [2 接口](#2-接口) - * [2.1 账户accounts](#21-账户accounts) - * [2.1.1 登录](#211-登录) - * [2.1.1.1 本地加密后再登陆(推荐使用)](#2111-本地加密后再登陆推荐使用) - * [2.1.1.2 本地不加密直接登陆](#2112-本地不加密直接登陆) - * [2.1.2 根据地址获取账户信息](#212-根据地址获取账户信息) - * [2.1.3 获取账户余额](#213-获取账户余额) - * [2.1.4 根据地址获取账户公钥](#214-根据地址获取账户公钥) - * [2.1.5 生成公钥](#215-生成公钥) - * [2.1.6 根据地址获取其投票列表](#216-根据地址获取其投票列表) - * [2.1.7 获取受托人手续费设置](#217-获取受托人手续费设置) - * [2.1.8 给受托人投票](#218-给受托人投票) - * [2.1.9 生成新账户](#219-生成新账户) - * [2.1.10 获取账户排行榜前100名](#2110-获取账户排行榜前100名) - * [2.1.11 获取当前链上账户总个数](#2111-获取当前链上账户总个数) - * [2.2 交易transactions](#22-交易transactions) - * [2.2.1 获取交易信息](#221-获取交易信息) - * [2.2.2 根据交易id查看交易详情](#222-根据交易id查看交易详情) - * [2.2.3 根据未确认交易id查看详情](#223-根据未确认交易id查看详情) - * [2.2.4 获取[全网所有]未确认的交易详情](#224-获取全网所有未确认的交易详情) - * [2.2.5 创建交易并广播](#225-创建交易并广播) - * [2.3 区块blocks](#23-区块blocks) - * [2.3.1 获取指定区块的详情](#231-获取指定区块的详情) - * [2.3.2 获取区块数据](#232-获取区块数据) - * [2.3.3 获取区块链高度](#233-获取区块链高度) - * [2.3.4 获取普通转账手续费](#234-获取普通转账手续费) - * [2.3.5 获取里程碑](#235-获取里程碑) - * [2.3.6 查看单个区块奖励](#236-查看单个区块奖励) - * [2.3.7 获取XAS当前供应值](#237-获取xas当前供应值) - * [2.3.8 区块链状态](#238-区块链状态) - * [2.3.9 获取指定区块的交易信息](#239-获取指定区块的交易信息) - * [2.4 受托人delegates](#24-受托人delegates) - * [2.4.1 获取受托人总个数](#241-获取受托人总个数) - * [2.4.2 根据受托人公钥查看哪些人为其投了票](#242-根据受托人公钥查看哪些人为其投了票) - * [2.4.3 根据公钥或者用户名获取受托人详情](#243-根据公钥或者用户名获取受托人详情) - * [2.4.4 获取受托人列表](#244-获取受托人列表) - * [2.4.5 获取受托人设置的转账费](#245-获取受托人设置的转账费) - * [2.4.6 根据公钥查看其锻造情况](#246-根据公钥查看其锻造情况) - * [2.4.7 注册受托人](#247-注册受托人) - * [2.4.8 受托人开启锻造](#248-受托人开启锻造) - * [2.4.9 受托人关闭锻造](#249-受托人关闭锻造) - * [2.4.10 受托人锻造状态查看](#2410-受托人锻造状态查看) - * [2.5 节点peers](#25-节点peers) - * [2.5.1 获取全网节点信息](#251-获取全网节点信息) - * [2.5.2 获取本节点版本号等信息](#252-获取本节点版本号等信息) - * [2.5.3 获取指定ip节点信息](#253-获取指定ip节点信息) - * [2.6 同步和加载](#26-同步和加载) - * [2.6.1 查看本地区块链加载状态](#261-查看本地区块链加载状态) - * [2.6.2 查看区块同步信息](#262-查看区块同步信息) - * [2.7 二级密码signatures](#27-二级密码signatures) - * [2.7.1 设置二级密码](#271-设置二级密码) - * [2.7.2 获取二级密码设置手续费](#272-获取二级密码设置手续费) - * [2.8 多重签名multisignatures](#28-多重签名multisignatures) - * [2.8.1 设置普通账户为多重签名账户](#281-设置普通账户为多重签名账户) - * [2.8.2 根据公钥获取挂起的多重签名交易详情](#282-根据公钥获取挂起的多重签名交易详情) - * [2.8.3 非交易发起人对交易进行多重签名](#283-非交易发起人对交易进行多重签名) - * [2.8.4 获取多重签名账户信息](#284-获取多重签名账户信息) - * [2.9 点对点传输tansport[安全的api]](#29-点对点传输tansport安全的api) - * [2.9.1 说明](#291-说明) - * [2.9.2 普通交易](#292-普通交易) - * [2.9.2.1 设置二级密码](#2921-设置二级密码) - * [2.9.2.2 转账](#2922-转账) - * [2.9.2.3 注册受托人](#2923-注册受托人) - * [2.9.2.4 投票 & 取消投票](#2924-投票--取消投票) - * [2.9.2.5 账户锁仓](#2925-账户锁仓) - * [2.9.3 UIA相关交易](#293-uia相关交易) - * [2.9.3.1 注册资产发行商](#2931-注册资产发行商) - * [2.9.3.2 注册资产](#2932-注册资产) - * [2.9.3.3 资产设置acl模式](#2933-资产设置acl模式) - * [2.9.3.4 更新访问控制列表(acl)](#2934-更新访问控制列表acl) - * [2.9.3.5 资产发行](#2935-资产发行) - * [2.9.3.6 资产转账](#2936-资产转账) - * [2.9.3.7 资产注销](#2937-资产注销) - * [2.9.4 其它内部通讯安全接口](#294-其它内部通讯安全接口) - * [2.10 用户自定义资产uia](#210-用户自定义资产uia) - * [2.10.1 获取全网所有发行商](#2101-获取全网所有发行商) - * [2.10.2 查询指定发行商的信息](#2102-查询指定发行商的信息) - * [2.10.3 查看指定发行商的资产](#2103-查看指定发行商的资产) - * [2.10.4 获取全网所有资产信息](#2104-获取全网所有资产信息) - * [2.10.5 获取指定资产信息](#2105-获取指定资产信息) - * [2.10.6 获取指定资产的访问控制列表(acl)](#2106-获取指定资产的访问控制列表acl) - * [2.10.7 获取指定账户所有uia的余额](#2107-获取指定账户所有uia的余额) - * [2.10.8 获取指定账户所有资产相关操作记录](#2108-获取指定账户所有资产相关操作记录) - * [2.10.9 获取指定账户指定资产的余额](#2109-获取指定账户指定资产的余额) - * [2.10.10 获取指定账户指定资产转账记录](#21010-获取指定账户指定资产转账记录) - * [2.10.11 获取指定资产转账记录](#21011-获取指定资产转账记录) - * [2.10.12 资产创建相关](#21012-资产创建相关) - * [2.10.12.1 注册资产发行商](#210121-注册资产发行商) - * [2.10.12.2 注册资产](#210122-注册资产) - * [2.10.12.3 更新资产访问控制列表(acl)](#210123-更新资产访问控制列表acl) - * [2.10.12.4 资产发行](#210124-资产发行) - * [2.10.12.5 资产转账](#210125-资产转账) - * [2.10.12.6 更新黑白名单](#210126-更新黑白名单) - * [2.11 存储storages](#211-存储storages) - * [2.11.1 上传数据](#2111-上传数据) - * [2.11.1.1 上传数据(直接上传)](#21111-上传数据直接上传) - * [2.11.1.2 上传数据(签名后再上传)](#21112-上传数据签名后再上传) - * [2.11.2 根据交易id查询存储的数据-1](#2112-根据交易id查询存储的数据-1) - * [2.11.3 根据交易id查询存储的数据-2](#2113-根据交易id查询存储的数据-2) - * [附录1:asch-js安装](#附录1asch-js安装) - -Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc) - - -# ASCH HTTP API文档 - - - -## **1 API使用说明** -### **1.1 请求过程说明** -1.1 构造请求数据,用户数据按照Asch提供的接口规则,通过程序生成签名,生成请求数据集合; -1.2 发送请求数据,把构造完成的数据集合通过POST/GET等提交的方式传递给Asch; -1.3 Asch对请求数据进行处理,服务器在接收到请求后,会首先进行安全校验,验证通过后便会处理该次发送过来的请求; -1.4 返回响应结果数据,Asch把响应结果以JSON的格式反馈给用户,每个响应都包含success字段,表示请求是否成功,成功为true, 失败为false。 如果失败,则还会包含一个error字段,表示错误原因; -1.5 对获取的返回结果数据进行处理; - ---- - -## **2 接口** -### **2.1 账户accounts** - -#### **2.1.1 登录** -##### **2.1.1.1 本地加密后再登陆(推荐使用)** -接口地址:/api/accounts/open2/ -请求方式:post -支持格式:json -接口备注:根据用户密码在本地客户端用js代码生成公钥 - -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|publicKey |string |Y |asch账户公钥 | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否登陆成功 | -|account|json |账户信息 | -请求示例: - -```js -var secret = 'Asch账户密码' //在浏览器内存中保留 -var AschJS = require('asch-js'); //asch-js具体安装方法见附录 -var publicKey = AschJS.crypto.getKeys(secret).publicKey; //根据密码生成公钥 -// var address = AschJS.crypto.getAddress(publicKey); //根据公钥生成地址 - -// 将上面生成的数据通过post提交到asch server -curl -X POST -H "Content-Type: application/json" -k -d '{"publicKey":"bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9"}' http://45.32.248.33:4096/api/accounts/open2/ -``` - -JSON返回示例: -```js -{ - "success": true, - "account": { - "address": "16723473400748954103", //asch地址 - "unconfirmedBalance": 19480000000, //未确认和已确认的余额之和,该值大于等于balance - "balance": 19480000000, //余额 - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9", //公钥 - "unconfirmedSignature": false, - "secondSignature": true, //二级签名 - "secondPublicKey": "edf30942beb74de5ed6368c792af8665e9636f32a5f1c9377bcdc3b252d3f277", //二级密码公钥 - "multisignatures": [], - "u_multisignatures": [], - "lockHeight: ": 0 // 锁仓高度 - }, - "latestBlock": { - "height": 114480, //当前节点最新区块高度 - "timestamp": 4471890 - }, - "version": { - "version": "1.0.0", //当前节点版本号 - "build": "12:11:11 16/08/2016", //构建日期 - "net": "testnet" //区块链类型,是主链还是测试链 - } -} -``` - -##### **2.1.1.2 本地不加密直接登陆** -接口地址:/api/accounts/open/ -请求方式:post -支持格式:json -接口备注:将密码传入到server端,根据生成的地址去查询账户信息。不推荐在公网坏境使用! -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|secret |string |Y |asch账户密码 | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否登陆成功 | -|account|json |账户信息 | - -请求示例: -```bash -curl -X POST -H "Content-Type: application/json" -k -d '{"secret":"fault still attack alley expand music basket purse later educate follow ride"}' http://45.32.248.33:4096/api/accounts/open/ -``` - -JSON返回示例: -```js -{ - "success": true, - "account": { - "address": "16723473400748954103", - "unconfirmedBalance": 19480000000, - "balance": 19480000000, - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9", - "unconfirmedSignature": false, - "secondSignature": true, - "secondPublicKey": "edf30942beb74de5ed6368c792af8665e9636f32a5f1c9377bcdc3b252d3f277", - "multisignatures": [ ], - "u_multisignatures": [ ] - } -} -``` -#### **2.1.2 根据地址获取账户信息** -接口地址:/api/accounts -请求方式:get -支持格式:urlencoded -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|address |string |Y |用户地址,最小长度:1 | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|account|json |账户信息 | -|latestBlock|json |该节点最新的区块信息 | -|version|json |版本相关信息 | - -请求示例: -```bash -curl -k -X GET http://45.32.248.33:4096/api/accounts?address=16723473400748954103 -``` - -JSON返回示例: -```js -{ - "success": true, - "account": { - "address": "16723473400748954103", //asch地址 - "unconfirmedBalance": 19480000000, //未确认和已确认的余额之和,该值大于等于balance - "balance": 19480000000, //余额 - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9", //公钥 - "unconfirmedSignature": false, - "secondSignature": true, //二级签名 - "secondPublicKey": "edf30942beb74de5ed6368c792af8665e9636f32a5f1c9377bcdc3b252d3f277", //二级密码公钥 - "multisignatures": [], - "u_multisignatures": [], - "lockHeight: ": 0 // 锁仓高度 - }, - "latestBlock": { - "height": 114480, //当前节点最新区块高度 - "timestamp": 4471890 - }, - "version": { - "version": "1.0.0", //当前节点版本号 - "build": "12:11:11 16/08/2016", //构建日期 - "net": "testnet" //区块链类型,是主链还是测试链 - } -} -``` -#### **2.1.3 获取账户余额** -接口地址:/api/accounts/getBalance -请求方式:get -支持格式:urlencoded -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|address |string |Y |用户地址,最小长度:1 | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|balance|integer |余额 | -|unconfirmedBalance|integer|未确认和已确认的余额之和,该值大于等于balance| - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/accounts/getBalance?address=14636456069025293113' -``` - -JSON返回示例: -```js -{ - "success": true, - "balance": 5281328514990, - "unconfirmedBalance": 5281328514990 -} -``` - -#### **2.1.4 根据地址获取账户公钥** -接口地址:/api/accounts/getPublickey -请求方式:get -支持格式:urlencoded -请求参数说明:只有给别人转过账,db中才会存取公钥,否则是查不到的。btc也是这样 - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|address |string |Y |用户地址,最小长度:1 | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|publicKey|string |公钥 | - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/accounts/getPublickey?address=14636456069025293113' -``` - -JSON返回示例: -```js -{ - "success": true, - "publicKey": "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7" -} -``` - -#### **2.1.5 生成公钥** -接口地址:/api/accounts/generatePublickey -请求方式:post -支持格式:json -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|secret |string |Y |asch账户密码 | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|publicKey|string |公钥 | - -请求示例: -```bash -curl -k -H "Content-Type: application/json" -X POST -d '{"secret":"fault still attack alley expand music basket purse later educate follow ride"}' 'http://45.32.248.33:4096/api/accounts/generatePublickey' -``` - -JSON返回示例: -```js -{ - "success": true, - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9" -} -``` - -#### **2.1.6 根据地址获取其投票列表** -接口地址:/api/accounts/delegates -请求方式:get -支持格式:urlencoded -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|address |string |Y |投票人地址 | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|delegates|Array |已投票的受托人详情数组 | - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/accounts/delegates?address=14636456069025293113' -``` - -JSON返回示例: -```js -{ - "success": true, - "delegates": [{ - "username": "wgl_002", - "address": "14636456069025293113", - "publicKey": "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7", - "vote": 9901985415600500, - "producedblocks": 1373, - "missedblocks": 6, - "rate": 1, - "approval": "98.54", - "productivity": "99.56" - }, - { - "username": "wgl_003", - "address": "9961157415582672274", - "publicKey": "c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2", - "vote": 9891995435600500, - "producedblocks": 1371, - "missedblocks": 8, - "rate": 2, - "approval": "98.44", - "productivity": "99.41" - }, - { - "username": "wgl_001", - "address": "1869971419039689816", - "publicKey": "c547df2dde6cbb4508aabcb5970d8f9132e5a1d1c422632da6bc20bf1df165b8", - "vote": 32401577128413, - "producedblocks": 969, - "missedblocks": 8, - "rate": 102, - "approval": "0.32", - "productivity": 0 - }] -} -``` - -#### **2.1.7 获取受托人手续费设置** -接口地址:/api/accounts/delegates/fee -请求方式:get -支持格式:无 -请求参数说明:无 - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|fee|integer |手续费 | - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/accounts/delegates/fee -``` - -JSON返回示例: -```js -{ - "success": true, - "fee": 100000000 // 0.1 XAS -} -``` - - -#### **2.1.8 给受托人投票** -接口地址:/api/accounts/delegates -请求方式:put -支持格式:json -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|secret |string |Y |asch账户密码 | -|publicKey|string |N|公钥 | -|secondSecret|string|N|asch账户二级密码,最小长度:1,最大长度:100| -|delegates|Array|受托人公钥数组,每个公钥前需要加上+或者-号,代表增加/取消对其的投票| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transaction|json |投票交易详情 | - - -请求示例: -```bash -curl -k -H "Content-Type: application/json" -X PUT -d '{"secret":"call scissors pupil water friend timber spend brand vote obey corn size","publicKey":"3ec1c9ec08c0512641deba37c0e95a0fe5fc3bdf58424009f594d7d6a4e28a2a","delegates":["+fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575"]}' 'http://45.32.248.33:4096/api/accounts/delegates' -``` - -JSON返回示例: -```js - { - "success": true, - "transaction": { - "type": 3, //投票的交易类型为3 - "amount": 0, - "senderPublicKey": "3ec1c9ec08c0512641deba37c0e95a0fe5fc3bdf58424009f594d7d6a4e28a2a", - "requesterPublicKey": null, - "timestamp": 5056064, - "asset": { - "vote": { - "votes": ["+fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575"] - } - }, - "recipientId": null, - "signature": "0bff58c7311fc59b3c8b3ffc236bbfece9850c334fb0c292ab087f78cf9a6c0f4d3e541c501887a2c2ec46294c777e8f7bf7dea9cb7c9a175fdec641bb684f08", - "id": "5630629337798595849", - "fee": 10000000, - "senderId": "15238461869262180695" - } -} -``` - - -#### **2.1.9 生成新账户** -接口地址:/api/accounts/new -请求方式:get -支持格式:无 -请求参数:无 - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|secret|string |密码 | -|publicKey|string |公钥 | -|privateKey|string |私钥 | -|address|string |地址 | - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/accounts/new' -``` - -JSON返回示例: -```js -{ - success: true, - secret: "during crush zoo wealth horror left night upset spike iron divert lawn", // 密码 - publicKey: "261fa56f389c324fddbe8777dbc0ef3341ee7b75d1ffdc82192265633b90d503", // 公钥 - privateKey: "67c9523b7622704c4bcfe960cb32d7fa04d3eb94e30e7964d3c6a24a3647a0a3261fa56f389c324fddbe8777dbc0ef3341ee7b75d1ffdc82192265633b90d503", // 私钥 - address: "ANfXDQUZroMnrQ6vRGR7UXXtbPn3fhEVRJ" // 地址 -} -``` - - -#### **2.1.10 获取账户排行榜前100名** -接口地址:/api/accounts/top -请求方式:get -支持格式:无 -请求参数说明:如果不加请求参数则返回持币量前100名账户信息 - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|limit |integer |N |限制结果集个数,最小值:0,最大值:100 | -|offset|integer |N |偏移量,最小值0 | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|accounts|json |账户信息元组,每个元素包含地址、余额、公钥 | - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/accounts/top?limit=5&offset=0' //返回前5名账户信息 -``` - -JSON返回示例: -```js -{ - "success": true, - "accounts": [{ - "address": "355198157736313687", - "balance": 4400099900000000, //44000999 XAS - "publicKey": "0b8e120db026d58cbf9d3f392f88eefe3a82a0a3023298b9466d7ed64ff05881" - }, - { - "address": "3196144307608101364", - "balance": 3750000020000000, - "publicKey": "988eb82a603dd033f94a4f3b6f9f9ef4a7d3d066607c433e5255d50ea7270720" - }, - { - "address": "9248745407080572308", - "balance": 988703397029757, - "publicKey": "02cedc56da08099532e312c5e563e2859bc5b93cc594eb3e5d350f368d681988" - }, - { - "address": "15745540293890213312", - "balance": 498186229718623, - "publicKey": "d39d6f26869067473d685da742339d1a9117257fe14b3cc7261e3f2ed5a339e3" - }, - { - "address": "8812460086240160222", - "balance": 100704426831866, - "publicKey": "0af92cc32f54d50dd83c4f7de14e71223a57843a40e993bc0813454aa9270053" - } -} -``` - - -#### **2.1.11 获取当前链上账户总个数** -接口地址:/api/accounts/count -请求方式:get -支持格式:无 -请求参数:无 - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|count|integer |当前链上账户总个数 | - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/accounts/count' -``` - -JSON返回示例: -```js -{ - success: true, - count: 105 -} -``` - - -### **2.2 交易transactions** -#### **2.2.1 获取交易信息** -接口地址:/api/transactions -请求方式:get -支持格式:urlencoded -接口备注:如果请求不加参数则会获取全网所有交易 -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|and|integer|N|取值范围0和1,默认值0。select查询时下面这些条件都是or的关系,and=1时select是and的关系 | -|blockId |string |N |区块id | -|limit |integer |N |限制结果集个数,最小值:0,最大值:100 | -|type|integer |N |交易类型,0:普通转账,1:设置二级密码,2:注册受托人,3:投票,4:多重签名,5:DAPP,6:IN_TRANSFER,7:OUT_TRANSFER | -|orderBy|string |N |根据表中字段排序,senderPublicKey:desc | -|offset|integer |N |偏移量,最小值0 | -|senderPublicKey|string|N|发送者公钥| -|ownerPublicKey|string|N|| - ownerAddress|string|N|| -|senderId|string|N|发送者地址| -|recipientId|string|N|接收者地址,最小长度:1| -|amount|integer|N|金额| -|fee|integer|N|手续费| -|uia|integer|N|是否uia,0:不是,1:是| -|currency|string|N|资产名| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transactions|列表 |多个交易详情json构成的列表 | -|count|int|获取到的交易总个数| - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/transactions?recipientId=16723473400748954103&orderBy=t_timestamp:desc&limit=3' -``` - -JSON返回示例: -```js -{ - "success": true, - "transactions": [{ - "id": "17192581936339156329", - "height": "105951", - "blockId": "15051364118100195665", - "type": 0, - "timestamp": 4385190, - "senderPublicKey": "d39d6f26869067473d685da742339d1a9117257fe14b3cc7261e3f2ed5a339e3", - "senderId": "15745540293890213312", - "recipientId": "16723473400748954103", - "amount": 10000000000, - "fee": 10000000, - "signature": "98d65df3109802c707eeed706e90a907f337bddab58cb4c1fbe6ec2179aa1c85ec2903cc0cf44bf0092926829aa5a0a6ec99458f65b6ebd11f0988772e58740e", - "signSignature": "", - "signatures": null, - "confirmations": "31802", - "asset": { - - } - }, - { - "id": "7000452951235123088", - "height": "105473", - "blockId": "11877628176330539727", - "type": 0, - "timestamp": 4380147, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "senderId": "16358246403719868041", - "recipientId": "16723473400748954103", - "amount": 10000000000, - "fee": 10000000, - "signature": "dc84044d4f6b4779eecc3a986b6507e458cc5964f601ebeb4d3b68a96129813f4940e14de950526dd685ca1328b6e477e6c57e95aeac45859a2ea62a587d0204", - "signSignature": "", - "signatures": null, - "confirmations": "32280", - "asset": { - - } - }, - { - "id": "14093929199102906687", - "height": "105460", - "blockId": "2237504897174225512", - "type": 0, - "timestamp": 4380024, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "senderId": "16358246403719868041", - "recipientId": "16723473400748954103", - "amount": 10000000000, - "fee": 10000000, - "signature": "73ceddc3cbe5103fbdd9eee12f7e4d9a125a3bcf2e7cd04282b7329719735aeb36936762f17d842fb14813fa8f857b8144040e5117dffcfc7e2ae88e36440a0f", - "signSignature": "", - "signatures": null, - "confirmations": "32293", - "asset": { - - } - }], - "count": 3 -} -``` -#### **2.2.2 根据交易id查看交易详情** -接口地址:/api/transactions/get -请求方式:get -支持格式:urlencoded -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|Id |string |Y |交易id | - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transactions|json |交易详情 | - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/transactions/get?id=14093929199102906687' -``` - -JSON返回示例: -```js -{ - "success": true, - "transaction": { - "id": "14093929199102906687", // 交易id - "height": "105460",// 该交易所在区块高度 - "blockId": "2237504897174225512",// 所在区块id - "type": 0,// 交易类型,0:普通XAS转账 - "timestamp": 4380024,// 距离阿希创世块的timestamp - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", // 发送者公钥 - "senderId": "16358246403719868041",// 发送者地址 - "recipientId": "16723473400748954103",// 接收者地址 - "amount": 10000000000,// 交易额,100XAS - "fee": 10000000, // 手续费0.1XAS - "signature": "73ceddc3cbe5103fbdd9eee12f7e4d9a125a3bcf2e7cd04282b7329719735aeb36936762f17d842fb14813fa8f857b8144040e5117dffcfc7e2ae88e36440a0f", - "signSignature": "", - "signatures": null, - "confirmations": "34268",// 确认数 - "asset": { - } - } -} -``` - -#### **2.2.3 根据未确认交易id查看详情** -接口地址:/api/transactions/unconfirmed/get -请求方式:get -支持格式:urlencoded -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|id|string |Y |未确认交易id | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transaction|json |未确认交易详情 | - - -请求示例: -```bash -curl -k -X GET http://45.32.248.33:4096/api/transactions/unconfirmed/get?id=7557072430673853692 // 正常情况,该未确认交易存在时间极短0~10秒 -``` - -JSON返回示例: -```js -{ - "success": true, - "transaction": { - "type": 0, - "amount": 10000, - "senderPublicKey": "3ec1c9ec08c0512641deba37c0e95a0fe5fc3bdf58424009f594d7d6a4e28a2a", - "requesterPublicKey": null, - "timestamp": 5082322, - "asset": { - - }, - "recipientId": "16723473400748954103", - "signature": "3a97f8d63509ef964bda3d816366b8e9e2d9b5d4604a660e7cbeefe210cb910f5de9a51bece06c32d010f55502c62f0f59b8224e1c141731ddfee27206a88d02", - "id": "7557072430673853692", - "fee": 10000000, - "senderId": "15238461869262180695" - } -} -``` - - -#### **2.2.4 获取[全网所有]未确认的交易详情** -接口地址:/api/transactions/unconfirmed -请求方式:get -支持格式:urlencoded -接口说明:如果不加参数,则会获取全网所有未确认交易 -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|senderPublicKey |string |N |发送者公钥 | -|address |string |N |地址 | - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transactions|Array |未确认交易列表 | - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/transactions/unconfirmed' -``` - -JSON返回示例: -```js -{ - "success": true, - "transactions": [] //全网目前不存在未确认的交易 -} -``` - -#### **2.2.5 创建交易并广播** -接口地址:/api/transactions -请求方式:PUT -支持格式:json - -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|secret |string |Y |asch账户密码 | -|amount|integer|Y|金额,最小值:1,最大值:10000000000000000| -|recipientId|string|Y|接收者地址,最小长度:1| -|publicKey|string|N|发送者公钥| -|secondSecret|string|N|发送者二级密码,最小长度1,最大长度:100| -|multisigAccountPublicKey|string|N|多重签名账户公钥| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transactionId|string |交易id | - - -请求示例: -```bash -curl -k -H "Content-Type: application/json" -X PUT -d '{"secret":"unaware label emerge fancy concert long fiction report affair appear decide twenty","amount":1000000,"recipientId":"16723473400748954103"}' 'http://45.32.248.33:4096/api/transactions' -``` - -JSON返回示例: -```js -{ - "success": true, - "transactionId": "16670272591943275531" -} -``` - -### **2.3 区块blocks** -#### **2.3.1 获取指定区块的详情** -接口地址:/api/blocks/get -请求方式:get -支持格式:urlencoded -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|id |string |参数3选1 |区块id | -|height|string|参数3选1|区块高度| -|hash|string|参数3选1|区块hash| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|block|json |区块详情 | - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/get?id=6076474715648888747' -``` - -JSON返回示例: -```js -{ - "success": true, - "block": { - "id": "6076474715648888747", - "version": 0, - "timestamp": 4734070, - "height": 140538, - "previousBlock": "16033230167082515105", //上一个区块id - "numberOfTransactions": 0, //交易数 - "totalAmount": 0, //交易额 - "totalFee": 0, - "reward": 350000000, //奖励 - "payloadLength": 0, - "payloadHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "generatorPublicKey": "1d352950c8141e1b35daba4a974a604519d7a2ef3a1ec0a503ce2653646aa052", - "generatorId": "6656029629904254066", - "blockSignature": "a53de66922cdc2f431acd0a474beec7cf7c420a8460b7b7caf84999be7caebb59fb7fbb7166c2c7013dbb431585ea7294722166cb08bf9663abf50b6bd81cd05", - "confirmations": "2", - "totalForged": 350000000 - } -} -``` - -#### **2.3.2 获取区块数据** -接口地址:/api/blocks -请求方式:get -支持格式:urlencoded -接口说明:不加参数则获取全网区块详情 -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|limit |integer |N |限制结果集个数,最小值:0,最大值:100 | -|orderBy|string |N |根据表中字段排序,如height:desc | -|offset|integer |N |偏移量,最小值0 | -|generatorPublicKey|string |N |区块生成者公钥 | -|totalAmount|integer |N |交易总额,最小值:0,最大值:10000000000000000 | -|totalFee|integer |N |手续费总额,最小值:0,最大值:10000000000000000 | -|reward|integer |N |奖励金额,最小值:0 | -|previousBlock|string |N |上一个区块 | -|height|integer |N |区块高度 | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|blocks|Array |由区块详情json串构成的数组 | -|count|integer|区块链高度| - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks?limit=2&offset=0&orderBy=height:desc' -``` - -JSON返回示例: -```js -{ - "success": true, - "blocks": [{ - "id": "12634047624004615059", - "version": 0, - "timestamp": 4708080, - "height": 137986, - "previousBlock": "3498191422350401106", - "numberOfTransactions": 0, // 交易数 - "totalAmount": 0, // 金额 - "totalFee": 0, // 手续费 - "reward": 350000000, // 奖励 - "payloadLength": 0, - "payloadHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "generatorPublicKey": "44db7bec89ef289d0def257285675ca14f2a947dfd2b70e6b1cff4392ce42ada", - "generatorId": "4925169939071346193", - "blockSignature": "83a2124e3e8201c1a6099b2ac8ab1c117ad34867978add3a90d41a64df9d2ad8fabc9ec14d27a77cd34c08a6479ef684f247c11b1cbbcb0e9767dffc85838600", - "confirmations": "1", - "totalForged": 350000000 - }, - { - "id": "3498191422350401106", - "version": 0, - "timestamp": 4708070, - "height": 137985, - "previousBlock": "14078155423801039323", - "numberOfTransactions": 0, - "totalAmount": 0, - "totalFee": 0, - "reward": 350000000, - "payloadLength": 0, - "payloadHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "generatorPublicKey": "500b1ec025cd64d36008341ed8d2508473ecf559be213ca5f9580620a21a592c", - "generatorId": "16006295608945777169", - "blockSignature": "a0b5ed6c94b1f33c4d0f017f21a08357061493392b19e34eeedf274b77c751e3f86c92443280de09ea1754d62fe7ef00e02acbdc3bc0c1063cef344bacaa4f07", - "confirmations": "2", - "totalForged": 350000000 - }], - "count": 137986 -} -``` - -#### **2.3.3 获取区块链高度** -接口地址:/api/blocks/getHeight -请求方式:get -支持格式:无 -请求参数说明:无 - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|height|integer |区块链高度 | - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/getheight' -``` - -JSON返回示例: -```js -{"success":true,"height":140569} -``` - -#### **2.3.4 获取普通转账手续费** -接口地址:/api/blocks/getFee -请求方式:get -支持格式:无 -请求参数说明:无 - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|fee|integer |交易手续费 | - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/getfee' -``` - -JSON返回示例: -```js -{"success":true,"fee":10000000} //手续费为0.1 XAS -``` - -#### **2.3.5 获取里程碑** -接口地址:/api/blocks/getMilestone -请求方式:get -支持格式:无 -请求参数说明:无 -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|milestone|integer | | - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/getMilestone' -``` - -JSON返回示例: -```js -{"success":true,"milestone":0} -``` - -#### **2.3.6 查看单个区块奖励** -接口地址:/api/blocks/getReward -请求方式:get -支持格式:无 -请求参数说明:无 - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|reward|integer |区块奖励,包含受托人奖励和手续费 | - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/getReward' -``` - -JSON返回示例: -```js -{"success":true,"reward":350000000} //每个生成一个block奖励3.5 XAS -``` - -#### **2.3.7 获取XAS当前供应值** -接口地址:/api/blocks/getSupply -请求方式:get -支持格式:无 -请求参数说明:无 - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|supply|integer |全网XAS个数 | - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/getSupply' -``` - -JSON返回示例: -```js -{"success":true,"supply":10049222600000000} //当前testnet共有100492226XAS -``` - -#### **2.3.8 区块链状态** -接口地址:/api/blocks/getStatus -请求方式:get -支持格式:无 -请求参数说明:无 - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|height|integer |区块链高度 | -|fee|integer |交易手续费 | -|milestone|integer | | -|reward|integer |区块奖励 | -|supply|integer |全网XAS个数 | - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/getStatus' -``` - -JSON返回示例: -```js -{ - "success": true, - "height": 140649, - "fee": 10000000, - "milestone": 0, - "reward": 350000000, - "supply": 10049227150000000 -} -``` - - -#### **2.3.9 获取指定区块的交易信息** -接口地址:/api/blocks/full -请求方式:get -支持格式:无 -请求参数说明:无 - - -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |---- |---- | -|id |string |参数2选1 |区块id | -|height|string|参数2选1|区块高度| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|block|json |区块详情,包含交易信息transactions | - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/full?height=2392' -``` - -JSON返回示例: -```js -{ - success: true, - block: { - id: "99773e6fc4feddc2d876427701ce2b52aabfefc8b54a5a8560ed237acb1c9565", - version: 0, - timestamp: 39605950, - height: 2392, - previousBlock: "436ca0351028854792ca63862e01b5285b017dd40bc8748a97c1de034e97817f", - numberOfTransactions: 1, - totalAmount: 100000000, - totalFee: 10000000, - reward: 350000000, - payloadLength: 117, - payloadHash: "07af33c345f733e5224877b290888db2faab26e779e784881fadb086148335f1", - generatorPublicKey: "1b36e7183125e3de33a4d778c5a705d4e6180e426b15f4737b18d1e09c150a42", - generatorId: "8280768395963849562", - blockSignature: "59b292c97e68f8a0fc311c0894e79e1fe23613b2387f42e389e0b5f4aba61847fb13feb8153578b3eb37d6249c13347001cce9c4d06ae521b6c8cefedb829804", - totalForged: 360000000, - transactions: [{ // 该区块包含的交易信息数组 - id: "07af33c345f733e5224877b290888db2faab26e779e784881fadb086148335f1", - height: 2392, - blockId: "99773e6fc4feddc2d876427701ce2b52aabfefc8b54a5a8560ed237acb1c9565", - type: 0, - timestamp: 39605935, - senderPublicKey: "8065a105c785a08757727fded3a06f8f312e73ad40f1f3502e0232ea42e67efd", - requesterPublicKey: "", - senderId: "14762548536863074694", - recipientId: "1", - amount: 100000000, - fee: 10000000, - signature: "72b72b3db7eb86436a32bff72f19f89fffc51e10f73ca19536968e70d34c38efd24e96ce43e5d4981a23b07849c9baa20263aeadd9dbbbad233c3efa2fa97100", - signSignature: "", - signatures: null, - args: null, - message: "", - asset: { - - } - }] - } -} -``` - - -### **2.4 受托人delegates** - -#### **2.4.1 获取受托人总个数** -接口地址:/api/delegates/count -请求方式:get -支持格式:无 -请求参数说明:无 - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|count|integer |受托人总个数 | - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/delegates/count' -``` - -JSON返回示例: -```js -{ - "success": true, - "count": 234 -} -``` - -#### **2.4.2 根据受托人公钥查看哪些人为其投了票** -接口地址:/api/delegates/voters -请求方式:get -支持格式:urlencoded -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|publicKey |string |Y |受托人公钥 | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|accounts|Array |账户json串组成的数组 | - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/delegates/voters?publicKey=ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7' -``` - -JSON返回示例: -```js -{ - "success": true, - "accounts": [{ - "address": "2918354313445278349", - "publicKey": "4fde4c49f1297d5d3a24b1494204543c4281aff17917ff7ff8ff32da3b4b222f", - "balance": 1338227722727, - "weight": 0.013316660647014596 - }, - { - "address": "1523444724068322527", - "publicKey": "8a6a61c28dc47541aadf1eecec2175c8f768f2331eea3472b1593bf1aa4e1fb4", - "balance": 2109297623765, - "weight": 0.020989552213127274 - }, - { - "address": "14483826354741911727", - "publicKey": "5dacb7983095466b9b037690150c3edec0f073815326e33a4744b6d1d50953e2", - "balance": 5135815841470, - "weight": 0.051106336795243436 - } - }] -} -``` - -#### **2.4.3 根据公钥或者用户名获取受托人详情** -接口地址: /api/delegates/get -请求方式:get -支持格式:urlencoded -接口备注:通过公钥或者用户名获取受托人信息 -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|publickey |string |二选一 |受托人公钥 | -|username |string |二选一 |受托人用户名 | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|delegate|json |委托人详情 | - - -请求示例: -```bash -curl -k -X GET http://45.32.248.33:4096/api/delegates/get?publicKey=bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9 -curl -k -X GET http://45.32.248.33:4096/api/delegates/get?username=delegate_register -``` - -JSON返回示例: -```js -{ - "success": true, - "delegate": { - "username": "delegate_register", - "address": "16723473400748954103", - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9", - "vote": 0, - "producedblocks": 0, - "missedblocks": 0, - "fees": 0, - "rewards": 0, - "rate": 191, - "approval": 0, - "productivity": 0, - "forged": "0" - } -} -``` - -#### **2.4.4 获取受托人列表** -接口地址:/api/delegates -请求方式:get -支持格式:urlencoded -接口说明:如果不加参数则会返回全网受托人列表 -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|address |string |N |受托人地址 | -|limit|int |N |限制返回结果数据集的个数 | -|offset|integer |N |偏移量,最小值:0 | -|orderBy|string |N |排序字段:排序规则,如:desc | - - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|delegates|Array |受托人详情列表 | - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/delegates?orderby=approval:desc&limit=2' //按照得票率降序排序,取出前2名 -``` - -JSON返回示例: -```js -{ - "success": true, - "delegates": [{ - "username": "wgl_002", //受托人名字 - "address": "14636456069025293113", //受托人地址 - "publicKey": "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7", //受托人公钥 - "vote": 9901984015600500, //得票数 - "producedblocks": 1371, //生成的区块数 - "missedblocks": 6, //丢失的区块数 - "fees": 12588514990, - "rewards": 276850000000, //已经得到的奖励 - "rate": 1, - "approval": 98.54, //得票率 - "productivity": 99.56, //生产率 - "forged": "289438514990" //锻造产生的所有奖励 - }, - { - "username": "wgl_003", - "address": "9961157415582672274", - "publicKey": "c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2", - "vote": 9891994035600500, - "producedblocks": 1370, - "missedblocks": 8, - "fees": 12355148480, - "rewards": 275100000000, - "rate": 2, - "approval": 98.44, - "productivity": 99.42, - "forged": "287455148480" - }], - "totalCount": 233 -} -``` - - -#### **2.4.5 获取受托人设置的转账费** -接口地址:/api/delegates/fee -请求方式:get -支持格式:urlencoded -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|publicKey |string |Y |受托人公钥 | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|fee|integer |转账费 | - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/delegates/fee?publicKey=ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7' -``` - -JSON返回示例: -```js -{"success":true,"fee":10000000000} //0.1 XAS -``` - -#### **2.4.6 根据公钥查看其锻造情况** -接口地址:/api/delegates/forging/getForgedByAccount -请求方式:get -支持格式:urlencoded -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|generatorPublicKey |string |Y |区块生成者公钥 | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|fees|integer |收取的手续费 | -|rewards|integer|已获得奖励| -|forged|integer|锻造获得的总奖励| - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/delegates/forging/getForgedByAccount?generatorPublicKey=ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7' -``` - -JSON返回示例: -```js -{ - "success": true, - "fees": 12589307065, - "rewards": 285600000000, - "forged": 298189307065 -} -``` - -#### **2.4.7 注册受托人** -接口地址:/api/delegates -请求方式:put -支持格式:urlencoded -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|secret |string |Y |asch账户密码 | -|publicKey|string |N |公钥| -|secondSecret|string|N|asch账户二级密码,最小长度:1,最大长度:100| -|username|string|N|受托人名字| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transaction|json |注册受托人交易详情 | - - -请求示例: -```bash -curl -k -H "Content-Type: application/json" -X PUT -d '{"secret":"unaware label emerge fancy concert long fiction report affair appear decide twenty","username":"delegate_0821"}' 'http://45.32.248.33:4096/api/delegates' -``` - -JSON返回示例: -```js -{ - "success": true, - "transaction": { - "type": 2, //注册受托人的交易类型为2 - "amount": 0, - "senderPublicKey": "3b64f1833e6328043e1f2fee31e638bdaa6dfff5c7eb9c8577a5cefcf11261f2", - "requesterPublicKey": null, - "timestamp": 4737615, - "asset": { - "delegate": { - "username": "delegate_0821", - "publicKey": "3b64f1833e6328043e1f2fee31e638bdaa6dfff5c7eb9c8577a5cefcf11261f2" - } - }, - "recipientId": null, - "signature": "7f8417e8db5f58ddff887c86c789c26b32fd3f01083ef1e3c8d4e18ed16622bf766492d78518c6c7a07aada1c98b1efc36d40c8e09394989dbde229d8e3f8103", - "id": "16351320834453011577", - "fee": 10000000000, - "senderId": "250438937633388106" - } -} -``` - -#### **2.4.8 受托人开启锻造** -接口地址:/api/delegates/forging/enable -请求方式:post -支持格式:urlencoded // url必须是受托人所在服务器 -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|secret |string |Y |asch账户密码 | -|publicKey|string |N |公钥| - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|address|string |受托人地址 | - - -请求示例: -```bash -curl -k -H "Content-Type: application/json" -X POST -d '{"secret":"motion group blossom coral upper warrior pattern fragile sister misery palm detect"}' 'http://localhost:4096/api/delegates/forging/enable' -``` - -JSON返回示例: -```js -{"success":true,"address":"16358246403719868041"} -``` - -#### **2.4.9 受托人关闭锻造** -接口地址:/api/delegates/forging/disable -请求方式:post -支持格式:urlencoded // url必须是受托人所在服务器 -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|secret |string |Y |asch账户密码 | -|publicKey|string |N |公钥| - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|address|string |受托人地址 | - - -请求示例: -```bash -curl -k -H "Content-Type: application/json" -X POST -d '{"secret":"motion group blossom coral upper warrior pattern fragile sister misery palm detect"}' 'http://localhost:4096/api/delegates/forging/disable' -``` - -JSON返回示例: -```js -{"success":true,"address":"16358246403719868041"} -``` - -#### **2.4.10 受托人锻造状态查看** -接口地址:/api/delegates/forging/status -请求方式:get -支持格式:urlencoded -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|publicKey|string |Y |公钥| - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|enabled|string |锻造是否开启 | - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/delegates/forging/status?publicKey=fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575' -``` - -JSON返回示例: -```js -{"success":true,"enabled":false} -``` - -### **2.5 节点peers** - -#### **2.5.1 获取本机连接的所有节点信息** -接口地址:/api/peers -请求方式:get -支持格式:urlencoded -备注:展示节点只是和本机有连接的节点,并不是全网所有的节点 -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|state |integer |N |节点状态,0: ,1:,2:,3: | -|os|string|N|内核版本| -|version|string|N|asch版本号| -|limit |integer |N |限制结果集个数,最小值:0,最大值:100 | -|orderBy|string|N|| -|offset|integer |N |偏移量,最小值0 | -|port|integer|N|端口,1~65535| - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|peers|Array |节点信息json构成的数组 | -|totalCount|integer|当前正在运行的节点个数| - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/peers?limit=1' -``` - -JSON返回示例: -```js -{ - "success": true, - "peers": [{ - "ip": "45.32.19.241", - "port": 4096, - "state": 2, - "os": "linux3.13.0-87-generic", - "version": "1.0.0" - }], - "totalCount": ["54"] -} -``` - -#### **2.5.2 获取本节点版本号等信息** -接口地址:/api/peers/version -请求方式:get -支持格式:无 -请求参数说明:无参数 - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|version|string |版本号 | -|build |timestamp |构建时间 | -|net |string |主链或者测试链 | - - -请求示例: -```bash -curl -k -X GET http://45.32.248.33:4096/api/peers/version -``` - -JSON返回示例: -```js -{ - "success": true, - "version": "1.0.0", - "build": "12:11:11 16/08/2016", - "net": "testnet" -} -``` - -#### **2.5.3 获取指定ip节点信息** -接口地址:/api/peers/get -请求方式:get -支持格式:urlencoded -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|ip |string |Y |待查询节点ip | -|port|integer|Y|待查询节点端口,1~65535| - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|peer|json | | - - -请求示例: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/peers/get?ip=45.32.248.33&port=4096' -``` - -JSON返回示例: -```js -{ - "success": true, - "peer": { - } -} -``` - - -### **2.6 同步和加载** -#### **2.6.1 查看本地区块链加载状态** -接口地址:/api/loader/status -请求方式:get -支持格式:无 -请求参数说明:无参数 - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|loaded |boole | | -|blocksCount|integer|| - -请求示例: -```bash -curl -k http://45.32.248.33:4096/api/loader/status -X GET -``` - -JSON返回示例: -```js -{ - "success": true, - "loaded": true, - "blocksCount": 0 -} -``` - -#### **2.6.2 查看区块同步信息** -接口地址:/api/loader/status/sync -请求方式:get -支持格式:无 -请求参数说明:无参数 - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|height |int |区块高度 | - -请求示例: -```bash -curl -k http://45.32.248.33:4096/api/loader/status/sync -X GET -``` - -JSON返回示例: -```js -{ - "success": true, - "syncing": false, // 是否在同步中,如果是则为true,目前没有数据可以同步所以为false - "blocks": 0, - "height": 111987 -} -``` - -### **2.7 二级密码signatures** -#### **2.7.1 设置二级密码** -接口地址:/api/signatures -请求方式:put -支持格式:json -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|secret |string |Y |asch账户密码 | -|publicKey|string |N|公钥 | -|secondSecret|string|Y|asch账户二级密码,最小长度:1,最大长度:100| -|multisigAccountPublicKey|string|N|多重签名账户公钥| - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transaction|json |设置二级密码产生的交易详情 | - - -请求示例: -```bash -curl -k -H "Content-Type: application/json" -X PUT -d '{"secret":"unaware label emerge fancy concert long fiction report affair appear decide twenty","secondSecret":"fault still attack alley expand music basket purse later educate follow ride"}' 'http://45.32.248.33:4096/api/signatures' -``` - -JSON返回示例: -```js -{ - "success": true, - "transaction": { - "type": 1, //设置二级密码密码的交易类型为1 - "amount": 0, - "senderPublicKey": "3b64f1833e6328043e1f2fee31e638bdaa6dfff5c7eb9c8577a5cefcf11261f2", - "requesterPublicKey": null, - "timestamp": 4872315, - "asset": { - "signature": { - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9" - } - }, - "recipientId": null, - "signature": "e76d9b25ec0fdaa88b19d59c5a222b7efdc04f738ee05896f55f4e6959229d9b1600ca25aa92fbea176668f3be7c12c506f2091e2b38c52ef0ece7a5d35e240a", - "id": "1614688380530105232", - "fee": 500000000, //设置二级密码密码的手续费为5 XAS - "senderId": "250438937633388106" - } -} -``` - -#### **2.7.2 获取二级密码设置手续费** -接口地址:/api/signatures/fee -请求方式:get -支持格式:无 -请求参数说明:无 - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|fee|integer |费用 | - - -请求示例: -```bash -curl -k http://45.32.248.33:4096/api/signatures/fee -X GET -``` - -JSON返回示例: -```js -{ - "success": true, - "fee": 500000000 //5 XAS -} -``` - - -### **2.8 多重签名multisignatures** -#### **2.8.1 设置普通账户为多重签名账户** -接口地址:/api/multisignatures -请求方式:put -支持格式:json -接口说明:返回结果只是生成交易id,还需要其他人签名后该账户才能成功设置成多重签名账户。注册多重签名账户后任意一笔转账都需要多人签名,签名最少个数为min的值(含交易发起人自身) -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|secret |string |Y |asch账户密码 | -|publicKey|string |N|公钥 | -|secondSecret|string|N|asch账户二级密码,最小长度:1,最大长度:100| -|min|integer|Y|多重签名交易账户的任意一笔转账都需要多人签名的最少个数,如果是注册多重签名账户操作,这该值不生效(此时需要所有人都签名)。最小值:2,最大值:16,该值需要小于keysgroup.length+1| -|lifetime|integer|Y|多重签名交易的最大挂起时间,最小值:1,最大值:24,暂时不生效| -|keysgroup|array|Y|其它签名人的公钥数组,每个公钥前需要加上+或者-号,代表增加/删除多重签名账户,数组最小长度:1,数组最大长度:10| - - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transactionId|string |多重签名交易的id | - - -请求示例: -```bash -curl -k -H "Content-Type: application/json" -X PUT -d '{"secret":"vanish deliver message evil canyon night extend unusual tell prosper issue antenna","min":2,"lifetime":1,"keysgroup":["+eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97","+d5d7aa157f866c47a2a1e09e2746286ed089fd90976b54fbfa930e87d11609cb"]}' 'http://45.32.248.33:4096/api/multisignatures' //公钥为2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd -``` - -JSON返回示例: -```js -{ - "success": true, - "transactionId": "17620378998277022323" //返回结果只是生成交易id,还需要其他人签名后该账户才能成功设置成多重签名账户 -} -``` - -#### **2.8.2 根据公钥获取挂起的多重签名交易详情** -接口地址:/api/multisignatures/pending -请求方式:get -支持格式:urlencoded -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|publicKey|string |Y|公钥 | - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transactions|Array |交易json组成的数组 | - - -请求示例: -```bash -curl -k -X GET http://45.32.248.33:4096/api/multisignatures/pending?publicKey=2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd -``` - -JSON返回示例: -```js -{ - "success": true, - "transactions": [{ //上一步中设置账户为多重签名交易的详情,transactionId: 17620378998277022323 - "min": 2, - "lifetime": 1, - "signed": true, - "transaction": { - "type": 4, //4代表注册多重签名账户 - "amount": 0, - "senderPublicKey": "2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd", - "requesterPublicKey": null, - "timestamp": 4879978, - "asset": { - "multisignature": { - "min": 2, - "keysgroup": ["+eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97", - "+d5d7aa157f866c47a2a1e09e2746286ed089fd90976b54fbfa930e87d11609cb"], - "lifetime": 1 - } - }, - "recipientId": null, - "signature": "a42feaccd9f2a4940fc0be1a1580e786b360f189db3154328f307988e75484293eae391f2f9eee489913cc6d15984eb1f5f5a0aa1bf78ea745d5c725f161af08", - "id": "17620378998277022323", - "fee": 1500000000, - "senderId": "3855903394839129841" - } - }] -} - -``` - -#### **2.8.3 非交易发起人对交易进行多重签名** -接口地址:/api/multisignatures/sign -请求方式:post -支持格式:json -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|secret |string |Y |asch账户密码 | -|secondSecret|string|N|asch账户二级密码,最小长度:1,最大长度:100| -|publicKey|string |N|公钥 | -|transactionId|string|Y|交易id| - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|transactionId|string |多重签名交易id | - - -请求示例: -```bash -curl -k -H "Content-Type: application/json" -X POST -d '{"secret":"lemon carpet desk accuse clerk future oyster essay seminar force live dog","transactionId":"17620378998277022323"}' 'http://45.32.248.33:4096/api/multisignatures/sign' //公钥为eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97的用户进行签名 -``` - -JSON返回示例: -```js -{ - "success": true, - "transactionId": "17620378998277022323" -} -// 此时再次获取pending -curl -k -X GET http://45.32.248.33:4096/api/multisignatures/pending?publicKey=2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd -{ - "success": true, - "transactions": [{ - "min": 2, - "lifetime": 1, - "signed": true, - "transaction": { - "type": 4, - "amount": 0, - "senderPublicKey": "2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd", - "requesterPublicKey": null, - "timestamp": 4879978, - "asset": { - "multisignature": { - "min": 2, - "keysgroup": ["+eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97", - "+d5d7aa157f866c47a2a1e09e2746286ed089fd90976b54fbfa930e87d11609cb"], - "lifetime": 1 - } - }, - "recipientId": null, - "signature": "a42feaccd9f2a4940fc0be1a1580e786b360f189db3154328f307988e75484293eae391f2f9eee489913cc6d15984eb1f5f5a0aa1bf78ea745d5c725f161af08", - "id": "17620378998277022323", - "fee": 1500000000, - "senderId": "3855903394839129841", - "signatures": ["b38a161264db2a23e353d3fbc4983562f6343d5ee693144543ca54e2bc67c0f73d1c761b7bfa38b2bb101ac2ab0797b674b1a9964ccd400aaa310746c3494d03"] //新生成的多重签名 - } - }] -} - -// 公钥为d5d7aa157f866c47a2a1e09e2746286ed089fd90976b54fbfa930e87d11609cb的账户对该注册交易进行签名 -curl -k -H "Content-Type: application/json" -X POST -d '{"secret":"chalk among elbow piece badge try van round quality position simple teach","transactionId":"17620378998277022323"}' 'http://45.32.248.33:4096/api/multisignatures/sign' -{"success":true,"transactionId":"17620378998277022323"} -// 此时再次获取pending,结果为空 -curl -k -X GET http://45.32.248.33:4096/api/multisignatures/pending?publicKey=2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd -{"success":true,"transactions":[]} -// 查看该注册交易详情(该交易已广播并写入blockchain),此时该账户已成功注册成为多重签名账户 -curl -k -X GET http://45.32.248.33:4096/api/transactions/get?id=17620378998277022323 -{ - "success": true, - "transaction": { - "id": "17620378998277022323", //注册账户为多重签名用户的交易id - "height": "157013", - "blockId": "4680888982781013372", - "type": 4, - "timestamp": 4879978, - "senderPublicKey": "2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd", - "senderId": "3855903394839129841", - "recipientId": "", - "amount": 0, - "fee": 1500000000, - "signature": "a42feaccd9f2a4940fc0be1a1580e786b360f189db3154328f307988e75484293eae391f2f9eee489913cc6d15984eb1f5f5a0aa1bf78ea745d5c725f161af08", - "signSignature": "", - "signatures": null, - "confirmations": "26", - "asset": { - - } - } -} - -``` - -#### **2.8.4 获取多重签名账户信息** -接口地址:/api/multisignatures/accounts -请求方式:get -支持格式:urlencoded -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|publicKey |string |Y |多重签名参与者之一的公钥 | - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据 | -|accounts|Array |多重签名账户详情 | - - -请求示例: -```bash -curl -k -X GET http://45.32.248.33:4096/api/multisignatures/accounts?publicKey=eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97 -``` - -JSON返回示例: -```js -{ - "success": true, - "accounts": [{ - "address": "3855903394839129841", //多重签名账户地址 - "balance": 18500000000, //多重签名账户余额 - "multisignatures": ["eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97", - "d5d7aa157f866c47a2a1e09e2746286ed089fd90976b54fbfa930e87d11609cb"], //多重签名账户公钥 - "multimin": 2, //最少签名个数 - "multilifetime": 1, - "multisigaccounts": [{ //签名者账户详情 - "address": "13542769708474548631", - "publicKey": "eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97", - "balance": 0 - }, - { - "address": "4100816257782486230", - "publicKey": "d5d7aa157f866c47a2a1e09e2746286ed089fd90976b54fbfa930e87d11609cb", - "balance": 0 - }] - }] -} -``` - -### **2.9 点对点传输tansport[安全的api]** -#### **2.9.1 说明** -/peer相关的api,在请求时都需要设置一个header - - - key为magic,testnet value:594fe0f3, mainnet value:5f5b3cf5 - - key为version,value为'' - -#### **2.9.2 普通交易** -asch系统的所有写操作都是通过发起一个交易来完成的。 -交易数据通过一个叫做asch-js的库来创建,然后再通过一个POST接口发布出去 - -POST接口规格如下: -payload为asch-js创建出来的交易数据 -接口地址:/peer/transactions -请求方式:post -支持格式:json - -##### **2.9.2.1 设置二级密码** -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|transaction|json|Y|asch-js.signature.createSignature生成的交易数据| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | - - -请求示例: -```js -var asch = require('asch-js'); -var password = 'measure bottom stock hospital calm hurdle come banner high edge foster cram'; -var secondPassword = 'erjimimashezhi001'; -var transaction = asch.signature.createSignature(password,secondPassword); -console.log(JSON.stringify(transaction)) -{"type":1,"amount":0,"fee":500000000,"recipientId":null,"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","timestamp":5328943,"asset":{"signature":{"publicKey":"27116db89cb5a8c02fb559712e0eabdc298480d3c79a089b803e35bc5ef7bb7b"}},"signature":"71ef98b1600f22f3b18cfcf17599db3c40727c230db817f610e86454b62df4fb830211737ff0c03c6a61ecfd4a9fcb68a30b2874060bb33b87766acf800e820a","id":"15605591820551652547"} - -// 将上面生成的设置二级密码的交易数据通过post提交给asch server -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":1,"amount":0,"fee":500000000,"recipientId":null,"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","timestamp":5328943,"asset":{"signature":{"publicKey":"27116db89cb5a8c02fb559712e0eabdc298480d3c79a089b803e35bc5ef7bb7b"}},"signature":"71ef98b1600f22f3b18cfcf17599db3c40727c230db817f610e86454b62df4fb830211737ff0c03c6a61ecfd4a9fcb68a30b2874060bb33b87766acf800e820a","id":"15605591820551652547"}}' http://45.32.248.33:4096/peer/transactions -``` - -JSON返回示例: -```js -{ - "success":true //二级密码设置成功 -} -``` - -##### **2.9.2.2 转账** -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|transaction|json|Y|asch-js.transaction.createTransaction生成的交易数据| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | - - -请求示例: -```js -var asch = require('asch-js'); -var targetAddress = "16358246403719868041"; -var amount = 100*100000000; //100 XAS -var password = 'measure bottom stock hospital calm hurdle come banner high edge foster cram'; -var secondPassword = 'erjimimashezhi001'; -var message = ''; // 转账备注 - -// 其中password是在用户登录的时候记录下来的,secondPassword需要每次让用户输入 -// 可以通过user.secondPublicKey来判断用户是否有二级密码,如果没有,则不必输入,以下几个交易类型类似 -var transaction = asch.transaction.createTransaction(targetAddress, amount, message, password, secondPassword || undefined); -JSON.stringify(transaction) -'{"type":0,"amount":10000000000,"fee":10000000,"recipientId":"16358246403719868041","message":"","timestamp":37002975,"asset":{},"senderPublicKey":"8065a105c785a08757727fded3a06f8f312e73ad40f1f3502e0232ea42e67efd","signature":"bd0ed22abf09a13c1778ebfb96fc8584dd209961cb603fd0d818d88df647a926795b5e3c51e23f6ed38648169f4e4c912dd854725c22cce9bbdc15ec51c23008","id":"de72b89312c7d128db28611ed36eab2ff0136912c4a67f97342417c942b055cf"}' - -// 将上面生成的转账操作的交易数据通过post提交给asch server -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":0,"amount":10000000000,"fee":10000000,"recipientId":"16358246403719868041","message":"","timestamp":37002975,"asset":{},"senderPublicKey":"8065a105c785a08757727fded3a06f8f312e73ad40f1f3502e0232ea42e67efd","signature":"bd0ed22abf09a13c1778ebfb96fc8584dd209961cb603fd0d818d88df647a926795b5e3c51e23f6ed38648169f4e4c912dd854725c22cce9bbdc15ec51c23008","id":"de72b89312c7d128db28611ed36eab2ff0136912c4a67f97342417c942b055cf"}}' http://45.32.248.33:4096/peer/transactions -``` - -JSON返回示例: -```js -{ - "success":true, //转账成功 - "transactionId":"a95c3a5bda15f3fd38295950268c234e922aae97cf803dd8c38c73a6ccf7c561" -} -``` - -##### **2.9.2.3 注册受托人** -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|transaction|json|Y|asch-js.delegate.createDelegate生成的交易数据| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | - - -请求示例: -```js -var asch = require('asch-js'); -var password = 'measure bottom stock hospital calm hurdle come banner high edge foster cram'; -var secondPassword = 'erjimimashezhi001'; -var userName = 'zhenxi_test'; - -var transaction = asch.delegate.createDelegate(userName, password, secondPassword || undefined); -JSON.stringify(transaction) -'{"type":2,"amount":0,"fee":10000000000,"recipientId":null,"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","timestamp":5334485,"asset":{"delegate":{"username":"zhenxi_test","publicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f"}},"signature":"a12ce415d2d21ab46e4c1b918b8717b1d351dd99abd6f2f94d9a1a7e1f32b697f843a05b1851cb857ea45a2476dce592f5ddd612c00cd44488b8b610c57d7f0a","signSignature":"35adc9f1f37d14458e8588f9b4332eedf1151c02480159f64a287a4b0cbb59bfe82040dfec96a4d9560bae99b8eaa1799a7023395db5ddc640d95447992d6e00","id":"12310465407307249905"}' - -// 将上面生成的注册受托人的交易数据通过post提交给asch server -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":2,"amount":0,"fee":10000000000,"recipientId":null,"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","timestamp":5334485,"asset":{"delegate":{"username":"zhenxi_test","publicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f"}},"signature":"a12ce415d2d21ab46e4c1b918b8717b1d351dd99abd6f2f94d9a1a7e1f32b697f843a05b1851cb857ea45a2476dce592f5ddd612c00cd44488b8b610c57d7f0a","signSignature":"35adc9f1f37d14458e8588f9b4332eedf1151c02480159f64a287a4b0cbb59bfe82040dfec96a4d9560bae99b8eaa1799a7023395db5ddc640d95447992d6e00","id":"12310465407307249905"}}' http://45.32.248.33:4096/peer/transactions -``` - -JSON返回示例: -```js -{ - "success":true //注册受托人成功 -} -``` - -##### **2.9.2.4 投票 & 取消投票** - -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|transaction|json|Y|asch-js.vote.createVote生成的交易数据| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | - - -请求示例: -```js -var asch = require('asch-js'); -var password = 'measure bottom stock hospital calm hurdle come banner high edge foster cram'; -var secondPassword = 'erjimimashezhi001'; -// 投票内容是一个列表,列表中的每一个元素是一个符号加上所选择的受托人的公钥,符号为+表示投票,符号为-表示取消投票 -var voteContent = [ - '-ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7', - '+c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2' -]; - -var transaction = asch.vote.createVote(voteContent, password, secondPassword || undefined); -JSON.stringify(transaction) -{"type":3,"amount":0,"fee":10000000,"recipientId":null,"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","timestamp":5334923,"asset":{"vote":{"votes":["-ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7","+c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2"]}},"signature":"6036c2066a231c452a1c83aafd3bb9db3842ee05d5f17813f8264a4294cdec761faa89edf4a95f9b2e2451285807ab18aa9f989ad9a3165b95643179b8e4580f","signSignature":"a216ca739112e6f65986604b9467ccc8058138a7077faf134d6c4d673306cd1c514cc95bd54a036f7c602a56c4b4f2e4e59f6aa7c376cb1429e89054042e050b","id":"17558357483072606427"} - -// 将上面生成的投票的交易数据通过post提交给asch server -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":3,"amount":0,"fee":10000000,"recipientId":null,"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","timestamp":5334923,"asset":{"vote":{"votes":["-ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7","+c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2"]}},"signature":"6036c2066a231c452a1c83aafd3bb9db3842ee05d5f17813f8264a4294cdec761faa89edf4a95f9b2e2451285807ab18aa9f989ad9a3165b95643179b8e4580f","signSignature":"a216ca739112e6f65986604b9467ccc8058138a7077faf134d6c4d673306cd1c514cc95bd54a036f7c602a56c4b4f2e4e59f6aa7c376cb1429e89054042e050b","id":"17558357483072606427"}}' http://45.32.248.33:4096/peer/transactions -``` - -JSON返回示例: -```js -{ - "success":true //投票&取消投票 成功 -} -``` - -##### **2.9.2.5 账户锁仓** -备注:锁仓后且区块高度未达到锁仓高度,则该账户不能执行如下操作: - -|交易类型type|备注| -|----|----| -|0|主链XAS转账| -|6|Dapp充值| -|7|Dapp提现| -|8|存储小文件| -|9|发行商注册| -|10|资产注册| -|13|资发行产| -|14|主链uia转账| - -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|transaction|json|Y|asch-js.transaction.createLock生成的交易数据| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | -|transactionId|string|交易id| - - -请求示例: -```js -var asch = require('asch-js'); -var height = 3500; // 锁仓高度 -var password = 'found knife gather faith wrestle private various fame cover response security predict'; -var secondPassword = ''; - - -// 其中password是在用户登录的时候记录下来的,secondPassword需要每次让用户输入 -// 可以通过user.secondPublicKey来判断用户是否有二级密码,如果没有,则不必输入,以下几个交易类型类似 -var transaction = asch.transaction.createLock(height, password, secondPassword || undefined); -JSON.stringify(transaction) -'{"type":100,"amount":0,"fee":10000000,"recipientId":null,"args":["3500"],"timestamp":39615653,"asset":{},"senderPublicKey":"2856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec4","signature":"46770ea4ba48ebb0abbaae95b7931dd9f6cc0d178ff22ec50b9e97f3f31126b8d0c9c47f7d2e4479124530f7d36d9e1aac72da598330cda3b7404cd48fb10e0c","id":"b71187f59e2a7f6dd68f18b4ddd0bb87f20394473f0388952f0ceedf49596811"}' - -// 将上面生成的转账操作的交易数据通过post提交给asch server -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":100,"amount":0,"fee":10000000,"recipientId":null,"args":["3500"],"timestamp":39615653,"asset":{},"senderPublicKey":"2856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec4","signature":"46770ea4ba48ebb0abbaae95b7931dd9f6cc0d178ff22ec50b9e97f3f31126b8d0c9c47f7d2e4479124530f7d36d9e1aac72da598330cda3b7404cd48fb10e0c","id":"b71187f59e2a7f6dd68f18b4ddd0bb87f20394473f0388952f0ceedf49596811"}}' http://localhost:4096/peer/transactions && echo -``` - -JSON返回示例: -```js -{ - "success":true, // 锁仓成功 - "transactionId":"b71187f59e2a7f6dd68f18b4ddd0bb87f20394473f0388952f0ceedf49596811" -} -``` - -#### **2.9.3 UIA相关交易** -asch系统的所有写操作都是通过发起一个交易来完成的。 -交易数据通过一个叫做asch-js的库来构建,然后再通过一个POST接口发布出去。 - -POST接口规格如下: -payload为asch-js创建出来的交易数据 -接口地址:/peer/transactions -请求方式:post -支持格式:json -公用变量: -``` -var AschJS = require('asch-js'); -// 一级密码 -var secret = 'motion group blossom coral upper warrior pattern fragile sister misery palm detect' -// 二级密码 -var secondSecret = 'erjimima001' -``` - -##### **2.9.3.1 注册资产发行商** -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|transaction|json|Y|AschJS.uia.createIssuer根据发行商名字、描述、一级密码、二级密码生成的交易数据| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | - - -请求示例: -```js -// 发行商名称,唯一标识 -var name = 'IssuerName' -// 发行商描述 -var desc = 'IssuerDesc' -// 构造交易数据 -var trs = AschJS.uia.createIssuer(name, desc, secret, secondSecret) -console.log(JSON.stringify(trs)) -{"type":9,"amount":0,"fee":10000000,"recipientId":null,"senderPublicKey":"fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575","timestamp":19395607,"asset":{"uiaIssuer":{"name":"IssuerName","desc":"IssuerDesc"}},"signature":"c6ed2a4bafe2b8aa31f4aaceacc2a96cb028abbabb2ed062937498c58e24ca5467a340ddd63b67f809a680ff91b83e685c64991eb695494ddb2fdc57e5761607","signSignature":"8eceacbd47c2b8ed335145ced19d7a3a51f99bdd6631d16ed214180c6f80e29bd6d572f45e7c7d685584e55cb5c303cf340406553ece28c9c0a2fa7a777aac0b"} - -// 将生成的交易数据通过post发送给server,注册资产发行商IssuerName -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":9,"amount":0,"fee":10000000,"recipientId":null,"senderPublicKey":"fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575","timestamp":19395607,"asset":{"uiaIssuer":{"name":"IssuerName","desc":"IssuerDesc"}},"signature":"c6ed2a4bafe2b8aa31f4aaceacc2a96cb028abbabb2ed062937498c58e24ca5467a340ddd63b67f809a680ff91b83e685c64991eb695494ddb2fdc57e5761607","signSignature":"8eceacbd47c2b8ed335145ced19d7a3a51f99bdd6631d16ed214180c6f80e29bd6d572f45e7c7d685584e55cb5c303cf340406553ece28c9c0a2fa7a777aac0b"}}' 'http://localhost:4096/peer/transactions' && echo -``` - -JSON返回示例: -```js -{"success":true} -``` - -##### **2.9.3.2 注册资产** -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|transaction|json|Y|AschJS.uia.createAsset根据资产名字、描述、上限、精度、策略、一级密码、二级密码生成的交易数据| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | - - -请求示例: -```js -// 资产名称,发行商名.资产名,唯一标识 -var name = 'IssuerName.CNY'; -var desc = '资产描述'; -// 上限 -var maximum = '1000000'; -// 精度,小数点的位数,这里上限是1000000,精度为3,代表资产IssuerName.CNY的最大发行量为1000.000 -var precision = 3; -// 策略 -var strategy = ''; -// 是否允许注销,默认不允许。0:不允许,1:允许 -var allowWriteoff = 0; -// 是否允许白名单,默认不允许。0:不允许,1:允许 -var allowWhitelist = 0; -// 是否允许黑名单,默认不允许。0:不允许,1:允许 -var allowBlacklist = 0; -// 构造交易数据 -var trs = AschJS.uia.createAsset(name, desc, maximum , precision, strategy, allowWriteoff, allowWhitelist, allowBlacklist, secret, secondSecret) -console.log(JSON.stringify(trs)) -// 返回的结果如下 -{"type":10,"amount":0,"fee":50000000000,"recipientId":null,"senderPublicKey":"fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575","timestamp":48697173,"message":null,"asset":{"uiaAsset":{"name":"IssuerName.CNY","desc":"资产描述","maximum":"1000000","precision":3,"strategy":"","allowBlacklist":0,"allowWhitelist":0,"allowWriteoff":0}},"signature":"17e12a741375bd0420b9e88a5be5b8563c12d90961914477116eb95ca5df119ca73c8edbcefef071a69bf5bf8a2b9829ed0e0d6fc3efedaaa16b528aa6239f04","signSignature":"a325267c0fc9cfcbed848494b7577dfe85f2ca751dcb02336ff84153cf46e79e99dc87a377f56ce2e500331f04df952415e38b7e3e8cbdb90192c99a0787120b","id":"8ef0982580b58094cb87f1f81c0cf3fa5588ec86681895b44b946ebbf05951d4"} - -// 将生成的交易数据通过post发送给server,注册资产IssuerName.CNY -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{{"type":10,"amount":0,"fee":50000000000,"recipientId":null,"senderPublicKey":"fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575","timestamp":48697173,"message":null,"asset":{"uiaAsset":{"name":"IssuerName.CNY","desc":"资产描述","maximum":"1000000","precision":3,"strategy":"","allowBlacklist":0,"allowWhitelist":0,"allowWriteoff":0}},"signature":"17e12a741375bd0420b9e88a5be5b8563c12d90961914477116eb95ca5df119ca73c8edbcefef071a69bf5bf8a2b9829ed0e0d6fc3efedaaa16b528aa6239f04","signSignature":"a325267c0fc9cfcbed848494b7577dfe85f2ca751dcb02336ff84153cf46e79e99dc87a377f56ce2e500331f04df952415e38b7e3e8cbdb90192c99a0787120b","id":"8ef0982580b58094cb87f1f81c0cf3fa5588ec86681895b44b946ebbf05951d4"}}' 'http://localhost:4096/peer/transactions' && echo -``` - -JSON返回示例: -```js -{"success":true} -``` - -##### **2.9.3.3 资产设置acl模式** -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|transaction|json|Y|AschJS.uia.createFlags根据资产名、流通状态、黑白名单模式、一级密码、二级密码生成的交易数据| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | - - -请求示例: -```js -var currency = 'IssuerName.CNY' -// 资产是否注销,1:流通,2:注销 -var flagType = 1 -// 访问控制列表的类型,0:黑名单, 1:白名单,资产创建后默认为黑名单模式 -var flag = 1 -var trs = AschJS.uia.createFlags(currency, flagType, flag, secret, secondSecret) -console.log(JSON.stringify(trs)) -{"type":11,"amount":0,"fee":10000000,"recipientId":null,"senderPublicKey":"fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575","timestamp":19400996,"asset":{"uiaFlags":{"currency":"IssuerName.CNY","flagType":1,"flag":1}},"signature":"b96fb3d1456e1f26357109cc24d82834eb9a4687f29e69c374bbb1d534568336e148cac52f213aa4d2a69185092f8e1143b49ec4b8048cd9b3af4e20f6ba0b08","signSignature":"b37c77ebebe90341346be2aefe1e12bd7403e5d8f4d6e8f04630190b3e09494a28820da0ffd5f9ff011033aa6d70fc9bb4c159a4493be3b18fd7ff470103570d"} - -// 将生成的交易数据通过post发送给server,将acl改为白名单模式 -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":11,"amount":0,"fee":10000000,"recipientId":null,"senderPublicKey":"fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575","timestamp":19400996,"asset":{"uiaFlags":{"currency":"IssuerName.CNY","flagType":1,"flag":1}},"signature":"b96fb3d1456e1f26357109cc24d82834eb9a4687f29e69c374bbb1d534568336e148cac52f213aa4d2a69185092f8e1143b49ec4b8048cd9b3af4e20f6ba0b08","signSignature":"b37c77ebebe90341346be2aefe1e12bd7403e5d8f4d6e8f04630190b3e09494a28820da0ffd5f9ff011033aa6d70fc9bb4c159a4493be3b18fd7ff470103570d"}}' 'http://localhost:4096/peer/transactions' && echo -``` - -JSON返回示例: -```js -{"success":true} -``` - -##### **2.9.3.4 更新访问控制列表(acl)** -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|transaction|json|Y|AschJS.uia.createAcl根据资产名字、列表操作方法、黑名单还是白名单、地址列表、一级密码、二级密码生成的交易数据| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | - - -请求示例: -```js -var currency = 'IssuerName.CNY' -// '+'表示增加列表, ‘-’表示删除列表 -var operator = '+' -var list = ['15745540293890213312'] -// 访问控制列表的类型,0:黑名单, 1:白名单 -var flag =1 -var trs = AschJS.uia.createAcl(currency, operator, flag, list, secret, secondSecret) -console.log(JSON.stringify(trs)) -{"type":12,"amount":0,"fee":20000000,"recipientId":null,"senderPublicKey":"fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575","timestamp":19403125,"asset":{"uiaAcl":{"currency":"IssuerName.CNY","operator":"+","flag":1,"list":["15745540293890213312"]}},"signature":"ad4060e04c1a12256de114e34499f8add24326753f1f8362991ee14aefc4c0fe90ff394d2db97e83770855a5688d463de00656fdd2d04604605cf3c04fdaca0e","signSignature":"63129c58b1b9fcce88cbe829f3104a10ab06037253e9b65feb50ce0d2bb988533b93e8edcad016a85675f9027758fc318cf899ca7ef161a95a8d8a055ae83a02"} - -// 将生成的交易数据通过post发送给server,把地址列表['15745540293890213312']增加到该白名单中,只修改名单列表,不修改acl模式,手续费0.2XAS -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":12,"amount":0,"fee":20000000,"recipientId":null,"senderPublicKey":"fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575","timestamp":19403125,"asset":{"uiaAcl":{"currency":"IssuerName.CNY","operator":"+","flag":1,"list":["15745540293890213312"]}},"signature":"ad4060e04c1a12256de114e34499f8add24326753f1f8362991ee14aefc4c0fe90ff394d2db97e83770855a5688d463de00656fdd2d04604605cf3c04fdaca0e","signSignature":"63129c58b1b9fcce88cbe829f3104a10ab06037253e9b65feb50ce0d2bb988533b93e8edcad016a85675f9027758fc318cf899ca7ef161a95a8d8a055ae83a02"}}' 'http://localhost:4096/peer/transactions' && echo -``` - -JSON返回示例: -```js -{"success":true} -// 查询更新后的列表(acl/1代表白名单) -curl -X GET -H "Content-Type: application/json" 'http://localhost:4096/api/uia/assets/IssuerName.CNY/acl/1?limit=10&offset=0' && echo -{ - "success": true, - "list": [{ - "address": "15745540293890213312" - }], - "count": 1 -} -``` - - -##### **2.9.3.5 资产发行** -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|transaction|json|Y|AschJS.uia.createIssuer根据发行商名字、描述、一级密码、二级密码生成的交易数据| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | - - -请求示例: -```js -var currency = 'IssuerName.CNY' -// 本次发行量=真实数量(100)*10**精度(3),所有发行量之和需 <= 上限*精度 -var amount = '100000' -var trs = AschJS.uia.createIssue(currency, amount, secret, secondSecret) -console.log(JSON.stringify(trs)) -{"type":13,"amount":0,"fee":10000000,"recipientId":null,"senderPublicKey":"fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575","timestamp":19475744,"asset":{"uiaIssue":{"currency":"IssuerName.CNY","amount":"100000"}},"signature":"32b01a18eca2b0dc7e2ce77ba4e758eaae2532f60844760a762cc20918e7439ac6ca585b921db6ede833ed0bf1c62e30cec545a928abafe0b679183a6ad02202","signSignature":"4fc290d7d7d788e9112a56233df0fe796cba39be3efa0cebf00cbc7e5bc5fd1369fad49e5698d967845b5c02e427926049cab25845d4d385e4a395791906f909"} - -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":13,"amount":0,"fee":10000000,"recipientId":null,"senderPublicKey":"fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575","timestamp":19475744,"asset":{"uiaIssue":{"currency":"IssuerName.CNY","amount":"100000"}},"signature":"32b01a18eca2b0dc7e2ce77ba4e758eaae2532f60844760a762cc20918e7439ac6ca585b921db6ede833ed0bf1c62e30cec545a928abafe0b679183a6ad02202","signSignature":"4fc290d7d7d788e9112a56233df0fe796cba39be3efa0cebf00cbc7e5bc5fd1369fad49e5698d967845b5c02e427926049cab25845d4d385e4a395791906f909"}}' 'http://localhost:4096/peer/transactions' && echo -``` - -JSON返回示例: -```js -{"success":true} -``` - -##### **2.9.3.6 资产转账** -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|transaction|json|Y|AschJS.uia.createTransfer根据资产名字、数量、接收者地址、一级密码、二级密码生成的交易数据| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | - - -请求示例: -```js -var currency = 'IssuerName.CNY' -// 本次转账数(10000)=真实数量(10)*10**精度(3),需 <= 当前资产发行总量 -var amount = '10000' -// 接收地址,需满足前文定义好的acl规则 -var recipientId = 'AKKHPvQb2A119LNicCQWLZQDFxhGVEY57a' -var trs = AschJS.uia.createTransfer(currency, amount, recipientId, secret, secondSecret) -console.log(JSON.stringify(trs)) -{"type":14,"amount":0,"fee":10000000,"recipientId":"AKKHPvQb2A119LNicCQWLZQDFxhGVEY57a","senderPublicKey":"fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575","timestamp":19481489,"asset":{"uiaTransfer":{"currency":"IssuerName.CNY","amount":"10000"}},"signature":"77789071a2ad6d407b9d1e0d654a9deb6d85340a3d2a13d786030e26ac773b4e9b5f052589958d2b8553ae5fc9449496946b5c225e0baa723e7ddecbd89f060a","signSignature":"f0d4a000aae3dd3fa48a92f792d4318e41e3b56cdbaf98649261ae34490652b87645326a432d5deb69f771c133ee4b67d2d22789197be34249e6f7f0c30c1705"} - -// 给AKKHPvQb2A119LNicCQWLZQDFxhGVEY57a发送10.000 IssuerName.CNY资产 -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":14,"amount":0,"fee":10000000,"recipientId":"AKKHPvQb2A119LNicCQWLZQDFxhGVEY57a","senderPublicKey":"fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575","timestamp":19481489,"asset":{"uiaTransfer":{"currency":"IssuerName.CNY","amount":"10000"}},"signature":"77789071a2ad6d407b9d1e0d654a9deb6d85340a3d2a13d786030e26ac773b4e9b5f052589958d2b8553ae5fc9449496946b5c225e0baa723e7ddecbd89f060a","signSignature":"f0d4a000aae3dd3fa48a92f792d4318e41e3b56cdbaf98649261ae34490652b87645326a432d5deb69f771c133ee4b67d2d22789197be34249e6f7f0c30c1705"}}' 'http://localhost:4096/peer/transactions' && echo -``` - -JSON返回示例: -```js -{"success":true} -``` - -##### **2.9.3.7 资产注销** -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|transaction|json|Y|AschJS.uia.createFlags根据资产名字、注销状态、黑白名单模式、一级密码、二级密码生成的交易数据| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | - - -请求示例: -```js -var currency = 'IssuerName.CNY' -// flagType为资产是否注销,1:流通,2:注销 -var flagType = 2 -// flag为黑、白名单模式 -var flag =1 -var trs = AschJS.uia.createFlags(currency, flagType, flag, secret, secondSecret) -console.log(JSON.stringify(trs)) -{"type":11,"amount":0,"fee":10000000,"recipientId":null,"senderPublicKey":"fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575","timestamp":19488690,"asset":{"uiaFlags":{"currency":"IssuerName.CNY","flagType":2,"flag":1}},"signature":"cbd656552417604704703e1236ec2bbed8eba6a2ccfcb54cc0b2d629c0a9d1335a264fc9f6dee1705f4a86c36a5ce2ba8e039d913a189b7c273c8ac0d9e3780c","signSignature":"3c7b91d03efeed2dc86e1f2301da60789751c1be8850460d8c66c0ae8f55ea27d26f0bc79541d74b4777d9b85c518c1c73c0284dbf3e826db0a686560e57a80b"} - -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":11,"amount":0,"fee":10000000,"recipientId":null,"senderPublicKey":"fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575","timestamp":19488690,"asset":{"uiaFlags":{"currency":"IssuerName.CNY","flagType":2,"flag":1}},"signature":"cbd656552417604704703e1236ec2bbed8eba6a2ccfcb54cc0b2d629c0a9d1335a264fc9f6dee1705f4a86c36a5ce2ba8e039d913a189b7c273c8ac0d9e3780c","signSignature":"3c7b91d03efeed2dc86e1f2301da60789751c1be8850460d8c66c0ae8f55ea27d26f0bc79541d74b4777d9b85c518c1c73c0284dbf3e826db0a686560e57a80b"}}' 'http://localhost:4096/peer/transactions' && echo -``` - -JSON返回示例: -```js -{"success":true} -``` - - -#### **2.9.4 其它内部通讯安全接口** -get /peer/list //查找dapp peer -get /peer/blocks/common //查找common block -... - - - -### **2.10 用户自定义资产uia** -#### **2.10.1 获取全网所有发行商** -接口地址:/api/uia/issuers -请求方式:get -支持格式:urlencoded - -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|limit|integer|N|限制结果集个数,最小值:0,最大值:100| -|offset|integer|N|偏移量,最小值0| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | -|issuers|list|元素为字典,每个字典代表一个发行商,包含发行商名字、描述、id(Asch地址)| -|count|integer|发行商总个数| - -请求示例: -```js -curl -X GET -H "Content-Type: application/json" 'http://testnet.asch.so:4096/api/uia/issuers?offset=0&limit=1' && echo -``` - -JSON返回示例: -```js -{ - "success": true, - "issuers": [{ - "name": "zhenxi", - "desc": "注册资产发行商-测试", - "issuerId": "AKKHPvQb2A119LNicCQWLZQDFxhGVEY57a" - }, - { - "name": "speedtest", - "desc": "speedtest", - "issuerId": "AEVWQWAq3TEJkCPSDxXMP2uCRrL2xbQnsy" - }], - "count": 6 -} -``` - -#### **2.10.2 查询指定发行商的信息** -接口地址:/api/uia/issuers/:name -请求方式:get -支持格式:urlencoded - -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|name|string|Y|可以为发行商名称或Asch账户地址| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | -|issuers|dict|包含发行商名字、描述、id(Asch地址)| - -请求示例: -```js -curl -X GET -H "Content-Type: application/json" 'http://testnet.asch.so:4096/api/uia/issuers/zhenxi' && echo -``` - -JSON返回示例: -```js -{ - "success": true, - "issuer": { - "name": "zhenxi", - "desc": "注册资产发行商-测试", - "issuerId": "AKKHPvQb2A119LNicCQWLZQDFxhGVEY57a" - } -} -``` - -#### **2.10.3 查看指定发行商的资产** -接口地址:/api/uia/issuers/:name/assets -请求方式:get -支持格式:urlencoded - -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|name|string|Y|可以为发行商名称或Asch账户地址| -|limit|integer|N|限制结果集个数,最小值:0,最大值:100| -|offset|integer|N|偏移量,最小值0| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | -|assets|list|每个元素是一个字典,每个字典是一个资产详情,包含资产名字、描述、上限(最大发行量=真实发行量*10**精度)、精度、策略、当前发行量、发行高度、发行商id,acl模式(0:黑名单,1:白名单)、是否注销| -|count|interger|该发行商注册的资产总个数(包含已注销的)| - - - -请求示例: -```js -curl -X GET -H "Content-Type: application/json" 'http://testnet.asch.so:4096/api/uia/issuers/zhenxi/assets?offset=0&limit=2' && echo -``` - -JSON返回示例: -```js -{ - "success": true, - "assets": [{ - "name": "zhenxi.UIA", - "desc": "注册资产-测试", - "maximum": "10000000", - "precision": 3, - "strategy": "", - "quantity": "1000000", - "height": 301, - "issuerId": "AKKHPvQb2A119LNicCQWLZQDFxhGVEY57a", - "acl": 0, - "writeoff": 1 - }], - "count": 1 -} -``` - -#### **2.10.4 获取全网所有资产信息** -接口地址:/api/uia/assets -请求方式:get -支持格式:urlencoded - -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|limit|integer|N|限制结果集个数,最小值:0,最大值:100| -|offset|integer|N|偏移量,最小值0| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | -|assets|list|每个元素是一个字典,每个字典是一个资产详情,包含资产名字、描述、上限、精度、策略、当前发行量、发行高度、发行商id,acl、是否注销| -|count|integer|所有资产的个数| - - - -请求示例: -```js -curl -X GET -H "Content-Type: application/json" 'http://testnet.asch.so:4096/api/uia/assets?offset=0&limit=2' && echo -``` - -JSON返回示例: -```js -{ - "success": true, - "assets": [{ - "name": "zhenxi.UIA", - "desc": "注册资产-测试", - "maximum": "10000000", - "precision": 3, - "strategy": "", - "quantity": "1000000", - "height": 301, - "issuerId": "AKKHPvQb2A119LNicCQWLZQDFxhGVEY57a", - "acl": 0, - "writeoff": 1 - }, - { - "name": "speedtest.SPEED", - "desc": "测速", - "maximum": "10000", - "precision": 1, - "strategy": "", - "quantity": "10000", - "height": 380, - "issuerId": "AEVWQWAq3TEJkCPSDxXMP2uCRrL2xbQnsy", - "acl": 0, - "writeoff": 0 - }], - "count": 13 -} -``` - -#### **2.10.5 获取指定资产信息** -接口地址:/api/uia/assets/:name -请求方式:get -支持格式:urlencoded - -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|name|string|Y|资产名| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | -|assets|dict|包含资产名字、描述、上限、精度、策略、当前发行量、发行高度、发行商id,acl、是否注销| - -请求示例: -```js -curl -X GET -H "Content-Type: application/json" 'http://testnet.asch.so:4096/api/uia/assets/zhenxi.UIA' && echo -``` - -JSON返回示例: -```js -{ - "success": true, - "asset": { - "name": "zhenxi.UIA", - "desc": "注册资产-测试", - "maximum": "10000000", - "precision": 3, - "strategy": "", - "quantity": "1000000", - "height": 301, - "issuerId": "AKKHPvQb2A119LNicCQWLZQDFxhGVEY57a", - "acl": 0, - "writeoff": 1 - } -} -``` - -#### **2.10.6 获取指定资产的访问控制列表(acl)** -接口地址:/api/uia/assets/:name/acl/flag -请求方式:get -支持格式:urlencoded - -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|name|string|Y|资产名| -|flag|boole|Y|取值0和1,0表示黑名单,1表示白名单| -|limit|integer|N|限制结果集个数,最小值:0,最大值:100| -|offset|integer|N|偏移量,最小值0| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | -|list|list|符合规则的账户列表| -|count|integer|符合规则账户总数| - - -请求示例: -```js -// 获取资产zhenxi.UIA白名单中的地址列表 -curl -X GET -H "Content-Type: application/json" 'http://localhost:4096/api/uia/assets/zhenxi.UIA/acl/1' && echo -``` - -JSON返回示例: -```js -{ - "success": true, - "list": [{ - "address": "15745540293890213312" - }, - { - "address": "AKKHPvQb2A119LNicCQWLZQDFxhGVEY57a" - }], - "count": 2 -} -``` - -#### **2.10.7 获取指定账户所有uia的余额** -接口地址:/api/uia/balances/:address -请求方式:get -支持格式:urlencoded - -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|address|string|Y|账户地址| -|limit|integer|N|限制结果集个数,最小值:0,最大值:100| -|offset|integer|N|偏移量,最小值0| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | -|balances|list|拥有的资产详情列表,每个元素是一个资产,包含资产名、余额、上限、精度、当前发行量、是否注销(0:未注销,1:已注销)| -|count|integer|当前该地址拥有的资产个数| - -请求示例: -```js -curl -X GET -H "Content-Type: application/json" 'http://localhost:4096/api/uia/balances/AKKHPvQb2A119LNicCQWLZQDFxhGVEY57a' && echo -``` - -JSON返回示例: -```js -{ - "success": true, - "balances": [{ - "currency": "zhenxi.UIA", - "balance": "900000", - "maximum": "10000000", - "precision": 3, - "quantity": "1000000", - "writeoff": 1 - }, - { - "currency": "speedtest.SPEED", - "balance": "400", - "maximum": "10000", - "precision": 1, - "quantity": "10000", - "writeoff": 0 - }], - "count": 2 -} -``` - -#### **2.10.8 获取指定账户所有资产相关操作记录** -接口地址:/api/uia/transactions/my/:address -请求方式:get -支持格式:urlencoded -备注:包含发行商创建以及资产创建、发行、转账等 - -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|address|string|Y|账户地址| -|limit|integer|N|限制结果集个数,最小值:0,最大值:100| -|offset|integer|N|偏移量,最小值0| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | -|transactions|list|交易列表,每个元素是一个字典代表一次交易,包含交易id、区块高度、区块id、交易类型、时间戳、发送者公钥、发送者id、接收者id(系统为空,如资产注册)、交易数量(资产交易都为0)、手续费0.1XAS、签名、多重签名、确认数、资产信息(包含发行商id、发行商名字、描述)、交易id。| -|count|integer|资产交易总个数| - -请求示例: -```js -curl -X GET -H "Content-Type: application/json" 'http://localhost:4096/api/uia/my/transactions/16358246403719868041?offset=0&limit=2' && echo -``` - -JSON返回示例: -```js -{ - "success": true, - "transactions": [{ - "id": "12372526051670720162", // 交易id - "height": "286", // 交易所在区块高度 - "blockId": "14863181420651287815", // 交易所在区块id - "type": 9, // 交易类型,9代表注册发行商 - "timestamp": 17597873, // 交易时间,距离创世块的offset - "senderPublicKey": "d39d6f26869067473d685da742339d1a9117257fe14b3cc7261e3f2ed5a339e3", // 交易发起者公钥 - "senderId": "AKKHPvQb2A119LNicCQWLZQDFxhGVEY57a", // 交易发起者id - "recipientId": "", // 接收者id,如果是系统则为空 - "amount": 0, // 交易数量,如果是资产或者XAS则为非0,否则为0 - "fee": 10000000, // 交易费 - "signature": "6a1e66387f610de5a89489105697082037b82bff4fb6f95f9786304176efe59f7d41e8fe9c5501e1b0b34a47e957a38e10e940fdb180f8ebcaf0ac062a63c601", // 交易签名 - "signSignature": "", // 二级签名,有二级密码时才有 - "signatures": null, // 多重签名,使用多重签名账户时才有 - "confirmations": "155998", // 交易确认数 - "asset": { - "uiaIssuer": { - "transactionId": "12372526051670720162", // 交易id - "name": "zhenxi", // 发行商名字 - "desc": "注册资产发行商-测试" // 发行商描述 - } - }, - "t_id": "12372526051670720162" // 交易id - }, - { - "id": "17308768226103450697", - "height": "371", - "blockId": "244913990990213995", - "type": 9, - "timestamp": 17598730, - "senderPublicKey": "7bd645f9626820d390311fb28dc30875e8bd26cce2d04ba2809df82e84088020", - "senderId": "AEVWQWAq3TEJkCPSDxXMP2uCRrL2xbQnsy", - "recipientId": "", - "amount": 0, - "fee": 10000000, - "signature": "6ea76ff6f58f1bc99d6b40ece45e371948db58a68f6fa41e13b34ff86bbf1f0bea53d6afe982562392861727f879205efc7d1342f6e963028985e243a94e5507", - "signSignature": "", - "signatures": null, - "confirmations": "155913", - "asset": { - "uiaIssuer": { - "transactionId": "17308768226103450697", - "name": "speedtest", - "desc": "speedtest" - } - }, - "t_id": "17308768226103450697" - }], - "count": 58 -} -``` - - -说明: - 注意这里asset内容与type相关,9 <= type <= 14, 根据不同的type从asset中取出不同的值,详情如下: - -``` -type=9 -"asset": { - "uiaIssuer": { - "transactionId": "260434858608363290", - "name": "issuername", - "desc": "issuer1_desc" - } - }, -展示: 注册了发行商"issuername" -``` - -``` -type=10 -"asset": { - "uiaAsset": { - "transactionId": "11613326283813789432", - "name": "issuername.BTC", - "desc": "asset1_desc", - "maximum": "10000000000000", - "precision": "6", - "strategy": "" - } - }, -展示: 注册了资产"issuername.BTC" -``` - -``` -type=11 -"asset": { - "uiaFlags": { - "transactionId": "14649028077581400942", - "currency": "issuername.BTC", - "flagType": "1", - "flag": "1" - } - }, -展示: -如果$flagType==1 : 资产issuername.BTC访问控制设置为(flag==0?黑名单:白名单) -如果$flagType==2 : 资产issuername.BTC被注销 -``` - -``` -type=12 -"asset": { - "uiaAcl": { - "transactionId": "16597707943986371131", - "currency": "issuername.BTC", - "operator": "+", - "flag": "1", - "list": [ - "196751217687897827", - "11053997261735317227" - ] - } - }, -展示:资产issuername.BTC更新了访问控制列表 -``` - -``` -type=13 -"asset": { - "uiaIssue": { - "transactionId": "10646196155790595088", - "currency": "issuername.BTC", - "amount": "10000000000" - } - }, -展示: 资产issuername.BTC新发行10000000000(实际数量*精度) -``` - -``` -type=14 -"asset": { - "uiaTransfer": { - "transactionId": "9105235822289198060", - "currency": "issuername.BTC", - "amount": "10" - } - }, -展示:转账10个issuername.BTC资产,交易id是9105235822289198060 -``` - - - - - -#### **2.10.9 获取指定账户指定资产的余额** -接口地址:/api/uia/balances/:address/:currency -请求方式:get -支持格式:urlencoded - -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|address|string|Y|Asch地址| -|currency|string|Y|资产名字| -|limit|integer|N|限制结果集个数,最小值:0,最大值:100| -|offset|integer|N|偏移量,最小值0| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | -|balances|dict|包含资产名、余额、最大发行量、精度、当前发行量、是否注销| - -请求示例: -```js -curl -X GET -H "Content-Type: application/json" 'http://localhost:4096/api/uia/balances/16358246403719868041/IssuerName.CNY' && echo -``` - -JSON返回示例: -```js -{ - "success": true, - "balance": { - "currency": "IssuerName.CNY", - "balance": "80000", - "maximum": "1000000", - "precision": 3, - "quantity": "100000", - "writeoff": 1 - } -} -``` - -#### **2.10.10 获取指定账户指定资产转账记录** -接口地址:/api/uia/transactions/my/:address/:currency -请求方式:get -支持格式:urlencoded -备注:只返回资产转账记录 - -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|address|string|Y|Asch地址| -|currency|string|Y|资产名字| -|limit|integer|N|限制结果集个数,最小值:0,最大值:100| -|offset|integer|N|偏移量,最小值0| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | -|transactions|list|交易列表,每个元素是一个字典代表一次交易,包含交易id、区块高度、区块id、交易类型、时间戳、发送者公钥、发送者id、接收者id(系统为空,如资产注册)、交易数量(资产交易都为0)、手续费0.1XAS、签名、多重签名、确认数、资产信息(包含发行商id、发行商名字、描述)、交易id。| -|count|integer|资产交易总个数| - -请求示例: -```js -curl -X GET -H "Content-Type: application/json" 'http://localhost:4096/api/uia/transactions/my/16358246403719868041/IssuerName.CNY' && echo -``` - -JSON返回示例: -```js -{ - "success": true, - "transactions": [{ - "id": "d6102fc30931e4dc449811cbbab705fd64bc79b09de703e8172f7bdd90835abc", - "height": "173109", - "blockId": "baa23acd566780e338436b48e4eb79a87d3bdd67caeb3812a663da8f77ae87d9", - "type": 14, - "timestamp": 19481489, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "senderId": "16358246403719868041", - "recipientId": "AKKHPvQb2A119LNicCQWLZQDFxhGVEY57a", - "amount": 0, - "fee": 10000000, - "signature": "77789071a2ad6d407b9d1e0d654a9deb6d85340a3d2a13d786030e26ac773b4e9b5f052589958d2b8553ae5fc9449496946b5c225e0baa723e7ddecbd89f060a", - "signSignature": "f0d4a000aae3dd3fa48a92f792d4318e41e3b56cdbaf98649261ae34490652b87645326a432d5deb69f771c133ee4b67d2d22789197be34249e6f7f0c30c1705", - "signatures": null, - "confirmations": "90853", - "asset": { - "uiaTransfer": { - "transactionId": "d6102fc30931e4dc449811cbbab705fd64bc79b09de703e8172f7bdd90835abc", - "currency": "IssuerName.CNY", - "amount": "10000", - "amountShow": "10" - } - }, - "t_id": "d6102fc30931e4dc449811cbbab705fd64bc79b09de703e8172f7bdd90835abc" - }], - "count": 15 -} -``` - -#### **2.10.11 获取指定资产转账记录** -接口地址:/api/uia/transactions/:currency -请求方式:get -支持格式:urlencoded -备注:只返回指定资产转账记录 - -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|currency|string|Y|资产名字| -|limit|integer|N|限制结果集个数,最小值:0,最大值:100| -|offset|integer|N|偏移量,最小值0| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功 | -|transactions|list|交易列表,每个元素是一个字典代表一次交易,包含交易id、区块高度、区块id、交易类型、时间戳、发送者公钥、发送者id、接收者id(系统为空,如资产注册)、交易数量(资产交易都为0)、手续费0.1XAS、签名、多重签名、确认数、资产信息(包含发行商id、发行商名字、描述)、交易id。| -|count|integer|该资产交易总数| - -请求示例: -```js -// 查询引力波资产absorb.YLB的所有转账记录 -curl -X GET -H "Content-Type: application/json" 'http://127.0.0.1:4096/api/uia/transactions/absorb.YLB' && echo -``` - -JSON返回示例: -```js -{ - success: true, - transactions: [{ - id: "a1ff79e3f37fd73b41abd293c22171ac7760160ad457e55f028e7a8b527651d3", - height: "43", - blockId: "b16b87e79b47edffdc2fd93bd1de70cbe3541684d5dbf8dc1d292903275e03dc", - type: 14, - timestamp: 39167334, - senderPublicKey: "2856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec4", - senderId: "ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M", - recipientId: "AMzDw5BmZ39we18y7Ty9VW79eL9k7maZPH", - amount: 0, - fee: 10000000, - signature: "a4e6b0e2c265e0d601fdfc9e82d971e7908457383835b801c725cdaac01bd619a435344241c64247599255f43a43b6576e1da3a357eac5bbd7058e013a8aa60e", - signSignature: "", - signatures: null, - confirmations: "809", - args: null, - message: "", - asset: { - uiaTransfer: { - transactionId: "a1ff79e3f37fd73b41abd293c22171ac7760160ad457e55f028e7a8b527651d3", - currency: "absorb.YLB", - amount: "200000000", - amountShow: "2", - precision: 8 - } - } - }, - { - id: "7cf50223e12b6eb51096353a066befcf2ef862bdd4d4eddcba28a79aa0249af9", - height: "809", - blockId: "278b096893bc028bb79692faec02de8c2f367804485b71f14e46027f3dd3000c", - type: 14, - timestamp: 39182041, - senderPublicKey: "b33b5fc45640cfc414981985bf92eef962c08c53e1a34f90dab039e985bb5fab", - senderId: "AMzDw5BmZ39we18y7Ty9VW79eL9k7maZPH", - recipientId: "1", - amount: 0, - fee: 10000000, - signature: "560bd31a4efe103ef9bd92f52cae5cf5a3b2aeb90fc83298498ff4126705e0433f751169bc32a3a7cfe894c7d8586d7182ebc790f2311daf9f02b881dc2aca0e", - signSignature: "", - signatures: null, - confirmations: "43", - args: null, - message: "", - asset: { - uiaTransfer: { - transactionId: "7cf50223e12b6eb51096353a066befcf2ef862bdd4d4eddcba28a79aa0249af9", - currency: "absorb.YLB", - amount: "100000000", - amountShow: "1", - precision: 8 - } - } - }], - count: 2 -} -``` - -#### **2.10.12 资产创建相关** -下面没有内容的章节请参考《2.9.3》章节。 -##### **2.10.12.1 注册资产发行商** -##### **2.10.12.2 注册资产** -##### **2.10.12.3 更新资产访问控制列表(acl)** -##### **2.10.12.4 资产发行** -##### **2.10.12.5 资产转账** -接口地址:/api/uia/transfers -请求方式:PUT -支持格式:json -接口备注: -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|secret |string |Y |发送者密码,最大长度100 | -|currency |string |Y |资产名,最大长度22 | -|amount |string |Y |转账金额,最大长度50 | -|recipientId |string |Y |接收地址,最小长度1 | -|publicKey|string|N|发送者公钥,格式必须符合公钥格式| -|secondSecret|string|N|发送者二级密码,最小长度1,最大长度:100| -|multisigAccountPublicKey|string|N|多签账户公钥,格式必须符合公钥格式| -|message|string|N|转账备注,最大长度256| - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据。| -|transactionId|string |交易id | - - -请求示例: -```bash -// 转0.01 absorb.YLB给16723473400748954103 -curl -k -H "Content-Type: application/json" -X PUT -d '{"secret":"found knife gather faith wrestle private various fame cover response security predict","amount":"1000000","recipientId":"16723473400748954103","currency":"absorb.YLB"}' 'http://localhost:4096/api/uia/transfers' && echo -``` - -JSON返回示例: -```js -{ - "success": true, - "transactionId": "3cb6d97534a3b90cf7fc883927f0a9a7c7f4878a9df526c2906ca97e250fcaba" -} -``` - -##### **2.10.12.6 更新黑白名单** - - - -### **2.11 存储storages** -源码在src/core/transactions.js文件中,适合存储短文。 -#### **2.11.1 上传数据** -##### **2.11.1.1 上传数据(直接上传)** -接口地址:/api/storages -请求方式:PUT -支持格式:json -接口备注: -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|secret |string |Y |asch账户密码 | -|secondSecret|string|N|发送者二级密码,最小长度1,最大长度:100| -|content|string|Y|上传数据内容| -|encode|string|N|上传数据的格式,可选项为:raw/base64/hex,默认为raw| -|wait|number|N|等待确认数,范围为0-6,默认为0。wait为0表示不等待,速度最快,但无法保证数据在掉电情况下不丢失,大于2时,可以100%确保数据已经同步到大部分机器上了,但需要时间较长10-20秒之间,折中的方案是1,wait为1时虽然不能100%保证同步到其他机器,但失败的几率非常小,只是理论上存在,实际上还没遇到过| - - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据。| -|transactionId|string |交易id | - - -请求示例: -```bash -// 将字符串"helloworld"用base64进行编码 -console.log(new Buffer('helloworld').toString('base64')); -aGVsbG93b3JsZA== -// Asch用base64方式存储刚才得到的编码值"aGVsbG93b3JsZA==" -curl -k -H "Content-Type: application/json" -X PUT -d '{"secret":"motion group blossom coral upper warrior pattern fragile sister misery palm detect","secondSecret":"erjimima001","content":"aGVsbG93b3JsZA==","encode":"base64","wait":1}' http://localhost:4096/api/storages && echo -``` - -JSON返回示例: -```js -{ - "success": true, - "transactionId": "2ae89f859f20e6e9be7aeef5f7ff7b8c6a457ff712100a1b694436bddd9800c0" -} -``` - -##### **2.11.1.2 上传数据(本地签名后再上传)** - -POST接口规格如下: -payload为asch-js创建出来的交易数据 -接口地址:/peer/transactions -请求方式:post -支持格式:json - -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|secret |string |Y |asch账户密码 | -|secondSecret|string|N|发送者二级密码,最小长度1,最大长度:100| -|content|string|Y|上传数据内容,必须是hex格式| - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据。| -|transactionId|string |交易id | - - -请求示例: -``` -var AschJS = require('asch-js'); -// 一级密码 -var secret = 'motion group blossom coral upper warrior pattern fragile sister misery palm detect' -// 二级密码 -var secondSecret = 'erjimima001' -// 将字符串"helloworld"用hex进行编码 -var content = new Buffer('helloworld').toString('hex') -68656c6c6f776f726c64 - -// Asch用hex方式存储刚才得到的编码值"68656c6c6f776f726c64" -var trs = AschJS.storage.createStorage(content, secret, secondSecret) -console.log(JSON.stringify(trs)) -{"type":8,"amount":0,"fee":10000000,"recipientId":null,"senderPublicKey":"fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575","timestamp":20587956,"asset":{"storage":{"content":"68656c6c6f776f726c64"}},"__assetBytes__":{"type":"Buffer","data":[]},"signature":"9663a7f54fd1c18c2447ada61326c34e1cb3ff417089b48e28c25196ebd4a648532782da2a2344de01100c896e568287c2445716f7ac096ff5972bcdf45d850a","signSignature":"60dcfc71cd93d09509c3384b5fa0311de2f31050628efb784e782d9dd39f9a76e76fc09dd03d73165853a194bb59a9d224c960d693c000490d83e58df5fbdd00"} - -// 将生成的交易信息广播出去 -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":8,"amount":0,"fee":10000000,"recipientId":null,"senderPublicKey":"fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575","timestamp":20587956,"asset":{"storage":{"content":"68656c6c6f776f726c64"}},"__assetBytes__":{"type":"Buffer","data":[]},"signature":"9663a7f54fd1c18c2447ada61326c34e1cb3ff417089b48e28c25196ebd4a648532782da2a2344de01100c896e568287c2445716f7ac096ff5972bcdf45d850a","signSignature":"60dcfc71cd93d09509c3384b5fa0311de2f31050628efb784e782d9dd39f9a76e76fc09dd03d73165853a194bb59a9d224c960d693c000490d83e58df5fbdd00"}}' 'http://localhost:4096/peer/transactions' && echo -``` - -JSON返回示例: -```js -{ - "success": true, - "transactionId": "0e009c7b5b732bc8d78a7ff98462f74d57706a8b3a32ac31d5ab67fede5d4c8d" -} -``` - -#### **2.11.2 根据交易id查询存储的数据-1** -接口地址:/api/storages/get -请求方式:GET -支持格式:urlencode -请求参数说明: - -|名称 |类型 |必填 |说明 | -|------ |----- |--- |---- | -|id |string |Y |交易id | - -返回参数说明: - -|名称 |类型 |说明 | -|------ |----- |---- | -|success|boole |是否成功获得response数据。| -|id|string |交易id | - - -请求示例: -```bash -curl -k -H "Content-Type: application/json" -X GET http://localhost:4096/api/storages/get/?id=2ae89f859f20e6e9be7aeef5f7ff7b8c6a457ff712100a1b694436bddd9800c0 && echo -``` - -JSON返回示例: -```js -{ - "success": true, - "id": "2ae89f859f20e6e9be7aeef5f7ff7b8c6a457ff712100a1b694436bddd9800c0", // 交易id - "height": "180182", // 交易所在区块高度 - "blockId": "b59e579a002297557003856fd4cc2b10ac72d3384a5d2a8aece5f906019d79ab", // 交易所在区块id - "type": 8, // 交易类型,8代表存储信息 - "timestamp": 19552678, // 交易时间,举例创世块的offset - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", // 上传者公钥 - "senderId": "16358246403719868041", // 上传者id - "recipientId": "", - "amount": 0, - "fee": 10000000, // 交易费。0.1XAS - "signature": "8a8a256ab16c9cc966f2b975cf5ce39f13f4f13ae4a60f8c6bdfbe94e2e4ee4cb79c3be80630a5c15289d7e959e50dba5f711e9956781b150185ca9d8519f50b", // 交易签名 - "signSignature": "46431039f7e15f3147ca6991e6b46a856741b8566aeb54af97dd73d8d3e03b69eb74693c87d4ce1ef4aa2fb69d56c710681494a013fcf747de24d7ea4e79740f", // 二级签名,有二级密码时才有 - "signatures": null, // 多重签名,使用多重签名账户时才有 - "confirmations": "68", // 交易确认数 - "asset": { - "storage": { - "content": "68656c6c6f776f726c64" // 数据内容,16进制字符串 - } - } -} -// 将得到的16进制(hex)格式的字符串"68656c6c6f776f726c64"转为文本字符串正好是"helloworld" -console.log(new Buffer('68656c6c6f776f726c64','hex').toString()); -helloworld -``` - -#### **2.11.3 根据交易id查询存储的数据-2** -接口地址:/api/storages/:id -请求方式:GET -支持格式:urlencode -请求参数说明:交易id -备注:与/api/storages/get功能相同 - -请求示例: -```bash -curl -k -H "Content-Type: application/json" -X GET http://localhost:4096/api/storages/2ae89f859f20e6e9be7aeef5f7ff7b8c6a457ff712100a1b694436bddd9800c0 && echo -``` - -JSON返回示例: -```js - -``` - - - -## **附录1:asch-js安装** -asch系统的所有写操作都是通过发起一个交易来完成的。 -交易数据通过一个叫做asch-js的库来创建,然后再通过一个POST接口发布出去 -**库安装** -npm install asch-js - - diff --git a/docs/asch_http_interface_de.md b/docs/asch_http_interface_de.md deleted file mode 100644 index d90bfaa..0000000 --- a/docs/asch_http_interface_de.md +++ /dev/null @@ -1,1976 +0,0 @@ -Inhaltsverzeichnis -================= - -- [Asch-HTTP Interface Spezifikation](#asch-http-interface-spezifikation) - - [1 Verwendung der API](#1-verwendung-der-api) - - [1.1 Übersicht über Netzwerkrequests](#11-übersicht-über-netzwerkrequests) - - [2 Interface](#2-interface) - - [2.1 Konten](#21-konten) - - [2.1.1 Login](#211-login) - - [2.1.1.1 Einloggen nachdem lokal verschlüsselt wurde (wird ausdrücklich empfohlen)](#2111-einloggen-nachdem-lokal-verschlüsselt-wurde-wird-ausdrücklich-empfohlen) - - [2.1.1.2 Einloggen ohne vorheriges lokales Verschlüssel (wird ausdrücklich nicht empfohlen)](#2112-einloggen-ohne-vorheriges-lokales-verschlüssel-wird-ausdrücklich-nicht-empfohlen) - - [2.1.2 Zeige Kontoinformationen](#212-zeige-kontoinformationen) - - [2.1.3 Zeige Saldo eines Kontos](#213-zeige-saldo-eines-kontos) - - [2.1.4 Zeigen öffentlichen Schlüssel eines Kontos](#214-zeigen-öffentlichen-schlüssel-eines-kontos) - - [2.1.5 Erzeuge öffentlichen Schlüssel](#215-erzeuge-öffentlichen-schlüssel) - - [2.1.6 Zeige eine Liste von Stimmabgaben von einer Adresse](#216-zeige-eine-liste-von-stimmabgaben-von-einer-adresse) - - [2.1.7 Zeige die Gebühren eines bestimmten Delegats](#217-zeige-die-gebühren-eines-bestimmten-delegats) - - [2.1.8 Abstimmung](#218-abstimmung) - - [2.2 Transaktionen](#22-transaktionen) - - [2.2.1 Zeige die Transaktionsdetails](#221-zeige-die-transaktionsdetails) - - [2.2.2 Zeige Details zu einer Transaktion](#222-zeige-details-zu-einer-transaktion) - - [2.2.3 Zeige Transaktionsdetails anhand von der ID einer unbestätigten Transaktion](#223-zeige-transaktionsdetails-anhand-von-der-id-einer-unbestätigten-transaktion) - - [2.2.4 Zeige unbestätigte Transaktionen [im ganzen Netzwerk]](#224-zeige-unbestätigte-transaktionen-im-ganzen-netzwerk) - - [2.2.5 Erstelle eine Transaktion](#225-erstelle-eine-transaktion) - - [2.3 Blocks](#23-blocks) - - [2.3.1 Zeige Blockinformationen anhand von ID, Blockhöhe oder Hash](#231-zeige-blockinformationen-anhand-von-id-blockhöhe-oder-hash) - - [2.3. Zeige den letzten Block an](#23-zeige-den-letzten-block-an) - - [2.3.3 Zeige die Blockhöhe](#233-zeige-die-blockhöhe) - - [2.3.4 Zeige die Transaktionsgebühr](#234-zeige-die-transaktionsgebühr) - - [2.3.5 Zeige den Milestone](#235-zeige-den-milestone) - - [2.3.6 Zeige die Belohnung für einen Block](#236-zeige-die-belohnung-für-einen-block) - - [2.3.7 Zeige die maximalen Anzahl an XAS im Umlauf](#237-zeige-die-maximalen-anzahl-an-xas-im-umlauf) - - [2.3.8 Zeige den momentanen Status der Blockchain](#238-zeige-den-momentanen-status-der-blockchain) - - [2.4 Delegate](#24-delegate) - - [2.4.1 Zeige die Anzahl aller Delegate](#241-zeige-die-anzahl-aller-delegate) - - [2.4.2 Zeige die Konten die für ein Delegat abgestimmt haben anhand des öffentlichen Schlüssels des Delegats](#242-zeige-die-konten-die-für-ein-delegat-abgestimmt-haben-anhand-des-öffentlichen-schlüssels-des-delegats) - - [2.4.3 Zeige die Details zu einem Delegat mittels öffentlichem Schlüssel oder Namen](#243-zeige-die-details-zu-einem-delegat-mittels-öffentlichem-schlüssel-oder-namen) - - [2.4.4 Zeige eine Liste aller Delegate](#244-zeige-eine-liste-aller-delegate) - - [2.4.5 Zeige die Transaktionsgebühr eines Delegats](#245-zeige-die-transaktionsgebühr-eines-delegats) - - [2.4.6 Zeige die Schmiede-Informationen (Forging) anhand eines öffentlichen Schlüssels](#246-zeige-die-schmiede-informationen-forging-anhand-eines-öffentlichen-schlüssels) - - [2.4.7 Registriere eine Delegat](#247-registriere-eine-delegat) - - [2.5 Andere Knoten](#25-andere-knoten) - - [2.5.1 Zeige die Information zu allen Knoten in einem Netzwerk](#251-zeige-die-information-zu-allen-knoten-in-einem-netzwerk) - - [2.5.2 Zeige die Asch-Versionsnummer eines Knotens](#252-zeige-die-asch-versionsnummer-eines-knotens) - - [2.5.3 Zeige die Information zu einem Knoten mittels seiner IP-Adresse](#253-zeige-die-information-zu-einem-knoten-mittels-seiner-ip-adresse) - - [2.6 Die Synchronisierung und der Lademechanismus](#26-die-synchronisierung-und-der-lademechanismus) - - [2.6.1 Zeige den lokalen Blockchain Ladestatus](#261-zeige-den-lokalen-blockchain-ladestatus) - - [2.6.2 Zeige den Status der Block-Synchronisierung](#262-zeige-den-status-der-block-synchronisierung) - - [2.7 Zweites Passwort](#27-zweites-passwort) - - [2.7.1 Setze ein zweites Passwort](#271-setze-ein-zweites-passwort) - - [2.7.2 Zeige die Gebühr für das Setzen eines zweiten Passworts](#272-zeige-die-gebühr-für-das-setzen-eines-zweiten-passworts) - - [2.8 Multi-Signatur](#28-multi-signatur) - - [2.8.1 Ein normales Konto in ein Multi-Signatur-Konto verwandeln](#281-ein-normales-konto-in-ein-multi-signatur-konto-verwandeln) - - [2.8.2 Zeige Informationen zu ausstehenden Multi-Signatur-Transaktionen](#282-zeige-informationen-zu-ausstehenden-multi-signatur-transaktionen) - - [2.8.3 Unterschriebe eine Multi-Signatur-Transaktion (als nicht Initiator)](#283-unterschriebe-eine-multi-signatur-transaktion-als-nicht-initiator) - - [2.8.4 Zeige Details zu einem Multi-Signatur Konto](#284-zeige-details-zu-einem-multi-signatur-konto) - - [2.9 Peer2Peer Transport[sichere API]](#29-peer2peer-transportsichere-api) - - [2.9.1 Übersicht](#291-übersicht) - - [2.9.2 Transaktion](#292-transaktion) - - [2.9.2.1 Setze ein zweites Bezahl-Passwort](#2921-setze-ein-zweites-bezahl-passwort) - - [2.9.2.2 Geld überweisen](#2922-geld-überweisen) - - [2.9.2.3 Ein Delegat registrieren](#2923-ein-delegat-registrieren) - - [2.9.2.4 Wahl abgeben und Stimmabgabe zurückziehen](#2924-wahl-abgeben-und-stimmabgabe-zurückziehen) - - [Appendix 1:Installiere das 'asch-js' Modul](#appendix-1installiere-das-asch-js-modul) - - -Inhaltsverzeichnis erstellt mittels [markdown-toc](https://github.com/AlanWalk/markdown-toc) - - -# Asch-HTTP Interface Spezifikation - ---- -## 1 Verwendung der API -### 1.1 Übersicht über Netzwerkrequests -- **Erstelle die Daten zum verschicken:** Laut der Asch-Interface Dokumentation müssen die Daten als JSON-Objekt versedet werden. (Um eine sichere Peer-to-Peer Verbindung herzustellen kann es hilfreich sein eine Signatur mittels asch-js zu erstellen. Siehe mehr in Abschnitt [2.9 Peer-to-Peer Transport](#29-Peer2Peer-Transport%5Bsichere-API%5D). -- **Sende Daten:** Sende das erstellte Objekt zur Asch-Plattform mittels HTTP POST/GET -- **Das Asch System überprüft die gesendeten Daten:** Nachdem der Asch-Server die Daten empfangen hat, wird er diese validieren und dann weiter verarbeiten. -- **Daten werden zurückgesandt:** Das Asch-System retouniert die Daten als JSON-Objekt. Weiterführende API-Informationen findest du weiter unten. -- **Der Client verarbeitet die empfangen Daten** - -## 2 Interface -### 2.1 Konten - -#### 2.1.1 Login -##### 2.1.1.1 Einloggen nachdem lokal verschlüsselt wurde (wird ausdrücklich empfohlen) -API Endpunkt: /api/accounts/open2/ -HTTP Verb: POST -Unterstützes Datenformat: JSON -Hinweis: Der öffentliche Schlüssel muss lokal mit Hilfe des Passwortes generiert werden (siehe Beispiel) - -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|publicKey |string |Ja|Öffentlicher Schlüssel| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Ob der Login erfolreich war | -|account|json |Kontoinformationen| -|latestBlock|json |Informationen zum letzten Block| -|version|json |Asch-Versionsnummer| -Beispiel: - -```js -var AschJS = require('asch-js'); //Mehr Informationen zu asch-js findest du im Appendix ganz unten -var publicKey = AschJS.crypto.getKeys(secret).publicKey; //zeige die Adresse anhand des Geheimnisses -// var address = AschJS.crypto.getAddress(publicKey); //zeige die Adresse anhand des öffentlichen Schlüssels - -// Schicke die gerade gesammelten Daten an den Asch-Server mit Hilfe der HTTP POST Methode -curl -X POST -H "Content-Datentyp: application/json" -k -d '{"publicKey":"bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9"}' http://45.32.248.33:4096/api/accounts/open2/ -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "account": { - "address": "16723473400748954103", - "unconfirmedBalance": 19480000000, - "balance": 19480000000, - "unconfirmedSignature": false, - "secondSignature": true, - "secondPublicKey": "edf30942beb74de5ed6368c792af8665e9636f32a5f1c9377bcdc3b252d3f277", - "multisignatures": [], - "u_multisignatures": [] - }, - "latestBlock": { - "height": 111923, - "timestamp": 4446270 - }, - "version": { - "version": "1.0.0", - "build": "12:11:11 16/08/2016", - "net": "testnet" - } -``` - -##### 2.1.1.2 Einloggen ohne vorheriges lokales Verschlüsseln (wird ausdrücklich nicht empfohlen) -API Endpunkt: /api/accounts/open/ -HTTP Verb: POST -Unterstützes Datenformat: JSON -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|secret |string |Ja|Passwort des Asch-Kontos| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Ob der Login erfolgreich war| -|account|json |Kontoinformationen | - -Beispiel: -```bash -curl -X POST -H "Content-Datentyp: application/json" -k -d '{"secret":"fault still attack alley expand music basket purse later educate follow ride"}' http://45.32.248.33:4096/api/accounts/open/ -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "account": { - "address": "16723473400748954103", - "unconfirmedBalance": 19480000000, - "balance": 19480000000, - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9", - "unconfirmedSignature": false, - "secondSignature": true, - "secondPublicKey": "edf30942beb74de5ed6368c792af8665e9636f32a5f1c9377bcdc3b252d3f277", - "multisignatures": [ ], - "u_multisignatures": [ ] - } -} -``` -#### 2.1.2 Zeige Kontoinformationen -API Endpunkt: /api/accounts -HTTP Verb: GET -Unterstütztes Format: urlencoded -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|address |string |Ja|Client Adresse, Minimum:1| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert| -|account|json |Kontoinformationen| -|latestBlock|json |Informationen zum letzten Block| -|version|json |Asch-Versionsnummer| - -Beispiel: -```bash -curl -k -X GET http://45.32.248.33:4096/api/accounts?address=16723473400748954103 -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "account": { - "address": "16723473400748954103", //Asch Adresse - "unconfirmedBalance": 19480000000, //Die Summe des unbestätigten und des bereits bestätigten Saldos. Dieses sollte größer als das Saldo weiter unten sein. - "balance": 19480000000, //Saldo - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9", //Öffentlicher Schlüssel - "unconfirmedSignature": false, - "secondSignature": true, //zweite Signatur - "secondPublicKey": "edf30942beb74de5ed6368c792af8665e9636f32a5f1c9377bcdc3b252d3f277", //zweiter öffentlicher Schlüssel - "multisignatures": [], - "u_multisignatures": [] - }, - "latestBlock": { - "height": 114480, //Blockhöhe - "timestamp": 4471890 - }, - "version": { - "version": "1.0.0", - "build": "12:11:11 16/08/2016", //Datum des Builds - "net": "testnet" //Blockchain-Typ: Mainnet oder Testnet - } -} -``` -#### 2.1.3 Zeige Saldo eines Kontos -API Endpunkt: /api/accounts/getBalance -HTTP Verb: GET -Unterstütztes Format: urlencoded -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|address |string |Ja|Kontoadresse, Minimum:1 | - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert | -|balance|integer |Saldo | -|unconfirmedBalance|integer|Die Summe des unbestätigten und des bereits bestätigten Saldos. Dieses sollte größer als das Saldo sein.| - - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/accounts/getBalance?address=14636456069025293113' -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "balance": 5281328514990, - "unconfirmedBalance": 5281328514990 -} -``` - -#### 2.1.4 Zeige öffentlichen Schlüssel eines Kontos -API Endpunkt: /api/accounts/getPublickey -HTTP Verb: GET -Unterstütztes Format: urlencoded -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|address |string |Ja|Adresse, Minimum:1 | - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|publicKey|string |Öffentlicher Schlüssel| - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/accounts/getPublickey?address=14636456069025293113' -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "publicKey": "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7" -} -``` - -#### 2.1.5 Erzeuge öffentlichen Schlüssel -API Endpunkt: /api/accounts/generatePublickey -HTTP Verb: POST -Unterstützes Datenformat: JSON -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|secret |string |Ja|Passwort des Asch-Kontos| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|publicKey|string |Öffentlicher Schlüssel| - -Beispiel: -```bash -curl -k -H "Content-Datentyp: application/json" -X POST -d '{"secret":"fault still attack alley expand music basket purse later educate follow ride"}' 'http://45.32.248.33:4096/api/accounts/generatePublickey' -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9" -} -``` - -#### 2.1.6 Zeige eine Liste von Stimmabgaben von einer Adresse -API Endpunkt: /api/accounts/delegates -HTTP Verb: GET -Unterstütztes Format: urlencoded -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|address |string |Ja|Die Adresse welche die Stimme abgegeben hat| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|delegates|Array |Eine Liste mit Kontos für welche diese Adresse bereits gestimmt hat| - - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/accounts/delegates?address=14636456069025293113' -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "delegates": [{ - "username": "wgl_002", - "address": "14636456069025293113", - "publicKey": "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7", - "vote": 9901985415600500, - "producedblocks": 1373, - "missedblocks": 6, - "rate": 1, - "approval": "98.54", - "productivity": "99.56" - }, - { - "username": "wgl_003", - "address": "9961157415582672274", - "publicKey": "c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2", - "vote": 9891995435600500, - "producedblocks": 1371, - "missedblocks": 8, - "rate": 2, - "approval": "98.44", - "productivity": "99.41" - }, - { - "username": "wgl_001", - "address": "1869971419039689816", - "publicKey": "c547df2dde6cbb4508aabcb5970d8f9132e5a1d1c422632da6bc20bf1df165b8", - "vote": 32401577128413, - "producedblocks": 969, - "missedblocks": 8, - "rate": 102, - "approval": "0.32", - "productivity": 0 - }] -} -``` - -#### 2.1.7 Zeige die Gebühren eines bestimmten Delegats -API Endpunkt: /api/accounts/delegates/fee -HTTP Verb: GET -Unterstütztes Format: keine -Beschreibung der Parameter: keine - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|fee|integer |Gebühren-Einstellungen | - - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/accounts/delegates/fee -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "fee": 100000000 -} -``` - - -#### 2.1.8 Abstimmung -API Endpunkt: /api/accounts/delegates -HTTP Verb: PUT -Unterstützes Datenformat: JSON -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|secret |string |Ja|Passwort des Asch-Kontos| -|publicKey|string |Nein|Öffentlicher Schlüssel| -|secondSecret|string|Nein|Zweites Asch-Konto Passwort. Länge zwischen 1 und 100| -|delegates|Array||Eine Liste mit öffentlichen Schlüssel von Delegaten. Setze ein Plus (+) oder ein Minus (-) vor den öffentlichen Schlüssel um zu signalisieren, dass es sich um eine Stimmabgabe bzw. um die Rückziehung einer Stimme handelt. - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|transaction|json |Informationen zur Stimmabgabe | - - -Beispiel: -```bash -curl -k -H "Content-Datentyp: application/json" -X PUT -d '{"secret":"call scissors pupil water friend timber spend brand vote obey corn size","publicKey":"3ec1c9ec08c0512641deba37c0e95a0fe5fc3bdf58424009f594d7d6a4e28a2a","delegates":["+fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575"]}' 'http://45.32.248.33:4096/api/accounts/delegates' -``` - -Mögliche JSON Antwort: -```js - { - "success": true, - "transaction": { - "type": 3, //Der Datentyp der Stimmabgabe ist '3' - "amount": 0, - "senderPublicKey": "3ec1c9ec08c0512641deba37c0e95a0fe5fc3bdf58424009f594d7d6a4e28a2a", - "requesterPublicKey": null, - "timestamp": 5056064, - "asset": { - "vote": { - "votes": ["+fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575"] - } - }, - "recipientId": null, - "signature": "0bff58c7311fc59b3c8b3ffc236bbfece9850c334fb0c292ab087f78cf9a6c0f4d3e541c501887a2c2ec46294c777e8f7bf7dea9cb7c9a175fdec641bb684f08", - "id": "5630629337798595849", - "fee": 10000000, - "senderId": "15238461869262180695" - } -} -``` - -### 2.2 Transaktionen -#### 2.2.1 Zeige die Transaktionsdetails -API Endpunkt: /api/transactions -HTTP Verb: GET -Unterstütztes Format: urlencoded -Hinweis: Falls kein Parameter angegeben wird, dann werden alle Transaktionen retourniert - -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|blockId |string |Nein|BlockID| -|limit |integer |Nein|Rückgabe der Datensätze limitieren,Minimum:0, Maximum:100 | -|type|integer |Nein|Die Transaktions-Datentypen: 0:Normaler Transfer,1:Setzen eines zweiten Passworts,2:Delegat registrieren,3:Stimmabgabe,4:Multi-Signatur,5:DAPP,6:IN_TRANSFER,7:OUT_TRANSFER| -|orderBy|string |Nein|Sortiere nach einem Feld in der Tabelle,senderPublicKey:desc (asc=aufsteigend, desc=absteigend)| -|offset|integer |Nein|Paging-Abstand, Minimum 0| -|senderPublicKey|string|Nein|Öffentlicher Schlüssel des Senders| -|ownerPublicKey|string|Nein|| -|ownerAddress|string|Nein|| -|senderId|string|Nein|Adresse des Senders| -|recipientId|string|Nein|Adresse des Empfängers, Minimum:1| -|amount|integer|Nein|Betrag| -|fee|integer|Nein|Gebühr| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|transactions|Array |Eine Liste mit Transaktionsdetails| -|count|int|Anzahl der aufgelisteten Transaktionen| - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/transactions?recipientId=16723473400748954103&orderBy=t_timestamp:desc&limit=3' -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "transactions": [{ - "id": "17192581936339156329", - "height": "105951", - "blockId": "15051364118100195665", - "type": 0, - "timestamp": 4385190, - "senderPublicKey": "d39d6f26869067473d685da742339d1a9117257fe14b3cc7261e3f2ed5a339e3", - "senderId": "15745540293890213312", - "recipientId": "16723473400748954103", - "amount": 10000000000, - "fee": 10000000, - "signature": "98d65df3109802c707eeed706e90a907f337bddab58cb4c1fbe6ec2179aa1c85ec2903cc0cf44bf0092926829aa5a0a6ec99458f65b6ebd11f0988772e58740e", - "signSignature": "", - "signatures": null, - "confirmations": "31802", - "asset": { - - } - }, - { - "id": "7000452951235123088", - "height": "105473", - "blockId": "11877628176330539727", - "type": 0, - "timestamp": 4380147, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "senderId": "16358246403719868041", - "recipientId": "16723473400748954103", - "amount": 10000000000, - "fee": 10000000, - "signature": "dc84044d4f6b4779eecc3a986b6507e458cc5964f601ebeb4d3b68a96129813f4940e14de950526dd685ca1328b6e477e6c57e95aeac45859a2ea62a587d0204", - "signSignature": "", - "signatures": null, - "confirmations": "32280", - "asset": { - - } - }, - { - "id": "14093929199102906687", - "height": "105460", - "blockId": "2237504897174225512", - "type": 0, - "timestamp": 4380024, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "senderId": "16358246403719868041", - "recipientId": "16723473400748954103", - "amount": 10000000000, - "fee": 10000000, - "signature": "73ceddc3cbe5103fbdd9eee12f7e4d9a125a3bcf2e7cd04282b7329719735aeb36936762f17d842fb14813fa8f857b8144040e5117dffcfc7e2ae88e36440a0f", - "signSignature": "", - "signatures": null, - "confirmations": "32293", - "asset": { - - } - }], - "count": 3 -} -``` -#### 2.2.2 Zeige Details zu einer Transaktion -API Endpunkt: /api/transactions/GET -HTTP Verb: GET -Unterstütztes Format: urlencoded -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|Id |string |Ja|TransaktionsId| - - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|transactions|json |Transaktionsdetails| - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/transactions/get?id=14093929199102906687' -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "transaction": { - "id": "14093929199102906687", - "height": "105460", - "blockId": "2237504897174225512", - "type": 0, - "timestamp": 4380024, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "senderId": "16358246403719868041", - "recipientId": "16723473400748954103", - "amount": 10000000000, - "fee": 10000000, - "signature": "73ceddc3cbe5103fbdd9eee12f7e4d9a125a3bcf2e7cd04282b7329719735aeb36936762f17d842fb14813fa8f857b8144040e5117dffcfc7e2ae88e36440a0f", - "signSignature": "", - "signatures": null, - "confirmations": "34268", - "asset": { - } - } -} -``` - -#### 2.2.3 Zeige Transaktionsdetails anhand von der ID einer unbestätigten Transaktion -API Endpunkt: /api/transactions/unconfirmed/GET -HTTP Verb: GET -Unterstütztes Format: urlencoded -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|id|string |Ja|Id einer unbestätigten Transaktion| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|transaction|json |Die Informationen zu der unbestätigten Transaktion| - - -Beispiel: -```bash -curl -k -X GET http://45.32.248.33:4096/api/transactions/unconfirmed/get?id=7557072430673853692 //Normalerweise existiert eine unbestätigte Transaktion nur für wenige Sekunden (0-10 Sekunden). -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "transaction": { - "type": 0, - "amount": 10000, - "senderPublicKey": "3ec1c9ec08c0512641deba37c0e95a0fe5fc3bdf58424009f594d7d6a4e28a2a", - "requesterPublicKey": null, - "timestamp": 5082322, - "asset": { - - }, - "recipientId": "16723473400748954103", - "signature": "3a97f8d63509ef964bda3d816366b8e9e2d9b5d4604a660e7cbeefe210cb910f5de9a51bece06c32d010f55502c62f0f59b8224e1c141731ddfee27206a88d02", - "id": "7557072430673853692", - "fee": 10000000, - "senderId": "15238461869262180695" - } -} -``` - - -#### 2.2.4 Zeige unbestätigte Transaktionen (im ganzen Netzwerk) -API Endpunkt: /api/transactions/unconfirmed -HTTP Verb: GET -Unterstütztes Format: urlencoded -Hinweis: Falls kein Parameter angegeben wurde, werden alle unbestätigten Transaktionen retourniert -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|senderPublicKey |string |Nein|Der öffentliche Schlüssel des Senders| -|address |string |Nein|Adresse| - - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert| -|transactions|Array |Eine Liste mit allen unbestätigten Transaktionen| - - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/transactions/unconfirmed' -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "transactions": [] //Zur Zeit existieren keine unbestätigten Transaktionen im Netzwerk -} -``` - -#### 2.2.5 Erstelle eine Transaktion -API Endpunkt: /api/transactions -HTTP Verb: PUT -Unterstützes Datenformat: JSON -Hinweis: Der Empfänger muss (vor der Transaktion) bereits sich einmal in die Web-Wallet eingeloggt haben. -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|secret |string |Ja|Passwort des Asch-Kontos| -|amount|integer|Ja|Betrag,muss zwischen 1 und 10000000000000000 (10^16^) sein| -|recipientId|string|Ja|Addresse des Empfängers, Minimum:1| -|publicKey|string|Nein|Öffentlicher Schlüssel des Senders| -|secondSecret|string|Nein|Zweites Passwort des Sender (dieses muss dem [BIP39 Standard](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) entsprechen), die Länge muss zwischen 1 und 100 sein| -|multisigAccountPublicKey|string|Nein|Der öffentliche Schlüssel eines Multi-Signatur-Kontos| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|transactionId|string |Transaktions-ID| - - -Beispiel: -```bash -curl -k -H "Content-Datentyp: application/json" -X PUT -d '{"secret":"unaware label emerge fancy concert long fiction report affair appear decide twenty","amount":1000000,"recipientId":"16723473400748954103"}' 'http://45.32.248.33:4096/api/transactions' -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "transactionId": "16670272591943275531" -} -``` - -### 2.3 Blocks -#### 2.3.1 Zeige Blockinformationen anhand von ID, Blockhöhe oder Hash -API Endpunkt: /api/blocks/ -HTTP Verb: GET -Unterstütztes Format: urlencoded -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung| -|------ |----- |--- |---- | -|id |string |only choose one of these three parameters |BlockID| -|height|string|ditto|Blockhöhe| -|hash|string|ditto|Der Hash des blocks| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|block|json |Die Blockdetails| - - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/get?id=6076474715648888747' -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "block": { - "id": "6076474715648888747", - "version": 0, - "timestamp": 4734070, - "height": 140538, - "previousBlock": "16033230167082515105", //vorherige block ID - "numberOfTransactions": 0, //Anzahl der Transaktionen - "totalAmount": 0, //Summe der Transaktionen - "totalFee": 0, - "reward": 350000000, //Belohnung - "payloadLength": 0, - "payloadHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "generatorPublicKey": "1d352950c8141e1b35daba4a974a604519d7a2ef3a1ec0a503ce2653646aa052", - "generatorId": "6656029629904254066", - "blockSignature": "a53de66922cdc2f431acd0a474beec7cf7c420a8460b7b7caf84999be7caebb59fb7fbb7166c2c7013dbb431585ea7294722166cb08bf9663abf50b6bd81cd05", - "confirmations": "2", - "totalForged": 350000000 - } -} -``` - -#### 2.3. Zeige den letzten Block an -API Endpunkt: /api/blocks -HTTP Verb: GET -Unterstütztes Format: urlencoded -Hinweis: Falls kein Parameter spezifiziert wird, dann werden die Details zu allen Blöcken im Netzwerk zurückgegeben. -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|limit |integer |Nein|Maximal zu retounierende Anzahl an Datensätzen, muss zwischen 0 und 100 sein| -|orderBy|string |Nein|Sortiere anhand eines Feldes in der Tabelle z.B.: height:desc (asc=aufsteigend, desc=absteigend) | -|offset|integer |Nein|Paging-Abstand, minimum 0 | -|generatorPublicKey|string |Nein|Öffentlicher Schlüssels des Blockgenerators| -|totalAmount|integer |Nein|Anzahl aller Transaktionen, muss zwischen 0 und 10000000000000000 (10^16^) sein | -|totalFee|integer |Nein|Summe der Transaktionsgebühr, muss zwischen 0 und 10000000000000000 (10^16^) sein| -|reward|integer |Nein|Belohnung, Minimum: 0 | -|previousBlock|string |Nein|Vorhergehender Block | -|height|integer |Nein|Blockhöhe| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|blocks|Array |Eine Liste von Blockdetails| -|count|integer|Blockhöhe| - - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks?limit=2&offset=0&orderBy=height:desc' -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "blocks": [{ - "id": "12634047624004615059", - "version": 0, - "timestamp": 4708080, - "height": 137986, - "previousBlock": "3498191422350401106", - "numberOfTransactions": 0, // die Anzahl der Transaktionen - "totalAmount": 0, // Summe der Transaktionen - "totalFee": 0, // Transaktionsgebühr - "reward": 350000000, // Belohnung - "payloadLength": 0, - "payloadHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "generatorPublicKey": "44db7bec89ef289d0def257285675ca14f2a947dfd2b70e6b1cff4392ce42ada", - "generatorId": "4925169939071346193", - "blockSignature": "83a2124e3e8201c1a6099b2ac8ab1c117ad34867978add3a90d41a64df9d2ad8fabc9ec14d27a77cd34c08a6479ef684f247c11b1cbbcb0e9767dffc85838600", - "confirmations": "1", - "totalForged": 350000000 - }, - { - "id": "3498191422350401106", - "version": 0, - "timestamp": 4708070, - "height": 137985, - "previousBlock": "14078155423801039323", - "numberOfTransactions": 0, - "totalAmount": 0, - "totalFee": 0, - "reward": 350000000, - "payloadLength": 0, - "payloadHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "generatorPublicKey": "500b1ec025cd64d36008341ed8d2508473ecf559be213ca5f9580620a21a592c", - "generatorId": "16006295608945777169", - "blockSignature": "a0b5ed6c94b1f33c4d0f017f21a08357061493392b19e34eeedf274b77c751e3f86c92443280de09ea1754d62fe7ef00e02acbdc3bc0c1063cef344bacaa4f07", - "confirmations": "2", - "totalForged": 350000000 - }], - "count": 137986 -} -``` - -#### 2.3.3 Zeige die Blockhöhe -API Endpunkt: /api/blocks/getHeight -HTTP Verb: GET -Unterstütztes Format: keine -Beschreibung der Parameter: keine -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|height|integer |Blockhöhe| - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/getheight' -``` - -Mögliche JSON Antwort: -```js -{"success":true,"height":140569} -``` - -#### 2.3.4 Zeige die Transaktionsgebühr -API Endpunkt: /api/blocks/getFee -HTTP Verb: GET -Unterstütztes Format: keine -Beschreibung der Parameter: keine -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|fee|integer |Transaktionsgebühr| - - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/getfee' -``` - -Mögliche JSON Antwort: -```js -{"success":true,"fee":10000000} //die Transaktionsgebühr ist 0.1 XAS -``` - -#### 2.3.5 Zeige den Milestone -API Endpunkt: /api/blocks/getMilestone -HTTP Verb: GET -Unterstütztes Format: keine -Beschreibung der Parameter: keine -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|milestone|integer | | - - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/getMilestone' -``` - -Mögliche JSON Antwort: -```js -{"success":true,"milestone":0} -``` - -#### 2.3.6 Zeige die Belohnung für einen Block -API Endpunkt: /api/blocks/getReward -HTTP Verb: GET -Unterstütztes Format: keine -Beschreibung der Parameter: keine -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|reward|integer |Die Belohnung für den Block| - - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/getReward' -``` - -Mögliche JSON Antwort: -```js -{"success":true,"reward":350000000} //jeder von dir erzeugte Block wird mit 3.5 XAS belohnt -``` - -#### 2.3.7 Zeige die maximalen Anzahl an XAS im Umlauf -API Endpunkt: /api/blocks/getSupply -HTTP Verb: GET -Unterstütztes Format: keine -Beschreibung der Parameter: keine -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|supply|integer |XAS Summe im ganzen Netzwerk| - - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/getSupply' -``` - -Mögliche JSON Antwort: -```js -{"success":true,"supply":10049222600000000} //Zur Zeit existieren 100492226 XAS im Testnet -``` - -#### 2.3.8 Zeige den momentanen Status der Blockchain -API Endpunkt: /api/blocks/getStatus -HTTP Verb: GET -Unterstütztes Format: keine -Beschreibung der Parameter: keine -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert| -|height|integer |Höhe der Blockchain| -|fee|integer |Transaktionsgebühr| -|milestone|integer | | -|reward|integer |Belohnung des Blocks| -|supply|integer |XAS Summe im ganzen Netzwerk| - - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/getStatus' -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "height": 140649, - "fee": 10000000, - "milestone": 0, - "reward": 350000000, - "supply": 10049227150000000 -} -``` - - - -### 2.4 Delegate - -#### 2.4.1 Zeige die Anzahl aller Delegate -API Endpunkt: /api/delegates/count -HTTP Verb: GET -Unterstütztes Format: keine -Beschreibung der Parameter: keine - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|count|integer |Die Summe aller Delegate| - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/delegates/count' -``` - -Mögliche JSON Antwort: -```js -{"success":true,"count":234} -``` - -#### 2.4.2 Zeige die Konten die für ein Delegat abgestimmt haben anhand des öffentlichen Schlüssels des Delegats -API Endpunkt: /api/delegates/voters -HTTP Verb: GET -Unterstütztes Format: urlencoded -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|publicKey |string |Ja|Der öffentliche Schülssel des Delegats| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|accounts|Array |Eine Kontenliste| - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/delegates/voters?publicKey=ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7' -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "accounts": [{ - "address": "2918354313445278349", - "publicKey": "4fde4c49f1297d5d3a24b1494204543c4281aff17917ff7ff8ff32da3b4b222f", - "balance": 1338227722727, - "weight": 0.013316660647014596 - }, - { - "address": "1523444724068322527", - "publicKey": "8a6a61c28dc47541aadf1eecec2175c8f768f2331eea3472b1593bf1aa4e1fb4", - "balance": 2109297623765, - "weight": 0.020989552213127274 - }, - { - "address": "14483826354741911727", - "publicKey": "5dacb7983095466b9b037690150c3edec0f073815326e33a4744b6d1d50953e2", - "balance": 5135815841470, - "weight": 0.051106336795243436 - } - }] -} -``` - -#### 2.4.3 Zeige die Details zu einem Delegat mittels öffentlichem Schlüssel oder Namen -API Endpunkt: /api/delegates/get/ -HTTP Verb: GET -Unterstütztes Format: urlencoded -Hinweis: Greife auf die Details des Delegats über seinen öffentlichen Schlüssel oder seinen Benutzernamen zu. -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|publickey |string |choose only one parameter of these two |Der öffentliche Schlüssel des Delegats| -|username |string |ditto |Der Benutzername des Delegats| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|delegate|json |the detail information of this delegate | - - -Beispiel: -```bash -curl -k -X GET http://45.32.248.33:4096/api/delegates/get?publicKey=bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9 -curl -k -X GET http://45.32.248.33:4096/api/delegates/get?username=delegate_register -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "delegate": { - "username": "delegate_register", - "address": "16723473400748954103", - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9", - "vote": 0, - "producedblocks": 0, - "missedblocks": 0, - "fees": 0, - "rewards": 0, - "rate": 191, - "approval": 0, - "productivity": 0, - "forged": "0" - } -} -``` - -#### 2.4.4 Zeige eine Liste aller Delegate -API Endpunkt: /api/delegates -HTTP Verb: GET -Unterstütztes Format: urlencoded -Hinweis: if there is no parameter, all delegates in the whole network will be returned. -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|address |string |Nein|delegate's address | -|limit|int |Nein|maximum return records | -|offset|integer |Nein|offset, minimum: 0 | -|orderBy|string |Nein|[field used to sort]:[sort Datentyp] e.g., address:desc | - - - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|delegates|Array |a list containing delegates' detail information | - - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/delegates?orderby=approval:desc&limit=2' //the first two delegates order by approval vote, descendingly -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "delegates": [{ - "username": "wgl_002", //delegate's user name - "address": "14636456069025293113", //delegate's address - "publicKey": "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7", //delegate's public key - "vote": 9901984015600500, //the number of vote - "producedblocks": 1371, //the number of generated blocks - "missedblocks": 6, //the number of missed blocks - "fees": 12588514990, - "rewards": 276850000000, //the gained reward - "rate": 1, - "approval": 98.54, //the rate of approval votes - "productivity": 99.56, //the productivity - "forged": "289438514990" //All reward from forge - }, - { - "username": "wgl_003", - "address": "9961157415582672274", - "publicKey": "c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2", - "vote": 9891994035600500, - "producedblocks": 1370, - "missedblocks": 8, - "fees": 12355148480, - "rewards": 275100000000, - "rate": 2, - "approval": 98.44, - "productivity": 99.42, - "forged": "287455148480" - }], - "totalCount": 233 -} -``` - - - - - - -#### 2.4.5 Zeige die Transaktionsgebühr eines Delegats -API Endpunkt: /api/delegates/fee -HTTP Verb: GET -Unterstütztes Format: urlencoded -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|publicKey |string |Ja|Der öffentliche Schlüssel des Delegats|| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|fee|integer |Transaktionsgebühr| - - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/delegates/fee?publicKey=ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7' -``` - -Mögliche JSON Antwort: -```js -{"success":true,"fee":10000000000} //0.1 XAS -``` - -#### 2.4.6 Zeige die Schmiede-Informationen (Forging) anhand eines öffentlichen Schlüssels -API Endpunkt: /api/delegates/forging/getForgedByAccount -HTTP Verb: GET -Unterstütztes Format: urlencoded -Beschreibung der Parameter: - -|Name|Datentyp|Obligatorisch|Beschreibung | -|------ |----- |--- |---- | -|generatorPublicKey |string |Ja|Der öffentliche Schlüssel des Block-Generators| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert| -|fees|integer |Die Summe der Transaktionsgebühren| -|rewards|integer|Errungene Belohnungen| -|forged|integer|Summe der Belohnungen von der Schmiede-Aktivität (Forging)| - - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/delegates/forging/getForgedByAccount?generatorPublicKey=ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7' -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "fees": 12589307065, - "rewards": 285600000000, - "forged": 298189307065 -} -``` - -#### 2.4.7 Registriere eine Delegat -API Endpunkt: /api/delegates -HTTP Verb: PUT -Unterstütztes Format: urlencoded -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|secret |string |Ja|Passwort des Asch-Kontos| -|publicKey|string |Nein|Öffentlicher Schlüssel| -|secondSecret|string|Nein|Zweites Asch-Konto Passwort, Minimale Länge: 1 Maximale Länge: 100| -|username|string|Nein|Der Benutzername des Delegats| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|transaction|json |Die Details zum Registrierungsprozess| - - -Beispiel: -```bash -curl -k -H "Content-Datentyp: application/json" -X PUT -d '{"secret":"unaware label emerge fancy concert long fiction report affair appear decide twenty","username":"delegate_0821"}' 'http://45.32.248.33:4096/api/delegates' -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "transaction": { - "type": 2, //der Transaktions-Typ einer Delegat-Registrierung ist 2 - "amount": 0, - "senderPublicKey": "3b64f1833e6328043e1f2fee31e638bdaa6dfff5c7eb9c8577a5cefcf11261f2", - "requesterPublicKey": null, - "timestamp": 4737615, - "asset": { - "delegate": { - "username": "delegate_0821", - "publicKey": "3b64f1833e6328043e1f2fee31e638bdaa6dfff5c7eb9c8577a5cefcf11261f2" - } - }, - "recipientId": null, - "signature": "7f8417e8db5f58ddff887c86c789c26b32fd3f01083ef1e3c8d4e18ed16622bf766492d78518c6c7a07aada1c98b1efc36d40c8e09394989dbde229d8e3f8103", - "id": "16351320834453011577", - "fee": 10000000000, - "senderId": "250438937633388106" - } -} -``` - -### 2.5 Andere Knoten - -#### 2.5.1 Zeige die Information zu allen Knoten in einem Netzwerk -API Endpunkt: /api/peers -HTTP Verb: GET -Unterstütztes Format: urlencoded -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|state |integer |Nein|Stati der Peers: 0:,1:,2:,3: | -|os|string|Nein|Linux Kernel Version| -|version|string|Nein|Asch-System Version| -|limit |integer |Nein|Anzahl der maximal zu retournierenden Datensätze, Minimum: 0, Maximum: 100| -|orderBy|string|Nein|| -|offset|integer |Nein|Abstand, Minimum: 0| -|port|integer|Nein|Port-Nummer,1~65535| - - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|peers|Array |Eine Liste von Knoteninformationen| -|totalCount|integer|Die Anzahl an gerade laufenden Knoten| - - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/peers?limit=1' -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "peers": [{ - "ip": "45.32.19.241", - "port": 4096, - "state": 2, - "os": "linux3.13.0-87-generic", - "version": "1.0.0" - }], - "totalCount": ["54"] -} -``` - -#### 2.5.2 Zeige die Asch-Versionsnummer eines Knotens -API Endpunkt: /api/peers/version -HTTP Verb: GET -Unterstütztes Format: keine -Beschreibung der Parameter: keine - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|version|string |Versionsnummer| -|build |timestamp |Zeitpunkt des Builds| -|net |string |Läuft der Knoten auf dem Mainnet oder auf dem Testnet| - - -Beispiel: -```bash -curl -k -X GET http://45.32.248.33:4096/api/peers/version -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "version": "1.0.0", - "build": "12:11:11 16/08/2016", - "net": "testnet" -} -``` - -#### 2.5.3 Zeige die Information zu einem Knoten mittels seiner IP-Adresse -API Endpunkt: /api/peers/GET -HTTP Verb: GET -Unterstütztes Format: urlencoded -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|ip |string |Ja|peer's IP | -|port|integer|Ja|peer's port,1~65535| - - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|peer|json |Die Information zu dem Knoten | - - -Beispiel: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/peers/get?ip=45.32.248.33&port=4096' -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "peer": { - } -} -``` - -### 2.6 Die Synchronisierung und der Lademechanismus -#### 2.6.1 Zeige den lokalen Blockchain Ladestatus -API Endpunkt: /api/loader/status -HTTP Verb: GET -Unterstütztes Format: keine -Beschreibung der Parameter: keine - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool|Die Daten wurden erfolgreich retouniert| -|loaded |bool| | -|blocksCount|integer|Anzahl der Blocks| - -Beispiel: -```bash -curl -k http://45.32.248.33:4096/api/loader/status -X GET -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "loaded": true, - "blocksCount": 0 -} -``` - -#### 2.6.2 Zeige den Status der Block-Synchronisierung -API Endpunkt: /api/loader/status/sync -HTTP Verb: GET -Unterstütztes Format: keine -Beschreibung der Parameter: keine - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool|Die Daten wurden erfolgreich retouniert| -|height |int|Blockhöhe| - - -Beispiel: -```bash -curl -k http://45.32.248.33:4096/api/loader/status/sync -X GET -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "syncing": false, // zeigt ob gerade sychronisiert wird. Wenn Ja, dann ist der Wert "true". Wenn keine Daten synchronisiert werden, dann ist der Wert "false". - "blocks": 0, - "height": 111987 -} -``` - -### 2.7 Zweites Passwort -#### 2.7.1 Setze ein zweites Passwort -API Endpunkt: /api/signatures -HTTP Verb: PUT -Unterstützes Datenformat: JSON -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|secret |string |Ja|Asch account's password | -|publicKey|string |Nein|Öffentlicher Schlüssel| -|secondSecret|string|Ja|Das zweite Passwort eines Asch-Kontos. Minimale Länge:1,Maximale Länge:100| -|multisigAccountPublicKey|string|Nein|Der öffentliche Schlüssel eines Multi-Signatur-Kontos| - - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert| -|transaction|json|the detail information of setting transaction| - - -Beispiel: -```bash -curl -k -H "Content-Datentyp: application/json" -X PUT -d '{"secret":"unaware label emerge fancy concert long fiction report affair appear decide twenty","secondSecret":"fault still attack alley expand music basket purse later educate follow ride"}' 'http://45.32.248.33:4096/api/signatures' -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "transaction": { - "type": 1, //Der Transaktions-Typ für das Setzen eines zweiten Passworts ist 1 - "amount": 0, - "senderPublicKey": "3b64f1833e6328043e1f2fee31e638bdaa6dfff5c7eb9c8577a5cefcf11261f2", - "requesterPublicKey": null, - "timestamp": 4872315, - "asset": { - "signature": { - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9" - } - }, - "recipientId": null, - "signature": "e76d9b25ec0fdaa88b19d59c5a222b7efdc04f738ee05896f55f4e6959229d9b1600ca25aa92fbea176668f3be7c12c506f2091e2b38c52ef0ece7a5d35e240a", - "id": "1614688380530105232", - "fee": 500000000, //Die Gebühr für das Setzen eines zweiten Passworts sind 5 XAS - "senderId": "250438937633388106" - } -} -``` - -#### 2.7.2 Zeige die Gebühr für das Setzen eines zweiten Passworts -API Endpunkt: /api/signatures/fee -HTTP Verb: GET -Unterstütztes Format: keine -Beschreibung der Parameter: keine - - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|fee|integer |Transaktionsgebühr| - - -Beispiel: -```bash -curl -k http://45.32.248.33:4096/api/signatures/fee -X GET -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "fee": 500000000 //5 XAS -} -``` - -### 2.8 Multi-Signatur -#### 2.8.1 Ein normales Konto in ein Multi-Signatur-Konto verwandeln -API Endpunkt: /api/multisignatures -HTTP Verb: PUT -Unterstützes Datenformat: JSON -Hinweis: Die Return-Wert ist ausschließlich die Transaktions-Id. Um erfolgreich ein Multi-Signatur-Konto zu eröffnen bedarf es weiterer Signaturen. Jede Transaktion nach dem Erstellen eines Multi-Signatur-Kontos benötigt mehrere Signaturen. Die kleinste Anzahl an Signaturen welche mit übertragen werden müssen wird festgehalten im Parameter "min" (schließt den Sender mit ein). -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|secret |string |Ja|Das Passwort des Asch-Kontos| -|publicKey|string |Nein|Öffentlicher Schlüssel| -|secondSecret|string|Nein|Das zweite Passwort des Asch-Kontos. Minimale Länge: 1, Maximale Länge: 100| -|min|integer|Ja|Die minimale Anzahl an Signaturen welche für eine Transaktion eines Multi-Signatur-Kontos verwendet werden muss. (Bei der Registrierung eines Multi-Signatur-Kontos hat dieser Parameter keine Bedeutung da jedes teilnehmende Konto die Transaktion unterzeichnen muss.) Minumum: 2, Maximum: 16. Diese Zahl darf nicht größer sein als "keysgroup.length + 1". | -|lifetime|integer|Ja|Die maximale Lebensdauer einer Multi-Signatur-Transaktion. Minimum:1, Maximum:24. HINWEIS: Dieser Parameter kann zur Zeit nicht verwendet werden.| -|keysgroup|array|Ja|Eine Liste mit allen öffentlichen Schlüssel der anderen Unterzeichner. Die Symbole Plus/Minus (+/-) vor einem öffentlichen Schlüssel bedeuten, dass ein Multi-Signatur-Konto hinzugefügt wird (+), oder ein Multi-Signatur-Konto entfernt wird (-). Minimale Anzahl an Konten:1, Maximum Anzahl an Konten Konten:10.| - - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|transactionId|string |die Multi-Signatur-TransaktionsId| - - -Beispiel: -```bash -curl -k -H "Content-Datentyp: application/json" -X PUT -d '{"secret":"vanish deliver message evil canyon night extend unusual tell prosper issue antenna","min":2,"lifetime":1,"keysgroup":["+eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97","+d5d7aa157f866c47a2a1e09e2746286ed089fd90976b54fbfa930e87d11609cb"]}' 'http://45.32.248.33:4096/api/multisignatures' //der öffentliche Schlüssel ist 2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "transactionId": "17620378998277022323" //Ausschließlich die TransaktionsId wird retouniert. Um erfolgreich ein Multi-Signatur-Konto zu eröffnen benötigt es mehrere Konto-Signaturen. -} -``` - -#### 2.8.2 Zeige Informationen zu ausstehenden Multi-Signatur-Transaktionen -API Endpunkt: /api/multisignatures/pending -HTTP Verb: GET -Unterstütztes Format: urlencoded -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|publicKey|string |Ja|Öffentlicher Schlüssel| - - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|transactions|Array |Eine Liste der ausstehenden transaktionen| - - -Beispiel: -```bash -curl -k -X GET http://45.32.248.33:4096/api/multisignatures/pending?publicKey=2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "transactions": [{ //die Informationen zu der Multi-Signatur-Transaktion (siehe 2.8.1, TransaktionsId: 17620378998277022323) - "min": 2, - "lifetime": 1, - "signed": true, - "transaction": { - "type": 4, //4 bedeutet, dass ein Multi-Signatur-Konto registriert wird - "amount": 0, - "senderPublicKey": "2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd", - "requesterPublicKey": null, - "timestamp": 4879978, - "asset": { - "multisignature": { - "min": 2, - "keysgroup": ["+eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97", - "+d5d7aa157f866c47a2a1e09e2746286ed089fd90976b54fbfa930e87d11609cb"], - "lifetime": 1 - } - }, - "recipientId": null, - "signature": "a42feaccd9f2a4940fc0be1a1580e786b360f189db3154328f307988e75484293eae391f2f9eee489913cc6d15984eb1f5f5a0aa1bf78ea745d5c725f161af08", - "id": "17620378998277022323", - "fee": 1500000000, - "senderId": "3855903394839129841" - } - }] -} - -``` - -#### 2.8.3 Unterschriebe eine Multi-Signatur-Transaktion (als nicht Initiator) -API Endpunkt: /api/multisignatures/sign -HTTP Verb: POST -Unterstützes Datenformat: JSON -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|secret |string |Ja|Password des Asch-Kontos| -|secondSecret|string|Nein|Zweites Passwort des Asch-Kontos. Minimale Länge: 1, Maximale Länge: 100| -|publicKey|string |Nein|Öffentlicher Schlüssel| -|transactionId|string|Ja|TransaktionsId| - - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert -|transactionId|string |Multi-Signatur-Transaktions-Id| - - -Beispiel: -```bash -curl -k -H "Content-Datentyp: application/json" -X POST -d '{"secret":"lemon carpet desk accuse clerk future oyster essay seminar force live dog","transactionId":"17620378998277022323"}' 'http://45.32.248.33:4096/api/multisignatures/sign' //dies wurde unterzeichnet von einem Benutzer dessen öffentlicher Schlüssel wie folgt ist: eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97 -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "transactionId": "17620378998277022323" -} -// erhalte die ausstehende Transaktion -curl -k -X GET http://45.32.248.33:4096/api/multisignatures/pending?publicKey=2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd -{ - "success": true, - "transactions": [{ - "min": 2, - "lifetime": 1, - "signed": true, - "transaction": { - "type": 4, - "amount": 0, - "senderPublicKey": "2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd", - "requesterPublicKey": null, - "timestamp": 4879978, - "asset": { - "multisignature": { - "min": 2, - "keysgroup": ["+eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97", - "+d5d7aa157f866c47a2a1e09e2746286ed089fd90976b54fbfa930e87d11609cb"], - "lifetime": 1 - } - }, - "recipientId": null, - "signature": "a42feaccd9f2a4940fc0be1a1580e786b360f189db3154328f307988e75484293eae391f2f9eee489913cc6d15984eb1f5f5a0aa1bf78ea745d5c725f161af08", - "id": "17620378998277022323", - "fee": 1500000000, - "senderId": "3855903394839129841", - "signatures": ["b38a161264db2a23e353d3fbc4983562f6343d5ee693144543ca54e2bc67c0f73d1c761b7bfa38b2bb101ac2ab0797b674b1a9964ccd400aaa310746c3494d03"] //die neue Multi-Signatur - } - }] -} - -// Der öffentlichen Schlüssel eines Benutzers ist "d5d7aa157f866c47a2a1e09e2746286ed089fd90976b54fbfa930e87d11609cb". Unterzeichne folgenden Registrierungs-Vertrag -curl -k -H "Content-Datentyp: application/json" -X POST -d '{"secret":"chalk among elbow piece badge try van round quality position simple teach","transactionId":"17620378998277022323"}' 'http://45.32.248.33:4096/api/multisignatures/sign' -{"success":true,"transactionId":"17620378998277022323"} -// Versuch ausstehende Transaktionen herunterzuladen. Diesmal gibt es keine. -curl -k -X GET http://45.32.248.33:4096/api/multisignatures/pending?publicKey=2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd -{"success":true,"transactions":[]} -// Beachte die Details dieser Transaktion. Zu diesem Zeitpunkt wurde die Transaktion an das ganze Netzwerk gesendet und wird auf die Blockchain geschrieben. Dieses Konto wurde erfolgreich als ein Multi-Signatur Konto registriert. - -curl -k -X GET http://45.32.248.33:4096/api/transactions/get?id=17620378998277022323 -{ - "success": true, - "transaction": { - "id": "17620378998277022323", //the registering transaction ID - "height": "157013", - "blockId": "4680888982781013372", - "type": 4, - "timestamp": 4879978, - "senderPublicKey": "2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd", - "senderId": "3855903394839129841", - "recipientId": "", - "amount": 0, - "fee": 1500000000, - "signature": "a42feaccd9f2a4940fc0be1a1580e786b360f189db3154328f307988e75484293eae391f2f9eee489913cc6d15984eb1f5f5a0aa1bf78ea745d5c725f161af08", - "signSignature": "", - "signatures": null, - "confirmations": "26", - "asset": { - - } - } -} - -``` - -#### 2.8.4 Zeige Details zu einem Multi-Signatur Konto -API Endpunkt: /api/multisignatures/accounts -HTTP Verb: GET -Unterstütztes Format: urlencoded -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|publicKey |string |Ja|Der öffentliche Schlüssel eines der Teilnehmer| - - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |Die Daten wurden erfolgreich retouniert| -|accounts|Array |Die Details des Multi-Signatur Kontos| - - -Beispiel: -```bash -curl -k -X GET http://45.32.248.33:4096/api/multisignatures/accounts?publicKey=eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97 -``` - -Mögliche JSON Antwort: -```js -{ - "success": true, - "accounts": [{ - "address": "3855903394839129841", //die Adresse dieses Multi-Signatur-Kontos - "balance": 18500000000, //das Saldo des Multi-Signatur Kontos - "multisignatures": ["eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97", - "d5d7aa157f866c47a2a1e09e2746286ed089fd90976b54fbfa930e87d11609cb"], //der öffentliche Schlüssel des Multi-Signatur Kontos - "multimin": 2, //Minimum an obligatorischen Signaturen - "multilifetime": 1, - "multisigaccounts": [{ //Die Kontodetails des Unterzeichners - "address": "13542769708474548631", - "publicKey": "eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97", - "balance": 0 - }, - { - "address": "4100816257782486230", - "publicKey": "d5d7aa157f866c47a2a1e09e2746286ed089fd90976b54fbfa930e87d11609cb", - "balance": 0 - }] - }] -} -``` - -### 2.9 Peer2Peer Transport[sichere API] -#### 2.9.1 Übersicht -Um Informationen zu einer Knoten-API abzufragen müssen folgender Header gesetzt werden: - - - key=magic, and value=594fe0f3 - - key=version, and value='' - -#### 2.9.2 Transaktion -Alle Schreiboperationen im Asch-System werden mit dem Erstellen einer Transaktion beendet. Die Daten für die Transaktion werden mit Hilfe des Moduls "asch-js" erstellt und dann mit einem HTTP POST an den Server geschickt. Der API-Endpunkt sieht folgendermaßen aus: - -Nutzlast: Transaktionsinformationen erstellt durch asch-js -API Endpunkt: /peer/transactions -HTTP Verb: POST -Unterstützes Datenformat: JSON - -##### 2.9.2.1 Setze ein zweites Bezahl-Passwort -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|transaction|JSON|Ja|Transaktionsdaten erstellt mittels [asch-js.signature.createSignature]| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |ob die Stimmabgabe erfolgreich war | - - -Beispiel: -```js -var asch = require('asch-js'); -var transaction = asch.signature.createSignature('measure bottom stock hospital calm hurdle come banner high edge foster cram','erjimimashezhi001') -console.log(json.stringify(transaction)) -{"type":1,"amount":0,"fee":500000000,"recipientId":null,"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","timestamp":5328943,"asset":{"signature":{"publicKey":"27116db89cb5a8c02fb559712e0eabdc298480d3c79a089b803e35bc5ef7bb7b"}},"signature":"71ef98b1600f22f3b18cfcf17599db3c40727c230db817f610e86454b62df4fb830211737ff0c03c6a61ecfd4a9fcb68a30b2874060bb33b87766acf800e820a","id":"15605591820551652547"} - -// schicke die oben erstellten Daten mittels HTTP POST an den Asch-Server um ein zweites Passwort zu hinterlegen -curl -H "Content-Datentyp: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":1,"amount":0,"fee":500000000,"recipientId":null,"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","timestamp":5328943,"asset":{"signature":{"publicKey":"27116db89cb5a8c02fb559712e0eabdc298480d3c79a089b803e35bc5ef7bb7b"}},"signature":"71ef98b1600f22f3b18cfcf17599db3c40727c230db817f610e86454b62df4fb830211737ff0c03c6a61ecfd4a9fcb68a30b2874060bb33b87766acf800e820a","id":"15605591820551652547"}}' http://45.32.248.33:4096/peer/transactions -``` - -Mögliche JSON Antwort: -```js -{ - "success":true //Aktion war erfolgreich -} -``` - -##### 2.9.2.2 Geld überweisen -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|transaction|JSON|Ja|Transaktionsdaten erstellt mittels [asch-js.transaction.createTransaction]| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |ob die Stimmabgabe erfolgreich war | - - -Beispiel: -```js -var asch = require('asch-js'); -var targetAddress = "16358246403719868041"; -var amount = 100*100000000; //100 XAS -var password = 'measure bottom stock hospital calm hurdle come banner high edge foster cram'; -var secondPassword = 'erjimimashezhi001'; - -// Hier ist die Eingabe eines Passworts zu sehen. In diesem Beispiel muss das zweite Passwort auch eingegeben werden. -// Ob ein zweites Passwort notwendig ist hängt davon ab, ob der Benutzer ein zweites Passwort festgelegt hat. Über die Funktion "user.secondPublicKey" kann verifiziert werden ob ein Benutzer ein zweites Passwort hinterlegt hat. - -var transaction = asch.transaction.createTransaction(targetAddress, amount, password, secondPassword || undefined); -json.stringify(transaction) -'{"type":0,"amount":10000000000,"fee":10000000,"recipientId":"16358246403719868041","timestamp":5333378,"asset":{},"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","signature":"2d47810b7d9964c5c4d330a53d1382769e5092b3a53639853f702cf4a382aafcff8ef8663c0f6856a23f41c249944f0c3cfac0744847268853a62af5dd8fc90a","signSignature":"dfa9b807fff362d581170b41c56a2b8bd723c48d1f100f2856d794408723e8973016d75aeff4705e6837dcdb745aafb41aa10a9f1ff8a77d128ba3d712e90907","id":"16348623380114619131"}' - -// schicke diese Daten mittels HTTP POST an den Asch-Server -curl -H "Content-Datentyp: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":0,"amount":10000000000,"fee":10000000,"recipientId":"16358246403719868041","timestamp":5333378,"asset":{},"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","signature":"2d47810b7d9964c5c4d330a53d1382769e5092b3a53639853f702cf4a382aafcff8ef8663c0f6856a23f41c249944f0c3cfac0744847268853a62af5dd8fc90a","signSignature":"dfa9b807fff362d581170b41c56a2b8bd723c48d1f100f2856d794408723e8973016d75aeff4705e6837dcdb745aafb41aa10a9f1ff8a77d128ba3d712e90907","id":"16348623380114619131"}}' http://45.32.248.33:4096/peer/transactions -``` - -Mögliche JSON Antwort: -```js -{ - "success":true //Erfolgte Überweisung -} -``` - -##### 2.9.2.3 Ein Delegat registrieren -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|transaction|JSON|Ja|Transaktionsdaten erstellt mittels [asch-js.delegate.createDelegate]| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |ob die Transaktion erfolgreich war oder nicht | - - -Beispiel: -```js -var asch = require('asch-js'); -var password = 'measure bottom stock hospital calm hurdle come banner high edge foster cram'; -var secondPassword = 'erjimimashezhi001'; -var userName = 'zhenxi_test'; - -var transaction = asch.delegate.createDelegate(password, userName, secondPassword || undefined); -json.stringify(transaction) -'{"type":2,"amount":0,"fee":10000000000,"recipientId":null,"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","timestamp":5334485,"asset":{"delegate":{"username":"zhenxi_test","publicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f"}},"signature":"a12ce415d2d21ab46e4c1b918b8717b1d351dd99abd6f2f94d9a1a7e1f32b697f843a05b1851cb857ea45a2476dce592f5ddd612c00cd44488b8b610c57d7f0a","signSignature":"35adc9f1f37d14458e8588f9b4332eedf1151c02480159f64a287a4b0cbb59bfe82040dfec96a4d9560bae99b8eaa1799a7023395db5ddc640d95447992d6e00","id":"12310465407307249905"}' - -// schicke oben erstellte Daten an den Asch Server mittels HTTP Post um ein Delegat zu registrieren -curl -H "Content-Datentyp: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":2,"amount":0,"fee":10000000000,"recipientId":null,"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","timestamp":5334485,"asset":{"delegate":{"username":"zhenxi_test","publicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f"}},"signature":"a12ce415d2d21ab46e4c1b918b8717b1d351dd99abd6f2f94d9a1a7e1f32b697f843a05b1851cb857ea45a2476dce592f5ddd612c00cd44488b8b610c57d7f0a","signSignature":"35adc9f1f37d14458e8588f9b4332eedf1151c02480159f64a287a4b0cbb59bfe82040dfec96a4d9560bae99b8eaa1799a7023395db5ddc640d95447992d6e00","id":"12310465407307249905"}}' http://45.32.248.33:4096/peer/transactions -``` - -Mögliche JSON Antwort: -```js -{ - "success":true //Registration war erfolgreich -} -``` - -##### 2.9.2.4 Wahl abgeben und Stimmabgabe zurückziehen - -Beschreibung der Parameter: - -|Name |Datentyp |Obligatorisch |Beschreibung | -|------ |----- |--- |---- | -|transaction|JSON|Ja|Transaktionsdaten erstellt mittels [asch-js.vote.createVote]| - -Beschreibung der Antwort-Parameter: - -|Name |Datentyp |Beschreibung | -|------ |----- |---- | -|success|bool |ob die Stimmabgabe erfolgreich war | - - -Beispiel: -```js -var asch = require('asch-js'); -var password = 'measure bottom stock hospital calm hurdle come banner high edge foster cram'; -var secondPassword = 'erjimimashezhi001'; -// Jedes Element der Liste zur Stimmabgabe setzt sich aus einem Symbol (+ oder -) und des öffentlichen Schlüssels des Delegats. Plus (+) bedeutet eine Stimmabgabe, ein Minus (-) steht für eine Annullierung der Stimme. -var voteContent = [ - '-ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7', - '+c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2' -]; - -var transaction = asch.vote.createVote(password, voteContent, secondPassword || undefined); -json.stringify(transaction) -{"type":3,"amount":0,"fee":10000000,"recipientId":null,"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","timestamp":5334923,"asset":{"vote":{"votes":["-ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7","+c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2"]}},"signature":"6036c2066a231c452a1c83aafd3bb9db3842ee05d5f17813f8264a4294cdec761faa89edf4a95f9b2e2451285807ab18aa9f989ad9a3165b95643179b8e4580f","signSignature":"a216ca739112e6f65986604b9467ccc8058138a7077faf134d6c4d673306cd1c514cc95bd54a036f7c602a56c4b4f2e4e59f6aa7c376cb1429e89054042e050b","id":"17558357483072606427"} - -// sende die oben bekommenen Daten den Asch-Server mittels HTTP POST -curl -H "Content-Datentyp: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":3,"amount":0,"fee":10000000,"recipientId":null,"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","timestamp":5334923,"asset":{"vote":{"votes":["-ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7","+c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2"]}},"signature":"6036c2066a231c452a1c83aafd3bb9db3842ee05d5f17813f8264a4294cdec761faa89edf4a95f9b2e2451285807ab18aa9f989ad9a3165b95643179b8e4580f","signSignature":"a216ca739112e6f65986604b9467ccc8058138a7077faf134d6c4d673306cd1c514cc95bd54a036f7c602a56c4b4f2e4e59f6aa7c376cb1429e89054042e050b","id":"17558357483072606427"}}' http://45.32.248.33:4096/peer/transactions -``` - -Mögliche JSON Antwort: -```js -{ - "success":true //war Stimmabgabe oder Rückziehung erfolgreich -} -``` - - -## Appendix 1:Installiere das 'asch-js' Modul -Alle Operationen in Asch werden mit einer Transaktion beendet. Die Transaktionsdaten werden mittels des Moduls "asch-js" erstellt und dann mittels HTTP POST an den API Endpunkt geschickt. - -**Installiere das Modul** -`npm install asch-js` diff --git a/docs/asch_http_interface_en.md b/docs/asch_http_interface_en.md deleted file mode 100644 index 683d16c..0000000 --- a/docs/asch_http_interface_en.md +++ /dev/null @@ -1,1979 +0,0 @@ -Table of Contents -================= - - * [Asch-HTTP Interface Specification](#asch-http-interface-specification) - * [1 API Usage Guide](#1-api-usage-guide) - * [1.1 Request Process Overview](#11-request-process-overview) - * [2 Interface](#2-interface) - * [2.1 Accounts](#21-accounts) - * [2.1.1 Login](#211-login) - * [2.1.1.1 Login after locally encrypt (recommended)](#2111-login-after-locally-encrypt-recommended) - * [2.1.1.2 Login without locally encrypt (not recommend)](#2112-login-without-locally-encrypt-not-recommend) - * [2.1.2 Get Account Information](#212-get-account-information) - * [2.1.3 Get Balance of Account](#213-get-balance-of-account) - * [2.1.4 Get Account's Public Key](#214-get-accounts-public-key) - * [2.1.5 Generate Public Key](#215-generate-public-key) - * [2.1.6 Get Voting List by Address](#216-get-voting-list-by-address) - * [2.1.7 Get the Fee of Given Delegate](#217-get-the-fee-of-given-delegate) - * [2.1.8 Voting](#218-voting) - * [2.2 Transactions](#22-transactions) - * [2.2.1 Get the Transaction Detail Information](#221-get-the-transaction-detail-information) - * [2.2.2 Get the Transaction Detail Information by Transaction ID](#222-get-the-transaction-detail-information-by-transaction-id) - * [2.2.3 Get Transaction Detail by Unconfirmed Transaction ID](#223-get-transaction-detail-by-unconfirmed-transaction-id) - * [**2.2.4 Get Unconfirmed Transaction Detail Inforamtion [within all network]](#224-get-unconfirmed-transaction-detail-inforamtion-within-all-network) - * [2.2.5 Create Transaction](#225-create-transaction) - * [2.3 Blocks](#23-blocks) - * [2.3.1 Get the Block Detail Information of the Given ID](#231-get-the-block-detail-information-of-the-given-id) - * [2.3.2 Get the Latest Block](#232-get-the-latest-block) - * [2.3.3 Get the Block Height](#233-get-the-block-height) - * [2.3.4 Get the Transaction Fee](#234-get-the-transaction-fee) - * [2.3.5 Get the Milestone](#235-get-the-milestone) - * [2.3.6 Get the Reward Information of a Block](#236-get-the-reward-information-of-a-block) - * [2.3.7 Get the Current Maximum Supply of the Blockchain](#237-get-the-current-maximum-supply-of-the-blockchain) - * [2.3.8 Get Current Status of Blockchain](#238-get-current-status-of-blockchain) - * [2.4 Delegates](#24-delegates) - * [2.4.1 Get the Total Number of Delegates](#241-get-the-total-number-of-delegates) - * [2.4.2 Check the Voters of Delegates by Public Key](#242-check-the-voters-of-delegates-by-public-key) - * [2.4.3 Get the Delegate's Detail by Public Key or Name](#243-get-the-delegates-detail-by-public-key-or-name) - * [2.4.4 Get the List of Delegates](#244-get-the-list-of-delegates) - * [2.4.5 Get the Transaction Fee Set by Delegate](#245-get-the-transaction-fee-set-by-delegate) - * [2.4.6 Get Forge Information by Public Key](#246-get-forge-information-by-public-key) - * [2.4.7 Register Delegate](#247-register-delegate) - * [2.5 Peers](#25-peers) - * [2.5.1 Get all Peers' Information in the Whole Network](#251-get-all-peers-information-in-the-whole-network) - * [2.5.2 Get the Version of Peer](#252-get-the-version-of-peer) - * [2.5.3 Get the Peer Information of a Given IP Address](#253-get-the-peer-information-of-a-given-ip-address) - * [2.6 Sync and Loader](#26-sync-and-loader) - * [2.6.1 Get the local blockchain loadig status](#261-get-the-local-blockchain-loadig-status) - * [2.6.2 Get the block syncing status](#262-get-the-block-syncing-status) - * [2.7 Second Password](#27-second-password) - * [2.7.1 Set the Second Password](#271-set-the-second-password) - * [2.7.2 Get the Transaction Fee of Setting Second Password](#272-get-the-transaction-fee-of-setting-second-password) - * [2.8 Multiple Signatures](#28-multiple-signatures) - * [2.8.1 Set Normal Account to Multi-signatures Account](#281-set-normal-account-to-multi-signatures-account) - * [2.8.2 Get the Detail Information of Pending Multi-signature Transaction](#282-get-the-detail-information-of-pending-multi-signature-transaction) - * [2.8.3 Sign the Multi-signature Transaction (by non-initiator)](#283-sign-the-multi-signature-transaction-by-non-initiator) - * [2.8.4 Get Detail Information of the Multi-signature Account](#284-get-detail-information-of-the-multi-signature-account) - * [2.9 Peer to Peer Transportation[secure API]](#29-peer-to-peer-transportationsecure-api) - * [2.9.1 Overview](#291-overview) - * [2.9.2 Transaction](#292-transaction) - * [2.9.2.1 Set the Second Payment Password](#2921-set-the-second-payment-password) - * [2.9.2.2 Transfer Money](#2922-transfer-money) - * [2.9.2.3 Register Delegates](#2923-register-delegates) - * [2.9.2.4 Vote and Cancel the vote](#2924-vote-and-cancel-the-vote) - * [Appendix 1: Install 'asch-js' library](#appendix-1-install-asch-js-library) - -Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc) - -# Asch-HTTP Interface Specification - ---- -## 1 API Usage Guide -### 1.1 Request Process Overview -- **Generate request data:** according the interface specification provided by Asch system, generate the request data as a JSON object. (In one case, if you write about secure peer to peer transportation, you may need a JS library called asch-js to create signature. see [2.9 Peer to Peer transportation](# 29-peer-to-peer-transportation) for detail). -- **Send request data:** transfer the generated data object to Asch platform through POST/GET method upon HTTP -- **Asch system handles the data object:** after receiving the data object, Asch server will validate the data firstly, then deal with it. -- **Return the response data:** Asch system send the response data to client as a JSON object. See interface part for detail, like response data format and error code. -- **Client handles the response data** - -## 2 Interface -### 2.1 Accounts - -#### 2.1.1 Login -##### 2.1.1.1 Login after locally encrypt (recommended) -Interface Address: /api/accounts/open2/ -Request Type: post -Supported Format: json -Comment: Public key needs to be generated locally according to user's password (see Request Example) - -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|publicKey |string |Y |Asch account public key | - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |Whether login is successful | -|account|json |Account Information | -Request Example: - -```js -var AschJS = require('asch-js'); //For further information about asch-js, please see Appendix -var publicKey = AschJS.crypto.getKeys(secret).publicKey; //Generate public key according to password -// var address = AschJS.crypto.getAddress(publicKey); //Generate address according to public key - -// Submit the above data to Asch server through post method -curl -X POST -H "Content-Type: application/json" -k -d '{"publicKey":"bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9"}' http://45.32.248.33:4096/api/accounts/open2/ -``` - -JSON Response Example: -```js -{ - "success": true, - "account": { - "address": "16723473400748954103", - "unconfirmedBalance": 19480000000, - "balance": 19480000000, - "unconfirmedSignature": false, - "secondSignature": true, - "secondPublicKey": "edf30942beb74de5ed6368c792af8665e9636f32a5f1c9377bcdc3b252d3f277", - "multisignatures": [], - "u_multisignatures": [] - }, - "latestBlock": { - "height": 111923, - "timestamp": 4446270 - }, - "version": { - "version": "1.0.0", - "build": "12:11:11 16/08/2016", - "net": "testnet" - } -``` - -##### 2.1.1.2 Login without locally encrypt (not recommend) -Interface Address: /api/accounts/open/ -Request Method:post -Supported Format: json -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|secret |string |Y |asch account password | - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |Whether login is successful | -|account|json |Account information | - -Request Example: -```bash -curl -X POST -H "Content-Type: application/json" -k -d '{"secret":"fault still attack alley expand music basket purse later educate follow ride"}' http://45.32.248.33:4096/api/accounts/open/ -``` - -JSON Response Example: -```js -{ - "success": true, - "account": { - "address": "16723473400748954103", - "unconfirmedBalance": 19480000000, - "balance": 19480000000, - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9", - "unconfirmedSignature": false, - "secondSignature": true, - "secondPublicKey": "edf30942beb74de5ed6368c792af8665e9636f32a5f1c9377bcdc3b252d3f277", - "multisignatures": [ ], - "u_multisignatures": [ ] - } -} -``` -#### 2.1.2 Get Account Information -Interface Address: /api/accounts -Request Method:get -Supported Format: urlencoded -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|address |string |Y |Client's address, minimum length:1 | - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |whether response data can be returned | -|account|json |account information | -|latestBlock|json |latest block information | -|version|json |version information | - -Request Example: -```bash -curl -k -X GET http://45.32.248.33:4096/api/accounts?address=16723473400748954103 -``` - -JSON Response Example: -```js -{ - "success": true, - "account": { - "address": "16723473400748954103", //Asch address - "unconfirmedBalance": 19480000000, //the sum of unconfirmed and confirmed balance, that should be larger than or equal to balance below. - "balance": 19480000000, //balance - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9", //Public key - "unconfirmedSignature": false, - "secondSignature": true, //second signature - "secondPublicKey": "edf30942beb74de5ed6368c792af8665e9636f32a5f1c9377bcdc3b252d3f277", //second public key - "multisignatures": [], - "u_multisignatures": [] - }, - "latestBlock": { - "height": 114480, //block height - "timestamp": 4471890 - }, - "version": { - "version": "1.0.0", - "build": "12:11:11 16/08/2016", //build date - "net": "testnet" //blockchain type: main chain or test one - } -} -``` -#### 2.1.3 Get Balance of Account -Interface Address: /api/accounts/getBalance -Request Method: get -Supported Format: urlencoded -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|address |string |Y |Client's address, minimum length:1 | - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|balance|integer |balance | -|unconfirmedBalance|integer|the sum of unconfirmed and confirmed balance, that should be larger than or equal to balance| - - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/accounts/getBalance?address=14636456069025293113' -``` - -JSON Response Example: -```js -{ - "success": true, - "balance": 5281328514990, - "unconfirmedBalance": 5281328514990 -} -``` - -#### 2.1.4 Get Account's Public Key -Interface Address: /api/accounts/getPublickey -Request Method:get -Supported Format: urlencoded -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|address |string |Y |Client's address, minimum length:1 | - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|publicKey|string |public key | - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/accounts/getPublickey?address=14636456069025293113' -``` - -JSON Response Example: -```js -{ - "success": true, - "publicKey": "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7" -} -``` - -#### 2.1.5 Generate Public Key -Interface Address: /api/accounts/generatePublickey -Request Method: post -Supported Format: json -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|secret |string |Y |Asch account password | - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|publicKey|string |public key | - -Request Example: -```bash -curl -k -H "Content-Type: application/json" -X POST -d '{"secret":"fault still attack alley expand music basket purse later educate follow ride"}' 'http://45.32.248.33:4096/api/accounts/generatePublickey' -``` - -JSON Response Example: -```js -{ - "success": true, - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9" -} -``` - -#### 2.1.6 Get Voting List by Address -Interface Address: /api/accounts/delegates -Request Method: get -Supported Format: urlencoded -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|address |string |Y |Voter's address | - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|delegates|Array |A list that contains detail information of those delegates who have already voted | - - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/accounts/delegates?address=14636456069025293113' -``` - -JSON Response Example: -```js -{ - "success": true, - "delegates": [{ - "username": "wgl_002", - "address": "14636456069025293113", - "publicKey": "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7", - "vote": 9901985415600500, - "producedblocks": 1373, - "missedblocks": 6, - "rate": 1, - "approval": "98.54", - "productivity": "99.56" - }, - { - "username": "wgl_003", - "address": "9961157415582672274", - "publicKey": "c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2", - "vote": 9891995435600500, - "producedblocks": 1371, - "missedblocks": 8, - "rate": 2, - "approval": "98.44", - "productivity": "99.41" - }, - { - "username": "wgl_001", - "address": "1869971419039689816", - "publicKey": "c547df2dde6cbb4508aabcb5970d8f9132e5a1d1c422632da6bc20bf1df165b8", - "vote": 32401577128413, - "producedblocks": 969, - "missedblocks": 8, - "rate": 102, - "approval": "0.32", - "productivity": 0 - }] -} -``` - -#### 2.1.7 Get the Fee of Given Delegate -Interface Address: /api/accounts/delegates/fee -Request Method:get -Supported Format: none -Request Parameter Description: none - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|fee|integer |fee setting | - - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/accounts/delegates/fee -``` - -JSON Response Example: -```js -{ - "success": true, - "fee": 100000000 -} -``` - - -#### 2.1.8 Voting -Interface Address: /api/accounts/delegates -Request Method:put -Supported Format: json -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|secret |string |Y |Asch account password | -|publicKey|string |N|public key | -|secondSecret|string|N|Asch account's second password,minimum length:1,maximum length:100| -|delegates|Array|a list that contains delegates' public key. put +/- in front of each public key, which means vote/abolish this delegate. | - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|transaction|json |voting detail inforamtion | - - -Request Example: -```bash -curl -k -H "Content-Type: application/json" -X PUT -d '{"secret":"call scissors pupil water friend timber spend brand vote obey corn size","publicKey":"3ec1c9ec08c0512641deba37c0e95a0fe5fc3bdf58424009f594d7d6a4e28a2a","delegates":["+fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575"]}' 'http://45.32.248.33:4096/api/accounts/delegates' -``` - -JSON Response Example: -```js - { - "success": true, - "transaction": { - "type": 3, //the type of vote is '3' - "amount": 0, - "senderPublicKey": "3ec1c9ec08c0512641deba37c0e95a0fe5fc3bdf58424009f594d7d6a4e28a2a", - "requesterPublicKey": null, - "timestamp": 5056064, - "asset": { - "vote": { - "votes": ["+fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575"] - } - }, - "recipientId": null, - "signature": "0bff58c7311fc59b3c8b3ffc236bbfece9850c334fb0c292ab087f78cf9a6c0f4d3e541c501887a2c2ec46294c777e8f7bf7dea9cb7c9a175fdec641bb684f08", - "id": "5630629337798595849", - "fee": 10000000, - "senderId": "15238461869262180695" - } -} -``` - -### 2.2 Transactions -#### 2.2.1 Get the Transaction Detail Information -Interface Address: /api/transactions -Request Method: get -Supported Format: urlencoded -Comment: if there is no parameter in request data, all network transactions will be returned. -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|blockId |string |N |block id | -|limit |integer |N |the limitation of returned records,minimum:0,maximum:100 | -|type|integer |N |The transaction type,0:normal transfer,1:setting second password,2:registering delegate,3:voting,4:multiple signature,5:DAPP,6:IN_TRANSFER,7:OUT_TRANSFER | -|orderBy|string |N |sort with a field in the table,senderPublicKey:desc | -|offset|integer |N |offset, minimum 0 | -|senderPublicKey|string|N|sender's public key| -|ownerPublicKey|string|N|| -|ownerAddress|string|N|| -|senderId|string|N|sender's address| -|recipientId|string|N|recipient's address, minimum:1| -|amount|integer|N|amount| -|fee|integer|N|charge fee| - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|transactions|Array |A JSON object list containing multiple transactions' detail | -|count|int|the total number of retrieved transactions| - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/transactions?recipientId=16723473400748954103&orderBy=t_timestamp:desc&limit=3' -``` - -JSON Response Example: -```js -{ - "success": true, - "transactions": [{ - "id": "17192581936339156329", - "height": "105951", - "blockId": "15051364118100195665", - "type": 0, - "timestamp": 4385190, - "senderPublicKey": "d39d6f26869067473d685da742339d1a9117257fe14b3cc7261e3f2ed5a339e3", - "senderId": "15745540293890213312", - "recipientId": "16723473400748954103", - "amount": 10000000000, - "fee": 10000000, - "signature": "98d65df3109802c707eeed706e90a907f337bddab58cb4c1fbe6ec2179aa1c85ec2903cc0cf44bf0092926829aa5a0a6ec99458f65b6ebd11f0988772e58740e", - "signSignature": "", - "signatures": null, - "confirmations": "31802", - "asset": { - - } - }, - { - "id": "7000452951235123088", - "height": "105473", - "blockId": "11877628176330539727", - "type": 0, - "timestamp": 4380147, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "senderId": "16358246403719868041", - "recipientId": "16723473400748954103", - "amount": 10000000000, - "fee": 10000000, - "signature": "dc84044d4f6b4779eecc3a986b6507e458cc5964f601ebeb4d3b68a96129813f4940e14de950526dd685ca1328b6e477e6c57e95aeac45859a2ea62a587d0204", - "signSignature": "", - "signatures": null, - "confirmations": "32280", - "asset": { - - } - }, - { - "id": "14093929199102906687", - "height": "105460", - "blockId": "2237504897174225512", - "type": 0, - "timestamp": 4380024, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "senderId": "16358246403719868041", - "recipientId": "16723473400748954103", - "amount": 10000000000, - "fee": 10000000, - "signature": "73ceddc3cbe5103fbdd9eee12f7e4d9a125a3bcf2e7cd04282b7329719735aeb36936762f17d842fb14813fa8f857b8144040e5117dffcfc7e2ae88e36440a0f", - "signSignature": "", - "signatures": null, - "confirmations": "32293", - "asset": { - - } - }], - "count": 3 -} -``` -#### 2.2.2 Get the Transaction Detail Information by Transaction ID -Interface Address: /api/transactions/get -Request Method:get -Supported Format: urlencoded -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|Id |string |Y |transaction id | - - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|transactions|json |transaction detail information | - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/transactions/get?id=14093929199102906687' -``` - -JSON Response Example: -```js -{ - "success": true, - "transaction": { - "id": "14093929199102906687", - "height": "105460", - "blockId": "2237504897174225512", - "type": 0, - "timestamp": 4380024, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "senderId": "16358246403719868041", - "recipientId": "16723473400748954103", - "amount": 10000000000, - "fee": 10000000, - "signature": "73ceddc3cbe5103fbdd9eee12f7e4d9a125a3bcf2e7cd04282b7329719735aeb36936762f17d842fb14813fa8f857b8144040e5117dffcfc7e2ae88e36440a0f", - "signSignature": "", - "signatures": null, - "confirmations": "34268", - "asset": { - } - } -} -``` - -#### 2.2.3 Get Transaction Detail by Unconfirmed Transaction ID -Interface Address: /api/transactions/unconfirmed/get -Request Method:get -Supported Format: urlencoded -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|id|string |Y |unconfirmed transaction id | - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|transaction|json |unconfirmed transaction detail inforamtion | - - -Request Example: -```bash -curl -k -X GET http://45.32.248.33:4096/api/transactions/unconfirmed/get?id=7557072430673853692 //Regularly, this unconfirmed transaction exist during an extremely short time, almost 0~10 second. -``` - -JSON Response Example: -```js -{ - "success": true, - "transaction": { - "type": 0, - "amount": 10000, - "senderPublicKey": "3ec1c9ec08c0512641deba37c0e95a0fe5fc3bdf58424009f594d7d6a4e28a2a", - "requesterPublicKey": null, - "timestamp": 5082322, - "asset": { - - }, - "recipientId": "16723473400748954103", - "signature": "3a97f8d63509ef964bda3d816366b8e9e2d9b5d4604a660e7cbeefe210cb910f5de9a51bece06c32d010f55502c62f0f59b8224e1c141731ddfee27206a88d02", - "id": "7557072430673853692", - "fee": 10000000, - "senderId": "15238461869262180695" - } -} -``` - - -#### **2.2.4 Get Unconfirmed Transaction Detail Inforamtion [within all network] -Interface Address: /api/transactions/unconfirmed -Request Method:get -Supported Format: urlencoded -Comment: If there is no parameter, all unconfirmed transactions in the whole network will be returned. -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|senderPublicKey |string |N |sender's public key | -|address |string |N |address | - - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|transactions|Array |a list containing all unconfirmed transactions | - - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/transactions/unconfirmed' -``` - -JSON Response Example: -```js -{ - "success": true, - "transactions": [] //Currently there is no unconfirmed transaction in the whole network -} -``` - -#### 2.2.5 Create Transaction -Interface Address: /api/transactions -Request Method:PUT -Supported Format: json -Comment: Recipiant acount must have already login in wallet on the web. -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|secret |string |Y |Asch account password | -|amount|integer|Y|amount,between 1 and 10000000000000000| -|recipientId|string|Y|recipient's address, minimum:1| -|publicKey|string|N|sender's public key| -|secondSecret|string|N|sender's second password (must fit the BIP39 standard), the length should be between 1 and 100| -|multisigAccountPublicKey|string|N|the public key of multiple signature account| - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|transactionId|string |transaction id | - - -Request Example: -```bash -curl -k -H "Content-Type: application/json" -X PUT -d '{"secret":"unaware label emerge fancy concert long fiction report affair appear decide twenty","amount":1000000,"recipientId":"16723473400748954103"}' 'http://45.32.248.33:4096/api/transactions' -``` - -JSON Response Example: -```js -{ - "success": true, - "transactionId": "16670272591943275531" -} -``` - -### 2.3 Blocks -#### 2.3.1 Get the Block Detail Information of the Given ID -Interface Address: /api/blocks/ -Request Method:get -Supported Format: urlencoded -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|id |string |only choose one of these three parameters |block ID | -|height|string|ditto|block height| -|hash|string|ditto|block hash value| - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|block|json |the block detail information | - - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/get?id=6076474715648888747' -``` - -JSON Response Example: -```js -{ - "success": true, - "block": { - "id": "6076474715648888747", - "version": 0, - "timestamp": 4734070, - "height": 140538, - "previousBlock": "16033230167082515105", //previous block ID - "numberOfTransactions": 0, //The number of transactions - "totalAmount": 0, //the total transactions' amount - "totalFee": 0, - "reward": 350000000, //reward - "payloadLength": 0, - "payloadHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "generatorPublicKey": "1d352950c8141e1b35daba4a974a604519d7a2ef3a1ec0a503ce2653646aa052", - "generatorId": "6656029629904254066", - "blockSignature": "a53de66922cdc2f431acd0a474beec7cf7c420a8460b7b7caf84999be7caebb59fb7fbb7166c2c7013dbb431585ea7294722166cb08bf9663abf50b6bd81cd05", - "confirmations": "2", - "totalForged": 350000000 - } -} -``` - -#### 2.3.2 Get the Latest Block -Interface Address: /api/blocks -Request Method: get -Supported Format: urlencoded -Comment: if there is no parameter, the detail of all the blocks in the whole network will be returned -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|limit |integer |N |maximum number of returned records, between 0 and 100 | -|orderBy|string |N |sort by a field in the table, for example, height:desc | -|offset|integer |N |offset, minimum 0 | -|generatorPublicKey|string |N |public key of the block generator | -|totalAmount|integer |N |total amount of transactions, from 0 to 10000000000000000 | -|totalFee|integer |N |total fee of transaction, from 0 to 10000000000000000 | -|reward|integer |N |the amount of reward, minimum: 0 | -|previousBlock|string |N |previous block | -|height|integer |N |block height | - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|blocks|Array |a list of JSON objects containing block detail| -|count|integer|block height| - - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks?limit=2&offset=0&orderBy=height:desc' -``` - -JSON Response Example: -```js -{ - "success": true, - "blocks": [{ - "id": "12634047624004615059", - "version": 0, - "timestamp": 4708080, - "height": 137986, - "previousBlock": "3498191422350401106", - "numberOfTransactions": 0, // the number of transactions - "totalAmount": 0, // total amount of transactions - "totalFee": 0, // transaction fee - "reward": 350000000, // reward - "payloadLength": 0, - "payloadHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "generatorPublicKey": "44db7bec89ef289d0def257285675ca14f2a947dfd2b70e6b1cff4392ce42ada", - "generatorId": "4925169939071346193", - "blockSignature": "83a2124e3e8201c1a6099b2ac8ab1c117ad34867978add3a90d41a64df9d2ad8fabc9ec14d27a77cd34c08a6479ef684f247c11b1cbbcb0e9767dffc85838600", - "confirmations": "1", - "totalForged": 350000000 - }, - { - "id": "3498191422350401106", - "version": 0, - "timestamp": 4708070, - "height": 137985, - "previousBlock": "14078155423801039323", - "numberOfTransactions": 0, - "totalAmount": 0, - "totalFee": 0, - "reward": 350000000, - "payloadLength": 0, - "payloadHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "generatorPublicKey": "500b1ec025cd64d36008341ed8d2508473ecf559be213ca5f9580620a21a592c", - "generatorId": "16006295608945777169", - "blockSignature": "a0b5ed6c94b1f33c4d0f017f21a08357061493392b19e34eeedf274b77c751e3f86c92443280de09ea1754d62fe7ef00e02acbdc3bc0c1063cef344bacaa4f07", - "confirmations": "2", - "totalForged": 350000000 - }], - "count": 137986 -} -``` - -#### 2.3.3 Get the Block Height -Interface Address: /api/blocks/getHeight -Request Method:get -Supported Format: none -Request Parameter Description: none - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|height|integer |block height | - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/getheight' -``` - -JSON Response Example: -```js -{"success":true,"height":140569} -``` - -#### 2.3.4 Get the Transaction Fee -Interface Address: /api/blocks/getFee -Request Method:get -Supported Format: none -Request Parameter Description: none - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|fee|integer |transaction fee | - - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/getfee' -``` - -JSON Response Example: -```js -{"success":true,"fee":10000000} //transaction fee is -0.1 XAS -``` - -#### 2.3.5 Get the Milestone -Interface Address: /api/blocks/getMilestone -Request Method: get -Supported Format: none -Request Parameter Description: none -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|milestone|integer | | - - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/getMilestone' -``` - -JSON Response Example: -```js -{"success":true,"milestone":0} -``` - -#### 2.3.6 Get the Reward Information of a Block -Interface Address: /api/blocks/getReward -Request Method:get -Supported Format: none -Request Parameter Description: none - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|reward|integer |the reward of the block | - - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/getReward' -``` - -JSON Response Example: -```js -{"success":true,"reward":350000000} //every single block you created will be rewarded by 3.5 XAS -``` - -#### 2.3.7 Get the Current Maximum Supply of the Blockchain -Interface Address: /api/blocks/getSupply -Request Method:get -Supported Format: none -Request Parameter Description: none - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|supply|integer |the total amount of XAS in the whole network | - - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/getSupply' -``` - -JSON Response Example: -```js -{"success":true,"supply":10049222600000000} //There are totally 100492226 XAS in current testnet -``` - -#### 2.3.8 Get Current Status of Blockchain -Interface Address: /api/blocks/getStatus -Request Method:get -Supported Format: none -Request Parameter Description: none - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|height|integer |blockchain height | -|fee|integer |transaction fee | -|milestone|integer | | -|reward|integer |block reward | -|supply|integer |total amount of XAS in the whole network | - - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/blocks/getStatus' -``` - -JSON Response Example: -```js -{ - "success": true, - "height": 140649, - "fee": 10000000, - "milestone": 0, - "reward": 350000000, - "supply": 10049227150000000 -} -``` - - - -### 2.4 Delegates - -#### 2.4.1 Get the Total Number of Delegates -Interface Address: /api/delegates/count -Request Method: get -Supported Format: none -Request Parameter Description: none - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|count|integer |total number of delegates | - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/delegates/count' -``` - -JSON Response Example: -```js -{"success":true,"count":234} -``` - -#### 2.4.2 Check the Voters of Delegates by Public Key -Interface Address: /api/delegates/voters -Request Method:get -Supported Format: urlencoded -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|publicKey |string |Y |public key of the delegate | - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|accounts|Array |a JSON object list of account | - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/delegates/voters?publicKey=ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7' -``` - -JSON Response Example: -```js -{ - "success": true, - "accounts": [{ - "address": "2918354313445278349", - "publicKey": "4fde4c49f1297d5d3a24b1494204543c4281aff17917ff7ff8ff32da3b4b222f", - "balance": 1338227722727, - "weight": 0.013316660647014596 - }, - { - "address": "1523444724068322527", - "publicKey": "8a6a61c28dc47541aadf1eecec2175c8f768f2331eea3472b1593bf1aa4e1fb4", - "balance": 2109297623765, - "weight": 0.020989552213127274 - }, - { - "address": "14483826354741911727", - "publicKey": "5dacb7983095466b9b037690150c3edec0f073815326e33a4744b6d1d50953e2", - "balance": 5135815841470, - "weight": 0.051106336795243436 - } - }] -} -``` - -#### 2.4.3 Get the Delegate's Detail by Public Key or Name -Interface Address: /api/delegates/get/ -Request Method:get -Supported Format: urlencoded -Comment:Get the delegate's detail by his/her public key or user name -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|publickey |string |choose only one parameter of these two |delegate's public key | -|username |string |ditto |delegate's user name | - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|delegate|json |the detail information of this delegate | - - -Request Example: -```bash -curl -k -X GET http://45.32.248.33:4096/api/delegates/get?publicKey=bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9 -curl -k -X GET http://45.32.248.33:4096/api/delegates/get?username=delegate_register -``` - -JSON Response Example: -```js -{ - "success": true, - "delegate": { - "username": "delegate_register", - "address": "16723473400748954103", - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9", - "vote": 0, - "producedblocks": 0, - "missedblocks": 0, - "fees": 0, - "rewards": 0, - "rate": 191, - "approval": 0, - "productivity": 0, - "forged": "0" - } -} -``` - -#### 2.4.4 Get the List of Delegates -Interface Address: /api/delegates -Request Method:get -Supported Format: urlencoded -Comment: if there is no parameter, all delegates in the whole network will be returned. -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|address |string |N |delegate's address | -|limit|int |N |maximum return records | -|offset|integer |N |offset, minimum: 0 | -|orderBy|string |N |[field used to sort]:[sort type] e.g., address:desc | - - - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|delegates|Array |a list containing delegates' detail information | - - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/delegates?orderby=approval:desc&limit=2' //the first two delegates order by approval vote, descendingly -``` - -JSON Response Example: -```js -{ - "success": true, - "delegates": [{ - "username": "wgl_002", //delegate's user name - "address": "14636456069025293113", //delegate's address - "publicKey": "ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7", //delegate's public key - "vote": 9901984015600500, //the number of vote - "producedblocks": 1371, //the number of generated blocks - "missedblocks": 6, //the number of missed blocks - "fees": 12588514990, - "rewards": 276850000000, //the gained reward - "rate": 1, - "approval": 98.54, //the rate of approval votes - "productivity": 99.56, //the productivity - "forged": "289438514990" //All reward from forge - }, - { - "username": "wgl_003", - "address": "9961157415582672274", - "publicKey": "c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2", - "vote": 9891994035600500, - "producedblocks": 1370, - "missedblocks": 8, - "fees": 12355148480, - "rewards": 275100000000, - "rate": 2, - "approval": 98.44, - "productivity": 99.42, - "forged": "287455148480" - }], - "totalCount": 233 -} -``` - - - - - - -#### 2.4.5 Get the Transaction Fee Set by Delegate -Interface Address: /api/delegates/fee -Request Method:get -Supported Format: urlencoded -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|publicKey |string |Y |delegate's public key | - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|fee|integer |transaction fee | - - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/delegates/fee?publicKey=ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7' -``` - -JSON Response Example: -```js -{"success":true,"fee":10000000000} //0.1 XAS -``` - -#### 2.4.6 Get Forge Information by Public Key -Interface Address: /api/delegates/forging/getForgedByAccount -Request Method:get -Supported Format: urlencoded -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|generatorPublicKey |string |Y |block generator's public key | - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|fees|integer |total amount of charged fee | -|rewards|integer|gained rewards| -|forged|integer|total rewards comming from forge| - - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/delegates/forging/getForgedByAccount?generatorPublicKey=ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7' -``` - -JSON Response Example: -```js -{ - "success": true, - "fees": 12589307065, - "rewards": 285600000000, - "forged": 298189307065 -} -``` - -#### 2.4.7 Register Delegate -Interface Address: /api/delegates -Request Method:put -Supported Format: urlencoded -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|secret |string |Y |Asch account password | -|publicKey|string |N |public key| -|secondSecret|string|N|Asch account's second password, minimum length:1 maximum length: 100 | -|username|string|N|the delegate's user name| - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|transaction|json |the detail of the registering process | - - -Request Example: -```bash -curl -k -H "Content-Type: application/json" -X PUT -d '{"secret":"unaware label emerge fancy concert long fiction report affair appear decide twenty","username":"delegate_0821"}' 'http://45.32.248.33:4096/api/delegates' -``` - -JSON Response Example: -```js -{ - "success": true, - "transaction": { - "type": 2, //the transaction type of registering delegate is 2 - "amount": 0, - "senderPublicKey": "3b64f1833e6328043e1f2fee31e638bdaa6dfff5c7eb9c8577a5cefcf11261f2", - "requesterPublicKey": null, - "timestamp": 4737615, - "asset": { - "delegate": { - "username": "delegate_0821", - "publicKey": "3b64f1833e6328043e1f2fee31e638bdaa6dfff5c7eb9c8577a5cefcf11261f2" - } - }, - "recipientId": null, - "signature": "7f8417e8db5f58ddff887c86c789c26b32fd3f01083ef1e3c8d4e18ed16622bf766492d78518c6c7a07aada1c98b1efc36d40c8e09394989dbde229d8e3f8103", - "id": "16351320834453011577", - "fee": 10000000000, - "senderId": "250438937633388106" - } -} -``` - -### 2.5 Peers - -#### 2.5.1 Get all Peers' Information in the Whole Network -Interface Address: /api/peers -Request Method:get -Supported Format: urlencoded -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|state |integer |N |peer's status: 0:,1:,2:,3: | -|os|string|N|Linux kernel version| -|version|string|N|Asch system version| -|limit |integer |N |maximum return records, minimum:0, maximum: 100| -|orderBy|string|N|| -|offset|integer |N |offset, minimum 0 | -|port|integer|N|port number,1~65535| - - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|peers|Array |a JSON array of peers' information | -|totalCount|integer|the number of currently running peers| - - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/peers?limit=1' -``` - -JSON Response Example: -```js -{ - "success": true, - "peers": [{ - "ip": "45.32.19.241", - "port": 4096, - "state": 2, - "os": "linux3.13.0-87-generic", - "version": "1.0.0" - }], - "totalCount": ["54"] -} -``` - -#### 2.5.2 Get the Version of Peer -Interface Address: /api/peers/version -Request Method:get -Supported Format: none -Request Parameter Description: none - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|version|string |version number | -|build |timestamp |built time | -|net |string |if the peer is mainnet or testnet | - - -Request Example: -```bash -curl -k -X GET http://45.32.248.33:4096/api/peers/version -``` - -JSON Response Example: -```js -{ - "success": true, - "version": "1.0.0", - "build": "12:11:11 16/08/2016", - "net": "testnet" -} -``` - -#### 2.5.3 Get the Peer Information of a Given IP Address -Interface Address: /api/peers/get -Request Method:get -Supported Format: urlencoded -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|ip |string |Y |peer's IP | -|port|integer|Y|peer's port,1~65535| - - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|peer|json | peer's information | - - -Request Example: -```bash -curl -k -X GET 'http://45.32.248.33:4096/api/peers/get?ip=45.32.248.33&port=4096' -``` - -JSON Response Example: -```js -{ - "success": true, - "peer": { - } -} -``` - -### 2.6 Sync and Loader -#### 2.6.1 Get the local blockchain loadig status -Interface Address: /api/loader/status -Request Method: get -Supported Format: none -Request Parameter Description: none - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|loaded |bool | | -|blocksCount|integer|| - -Request Example: -```bash -curl -k http://45.32.248.33:4096/api/loader/status -X GET -``` - -JSON Response Example: -```js -{ - "success": true, - "loaded": true, - "blocksCount": 0 -} -``` - -#### 2.6.2 Get the block syncing status -Interface Address: /api/loader/status/sync -Request Method: get -Supported Format: none -Request Parameter Description: none - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|height |int |block height | - -Request Example: -```bash -curl -k http://45.32.248.33:4096/api/loader/status/sync -X GET -``` - -JSON Response Example: -```js -{ - "success": true, - "syncing": false, // show whether in synchronising. if yes, it will be "true". if there is no data to synchronise, it will be "false" - "blocks": 0, - "height": 111987 -} -``` - -### 2.7 Second Password -#### 2.7.1 Set the Second Password -Interface Address: /api/signatures -Request Method: put -Supported Format: json -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|secret |string |Y |Asch account's password | -|publicKey|string |N|public key | -|secondSecret|string|Y|Asch account's second password,minimum length:1,maximum length:100| -|multisigAccountPublicKey|string|N|the public key of multi signatures account| - - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|transaction|json |the detail information of setting transaction | - - -Request Example: -```bash -curl -k -H "Content-Type: application/json" -X PUT -d '{"secret":"unaware label emerge fancy concert long fiction report affair appear decide twenty","secondSecret":"fault still attack alley expand music basket purse later educate follow ride"}' 'http://45.32.248.33:4096/api/signatures' -``` - -JSON Response Example: -```js -{ - "success": true, - "transaction": { - "type": 1, //the transaction type of setting second password is 1 - "amount": 0, - "senderPublicKey": "3b64f1833e6328043e1f2fee31e638bdaa6dfff5c7eb9c8577a5cefcf11261f2", - "requesterPublicKey": null, - "timestamp": 4872315, - "asset": { - "signature": { - "publicKey": "bd1e78c5a10fbf1eca36b28bbb8ea85f320967659cbf1f7ff1603d0a368867b9" - } - }, - "recipientId": null, - "signature": "e76d9b25ec0fdaa88b19d59c5a222b7efdc04f738ee05896f55f4e6959229d9b1600ca25aa92fbea176668f3be7c12c506f2091e2b38c52ef0ece7a5d35e240a", - "id": "1614688380530105232", - "fee": 500000000, //the transaction fee of setting second password is 5 XAS - "senderId": "250438937633388106" - } -} -``` - -#### 2.7.2 Get the Transaction Fee of Setting Second Password -Interface Address: /api/signatures/fee -Request Method:get -Supported Format: none -Request Parameter Description: none - - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|fee|integer |transaction fee | - - -Request Example: -```bash -curl -k http://45.32.248.33:4096/api/signatures/fee -X GET -``` - -JSON Response Example: -```js -{ - "success": true, - "fee": 500000000 //5 XAS -} -``` - -### 2.8 Multiple Signatures -#### 2.8.1 Set Normal Account to Multi-signatures Account -Interface Address: /api/multisignatures -Request Method: put -Supported Format: json -Comment: the return value is transaction ID only. To successfully set to multi-signature account still needs other's signatures. Every transaction after registered as multi-signatures account will be asked for multiple signatures. The minimum necessary signatures is defined by "min" (include sender itself) -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|secret |string |Y |Asch account's password | -|publicKey|string |N|public key | -|secondSecret|string|N|Asch account's second password, minimum length:1 maximum length: 100| -|min|integer|Y|the minimum signatures that is required to each transaction for multi-signatures account. (When the transaction is to register multi-signature account, this parameter will not work since everyone needs to sign.) Minimum:2, maximum:16. This number must not be larger than keysgroup.length+1. | -|lifetime|integer|Y|the maximum pending time of multi-signature transaction. Minimum:1, maximum:24. NOTE: this parameter is not available currently.| -|keysgroup|array|Y|an array containing other signaturers' public key. There are plus/minus (+/-) in front of each public key, means add or delete multi-signature account respectively. Minimum length:1, maximum length:10.| - - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|transactionId|string |the multi-signature transaction ID | - - -Request Example: -```bash -curl -k -H "Content-Type: application/json" -X PUT -d '{"secret":"vanish deliver message evil canyon night extend unusual tell prosper issue antenna","min":2,"lifetime":1,"keysgroup":["+eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97","+d5d7aa157f866c47a2a1e09e2746286ed089fd90976b54fbfa930e87d11609cb"]}' 'http://45.32.248.33:4096/api/multisignatures' //公钥为2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd -``` - -JSON Response Example: -```js -{ - "success": true, - "transactionId": "17620378998277022323" //only transaction ID is returned. To successfully set to multi-signature account needs other accounts' signatures. -} -``` - -#### 2.8.2 Get the Detail Information of Pending Multi-signature Transaction -Interface Address: /api/multisignatures/pending -Request Method:get -Supported Format: urlencoded -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|publicKey|string |Y|public key | - - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|transactions|Array |a JSON object list containing those pending transactions | - - -Request Example: -```bash -curl -k -X GET http://45.32.248.33:4096/api/multisignatures/pending?publicKey=2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd -``` - -JSON Response Example: -```js -{ - "success": true, - "transactions": [{ //the detail information of the setting multi-signature account transaction (see 2.8.1, transactionId: 17620378998277022323) - "min": 2, - "lifetime": 1, - "signed": true, - "transaction": { - "type": 4, //4 means registering multi-signature account - "amount": 0, - "senderPublicKey": "2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd", - "requesterPublicKey": null, - "timestamp": 4879978, - "asset": { - "multisignature": { - "min": 2, - "keysgroup": ["+eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97", - "+d5d7aa157f866c47a2a1e09e2746286ed089fd90976b54fbfa930e87d11609cb"], - "lifetime": 1 - } - }, - "recipientId": null, - "signature": "a42feaccd9f2a4940fc0be1a1580e786b360f189db3154328f307988e75484293eae391f2f9eee489913cc6d15984eb1f5f5a0aa1bf78ea745d5c725f161af08", - "id": "17620378998277022323", - "fee": 1500000000, - "senderId": "3855903394839129841" - } - }] -} - -``` - -#### 2.8.3 Sign the Multi-signature Transaction (by non-initiator) -Interface Address: /api/multisignatures/sign -Request Method:post -Supported Format: json -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|secret |string |Y |Asch account's password | -|secondSecret|string|N|Asch account second password. Minimum length:1, maximum length:100| -|publicKey|string |N|public key | -|transactionId|string|Y|transaction ID| - - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|transactionId|string |multi-signature transaction ID | - - -Request Example: -```bash -curl -k -H "Content-Type: application/json" -X POST -d '{"secret":"lemon carpet desk accuse clerk future oyster essay seminar force live dog","transactionId":"17620378998277022323"}' 'http://45.32.248.33:4096/api/multisignatures/sign' //signed by a user whose public key is eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97 -``` - -JSON Response Example: -```js -{ - "success": true, - "transactionId": "17620378998277022323" -} -// Now get the pending transaction again -curl -k -X GET http://45.32.248.33:4096/api/multisignatures/pending?publicKey=2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd -{ - "success": true, - "transactions": [{ - "min": 2, - "lifetime": 1, - "signed": true, - "transaction": { - "type": 4, - "amount": 0, - "senderPublicKey": "2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd", - "requesterPublicKey": null, - "timestamp": 4879978, - "asset": { - "multisignature": { - "min": 2, - "keysgroup": ["+eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97", - "+d5d7aa157f866c47a2a1e09e2746286ed089fd90976b54fbfa930e87d11609cb"], - "lifetime": 1 - } - }, - "recipientId": null, - "signature": "a42feaccd9f2a4940fc0be1a1580e786b360f189db3154328f307988e75484293eae391f2f9eee489913cc6d15984eb1f5f5a0aa1bf78ea745d5c725f161af08", - "id": "17620378998277022323", - "fee": 1500000000, - "senderId": "3855903394839129841", - "signatures": ["b38a161264db2a23e353d3fbc4983562f6343d5ee693144543ca54e2bc67c0f73d1c761b7bfa38b2bb101ac2ab0797b674b1a9964ccd400aaa310746c3494d03"] //new multi-signature generated - } - }] -} - -// a user whose public key is "d5d7aa157f866c47a2a1e09e2746286ed089fd90976b54fbfa930e87d11609cb" sign this registering transaction -curl -k -H "Content-Type: application/json" -X POST -d '{"secret":"chalk among elbow piece badge try van round quality position simple teach","transactionId":"17620378998277022323"}' 'http://45.32.248.33:4096/api/multisignatures/sign' -{"success":true,"transactionId":"17620378998277022323"} -// trying to get pending transaction again, but this time there isn't any of it. -curl -k -X GET http://45.32.248.33:4096/api/multisignatures/pending?publicKey=2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd -{"success":true,"transactions":[]} -// Check the detail of this transaction. (at this time, this transaction has been broadcasted to the whole network and been written to the blockchain) Now the account has already registered as a multi-signature account. -curl -k -X GET http://45.32.248.33:4096/api/transactions/get?id=17620378998277022323 -{ - "success": true, - "transaction": { - "id": "17620378998277022323", //the registering transaction ID - "height": "157013", - "blockId": "4680888982781013372", - "type": 4, - "timestamp": 4879978, - "senderPublicKey": "2cef5711e61bb5361c544077aa08aebc4d962a1d656571901c48d716382ad4fd", - "senderId": "3855903394839129841", - "recipientId": "", - "amount": 0, - "fee": 1500000000, - "signature": "a42feaccd9f2a4940fc0be1a1580e786b360f189db3154328f307988e75484293eae391f2f9eee489913cc6d15984eb1f5f5a0aa1bf78ea745d5c725f161af08", - "signSignature": "", - "signatures": null, - "confirmations": "26", - "asset": { - - } - } -} - -``` - -#### 2.8.4 Get Detail Information of the Multi-signature Account -Interface Address: /api/multisignatures/accounts -Request Method: get -Supported Format: urlencoded -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|publicKey |string |Y |One of the participants‘ public key | - - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |true: response data return successfully | -|accounts|Array |the detail of this multi-signature account | - - -Request Example: -```bash -curl -k -X GET http://45.32.248.33:4096/api/multisignatures/accounts?publicKey=eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97 -``` - -JSON Response Example: -```js -{ - "success": true, - "accounts": [{ - "address": "3855903394839129841", //the address of this multi-signature account - "balance": 18500000000, //the balance of this multi-signature account - "multisignatures": ["eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97", - "d5d7aa157f866c47a2a1e09e2746286ed089fd90976b54fbfa930e87d11609cb"], //the public key of this multi-signature account - "multimin": 2, //minimum required signature - "multilifetime": 1, - "multisigaccounts": [{ //the detail of signer's account - "address": "13542769708474548631", - "publicKey": "eb48b9ab7c9a34a9b7cdf860265d65b31af774355cabf1b3a387d14a1925dc97", - "balance": 0 - }, - { - "address": "4100816257782486230", - "publicKey": "d5d7aa157f866c47a2a1e09e2746286ed089fd90976b54fbfa930e87d11609cb", - "balance": 0 - }] - }] -} -``` - -### 2.9 Peer to Peer Transportation[secure API] -#### 2.9.1 Overview -To request a peer related API, it is required to set a header like this: - - - key=magic, and value=594fe0f3 - - key=version, and value='' - -#### 2.9.2 Transaction -All the writing operations in Asch system are finished by starting a transaction. -The transaction data is generated through a JS library named "asch-js", and then broadcasted by a POST API. -The POST API specification is as follows: - -payload: transaction data generated by asch-js -API Address: /peer/transactions -Request Method: POST -Supported Format: JSON - -##### 2.9.2.1 Set the Second Payment Password -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|transaction|json|Y|transaction data generated by [asch-js.signature.createSignature]| - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |whether the transaction is successful | - - -Request Example: -```js -var asch = require('asch-js'); -var transaction = asch.signature.createSignature('measure bottom stock hospital calm hurdle come banner high edge foster cram','erjimimashezhi001') -console.log(JSON.stringify(transaction)) -{"type":1,"amount":0,"fee":500000000,"recipientId":null,"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","timestamp":5328943,"asset":{"signature":{"publicKey":"27116db89cb5a8c02fb559712e0eabdc298480d3c79a089b803e35bc5ef7bb7b"}},"signature":"71ef98b1600f22f3b18cfcf17599db3c40727c230db817f610e86454b62df4fb830211737ff0c03c6a61ecfd4a9fcb68a30b2874060bb33b87766acf800e820a","id":"15605591820551652547"} - -// submit above data of setting second password to Asch server by POST method -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":1,"amount":0,"fee":500000000,"recipientId":null,"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","timestamp":5328943,"asset":{"signature":{"publicKey":"27116db89cb5a8c02fb559712e0eabdc298480d3c79a089b803e35bc5ef7bb7b"}},"signature":"71ef98b1600f22f3b18cfcf17599db3c40727c230db817f610e86454b62df4fb830211737ff0c03c6a61ecfd4a9fcb68a30b2874060bb33b87766acf800e820a","id":"15605591820551652547"}}' http://45.32.248.33:4096/peer/transactions -``` - -JSON Response Example: -```js -{ - "success":true //setting is successful -} -``` - -##### 2.9.2.2 Transfer Money -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|transaction|json|Y|transaction data generated by [asch-js.transaction.createTransaction]| - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |whether the transaction is successful | - - -Request Example: -```js -var asch = require('asch-js'); -var targetAddress = "16358246403719868041"; -var amount = 100*100000000; //100 XAS -var password = 'measure bottom stock hospital calm hurdle come banner high edge foster cram'; -var secondPassword = 'erjimimashezhi001'; - -// in above code, password is recorded when user logs in. meanwhile the second password needs to be input every time by user. -// To input or not depends on whether user has second password, which can be identified by "user.secondPublicKey" function. - -var transaction = asch.transaction.createTransaction(targetAddress, amount, password, secondPassword || undefined); -JSON.stringify(transaction) -'{"type":0,"amount":10000000000,"fee":10000000,"recipientId":"16358246403719868041","timestamp":5333378,"asset":{},"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","signature":"2d47810b7d9964c5c4d330a53d1382769e5092b3a53639853f702cf4a382aafcff8ef8663c0f6856a23f41c249944f0c3cfac0744847268853a62af5dd8fc90a","signSignature":"dfa9b807fff362d581170b41c56a2b8bd723c48d1f100f2856d794408723e8973016d75aeff4705e6837dcdb745aafb41aa10a9f1ff8a77d128ba3d712e90907","id":"16348623380114619131"}' - -// submit above data of transfer to Asch server by POST method -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":0,"amount":10000000000,"fee":10000000,"recipientId":"16358246403719868041","timestamp":5333378,"asset":{},"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","signature":"2d47810b7d9964c5c4d330a53d1382769e5092b3a53639853f702cf4a382aafcff8ef8663c0f6856a23f41c249944f0c3cfac0744847268853a62af5dd8fc90a","signSignature":"dfa9b807fff362d581170b41c56a2b8bd723c48d1f100f2856d794408723e8973016d75aeff4705e6837dcdb745aafb41aa10a9f1ff8a77d128ba3d712e90907","id":"16348623380114619131"}}' http://45.32.248.33:4096/peer/transactions -``` - -JSON Response Example: -```js -{ - "success":true //transfer success -} -``` - -##### 2.9.2.3 Register Delegates -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|transaction|json|Y|transaction data generated by [asch-js.delegate.createDelegate]| - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |whether transaction is success | - - -Request Example: -```js -var asch = require('asch-js'); -var password = 'measure bottom stock hospital calm hurdle come banner high edge foster cram'; -var secondPassword = 'erjimimashezhi001'; -var userName = 'zhenxi_test'; - -var transaction = asch.delegate.createDelegate(password, userName, secondPassword || undefined); -JSON.stringify(transaction) -'{"type":2,"amount":0,"fee":10000000000,"recipientId":null,"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","timestamp":5334485,"asset":{"delegate":{"username":"zhenxi_test","publicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f"}},"signature":"a12ce415d2d21ab46e4c1b918b8717b1d351dd99abd6f2f94d9a1a7e1f32b697f843a05b1851cb857ea45a2476dce592f5ddd612c00cd44488b8b610c57d7f0a","signSignature":"35adc9f1f37d14458e8588f9b4332eedf1151c02480159f64a287a4b0cbb59bfe82040dfec96a4d9560bae99b8eaa1799a7023395db5ddc640d95447992d6e00","id":"12310465407307249905"}' - -// submit above data of registering delegate to Asch server by POST method -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":2,"amount":0,"fee":10000000000,"recipientId":null,"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","timestamp":5334485,"asset":{"delegate":{"username":"zhenxi_test","publicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f"}},"signature":"a12ce415d2d21ab46e4c1b918b8717b1d351dd99abd6f2f94d9a1a7e1f32b697f843a05b1851cb857ea45a2476dce592f5ddd612c00cd44488b8b610c57d7f0a","signSignature":"35adc9f1f37d14458e8588f9b4332eedf1151c02480159f64a287a4b0cbb59bfe82040dfec96a4d9560bae99b8eaa1799a7023395db5ddc640d95447992d6e00","id":"12310465407307249905"}}' http://45.32.248.33:4096/peer/transactions -``` - -JSON Response Example: -```js -{ - "success":true //register successfully -} -``` - -##### 2.9.2.4 Vote and Cancel the vote - -Request Parameter Description: - -|Name |Type |Required |Description | -|------ |----- |--- |---- | -|transaction|json|Y|transaction data generated by [asch-js.vote.createVote]| - -Response Parameter Description: - -|Name |Type |Description | -|------ |----- |---- | -|success|bool |whether the transaction is successful | - - -Request Example: -```js -var asch = require('asch-js'); -var password = 'measure bottom stock hospital calm hurdle come banner high edge foster cram'; -var secondPassword = 'erjimimashezhi001'; -// the voting content is a list in which each item consists of a symbol (+ or -) and the delegate's public key. The "+" means vote, and "-" means cancel the vote. -var voteContent = [ - '-ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7', - '+c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2' -]; - -var transaction = asch.vote.createVote(password, voteContent, secondPassword || undefined); -JSON.stringify(transaction) -{"type":3,"amount":0,"fee":10000000,"recipientId":null,"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","timestamp":5334923,"asset":{"vote":{"votes":["-ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7","+c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2"]}},"signature":"6036c2066a231c452a1c83aafd3bb9db3842ee05d5f17813f8264a4294cdec761faa89edf4a95f9b2e2451285807ab18aa9f989ad9a3165b95643179b8e4580f","signSignature":"a216ca739112e6f65986604b9467ccc8058138a7077faf134d6c4d673306cd1c514cc95bd54a036f7c602a56c4b4f2e4e59f6aa7c376cb1429e89054042e050b","id":"17558357483072606427"} - -// submit above data of vote/cancel vote to Asch server by POST method -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":3,"amount":0,"fee":10000000,"recipientId":null,"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","timestamp":5334923,"asset":{"vote":{"votes":["-ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7","+c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2"]}},"signature":"6036c2066a231c452a1c83aafd3bb9db3842ee05d5f17813f8264a4294cdec761faa89edf4a95f9b2e2451285807ab18aa9f989ad9a3165b95643179b8e4580f","signSignature":"a216ca739112e6f65986604b9467ccc8058138a7077faf134d6c4d673306cd1c514cc95bd54a036f7c602a56c4b4f2e4e59f6aa7c376cb1429e89054042e050b","id":"17558357483072606427"}}' http://45.32.248.33:4096/peer/transactions -``` - -JSON Response Example: -```js -{ - "success":true //transaction of vote/cancel the vote is success -} -``` - - -## Appendix 1: Install 'asch-js' library -All the writing operations in Asch system are finished by starting a transaction. -The transaction data is generated through a JS library named "asch-js", and then broadcasted by a POST API. - -**Install the library** -`npm install asch-js` - \ No newline at end of file diff --git a/docs/asch_install.md b/docs/asch_install.md deleted file mode 100644 index 642d45a..0000000 --- a/docs/asch_install.md +++ /dev/null @@ -1,207 +0,0 @@ -# Asch节点安装文档 - -## 1 系统要求 - -- 必须是linux系统 -- 必须有公网ip -- 建议使用ubuntu 16.04 64位操作系统 -- 建议CPU 2C以上 -- 建议内存2G以上 -- 建议带宽2Mb以上 -- 建议硬盘空间10GB以上 - -## 2 安装 - -测试版(testnet)与正式版(mainnet)是同时存在但无法互通的两套系统
-除了安装包、默认配置文件(包括默认端口等)不一样外,安装流程是一样的
-只要端口不冲突,可以同时在一台机器安装,但是不推荐这样做,除非机器配置足够好,比如4核、4G内存、4M带宽... - -### 2.1 下载和解压缩 - -测试版testnet - -``` -wget https://www.asch.io/downloads/asch-linux-latest-testnet.tar.gz -tar zxvf asch-linux-latest-testnet.tar.gz -``` - -正式版mainnet - -``` -wget https://www.asch.io/downloads/asch-linux-latest-mainnet.tar.gz -tar zxvf asch-linux-latest-mainnet.tar.gz -``` - -一般情况下,testnet的版本号大于等于mainnet的版本号 - -### 2.2 初始化 - -这一步会自动帮您做以下几件事情 - -1. 安装sqlite3等依赖软件 -2. 安装和配置ntp服务,保证您的时间与其他节点同步 - -这一步只需要运行一次即可,重复运行也无妨 - -``` -# 进入你的安装目录 -# ubuntu执行下面的命令 -chmod u+x init/*.sh && ./aschd configure -# 其他linux系统 -请自行利用apt-get/yum/zypper等包管理器工具安装sqlite3/ntp2个依赖包 -``` - -## 3 运行 - -``` -# 进入你的安装目录 - -# 启动 -./aschd start - -# 停止 -./aschd stop - -# 查看运行状态 -./aschd status - -# 重启 -./aschd restart - -# 升级 -./aschd upgrade - -# 重新同步区块 -./aschd rebuild - -# 查看版本 -./aschd version - -# 开启区块生产 -./aschd enable "your sercret" - -# 查看log -tail -f logs/debug.log -``` - -## 4 受托人配置 - -### 4.1 受托人密码 - -使用文本编辑工具打开config.json, 找到secret字段,将你的受托人密钥填进去即可,该字段为json字符串数组,一台机器可以配置多个,但不能重复 - -![forging secret](./assets/forging-secret.png) - -**注意** 不管是一台机器还是多台机器,不要配置重复的受托人密钥 - -### 4.2 公网IP - -默认情况下,系统会自动检测公网ip,但在某些云主机中,公网ip无法检测到,这时需要手动在config.json修改或添加如下字段 - -``` -"publicIp": "此处填写你的公网ip", -``` - -配置完之后需要重启程序 - -``` -./aschd restart -``` - -## 5 升级 - -``` -./aschd upgrade -./aschd start -``` - -## 6 错误诊断 - -### 6.1 在线钱包无法访问 - -【情况一】 - -查看是否改了config.json里的port字段, testnet的端口默认为4096,mainnet的端口默认为8192
-官方的种子节点将端口改成了80 -检查防火墙配置,需要打开Asch的端口入站和出站。 - -【情况二】 - -查看服务是否启动,可以使用如下命令 - -``` -./aschd status - -# 如果没有启动则显示 -Asch server is not running - -# 如果出现这种情况,重启即可 -./aschd restart -``` - -### 6.2 无法生产区块 - -【情况一】 - -查看受托人排名是否进入前101 - -【情况二】 - -使用下面的命令搜索错误日志 - -``` -grep Failed logs/debug.log -``` - -如果出现了如下字样 - -``` -Failed to get public ip, block forging MAY not work! -``` - -说明公网ip没有自动获取到,需要你手动配置,具体可以参考[4.2 公网IP]一节 - -【情况三】 - -使用下面的命令搜索错误日志 - -``` -grep error logs/debug.log -``` - -如果出现了如下字样 - -``` -Failed to load delegates: Account xxxxxxxxx not found -``` - -说明你配置的账户密钥还没有注册成为受托人,或者注册成为受托人之前就启动了服务,这时重启服务即可
-**注意** 如果你的节点正在同步区块,不要立即重启,等同步完成了再重启 - -``` -./aschd restart -``` - -正常情况下应该会出现如下log - -``` -grep Forging logs/debug.log - -Forging enabled on account: xxxxxxxxxxxxxx -``` - -### 6.3 无法同步区块(卡块) - -(可以通过对比自己钱包的区块高度与官方节点的最新区块高度来确认这一现象)
- -优先使用restart命令 - -``` -./aschd restart -``` - -如果无法解决,使用rebuild命令 - -``` -./aschd rebuild -``` \ No newline at end of file diff --git a/docs/asch_install_de.md b/docs/asch_install_de.md deleted file mode 100644 index 33a251e..0000000 --- a/docs/asch_install_de.md +++ /dev/null @@ -1,172 +0,0 @@ -# Asch Knoten Installation Anleitung - -## 1. System Anforderung -- Linux-System erforderlich -- Öffentliche IP-Adresse erforderlich -- Ubuntu 16.04 64bit OS empfohlen -- Mehr als 2Gb RAM wird empfohlen -- Mehr als 2Mb Bandbreite wird empfohlen -- Mehr als 10GB Festplattespeicher wird empfohlen - -## 2. Installation - -Es gibt zwei unterschiedliche Systeme: Das Testsystem (testnet) und Hauptsystem (mainnet). Beide existieren nebeneinander, können aber nicht miteinander kommunizieren. - -Die Schritte zur Installation sind für diese beiden System die Gleichen. Bis auf das Installationspaket und die Datei-Konfiguration (inklusive der Port Einstellungen). - -So lange es keinen Konflikt mit den Ports gibt, ist es möglich die beiden Versionen nebeneinander auf dem Computer zu installieren. Dies ist jedoch nicht empfohlen, da alle Ressourcen benötigt werden. Am besten eignet sich ein Server mit einer 4 Kerne CPU, 4GB RAM und mindestens 4MB Netzwerkanbindung. - - -### 2.1 Downloaden und Entpacken - -test version (testnet) - -``` -wget https://www.asch.so/downloads/asch-linux-latest-testnet.tar.gz -tar zxvf asch-linux-latest-testnet.tar.gz -``` - -official version (mainnet) -``` -wget https://www.asch.so/downloads/asch-linux-latest-mainnet.tar.gz -tar zxvf asch-linux-latest-mainnet.tar.gz -``` - -Üblicherweise ist die Versionsnumber der Testchain höher als die der Mainchain. - -### 2.2 Initialisierung -In diesem Schritt werden folgenden Dinge automatisch installiert: -- Installtion von Module wie **sqlite3** -- Installation und Konfiguration des NTP-Service, welcher die Systemzeit mit der der anderen Knoten synchronisiert - -Dieser Schritt muss nicht ausgeführt werden, es passiert aber nichts Schlimmes, wenn er öfters ausgeführt wird. - - # dies soll im Installations-Verzeichnis ausgeführt werden - ./aschd configure - ... - -## 3. Starten -``` -# Folgende Kommandos werden im Installations-Verzeichnis ausgeführt - -# das Service starten -./aschd start - -# das Service stoppen -./aschd stop - -# zeige den aktuellen Status -./aschd status - -# das Service neustarten -./aschd restart - -# ein Asch-Upgrade durchführen -./aschd upgrade - -# die blockchain resynchronisieren -./aschd rebuild - -# die Asch-Version anzeigen lassen -./aschd version - -# mit der Blöcke-Produzieren starten -./aschd enable "your sercret" - -# die Logs anzeigen -tail -f logs/debug.log -``` - -## 4. Delegat Konfiguration -### 4.1 Delegat Passwort - -Öffne mit deinem Lieblingseditor folgende Datei `config.json` und navigiere zum `[secret]` Feld. Fülle dieses Feld mit dem Passwort des Delegats. Dieses Feld ist eine JSON-String-Array welches verwendet werden kann um mehrere Passwörter zu setzen. Sei vorsichtig kein Passwort zu wiederholen. - -![forging secret](./assets/forging-secret.png) - -**HINWEIS:** Konfiguriere NIEMALS das selbe Passwort. Egal ob auf einem Rechner oder auf unterschiedlichen. - - -### 4.2 Öffentliche IP-Adresse -Von Haus aus erkennt das System automatisch die zugewiesene öffentliche IP-Adresse. Aber auf manchen Knoten in der Cloud kann die öffentliche IP-Adresse nicht identifiziert werden. Unter diesen Umständen muss folgendes Feld an die Datei `config.json` angehängt werden. - - -``` -"publicIp": "Hier steht die öffentliche IP-Adresse", -``` -Vergiss nicht das System nach der Konfiguration mit folgendem Befehl neu zu starten. -``` -./aschd restart -``` - -## 5. System Upgrade -``` -./aschd upgrade -./aschd start -``` -## 6. Fehlerbehebung -### 6.1 Ich kann nicht auf meine Online-Wallet zugreifen -#### Lösung 1 -Überprüfe das `[port]` Feld in der `config.json` Datei. Die default Portnummer für das **testnet** ist `4096` und für das **mainnet** `8192`. -Die offiziellen Seed-Nodes haben die Portnummer auf 80 geändert. -Überprüfe die Firewall-Einstellungen und öffne den Asch-Port für eingehenden und ausgehenden Verkehr. - -#### Lösung 2 -Überprüfe ob mit folgendem Kommando ob der Service gestartet ist: -``` -./aschd status - -# falls der Service nicht läuft kommt folgende Meldung: -Asch server is not running - -# danach starte das Service neu -./aschd restart -``` - -### 6.2 Es werden keine Blöcke produziert -#### Lösung 1 -Stelle sicher, dass dein Delegat-Rank unter den TOP 101 ist - -#### Lösung 2 -Überprüfe den Fehler-Log mit folgendem Kommando: -``` -grep Failed logs/debug.log -``` -Falls es eine ähnliche Fehlernachricht gibt wie: -``` -Failed to get public ip, block forging MAY not work! -``` -bedeutet dies, dass das system nicht die öffentliche IP-Adresse hat. Dies muss manuell konfiguriert werden. Siehe **[4.2 Public IP]** - -#### Lösung 3 -Überprüfe den Fehler-Log mit folgendem Kommando: -``` -grep error logs/debug.log -``` -Falls es eine ähnliche Fehlernachricht gibt wie: -``` -Failed to load delegates: Account xxxxxxxxx not found -``` -bedeutet dies, dass die Passphrase für dein Konto noch nicht als Delegat registriert wurde. Es kann auch sein, dass der Service gestartet wurde bevor er als Delegat registriert wurde. In diesem Fall hilft ein einfaches neustarten des Services. - -**HINWEIS:** Falls dein Knoten gerade die Blöcke synchronisiert ist es zu empfehlen das System erst nach der abgeschlossenen Sychronisation zu starten. -``` -./aschd restart -``` -Wenn das System erfolgreich neugestartet wurde, ist folgendes im Log zu lesen: -``` -grep Forging logs/debug.log - -Forging enabled on account: xxxxxxxxxxxxxx -``` -### 6.3 Meine Blöcke werden nicht sychronisiert (Blockhöhe wächst nicht) -*Dieses Problem kann verifiziert werden in dem man seine Blockhöhe mit der des offiziellen Knotens vergleicht - -Als allererstes, versuche das System neu zu starten -``` -./aschd restart -``` -Falls das Problem noch immer auftritt, versuche folgendes:` -``` -./aschd rebuild -``` diff --git a/docs/asch_install_en.md b/docs/asch_install_en.md deleted file mode 100644 index d7c1143..0000000 --- a/docs/asch_install_en.md +++ /dev/null @@ -1,170 +0,0 @@ -# Asch Node Installation Guide - -## 1. System requirements -- Linux system required -- Public IP address required -- Ubuntu 16.04 64bit OS recommended -- Above 2Gb RAM recommended -- Above 2Mb broadwidth recommended -- Above 10GB GB harddisk recommended - -## 2. Installation -There are two seperated system: test version (testnet) and main official version (mainnet). Both of them are co-existed but unable to communicate with each other. - -The installation procedures of these two system are the same except the installation package and configuration file (including default port setting). - -As long as there is no conflict of ports, you can install the test version and official version into the same compouter, but please note, the power of the machine is highly required, such as 4core CPU, 4Gb RAM above or at least 4Mb broadwidth... - -### 2.1 Download and unpack - -test version (testnet) - -``` -wget https://www.asch.io/downloads/asch-linux-latest-testnet.tar.gz -tar zxvf asch-linux-latest-testnet.tar.gz -``` - -official version (mainnet) -``` -wget https://www.asch.io/downloads/asch-linux-latest-mainnet.tar.gz -tar zxvf asch-linux-latest-mainnet.tar.gz -``` - -Usually, the version number of testnet will larger than that of mainnet. - -### 2.2 Initialize -In this step, something will be done for you automatically: -- Install some dependency modules like **sqlite3** -- Install and configure the ntp service by which your time can be synchronized with that of other nodes. - -There is no need to run this step once although there is no harm to execute it more than one time. - - # locate to your installation folder - # for ubuntu - chmod u+x init/*.sh && ./aschd configure - # for other linux - please install sqlite3/ntp using apt-get/yum/zypper or other package manager. - ... - -## 3. Run -``` -# Enter the installation folder - -# start the service -./aschd start - -# stop the service -./aschd stop - -# check the running status -./aschd status - -# restart the service -./aschd restart - -# upgrade the system -./aschd upgrade - -# re-synchronize the blockchain -./aschd rebuild - -# check the system version -./aschd version - -# start producing block -./aschd enable "your sercret" - -# check the log -tail -f logs/debug.log -``` - -## 4. Delegate configuration -### 4.1 Delegate's password - -Use your favorite editor to open `config.json` and locate the `[secret]` field. Fill this field with your delegate's password. This field is an array of JSON format string, which means you can set several passwords in one particular computer, but be careful not to duplicate them. - -![forging secret](./assets/forging-secret.png) - -**NOTICE:** DO NOT configure the same password, no matter in a single machine or in multiple machines. - -### 4.2 Public IP -By default, the system will automatically detect the public IP you assigned. But in some host built on cloud, the public IP may not be able to identified. Under such circumstance, the following field needs to be appended in `config.json`: -``` -"publicIp": "Here is your public IP", -``` -And don't forget restarting your system after configuration by: -``` -./aschd restart -``` - -## 5. Upgrade the system -``` -./aschd upgrade -./aschd start -``` -## 6. Troubleshooting -### 6.1 I cannot access my online wallet -#### Solution 1 -Check the `[port]` field in `config.json`, the default port numbers of **testnet** and **mainnet** are `4096` and `8192`, respectively. -The official seed nodes changed the port to 80. -Check the firewall configuration, and you need to open the Asch port inbound and outbound. - -#### Solution 2 -Check whether service is started by typing commands as follows: -``` -./aschd status - -# if service is not started, then following message will be shown -Asch server is not running - -# then restart the service -./aschd restart -``` - -### 6.2 Unable to generate the block -#### Solution 1 -Make sure the rank of delegate is in top 101 - -#### Solution 2 -Check the error log with following commands: -``` -grep Failed logs/debug.log -``` -If there is an error message like this: -``` -Failed to get public ip, block forging MAY not work! -``` -it means system cannot get the public IP, and it will need you to configure it manually, see **[4.2 Public IP]** - -#### Solution 3 -Check the error log with following commands: -``` -grep error logs/debug.log -``` -If there is an error message like this: -``` -Failed to load delegates: Account xxxxxxxxx not found -``` -It means that the passphrase of your account has not been registed as delegates yet, or you started the service before it registered as a delegate. Simply restarting the servie will solve the problem. - -**NOTICE:** If your node is synchronizing the blocks, restart the system after the synchronization is finished. -``` -./aschd restart -``` -If the system has been restarted successfully, the following log will be found: -``` -grep Forging logs/debug.log - -Forging enabled on account: xxxxxxxxxxxxxx -``` -### 6.3 Unable to synchronize the block (blockchain growth suspend) -*This issue can be confirmed by comparing the block height of your wallet and official node* - -First, try `restart` the system: -``` -./aschd restart -``` -If problem is still unsolved, try `rebuild` -``` -./aschd rebuild -``` diff --git a/docs/asch_js_api.md b/docs/asch_js_api.md deleted file mode 100644 index 8c1df90..0000000 --- a/docs/asch_js_api.md +++ /dev/null @@ -1,994 +0,0 @@ -Table of Contents -================= - - * [Asch-JS API 使用说明](#asch-js-api-使用说明) - * [1 Asch-js说明](#1-asch-js说明) - * [1.1 asch-js安装](#11-asch-js安装) - * [1.2 说明](#12-说明) - * [2 账户](#2-账户) - * [2.1 根据密码获取密钥对](#21-根据密码获取密钥对) - * [2.1 根据公钥获取地址](#21-根据公钥获取地址) - * [2.3 设置二级密码,type=1](#23-设置二级密码type1) - * [2.4 账户锁仓,type=100](#24-账户锁仓type100) - * [3 普通交易transactions](#3-普通交易transactions) - * [3.1 在主链转账XAS,type=0](#31-在主链转账xastype0) - * [3.2 根据交易内容获取交易id](#32-根据交易内容获取交易id) - * [4 资产相关uia](#4-资产相关uia) - * [4.1 资产发行商注册,type=9](#41-资产发行商注册type9) - * [4.2 资产注册,type=10](#42-资产注册type10) - * [4.3 资产设置访问控制列表(acl)模式,type=11](#43-资产设置访问控制列表acl模式type11) - * [4.4 更新访问控制列表(acl),type=12](#44-更新访问控制列表acltype12) - * [4.5 资产发行,type=13](#45-资产发行type13) - * [4.6 资产转账,type=14](#46-资产转账type14) - * [4.7 资产注销,type=11](#47-资产注销type11) - * [5 受托人delegate](#5-受托人delegate) - * [5.1 注册受托人,type=2](#51-注册受托人type2) - * [5.2 给受托人增加/取消投票,type=3](#52-给受托人增加取消投票type3) - * [6 dapp相关](#6-dapp相关) - * [6.1 dapp注册,type=5](#61-dapp注册type5) - * [6.2 dapp充值,type=6](#62-dapp充值type6) - * [6.3 dapp内部合约调用](#63-dapp内部合约调用) - * [6.3.1 dapp提现,合约type=2](#631-dapp提现合约type2) - * [6.3.2 dapp内部转账,合约type=3](#632-dapp内部转账合约type3) - * [6.3.4 dapp内设置昵称,合约type=3](#634-dapp内设置昵称合约type3) - * [6.4 dapp提现](#64-dapp提现) - * [6.4.1 创建提现交易,type=7](#641-创建提现交易type7) - * [6.4.2 受托人对提现交易进行签名](#642-受托人对提现交易进行签名) - * [7 存储storage](#7-存储storage) - * [7.1 创建存储交易,type=8](#71-创建存储交易type8) - * [8 签名验证相关crypto](#8-签名验证相关crypto) - * [8.1 根据交易内容获取字节Buffer对象](#81-根据交易内容获取字节buffer对象) - * [8.2 根据交易内容获取Hash Buffer对象](#82-根据交易内容获取hash-buffer对象) - * [8.3 根据交易内容获取交易id](#83-根据交易内容获取交易id) - * [8.4 对交易Bytes Buffer进行签名](#84-对交易bytes-buffer进行签名) - * [8.5 验证交易签名是否和已存在的签名一致](#85-验证交易签名是否和已存在的签名一致) - * [9 其它](#9-其它) - * [9.1 全局参数变量options](#91-全局参数变量options) - * [9.1.1 设置变量k/v](#911-设置变量kv) - * [9.1.2 根据key获取value](#912-根据key获取value) - * [9.1.3 获取所有的k/v](#913-获取所有的kv) - * [9.2 时间相关slot.time](#92-时间相关slottime) - * [9.2.1 asch主网创世块生成时间](#921-asch主网创世块生成时间) - * [9.2.2 根据unix时间戳获获Asch时间戳](#922-根据unix时间戳获获asch时间戳) - * [9.2.3 根据Asch时间戳获取unix时间戳](#923-根据asch时间戳获取unix时间戳) - -Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc) - - -# Asch-JS API 使用说明 - - -## **1 Asch-js说明** - -### **1.1 asch-js安装** - -``` -npm install asch-js -var AschJS = require('asch-js'); -``` - -### **1.2 说明** -很多函数都需要传入secret、secondSecret这2个参数,分表代表密码和二级密码,下面章节不再赘述。 -自定如下全局变量,用于之后章节代码演示。 - -- `secret` 密码 -- `publicKey` 公钥 -- `secondSecret` 二级密码 - -``` -> var secret = 'minor borrow display rebel depart core buzz right distance avocado immense push' -> var publicKey = 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed'; -> var secondSecret = 'erjimima2017'; -``` - -生成的json交易信息都需要通过http api进行广播。 -- 主链交易通过 `POST /peer/transactions` -- dapp交易通过 `PUT /api/dapps/dappID/transactions/signed` - - -## **2 账户** - -### **2.1 根据密码获取密钥对** - -`crypto.getKeys(secret)` - -- `secret` 密码 - -``` -> AschJS.crypto.getKeys(secret) -{ publicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - privateKey: '7ae536fa343281d9e9ed383e8b5ef62e0fd0d0cbed79786cac241d484e312fdeebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed' } -``` - -### **2.1 根据公钥获取地址** - -`crypto.getAddress(publicKey)` - -- `publicKey` 公钥 - -``` -> AschJS.crypto.getAddress(publicKey); -'AFUH568CbGC2GPcE4gXHiZhxdYQYfziz2J' - -``` - -### **2.3 设置二级密码,type=1** - -`crypto.signature.createSignature(secret, secondSecret)` -`备注` 在主链的交易类型为1 - -- `secret` 密码 -- `secondSecret` 二级密码 - -``` -> AschJS.signature.createSignature(secret, secondSecret) -{ type: 1, - amount: 0, - fee: 500000000, - recipientId: null, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - timestamp: 40566038, - asset: { signature: { publicKey: '632a41caf7d3c8d3754f27a11004acaea6f5571eed28b42451b5560ee91e991c' } }, - signature: 'ee42f4dc17ace4f76f86fba93c7d86b61a69de46ac96e102e9f93668c8cdd9e6281821c63cb3e0c23099968cccdcfd0197aaab42afba4a98fa696c17b133be06', - id: '2237134c11b3cbaa9b7951f4afd47454ca04af2c7c6a030729ec63f75230e9ad' } - -``` - -### **2.4 账户锁仓,type=100** - -`transaction.createLock(height, secret, secondSecret)` -`备注` 在主链的交易类型为100 - -- `height` 锁仓高度 -- `secret` 密码 -- `secondSecret` 二级密码 - -``` -> AschJS.transaction.createLock(8130, secret, secondSecret) -{ type: 100, - amount: 0, - fee: 10000000, - recipientId: null, - args: [ '8130' ], - timestamp: 40566287, - asset: {}, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - signature: '06f6852d0e2e56ca441fa60b407aaa2197290ff096558c746c9c8bcdc971b8c4065ec08edd49c7292eca51849c16c5b8f0d33bb4ce972a932603dcf46a391e0e', - signSignature: '3b645b0f6a2c597c55595669a856489c0c4f3a132c798c615b8e0241f3169a367edea7228ebc8915d5fd7a0571cc08c971d07520b9908c80c9b2c2c76ada5e07', - id: 'c87d93af84939076a65a49c3b483897d262edc340b2d4184a4d2505b58711a91' } -``` - - -## **3 普通交易transactions** - -### **3.1 在主链转账XAS,type=0** - -`transaction.createTransaction(recipientId, amount, message, secret, secondSecret)` -`备注` 在主链的交易类型为0 - -- `recipientId` 接收者地址 -- `amount` 转账数量 -- `message` 转账附言 -- `secret` 密码 -- `secondSecret` 二级密码 - -``` -> var targetAddress = "16358246403719868041"; -undefined -> var amount = 100*100000000; //100 XAS -undefined -> var message = 'beizhu'; -undefined -> AschJS.transaction.createTransaction(targetAddress, amount, message, secret, secondSecret) -{ type: 0, - amount: 10000000000, - fee: 10000000, - recipientId: '16358246403719868041', - message: 'beizhu', - timestamp: 40566970, - asset: {}, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - signature: '9bef374be100fcfec59d245af59e5646ba5dcb79c6f1399ddd676a617542eeb45cc363822b84410e379f0caa501c25b66e59142353c04d23d1cb95cf64cef306', - signSignature: '513e3efdbb65f8e60e85ca98d8d065ec9bd3bfa6f45a1f48cfade9c94d410338ee64bd55938c168b10f0749335c050312785dbf08882ffd0e40a65fde8c2b10b', - id: '871554a8346d84cab2147324706d8ab5494fde928a7463a68d536ed6c0357897' } - -``` - - -### **3.2 根据交易内容获取交易id** - -`crypto.getId(transaction)` - -- `transaction` 签名后的交易内容 - -``` -> var targetAddress = "16358246403719868041"; -> var amount = 100*100000000; //100 XAS -> var message = 'beizhu'; -> transaction = AschJS.transaction.createTransaction(targetAddress, amount, message, secret, secondSecret) -{ type: 0, - amount: 10000000000, - fee: 10000000, - recipientId: '16358246403719868041', - message: 'beizhu', - timestamp: 40566970, - asset: {}, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - signature: '9bef374be100fcfec59d245af59e5646ba5dcb79c6f1399ddd676a617542eeb45cc363822b84410e379f0caa501c25b66e59142353c04d23d1cb95cf64cef306', - signSignature: '513e3efdbb65f8e60e85ca98d8d065ec9bd3bfa6f45a1f48cfade9c94d410338ee64bd55938c168b10f0749335c050312785dbf08882ffd0e40a65fde8c2b10b', - id: '871554a8346d84cab2147324706d8ab5494fde928a7463a68d536ed6c0357897' } - -> AschJS.crypto.getId(transaction) -'871554a8346d84cab2147324706d8ab5494fde928a7463a68d536ed6c0357897' // 返回结果,交易id - -``` - - -## **4 资产相关uia** - -### **4.1 资产发行商注册,type=9** - -`uia.createIssuer(name, desc, secret, secondSecret)` -`备注` 在主链的交易类型为9 - -- `name` 资产发行商名字 -- `desc` 资产发行商描述 - -``` -var name = 'IssuerName' -var desc = 'IssuerDesc' -AschJS.uia.createIssuer(name, desc, secret, secondSecret) -{ - "type": 9, - "amount": 0, - "fee": 10000000, - "recipientId": null, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "timestamp": 19395607, - "asset": { - "uiaIssuer": { - "name": "IssuerName", - "desc": "IssuerDesc" - } - }, - "signature": "c6ed2a4bafe2b8aa31f4aaceacc2a96cb028abbabb2ed062937498c58e24ca5467a340ddd63b67f809a680ff91b83e685c64991eb695494ddb2fdc57e5761607", - "signSignature": "8eceacbd47c2b8ed335145ced19d7a3a51f99bdd6631d16ed214180c6f80e29bd6d572f45e7c7d685584e55cb5c303cf340406553ece28c9c0a2fa7a777aac0b" -} -``` - - - -### **4.2 资产注册,type=10** - -`uia.createAsset(name, desc, maximum , precision, strategy, secret, secondSecret)` -`备注` 在主链的交易类型为10 - -- `name` 资产名称,格式为:发行商名.资产名,是资产的唯一标识 -- `desc` 资产描述 -- `maximum` 资产可发行的上限值 -- `precision` 精度,小数点的位数,这里上限是1000000,精度为3,代表资产IssuerName.CNY的最大发行量为1000.000 -- `strategy` 发行策略策略,如没隔1年发行10% - -``` -var name = 'IssuerName.CNY' -var desc = '资产描述' -var maximum = '1000000' -var precision = 3 -var strategy = '' - -AschJS.uia.createAsset(name, desc, maximum , precision, strategy, secret, secondSecret) -{ - "type": 10, - "amount": 0, - "fee": 10000000, - "recipientId": null, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "timestamp": 19397444, - "asset": { - "uiaAsset": { - "name": "IssuerName.CNY", - "desc": "资产描述", - "maximum": "1000000", - "precision": 3, - "strategy": "" - } - }, - "signature": "c755587d331dd2eb62ef91dce1511d83a3e603c7cdc7548a16052519c21ea89c78364e35e5d46da0e2103fa2fb7f037eec55a5deba18826fa13e4252422d750e", - "signSignature": "1b7ed4c21c477b8ff3d2acfdfd7ff85617093f4c21de70938c46b61c9704b037dbcf7f9e5f5dd1a5dc8f22cf473aaa459e6e5b15ced388b8a1da1e307987a509" -} -``` - - - -### **4.3 资产设置访问控制列表(acl)模式,type=11** - -`uia.createFlags(currency, flagType, flag, secret, secondSecret)` -`备注` 在主链的交易类型为11 - -- `currency` 资产名称 -- `flagType` 资产是否注销,1:流通,2:注销 -- `flag` 访问控制列表的类型,0:黑名单, 1:白名单,资产创建后默认为黑名单模式 - -``` -var currency = 'IssuerName.CNY' -var flagType = 1 -var flag = 1 - -AschJS.uia.createFlags(currency, flagType, flag, secret, secondSecret) -{ - "type": 11, - "amount": 0, - "fee": 10000000, - "recipientId": null, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "timestamp": 19400996, - "asset": { - "uiaFlags": { - "currency": "IssuerName.CNY", - "flagType": 1, - "flag": 1 - } - }, - "signature": "b96fb3d1456e1f26357109cc24d82834eb9a4687f29e69c374bbb1d534568336e148cac52f213aa4d2a69185092f8e1143b49ec4b8048cd9b3af4e20f6ba0b08", - "signSignature": "b37c77ebebe90341346be2aefe1e12bd7403e5d8f4d6e8f04630190b3e09494a28820da0ffd5f9ff011033aa6d70fc9bb4c159a4493be3b18fd7ff470103570d" -} -``` - -### **4.4 更新访问控制列表(acl),type=12** - -`uia.createAcl(currency, operator, flag, list, secret, secondSecret)` -`备注` 在主链的交易类型为12 - -- `currency` 资产名称 -- `operator` 操作符,'+'表示增加列表, ‘-’表示删除列表 -- `flag` 访问控制列表的类型,0:黑名单, 1:白名单,资产创建后默认为黑名单模式 -- `list` 待修改地址列表 - -``` -var currency = 'IssuerName.CNY' -var operator = '+' -var list = ['15745540293890213312'] -var flag =1 - -AschJS.uia.createAcl(currency, operator, flag, list, secret, secondSecret) -{ - "type": 12, - "amount": 0, - "fee": 20000000, - "recipientId": null, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "timestamp": 19403125, - "asset": { - "uiaAcl": { - "currency": "IssuerName.CNY", - "operator": "+", - "flag": 1, - "list": ["15745540293890213312"] - } - }, - "signature": "ad4060e04c1a12256de114e34499f8add24326753f1f8362991ee14aefc4c0fe90ff394d2db97e83770855a5688d463de00656fdd2d04604605cf3c04fdaca0e", - "signSignature": "63129c58b1b9fcce88cbe829f3104a10ab06037253e9b65feb50ce0d2bb988533b93e8edcad016a85675f9027758fc318cf899ca7ef161a95a8d8a055ae83a02" -} -``` - -### **4.5 资产发行,type=13** - -`uia.createIssue(currency, amount, secret, secondSecret)` -`备注` 在主链的交易类型为13 - -- `currency` 资产名称 -- `amount` 本次发行量=真实数量(100)*10**精度(3),并且所有发行量之和 <= 上限*精度 - -``` -var currency = 'IssuerName.CNY' -var amount = '100000' - -AschJS.uia.createIssue(currency, amount, secret, secondSecret) -{ - "type": 13, - "amount": 0, - "fee": 10000000, - "recipientId": null, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "timestamp": 19475744, - "asset": { - "uiaIssue": { - "currency": "IssuerName.CNY", - "amount": "100000" - } - }, - "signature": "32b01a18eca2b0dc7e2ce77ba4e758eaae2532f60844760a762cc20918e7439ac6ca585b921db6ede833ed0bf1c62e30cec545a928abafe0b679183a6ad02202", - "signSignature": "4fc290d7d7d788e9112a56233df0fe796cba39be3efa0cebf00cbc7e5bc5fd1369fad49e5698d967845b5c02e427926049cab25845d4d385e4a395791906f909" -} -``` - -### **4.6 资产转账,type=14** - -`uia.createTransfer(currency, amount, recipientId, secret, secondSecret)` -`备注` 在主链的交易类型为14 - -- `currency` 资产名字 -- `amount` 本次转账数(10000)=真实数量(10)*10**精度(3),需 <= 当前资产发行总量 -- `recipientId` 收地址,需满足前文定义好的acl规则 - -``` -var currency = 'IssuerName.CNY' -var amount = '10000' -var recipientId = 'AKKHPvQb2A119LNicCQWLZQDFxhGVEY57a' -AschJS.uia.createTransfer(currency, amount, recipientId, secret, secondSecret) -{ - "type": 14, - "amount": 0, - "fee": 10000000, - "recipientId": "AKKHPvQb2A119LNicCQWLZQDFxhGVEY57a", - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "timestamp": 19481489, - "asset": { - "uiaTransfer": { - "currency": "IssuerName.CNY", - "amount": "10000" - } - }, - "signature": "77789071a2ad6d407b9d1e0d654a9deb6d85340a3d2a13d786030e26ac773b4e9b5f052589958d2b8553ae5fc9449496946b5c225e0baa723e7ddecbd89f060a", - "signSignature": "f0d4a000aae3dd3fa48a92f792d4318e41e3b56cdbaf98649261ae34490652b87645326a432d5deb69f771c133ee4b67d2d22789197be34249e6f7f0c30c1705" -} -``` - -### **4.7 资产注销,type=11** - -`uia.createTransfer(currency, amount, recipientId, secret, secondSecret)` -`备注` 在主链的交易类型为11 - -- `currency` 资产名字 -- `flagType` 资产是否注销,1:流通,2:注销 -- `flag` flag为黑、白名单模式 - -``` -var currency = 'IssuerName.CNY' -var flagType = 2 -var flag =1 - -AschJS.uia.createFlags(currency, flagType, flag, secret, secondSecret) -{ - "type": 11, - "amount": 0, - "fee": 10000000, - "recipientId": null, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "timestamp": 19488690, - "asset": { - "uiaFlags": { - "currency": "IssuerName.CNY", - "flagType": 2, - "flag": 1 - } - }, - "signature": "cbd656552417604704703e1236ec2bbed8eba6a2ccfcb54cc0b2d629c0a9d1335a264fc9f6dee1705f4a86c36a5ce2ba8e039d913a189b7c273c8ac0d9e3780c", - "signSignature": "3c7b91d03efeed2dc86e1f2301da60789751c1be8850460d8c66c0ae8f55ea27d26f0bc79541d74b4777d9b85c518c1c73c0284dbf3e826db0a686560e57a80b" -} -``` - -## **5 受托人delegate** -### **5.1 注册受托人,type=2** - -`delegate.createDelegate(username, secret, secondSecret)` -`备注` 在主链的交易类型为2 - -- `username` 受托人名字 -- `secret` 密码 -- `secondSecret` 二级密码 - -``` -> var userName='zhenxi' -undefined -> AschJS.delegate.createDelegate(userName, secret, secondSecret || undefined) -{ type: 2, - amount: 0, - fee: 10000000000, - recipientId: null, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - timestamp: 40568017, - asset: - { delegate: - { username: 'zhenxi', - publicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed' } }, - signature: 'e471ade7ded7785f597821f8946d4e98da5ba4331505141c5bea5ff80bbf30b649218ef03254ac703ce93e15207c8b71c69c0d1400cb5790440860ed0e51a30a', - signSignature: 'ec47d565a70e6ad075abaf1ff55c129bde9495e4cc7ab2a9404b698ef257f3b1cfd0ce4f9f1854a1bbfec0f663867823a544f80964e3be05ddf03a50a9b77d07', - id: '774ccf5e7d9d9fefa459b23d96e10ffae4bb891e1e07912ac1370af04192e810' } -``` - -### **5.2 给受托人增加/取消投票,type=3** - -`vote.createVote(keyList, secret, secondSecret)` -`备注` 在主链的交易类型为3 - -- `keyList` 受托人公钥列表 -- `secret` 密码 -- `secondSecret` 二级密码 - -``` -// 投票内容是一个列表,列表中的每一个元素是一个符号加上所选择的受托人的公钥,符号为+表示投票,符号为-表示取消投票 -> var voteContent = [ -... '-ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7', -... '+c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2' -... ]; -undefined - -> transaction=AschJS.vote.createVote(voteContent, secret, secondSecret || undefined); -{ type: 3, - amount: 0, - fee: 10000000, - recipientId: null, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - timestamp: 40568669, - asset: { vote: { votes: [Array] } }, - signature: '66f6f3c4fbb8545df53ea35ff655fc1a28815591885757d0b735e77ed348caf33d8d9cb2895f85cd40bf2d3b4633f45a19ebd1dd130233305a603304a92ce003', - signSignature: 'c026d373e026b524efd82ad1ab046708ee1ff68573f016490d12908f5ad00a97fa7501f46834c94f6dd64afd00aa77f9d29ded087977ac6601778d4aacb5cd0e', - id: '0789524787384e2e4da7773afdd3871193a67303c4da69c4a9070eaa5676d36c' } - -> transaction.asset.vote.votes -[ '-ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7', - '+c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2' ] - -``` - - -## **6 dapp相关** - -### **6.1 dapp注册,type=5** - -`dapp.createDApp(options, secret, secondSecret)` -`备注` 在主链的交易类型为5 - -- `options` dapp的基本属性,如名字、url、icon、预置的受托人公钥、dapp类型、dapp tag等信息 -- `secret` 密码 -- `secondSecret` 二级密码 - -``` -> var options = { name: 'asch-dapp-cctime', -... link: 'https://github.com/AschPlatform/asch-dapp-cctime/archive/master.zip', -... category: 1, -... description: 'Decentralized news channel', -... tags: 'asch,dapp,demo,cctime', -... icon: 'http://o7dyh3w0x.bkt.clouddn.com/hello.png', -... type: 0, -... delegates: -... [ '8b1c24a0b9ba9b9ccf5e35d0c848d582a2a22cca54d42de8ac7b2412e7dc63d4', -... 'aa7dcc3afd151a549e826753b0547c90e61b022adb26938177904a73fc4fee36', -... 'e29c75979ac834b871ce58dc52a6f604f8f565dea2b8925705883b8c001fe8ce', -... '55ad778a8ff0ce4c25cb7a45735c9e55cf1daca110cfddee30e789cb07c8c9f3', -... '982076258caab20f06feddc94b95ace89a2862f36fea73fa007916ab97e5946a' ], -... unlockDelegates: 3 }; -undefined - -> trs=AschJS.dapp.createDApp(options, secret); -{ type: 5, - amount: 0, - fee: 10000000000, - recipientId: null, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - timestamp: 40572296, - asset: - { dapp: - { category: 1, - name: 'asch-dapp-cctime', - description: 'Decentralized news channel', - tags: 'asch,dapp,demo,cctime', - type: 0, - link: 'https://github.com/AschPlatform/asch-dapp-cctime/archive/master.zip', - icon: 'http://o7dyh3w0x.bkt.clouddn.com/hello.png', - delegates: [Array], - unlockDelegates: 3 } }, - signature: '5a8e2dba5e14b4ec62ce1b8543de2796d3cded249ed899c5049dd0adeff00963dd40436e7cfc6f9952e09d5c6ac8f5144d3e568f263586520c68012d3c7ca509', - id: 'ecf9366a128408b843f0e6b2bd7261a4d602c32ae36a8c3cef609e904f180735' } -> trs.asset.dapp.delegates -[ '8b1c24a0b9ba9b9ccf5e35d0c848d582a2a22cca54d42de8ac7b2412e7dc63d4', - 'aa7dcc3afd151a549e826753b0547c90e61b022adb26938177904a73fc4fee36', - 'e29c75979ac834b871ce58dc52a6f604f8f565dea2b8925705883b8c001fe8ce', - '55ad778a8ff0ce4c25cb7a45735c9e55cf1daca110cfddee30e789cb07c8c9f3', - '982076258caab20f06feddc94b95ace89a2862f36fea73fa007916ab97e5946a' ] -``` - -### **6.2 dapp充值,type=6** - -`transfer.createInTransfer(dappid, currency, amount, secret, secondSecret);` -`备注` 在主链的交易类型为6 - -- `dappid` dapp的id -- `currency` 充值的资产名 -- `amount` 充值的数量 - -``` -var dappid = "bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024"; -var currency = "XAS"; -var amount = 10*100000000 ; - -> AschJS.transfer.createInTransfer(dappid, currency, amount, secret, secondSecret || undefined); -{ type: 6, - amount: 1000000000, - fee: 10000000, - recipientId: null, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - timestamp: 40578327, - asset: - { inTransfer: - { dappId: 'bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024', - currency: 'XAS' } }, - signature: '6907c1402c702e0fd504a8734a047c1bb216d437e65d5675325846b92ef8b916fc634ea7e33a7c72c60c058d1496d0385c95e39a8291e27b2dceb2f40b6aed02', - signSignature: '86de438431c639124a13429e8c6a8c13a5cbbbab3a8323ae08b56f65faeff6d816815d7cdecfdb7287077b14e4d14865637efc9d7fd72d085b0aa9d82f27170c', - id: '25be71c296430a409cfeaf1ffaa957d18793f3695db07a846c22a7c467c45994' } -``` - -### **6.3 dapp内部合约调用** - -`dapp.createInnerTransaction(options, secret)` - -- `options` 合约相关的选项,如手续费、合约编号、合约字符串数组参数 -- `secret` 密码 - -自定如下全局变量,用于下面子章节代码演示。 - -``` -> var fee = String(0.1 * 100000000); // 目前dapp内置合约调用的手续费统一为10000000 对应的资产 -``` - -#### **6.3.1 dapp提现,合约type=2** - -`args` '["资产名字","提现数额"]' - -``` -> var type = 2; // 这里的type指的是合约标号,而非主链的交易类型 -> var options = {fee: fee, type: type, args: '["CCTime.XCT", "100000000"]'}; - -> AschJS.dapp.createInnerTransaction(options, secret); -{ fee: '10000000', - timestamp: 40572732, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - type: 2, - args: '["CCTime.XCT", "100000000"]', - signature: 'a0d860a0c13cf40d6be08f42a66bf01264f96fadc8ed2997139c583ba7fcd5e7ceeda9207c635215ddfd60bde8c35914cdfe2b03a4862cdd187b9142d497c301' } -``` - -#### **6.3.2 dapp内部转账,合约type=3** - -`args` '["资产名字","转账数额","接收地址"]' - -``` -> var type = 3; -> var options = {fee: fee, type: type, args: '["CCTime.XCT", "100000000", "A6H9rawJ7qvE2rKwQfdtBHdeYVehB8gFzC"]'}; - -> AschJS.dapp.createInnerTransaction(options, secret); -{ fee: '10000000', - timestamp: 40573272, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - type: 3, - args: '["CCTime.XCT", "100000000", "A6H9rawJ7qvE2rKwQfdtBHdeYVehB8gFzC"]', - signature: '3843bef77ad7c6f2b57083270055720186b8ba286cd44e263028eef9b8650ecf6d243c1861f9b9416e123b594695934430deb0f5146a173ebfcdccb6915acf0c' } - -``` - -#### **6.3.4 dapp内设置昵称,合约type=3** - -`args` '["昵称"]' - -``` -> var type = 4; -> var options = {fee: fee, type: type, args: '["nicheng"]'}; - -> AschJS.dapp.createInnerTransaction(options, secret); -{ fee: '10000000', - timestamp: 40573343, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - type: 4, - args: '["nicheng"]', - signature: '172998ddbb2ef72037be673d658dbc64760da307d451257666c956868b142707cd4aa38668b52d1d0d7cc62c01866daef2bae8d427844194d42ca9fea97ea70b' } -``` - -### **6.4 dapp提现** -#### **6.4.1 创建提现交易,type=7** - -`transfer.createOutTransfer(recipientId, dappId, transactionId, currency, amount, secret, secondSecret)` -`备注` 在主链的交易类型为7,该接口一般由dapp受托人来调用(受托人每隔10秒扫描侧链上由智能合约所创建的提现交易,发现后则在主链创建type=7的提现交易),所以一般情况下开发人员用不到。 - -- `recipientId` 提现接收者id -- `dappId` dapp id -- `transactionId` 提现交易id,该交易id是编号为2的智能合约在侧链dapp上所创建的 -- `currency` 提现资产名(XAS或者UIA) -- `amount` 提现数额 - -``` -let recipientId = 'AFUH568CbGC2GPcE4gXHiZhxdYQYfziz2J'; -let dappId = 'bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024'; -let transactionId = '123b04a6e380500903d8942622d57987661e72b2ae95464066d0af3f02c3c691'; -let currency = 'XAS' -let amount = '10000000' - -> transaction = AschJS.transfer.createOutTransfer(recipientId, dappId, transactionId, currency, amount, secret, secondSecret); -{ type: 7, - amount: 0, - fee: 10000000, - recipientId: 'AFUH568CbGC2GPcE4gXHiZhxdYQYfziz2J', - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - timestamp: 40668981, - asset: - { outTransfer: - { dappId: 'bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024', - transactionId: '123b04a6e380500903d8942622d57987661e72b2ae95464066d0af3f02c3c691', - currency: 'XAS', - amount: '10000000' } }, - signature: '432d25e5c5b81fa3a5937adca2dd4a1e2a38e51f8896838601902e0c123a5ccb664bbc8a55344b9fedb773da98e0988e4e8d1ca99dcbc51a80ea3bc9a6b61806', - signSignature: '8154c1f8305b9b957974e778de1e08dd3f08afcb70f27624d1385dbae9dfa6d0a3aaed6211ed8a40f4015f7e47312f0f205d94518c68e4deec8d76567f56f10f', - id: '237925a60ccc0abfc1494720aab8c11c74ba61e8ab3ca4bd8ded8c3215c201a7' } - -``` - -#### **6.4.2 受托人对提现交易进行签名** - -`transfer.signOutTransfer(transaction, secret)` -`备注` dapp提现交易,需要多个受托人签名后才能生效。受托人签名的最小数量取决于dapp的注册参数:unlockDelegates。受托人每隔10秒扫描侧链上由智能合约所创建的提现交易,发现有交易且签名个数未满足时,会对其进行签名。一般情况下普通开发人员用不到。 - -- `transaction` transfer.createOutTransfer生成的提现交易 -- `secret` 受托人密码 - -``` -// 沿用上一章节《6.4.1 创建提现交易,type=7》的变量 -transaction.signatures = [] // 受托人签名列表 - -// 第1个受托人对提现交易transaction进行签名 -delegate1_secret = 'chalk flame jeans rebuild dutch stone abstract capital lucky pottery raven depend' -> signature1 = AschJS.transfer.signOutTransfer(transaction,delegate1_secret); -'ac0ea4c10b911f2134e5adfb3535ffc070ffa8f2858a5a1bc4e9bef442863e117e6bce552bba0d5b0160c4076dd3c657ebc33cbe077a8ef719798a8bb0fac30c' -transaction.signatures.push(signature1) // 将签名加入到transaction的签名列表中 -// 第2个受托人对提现交易transaction进行签名 -delegate2_secret = 'twist arrange matter twice daughter cave cause never enough scare warfare uncover' -> signature2 = AschJS.transfer.signOutTransfer(transaction,delegate2_secret); -'480e0717e4be02e48a27e2323bf6507c4c72d1033b4e7e674651e9e4feced17836f0b81b91ade99b61620a2766ecc901f090d81cc72d22b86807ae981eb2d10c' -transaction.signatures.push(signature2) // 将签名加入到transaction的签名列表中 -// 依次类推,多个受托人都对该交易进行签名,当满足最小签名个数时,该提现交易才会真正生效 -> transaction -{ type: 7, - amount: 0, - fee: 10000000, - recipientId: 'AFUH568CbGC2GPcE4gXHiZhxdYQYfziz2J', - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - timestamp: 40669013, - asset: - { outTransfer: - { dappId: 'bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024', - transactionId: '123b04a6e380500903d8942622d57987661e72b2ae95464066d0af3f02c3c691', - currency: 'XAS', - amount: '10000000' } }, - signature: '1dfae733408d374cd7be5f4b55183c0c05dc31341f93daaf82c26c80ab11035202502180dd78c5643edcd3bb481a38f352408bc35e44e6c1c53c95612fbca804', - signSignature: '8f4f7aa06c02c0a3d637329e1a3b23489b91797b9f3477afd4314b2f78d1e8e8a369a640d75916bd9477e69363cf440c27124db615dced1701a1a934714afe05', - id: '95a0c4ac9d5397452629b89410413f54ed37caee84a13edf3c9c26d3d0606dab', - signatures: - [ 'ac0ea4c10b911f2134e5adfb3535ffc070ffa8f2858a5a1bc4e9bef442863e117e6bce552bba0d5b0160c4076dd3c657ebc33cbe077a8ef719798a8bb0fac30c', - '480e0717e4be02e48a27e2323bf6507c4c72d1033b4e7e674651e9e4feced17836f0b81b91ade99b61620a2766ecc901f090d81cc72d22b86807ae981eb2d10c' ] // 受托人签名数组 - } -``` - - -## **7 存储storage** - -### **7.1 创建存储交易,type=8** - -`storage.createStorage(content, secret, secondSecret)` -`备注` 在主链的交易类型为8 - -- `content` - - -``` -> var content = new Buffer('helloworld').toString('hex') -> AschJS.storage.createStorage(content, secret, secondSecret) -{ type: 8, - amount: 0, - fee: 10000000, - recipientId: null, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - timestamp: 40578932, - asset: { storage: { content: '68656c6c6f776f726c64' } }, - signature: 'd7f3f29549542d6716bdb13e8e1f97e3965c6fbe34f1ee18dbdcad7ba9cbf83ee7cb2b7fcbaab5ffed5d569771731bb5a40efc4fabd142cb30becdad8bc8bb06', - signSignature: '38315bf369540cc7a793139b1b6195f4c0e1512514d62bf028d454182a4b7a8912c1b1e6f617f6fb4ff8d80bd141a2ebb9dfcaa8fee68cfc81f8872611bba803', - id: '4d0b04a6e380500903d8942622d57987661e72b2ae95464066d0af3f02c3c691' } -``` - -## **8 签名验证相关crypto** - -自定义如下已签名的转账交易内容(在主链给16358246403719868041转账100XAS),用于下面章节演示。 -``` -> var targetAddress = "16358246403719868041"; -> var amount = 100*100000000; //100 XAS -> var message = 'beizhu'; -> transaction = AschJS.transaction.createTransaction(targetAddress, amount, message, secret, secondSecret) -{ type: 0, - amount: 10000000000, - fee: 10000000, - recipientId: '16358246403719868041', - message: 'beizhu', - timestamp: 40566970, - asset: {}, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - signature: '9bef374be100fcfec59d245af59e5646ba5dcb79c6f1399ddd676a617542eeb45cc363822b84410e379f0caa501c25b66e59142353c04d23d1cb95cf64cef306', - signSignature: '513e3efdbb65f8e60e85ca98d8d065ec9bd3bfa6f45a1f48cfade9c94d410338ee64bd55938c168b10f0749335c050312785dbf08882ffd0e40a65fde8c2b10b', - id: '871554a8346d84cab2147324706d8ab5494fde928a7463a68d536ed6c0357897' } -``` - -### **8.1 根据交易内容获取字节Buffer对象** - -`getBytes(transaction, skipSignature, skipSecondSignature)` - -- `transaction` 交易内容,可以是签名后也可是未签名的,默认需传入签名后的交易。必传参数 -- `skipSignature` 是否跳过签名计算,默认不跳过。非必传参数 -- `skipSecondSignature` 是否跳过二级密码签名计算,默认不跳过。非必传参数 - -``` -// 此时transaction.signature和transaction.signSignature都会计算在内 -> AschJS.crypto.getBytes(transaction) - // 返回的字节buffer对象 -``` - -### **8.2 根据交易内容获取Hash Buffer对象** - -`getHash(transaction, skipSignature, skipSecondSignature)` - -- `transaction` 交易内容,可以是签名后也可是未签名的,默认需传入签名后的交易。必传参数 -- `skipSignature` 是否跳过签名计算,默认不跳过。非必传参数 -- `skipSecondSignature` 是否跳过二级密码签名计算,默认不跳过。非必传参数 - -``` -// 此时transaction.signature和transaction.signSignature都会计算在内 -> AschJS.crypto.getHash(transaction) - // 返回的Hash Buffer -``` - -### **8.3 根据交易内容获取交易id** - -`crypto.getId(transaction)` - -- `transaction` 签名后的交易内容 - -``` -> AschJS.crypto.getId(transaction) -'871554a8346d84cab2147324706d8ab5494fde928a7463a68d536ed6c0357897' // 返回结果,交易id - -``` - -### **8.4 对交易Bytes Buffer进行签名** - -`crypto.signBytes(bytes, keys)` - -- `bytes` 交易的Bytes Buffer,未签名交易或者一级密码签名但二级密码未签名的交易 -- `keys` 公钥/私钥 密钥对 - -``` -// 定义未签名交易 -> var trs = { type: 0, -... amount: 10000000000, -... fee: 10000000, -... recipientId: '16358246403719868041', -... message: 'beizhu', -... timestamp: 40566970, -... asset: {}} - -// 根据密码,生成 -> keys = AschJS.crypto.getKeys(secret) -{ publicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - privateKey: '7ae536fa343281d9e9ed383e8b5ef62e0fd0d0cbed79786cac241d484e312fdeebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed' } - -> trs.senderPublicKey = keys.publicKey; -'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed' - -// 获取交易的Bytes Buffer -> buf = AschJS.crypto.getBytes(trs) - -// 通过私钥对交易Bytes Buffer进行签名 -> signature = AschJS.crypto.signBytes(buf,keys) -'9bef374be100fcfec59d245af59e5646ba5dcb79c6f1399ddd676a617542eeb45cc363822b84410e379f0caa501c25b66e59142353c04d23d1cb95cf64cef306' // 返回值与上面自定义的已签名交易中的签名一致 - -``` - -### **8.5 验证交易签名是否和已存在的签名一致** - -`crypto.verifyBytes(bytes, signature, publicKey)` 返回true/false - -- `bytes` 交易的Bytes Buffer,未签名交易或者一级密码签名但二级密码未签名的交易 -- `signature` 待校验的签名 -- `publicKey` 签名者公钥 - -``` -// 沿用上一章节《对交易Bytes Buffer进行签名》的变量 -> AschJS.crypto.verifyBytes(buf,transaction.signature,transaction.senderPublicKey) -true // 本章最上面自定义的transaction签名一致 -``` - -## **9 其它** - -### **9.1 全局参数变量options** - -#### **9.1.1 设置变量k/v** -`options.set(key, values)` - -- `key` 键名 -- `value` 键值 - -``` -> AschJS.options.set('secret','minor borrow display rebel depart core buzz right distance avocado immense push') -undefined - -``` - - -#### **9.1.2 根据key获取value** - -`options.get(key)` - -- `key` 键名 - -``` -> AschJS.options.get('secret') -'minor borrow display rebel depart core buzz right distance avocado immense push' - -``` - - -#### **9.1.3 获取所有的k/v** - -`options.getAll()` - -``` -> AschJS.options.getAll() -{ clientDriftSeconds: 5, // asch-js内置变量 - secret: 'minor borrow display rebel depart core buzz right distance avocado immense push' } - -``` - -### **9.2 时间相关slot.time** - -#### **9.2.1 asch主网创世块生成时间** - -`utils.slots.beginEpochTime()` -`备注` 结果为UTC时间,即Asch纪元的开始时间。 - -``` -> AschJS.utils.slots.beginEpochTime() -2016-06-27T20:00:00.000Z // Asch主网创世块生成时间,但主网正式运行是在8月16号那天(主网正式运行的标志是 生成了block heihgt=2的区块) -``` - - -#### **9.2.2 根据unix时间戳获获Asch时间戳** - -`utils.slots.getTime(time)` -`备注` 获得结果叫做EpochTim(Asch时间戳),传入的time相对于Asch纪元经历的秒数 - -- `time` 如果不传值则取当前时刻的 Unix时间戳*1000 (即单位是毫秒) - -``` -> AschJS.utils.slots.getTime() -40655681 // Asch时间戳 - -> unix_timestamp = 1507713496 -> epochTime = AschJS.utils.slots.getTime(unix_timestamp * 1000) -40655896 // Asch时间戳 - -``` - -#### **9.2.3 根据Asch时间戳获取unix时间戳** - -`utils.slots.getRealTime(epochTime)` -`备注` 返回结果是真实的 unix时间戳* 1000 - -- `epochTime` Asch时间戳,单位是秒 - -``` -> unix_timestamp = 1507713496 // unix时间戳 -> epochTime = AschJS.utils.slots.getTime(unix_timestamp * 1000) -40655896 // 通过unix时间戳获取到asch时间戳 -> real_time = AschJS.utils.slots.getRealTime(epochTime) -1507713496000 // 通过asch时间戳获取unix时间戳 - -> unix_timestamp === real_time/1000 -true // 换算结果一致 -``` - - diff --git a/docs/asch_js_api_en.md b/docs/asch_js_api_en.md deleted file mode 100644 index 2ad7f6d..0000000 --- a/docs/asch_js_api_en.md +++ /dev/null @@ -1,1042 +0,0 @@ -Table of Contents -================= - -- [Asch-JS API](#asch-js-api) - - [**1 Asch-js description**](#1-asch-js-description) - - [**1.1 asch-js installation**](#11-asch-js-installation) - - [**1.2 description**](#12-description) - - [**2 Account**](#2-account) - - [**2.1 Get keypairs from secret**](#21-get-keypairs-from-secret) - - [**2.1 Get address from public key**](#21-get-address-from-public-key) - - [**2.3 Set second secret, type=1**](#23-set-second-secret-type1) - - [**2.4 Lock account,type=100**](#24-lock-accounttype100) - - [**3 Ordinary transactions**](#3-ordinary-transactions) - - [**3.1 Transfer XAS in the main-chain, type=0**](#31-transfer-xas-in-the-main-chain-type0) - - [**3.2 Get TransactionId from Transaction**](#32-get-transactionid-from-transaction) - - [**4 Asset related UIA**](#4-asset-related-uia) - - [**4.1 Asset publisher registration,type=9**](#41-asset-publisher-registrationtype9) - - [**4.2 Asset registration, type=10**](#42-asset-registration-type10) - - [**4.3 Asset set Access control list (acl), type=11**](#43-asset-set-access-control-list-acl-type11) - - [**4.4 Update access control list(acl), type=12**](#44-update-access-control-listacl-type12) - - [**4.5 Asset distribution, type=13**](#45-asset-distribution-type13) - - [**4.6 Asset transfer, type=14**](#46-asset-transfer-type14) - - [**4.7 Asset write-off, type=11**](#47-asset-write-off-type11) - - [**5 Delegate**](#5-delegate) - - [**5.1 Registere delegate, type=2**](#51-registere-delegate-type2) - - [**5.2 Vote or cancel vote for delegate, type=3**](#52-vote-or-cancel-vote-for-delegate-type3) - - [**6 Dapp**](#6-dapp) - - [**6.1 Dapp registration, type=5**](#61-dapp-registration-type5) - - [**6.2 Dapp recharge, type=6**](#62-dapp-recharge-type6) - - [**6.3 Dapp internal contract call**](#63-dapp-internal-contract-call) - - [**6.3.1 Dapp cash, contract type=2**](#631-dapp-cash-contract-type2) - - [**6.3.2 Dapp internal transfer, contract type=3**](#632-dapp-internal-transfer-contract-type3) - - [**6.3.4 Set a dapp nickname, contract type=3**](#634-set-a-dapp-nickname-contract-type3) - - [**6.4 Dapp withdraw**](#64-dapp-withdraw) - - [**6.4.1 Create a cash transaction, type=7**](#641-create-a-cash-transaction-type7) - - [**6.4.2 The delegate signs the cash transaction**](#642-the-delegate-signs-the-cash-transaction) - - [**7 Storage**](#7-storage) - - [**7.1 Create a storage transaction,type=8**](#71-create-a-storage-transactiontype8) - - [**8 Related to signature verification, crypto**](#8-related-to-signature-verification-crypto) - - [**8.1 Get transaction bytes**](#81-get-transaction-bytes) - - [**8.2 Get Transaction Hash**](#82-get-transaction-hash) - - [**8.3 Get transaction id based on transaction content**](#83-get-transaction-id-based-on-transaction-content) - - [**8.4 Sign the transaction bytes**](#84-sign-the-transaction-bytes) - - [**8.5 Verify that the transaction signature is consistent with the existing signature**](#85-verify-that-the-transaction-signature-is-consistent-with-the-existing-signature) - - [**9 Miscellaneous**](#9-miscellaneous) - - [**9.1 Global parameters**](#91-global-parameters) - - [**9.1.1 Set the variable k/v**](#911-set-the-variable-kv) - - [**9.1.2 According to the key for value**](#912-according-to-the-key-for-value) - - [**9.1.3 Get all k/v**](#913-get-all-kv) - - [**9.2 Time related slot.time**](#92-time-related-slottime) - - [**9.2.1 Asch main network creation block generation time**](#921-asch-main-network-creation-block-generation-time) - - [**9.2.2 Get Asch timestamp based on unix timestamp**](#922-get-asch-timestamp-based-on-unix-timestamp) - - [**9.2.3 Get the unix timestamp based on the Asch timestamp**](#923-get-the-unix-timestamp-based-on-the-asch-timestamp) - - -Created by [Markdown-Toc](https://github.com/AlanWalk/Markdown-TOC) - -# Asch-JS API - - -## **1 Asch-js description** - -### **1.1 asch-js installation** - -``` -npm install asch-js -var AschJS = require('asch-js'); -``` - -### **1.2 description** -Many functions need to receive a password or optionally a second password. - -- `secret` password -- `publicKey` public key -- `secondSecret` second password - -```js -var secret = 'minor borrow display rebel depart core buzz right distance avocado immense push' -var publicKey = 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed'; -var secondSecret = 'erjimima2017'; -``` - -The generated transaction data (in json format) needs to be send to a http api -- The main chain transaction passed `POST /peer/transactions` -- Dapp transaction passed `PUT /api/dapps/dappID/transactions/signed` - - -## **2 Account** - -### **2.1 Get keypairs from secret** - -`crypto.getKeys(secret)` - -- `secret` password - -```js -AschJS.crypto.getKeys(secret) -{ - publicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - privateKey: '7ae536fa343281d9e9ed383e8b5ef62e0fd0d0cbed79786cac241d484e312fdeebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed' -} -``` - -### **2.1 Get address from public key** - -`crypto.getAddress(publicKey)` - -- `publicKey` public key - -```js -AschJS.crypto.getAddress(publicKey); -'AFUH568CbGC2GPcE4gXHiZhxdYQYfziz2J' -``` - -### **2.3 Set second secret, type=1** - -`crypto.signature.createSignature(secret, secondSecret)` -`remarks` The transaction-type in the main chain for this operation is 1 - -- `secret` password -- `secondSecret` second password - -```js -AschJS.signature.createSignature(secret, secondSecret) -{ - type: 1, - amount: 0, - fee: 500000000, - recipientId: null, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - timestamp: 40566038, - asset: { - signature: { - publicKey: '632a41caf7d3c8d3754f27a11004acaea6f5571eed28b42451b5560ee91e991c' - } - }, - signature: 'ee42f4dc17ace4f76f86fba93c7d86b61a69de46ac96e102e9f93668c8cdd9e6281821c63cb3e0c23099968cccdcfd0197aaab42afba4a98fa696c17b133be06', - id: '2237134c11b3cbaa9b7951f4afd47454ca04af2c7c6a030729ec63f75230e9ad' -} -``` - -### **2.4 Lock account, type=100** - -`transaction.createLock(height, secret, secondSecret)` -`remarks` The transaction-type in the main chain for this operation is 100 - -- `height` The block height at which the account should be locked -- `secret` password -- `secondSecret` second password - -```js -AschJS.transaction.createLock(8130, secret, secondSecret) -{ - type: 100, - amount: 0, - fee: 10000000, - recipientId: null, - args: [ '8130' ], - timestamp: 40566287, - asset: {}, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - signature: '06f6852d0e2e56ca441fa60b407aaa2197290ff096558c746c9c8bcdc971b8c4065ec08edd49c7292eca51849c16c5b8f0d33bb4ce972a932603dcf46a391e0e', - signSignature: '3b645b0f6a2c597c55595669a856489c0c4f3a132c798c615b8e0241f3169a367edea7228ebc8915d5fd7a0571cc08c971d07520b9908c80c9b2c2c76ada5e07', - id: 'c87d93af84939076a65a49c3b483897d262edc340b2d4184a4d2505b58711a91' -} -``` - -## **3 Ordinary transactions** - -### **3.1 Transfer XAS in the main-chain, type=0** - -`transaction.createTransaction(recipientId, amount, message, secret, secondSecret)` -`remark` The transaction-type in the main chain for this operation is 0 - -- `recipientId` Receiver address -- `amount` Transfer amount -- `message` Transfer postscript -- `secret` Password -- `secondSecret` Second password - -```js -var targetAddress = "16358246403719868041"; -undefined -var amount = 100*100000000; //100 XAS -undefined -var message = 'beizhu'; -undefined -AschJS.transaction.createTransaction(targetAddress, amount, message, secret, secondSecret) -{ - type: 0, - amount: 10000000000, - fee: 10000000, - recipientId: '16358246403719868041', - message: 'beizhu', - timestamp: 40566970, - asset: {}, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - signature: '9bef374be100fcfec59d245af59e5646ba5dcb79c6f1399ddd676a617542eeb45cc363822b84410e379f0caa501c25b66e59142353c04d23d1cb95cf64cef306', - signSignature: '513e3efdbb65f8e60e85ca98d8d065ec9bd3bfa6f45a1f48cfade9c94d410338ee64bd55938c168b10f0749335c050312785dbf08882ffd0e40a65fde8c2b10b', - id: '871554a8346d84cab2147324706d8ab5494fde928a7463a68d536ed6c0357897' -} -``` - -### **3.2 Get TransactionId from Transaction** - -`crypto.getId(transaction)` - -- `transaction` Content of signed transaction - -```js -var targetAddress = "16358246403719868041"; -var amount = 100*100000000; //100 XAS -var message = 'beizhu'; -transaction = AschJS.transaction.createTransaction(targetAddress, amount, message, secret, secondSecret) -{ - type: 0, - amount: 10000000000, - fee: 10000000, - recipientId: '16358246403719868041', - message: 'beizhu', - timestamp: 40566970, - asset: {}, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - signature: '9bef374be100fcfec59d245af59e5646ba5dcb79c6f1399ddd676a617542eeb45cc363822b84410e379f0caa501c25b66e59142353c04d23d1cb95cf64cef306', - signSignature: '513e3efdbb65f8e60e85ca98d8d065ec9bd3bfa6f45a1f48cfade9c94d410338ee64bd55938c168b10f0749335c050312785dbf08882ffd0e40a65fde8c2b10b', - id: '871554a8346d84cab2147324706d8ab5494fde928a7463a68d536ed6c0357897' -} - -AschJS.crypto.getId(transaction) -'871554a8346d84cab2147324706d8ab5494fde928a7463a68d536ed6c0357897' // Return result, transaction id -``` - - -## **4 Asset related UIA** - -### **4.1 Asset publisher registration,type=9** - -`uia.createIssuer(name, desc, secret, secondSecret)` -`remark` The transaction-type in the main chain for this operation is 9 - -- `name` Asset publisher name -- `desc` Assset publisher description - -```js -var name = 'IssuerName' -var desc = 'IssuerDesc' -AschJS.uia.createIssuer(name, desc, secret, secondSecret) -{ - "type": 9, - "amount": 0, - "fee": 10000000, - "recipientId": null, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "timestamp": 19395607, - "asset": { - "uiaIssuer": { - "name": "IssuerName", - "desc": "IssuerDesc" - } - }, - "signature": "c6ed2a4bafe2b8aa31f4aaceacc2a96cb028abbabb2ed062937498c58e24ca5467a340ddd63b67f809a680ff91b83e685c64991eb695494ddb2fdc57e5761607", - "signSignature": "8eceacbd47c2b8ed335145ced19d7a3a51f99bdd6631d16ed214180c6f80e29bd6d572f45e7c7d685584e55cb5c303cf340406553ece28c9c0a2fa7a777aac0b" -} -``` - - - -### **4.2 Asset registration, type=10** - -`uia.createAsset(name, desc, maximum , precision, strategy, secret, secondSecret)` -`remark` The transaction-type in the main chain for this operation is 10 - -- `name` The name of the asset, has the following format: issuer name, asset name (this is the unique identifier for the asset) -- `desc` Asset description -- `maximum` The maximum quantity of assets that can be issued -- `precision` Precision in decimal places, the upper limit is 1000000, the accuracy of 3, representing the maximum issuance of assets IssuerName.CNY 1000.000 -- `strategy` Issue strategy, if not set then the default is 10% every 10 years - -```js -var name = 'IssuerName.CNY' -var desc = 'Asset description' -var maximum = '1000000' -var precision = 3 -var strategy = '' - -AschJS.uia.createAsset(name, desc, maximum, precision, strategy, secret, secondSecret) -{ - "type": 10, - "amount": 0, - "fee": 10000000, - "recipientId": null, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "timestamp": 19397444, - "asset": { - "uiaAsset": { - "name": "IssuerName.CNY", - "desc": "Asset description", - "maximum": "1000000", - "precision": 3, - "strategy": "" - } - }, - "signature": "c755587d331dd2eb62ef91dce1511d83a3e603c7cdc7548a16052519c21ea89c78364e35e5d46da0e2103fa2fb7f037eec55a5deba18826fa13e4252422d750e", - "signSignature": "1b7ed4c21c477b8ff3d2acfdfd7ff85617093f4c21de70938c46b61c9704b037dbcf7f9e5f5dd1a5dc8f22cf473aaa459e6e5b15ced388b8a1da1e307987a509" -} -``` - - - -### **4.3 Asset set Access control list (acl), type=11** - -`uia.createFlags(currency, flagType, flag, secret, secondSecret)` -`remark` The transaction-type in the main chain for this operation is 11 - -- `currency` Asset name -- `flagType` Whether the assets write-off, 1: circulation, 2: cancellation -- `flag` Access control list type, 0: blacklist, 1: whitelist, default to blacklist mode after assets are created - -```js -var currency = 'IssuerName.CNY' -var flagType = 1 -var flag = 1 - -AschJS.uia.createFlags(currency, flagType, flag, secret, secondSecret) -{ - "type": 11, - "amount": 0, - "fee": 10000000, - "recipientId": null, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "timestamp": 19400996, - "asset": { - "uiaFlags": { - "currency": "IssuerName.CNY", - "flagType": 1, - "flag": 1 - } - }, - "signature": "b96fb3d1456e1f26357109cc24d82834eb9a4687f29e69c374bbb1d534568336e148cac52f213aa4d2a69185092f8e1143b49ec4b8048cd9b3af4e20f6ba0b08", - "signSignature": "b37c77ebebe90341346be2aefe1e12bd7403e5d8f4d6e8f04630190b3e09494a28820da0ffd5f9ff011033aa6d70fc9bb4c159a4493be3b18fd7ff470103570d" -} -``` - -### **4.4 Update access control list(acl), type=12** - -`uia.createAcl(currency, operator, flag, list, secret, secondSecret)` -`remark` The transaction-type in the main chain for this operation is 12 - -- `currency` Asset name -- `operator` Operator '+' means adding something to the list, '-' means deleting from the list -- `flag` Access control list types, 0: blacklist, 1: whitelist, default flag is blacklist after assets are created -- `list` A list of address that should be updated - -```js -var currency = 'IssuerName.CNY' -var operator = '+' -var list = ['15745540293890213312'] -var flag = 1 - -AschJS.uia.createAcl(currency, operator, flag, list, secret, secondSecret) -{ - "type": 12, - "amount": 0, - "fee": 20000000, - "recipientId": null, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "timestamp": 19403125, - "asset": { - "uiaAcl": { - "currency": "IssuerName.CNY", - "operator": "+", - "flag": 1, - "list": ["15745540293890213312"] - } - }, - "signature": "ad4060e04c1a12256de114e34499f8add24326753f1f8362991ee14aefc4c0fe90ff394d2db97e83770855a5688d463de00656fdd2d04604605cf3c04fdaca0e", - "signSignature": "63129c58b1b9fcce88cbe829f3104a10ab06037253e9b65feb50ce0d2bb988533b93e8edcad016a85675f9027758fc318cf899ca7ef161a95a8d8a055ae83a02" -} -``` - -### **4.5 Asset distribution, type=13** - -`uia.createIssue(currency, amount, secret, secondSecret)` -`remark` The transaction-type in the main chain for this operation is 13 - -- `currency` Asset name -- `amount` This Issue = Actual Quantity (100) * 10 ** Accuracy (3), and Sum of All Circulations <= Upper Limit * Accuracy - -```js -var currency = 'IssuerName.CNY' -var amount = '100000' - -AschJS.uia.createIssue(currency, amount, secret, secondSecret) -{ - "type": 13, - "amount": 0, - "fee": 10000000, - "recipientId": null, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "timestamp": 19475744, - "asset": { - "uiaIssue": { - "currency": "IssuerName.CNY", - "amount": "100000" - } - }, - "signature": "32b01a18eca2b0dc7e2ce77ba4e758eaae2532f60844760a762cc20918e7439ac6ca585b921db6ede833ed0bf1c62e30cec545a928abafe0b679183a6ad02202", - "signSignature": "4fc290d7d7d788e9112a56233df0fe796cba39be3efa0cebf00cbc7e5bc5fd1369fad49e5698d967845b5c02e427926049cab25845d4d385e4a395791906f909" -} -``` - -### **4.6 Asset transfer, type=14** - -`uia.createTransfer(currency, amount, recipientId, secret, secondSecret)` -`remark` The transaction-type in the main chain for this operation is 14 - -- `currency` Asset name -- `amount` The number of transfer (10000) = true number (10) * 10 ** accuracy (3), required <= the current total assets issued -- `recipientId` Receive address, to meet the above definition of the acl rules - -```js -var currency = 'IssuerName.CNY' -var amount = '10000' -var recipientId = 'AKKHPvQb2A119LNicCQWLZQDFxhGVEY57a' -AschJS.uia.createTransfer(currency, amount, recipientId, secret, secondSecret) -{ - "type": 14, - "amount": 0, - "fee": 10000000, - "recipientId": "AKKHPvQb2A119LNicCQWLZQDFxhGVEY57a", - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "timestamp": 19481489, - "asset": { - "uiaTransfer": { - "currency": "IssuerName.CNY", - "amount": "10000" - } - }, - "signature": "77789071a2ad6d407b9d1e0d654a9deb6d85340a3d2a13d786030e26ac773b4e9b5f052589958d2b8553ae5fc9449496946b5c225e0baa723e7ddecbd89f060a", - "signSignature": "f0d4a000aae3dd3fa48a92f792d4318e41e3b56cdbaf98649261ae34490652b87645326a432d5deb69f771c133ee4b67d2d22789197be34249e6f7f0c30c1705" -} -``` - -### **4.7 Asset write-off, type=11** - -`uia.createTransfer(currency, amount, recipientId, secret, secondSecret)` -`remark` The transaction-type in the main chain for this operation is 11 - -- `currency` Asset name -- `flagType` Whether the assets write-off, 1: circulation, 2: cancellation -- `flag` flag is for black and white list mode - -```js -var currency = 'IssuerName.CNY' -var flagType = 2 -var flag =1 - -AschJS.uia.createFlags(currency, flagType, flag, secret, secondSecret) -{ - "type": 11, - "amount": 0, - "fee": 10000000, - "recipientId": null, - "senderPublicKey": "fafcd01f6b813fdeb3c086e60bc7fa9bfc8ef70ae7be47ce0ac5d06e7b1a8575", - "timestamp": 19488690, - "asset": { - "uiaFlags": { - "currency": "IssuerName.CNY", - "flagType": 2, - "flag": 1 - } - }, - "signature": "cbd656552417604704703e1236ec2bbed8eba6a2ccfcb54cc0b2d629c0a9d1335a264fc9f6dee1705f4a86c36a5ce2ba8e039d913a189b7c273c8ac0d9e3780c", - "signSignature": "3c7b91d03efeed2dc86e1f2301da60789751c1be8850460d8c66c0ae8f55ea27d26f0bc79541d74b4777d9b85c518c1c73c0284dbf3e826db0a686560e57a80b" -} -``` - -## **5 Delegate** -### **5.1 Registere delegate, type=2** - -`delegate.createDelegate(username, secret, secondSecret)` -`remark` The transaction-type in the main chain for this operation is 2 - -- `username` Delegate name -- `secret` password -- `secondSecret` second password - -```js -var userName='zhenxi' -undefined -AschJS.delegate.createDelegate(userName, secret, secondSecret || undefined) -{ - type: 2, - amount: 0, - fee: 10000000000, - recipientId: null, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - timestamp: 40568017, - asset: { - delegate: { - username: 'zhenxi', - publicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed' - } - }, - signature: 'e471ade7ded7785f597821f8946d4e98da5ba4331505141c5bea5ff80bbf30b649218ef03254ac703ce93e15207c8b71c69c0d1400cb5790440860ed0e51a30a', - signSignature: 'ec47d565a70e6ad075abaf1ff55c129bde9495e4cc7ab2a9404b698ef257f3b1cfd0ce4f9f1854a1bbfec0f663867823a544f80964e3be05ddf03a50a9b77d07', - id: '774ccf5e7d9d9fefa459b23d96e10ffae4bb891e1e07912ac1370af04192e810' -} -``` - -### **5.2 Vote or cancel vote for delegate, type=3** - -`vote.createVote(keyList, secret, secondSecret)` -`remark` The transaction-type in the main chain for this operation is 3 - -- `keyList` list of delegate's public keys -- `secret` password -- `secondSecret` second password - -```js -// voting works as shown below as a array with a symbol ('+'/'-') and a public key for each delegate. The '+' symbol votes for a person the '-' symbol cancels the vote for this delegate. -var voteContent = [ -... '-ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7', -... '+c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2' -... ]; -undefined - -transaction=AschJS.vote.createVote(voteContent, secret, secondSecret || undefined); -{ - type: 3, - amount: 0, - fee: 10000000, - recipientId: null, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - timestamp: 40568669, - asset: { - vote: { - votes: [Array] - } - }, - signature: '66f6f3c4fbb8545df53ea35ff655fc1a28815591885757d0b735e77ed348caf33d8d9cb2895f85cd40bf2d3b4633f45a19ebd1dd130233305a603304a92ce003', - signSignature: 'c026d373e026b524efd82ad1ab046708ee1ff68573f016490d12908f5ad00a97fa7501f46834c94f6dd64afd00aa77f9d29ded087977ac6601778d4aacb5cd0e', - id: '0789524787384e2e4da7773afdd3871193a67303c4da69c4a9070eaa5676d36c' -} - -transaction.asset.vote.votes [ - '-ae256559d06409435c04bd62628b3e7ea3894c43298556f52b1cfb01fb3e3dc7', - '+c292db6ea14d518bc29e37cb227ff260be21e2e164ca575028835a1f499e4fe2' -] -``` - - -## **6 Dapp** - -### **6.1 Dapp registration, type=5** - -`dapp.createDApp(options, secret, secondSecret)` -`remark` The transaction-type in the main chain for this operation is 5 - -- `options` Basic dapp related attributes, such as name, url, icon, initial delegates public key, dapp type, dapp tag and other information -- `secret` password -- `secondSecret` second password - -```js -var options = { -... name: 'asch-dapp-cctime', -... link: 'https://github.com/AschPlatform/asch-dapp-cctime/archive/master.zip', -... category: 1, -... description: 'Decentralized news channel', -... tags: 'asch,dapp,demo,cctime', -... icon: 'http://o7dyh3w0x.bkt.clouddn.com/hello.png', -... type: 0, -... delegates: -... [ '8b1c24a0b9ba9b9ccf5e35d0c848d582a2a22cca54d42de8ac7b2412e7dc63d4', -... 'aa7dcc3afd151a549e826753b0547c90e61b022adb26938177904a73fc4fee36', -... 'e29c75979ac834b871ce58dc52a6f604f8f565dea2b8925705883b8c001fe8ce', -... '55ad778a8ff0ce4c25cb7a45735c9e55cf1daca110cfddee30e789cb07c8c9f3', -... '982076258caab20f06feddc94b95ace89a2862f36fea73fa007916ab97e5946a' ], -... unlockDelegates: 3 -}; -undefined - -trs = AschJS.dapp.createDApp(options, secret); -{ - type: 5, - amount: 0, - fee: 10000000000, - recipientId: null, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - timestamp: 40572296, - asset: { - dapp: { - category: 1, - name: 'asch-dapp-cctime', - description: 'Decentralized news channel', - tags: 'asch,dapp,demo,cctime', - type: 0, - link: 'https://github.com/AschPlatform/asch-dapp-cctime/archive/master.zip', - icon: 'http://o7dyh3w0x.bkt.clouddn.com/hello.png', - delegates: [Array], - unlockDelegates: 3 - } - }, - signature: '5a8e2dba5e14b4ec62ce1b8543de2796d3cded249ed899c5049dd0adeff00963dd40436e7cfc6f9952e09d5c6ac8f5144d3e568f263586520c68012d3c7ca509', - id: 'ecf9366a128408b843f0e6b2bd7261a4d602c32ae36a8c3cef609e904f180735' -} - -trs.asset.dapp.delegates -[ '8b1c24a0b9ba9b9ccf5e35d0c848d582a2a22cca54d42de8ac7b2412e7dc63d4', - 'aa7dcc3afd151a549e826753b0547c90e61b022adb26938177904a73fc4fee36', - 'e29c75979ac834b871ce58dc52a6f604f8f565dea2b8925705883b8c001fe8ce', - '55ad778a8ff0ce4c25cb7a45735c9e55cf1daca110cfddee30e789cb07c8c9f3', - '982076258caab20f06feddc94b95ace89a2862f36fea73fa007916ab97e5946a' ] -``` - -### **6.2 Dapp recharge, type=6** - -`transfer.createInTransfer(dappid, currency, amount, secret, secondSecret);` -`remark` The transaction-type in the main chain for this operation is 6 - -- `dappid` id of dapp -- `currency` Recharge the name of the asset -- `amount` The amount to recharge - -```js -var dappid = "bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024"; -var currency = "XAS"; -var amount = 10*100000000 ; - -AschJS.transfer.createInTransfer(dappid, currency, amount, secret, secondSecret || undefined); -{ - type: 6, - amount: 1000000000, - fee: 10000000, - recipientId: null, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - timestamp: 40578327, - asset: { - inTransfer: { - dappId: 'bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024', - currency: 'XAS' - } - }, - signature: '6907c1402c702e0fd504a8734a047c1bb216d437e65d5675325846b92ef8b916fc634ea7e33a7c72c60c058d1496d0385c95e39a8291e27b2dceb2f40b6aed02', - signSignature: '86de438431c639124a13429e8c6a8c13a5cbbbab3a8323ae08b56f65faeff6d816815d7cdecfdb7287077b14e4d14865637efc9d7fd72d085b0aa9d82f27170c', - id: '25be71c296430a409cfeaf1ffaa957d18793f3695db07a846c22a7c467c45994' -} -``` - -### **6.3 Dapp internal contract call** - -`dapp.createInnerTransaction(options, secret)` - -- `options` Contract related options such as commission, contract number, contract string array parameters -- `secret` password - -Customize the following global variables for the following code demo - -```js -var fee = String(0.1 * 100000000); // Currently dapp built-in contract calls the unified fee of 10,000,000 corresponding to the assets -``` - -#### **6.3.1 Dapp cash, contract type=2** - -`args` '["Asset name","Withdrawal amount"]' - -```js -var type = 2; // The type here refers to the contract number, not the main transaction-type -var options = {fee: fee, type: type, args: '["CCTime.XCT", "100000000"]'}; - -AschJS.dapp.createInnerTransaction(options, secret); -{ - fee: '10000000', - timestamp: 40572732, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - type: 2, - args: '["CCTime.XCT", "100000000"]', - signature: 'a0d860a0c13cf40d6be08f42a66bf01264f96fadc8ed2997139c583ba7fcd5e7ceeda9207c635215ddfd60bde8c35914cdfe2b03a4862cdd187b9142d497c301' -} -``` - -#### **6.3.2 Dapp internal transfer, contract type=3** - -`args` '["Asset name","Transfer amount","Receiving address"]' - -```js -var type = 3; -var options = {fee: fee, type: type, args: '["CCTime.XCT", "100000000", "A6H9rawJ7qvE2rKwQfdtBHdeYVehB8gFzC"]'}; - -AschJS.dapp.createInnerTransaction(options, secret); -{ - fee: '10000000', - timestamp: 40573272, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - type: 3, - args: '["CCTime.XCT", "100000000", "A6H9rawJ7qvE2rKwQfdtBHdeYVehB8gFzC"]', - signature: '3843bef77ad7c6f2b57083270055720186b8ba286cd44e263028eef9b8650ecf6d243c1861f9b9416e123b594695934430deb0f5146a173ebfcdccb6915acf0c' -} -``` - -#### **6.3.4 Set a dapp nickname, contract type=3** - -`args` '["nickname"]' - -```js -var type = 4; -var options = { fee: fee, type: type, args: '["nicheng"]' }; - -AschJS.dapp.createInnerTransaction(options, secret); -{ - fee: '10000000', - timestamp: 40573343, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - type: 4, - args: '["nicheng"]', - signature: '172998ddbb2ef72037be673d658dbc64760da307d451257666c956868b142707cd4aa38668b52d1d0d7cc62c01866daef2bae8d427844194d42ca9fea97ea70b' -} -``` - -### **6.4 Dapp withdraw** -#### **6.4.1 Create a cash transaction, type=7** - -`transfer.createOutTransfer(recipientId, dappId, transactionId, currency, amount, secret, secondSecret)` -`remark` The transaction-type in the main chain for this operation is 7. This interface is typically called by the dapp delegate (the delegate scans the cash transaction created by the smart contract on the sidechain every 10 seconds, and when found, creates a type = 7 cash transaction in the main chain) - - -- `recipientId` Receiptient Id -- `dappId` dapp id -- `transactionId` Transaction id, which is the smart contract number 2 created on the sidechain -- `currency` Withdraw the asset (XAS or UIA) -- `amount` Withdrawal amount - -```js -let recipientId = 'AFUH568CbGC2GPcE4gXHiZhxdYQYfziz2J'; -let dappId = 'bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024'; -let transactionId = '123b04a6e380500903d8942622d57987661e72b2ae95464066d0af3f02c3c691'; -let currency = 'XAS' -let amount = '10000000' - -var transaction = AschJS.transfer.createOutTransfer(recipientId, dappId, transactionId, currency, amount, secret, secondSecret); -{ - type: 7, - amount: 0, - fee: 10000000, - recipientId: 'AFUH568CbGC2GPcE4gXHiZhxdYQYfziz2J', - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - timestamp: 40668981, - asset: { - outTransfer: { - dappId: 'bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024', - transactionId: '123b04a6e380500903d8942622d57987661e72b2ae95464066d0af3f02c3c691', - currency: 'XAS', - amount: '10000000' - } - }, - signature: '432d25e5c5b81fa3a5937adca2dd4a1e2a38e51f8896838601902e0c123a5ccb664bbc8a55344b9fedb773da98e0988e4e8d1ca99dcbc51a80ea3bc9a6b61806', - signSignature: '8154c1f8305b9b957974e778de1e08dd3f08afcb70f27624d1385dbae9dfa6d0a3aaed6211ed8a40f4015f7e47312f0f205d94518c68e4deec8d76567f56f10f', - id: '237925a60ccc0abfc1494720aab8c11c74ba61e8ab3ca4bd8ded8c3215c201a7' -} -``` - -#### **6.4.2 The delegate signs the cash transaction** - -`transfer.signOutTransfer(transaction, secret)` -`remark` For the Dapp cash transactions more than one trustee must sign the transaction. The minimum number of trustee signatures depends on dapp's registration parameters: unlockDelegates. The trustee scans the cash transaction created by the smart contract on the sidechain every 10 seconds and signs the transaction if there is a transaction and the number of signatures is not met. - -- `transaction` the withdrawal transaction is generated with a call to transfer.createOutTransfer -- `secret` delegate password - -```js -// Follow the previous section Create a cash transaction, type=7" variable -transaction.signatures = [] // delegate signature list - -// The first delegate signs the cash transaction -delegate1_secret = 'chalk flame jeans rebuild dutch stone abstract capital lucky pottery raven depend' -signature1 = AschJS.transfer.signOutTransfer(transaction,delegate1_secret); -'ac0ea4c10b911f2134e5adfb3535ffc070ffa8f2858a5a1bc4e9bef442863e117e6bce552bba0d5b0160c4076dd3c657ebc33cbe077a8ef719798a8bb0fac30c' -transaction.signatures.push(signature1) // Add the signature to the transaction's signature list -// The second delegate signs the cash transaction -delegate2_secret = 'twist arrange matter twice daughter cave cause never enough scare warfare uncover' -signature2 = AschJS.transfer.signOutTransfer(transaction,delegate2_secret); -'480e0717e4be02e48a27e2323bf6507c4c72d1033b4e7e674651e9e4feced17836f0b81b91ade99b61620a2766ecc901f090d81cc72d22b86807ae981eb2d10c' -transaction.signatures.push(signature2) // Add the signature to the transaction's signature list -// By analogy, multiple delegates sign the transaction and the take-over transaction takes effect when the minimum number of signatures is satisfied -transaction -{ - type: 7, - amount: 0, - fee: 10000000, - recipientId: 'AFUH568CbGC2GPcE4gXHiZhxdYQYfziz2J', - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - timestamp: 40669013, - asset: { - outTransfer: { - dappId: 'bebe3c57d76a5bbe3954bd7cb4b9e381e8a1ba3c78e183478b4f98b9d532f024', - transactionId: '123b04a6e380500903d8942622d57987661e72b2ae95464066d0af3f02c3c691', - currency: 'XAS', - amount: '10000000' - } - }, - signature: '1dfae733408d374cd7be5f4b55183c0c05dc31341f93daaf82c26c80ab11035202502180dd78c5643edcd3bb481a38f352408bc35e44e6c1c53c95612fbca804', - signSignature: '8f4f7aa06c02c0a3d637329e1a3b23489b91797b9f3477afd4314b2f78d1e8e8a369a640d75916bd9477e69363cf440c27124db615dced1701a1a934714afe05', - id: '95a0c4ac9d5397452629b89410413f54ed37caee84a13edf3c9c26d3d0606dab', - signatures: - [ 'ac0ea4c10b911f2134e5adfb3535ffc070ffa8f2858a5a1bc4e9bef442863e117e6bce552bba0d5b0160c4076dd3c657ebc33cbe077a8ef719798a8bb0fac30c', - '480e0717e4be02e48a27e2323bf6507c4c72d1033b4e7e674651e9e4feced17836f0b81b91ade99b61620a2766ecc901f090d81cc72d22b86807ae981eb2d10c' ] // 受托人签名数组 -} -``` - - -## **7 Storage** - -### **7.1 Create a storage transaction,type=8** - -`storage.createStorage(content, secret, secondSecret)` -`remark` The transaction-type in the main chain for this operation is 8 - -- `content` - - -```js -var content = new Buffer('helloworld').toString('hex') -AschJS.storage.createStorage(content, secret, secondSecret) -{ - type: 8, - amount: 0, - fee: 10000000, - recipientId: null, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - timestamp: 40578932, - asset: { - storage: { - content: '68656c6c6f776f726c64' - } - }, - signature: 'd7f3f29549542d6716bdb13e8e1f97e3965c6fbe34f1ee18dbdcad7ba9cbf83ee7cb2b7fcbaab5ffed5d569771731bb5a40efc4fabd142cb30becdad8bc8bb06', - signSignature: '38315bf369540cc7a793139b1b6195f4c0e1512514d62bf028d454182a4b7a8912c1b1e6f617f6fb4ff8d80bd141a2ebb9dfcaa8fee68cfc81f8872611bba803', - id: '4d0b04a6e380500903d8942622d57987661e72b2ae95464066d0af3f02c3c691' -} -``` - -## **8 Related to signature verification, crypto** - -Customize the signed transfer transaction (transfer 100 XAS to 16358246403719868041 in the main chain) for the demo purpose. - -```js -var targetAddress = "16358246403719868041"; -var amount = 100*100000000; //100 XAS -var message = 'beizhu'; -transaction = AschJS.transaction.createTransaction(targetAddress, amount, message, secret, secondSecret) -{ - type: 0, - amount: 10000000000, - fee: 10000000, - recipientId: '16358246403719868041', - message: 'beizhu', - timestamp: 40566970, - asset: {}, - senderPublicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - signature: '9bef374be100fcfec59d245af59e5646ba5dcb79c6f1399ddd676a617542eeb45cc363822b84410e379f0caa501c25b66e59142353c04d23d1cb95cf64cef306', - signSignature: '513e3efdbb65f8e60e85ca98d8d065ec9bd3bfa6f45a1f48cfade9c94d410338ee64bd55938c168b10f0749335c050312785dbf08882ffd0e40a65fde8c2b10b', - id: '871554a8346d84cab2147324706d8ab5494fde928a7463a68d536ed6c0357897' -} -``` - -### **8.1 Get transaction bytes** - -`getBytes(transaction, skipSignature, skipSecondSignature)` - -- `transaction` The content of the transaction can be signed or unsigned, and the signed transaction is required by default. -- `skipSignature` Whether to skip the signature calculation, the default is not skipped. Non-mandatory parameters -- `skipSecondSignature` Whether to skip the secondary password signature calculation, the default is not skipped. Non-mandatory parameters - -```js -// Transaction.signature and transaction.signSignature are counted -AschJS.crypto.getBytes(transaction) - // The returned byte buffer -``` - -### **8.2 Get Transaction Hash** - -`getHash(transaction, skipSignature, skipSecondSignature)` - -- `transaction` The content of the transaction can be signed or unsigned, and the signed transaction is required by default. -- `skipSignature` Whether to skip the signature calculation, the default is not skipped. Non-mandatory parameters -- `skipSecondSignature` Whether to skip the secondary password signature calculation, the default is not skipped. Non-mandatory parameters - - -```js -// Transaction.signature and transaction.signSignature are counted -AschJS.crypto.getHash(transaction) - // the hash buffer which was returned -``` - -### **8.3 Get transaction id based on transaction content** - -`crypto.getId(transaction)` - -- `transaction` Signed transaction content - -```js -AschJS.crypto.getId(transaction) -'871554a8346d84cab2147324706d8ab5494fde928a7463a68d536ed6c0357897' // Return result, transaction id -``` - -### **8.4 Sign the transaction bytes** - -`crypto.signBytes(bytes, keys)` - -- `bytes` Transaction Bytes, unsigned transactions or primary password signatures but secondary password unsigned transactions -- `keys` Public key / private key pair - -```js -// Define unsigned transactions -var trs = { -... type: 0, -... amount: 10000000000, -... fee: 10000000, -... recipientId: '16358246403719868041', -... message: 'beizhu', -... timestamp: 40566970, -... asset: {} -} - -// created from the password -keys = AschJS.crypto.getKeys(secret) -{ - publicKey: 'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed', - privateKey: '7ae536fa343281d9e9ed383e8b5ef62e0fd0d0cbed79786cac241d484e312fdeebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed' -} - -trs.senderPublicKey = keys.publicKey; -'ebd4c62ebe2255b7ad5ee43120a9f9191c76e30928c92cd536351e3cc2c626ed' - -// Get the transaction byte buffer -buf = AschJS.crypto.getBytes(trs) - -// 通过私钥对交易Bytes Buffer进行签名 -signature = AschJS.crypto.signBytes(buf,keys) -'9bef374be100fcfec59d245af59e5646ba5dcb79c6f1399ddd676a617542eeb45cc363822b84410e379f0caa501c25b66e59142353c04d23d1cb95cf64cef306' // 返回值与上面自定义的已签名交易中的签名一致 -``` - -### **8.5 Verify that the transaction signature is consistent with the existing signature** - -`crypto.verifyBytes(bytes, signature, publicKey)` 返回true/false - -- `bytes` Transaction Bytes Buffer, unsigned transactions or primary password signatures but secondary password unsigned transactions -- `signature` Signature to be verified -- `publicKey` Signer public key - -```js -// Follow the previous section, "Sign Trading Bytes Buffer" variables -AschJS.crypto.verifyBytes(buf, transaction.signature,transaction.senderPublicKey) -true // The top of this chapter custom transaction signature -``` - -## **9 Miscellaneous** - -### **9.1 Global parameters** - -#### **9.1.1 Set the variable k/v** -`options.set(key, values)` - -- `key` Key name -- `value` Key value - -```js -AschJS.options.set('secret', 'minor borrow display rebel depart core buzz right distance avocado immense push') -undefined -``` - - -#### **9.1.2 According to the key for value** - -`options.get(key)` - -- `key` key - -```js -AschJS.options.get('secret') -'minor borrow display rebel depart core buzz right distance avocado immense push' -``` - - -#### **9.1.3 Get all k/v** - -`options.getAll()` - -```js -AschJS.options.getAll() -{ - clientDriftSeconds: 5, // asch-js built in variables - secret: 'minor borrow display rebel depart core buzz right distance avocado immense push' -} -``` - -### **9.2 Time related slot.time** - -#### **9.2.1 Asch main network creation block generation time** - -`utils.slots.beginEpochTime()` -`remark` The result is UTC time, the beginning of the Asch era. - -```js -AschJS.utils.slots.beginEpochTime() -2016-06-27T20:00:00.000Z // Asch main network creation time, but the main network is officially running on August 16 that day (the main network is running the logo is generated block heihgt = 2 block) -``` - - -#### **9.2.2 Get Asch timestamp based on unix timestamp** - -`utils.slots.getTime(time)` -`remark` The result is called EpochTim (Asch timestamp), the time passed in relation to the number of seconds experienced by the Asch era - -- `time` If you do not pass the current time Unix timestamp * 1000 (ie milliseconds) - -```js -AschJS.utils.slots.getTime() -40655681 // Asch time stamp - -unix_timestamp = 1507713496 -epochTime = AschJS.utils.slots.getTime(unix_timestamp * 1000) -40655896 // Asch time stamp -``` - -#### **9.2.3 Get the unix timestamp based on the Asch timestamp** - -`utils.slots.getRealTime(epochTime)` -`remark` The result is a real unix timestamp * 1000 - -- `epochTime` Asch timestamp in seconds - -```js -unix_timestamp = 1507713496 // unix timestamp -epochTime = AschJS.utils.slots.getTime(unix_timestamp * 1000) -40655896 // Obtained by the unix timestamp asch timestamp -real_time = AschJS.utils.slots.getRealTime(epochTime) -1507713496000 // Get the unix timestamp by asch timestamp - -unix_timestamp === real_time/1000 -true // The conversion result is the same -``` diff --git a/docs/asch_sdk_api.md b/docs/asch_sdk_api.md deleted file mode 100644 index 3488ef4..0000000 --- a/docs/asch_sdk_api.md +++ /dev/null @@ -1,621 +0,0 @@ -Table of Contents -================= - - * [Asch SDK API 使用说明](#asch-sdk-api-使用说明) - * [1. 数据库](#1-数据库) - * [1.1 aync app.sdb.load(model, fields, indices)](#11-aync-appsdbloadmodel-fields-indices) - * [1.2 app.sdb.get(model, cond)](#12-appsdbgetmodel-cond) - * [1.3 app.sdb.keys(model)](#13-appsdbkeysmodel) - * [1.4 app.sdb.entries(model)](#14-appsdbentriesmodel) - * [1.5 ap.sdb.lock(key)](#15-apsdblockkey) - * [1.6 app.sdb.create(model, values)](#16-appsdbcreatemodel-values) - * [1.7 app.sdb.replace(model, values)](#17-appsdbreplacemodel-values) - * [1.8 app.sdb.update(model, modifier, cond)](#18-appsdbupdatemodel-modifier-cond) - * [1.9 app.sdb.increment(model, modifier, cond)](#19-appsdbincrementmodel-modifier-cond) - * [1.10 app.sdb.del(model, cond)](#110-appsdbdelmodel-cond) - * [2. 余额](#2-余额) - * [2.1 app.balances.get(address, currency)](#21-appbalancesgetaddress-currency) - * [2.2 app.balances.increase(address, currency, amount)](#22-appbalancesincreaseaddress-currency-amount) - * [2.3 app.balances.decrease(address, currency, amount)](#23-appbalancesdecreaseaddress-currency-amount) - * [2.4 app.balances.transfer(currency, amount, from, to)](#24-appbalancestransfercurrency-amount-from-to) - * [3 数据模型](#3-数据模型) - * [3.1 app.model[name]](#31-appmodelname) - * [3.2 fields()](#32-fields) - * [3.3 count(cond)](#33-countcond) - * [3.4 exists(cond)](#34-existscond) - * [3.5 findOne(options)](#35-findoneoptions) - * [3.6 findAll(options)](#36-findalloptions) - * [4. 路由](#4-路由) - * [4.1 app.route.get(path, handler)](#41-approutegetpath-handler) - * [4.2 app.route.post(path, handler)](#42-approutepostpath-handler) - * [4.3 app.route.put(path, handler)](#43-approuteputpath-handler) - * [5. 费用池](#5-费用池) - * [5.1 app.feePool.add(currency, amount)](#51-appfeepooladdcurrency-amount) - * [6. 自增ID](#6-自增id) - * [6.1 app.autoID.get(name)](#61-appautoidgetname) - * [6.2 app.autoID.increment(name)](#62-appautoidincrementname) - * [7. 日志](#7-日志) - * [7.1 app.logger.setLevel(level)](#71-apploggersetlevellevel) - * [7.2 app.logger.log()](#72-apploggerlog) - * [7.3 app.logger.trace()](#73-apploggertrace) - * [7.4 app.logger.debug()](#74-apploggerdebug) - * [7.5 app.logger.info()](#75-apploggerinfo) - * [7.6 app.logger.warn()](#76-apploggerwarn) - * [7.7 app.logger.error()](#77-apploggererror) - * [8. 工具类](#8-工具类) - * [8.1 app.validate(type, value)](#81-appvalidatetype-value) - * [8.2 app.registerContract(type, name)](#82-appregistercontracttype-name) - * [8.3 app.getContractName(type)](#83-appgetcontractnametype) - * [8.4 app.registerFee(type, min, currency)](#84-appregisterfeetype-min-currency) - * [8.5 app.getFee(type)](#85-appgetfeetype) - * [8.6 app.setDefaultFee(min, currency)](#86-appsetdefaultfeemin-currency) - * [8.7 app.getRealTime(epochTime)](#87-appgetrealtimeepochtime) - * [8.8 app.registerHook](#88-appregisterhook) - * [8.9 app.custom[]](#89-appcustom) - -Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc) - - -# Asch SDK API 使用说明 - - -## **1. 数据库** - -### 1.1 `aync` app.sdb.load(model, fields, indices) - -- `model` 模型名称 -- `fields` 加载到内存中的字段 -- `indices` 索引数组, 单字段索引时, 元素为字符串; 多字段索引时, 元素为字符串数组 - -> 无返回值, 出现错误时抛异常 -> 将指定模型的数据加载到内存并建立索引, 这样可以提高查询和更新一个状态的效率 -> 当一个数据模型需要频繁更新和查询时, 建议使用这个接口, 比如系统内置的账户余额、自增ID都使用了这个功能 - -示例: - -``` -await app.sdb.load('Balance', app.model.Balance.fields(), [['address', 'currency']]) -await app.sdb.load('Variable', ['key', 'value'], ['key']) -``` - -### 1.2 app.sdb.get(model, cond) - -- `model` 模型名称 -- `cond` 查询条件 - -> 返回一个数据项, 包含的字段为`load`时指定的字段 -> 按指定条件查询内存中的数据, 如果该模型没有被载入内存, 会抛出异常; 查询条件包换未建索引的字段时也会抛出异常 - -示例: - -``` -app.sdb.get('Variable', { key: 'foo' }) -/* output: -{ - key: 'foo', - value: 'bar' -} -*/ - -let balance = app.sdb.get('Balance', { address: 'foo', currency: 'XAS' }) -/* output: -{ - address: 'foo', - currency: 'XAS', - balance: '1000000' -} -*/ -``` - -### 1.3 app.sdb.keys(model) - -- `model` 模型名称 - -> 返回一个数据模型的全部索引字段 - -示例: - -``` -let keys = app.sdb.keys('Variable') -for (let i of keys) { - console.log(i) -} -/* output: -foo -foo1 -foo2 -*/ -``` - - -### 1.4 app.sdb.entries(model) - -- `model` 模型名称 - -> 返回一个数据模型的所有缓存项 - -示例: - -``` -let entries = app.sdb.entries('Variable') -for (let [key, value] of entries) { - console.log(key, value) -} -/* output: -foo bar -foo1 bar1 -foo2 bar2 -*/ -``` - -### 1.5 ap.sdb.lock(key) - -- `key` - -> 无返回值 -> 对一个key进行加锁, 有效期为一个区块间隔, 在同一个区块生命周期内不允许对一个key二次加锁, 否则会抛异常 -> 该功能主要是为了解决对未确认数据的依赖问题。比如, 一个合约中需要对某账户设置昵称, 在这个合约调用被确认之前, 我们需要防止再次调用, 这种情况下可以使用加锁功能 - -示例: - -``` -app.sdb.lock('AC3pinmvz9qX9cj6c7VrGigq7bpPxVJq85@nickname' -``` - -### 1.6 app.sdb.create(model, values) - -- `model` 模型名称 -- `values` 待创建的数据项 - -> 无返回值 -> 创建一个数据项, 如果该模型有缓存, 会实时更新缓存. 在区块确认后, 持久化到磁盘数据库 - -示例: - -``` -app.sdb.create('Article', { - title: 'This is an article title', - content: 'article contents', - author: 'qingfeng', - tag: 'Science' -}) -``` - -### 1.7 app.sdb.replace(model, values) - -- `model` 模型名称 -- `values` 待创建或更新的数据项 - -> 无返回值 -> 创建或更新一个数据项, 如果数据库中无此项则创建, 否则更新. 模型必须包含主键, `values`必须包含主键 - -示例: - -``` -app.sdb.replace('Account', { - address: 'AC3pinmvz9qX9cj6c7VrGigq7bpPxVJq85', - nickname: 'Nakamoto' -}) -``` - -### 1.8 app.sdb.update(model, modifier, cond) - -- `model` 模型名称 -- `modifier` 待更新的数据项 -- `cond` 更新条件 - -> 无返回值 -> 按指定条件更新一个模型的若干个数据项 - -示例: - -``` -app.sdb.update('Account', { nickname: 'Nakamoto' }, { nickname: 'Satoshi' }) -``` - -### 1.9 app.sdb.increment(model, modifier, cond) - -- `model` 模型名称 -- `modifier` 待更新的数据项 -- `cond` 更新条件 - -> 按指定条件增量更新一个模型的若干个数据项, 只能用于更新整数类型 - -示例: - -``` -app.sdb.increment('Article', { votes: -10 }, { id: '10000' }) -app.sdb.increment('Article', { comments: 1 }, { id: '10000' }) -``` - -### 1.10 app.sdb.del(model, cond) - -- `model` 模型名称 -- `cond` 删除条件 - -> 无返回值 -> 按条件删除一个模型中的数据项 -> 删除操作的底层实现目前是标记为deleted, 默认的查询接口都会过滤掉被标记的数据, 但非标准接口或协议仍然可以获取到这些已经被`删除`的数据 - -示例: - -``` -app.sdb.del('Article', { id: '100001' }) -``` - -## 2. 余额 - -### 2.1 app.balances.get(address, currency) - -- `address` 账户地址 -- `currency` 币种 - -> 获取指定账户、指定币种的余额 - -示例: - -``` -app.balances.get('AC3pinmvz9qX9cj6c7VrGigq7bpPxVJq85', 'XAS') -/* output: -{ - address: 'AC3pinmvz9qX9cj6c7VrGigq7bpPxVJq85', - currency: 'XAS', - balance: '10000000' -} -*/ -``` - -### 2.2 app.balances.increase(address, currency, amount) - -- `address` 账户地址 -- `currency` 币种 -- `amount` 增加的数额 - -> 无返回值 -> 增加指定账户、指定币种的余额 - -示例: - -``` -app.balances.increase('AC3pinmvz9qX9cj6c7VrGigq7bpPxVJq85', 'XAS', '100000') -``` - -### 2.3 app.balances.decrease(address, currency, amount) - -- `address` 账户地址 -- `currency` 币种 -- `amount` 减少的数额 - -> 无返回值 -> 减少指定账户、指定币种的余额 - -示例: - -``` -app.balances.decrease('AC3pinmvz9qX9cj6c7VrGigq7bpPxVJq85', 'XAS', '100000') -``` - -### 2.4 app.balances.transfer(currency, amount, from, to) - -- `currency` 币种 -- `amount` 转移的数额 -- `from` 源地址(发款人) -- `to` 目的地址(收款人) - -> 无返回值 -> 两个账户之间转移资产 - -示例: - -``` -app.balances.transfer('XAS', '100000', 'AC3pinmvz9qX9cj6c7VrGigq7bpPxVJq85', 'A4MFPoF3c9vCzZ3GGf9sNQ3rDy2q8aXuVF') -``` - -## 3 数据模型 - -### 3.1 app.model[name] - -- `name` 模型名称 - -> 返回一个模型的实例, 主要用于查询已确认的数据 - -### 3.2 fields() - -> 返回该模型所有字段 - -### 3.3 count(cond) - -- `cond` 查询条件 - -> 返回`Number` -> 表示指定条件的数据项总数 - -示例: - -``` -app.model.Block.count({ height: { $lt: 100 } }) -/* output: -99 -/* -``` - -### 3.4 exists(cond) - -- `cond` 查询条件 - -> 返回`Boolean` -> 表示指定条件的数据项是否存在 - -示例: - -``` -app.model.Transaction.exists({ id: '9a5ec0669c79b9f5a1d5a4dbb2c200bc28c9ea829dbff71f41cbb2ad5a7d9b01' }) -/* output: -false -/* - -app.model.Account.exists({ nickname: 'Nakamoto' }) -/* output: -true -*/ -``` - -### 3.5 findOne(options) - -`options`是一个对象, 包含以下元素 - -- `condition` 查询条件 -- `fields` 返回的字段 - -> 查询一个指定条件的数据项 - -示例: - -``` -app.model.Account.findOne({ nickname: 'Nakamoto' }) -/* output: -{ - address: 'AC3pinmvz9qX9cj6c7VrGigq7bpPxVJq85', - nickname: 'Nakamoto', - ...other values -} -*/ -``` - -### 3.6 findAll(options) - -`options`是一个对象, 包含以下元素 - -- `condition` 查询条件 -- `fields` 返回的字段 -- `sort` 排序字段 -- `limit` 返回的最大数量 -- `offset` 偏移量 - -> 查询指定条件的所有数据项 - -示例: - -``` -app.model.Transfer.findAll({ senderId: 'AC3pinmvz9qX9cj6c7VrGigq7bpPxVJq85'}) -/* output: -[ - { - tid: "50e062f25946d220b924cb5ec6e52e260e44c9417d9f3c8ea041b704e06895f7", - senderId: "AFnwUuET2XddPtqpFb2ns78CQEqc7KZ6vD", - recipientId: "asdasdasd", - currency: "CCTime.XCT", - amount: "100000000", - t_timestamp: 38660145, - t_type: 3, - t_height: 93953 - }, - { - tid: "f15ce92add809b4a132936d514dce7fa7bdc15e850e7c026a001625b48595af3", - senderId: "AFnwUuET2XddPtqpFb2ns78CQEqc7KZ6vD", - recipientId: "asdasd", - currency: "CCTime.XCT", - amount: "100000000", - t_timestamp: 38660096, - t_type: 3, - t_height: 93948 - } -] -*/ -``` - -## 4. 路由 - -- `path` 路径 -- `handler` http请求处理函数, async类型 - -### 4.1 app.route.get(path, handler) - -> 注册一个`get`类型的`http`请求处理函数 - -### 4.2 app.route.post(path, handler) - -> 注册一个`post`类型的`http`请求处理函数 - -### 4.3 app.route.put(path, handler) - -> 注册一个`put`类型的`http`请求处理函数 - -## 5. 费用池 - -### 5.1 app.feePool.add(currency, amount) - -- `currency` 币种 -- `amount` 数额 - -> 无返回值 -> 将资产加入费用池(在每一个`round`结尾平均分给记账人) - -示例: - -``` -app.feelPool.add('XAS', '10000000') -``` - -## 6. 自增ID - -### 6.1 app.autoID.get(name) - -- `name` ID类型名称 - -> 返回`String` -> 获取一个类型的当前最大ID - -### 6.2 app.autoID.increment(name) - -- `name` ID类型名称 - -> 返回`String` -> 对指定类型的ID增加1并以字符串形式返回更新后的数值, 相当于原子的`++1`, 超大数也适用 - -示例: - -``` -const AID = 'article_id' -app.autoID.get(AID) === '0' -app.autoID.increment(AID) === '1' -app.autoID.get(AID) === '1' -``` - -## 7. 日志 - -### 7.1 app.logger.setLevel(level) -### 7.2 app.logger.log() -### 7.3 app.logger.trace() -### 7.4 app.logger.debug() -### 7.5 app.logger.info() -### 7.6 app.logger.warn() -### 7.7 app.logger.error() - -示例: - -``` -app.logger.setLevel('debug') -app.logger.setLevel('info') - -logger.log('hello'); -logger.trace('hello', 'world'); -logger.debug('hello %s', 'world', 123); -logger.info('hello %s %d', 'world', 123, {foo:'bar'}); -logger.warn('hello %s %d %j', 'world', 123, {foo:'bar'}); -logger.error('hello %s %d %j', 'world', 123, {foo:'bar'}, [1, 2, 3, 4], Object); -``` - -## 8. 工具类 - -### 8.1 app.validate(type, value) - -- `type` 待验证的数据类型 -- `value` 待验证的数据值 - -> 验证一个数据是否符合规范, 不符合则抛出异常 - -示例: - -``` -app.validate('amount', '10000') // pase -app.validate('amount', 10000) // throws -app.validate('amount', 'abc') // throws -app.validate('amount', '1e10') // throws -``` - -### 8.2 app.registerContract(type, name) - -- `type` 合约数值类型或编号 -- `name` 合约的字符串名称 - -> 无返回值 -> 为合约注册一个数字类型, 未注册的合约无法被外部调用 - -示例: - -``` -app.registerContract(1001, 'cctime.postArticle') -``` - -### 8.3 app.getContractName(type) - -- `type` 合约的数字类型或编号 - -> 根据合约编号查询名称 - -示例: - -``` -app.getContractName(1001) === 'cctime.postArticle' -``` - -### 8.4 app.registerFee(type, min, currency) - -- `type` 合约的数字类型或编号 -- `min` 最小费用 -- `currency` 币种 - -> 为一个合约注册最小费用, 不固定资产, 可通过`currency`参数指定收哪种资产作为手续费 -> `min`表示最小费用, 实际调用合约的时候, 费用不能小于`min`, 但可以大于, 超过的部分自动放入费用池 - -示例: - -``` -app.registerFee(1001, '100000', 'XAS') -``` -### 8.5 app.getFee(type) - -- `type` 合约的数字类型或编号 - -> 获取指定合约的费用设定 - -示例: - -``` -app.getFee(1001) -/* output: -{ - min: '100000', - currency: 'XAS' -} -*/ -``` - -### 8.6 app.setDefaultFee(min, currency) - -- `min` 最小费用 -- `currency` 币种 - -> 为系统的所有合约设置默认手续费 - -示例: - -``` -app.setDefaultFee('10000', 'XAS') -``` - -### 8.7 app.getRealTime(epochTime) - -- `epochTime` 距离创世区块生成时间的秒数 - -> 返回完整的时间戳, 即区块创世时间加上偏移量, 单位为毫秒 -> Asch系统中底层存储和上层查询的时间戳均为一个偏移量, 并非实际时间戳, 可以调用这个函数转换为真实的时间戳 - -示例: - -``` -app.getRealTime(4353634) -``` - -### 8.8 app.registerHook - -// TBD - -### 8.9 app.custom[] - -> 应用的名字空间, 可用来保存应用本身自定义的一些全局变量, 主要是为了与系统级的全局变量进行隔离 - - - - diff --git a/docs/asch_sdk_api_en.md b/docs/asch_sdk_api_en.md deleted file mode 100644 index c2d7ea2..0000000 --- a/docs/asch_sdk_api_en.md +++ /dev/null @@ -1,1017 +0,0 @@ - -# Table of Contents - - - -- [Table of Contents](#table-of-contents) -- [Asch SDK API](#asch-sdk-api) - - [**1. Database**](#1-database) - - [1.1 `aync` app.sdb.load(model, fields, indices)](#11-aync-appsdbloadmodel-fields-indices) - - [1.2 app.sdb.get(model, cond)](#12-appsdbgetmodel-cond) - - [1.3 app.sdb.keys(model)](#13-appsdbkeysmodel) - - [1.4 app.sdb.entries(model)](#14-appsdbentriesmodel) - - [1.5 ap.sdb.lock(key)](#15-apsdblockkey) - - [1.6 app.sdb.create(model, values)](#16-appsdbcreatemodel-values) - - [1.7 app.sdb.replace(model, values)](#17-appsdbreplacemodel-values) - - [1.8 app.sdb.update(model, modifier, cond)](#18-appsdbupdatemodel-modifier-cond) - - [1.9 app.sdb.increment(model, modifier, cond)](#19-appsdbincrementmodel-modifier-cond) - - [1.10 app.sdb.del(model, cond)](#110-appsdbdelmodel-cond) - - [2. Balance](#2-balance) - - [2.1 app.balances.get(address, currency)](#21-appbalancesgetaddress-currency) - - [2.2 app.balances.increase(address, currency, amount)](#22-appbalancesincreaseaddress-currency-amount) - - [2.3 app.balances.decrease(address, currency, amount)](#23-appbalancesdecreaseaddress-currency-amount) - - [2.4 app.balances.transfer(currency, amount, from, to)](#24-appbalancestransfercurrency-amount-from-to) - - [3 Data model](#3-data-model) - - [3.1 app.model[name]](#31-appmodelname) - - [3.2 fields()](#32-fields) - - [3.3 count(cond)](#33-countcond) - - [3.4 exists(cond)](#34-existscond) - - [3.5 findOne(options)](#35-findoneoptions) - - [3.6 findAll(options)](#36-findalloptions) - - [4. Routing](#4-routing) - - [4.1 app.route.get(path, handler)](#41-approutegetpath-handler) - - [4.2 app.route.post(path, handler)](#42-approutepostpath-handler) - - [4.3 app.route.put(path, handler)](#43-approuteputpath-handler) - - [5. Cost pool](#5-cost-pool) - - [5.1 app.feePool.add(currency, amount)](#51-appfeepooladdcurrency-amount) - - [6. Increment ID](#6-increment-id) - - [6.1 app.autoID.get(name)](#61-appautoidgetname) - - [6.2 app.autoID.increment(name)](#62-appautoidincrementname) - - [7. Logging](#7-logging) - - [7.1 app.logger.setLevel(level)](#71-apploggersetlevellevel) - - [7.2 app.logger.log()](#72-apploggerlog) - - [7.3 app.logger.trace()](#73-apploggertrace) - - [7.4 app.logger.debug()](#74-apploggerdebug) - - [7.5 app.logger.info()](#75-apploggerinfo) - - [7.6 app.logger.warn()](#76-apploggerwarn) - - [7.7 app.logger.error()](#77-apploggererror) - - [8. Tools](#8-tools) - - [8.1 app.validate(type, value)](#81-appvalidatetype-value) - - [8.2 app.registerContract(type, name)](#82-appregistercontracttype-name) - - [8.3 app.getContractName(type)](#83-appgetcontractnametype) - - [8.4 app.registerFee(type, min, currency)](#84-appregisterfeetype-min-currency) - - [8.5 app.getFee(type)](#85-appgetfeetype) - - [8.6 app.setDefaultFee(min, currency)](#86-appsetdefaultfeemin-currency) - - [8.7 app.getRealTime(epochTime)](#87-appgetrealtimeepochtime) - - [8.8 app.registerHook](#88-appregisterhook) - - [8.8.1 beforeCreateBlock](#881-beforecreateblock) - - [8.9 app.custom[]](#89-appcustom) - - [8.10 app.meta](#810-appmeta) - - - -# Asch SDK API - - -## **1. Database** - -### 1.1 `aync` app.sdb.load(model, fields, indices) - -- `model` Datamodel -- `fields` Fields of the data model -- `indices` Array of indexes, it can be a single field index or a multi field index (provide an string array) - -> The operation has no return value, it throws an Exception when an error occurs -> Load the data for the specified model into memory and index the table which can further improve the efficiency of the query -> When a data model needs frequent updates and inquiries, it is recommended to use this interface, such as the system's built-in account balance, the increment ID uses this operation - -Example: - -```js -await app.sdb.load('Balance', app.model.Balance.fields(), [['address', 'currency']]) -await app.sdb.load('Variable', ['key', 'value'], ['key']) -``` - -### 1.2 app.sdb.get(model, cond) - -- `model` Datamodel -- `cond` Query conditions - -> Returns the model that matched the query conditions -> Query the data according to the specified query condition. When the model can't be loaded an exception will be thrown. Query conditions will also throw an error if the key value is not indexed - -Example: - -```js -app.sdb.get('Variable', { key: 'foo' }) -/* output: -{ - key: 'foo', - value: 'bar' -} -*/ - -let balance = app.sdb.get('Balance', { address: 'foo', currency: 'XAS' }) -/* output: -{ - address: 'foo', - currency: 'XAS', - balance: '1000000' -} -*/ -``` - -### 1.3 app.sdb.keys(model) - -- `model` Model - -> This operation returns all indexed fields for a model - -Example: - -```js -let keys = app.sdb.keys('Variable') -for (let i of keys) { - console.log(i) -} -/* output: -foo -foo1 -foo2 -*/ -``` - - -### 1.4 app.sdb.entries(model) - -- `model` Model name - -> Returns all cached fields for a data model - -Example: - -```js -let entries = app.sdb.entries('Variable') -for (let [key, value] of entries) { - console.log(key, value) -} -/* output: -foo bar -foo1 bar1 -foo2 bar2 -*/ -``` - -### 1.5 ap.sdb.lock(key) - -- `key` - -> No return value -> Lock a key. This lock is valid for the timespan of a block interval. A block life cycle does not allow a second lock or an exception will be thrown. -> This features is to prevent a duplicate call in a block life cycle. For example: A contract needs to set a nickname for an account. Before the contract call is confirmed, we need to prevent that the nickname is set again. Therefore we can use the lock function. - -Example: - -```js -let senderId = 'AHMCKebuL2nRYDgszf9J2KjVZzAw95WUyB' -app.sdb.lock(`cctime.postArticle@${senderId}`) -``` - -### 1.6 app.sdb.create(model, values) - -- `model` Model -- `values` Data items that will be created - -> No return value -> This operation creates a data item that updates the cache in real time if the model is cached. After the block is confirmed, the data will be persisted in the database. - -Example: - -```js -app.sdb.create('Article', { - title: 'This is an article title', - content: 'article contents', - author: 'qingfeng', - tag: 'Science' -}) -``` - -### 1.7 app.sdb.replace(model, values) - -- `model` model -- `values` data item that will be created or updated - -> No return value -> Create or update the data model. If the data model already exists, update it. The parameter `values` must must contain the primary key. - -Example: - -```js -app.sdb.replace('Account', { - address: 'AC3pinmvz9qX9cj6c7VrGigq7bpPxVJq85', - nickname: 'Nakamoto' -}) -``` - -### 1.8 app.sdb.update(model, modifier, cond) - -- `model` Model -- `modifier` Data item that should be updated -- `cond` Update condition - -> No return value -> One or many data items of a model are updated according to the update condition. - -Example: - -```js -app.sdb.update('Account', { nickname: 'Nakamoto' }, { nickname: 'Satoshi' }) -``` - -### 1.9 app.sdb.increment(model, modifier, cond) - -- `model` Model -- `modifier` Data item that should be updated -- `cond` Update condition - -> Incremental update of a model by specified number. This can only be used to update integer types. - -Example: - -```js -app.sdb.increment('Article', { votes: -10 }, { id: '10000' }) -app.sdb.increment('Article', { comments: 1 }, { id: '10000' }) -``` - -### 1.10 app.sdb.del(model, cond) - -- `model` Model name -- `cond` Delete condition - -> No return value -> Delete data items in a model according to a query condition -> The implementation of the delete operation is currently marked as obsolete. This query interface will not delete model data. However, a custom implementation can still delete data. - -Example: - -```js -app.sdb.del('Article', { id: '100001' }) -``` - -## 2. Balance - -### 2.1 app.balances.get(address, currency) - -- `address` Account address -- `currency` Currency - -> Returns the balance of the specified account - -Example: - -```js -app.balances.get('AC3pinmvz9qX9cj6c7VrGigq7bpPxVJq85', 'XAS') -/* output: -{ - address: 'AC3pinmvz9qX9cj6c7VrGigq7bpPxVJq85', - currency: 'XAS', - balance: '10000000' -} -*/ -``` - -### 2.2 app.balances.increase(address, currency, amount) - -- `address` Account address -- `currency` Currency -- `amount` Amount to increase - -> No return value -> This operation raises the balance of the address by `amount` (amount to increase). - -Example: - -```js -app.balances.increase('AC3pinmvz9qX9cj6c7VrGigq7bpPxVJq85', 'XAS', '100000') -``` - -### 2.3 app.balances.decrease(address, currency, amount) - -- `address` Account address -- `currency` Currency -- `amount` Amount to subtract - -> No return value -> This operation subtracts the `amount` of the balance. - -Example: - -```js -app.balances.decrease('AC3pinmvz9qX9cj6c7VrGigq7bpPxVJq85', 'XAS', '100000') -``` - -### 2.4 app.balances.transfer(currency, amount, from, to) - -- `currency` Currency -- `amount` Amount to transfer -- `from` Sender -- `to` Recipient - -> No return value -> Transfers assets between two accounts - -Example: - -```js -app.balances.transfer('XAS', '100000', 'AC3pinmvz9qX9cj6c7VrGigq7bpPxVJq85', 'A4MFPoF3c9vCzZ3GGf9sNQ3rDy2q8aXuVF') -``` - -## 3 Data model - -### 3.1 app.model[name] - -- `name` Model name - -> Returns an instance of the model - -### 3.2 fields() - -> Returns all fields of the model - -```js -app.model.Article.fields() -/* output: -[ - 'id', - 'tid', - 'authorId', - 'timestamp', - 'title', - 'url', - 'text', - 'tags', - 'votes', - 'comments', - 'reports' -] -*/ -``` - -### 3.3 count(cond) - -- `cond` Query condition - -> Returns a `Number` -> The total number of data items that match the specified condition. - -Example: - -```js -app.model.Block.count({ height: { $lt: 100 } }) -/* output: -99 -/* -``` - -### 3.4 exists(cond) - -- `cond` Query condition - -> Returns a `Boolean` -> Indicates whether the data item for the specified condition exists. - -Example: - -```js -app.model.Transaction.exists({ id: '9a5ec0669c79b9f5a1d5a4dbb2c200bc28c9ea829dbff71f41cbb2ad5a7d9b01' }) -/* output: -false -/* - -app.model.Account.exists({ nickname: 'Nakamoto' }) -/* output: -true -*/ -``` - -### 3.5 findOne(options) - -`options` Is an object that has the following properties: - -- `condition` Query conditions -- `fields` The field that should be returned - -> Query data items for a specified condition. - -Example: - -```js -app.model.Account.findOne({ nickname: 'Nakamoto' }) -/* output: -{ - address: 'AC3pinmvz9qX9cj6c7VrGigq7bpPxVJq85', - nickname: 'Nakamoto', - ...other values -} -*/ -``` - -### 3.6 findAll(options) - -`options` Is an object that has the following properties: - -- `condition` Query condition -- `fields` Fields to return -- `sort` Fields to sort after -- `limit` The maximum number to return -- `offset` Offset - -> Query all data items for the specified condition - -Example: - -```js -app.model.Transfer.findAll({ senderId: 'AC3pinmvz9qX9cj6c7VrGigq7bpPxVJq85'}) -/* output: -[ - { - tid: "50e062f25946d220b924cb5ec6e52e260e44c9417d9f3c8ea041b704e06895f7", - senderId: "AFnwUuET2XddPtqpFb2ns78CQEqc7KZ6vD", - recipientId: "asdasdasd", - currency: "CCTime.XCT", - amount: "100000000", - t_timestamp: 38660145, - t_type: 3, - t_height: 93953 - }, - { - tid: "f15ce92add809b4a132936d514dce7fa7bdc15e850e7c026a001625b48595af3", - senderId: "AFnwUuET2XddPtqpFb2ns78CQEqc7KZ6vD", - recipientId: "asdasd", - currency: "CCTime.XCT", - amount: "100000000", - t_timestamp: 38660096, - t_type: 3, - t_height: 93948 - } -] -*/ -``` - -## 4. Routing - -- `path` Path -- `handler` Http Request Handler (async) - -### 4.1 app.route.get(path, handler) - -> Register a `get` type `http` request handler - - -Example: -```js -// file-name: interface/index.js -// Access this API endpoint with a GET call to `http://localhost:4096/api/dapps//articles` - -app.route.get('/articles', async (req) => { - - let articles = await app.model.Article.findAll({ - limit: 50, - offset: 0, - sort: { timestamp: -1 } - }) - - return articles -}) - -``` - -### 4.2 app.route.post(path, handler) - -> Register a `post` type `http` request handler - -### 4.3 app.route.put(path, handler) - -> Register a `put` type `http` request handler - -## 5. Cost pool - -### 5.1 app.feePool.add(currency, amount) - -- `currency` Currency -- `amount` Amount - -> No return value -> The specified asset (currency) is added to the fee pool (the amount is evenly distributed to all accountants at the end of each round). - -Example: - -```js -app.feelPool.add('XAS', '10000000') -``` - -## 6. Increment ID - -The creation of a table `articles` (with primary key id) results into the creation of a variable `article_max_id`. This new variable can be incremented. - -Example: -```js -// file-name: model/article.js -module.exports = { - name: 'articles', - fields: [ - { - name: 'id', - type: 'Number', - not_null: true, - primary_key: true - } - ] -} -``` - -![alt](./assets/dapp/dapp_variables_article_max_id.png) - -### 6.1 app.autoID.get(name) - -- `name` Id Type - -> Returns a `String` -> Get the highest Id of a type - -Example: -```js -const aid = 'article_max_id' -app.autoID.get(aid) === '0' // true -``` - -### 6.2 app.autoID.increment(name) - -- `name` Id Type - -> Returns a `String` -> Increment the Id of the specified type by 1 and return the updated value as a string. This is equivalent to the `++i` operation in javascript. - -Example: - -```js -const aid = 'article_max_id' -app.autoID.get(aid) === '0' -app.autoID.increment(aid) === '1' -app.autoID.get(aid) === '1' -``` - -## 7. Logging - -### 7.1 app.logger.setLevel(level) - -Example: -```js -app.logger.setLevel('debug') -app.logger.setLevel('info') -``` - -### 7.2 app.logger.log() - -Example: -```js -app.logger.log('hello') -``` - -### 7.3 app.logger.trace() - -Example: -```js -app.logger.trace('hello', 'world'); -``` - -### 7.4 app.logger.debug() - -Example: -```js -app.logger.debug('hello %s', 'world', 123) -``` - -### 7.5 app.logger.info() - -Example: -```js -app.logger.info('hello %s %d', 'world', 123, {foo:'bar'}) -``` - -### 7.6 app.logger.warn() - -Example: -```js -app.logger.warn('hello %s %d %j', 'world', 123, {foo:'bar'}) -``` - -### 7.7 app.logger.error() - -Example: -```js -app.logger.error('hello %s %d %j', 'world', 123, {foo:'bar'}, [1, 2, 3, 4], Object) -``` - -## 8. Tools - -### 8.1 app.validate(type, value) - -- `type` The datatype that should be verified -- `value` Data value which will be verified - -> Verify that a data is matches the specification. If not, throw an exception. - -Example: - -```js -app.validate('amount', '10000') // pase -app.validate('amount', 10000) // throws -app.validate('amount', 'abc') // throws -app.validate('amount', '1e10') // throws - -app.validate('string', title, { length: { minimum: 5, maximum: 256 }}) -app.validate('string', image, { length: { minimum: 15, maximum: 256 }}) -app.validate('string', image, { url: { schemes: ["http", "https"] }}) -app.validate('string', desc, { length: { minimum: 1000, maximum: 4096 }}) -``` - -### 8.2 app.registerContract(type, name) - -- `type` Contract Type -- `name` The name of contract - -> No return value -> To register a number type for a contract, an unregistered contract can not be called externally - - -Example: - -```js -app.registerContract(1001, 'cctime.postArticle') -``` - - -The string `'cctime.postArticle'` means, that they must be a `cctime` file in the `contract` directory and in the `cctime` file a function named `postArticle`. - -![alt](./assets/dapp/cctime_file.png) - - -### 8.3 app.getContractName(type) - -- `type` The type or the number of the contract - -> Get the contract name for a specified type - -Example: - -```js -app.getContractName(1001) === 'cctime.postArticle' -``` - -### 8.4 app.registerFee(type, min, currency) - -- `type` The type or the the number of the contract -- `min` Minimum cost -- `currency` Currency - -> The minimum fee for a contract registration -> `Min` stands for the minimum cost. The fee to call the contract. The fee can not be less then `min`. The fee can be greater. The execess part will be send to the fee pool. - -Example: - -```js -app.registerFee(1001, '100000', 'XAS') -``` -### 8.5 app.getFee(type) - -- `type` The type or number of the contract - -> Get the specified fee for a contract - -Example: - -```js -app.getFee(1001) -/* output: */ -{ - min: '100000', - currency: 'XAS' -} -``` - -### 8.6 app.setDefaultFee(min, currency) - -- `min` Minimum cost -- `currency` Currency - -> Set default fee for all contracts in the system. - -Example: - -```js -app.setDefaultFee('10000', 'XAS') -``` - -### 8.7 app.getRealTime(epochTime) - -- `epochTime` The number of seconds since the creation of the block. - -> Returns a timestamp which is the time of the block creation plus the offset in milliseconds -> Asch systems timestamp is not a real timestamp. It is timespan. You can call this function to get a real timestamp - -Example: - -```js -app.getRealTime(4353634) -``` - -### 8.8 app.registerHook - -##### 8.8.1 beforeCreateBlock - -> The callback `beforeCreateBlock` can be used to execute code before a new block gets created. This callback is executed before each block. - - -Params Properties: - -|Name |Type | Description | -|------ |----- |---- | -|height|number | Get the upcoming block height.
code: `modules.blockchain.blocks.getLastBlock().height + 1` | -|pointId|string |block-id of the corresponding block in the mainchain
e.g. `802231c4798740e12bf702bd88fbb41b5b93c709e75abedc585b7813f11c76ce` | -|pointHeight |number |block-height of the corresponding block in the mainchain
e.g.`2847` | -|slotTime |timestamp |time in which the sidechain-block and the mainchain-block was created. The timestamp is in epoch-time e.g. `62551620`
See [8.7 app.getRealTime(epochTime)](#87-appgetrealtimeepochtime) for details | -|signTransaction |method |Parameters: object with the following properties
__type:__ Smart contract Number e.g. 1000
__fee:__ The fee of the smart contract
__args:__ a JSON stringified array with parameters for the smart contract | -|addTransactions |method |Parameters: array of signed transactions
Usually the result from multiple calls to `params.signTransaction` | - - -Simple Example: -```js -// file-name. init.js - -module.exports = async function () { - app.logger.info('enter dapp init') - - app.registerHook('beforeCreateBlock', async (params) => { - // action - }) -} -``` - - -Advanced Example: Delete tweet-like message after certain block height -```js -// file-name: model/tweet.js -module.exports = { - name: 'tweets', - fields: [ - { - name: 'id', - type: 'Number', - not_null: true, - primary_key: true - }, - { - name: 'tid', - type: 'String', - length: 64, - not_null: true, - unique: true, - index: true - }, - { - name: 'creator', - type: 'String', - length: 50, - not_null: true, - index: true - }, - { - name: 'timestamp', - type: 'Number', - not_null: true, - index: true - }, - { - name: 'title', - type: 'String', - length: 128, - not_null: true - }, - { - name: 'message', - type: 'String', - length: 256, - not_null: true - }, - { - name: 'endingBlockHeight', - type: 'BigInt', - not_null: true - } - ] -} -``` - -```js -// file-name contract/tweet.js -module.exports = { - tweet: async function (title, message, endingBlockHeight) { - app.validate('string', title, { length: { minimum: 5, maximum: 128 }}) - app.validate('string', message, { length: { minimum: 20, maximum: 256 }}) - app.validate('amount', endingBlockHeight) - - let tweetId = app.autoID.increment('tweet_max_id') - app.sdb.create('Tweet', { - id: tweetId, - tid: this.trs.id, - creator: this.trs.senderId, - timestamp: this.trs.timestamp, - title: title, - message: message, - endingBlockHeight: endingBlockHeight - }) - }, - deleteTweet: async function (tweetId) { - // only delegates can delete tweets - if (app.meta.delegates.indexOf(this.trs.senderPublicKey) === -1) { - return 'Permission denied' - } - await app.sdb.del('Tweet', { id: tweetId }) - } -} -``` - -```js -// file: interface/tweet.js -app.route.get('/tweets', async (req) => { - - let tweets = await app.model.Tweet.findAll({}) - - return tweets -}) -``` - -```js -// file-name init.js - -async function deleteTweets (params) { - app.logger.info(`current sidechain block height: ${params.height}`) - - // load all tweets that should be closed - let tweetsToClose = await app.model.Tweet.findAll({ - condition: { - endingBlockHeight: { - $lt: params.height - 1 - } - } - }) - - if (!tweetsToClose.length) { - return - } - app.logger.info(`closing ${tweetsToClose.length} tweets`) - - let transactions = tweetsToClose.map((tw) => { - return params.signTransaction({ - type: 1001, - fee: '0', - args: JSON.stringify([tw.id]) - }) - }) - - await params.addTransactions(transactions) -} - - -module.exports = async function () { - app.logger.info('enter dapp init') - - // register contract: 'fileName.functionName' - app.registerContract(1000, 'tweet.tweet') - app.registerContract(1001, 'tweet.deleteTweet') - - app.setDefaultFee('0', 'XAS') - - app.registerHook('beforeCreateBlock', deleteTweets) -} -``` - - -### 8.9 app.custom[] - -> The application's namespace can be used to save some of the application's own custom global variables, mainly to isolate system-wide global variables - -This namespace can be used for example for a custom cache implementation - -Example: Create custom cache implementation - -```js -// file-name: lib/interval-cache.js -class IntervalCache { - constructor(interval) { - if (!Number.isInteger(interval)) throw new Error('Invalid interval') - this.interval = interval - this.container = new Map - setInterval(() => { - this.container.clear() - }, interval) - } - has(key) { - return this.container.has(key) - } - set(key, value) { - this.container.set(key, value) - } - get(key) { - return this.container.get(key) - } -} - -module.exports = IntervalCache -``` - -Register own custom cache implementation: -```js -// file-name: init.js -const IntervalCache = require('./lib/interval-cache') - -module.exports = async function () { - app.logger.info('enter dapp init') - - app.registerContract(1000, 'cctime.postArticle') - app.registerContract(1001, 'cctime.postComment') - app.registerContract(1002, 'cctime.voteArticle') - app.registerContract(1003, 'cctime.likeComment') - app.registerContract(1004, 'cctime.report') - - app.setDefaultFee('10000000', 'CCTime.XCT') - - // set cache - app.custom.cache = new IntervalCache(10 * 1000) -} -``` - -Use cache: -```js -// file-name: interface/index.js - -app.route.get('/articles/:id', async (req) => { - let id = req.params.id - let key = 'article_' + id - - // check cache - if (app.custom.cache.has(key)) { - return app.custom.cache.get(key) - } - let article = await app.model.Article.findOne({ - condition: { id: id } - }) - if (!article) throw new Error('Article not found') - if (article.reports >= 3) throw new Error('Article not allowed') - let account = await app.model.Account.findOne({ - condition: { address: article.authorId } - }) - if (account) { - article.nickname = account.str1 - } - let result = { article: article } - - // set cache - app.custom.cache.set(key, result) - return result -}) - -// ommitted further api endpoints... -``` - -### 8.10 app.meta - -> Returns object -> With `app.meta` you can access meta-information about your dapp, like name, which delegates are responsible etc... - -Warning: -This information is not available in `init.js`, because it is not loaded yet. - -`app.meta` has following properties: - -|Name |Type | Description | -|------ |----- |---- | -|name |string |The name of the dapp.
e.g. asch-dapp-cctime| -|description |string |The description of the dapp.
e.g. Decentralized news channel | -|tags |string|A comma seperated list of tags that categorize this Dapp
e.g. asch,dapp,demo,cctime | -|link |url|The link to the .zip archive of the source code.
e.g. https://github.com/AschPlatform/asch-dapp-cctime/archive/master.zip | -|type | | | -|category |number |Identifies an dapp category
e.g. 1 | -|icon |url|An URL to the dapp icon
e.g.http://o7dyh3w0x.bkt.clouddn.com/hello.png| -|delegates |array |An array of the public keys of the delegates | -|unlockDelegates |number | | -|transactionId |string |The mainchain-transaction in which this dapp was registered
e.g. f30b85cff0d57d949ee84950bf59dbfbeebc369c0287cd6ea3f3d7501994a42a | - -Example: Use `app.meta` to allow access to a smart contract only to the dapp delegates - -```js -// file-name: contract/tweet.js - -module.exports = { - deleteTweet: async function (tweetId) { - // only delegates can delete tweets - if (app.meta.delegates.indexOf(this.trs.senderPublicKey) === -1) { - return 'Permission denied' - } - await app.sdb.del('Tweet', { id: tweetId }) - } - - // other functions ommitted -} -``` diff --git a/docs/asch_whitepaper.md b/docs/asch_whitepaper.md deleted file mode 100644 index cd185bf..0000000 --- a/docs/asch_whitepaper.md +++ /dev/null @@ -1,265 +0,0 @@ -title: 白皮书 ---- -# 0 引言 - -比特币的出现使得去中心化的货币系统成为可能,经过几年的发展,人们发现比特币背后的区块链技术潜力巨大,可以被广泛应用在各行各业。为了更好地利用区块链技术,出现了以以太坊为代表的一批应用平台,它们封装了底层协议、建设了基础设施,为开发者提供了更加友好、也更加灵活的接口,使得开发者的关注点能够集中在业务逻辑上,很大程度上提高了开发效率。本文提出的 asch 系统也是一种去中心化应用的开发平台,接下来我们会详细阐述这一系统的特色、原理及应用场景。 - -# 1 概述 - -## 1.1 去中心化应用 - -去中心化应用是一种具有以下特点的应用。 - -1. 必须完全开源,自主运行,不能被中心化的组织、机构或个人操控,可以被改进以响应市场需求,但必须经过用户们的共识。 - -2. 数据必须被安全、公开、冗余的存储在一个分布式网络中,以避免被篡改和单点故障。 - -3. 应用访问者需要消耗令牌,而应用贡献者可以获得令牌的奖励。 - -4. 应用必须使用一种价值证明的密码学算法来生成令牌。 - - 去中心化应用可以通过授权系统的权益人来投资应用的开发,从而有潜力达到自给自 - -足。去中心化应用还有公开透明、安全可靠、去信任等优点。因此,可以想像去中心化应用在支付、数据存储、云计算、电子商务等领域将有非常可观的前景,它所产生的价值甚至有可能会超过 visa、dropbox、亚马逊等跨国公司的市值。 - -## 1.2 侧链是什么 - -区块链是一串使用密码学方法相关联产生的数据块,每一个数据块中包含了若干网络交易的信息,用于验证其信息的有效性(防伪)和生成下一个区块,对于普通用户来说它就像一个公有账本,记载所有的交易记录,对于开发者来说可以理解为一个分布式的数据库。区块链这个数据库的特点是去中心化、开放、自治、不可篡改,区块链与去中心化应用息息相关,非常适合为去中心化应用提供存储功能。 - -侧链是一种特殊的区块链。它使用一种叫做“SPV 楔入”的技术实现与其他区块链之间的资产转移,这使得用户能用已有的资产来使用新的加密货币系统。人们不必再担心比特币难于采纳创新和适应新需求,只要创造一个侧链,然后对接到比特币的区块链中即可,通过继承和复用比特币强大的区块链,还避免了新货币的流动性短缺和市场波动等问题。并且由于侧链是一个独立的、隔离的系统,侧链中出现的严重问题只会影响侧链本身,这极大地降低了创新的风险和成本。 - -## 1.3 Asch 是什么 - -Asch 是一个去中心化的应用平台。它提供了一系列的 sdk 和 api 来帮助开发者构建基于 Javascript 和侧链技术的去中心化应用。Asch 通过提供定制侧链、智能合约、应用托管等一体化的行业解决方案,致力于打造一个易于使用、功能完备、即插即用的系统。利用 Asch 生态系统,开发者可以快速迭代他们的 Javascript 应用,并发布到系统内置的应用商店中,这些应用可以被平台中的分布式节点下载并执行,并服务于普通用户,整个过程都由诚实安全的 Asch 侧链共识网络提供安全保证。 - -Asch 系统本身也是一个完全开放的、去中心化的应用,内置有代币,单位为 XAS,中文名叫阿希币。阿希币可以通过双向楔入的方式与侧链或 dapp 进行交互,作为所有 - -dapp 之间资产转换的桥梁和媒介,这些代币将在系统发布之前以 ico 的方式预售给投资人。系统一旦发布,Asch 最初的核心团队将不再掌控系统的走向,只有系统的权益人和代币的拥有者决定系统将来的发展。 - -## 1.4 Asch 面向哪些用户 - -Asch 平台除提供一些基本服务外,还将提供技术和工具上的支持,主要面向以下群体: - -### 1.4.1 开发者 - -开发者可以根据 Asch 平台的应用开发规则和商业行为准则,并按照相关的规范进行开发和提交 dapp。Dapp 的商业模式或免费,或定价销售,或按增值服务付费。采用何种商业模式完全由开发者决定。 - -### 1.4.2 企业 - -Asch 平台提供的工具可以非常容易地创建一个完整的区块链,更重要的是可以楔入到Asch 平台的主链或者比特币的区块链中,实现与成熟电子货币的对接,这对中小型企业,特别是初创企业是非常有吸引力的。 - -中小企业可以通过区块链技术提供原本封闭在企业内部、互联网内部的信息和数据,甚至与监管机构的相关系统数据相互链接,增强透明度,以此树立良好的形象,赢得投资者、金融机构的信任度,顺利拿到融资或项目合同等。 - -中小企业主动公开和开放资料,已成无法阻挡的趋势。因为现在有很多的公开渠道来获取数据,中小企业已经越来越难隐瞒它们不想让外界知道的信息。我们可以大胆预测,在未来区块链将是帮助中小企业发展的重要武器。 - -### 1.4.3 普通用户 - -普通用户可以通过 Asch 内置的应用商店进行下载、安装和使用去中心化应用,这跟手机平台的应用商店是类似的模式。Asch 系统支持多种类型的去中心化应用,普通用户在消费这些应用的同时,还可以通过贡献内容来获得收益。开发者与普通用户将共同组成一个繁荣的生态系统。 - -# 2 设计理念 - -## 2.1 完备脚本 vs 侧链 - -比特币为人称道的一个设计上的亮点就是它的脚本引擎。基于这套脚本引擎,不但可以实现普通的转账功能,还可以实现多方签名、抵押担保、博彩等智能合约应用。但是出于安全和实现难度的考虑,比特币的脚本系统设计的较为简陋,做了非常多的限制,比如它不支持循环、脚本长度受限、只支持几种标准的的交易类型。 - -以太坊的最大特色就是极大地扩展了这个脚本引擎的功能,加入了读取区块链、计费、跳转等新指令,还解除了栈内存、函数调用深度以及脚本长度限制等。以太坊自称他们的脚本语言达到了图灵完备,利用这样的脚本,开发者可以实现几乎任何可以用数学方式表述的功能。 - -自以太坊以来,扩展脚本成为了一种实现去中心化开发平台的流行方式,但这种方式有一个很大的缺点就是,应用代码本身及应用产生的数据都存在同一个区块链中,造成了区块链的快速膨胀。以太坊试图通过优化和压缩区块和交易本身来延缓这种膨胀,也只是一种治标不治本的方法。此外,基于脚本实现的应用之间是共享同一个账本的,像区块产生时间等参数是无法被定制的,这无疑限制了应用的个性化。 - -侧链机制是通过另一个维度实现扩展性的,每个侧链运行在不同的分布式节点网络中,有独立的受众、投资人和开发团队。这种天然的分片解决方案,不但解决了区块链的膨胀问题,而且每个应用都拥有一套个性化的账本,其共识机制、区块参数、交易类型都是可以被定制的,所以我们认为侧链与完备交易脚本相比,是一种成本更低、更加灵活、也更加易用的解决方案。 - -## 2.2 账户 vs UTXO - -在比特币及其衍生系统中,是没有一个所谓的账户来存储用户的余额的,用户的余额是通过整个系统的交易状态转换来实现的。这里要引入一个术语,UTXO(unspenttransaction outputs),即未花费的交易输出。每个 UTXO 都有一个面值和所有者,一笔交易包括一个或多个输入和一个或多个输出。每个输入包含一个对现有 UTXO 的引用和由与所有者地址相对应的私钥创建的密码学签名,如果一个用户拥有这个私钥,那么他就可以消费这个 UTXO 对应的币值,也就是说一个用户的余额就是他所有拥有的所有私钥对应的 UTXO 的币值总和。UTXO 主要优点是高度的私密性,用户可以为每一笔交易生成一个新的地址,从而使得用户无法被追踪,这对于货币来说是好事,但对于各式各样的dapp 来说,就未必了。账户相对于 UTXO 来说,有以下几个优点: - -1. 节省空间。举例来说,如果某个用户有 5 个 UTXO,需要的存储空间是(20 + 32 +8)* 5 = 300 字节(其中 20 字节为地址,32 字节为交易号,8 字节为交易额),而账户仅需要 20+8+2=30 字节(20 字节位地址,8 字节位余额,2 字节为随机数)。 -2. 利于监督。账户的存在使得电子货币很容易被区分,因为我们只要知道这些币来自哪些账户即可。 -3. 简单、易于编码和理解。 -4. 常量级引用。轻客户端能以常数时间访问一个用户的账户任意数据,而在 UTXO 系统中,每当有交易发生时,数据引用将发生变化。 - -Asch 平台本身并不是一个纯粹的货币系统,要容纳各种各样的应用,综合比较起来,账户对于我们来说是一种更好的选择。 - -## 2.3 关系数据库 vs 非关系数据库 - -目前大多数的区块链系统都选择使用模型较简单的非关系数据库来存储数据,比如berkeley db,leveldb 等,这些数据库一般都提供一些简单的数据结构,比如 btree、hashtable、queue 等,它们一般不支持 SQL 对数据进行操作,虽然这些数据库对于一般的电子货币系统来说足够了,但对于应用平台来说是远远不够的,特别是对于金融、银行、电子商务等领域,目前主流的存储系统都是采用了关系数据库,因为关系数据有以下几个优点: - -1. 事务处理; -2. 数据更新开销非常小; -3. 可以进行 join 等复杂查询。 - -我们选择的 sqlite 是一种性能极佳的轻量级嵌入式关系数据库,容量最高支持 2T,数据文件可在不同字节序机器之间自由共享,特别是对 SQL 的支持,将为 dapp 开发者提供极大的便利。 - -# 3 系统特点 - -## 3.1 易用 - -### 3.1.1 开发语言 - -开发者可以使用 javascript 语言以及海量的 npm 库来构建他们的应用。相对于比特币的 c++语言及栈式脚本、以太坊的新语言 solidity,javascript 流行度更高、受众更广、上手更容易的一门语言。此外,关系数据库的加入也是 Asch 系统的一大特色,使得去中心化的应用开发模式与传统 web 应用的开发模式已经非常相近了。Asch 平台的应用开发门槛可以说是同类产品中最低的。 - -### 3.1.2 工具 - -Asch 系统提供了一个命令行工具,只需要根据提示输入一些配置项,就可以快速的建立一个侧链,并可在侧链上开发任意类型的应用。其次,系统还提供了一系列的 api 帮助用户构建复杂的智能合约应用,这些 api 涵盖共识、强随机数、数据库、密码学等方面。 - -### 3.1.3 部署 - -开发者只需要把自己的 dapp 提交到 github,然后在 web 钱包或轻钱包中注册,就完成了部署的工作,之后 dapp 将被显示在应用商店中被用户下载和使用。 - -## 3.2 灵活 - -开发者可以随意定制其侧链的各项参数,比如区块产生速度、交易类型、交易费等等,甚至可以实现一个新的共识机制,比如开发者可以使用权益证明或工作量证明的共识机制来取代默认的委托人权益证明机制。 - -## 3.3 安全 - -Asch 系统的一大亮点是使用了一个增强 DPOS 的共识算法,在 DPOS 的基础上加入了一个高效的实用拜占庭容错算法,极大地降低了网络分叉的可能性,只要不超过 1/3 节点联合做恶,系统就不会分叉,也就没有双重支付的风险。其次,系统在一些小的细节方面也是尽量从安全角度进行了考量。比如采用 BIP39 标准算法的口令助记符、二级交易密码、多重签名账户等。 - -# 4 技术细节 - -## 4.1 共识机制 - -Asch 系统采用的共识机制是基于 DPOS 的,也是使用了委托人选举的制度,但是在算法的后半部分采用了一个优化后的 PBFT 算法变种,这个算法可以在 t < n / 3 时,以O(n^2)消息复杂度,O(1)的时间复杂度使忠诚的节点达成一致,不会分叉,其中 t 表示拜占庭节点(即可能发生任意行为的节点,比如网络延迟、停机、恶意攻击等等)的个数,n 表示所有节点的个数。 - -### 4.1.1 委托人选举 - -Asch 系统的委托人选举制度与 DPOS 是类似的,核心系统是由 101 个委托人节点组成,委托人是被社区选举的可信账户,得票最高的 101 个委托人负责生产区块。得票排名未进入前 101 名的账户被称为候选人,当他们将来获得足够多的选票并进入前 101 名后,将成为正式的委托人。 - -每个 Asch 用户都有权利投票给最多 101 位委托人,选票的权重是由用户持有的 XAS数量决定。 - -每一个选举周期产生 101 个区块,每一次投票和委托人排名的变化将体现在下一个周 - -期。每个区块产生的间隔时间是 10 秒,新创建的区块会被广播到网络中并添加到区块链中。每当新的区块被添加到区块链中,该区块之前的所有交易的确认次数加一,得到 6 个确认后,可以认为交易是安全的,如果数额较小的交易,可以允许更小的确认次数,相反,数额较大的交易可以通过增加确认数来保证安全性。 - -如果有少数委托人发生故障,比如被攻击或者宕机,就会错失区块,这会被记录在案,这将影响该节点的在线率,进而影响社区的投票。因此委托人的竞选是需要严肃对待的,委托人应当由有一定网站运营经验的人来做,委托人要保障自己节点的稳定性,并以此促进整个系统的安全和稳定。 - -### 4.1.2 拜占庭容错 - -Asch 系统与 DPOS 的不同主要体现在算法的后半部分。 - -DPOS 采用的方法是,首先对当前 round 的委托人列表进行随机的排序(保证每一轮的委托人顺序不同,也无法预测下一轮委托人顺序),然后通过 round-robin 的方式依次让每个委托人创建区块。这个算法的主要缺点是,如果某个委托人节点叛变了,他可能会广播多个不一致的区块,这些区块间可能包括双重支付交易,导致整个网络被分叉了。当然,如果只有一个委托人叛变的话,这个分叉很快就可以通过下一次最长链同步的方法来消除,但是随着叛变节点的增加,消除分叉的时间将越来越长,少量节点的联合叛变将严重影响系统的安全性,即使一个交易达到 6 次确认,也很可能是不安全的。 - -为了解决这个问题,我们引入了 PBFT(Pratical Byzantine Fault Tolerance)算法。PBFT 算法也是使用 round-robin 的方式选择委托人,但是选出委托人后并不立即创建区块,而是首先发起一个提议(propose),这个提议的目的是确定下一次区块的 hash。当超过 2/3 的节点都赞成该提议时,才接受由提议人创建的的下一个区块,下一个区块的 - -hash 必须与当前 round 达成共识的区块 hash 一致。从本质上来说,PBFT 算法的加入解决了委托人权利滥用的问题,使得委托人的记账能力更为可控。 - -## 4.2 侧链与 dapp - -Asch 系统提供了一个命令行工具,可以用来轻松创建一个基础的侧链系统,侧链的开发者也可以深度定制自己的侧链,侧链拥有自己的数据库、共识机制、交易类型以及账户体系。侧链可以托管在独立的委托人节点集群中,这就自然形成了一种分片的机制,延缓了主区块链的膨胀。 - -每一个 dapp 对应一个侧链,侧链的核心逻辑使用 nodejs 开发,界面部分可以使用任意前端技术,比如 qt,html,javascript 等等,前端与后端之间一般通过 json rpc 协议通讯。Dapp 的作者或者所有者可以跟踪自己的 dapp 被使用的情况,加密货币是基于社区的共识,但 dapp 更像是一家私人拥有的公司。Dapp 内的交易是由主节点处理的,主节点是由 dapp 所有者运行的,dapp 所有者必须拥有一个 Asch 帐号,这个帐号类似多重签名的帐号,它的主要任务是在 dapp 主节点创建共识并签名新的区块,如多重签名钱包。一旦一个新的 dapp 区块被创建,并且在主节点内被签名,这个区块需要被计算出SHA256 哈希,然后 dapp 所有者提交这个哈希值给 Asch 区块链,然后存储该哈希值为dapp 区块,一旦 Asch 区块链收到一条包含 dapp 哈希值的交易,由受托人对比这条哈希值与上一个啥希值,并将它保存到 Asch 区块链,在未来,当主节点同步网络,用户将通过 Asch 区块链来验证所有 dapp 区块,想从 Asch 区块链中移走上一个 dapp 区块将是不可能的事情。相同的功能,以比特币区块链来替代 Asch 区块链将同样适用,API 在比特币区块链上工作的方式是一样的,通过比特币区块链来保证 dapp 的安全性。开发者可以使用 XAS 和 BTC 来做为其 dapp 的货币,使用 dapp 时可能需要存入或者取出资金,当 Asch 或者 BTC 被发送到 dapp 的地址时,资金会在其 dapp 的帐户内出现,用户便可在 dapp 内使用该资金,BTC 和 Asch 的存入方式是一样的,都是发送到 dapp 的特定地址,然后资金就会出现在 dapp 帐户内。Dapp 的帐户都是由 dapp 的作者创建的,所有存入的 Asch 或者 BTC 都将被存储在这个地址内,考虑到安全性,只推荐使用了多重签名可信任的签名者的 dapp 帐户。从 dapp 取款是由主节点负责处理的,当有人发送一条取款请求,dapp 主节点就会处理它并且把资金从 dapp 的地址上移出到 Asch 区块链上,或者比特币区块链上。开发者可以在他们自己的 dapp 里面发行令牌,而且使用此令牌做为该 dapp 的流通货币,这些令牌在该 dapp 内可像 XAS 或者 BTC 一样使用,但是它不能直接从一个 dapp 转移到另一个 dapp,他们必须通过 Asch 主链来转移。 - -## 4.3 沙箱和 VM - -沙箱是一种按照安全策略限制程序行为的执行环境。早期主要用于测试可疑软件等,比如黑客们为了试用某种病毒或者不安全产品,往往可以将它们在沙箱环境中运行。经典的沙箱系统的实现途径一般是通过拦截系统调用,监视程序行为,然后依据用户定义的策略来控制和限制程序对计算机资源的使用,比如读写磁盘等。 - -Asch 系统使用了 nodejs 的 vm 模块实现沙箱机制。VM 模块是对 javascript 的 v8引擎的封装,可以用来执行纯粹的 javascript 代码,但无法使用系统层的 api,比如文件系统、网络传输相关的模块,并且由于没有 require 函数,第三方库也没法轻易导入进来,甚至无法进行模块化开发,这就需要 dapp 的开发者使用 browserify 的技术将常用的第三方库打包成一个 js 文件,Asch 的主链系统才能加载并运行。对于一些必须的系统级api,则通过进程间通讯的方法为侧链提供,这样兼顾了安全性与功能的完备性。 - -## 4.4 交易 - -Asch 系统内建了一个交易抽象层,核心系统的几乎所有功能都是建立在交易上的,比如转账、投票、应用商店、充值、提现等。侧链本身也可以实现自己的不同类型的交易。交易之间的区别主要是交易类型和 asset。基础交易的数据结构如下,扩展部分会根据类型的不同分别存在不同的 asset 表中。 - -```sql -Transaction { -required VARCHAR(20) id; -required VARCHAR(20) blockId; -required TINYINT type; -required INT timstamp; -required VARCHAR(21) senderId; -optional VARCHAR(21) recpientId; -required BIGINT amount; -required BIGINT fee; -required BINARY(64) signature; -optional BINARY(64) signSignature; -optional TEXT signatures; -required BINARY(32) senderPublicKey; -} -``` - -以投票交易举例来说, votes 实体通过交易 id 来关联到一个基础交易中。 - -```sql -Asset_Votes { -required VARCHAR(20) transactionId; -optional TEXT votes; -} -``` - -## 4.5 账户系统 - -Asch 的每个账户由一个口令、一对公私钥、一个地址组成。用户还可以额外设置一个二级密码。注意这里与比特币有所不同的是,每个账户仅对应一个地址,而比特币中每个钱包对用多个地址和私钥。 - -口令(passphrase)是符合 BIP39 标准的用于产生确定性钱包的助记符。这种助记符与二进制或十六进制字符相比对人类记忆更友好。口令的生成方式是将一个 32bit 倍数长度的熵转换成若干个单词,Asch 系统选择的熵长度为 128bit,将转换成 12 个单词。口令作为一级密码,由用户保管,不对外公开,一旦丢失用户将失去对应账户的所有权。口令形式如下: - -``` -barely decline dust stamp protect color certain cup arena busy latin shell -``` - -**密钥对**包括公钥和私钥,是以口令的`sha256` 哈希做种子,再通过 `ed25519` 爱德华兹曲线签名算法生成的。形式如下: - -``` -公钥: -9989388b220a13465e49f52df5ba28ba08eb1e7a973320347f9687a107dc2f -9a - -私钥: -91e891f653e3ed0232d8c7de2e72b625d50d48593fc0fb570c0db25c5e4456 -9a9989388b220a13465e49f52df5ba28ba08eb1e7a973320347f9687a107dc -2f9a -``` - -账户地址是取公钥的 `sha256` 哈希的前 8 位,逆序后转换成 bignumber,其形式如下 - -``` -5034187504202890358 -``` - -## 4.6 客户端 - -Asch 系统将提供三种客户端程序。 - -完整版客户端是针对超级用户、委托人和开发者的最佳解决方案,它可用于windows,Mac OS 以及 linux,但它只允许 linux 运行受托人节点。 - -轻钱包的用户可以通过连接到完整版钱包以连接到网络,也可以直接调用 API,但前提是完整版钱包的所有者有开放该 API 权限,完整版钱包会通过点对点网络,从其它完整版钱包节点下载完整的区块链。 - -普通用户将主要使用轻钱包来管理自己的 Asch 帐户,它是一个精简版的 Asch 钱包,轻钱包支持 windows 和 Mac OS,它无需安装,它使用的是内嵌式的浏览器,它无法作为网络节点,因为它不下载区块数据,它只通过 http 连接到其它的节点,这样做能带来几点好处。首先它不下载区块数据,这意味着它会一直保持着较小的体积,不占容量;其次它不向网络广播密钥,所有数据在本地设计上签名,可以做所有类型的交易,如果你想运行一个受托人节点,你可以使用轻钱包注册一个受托人帐号,但你无法使用轻钱包来运行受托人节点来创建区块,为了运行受托人节点,你需要下载完整版钱包,并运行在 linux 上。Dapp 用户可以使用轻钱包来管理已安装的 dapp。Dapp 的 API 和节点的API 也可供开发人员调用,这使得开发人员可以使用 Node.js 快速且简单地创建javascript dapp。 - -移动版客户端允许用户通过移动终端来操作自己的 Asch 帐户,它将提供 ios 与安卓两种版本,并于苹果应用商店和安卓应用商店提供下载。它的后端将基于我们的桌面版的解决方案,与桌面版的区别将在于移动版钱包界面将使用响应式技术,自适应移动终端屏幕,并根据移动设计调整了一些交互方式。该 APP 使用了专为移动终端定制了易用的界面,类似于 bitcoin 和一些常用的银行类 app 的界面,而且它将支持在内部运行所有你喜爱的 dapp。 - -## 4.7 性能 - -一笔交易信息通过优化和压缩后大概占 100 字节,我们算算系统达到 1 万 tps 时候需要消耗的带宽。因为出块间隔为 10 秒,那么每次出块需要包含 10 万个交易,也就是说要包含 10M 字节的交易数据,这 10MB 的数据需要在 10 秒内广播到全网,按最理想情况下,第一跳广播到 10 个节点,第二跳广播至 100 个节点,每一跳要在 5 秒内传输完毕,服务器需要的带宽是 10MB * 10 / 5 = 20MB,考虑到中间的带宽损耗和非理想情况,我们认为至少要 40MB 的带宽才能够满足 1 万 tps 的吞吐量。这个带宽要求显然不低,但是相信 1 万 tps 给委托人带来的收益远大于网络维护的费用。2014 年双十一支付宝的吞吐量峰值达到了 8.59 万每秒。Asch 系统在交易吞吐量方面还是有优化空间的,这也是将来我们的重点要投入的方向。 - -# 5 应用场景 - -## 5.1 令牌系统 - -使用 Asch 工具创建的第一个 hello world 应用,就是一个最基本的令牌系统了。 - -开发者可能不需要编写代码,只要在 genesis.json 文件里修改一些创世参数,就可以发布一个令牌系统了。Asch 系统中的令牌与以太坊的子货币一样,可以表示黄金、股票、抵押物、或任意其他资产,这些令牌可以与转入侧链中的 XAS 通过去中心化的方式进行交易,从而实现流通,也可以在中心化的交易所与其他货币进行交易。 - -## 5.2 仲裁合约 - -假设一个买家想跟一个不认识的人进行交易,一般情况下如果交易顺利进行的话,双方都不希望有第三方介入,但是如果某个环节出了问题,比如买家对商品不满意时,他们就希望有一个中间人来做调解。这个中间人可能会要求买卖双方出示一些证据,然后做出判决,比如把钱退还一部分给买家。这个业务流程如下: - -1. 买卖双方共同选择一个中间人 -2. 买家使用三方的公钥创建一个 2-3 的多重签名账户,然后转账到这个账户,再以该账户为发起人,以卖家的账户为接收人,签署一个交易并发布出去。此时这个交易是不能立即被确认的,只有 3 个人中的 2 个人共同签名,才会生效。 -3. 卖家发货给买家。 -4. 如果买家收到货物后,检查没问题,使用自己的私钥对刚才的交易进行签名。然后卖家再次签名后,交易就顺利完成。 -5. 如果买家对货物不满意,可以向中间人发起申诉并出示证据,卖家也可以出示证据,最终由中间人与买卖其中的一方达成一致,共同签署,完成交易,结束仲裁。 - -## 5.3 去中心化交易所 - -根据是否支持法币,可以分为两种程度的去中心化。如果不支持法币,可以实现完全的去中心化,如果支持法币,则只能实现半去中心化,即法币通过网关出入,但交易信息公开。 - -完全的去中心化交易所又分为两种,一种是点对点的交易,通过 Asch 系统提供的“原子跨链交易 api”来实现。另一种是挂单交易,挂单交易要求卖方从其他区块链转入一定的资产到 Asch 侧链中,这个转入操作通过父链冻结资产的 SPV 证明达成。此外,由于关系数据库的支持,利用联表查询和索引功能,可以很容易的实现一个效率不错的撮合引擎。 - -## 5.4 存在性证明 - -存在性证明可以用于登记文件版权、专利等,其基本原理是将要存储的文件的哈希值存入到 Asch 的侧链中,以此来证明某个特定文件存在,还可以加上时间戳、当事人的数字签名等元数据,来证明他们是在何时持有这些文件的。这些信息无法伪造、无法篡改,不会暴露数据和隐私,在需要的时候随时可以验证且不依赖第三方机构。 - -## 5.5 物联网 - -物联网中存在海量的联网设备,很难有一个中央机构来管理所有的设备和各节点的身份。Asch 的侧链是一个很好的解决方案,首先,它解决了节点间信任问题,设备间彼此相连形成分布式网络,通过共识算法来保证设备间交易的合法,并且可追踪、可审查、可分析。其次,不同种类的设备可以接入不同的侧链,这是我们前面提到的天然分片机制,避免了总账本的爆炸式增长。我们试想下,在一个基于区块链的物联网中,一个自动售货机不但可以监控和报告它自身的存货,还可以通过分析历史交易数据智能地从分销商那里进行招标并自动完成付款。 - -# 6 总结 - -Asch 是一个去中心化的应用平台,其设计初衷是为了降低开发者的门槛,比如使用javascript 作为应用编程语言,支持关系数据库来存储交易数据,使得开发一个 dapp 与传统的 web 应用非常相似,相信这对开发者和中小型企业有很大的吸引力,只有开发者的生产力提高了,整个平台的生态才能够更迅速的繁荣起来。Asch 在设计上也是开放的,并没有局限于某个细分领域,比如金融、文件存储、版权证明等,其提供的 api 都是较底层和抽象的,它们可以被自由组合实现各种不同的应用。在共识机制方面,Asch 继承并增强了 DPOS 算法,大大降低了分叉几率和双重支付风险。另外,Asch 的侧链即应用模式不但延缓了区块链膨胀问题,还使得 dapp 更加的灵活和个性化。Asch 是一个具有前瞻性的、低成本的一站式应用解决方案,相信将成为新一代去中心化应用的孵化器。 \ No newline at end of file diff --git a/docs/asch_whitepaper_de.md b/docs/asch_whitepaper_de.md deleted file mode 100644 index 24600c0..0000000 --- a/docs/asch_whitepaper_de.md +++ /dev/null @@ -1 +0,0 @@ -Bitte besuchen Sie die offizielle Webseite um das englisprachige Whitepaper zu lesen. [Whitepaper (eng)](https://www.asch.so/asch-whitepaper-en.pdf) diff --git a/docs/asch_whitepaper_en.md b/docs/asch_whitepaper_en.md deleted file mode 100644 index f32f381..0000000 --- a/docs/asch_whitepaper_en.md +++ /dev/null @@ -1,164 +0,0 @@ -title: Whitepaper ---- -# Introduction -Since Bitcoin was introduced in 2009 and had been rapidly developing for these several years, people found that Bitcoin has more potential than just be a kind of electronic currency. Especially blockchain, the underlying technology of Bitcoin, has the unlimited capacity even more valuable than Bitcoin itself. The blockchain technology can be applied in the development of different kinds of application, which have the same characteristic that is decentralization. The emerging of these decentralized applications also promotes a new application architecture, which is based on an open-source platform. Based on this concept, we propose the Asch system, a development platform for decentralized applications. -# Overview -## Decentralized Application -Decentralized application has following features: -1. The application must be completely open-sourced. It must be run under the control of itself, which means it should not be tampered by any centralized organization, institution or individual. It can be revised to reflect the market requests, but has to be recognized by all users. -2. The application data should be stored in a distributed network that has to be secure, open, and redundant, in order to avoid data manipulation and single node failure. -3. Application users need tokens to access, and application contributors can get tokens as rewards. -4. The application must apply a value-proved cryptographic algorithm to generate tokens. -The decentralized application can make the stakeholder to invest in the development of it by granting them the privilege in it so that it becomes possible to be self-sufficient. These kinds of application also have the advantages such as publicity, security, and trustless. Therefore, it is not strange that decentralized applications will play a vital role in following fields: payment, data store, cloud computing, e-business, and etc., and it is even possible that the value created by those applications will exceed the market value of giant international company such as VISA, Dropbox, or Amazon. -## About Sidechain -A blockchain is a well-ordered collection of data blocks generated by using cryptographic algorithm. Each block of data contains an amount of network transaction information which is used to validate the authenticity, as well as generate the next block. To a normal user it looks like a public ledger on which every single transaction will be recorded, and to an -application developer it looks like a distributed database, which features decentralization, open, self-autonomy, and harden against tampering. The blockchain presents a very tight relationship with decentralized application which makes it very suitable for store these applications. -As a specific blockchain, the sidechain applies a “SPV (simplified payment verification) Pegged” technology to achieve the goal that the user’s asset can be transferred from one blockchain to another, which means users can use their current assets to utilize the new cryptocurrency system. There will be no need to worry about the disadvantage of Bitcoin that is hard to adapt the innovation and meet the new request. What need to be done is just create a sidechain and link it to the main blockchain of Bitcoin. By inheriting and reusing the powerful blockchain of Bitcoin, other issues such as liquidity shortage and market fluctuation, often occurred when a new currency is introduced, can be averted. Furthermore, since the sidechain is a isolate individual system, any severe failure will only impact the sidechain itself instead of the whole blockchain, thus significantly reduce the risk and cost of innovations. -## About Asch Platform -Asch is a decentralized application platform, providing a series of SDK and API to help developers creating decentralized applications based on JavaScript and sidechain technology. By providing a whole set of industry standard solutions including customized sidechain, -smart contracts, application hosting, and etc., Asch intends to offer an easy-to-use, fully functional and plug & play ecosystem, by which developers can rapidly iterate their JavaScript applications, and easily deploy them into application store built in the system. These application can be smoothly downloaded and executed by every node and user located in everywhere of this ecosystem. The whole process will be secured by the Asch sidechain consensus network. -On the other hand Asch itself is also a fully opened, decentralized application, which has its own cryptocurrency known as Asch coin. Asch coin is capable of interfacing with sidechain or any decentralized application (DAPP) through “two-way peg” mechanism so that it can be the bridge or media for the asset transition among all DAPPs, and to achieve that purpose, the Asch coin will be sold to the investors through ICO (initial coin offering) before the deployment of the system. Once an Asch system is published, it will not under the control of the core development team, but the stakeholders of the system and the owners of Asch coin. -## Who Should Use Asch Platform -Apart from some basic services, Asch platform also provides technology and toolkit support, whose main target audiences are as follow: -### Developers -Developers can create and deploy DAPP in Asch platform by following the criteria of application development and business activities. The business model of these DAPPs may be free or fixed price, or pay with value added service. It is all up to the developers themselves. -### Enterprises -The tools provided by Asch platform can be used to easily create a complete blockchain, and more importantly, this blockchain can be pegged into main chain of Asch platform or even the blockchain of Bitcoin, thereby connected with well-developed electronic currency. It is a very attractive feature that is suitable for small and medium enterprises (SMEs) especially start-up companies. -SMEs can utilize blockchain technology to provide the information and data that were enclosed inside companies or Internet in the past, and to connect with the system data owned by authority so that they can promote the business publicity and improve the companies’ image. Consequently more trustiness can be brought to the investors and financial institutions to make it easy to get the funds or contracts. -It is inevitable for SMEs to public their business information. SMEs found it is difficult to prevent social community to know their secrets. Therefore we can assume that blockchain will play a vital role in SMEs everyday business activities. -### End users -Individual users can download, install and use numbers of decentralized applications through Asch built-in app store, which is similar with application store in current smart phone. Asch system supports different kinds of decentralized application on which end users can make profit by contributing the program or content. It is possible for developers and users to create a vivid ecosystem together. -# Design Rationale -## Turing-Completeness Scripting vs Sidechain -The scripting engine is a highlight in design of Bitcoin on which not only can transfer the currency but can realize the smart contracts such as multi-signature, escrow and arbitration, and gambling. Bitcoin’s scripting system, however, applies a concise design setting a series of limitations due to the consideration of security and difficulty of implementation, for example, it cannot support loop, or must strict the length of its scripts, or only supports limited numbers of standard transactions. -The most attractive characteristic of Ethereum is that it significantly expands the scale of functionality of this scripting engine. In detail, Ethereum adds several instructions such as reading blockchain, charging, jumping, etc., as well as releases the limitation of the invoke depth of stakes and functions, and length of the script. Ethereum claims that its scripting engine is Turing-completeness by which developers can carry out almost any computation that can be represented by mathematic model. -Although with Ethereum, expanding script became a prevail approach of decentralized application platform, it still has one disadvantage that cannot be ignored: the application itself and the data generated by it have to be stored in the same blockchain, which makes the blockchain grows extremely rapidly. Ethereum tried to slow this trend down by optimizing or compressing the program code and data, but still cannot solve the problem completely. Moreover, since those applications based on scripting have to share the same ledger, some parameters, i.e., created-time of blockchain, cannot be changed, which prevents developers from customizing the application. -Sidechain mechanism, in contrast, deals with scalability in another way. Every sidechain is running in a different distributed network node, having separate users, investors and development team. This partition-like solution has resolved the blockchain expansion problem, and has made every application has its own ledger, on which the consensus mechanism, blockchain parameter, and transaction mode can be customized. For this reason, we believe sidechain mechanism is a lower-cost, more flexible and easier to use solution -than a Turing-completeness transaction scripting. -## Account vs UTXO -Within Bitcoin and derived systems, there is no so-called “account” to save the user’s balance. The balance has to be dealt with by the status transition of the whole transaction system’s status. Let’s introduce a new term, UTXO, standing for unspent transaction outputs. Every UTXO has its own nominal price and its owner and each transaction has multiple -inputs and outputs. Each input includes a reference of current UTXO and a cryptographic signature generated by private key related to owner’s address. If a user own this private key, he/she can consume the value of this UTXO, in other words, the balance this user has is the sum of the currency value of all the UTXO related to the user’s private keys. The main advantage of UTXO is high level security, which means the user can generate a new address for each of his/her transaction so that he/she cannot be traced. It is a great thing for a currency involved transaction, but to variety of DAPPs, it is not sure. Compare to UTXO, account has following benefits: -1. Space efficiency. For instance, it will take a user 300 bytes space when he/she has 5 UTXOs: (20+32+8) x 5 = 300 bytes (20 bytes for address, 32 bytes for transaction No., -and 8 bytes for transaction amount). Meanwhile if using account, the storage space will be limited to 30 bytes: 20+8+2=30 bytes (in this case, 20 bytes for address, 8 bytes for balance, and 2 bytes for random number). -2. Easy to monitor. Due to the account, the electronic currencies are easy to recognized, since all we have to know is the account that the currency is coming from. -3. Simple, easy to code and understand. -4. Referring in a fixed time. A lightweight client can access all the data in a user’s account -in a fixed time, while with UTXO system, the access time will change every time once there is a transaction. -Asch platform is not a pure currency system because it has to contain various applications. In general, account mechanism is a better option under this circumstance. -## Relational Database vs Non-relational Database -At present most blockchain system choose to use lightweight non-relational databases, such as Berkeley DB, LevelDB, and so on. Usually these kinds of database support some simple data structures, like B-tree, hashtable, and they are not able to manipulate data through SQL. Generally non-relational database is good enough at the application of electronic currency system, but speaking of application platform, it is not the case, especially when we talk -about finance, bank, e-commerce and so no. Within these fields, the relational database is wildly used because of its following advantages: -1. Transaction processing -2. Very low cost of data updating -3. Capability of complex query (using join, for example) -We decide to adopt SQLite, a high-performance lightweight embedded rational database. SQLite can support up to 2T data volume, and the data file can be shared smoothly among different byte order machines. The most attractive feature is SQL, which is very suitable for DAPP developers. -# System Highlights -## Ease of Use -### Development Language -Developers can use JavaScript and numerous npm libraries to create their application. Unlike C++ and transaction script for Bitcoin and new Solidity for Ethereum, JavaScript is more popular, has more followers, and is easier to master. Furthermore, by introducing relational database, Asch platform make decentralized application development more like coding -traditional web application, hence it become the easiest way among all the current development approaches. -### Toolkits -Asch system provides a command-line tool to rapidly create a sidechain on which any kind of applications can be created and deployed. Also the system provides a series of API, involving consensus mechanism, strong random number, database, and cryptography, to help users creating complex smart contract applications. -### Deployment -To deploy the applications, all the developers need to do is committing their DAPPs onto Github, and registering in web wallet or light wallet. After that DAPPs will be presented in App store to download. -## Flexibility -Developers can freely customize all parameters in their sidechain, such as generating speed of block, transaction type, and transaction fee, etc., even can carry out a new consensus mechanism. -## Security -One well-known highlight of Asch system is an consensus algorithm based on improved DPOS, in detail, the system embedded a high-performance Byzantine fault tolerance algorithm upon original DPOS hence significantly reduce the possibility of network forks. As long as there is no more than 1/3 nodes which are attempting to attack together, the system will not generate a separate chain, or a fork, so that the risk of double payment will be avoided. Secondly, Asch system closely examined every detail with security consideration, such as passphrase hint based on BIP39 algorithm, two level trading password, and multi-signature, etc. -# Technique Specification -## Consensus Mechanism -The consensus mechanism used by Asch system is based on DPOS, a mechanism of delegates vote, but applied an optimized variant algorithm of PBFT, which can make loyal nodes reach an agreement, i.e., not fork, in O(n^2) message complexity and O(1) time complexity when t < n/3. Here “t” refers to the number of Byzantine node (on which any situation can happen, such as network delay, machine shutdown, or malicious attacks) and “n” refers to the number of all nodes. -### Delegates vote -The delegates vote mechanism of Asch is similar with the one of DPOS, which is composed of 101 delegate nodes. A delegate is a trustful account voted by community, and 101 delegates who have the most votes are allowed to running the nodes which maintain the network and generate the blocks. Those accounts who cannot be the top 101 are called “candidates”, who can be delegate once they get enough votes to become the top 101. -Every Asch user has the right to vote up to 101 delegates, and the weights of vote is determined by the amount of XAS owned by this user. -Each voting round will generate 101 blocks, and the ranking change of each voting and delegates will be shown in the next round. The new block will be generated in 10 seconds after the previous one, and then be broadcasted into network and appended in the blockchain. Once new block is added, the confirmation count of all transactions before will be increased 1 time. After gaining 6 confirmations, a transaction can be treated as “safe”. If the amount of transaction is small, less confirmation count is allowed. In other words, larger confirmation count is necessary when it is a large transaction to improve the security. -If some failures occurred in a few delegates, such as under attacks or shutdown, the block will miss, and this issue will be recorded. This problem has an impact on the online rate of this node hence the voting of community. Therefore the election of delegate should be treated solemnly, for example, a delegate needs to have experience on running a website, ability to maintain the nodes stable, so that the security and stability of the whole system will be strengthened. -### Byzantine Fault Tolerance -The major difference between Asch system and DPOS is reflected in the second part of the algorithm. -What the DPOS applied is, first, randomly sorting the delegate list of current round (to make sure the delegate of next round cannot be predicted since the order of delegate of each round will be different), then let delegates create block in turn through a round-robin way. The main issue of this algorithm is that, if a delegate attempt to attack, he may broadcast many different blocks, which may contact double payment trades, to “fork” the whole network. It is no doubt that if only one delegate betrays, the fork will be solved by syncing with the next longest chain. However, it will take a much longer time to eliminate betrayed nodes as their amount is increasing. A few betrayed nodes are enough to have a serious impact on system security, which means even we can gain 6 confirmations, it still may not be sure that the network is safe. -To deal with this problem, we introduced an algorithm known as PBFT (Practical Byzantine Fault Tolerance). Same as DPOS, PBFT also chooses delegates in the way of round-robin. The different part is there will not be a block generated after delegates are voted. In fact, there will be a piece of propose issued to determine the hash code of next block. Only when more than 2/3 of all nodes agree with this propose, next block will be generated. The hash of next block must be the same as that agreed with all delegates of current round. Essentially, the introduction of PBFT solved the issue of abusing the delegates’ right, and improved the control capability of ledgers. -## Sidechain and DAPP -Asch system provides a command tool by which developers can easily create a basic sidechain system. Developers are also able to fully customize their sidechain system, including its own database, consensus mechanism, trading mode and account architecture. Sidechain system can be hosted in the clusters of nodes of individual delegates, so that a partitioned mechanism can be naturally generated hence avoid the rapid expansion of the main blockchain. -Every DAPP is related to a sidechain. A sidechain’s core code is developed by nodejs, but UI can be programmed by any of front-end techniques such as QT, HTML, or JavaScript. The communication between front-end and back-end is usually implemented under JSON RPC protocol. The developer or owner of a DAPP can trace the usage of their application. Compare to cryptocurrency that is based on community consensus, DAPPs are more like a private company. All the transactions within a DAPP are handled by main node, which is run by DAPP’s owner. The owner of DAPP must have an Asch account, like a multi-signature account, whose major objective is to create a consensus of a new block and to sign it in DAPP’s main node, just like multi-signature wallet. Once a new DAPP is created, and signed in main node, the SHA256 hash of this block need to be calculated, and submitted to the main blockchain of Asch system as a DAPP block by the owner of it. When Asch’s main blockchain received information of a trade including DAPP hash, the delegate will compare it with the previous one and then store it into Asch blockchain. Then lately when main node is in sync with network, the user will validate all DAPP blocks through Asch blockchain, which means it is impossible to remove the previous DAPP block from main blockchain. Developers can replace Asch blockchain with Bitcoin blockchain to use the same functionality since the usage of Asch API will be the same. The security of DAPP can also be guaranteed by Bitcoin blockchain. Developers can take advantage of both XAS and BTC as the currency of their DAPP. In the case of money in-and-out when using a DAPP, the Asch coin or BTC will be delivered to a DAPP address, and appropriate amount of money will be shown in that DAPP’s account, ready to use. The deposit mechanisms of both BTC and Asch are the same, which is to deliver to a particular DAPP address, and then the appropriate amount will be shown in -the account. In every DAPP the account is created by the developer, so all deposited BTC or Asch coin will be saved in related address. Considering the security, only those DAPP accounts owned by trustable signers with multi-signature are recommended. A withdrawal from DAPP is main node’s responsibility. When someone requests a withdrawal of money, DAPP main nodes will acquire the request and move the money from DAPP address to Asch blockchain or Bitcoin blockchain. Developers are allowed to issue a token in their own DAPP, and to use it as the currency of this DAPP. These kinds of token can be circulated in DAPP like XAS or BTC, but are not allowed to transfer from one DAPP to another directly but through Asch main blockchain. -## Sandbox and VM -Sandbox is a running environment that restricts program’s activities under the security policy. In early time it was used to test suspicious software, for example hackers usually use sandbox technique to run some virus or unsafe program. The implementation of a classic sandbox is usually to intercept the system calls, to monitor program’s activities, in order to control the usage of computer’s resource such as disk I/O according to user’s policy. -Asch system implemented sandbox mechanism by using VM module of nodejs. The VM module is an encapsulation of JavaScript V8 engine, which is used to run the pure JavaScript code. But it cannot use system APIs like file system or network communication. It also is lack of “require” function therefore the third-party libraries cannot be imported smoothly and even worse, the modular development cannot be conducted. This requires DAPP developers to use a “browserify” technique to bundle all the third-party libraries they used to a JavaScript file, so that Asch system can load it and run. Some necessary system level API will be provided to sidechain through IPC (Inter-Process Communication), which takes into account both security and functional completeness. -## Transaction -Asch system has built a abstract transaction layer, on which almost all the functionalities of system core are established, such as transferring, voting, application store, deposit, and withdrawal. The sidechain itself can also implement its own type of transaction. The main difference between each transaction is their types and assets. The data structure of a basic transaction is as follow, and the extension of transaction will be saved in different asset table according to its type. -```sql -Transaction { -required VARCHAR(20) id; -required VARCHAR(20) blockId; -required TINYINT type; -required INT timstamp; -required VARCHAR(21) senderId; -optional VARCHAR(21) recpientId; -required BIGINT amount; -required BIGINT fee; -required BINARY(64) signature; -optional BINARY(64) signSignature; -optional TEXT signatures; -required BINARY(32) senderPublicKey; -} -``` -Let us take a vote transaction as an example: the vote entity is connected to a basic transaction through transaction Id like follows: -```sql -Asset_Votes { -required VARCHAR(20) transactionId; -optional TEXT votes; -} -``` - -## Account System -Every account in Asch system consists of one passphrase, a pair of public/private key and an address. Users can also set their own secondary password. Note that the difference with Bitcoin here is that each account is related to only one address, instead of multiple addresses and private keys related to one wallet in Bitcoin. -Passphrase is a mnemonics used to produce real wallet in line with BIP39 standard. The mnemonics is much easier to remember for people than other binary or hexadecimal characteristics. The way in which a passphrase is generated is to convert entropy on a multiple of 32bit into several words, particular in Asch system, the length of entropy is 128bit and it will be converted into 12 words. The passphrase, as a top-level password, is maintained by users instead of published in public. Once users lost their passphrase they would lost the ownership of their account. A passphrase is generally like follows: -barely decline dust stamp protect color certain cup arena busy latin shell -A pair of keys includes public key and private key, which uses SHA256 hash of passphrase as seed and is generated through ed25519 Edwards-curve Digital Signature Algorithm (EdDSA). It looks like this: -``` -Public Key: -9989388b220a13465e49f52df5ba28ba08eb1e7a973320347f9687a107dc2f9a - -Private Key: -91e891f653e3ed0232d8c7de2e72b625d50d48593fc0fb570c0db25c5e44569a9989388b220a13465e4 -9f52df5ba28ba08eb1e7a973320347f9687a107dc2f9a -``` -The account address is a big number generated by reversely converting the first 8 bits of SHA256 hash of public key, shown as follows: -``` -5034187504202890358 -``` -## Client -Asch platform provides three types of clients: -The full version client is a perfect solution for those super users, delegates and developers, running on Windows, Mac OSX and Linux, but only Linux system can run delegate nodes on which blocks forging is enabled. -The lite wallet client allows users to connect network through full version wallet or API, but it is necessary to open all the right of this API by the owner of this full version wallet. A full version wallet can download the whole blockchain from other full version wallets through peer-to-peer network. -An ordinary user usually use lite wallet to manage his/her Asch account. The lite wallet can run on Windows and Mac OSX platform without installation. It utilizes the system built-in browser. It needs to be noted that the lite wallet cannot run as a network node since it would not download the blockchain data but only links with other nodes through HTTP protocol, which have several advantages: first, no blockchain data downloaded would keep the volume small; second, no private key broadcasted to network make it possible to make all types of trade since all the data will be signed locally. If you want to run a delegate node, you can use lite wallet to register a delegate account, but cannot run delegate node through it to produce block. In order to run it, downloading and running a full version wallet in Linux would be necessary. The DAPP users can take advantage of lite version wallet to manage installed DAPP. The APIs of both DAPP and node are available for developer to invoke, so that it can make them rapidly and easily creating JavaScript DAPP through Node.js. -The mobile version client allows users to manipulate their own Asch accounts on their mobile devices, both iOS and Android platform. They can download the client from AppStore or Google Play. The backend of the client is based on our solution applied in our desktop version, but mobile client applies responsive UI instead to fit the mobile device screen and changes some interface mode according to the device characteristics. This mobile -application brings mobile user-friendly interface, like Bitcoin or some major bank application, and of course, the mobile client can also support all the DAPP you like running inside of it. -## Performance -All the information of a transaction usually occupies about 100 bytes. Let us calculate how much network bandwidth will it be demanded when system achieve 10,000 TPS. Since the interval of block production is 10 seconds, each block needs to carry 100,000 transactions, which make the volume become 10 megabytes. This 10 MB data needs to be broadcasted to whole network, so even under the best situation, 10 nodes will be achieved in the first step, and then 100 nodes in the next step, and each step is supposed to complete in 5 seconds, which makes the necessary bandwidth be 10MB x 10 /5 = 20 MB. Considering the bandwidth loss and unexpected circumstance, we think that bandwidth needs to be at least 40 MB to satisfy the 10,000 TPS throughput. Although this volume of bandwidth is not easy to gain, it can be sure that it will bring much more benefit to delegates than the cost. In Nov 11, 2014, the peak throughput of Alipay payment system reached 85900 per second. There is still possibility for optimization of trade throughput in Asch system, which is our major investment in the future. -# Scenarios -## Token System -The “hello world” program generated by Asch toolkit would be a basic token system. -Developers may not need to write even a line of code but adjust some initial parameters in genesis.json, to publish a token system. Like sub-currency on top of Ethereum, the token in Asch system can represent gold, stock, mortgage, or any other type of asset. These tokens can be traded with XAS transferred in sidechain in a decentralized way, and with any other currencies in a centralized exchange. -## Mediatory Contract -Let us assume that a buyer wants to trade with a person he/she does not familiar with. Generally if the trade is well-doing, both would not hope the interference from a third-party. But if there is any issue occurred during the procedure, like the buyer does not satisfy with the items, they would like a mediator to help solving the problem. The mediator will ask both sides to present some evidences and then make a decision, for example, ask seller making a refund. This business process can be described as follows: -1. Both the buyer and seller of the transaction choose a mediator together. -2. The buyer creates a 2-3 multi-signature account by using a public key shared with all the -three parties. Then the buyer transfers the money into this account, then signs and -publishes a transaction in which the buyer’s account and seller’s one are treated as promotor and recipient respectively. At this moment this transaction would not be confirmed immediately until two of these three people have signed. -3. The seller dispatches the item to the buyer. -4. If the buyer received the item and satisfy with it, he/she will sign the transaction with -his/her private key. After that when the seller sign the transaction again, it will be -completed successfully. -5. If the buyer does not satisfy with the item, he/she can launch a complaint to the -mediator and show evidences about the item with faults. Then the seller also can show evidences against buyer’s one. Finally the mediator would make an agreement with one of the two sides of trade and sign this trade together to complete it. -## Decentralized Exchange -There are two types of decentralization according to legal currency support. If legal currency is not supported, the full decentralization can be realized; otherwise only half decentralization would be supported. In this case, legal currency can circulate through gateway but transaction information would be made public. -Full decentralized exchange can still be divided into two types: one is peer-to-peer trade through “atomic cross chain exchange API”. The other one is pending order, which require seller transfer an amount of asset to Asch sidechain from other blockchain. This moving should be achieved by the SPV proof of frozen assets of main chain. Beside, with the support of relational database, it is easy to create a well performance matching engine by using union-table query and index. -## Existence Proof -Existence proof is used to register copyright, patent and so on, which is based on the idea that to prove an existed particular file by saving hash code of this file into Asch sidechain. In addition we can add metadata such as timestamps, owners’ digital signatures to prove when they own these files. This kind of information cannot be forged or revised, will not expose the privacy data and ready to verify at any time without any third-party authority. -## IoT (Internet of Things) -There are numerous of online devices existed in IoT, which make it difficult to manage all the devices and identification of every nodes by a single authority. Asch sidechain is an excellent solution for it. Firstly, it can deal with trustiness among different nodes. It means that all devices connect to each other to be a distributed network, and trade between devices can be verified by consensus algorithm, and can be traced, audited, and analyzed. Secondly, different types of devices can be connected to different side chains, and this natural partition mechanism that we mentioned above can prevent main ledger from explosive -increment. Let us imagine that a vending machine in a sidechain based IoT can not only monitor and report its own stock, but also analyze historic trading data to select suppliers to submit the tender, and then automatically complete payment. -# Conclusion -Asch system is a decentralized application platform, which is designed to lower the threshold for developers, such as using JavaScript as develop language, supporting relational database to save transaction data, and making DAPP development be similar with traditional Web application. It is sure that these characteristics are very attractive to developers and SMEs. The ecosystem of the whole platform cannot be improved until developers make a huge progress on productivity. Also, Asch platform is designed to be open for various fields, not limited to some particular parts such as finance, file storage, or copyright proof. It provides underlying and abstract API which can be combined freely to create different types of applications. In consensus mechanism, Asch inherits and enhances DPOS algorithm, by which the possibility of forks and risk of duplicate payments would be significantly reduced. Furthermore, Asch sidechain mode not only can mitigate the pressure of blockchain expansion, but also make DAPP more flexible and personal. Asch system, as a proactive, low-cost and full stack solution, will surely be a next generation incubator of decentralized applications. \ No newline at end of file diff --git a/docs/assets/dapp/cctime_file.png b/docs/assets/dapp/cctime_file.png deleted file mode 100644 index ef35ecdd4b73b2eeede1d543a2ce60c31ae518ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68119 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

Ui+t^}!R-3`Qiiq%4cp%s&tCKo1F(o_W0)95%pk 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%0A8V^9*Z+KZ;&5 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 diff --git a/docs/assets/dapp/custom_api_example.png b/docs/assets/dapp/custom_api_example.png deleted file mode 100644 index f2974c69ab0732be74c994b87976887a0092e962..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52146 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 diff --git a/docs/assets/dapp/dapp_variables_article_max_id.png b/docs/assets/dapp/dapp_variables_article_max_id.png deleted file mode 100644 index ba034e19d9cae1893a4ff142773c7753c61240f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28699 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

sZ!&?Bv{nNKfT;r|nB82fx{R)sED9IC{pKkqiI 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 AkN^Mx diff --git a/docs/assets/inbuilt-modules.png b/docs/assets/inbuilt-modules.png deleted file mode 100644 index 8e84271e48e7c8ba2181492d5fef2b1e666e5708..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20739 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

LP&X4mRMz~)f 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 diff --git a/docs/assets/process-structure.png b/docs/assets/process-structure.png deleted file mode 100644 index d414e36cca5ae66c3c2eaf94f2061c9f325c5942..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16085 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 Z8;i=qf&1rNz!7Pf=1pC-{2Nw({x5!LJ~aRU diff --git a/docs/assets/sidechain-deploy.png b/docs/assets/sidechain-deploy.png deleted file mode 100644 index 32ec1ceace1b07fc68c3a8c90b5980932383299e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18839 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 diff --git a/docs/assets/win_install/install.png b/docs/assets/win_install/install.png deleted file mode 100644 index 3d26ab7875462d078281c84ba57e162ea9356cb1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19470 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 diff --git a/docs/assets/win_install/node.png b/docs/assets/win_install/node.png deleted file mode 100644 index cfd47c11011102a4e60e08231067e006294da2b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1621 zcma)-ZB){C6vuyRR$Ah+)@Yg8)U>58+@{T;h-UU+>Y@izl+-LT(I#0b{K3lku-SBJ ziO-r2GZdeANI|fgv!+f=5#^szOUxqXnFwZx&UW@@=j`n4%{}+U_xs|W`~BRT9TF5^ zVg8{x0Kj7Jo?Qn4FbZ4hBUUb7s^fO-Q~;J+@7;wxbg@)Db|B%oyLDz1^Fi$8gw#t$ z!XmrgO{rHBjB`wSnI4lHuK6P*S1%bK%du% zOhc-+U(8Muj<$J{ky|(rdsfDMJj8|SCC^ud6i%&%6Zm~6TTc(Gl3T+Xij_&D)Dk-B ziDl^oblo|hqMLEbmtXnT(k0~f9MVs-?Hz{ z&=NYi3m;{m6D944@)47db;n=d#%P}+#xOz5i!q`EApsda1q<+wy}pyoIfk1)-fk4m z{wjSAY^>;Q)!LcJ6`GnrEbgqe%TC}mSEi{l< zV9lx9Ol%r+l{z|+X_dynex1j;r|lkVLEK@yMCafCzRydc-wJl{V-7~8(FQ-u*+7et zS%R&JxkoH?NI~B3+D+C(G(7^JSlMG#-r-xU{I}6u~I1%oLYl$ z?f1MB=mHUK$IZoOyedlXB5@e7=k`K0@`4j^iU^S~XRP4nL3Z-YV#%!3iV5Owpm(3y zh*NKTz&n+NIJP8iPf1BR9UsG4G-&uE8lutheYZDPo2EVb2TAY7L}FKgdn?1hd%Gon zQ}ExCCRiX4EN*@ap=~fWZ#xuI7@K(uuqPmQiJy1QKs52p;&NCHTOOxku`o@^_x`2@ z+TYNCR|rva@lJ;yGrctL%qbXa=WI?)D8RnVpf;g)O9E&6M=Wk{EHsE<4kB=BHiqw1uFLN z43Xq`%SJbm6#j_>JpjQaJ-9osh6+dJR$+AFoJfmTrgIuu_)T8nfx`*>Gd!5oIvQWB zO&zO0!aCW8cUMdhN@nwKrVt!@#y{?HCsY)+3k{>(0}pf}U9D>&Tk-e;yl}y#e?T;n zT*P2UefZj2UP|};c_yoORRYx0I2Wv77_R%~uE!mkmt1mrn)JkU%|Y*J+Y_k6Pb!nI z)^(NdXpT7-p{*?!R_VKuG3ZE-z++QYCNi_<0+p?QU=hUIM%r1)(J`VGmcHw8=gDoz zlay4MX0W=w0z<7|mlXTOOk5i)vtC6B@Ocoiq6(G|qhwQqA`wZF>4txPuS%)^-9Bq< zD-%k0X1Y2N$t=S-tHS^?x&{TnXT%8`PDyOi=}eI8z5f5=|GJR>o(+-7fxE}PJX^Ev R#L~L}d;NoUv3-wU{u8Gf8two9 diff --git a/docs/assets/win_install/python.png b/docs/assets/win_install/python.png deleted file mode 100644 index 336dcb64c9467e01ed9a25b2ebb9a86d280a083b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1578 zcmbuA`BTyf0L8yvS=zB>n^`7hYssc-c4*KDh*lb2savUeY^CNF8s5hjB+cAxqEaKT zLJKH!J+>6KJn+b@%p(sdFCbJ9GDN^s1lD%;KiFU1ym>#pc{87R*L}Q>tufkS1OUJq zcQ;pG0MG%KJ$mJeW%cJ_9|3@Y%-z-5Ke=Rj)H8bc(8gvQOw{P7| zO8K_#3RJW}KS-aZI>H7Mg-Uw(#b?UU@ZksqJzoGFB^V8BQZj?st#Syn1KvupJ6$)v zk4a-h1)h99wUpmrZ2gHa)#N>C`u?B|4unSY7jDhnZu92JEemGR0ngNDoZIWPRvCnM z!PdPd_B;$z&{tU>f1(=pu5-B~hZrZy-njXA+~f>ra!ccsga$szhuFg4wG-z(Ur2kw zh8R`VNR2J!k|flvJ0KnTY5+NflcjhBORe10@lNSrcc_iJ1Zel9)H<236%bgEr25f$ zh2j7qZGK;q)A|nPU_j0QIqJnrn*{X|%fI7sQ>C_Cf{}(I6Z>WLY@vuE)nM`0Kc$Oh zFT^VIit?+9Z1mfJO=f(d`CIB_1^(zmdUz%2)majAV?S&FvNd6Af3Wj~biZ46G=kgc zNlNGi%pi1|-&alo=0QDv+!>|E-n{~h^52@qe@)5_R`ob#wMJ(FX>ptw9BIDkRkp+abMFEE-#}j=6-=@p~Rab?+|98V%mhK72)>E zI9~Vq8+Rh6R%eY_jX5ApzEAEC_E-r^&~N?bskSHWZ;`Rk0@$x_M5b@r3j1_`krhYh zf!NX%Q-f64eY^M*z=4fVXZ+nM7m7GZt_j>n?Hj!d6HAi{dLuL`)Pa8V%6!x+lM3eeIh{sboc_}eNn$9K&0dnUX3^~EdZZ;RHApO zAu(~UtqA~kZZ;%({V=0bYNEdkkiHJ&e?%t^@T%2%{PI945_nRglWvrnDm$pwe^}dC z-dKRoKQCduV|bGOL+@gWxz3V;?}+WdEh)dnw}@Fm#S+U0ndL)GQ2|}Y4Qq3!?PPk2 zN~Z_Sl`30aMT0r{+)EzvQhP z;JX}u>_A7AHHkzL&qrsScpt?QiJzOwpHsN_xjvmchaGmGo>%k?R^{A5_*@al4q2?t z#<94!>PMqN5Hx2wfo9xax}mH*nj5x|T+!*v>Cs{mK=JS*!A0$A|BZtC(Fr*h^tRn_U1!`PU!Ulfo;}$L`{{qAJK08c-&rtp_1px5d2eyAs1IJ4RxG^Gpq-!Tw=SDT=IAC@k@hIMr@H?h| zfDH-$BKR$}+ry8DH9!%Hg+ie$wQ=pe&WXknug82YOS=Vu1o7PF$X(Z@Up7pUoPUI8 zzK$f5VuJe}7Uy=Tji)n<&gPCe&S1F?@?8us4=q(bWhAbnn_VGeLqbAcb2yxDVd)4; zHUvpn&DAamPBr&bDu-2URj9EpqNaiC3r|W)k{SS)(=>*&KRbByZcf9OKLBt);^kU} H4$Jrl3hp+q diff --git a/docs/assets/win_install/run.png b/docs/assets/win_install/run.png deleted file mode 100644 index 28d49f1e2062eee894d8f9dbda5a792a9f7d7a96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 93888 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

d5+-7K1ngmwS7vetaM&yNaO~C&$92HAV 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

8D7#xt`G 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 diff --git a/docs/assets/win_install/sqlite3_verify.png b/docs/assets/win_install/sqlite3_verify.png deleted file mode 100644 index 7cd4303655f6dde00c6cf7a79a037f1c90fa8d43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3750 zcmdUy`B&2U_s8F6spXbAIrS-_GCxkKS(;@kI%6f8C6g5@F4$NaZfK<`2v}KJE@Y{+ zLZ;YaNQK}sBIelWh)be~q5;)dqT!05tY7>7^8FjWzua?Q=f2Ll=XKBX^|<%m{5=?I zzUDt`001x#3^)`500uM5ex8ZZvfc2qK?eX9$$^J{JDK@N_7PSyT5r|zNqObKpwlC) z`C7}{{oC^+%UwQELq&@w*V*IscTI|K?t~XR9dVK>4RW=J&&W6LtJ>fkf>yP#^rf9x zH!bFHaB782hSY1?N5Eixwjlsas<^|emh;Irv={&Zc?O$-oZKpN39&sE&b!eOjR#to zTKLE>=6`^FvQzCf!s+!$A%QZ*io(c_GUulGis6a9A(UY$@%h*^>d)t{kN7@g>ey>| zQ;E-jL8Rv%|L!BycYR(lHGe3~aB(WAnTA39HXIsItAv*6Ot)|*%r<*UJ1?_(6Qt;? zlfO9X?_bS4sop)lqT@)Dan0j_+90YhaBspBk08YyUGg%ytiZ20=SIMPIN+JQP^WF#{q^wzuK=3Bj0{=QRAu-K+HgOF6(Z@^wb}B?mlUa>z zg5a5RHRrRpiCtE%xGXX6=NN;sRx{(TpV(EBc+7X+UP4y&e7;{^=B6u)y;K(3;HtC& zvYfH2qda$DcD?hjB5vSG9+zt)RD!NmSYV5l@$w_MqVQB$q@%v?F0~H-=#iQ)bbd+b zZiS!$#|ub5L2wwcbEn)2f?~CW%kF$j7~8P`vP{0s;5o*RLu-kp?Gx=LE$k)%K6n7} z&!6J<2ZiU{R1g%O!D8ER9BOJ|4TPX21ot)gbuIR#NKXAyW$q*LfQ&JO3>(fUy=l$5 zK3xci>B>qm&UsOJY8-tR-UYcsAMB3SeZQ=5SZk82zag#uaM@%eiNqZOW{@{({Ce>> z_h6UYDr5$d(60Z}&2_wGWCV38oZT#*t|38tYX}27CxoG9(0(w=4yGf^A;=q>P+mKl z7igCUz2j^t2$k9!(Vwz3m|M$sAc}MbkNhL9?V>H>PLj_iYn`vPcT?GIj`96cXiZS9icx9`!JRYE=`!RUi+pgtVXC@;09EOS) zouyC~KVT^iJjo~OziY8-}qPP|Fc{?l1=cYIzA@WdpV_iDr}RTcP3!);=El!dn|pUWdU z_r&J#h2jYTh#9-7R5#rItZe$6n8g$G7QP$5>d3y$?WBANeT}xR#>L@GZUw{+&PJ8% zyJ{jPS>#%(<>LxC`Eta9xS$NnR~dq)9NwVNPux(9wL}~)fuZS>a|LjB^&**1fKM{2 ze;GOZUa2geiYEM9X(1u^WGlv=4KMlkK81V!*0qbfCOxX$jO|K-wA!j1cE3ceSH1qNuN6ft?et@5RHdQ8vPGVTHd*o7l)~bqy-0G;5!XwDWR^C&0eUf2O9bSYVjL?hl z-a_9TyXPF^UFn#~++Wx=)K7t&qx3R@Gya&Y@C8*Y+{g2QpaPZz(To9M?}cY?CI*qT- zYkbVt!Bw;osD5gP{+yny)ood8qO>?j`aryA{(as9quArcd7DyUDvtAbt7SIzB#`=4 z{&hby&;Ygu`l81(?UhFivm;vP76=Y&B0Z%Fnn**8nOe&nY$C=+Ww)4kW*8PQ%q6gd zf}d#3U#0oOL>LVRNIskzA1oN}*w`Q2IvrJ46}sz8Vi|fg*-ypI&!)&Tds&cD z95<6EX5uQd+4L+0b51!xsMLBdkgo9Iy+@jhXCsJ�XXihY6O;VZA!LWh^GH^xIhF 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

6|Mcu5cJE^|_HtE52a0 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 W#n8PlQWm)c{ymjdl0iUT`2P git clone https://github.com/AschPlatform/asch.git -``` - -下载后就可以参照该项目的[README](https://github.com/AschPlatform/asch/blob/master/README.md)进行后面的安装、运行操作。 - -## 3 安装asch-cli -建议用nvm安装node和npm -``` -# Install nvm -curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash -# This loads nvm -export NVM_DIR="$HOME/.nvm" -[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" -[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion - -# Install node and npm for current user. -nvm install node 8 -# check node version and it should be v8.x.x -node --version -``` - -``` -> npm install -g asch-cli -``` - -注意这一步不要用淘宝的```cnpm```, **有bug** - -## 4 在本地创建一个应用 - -首先要进入你的asch源码目录,并确保localnet启动(访问http://127.0.0.1:4096,如能打开钱包页面说明启动成功) - -``` -> cd -> npm install -> node app.js -``` - -### 4.1 创建你的受托人账户 - -每个dapp都有独立的受托人,这些受托人也是默认的记账人,他们负责区块的生产,跨链资产的中转,与此同时可以获得交易手续费。 -注册dapp的时候,我们只需要收集受托人的公钥就行,为了权力分散,最好每个秘钥分别由一个人保管。 -这里为了演示,我们一次性创建5个账户,一个dapp最多有101个受托人,最少是5个。 - -``` -// 注意这里的密码都是演示用途,且不可用于正式的dapp中 -> asch-cli crypto -g - -# 接下来输入 5 即可生成5个账户 -[ { address: 'AijfU9bAE6Jpt5ve7zG3LoriDamH67eLb', // 地址 - secret: 'easy snap cable harvest plate tone planet yellow spot employ humble what', // 主密码,也叫一级密码,可以生成公钥和地址,实质为私钥的助记词,必须记录下来 - publicKey: 'a437a1d4bedf738e8620920ef29542644e3366c635b16fc9faa6f5db744bcd5c' },// 公钥,用于4.2章节配置受托人公钥 - { address: 'ABGGUL5D2SoBaQTqDMAb3u9RdUjYBcmRxx', - secret: 'adjust edge exist hurry joke carbon spice envelope battle shuffle hawk thought', - publicKey: '522cdc822d3bec74aa5c4e972ed6cba84850f9c4d521e43fe08675e9e4759bb9' }, - { address: 'AMg37s4avDUojJd6d3df7HPA3vqtRRwved', - secret: 'survey spoil submit select warm chapter crazy link actual lonely pig grain', - publicKey: '6ee3ae36166f69e8b9408d277486c9870f40c1b7c16016328737d6445409b99f' }, - { address: 'AL5p8BHzhCU3e5pkjMYbcjUSz771MrQcQr', - secret: 'march struggle gap piece entry route kind pistol chunk spell honey summer', - publicKey: 'ad558e44b347a54981295fcb5ee163c2915ca03536496129103e9d72c5025d69' }, - { address: 'A2WassKticpB7cx15RZfenBekthwmqXRXd', - secret: 'response modify knife brass excess absurd chronic original digital surge note spare', - publicKey: '6b2594ebeee9b072087e5f1e89e5c41ee2d73eb788b63abeedf5c04664f0ce5b' } ] -``` - -## 4.2 生成应用模板 - -应用模板包括注册dapp必须的元信息、创世块以及一个初始的目录结构 - -生成应用模板需要使用`dapps`子命令,如下所示 - -``` -# 生成应用模板的时候,最好建立一个新目录 -> mkdir asch-test-dapp && cd asch-test-dapp -> asch-cli dapps -a -``` - -接下来,我们要回答一系列的问题,以生成应用的注册信息与创世块 - -``` -? Enter DApp name Asch-test-dapp -? Enter DApp description Demo of asch dapp -? Enter DApp tags asch,dapp,demo -? Choose DApp category Common -? Enter DApp link https://github.com/AschPlatform/Asch-test-dapp.zip -? Enter DApp icon url https://yourdomain.com/logo.png -? Enter public keys of dapp delegates - hex array, use ',' for separator //这里是4.1章节生存的5个受托人对应的公钥 -a437a1d4bedf738e8620920ef29542644e3366c635b16fc9faa6f5db744bcd5c,522cdc822d3bec74aa5c4e972ed6cba84850f9c4d521e43fe08675e9e4759bb9,6ee3ae36166f69e8b9408d277486c9870f40c1b7c16016328737d6445409b99f,ad558e44b347a54981295fcb5ee163c2915ca03536496129103e9d72c5025d69,6b2594ebeee9b072087e5f1e89e5c41ee2d73eb788b63abeedf5c04664f0ce5b -? How many delegates are needed to unlock asset of a dapp? 3 -DApp meta information is saved to ./dapp.json ... -? Enter master secret of your genesis account [hidden] -? Do you want publish a inbuilt asset in this dapp? Yes -? Enter asset name, for example: BTC, CNY, USD, MYASSET XCT -? Enter asset total amount 1000000 -? Enter asset precision 8 -``` - -有几个注意事项 - -1. `DApp link`是为了方便普通用户自动安装,必须以`.zip`结尾, 如果您的dapp不打算开源或者没有准备好,可以把这个选项当做占位符,它所在的地址不必真实存在 -2. `DApp icon url`这是在阿希应用中心展示用的应用图标, 必须以`.jpg`或`.png`结尾,如果该图片无法访问,阿希应用中心会展示一个默认的图标 -3. `How many delegates ...`这个选项表示从`dapp`跨链转账资产时需要多少个受托人联合签名,该数字必须大于等于3、小于等于你配置的受托人公钥个数且小于等于101,数字越大越安全,但效率和费用越高 -4. Dapp的创世块中可以创建内置资产,但不是必须的,内置资产无法跨链转账,只能在链内使用。在主链发行的UIA(用户自定义资产)可以充值到任意dapp中,也可从dapp提现到主链,这是dapp内置资产和UIA最大的区别。“一链多币,一币多链”指的就是主链可以发行多个UIA,而每个UIA都可以充值到多个dapp中。 - -## 4.3 注册应用到主链 - -注意这里的`主链`不是指`mainnet`, 每个`net`下都有相应的主链, 主链是相对Dapp(侧链)而言。 - -我们可以使用`registerdapp`注册应用到主链,如下所示 - -``` -// 先生成一个dapp注册账户 -// 注意这里的密码都是演示用途,且不可用于正式的dapp中 -> asch-cli crypto -g -? Enter number of accounts to generate 1 -[ { address: 'A9rhsV5xDny4G45gD2TXmFFpeiTfvAAQ7W', - secret: 'possible melt adapt spoon wing coyote found flower bitter warm tennis easily', - publicKey: '74db8511d0021206abfdc993a97312e3eb7f8595b8bc855d87b0dc764cdfa5a8' } ] -Done - -// 在http://127.0.0.1:4096用localnet的创世账户“someone manual strong movie roof episode eight spatial brown soldier soup motor”登陆(该账户中有初始发行的1亿xas token),然后给A8QCwz5Vs77UGX9YqBg9kJ6AZmsXQBC8vj地址转10000个xas - -> asch-cli registerdapp -f dapp.json -e "possible melt adapt spoon wing coyote found flower bitter warm tennis easily" -# 返回结果如下,这就是应用id。每个应用注册时返回的id不同,请记下你自己的应用id -0599a6100280df0d296653e89177b9011304d971fb98aba3edcc5b937c4183fb -``` - -使用浏览器访问`http://localhost:4096/api/dapps/get?id=0599a6100280df0d296653e89177b9011304d971fb98aba3edcc5b937c4183fb`, 可以查询到该dapp了,下面是返回信息 - -``` -{ - "success": true, - "dapp": { - "name": "asch-dapp-helloworld", - "description": "A hello world demo for asch dapp", - "tags": "asch,dapp,demo", - "link": "https://github.com/AschPlatform/asch-dapp-helloworld/archive/master.zip", - "type": 0, - "category": 1, - "icon": "http://o7dyh3w0x.bkt.clouddn.com/hello.png", - "delegates": [ - "a518e4390512e43d71503a02c9912413db6a9ffac4cbefdcd25b8fa2a1d5ca27", - "c7dee266d5c85bf19da8fab1efc93204fed7b35538a3618d7f6a12d022498cab", - "9cac187d70713b33cc4a9bf3ff4c004bfca94802aed4a32e2f23ed662161ea50", - "01944ce58570592250f509214d29171a84f0f9c15129dbea070251512a08f5cc", - "f31d61066c902bebc80155fed318200ffbcfc97792511ed18d85bd5af666639f" - ], - "unlockDelegates": 3, - "transactionId": "0599a6100280df0d296653e89177b9011304d971fb98aba3edcc5b937c4183fb" - } -} -``` - -## 4.4 部署应用代码及子网络 - -现在我们把4.2章节中创建的模板代码拷贝到asch的安装目录下的dapp子目录,并改名为dapp的id - -``` -> cp -r asch-test-dapp path/to/asch/dapps/0599a6100280df0d296653e89177b9011304d971fb98aba3edcc5b937c4183fb -``` - -然后把4.1章节创建的5个受托人密码写入这个dapp的配置文件中 - -``` -> cat path/to/asch/dapps/0599a6100280df0d296653e89177b9011304d971fb98aba3edcc5b937c4183fb/config.json -{ - "secrets": [ - "easy snap cable harvest plate tone planet yellow spot employ humble what", - "adjust edge exist hurry joke carbon spice envelope battle shuffle hawk thought", - "survey spoil submit select warm chapter crazy link actual lonely pig grain", - "march struggle gap piece entry route kind pistol chunk spell honey summer", - "response modify knife brass excess absurd chronic original digital surge note spare" - ] -} -``` - -这里我们把所有受托人的配置到同一个节点了,在生产环境中不推荐这样做,应该把秘钥尽量分散到多个节点,以防止单点故障。 -至此,dapp手工安装部署完成,开发调试阶段需要这样。等以后正式发布到mainnet后,其他节点只需要在钱包页面点击dapp就可以安装。 - -## 4.5 重启asch节点程序 - -``` -> ./aschd restart -``` - -使用浏览器打开`http://localhost:4096/dapps/0599a6100280df0d296653e89177b9011304d971fb98aba3edcc5b937c4183fb/`,可以访问默认的一个前端页面,该页面可以进行一些简单的接口测试 - -也可以观察dapp的日志来排查一些问题 - -``` -> tail -f path/to/asch/dapps/0599a6100280df0d296653e89177b9011304d971fb98aba3edcc5b937c4183fb/logs/debug.*.log -``` - -## 4.6 跨链充值 - -dapp的前后端通讯协议一般可以分为两大类:读和写。 -读指的是数据查询,比如内置的区块查询、交易查询、转账记录,以及自己定义和实现的一些查询接口。 -写指的是合约调用或事务执行,比如发起转账、设置昵称、提现等,同样,也包括其他的由开发者实现的各种合约或事务。 - -每一个写入操作都需要消耗燃料资产,模板dapp默认的燃料是XAS,开发者可以通过调用相关接口改为适合您的燃料类型,可以设置成任意其他资产,包括dapp内置资产。 -如果你您设置的燃料为外部资产,则需要从主链转入资产到这个dapp,这个过程叫充值,相反的过程叫做提现,这都是通过asch的跨链协议实现的。 - -充值有三种方式: - -1. 使用交互式的web图型界面,在【应用中心】的【已安装应用列表】,选择“充值”即可 -2. 使用`asch-cli deposit`命令,具体可参考[asch-cli文档](../asch_cli_usage.md)的“4.6.2 dapp充值章节” -3. 调用`asch-js`的`createInTransfer`函数,具体可参考[asch-js接口文档](../asch_js_api.md) - -## 4.7 查询接口调用 - -查询接口一般通过http get协议,比如 - -``` -// 获取dapp区块数据 -> curl http://localhost:4096/api/dapps/0599a6100280df0d296653e89177b9011304d971fb98aba3edcc5b937c4183fb/blocks -# 返回结果如下 -{ - "blocks": [ - { - "id": "9fae0c8200b7f4ef8c96f264e621f01a39a0b365ff42b80232aece0f3136b0e5", - "timestamp": 0, - "height": 1, - "payloadLength": 103, - "payloadHash": "c3674e36954811f869865a3b106ada847d47b6bc1ffc0a69c1859756d34cb5ad", - "prevBlockId": "", - "pointId": "", - "pointHeight": 0, - "delegate": "8065a105c785a08757727fded3a06f8f312e73ad40f1f3502e0232ea42e67efd", - "signature": "fd7423c1ce4cb82e79125e39fc13e040cefce158af69b45d035aaf5a4c78db8f66aa3e93bbdfb72bfa0dd604f64f8bebc66dd08fd17715bb77225fc0743f680b", - "count": 1 - } - ], - "count": 1, - "success": true -} -``` - -更多接口(外部获取dapp数据,非内部通讯)可以参考[dapp默认接口文档](../asch_dapp_default_api.md) - -## 4.8 合约或事务调用 - -合约调用也有三种方式 - -1. 在模板应用的默认前端页面,通过交互式web图型界面进行 -2. 使用`asch-cli dapptransaction`命令, 具体可参考[asch-cli使用说明](../asch_cli_usage.md) -3. 使用`asch-js`的`createInnerTransaction`函数, 具体可参考[asch-js接口文档](../asch_js_api.md) - -## 5 目录结构 - -下面我们分析下asch dapp的目录结构 - -``` -dapps/0599a6100280df0d296653e89177b9011304d971fb98aba3edcc5b937c4183fb/ -├── blockchain.db // dapp数据库文件,与主链的数据是分开存放的 -├── config.json // 应用的节点配置文件,目前主要用于配置受托人秘钥 -├── contract // 合约目录 -│   └── domain.js // 域名合约的实现代码 -├── dapp.json // 注册dapp时用到的元文件 -├── genesis.json // 创世区块 -├── init.js // 应用初始化代码,可以在该文件进行一些设置、事件注册等 -├── interface // 查询接口的实现目录 -│   ├── domain.js // 域名查询接口实现 -│   └── helloworld.js -├── logs // 日志目录 -│   └── debug.20170928.log -├── model -│   └── domain.js // 域名业务数据模型定义 -└── public - └── index.html // 默认前端页面 -``` - -## 6 实现你的业务逻辑 - -我曾经在这个[博客里](http://blog.asch.so/2017/06/30/asch-1.3-foresight-2/)写过我们的开发理念 - -在asch dapp中实现一个业务逻辑,大概思路如下 - -### 6.1 定义你的数据模型 - -在这个环节,你需要考虑的是在区块链中保存什么数据或状态,你的账本内容是什么。 -哪些字段需要建立索引,以提高客户端查询速度。 -dapp有自己的db文件(sqlite3),在dapps/dappId/blockchain.db,所有的表结构定义以及数据都存在这里。跟主链的数据是隔离的,主链的db文件在asch根目录下。 - -### 6.2 实现合约逻辑 - -这个环节,你需要考虑的是一个事务或一个调用会修改哪些状态,比如资产余额,账户属性等。 -我们在sdk中提供了丰富的接口可供调用,具体可参考[sdk接口文档](../asch_sdk_api.md) - -### 6.3 实现查询接口 - -在这个环节,你需要考虑的是如何给前端返回数据,比如区块、交易,各种合约业务状态的查询等 -也可以可用这个通道将一些非全局状态保存到本地节点,我们会在后续章节介绍这些高级用法。 -目前dapp有[预置的通用查询接口](../asch_dapp_default_api.md),这些是由asch-sandbox提供的。另外一部分就是用户自定义的查询接口,在dapps/dappID/interface/xx.js中进行定义。 diff --git a/docs/dapp_docs/1_hello_de.md b/docs/dapp_docs/1_hello_de.md deleted file mode 100644 index 9f338f2..0000000 --- a/docs/dapp_docs/1_hello_de.md +++ /dev/null @@ -1,167 +0,0 @@ -# Dapp Entwicklung Tutorial 1: Asch Dapp Hello World - -## 1 Grundlegender Ablauf - -Asch kann in drei grundlegend verschiedenen Netzwerkumgebungen ausgeführt werden. Localnet, Testnet und Mainnet. Die zwei letztgenannten Testnet und Mainnet sind öffentlich für jeden im Internet zugänglich. Hingegen der erstgenannte Typ, Localnet läuft auf der eigenen Maschine. Dies ist eine private Blockchain mit nur einem Knoten. Diese erleichtert das lokale Entwickeln und das Testen von Applikationen. - -Der Entwicklungsprozess einer Dapp nützt alle drei dieser Netzwerktypen: -- Schritt 1: Entwickeln und Testen auf dem lokalen Rechner mittels der Localnet -- Schritt 2: Das Testen der Dapp auf dem Testnet -- Schritt 3: Das Deployen der Dapp auf dem Mainnet - -## 2 Localnet starten - -Das Localnet kann gleich nach dem Download ausgeführt werden. [Asch Source-Code](https://github.com/AschPlatform/asch). - -``` -git clone https://github.com/AschPlatform/asch -``` -Danach müssen die Installationsschritte in der README-Datei befolgt werden. - -## 3 Install asch-cli - -``` -npm install -g asch-cli -``` -HINWEIS: Verwende NICHT ```cnpm``` von TAOBAO da es dort einige **Bugs** gibt. - -## 4 Erstelle eine Applikation lokal - -Wechsle in das Asch Source-Code Verzeichnis und stelle sicher, dass das Localnet läuft. - -``` -cd -node app.js -``` - -Führe dann das Kommande ```dapps``` der ```asch-cli``` aus, um eine Applikation zu erstellen. - - -``` -asch-cli dapps -a -``` -Anschließend folgen einige Fragen welche beantwortet werden müssen damit der Genesisblock erstellt werden kann. - -``` -? Enter secret of your testnet account ******************************************************************************* -# To input a primary password of the genesis account, which can be any of the main passwords of Asch system (the one that contains 12 words) - -? Enter second secret of your testnet account if you have -# By default genesis account does not set second password, so we can just type the Enter key. - -? Enter DApp name Hello Dapp -# The name of DApp, we choose "Hello Dapp" - -? Enter DApp description Hello world demo for asch dapp -# The description of DApp, let's leave it empty. - -? Enter DApp tags hello,asch,dapp -# The tags of DApp. It can be empty to be searched more efficiently. - -? Choose DApp category - 1) Common - 2) Business - 3) Social - 4) Education - 5) Entertainment - 6) News -(Move up and down to reveal more choices) - Answer: -# The type of DApp, you can choose it according to your business type. Just input the number in front of each option. - -? Enter DApp link https://github.com/sqfasd/asch-hello/archive/master.zip -# Input the zip file of DApp source code (must end by zip). The installation process needs this link to download necessary source file. - -? Enter DApp icon url https://www.asch.com/logo.png -# The URL of DApp's icon file. - -? Do you want publish a inbuilt asset in this dapp? No -# Input Yes if you need an asset built in DApp. For the time being, input No. - -? Enter public keys of dapp forgers - hex array, use ',' for separator 8065a105c785a08757727fded3a06f8f312e73ad40f1f3502e0232ea42e67efd -# Input the list of public keys of DApp's initial delegates, seperated by comma. You can dynamically add delegates later so right now you can just input one private key for genesis account. - -Creating DApp genesis block -Fetching Asch Dapps SDK -Saving genesis block -Saving dapp meta information -Registering dapp in localnet -Done (DApp id is 6299140990391157236) - -# Then the program can automatically register this DApp on localnet. In this case, our application ID is 6299140990391157236 -``` - -## 5 Die Verzeichnis Struktur -Unter dem Verzeichnis `dapps` findet sich jetzt ein neues Verzeichnis dessen Name der Name der Dapp ID ist. - -``` -ls -1 dapps/ - -blockchain.json # the database description of DApp -config.json # the configuration file of DApp, which mainly contains the list of seed nodes. Developers can also add other configurations in it. -dapp.json # the meta information of DApp, including name, description, source code package, and etc. This file can also be used when registering the app to other networks. -genesis.json # indicate the genesis blcok. This file is generated by CLI automatically, but also can be written by yourself, by which the assets of genesis account can be distributed with more flexibility. -index.js # this file contains the entry of DApp -init.js # this file contains the initial code of each module. -LICENSE # this file describes the permit license of source code. -modules # main code -modules.full.json # this file indicates all the modules need to be loaded. You can add other necessary modules here. -modules.genesis.json # (the simplified version of modules.full.json, currently not need) -node_modules # -package.json # -public # this folders contains all front-end files -routes.json # this file contains the configuration of http route. If you want to add new interface, you need to revise this file. -``` -Keine Sorge bezüglich der Komplexität der Verzeichnisstruktur. Zur Zeit genügt es wenn wir nur einen Blick drauf werfen. - -Die für die Entwickler wichtige Dateien befinden sich in ```modules/contracts/```. - -Es gibt von Haus aus 4 verschiedene Verträge in diesem Verzeichnis. - -``` -ls -1 dapps//modules/contracts/ - -delegates.js # Delegat-Registrierungs-Vertrag -insidetransfer.js # In-Chain Transfer Vertrag -outsidetransfer.js # XAS Einzahlungs-Vertrag -withdrawaltransfer.js # XAS Auszahlungs-Vertrag -``` -Entwickler müssen nur einen neuen Vertrag erstellen um ihre Business-Logik auszuführen. - -## 6 Das Genesis-Passwort für die Dapp setzen - -Es ist obligatorisch das Primärpasswort des Genesis-Blocks sowie die Dapp ID in die ```config.json``` Datei unter dem Punkt ```dapp``` zu schreiben. - -In der Zukunft wenn die Dapp auf dem Mainnet veröffentlich wird, wird auch ein Rechner zur Konfiguration der Primärpassworts benötigt. HINWEIS: Es genügt ein Rechner. - -``` -"params": { - "6299140990391157236": [ - "someone manual strong movie roof episode eight spatial brown soldier soup motor" - ] -} -``` - -## 7 Auf die Front-End Oberfläche zugreifen - -Wir könnnen uns nun mit der grafischen Benutzeroberfläche für die Dapp-Entwicklung auseinander setzen. - -Diese findet man im Programm in der Liste der installierten Anwendungen. Alternativ dazu kann man auch mit folgender URL darauf zugreifen: ```localhost:4096/dapps/``` - -Für dieses Projekt zeigen wir mehrere Schritte. Einzahlen, In-Chain Transfer und Auszahlen. - -Zur Zeit können Einzahlungen nur über die Konsole getätigt werden (Einzahlungen über die GUI sind für die Zukunft geplant). Alle anderen Operationen können über die GUI geschehen. - -``` -asch-cli dapps -d - -? Enter secret ******************************************************************************* -? Enter amount 100 -? DApp Id 6299140990391157236 -? Enter secondary secret (if defined) -? Host and port localhost:4096 -null { success: true, transactionId: '10589988261732949004' } -10589988261732949004 -``` - -Die Applikation aktualisiert sich alle 30 Sekunden. Nach kurzer Zeit können wir das Saldo der Ein- und Auszahlungen sehen. diff --git a/docs/dapp_docs/1_hello_en.md b/docs/dapp_docs/1_hello_en.md deleted file mode 100644 index 9b3efdd..0000000 --- a/docs/dapp_docs/1_hello_en.md +++ /dev/null @@ -1,400 +0,0 @@ -# Dapp Development Tutorial 1: Asch Dapp Hello World - -## 1 Basic Process - -There are three types of networks in Asch, localnet, testnet, and mainnet. The later two, testnet and mainnet, are usually deployed online, which can be accessed by a public network. Meanwhile the first type, localnet, as its name is running on local machine, which is actually a private chain with only one node. Localnet is designed to help developing and testing locally. - -And the development of Dapp involves all of these types of network simultaneously, which is: -- step 1: developing and testing locally on the localnet -- step 2: testing on the testnet -- step 3: deploying officially on mainnet - -### 1.1 System requirements -- Node v8.x.x - -## 2 Setup asch-cli - -``` -npm install -g asch-cli -``` - -## 3 Setup asch -``` -# clone asch -git clone https://github.com/aschplatform/asch.git asch && cd asch && npm install && cd .. -``` -## 4 Start localnet - -Run your own local asch node. - -``` -# change directory -cd asch - -# start the localnet (default on localhost:4096) -node app.js -``` - - -## 5 Start The Frontend Application (optional) - -To access the localnet via a graphical user interface (GUI) start the frontend application. Be sure to have the localnet up and running. - -This step must be run from another console. The first console is already busy with running the localnet. - -``` -# change directory -cd asch/public -``` - -Install the dependencies for the frontend application -``` -yarn install -``` - -Build the frontend application for the localnet. -``` -gulp build-local -``` - -Now you can access the frontend application on the address ```localhost:4096```. -*NOTE:* You don't need to start a http-server. Asch is already providing one for you. - - -## 6 Prepare Account For Dapp Registration - -First create a new local asch-account. - -``` -# execute (in root folder) -> asch-cli -H 127.0.0.1 -P 4096 crypto --generate -# ? Enter number of accounts to generate: -1 -``` -**Our New Account** -``` - address: AHMCKebuL2nRYDgszf9J2KjVZzAw95WUyB - secret: sentence weasel match weather apple onion release keen lens deal fruit matrix - publicKey: a7cfd49d25ce247568d39b17fca221d9b2ff8402a9f6eb6346d2291a5c81374c -``` - -**Genesis Account** -``` - address: 14762548536863074694 - secret: someone manual strong movie roof episode eight spatial brown soldier soup motor - publicKey: 8065a105c785a08757727fded3a06f8f312e73ad40f1f3502e0232ea42e67efd -``` - - -**Our new Acccount** will be our account for this tutorial. - -We need **100 XAS** to register a dapp. Our new account has **0 XAS**. The **genesis** account has 100000000 XAS on it. Lets send some money to **our** account. - - -``` -# send money to our account -> asch-cli -H 127.0.0.1 -P 4096 sendmoney --secret "someone manual strong movie roof episode eight spatial brown soldier soup motor" --to "AHMCKebuL2nRYDgszf9J2KjVZzAw95WUyB" --amount 100000000000 - -# check your balance -> asch-cli -H 127.0.0.1 -P 4096 openaccount "sentence weasel match weather apple onion release keen lens deal fruit matrix" -``` - - -## 7 Create A Dapp Metadata File - -First we have to create 5 delegate accounts: - -``` -# execute in root (you don't have to point to the localhost, this command is execute only in asch-cli) -> asch-cli crypto --generate -? Enter number of accounts to generate -5 - -[ - { - address: 'AN1yKK47P3MtD5ZgHYoncGQ1gCn4p2vGAC', - secret: 'flame bottom dragon rely endorse garage supply urge turtle team demand put', - publicKey: 'db18d5799944030f76b6ce0879b1ca4b0c2c1cee51f53ce9b43f78259950c2fd' - }, - { - address: 'AGeeCmSVLDNbtMqqpJchQZakchwzpuje1P', - secret: 'thrive veteran child enforce puzzle buzz valley crew genuine basket start top', - publicKey: '590e28d2964b0aa4d7c7b98faee4676d467606c6761f7f41f99c52bb4813b5e4' - }, - { - address: 'A7NWaYUkpa543hdTsfw57AoZAgCBr2NFY6', - secret: 'black tool gift useless bring nothing huge vendor asset mix chimney weird', - publicKey: 'bfe511158d674c3a1e21111223a49770bee93611d998e88a5d2ea3145de2b68b' - }, - { - address: 'ABU1G2pQFMGa7c1GiAPYCQuUhiPHdvCSB2', - secret: 'ribbon crumble loud chief turn maid neglect move day churn share fabric', - publicKey: '7bbf62931cf3c596591a580212631aff51d6bc0577c54769953caadb23f6ab00' - }, - { - address: 'AG1A3ojeLAMZySaZWTkg49jcoVCV7FCKXF', - secret: 'scan prevent agent close human pair aerobic sad forest wave toe dust', - publicKey: '452df9213aedb3b9fed6db3e2ea9f49d3db226e2dac01828bc3dcd73b7a953b4' - } -] -``` - - -After that enter your Asch source code folder and make sure the localnet is running. - -``` -# this must be executed in a new console -> mkdir asch-test-dapp && cd asch-test-dapp -> asch-cli dapps -a - -# enter dapp name? -hello - -# enter dapp description? -[empty] - -# enter dapp tags? -[empty] - -# choose dapp category -1 - -# enter dapp link -https://github.com/AschPlatform/asch-dapp-helloworld/archive/master.zip - -# enter dapp icon url -http://o7dyh3w0x.bkt.clouddn.com/hello.png - -# enter public keys of dapp delegates - hex array, use ',' for separator (at least 5 delegates, max 101): -db18d5799944030f76b6ce0879b1ca4b0c2c1cee51f53ce9b43f78259950c2fd,590e28d2964b0aa4d7c7b98faee4676d467606c6761f7f41f99c52bb4813b5e4,bfe511158d674c3a1e21111223a49770bee93611d998e88a5d2ea3145de2b68b,7bbf62931cf3c596591a580212631aff51d6bc0577c54769953caadb23f6ab00,452df9213aedb3b9fed6db3e2ea9f49d3db226e2dac01828bc3dcd73b7a953b4 - -# how many delegates are needed to unlock asset of a dapp? -3 - -# Enter master secret of your genesis account -[hidden] - -# Do you want publish a inbuilt asset in this dapp? -No -``` - -This step created the `asch-test-dapp/dapp.json` file. -``` -{ - "name": "hello", - "link": "https://github.com/sqfasd/asch-hello-dapp/archive/master.zip", - "category": 1, - "description": "", - "tags": "", - "icon": "http://o7dyh3w0x.bkt.clouddn.com/hello.png", - "delegates": [ - "db18d5799944030f76b6ce0879b1ca4b0c2c1cee51f53ce9b43f78259950c2fd", - "590e28d2964b0aa4d7c7b98faee4676d467606c6761f7f41f99c52bb4813b5e4", - "bfe511158d674c3a1e21111223a49770bee93611d998e88a5d2ea3145de2b68b", - "7bbf62931cf3c596591a580212631aff51d6bc0577c54769953caadb23f6ab00", - "452df9213aedb3b9fed6db3e2ea9f49d3db226e2dac01828bc3dcd73b7a953b4" - ], - "unlockDelegates": 3, - "type": 0 -} -``` - - -## 8 Register The Dapp On The Localnet - -Until now we only have generated file (`asch-test-dapp/dapp.json`). Now we want to register this dapp metadata file on the localnet. We register the dapp with **our** newly generated address. - -``` -# execute (in asch/dapps) -> asch-cli -H 127.0.0.1 -P 4096 registerdapp --metafile dapp.json --secret "sentence weasel match weather apple onion release keen lens deal fruit matrix" -``` - -**Result** -``` -# This returns the new Dapp-ID - -``` - -Now navigate in your browser to `localhost:4096`. Login with **our** new created account. Under dapps you should see the register dapps. - -Use browser access `http://localhost:4096/api/dapps/get?id=`, you can query the dapp, the following is the return information: - -``` -{ - "success": true, - "dapp": { - "name": "asch-dapp-helloworld", - "description": "A hello world demo for asch dapp", - "tags": "asch,dapp,demo", - "link": "https://github.com/AschPlatform/asch-dapp-helloworld/archive/master.zip", - "type": 0, - "category": 1, - "icon": "http://o7dyh3w0x.bkt.clouddn.com/hello.png", - "delegates": [ - "a518e4390512e43d71503a02c9912413db6a9ffac4cbefdcd25b8fa2a1d5ca27", - "c7dee266d5c85bf19da8fab1efc93204fed7b35538a3618d7f6a12d022498cab", - "9cac187d70713b33cc4a9bf3ff4c004bfca94802aed4a32e2f23ed662161ea50", - "01944ce58570592250f509214d29171a84f0f9c15129dbea070251512a08f5cc", - "f31d61066c902bebc80155fed318200ffbcfc97792511ed18d85bd5af666639f" - ], - "unlockDelegates": 3, - "transactionId": "0599a6100280df0d296653e89177b9011304d971fb98aba3edcc5b937c4183fb" - } -} -``` - -## 9 Install the dapp on the localnet - -Finally it is time to install the dapp on the localnet. - -First we copy the files created in previous step to the dapp subdirectory under the asch installation directory and rename it to dapp's id: - -``` -> cp -r asch-test-dapp path/to/asch/dapps/0599a6100280df0d296653e89177b9011304d971fb98aba3edcc5b937c4183fb -``` - -then: -``` -# execute -asch-cli -H 127.0.0.1 -P 4096 dapps --install - -# ? Enter dapp id -# (input your dapp Id) - -# ? Host and port (localhost:4096) -# [Enter] - -# ? What is your dapp master password -# -``` -The dapp masterpassword is located in `asch/config.json`. -``` - "dapp": { - "masterpassword": "ytfACAMegjrK", - "params": { - "": [ - ] - } -``` - -Then write the passwords of the 5 delegates into the dapp configuration file `asch/dapps//config.json`. - -``` -# config.json -{ - "secrets": [ - "flame bottom dragon rely endorse garage supply urge turtle team demand put", - "thrive veteran child enforce puzzle buzz valley crew genuine basket start top", - "black tool gift useless bring nothing huge vendor asset mix chimney weird", - "ribbon crumble loud chief turn maid neglect move day churn share fabric", - "scan prevent agent close human pair aerobic sad forest wave toe dust" - ] -} -``` - -**After the installation restart the node** -``` -# stop the localnet with Ctrl + C - -# restart the localnet -> node app.js -``` - -## 10 Access The Dapp In Your Browser - -Now you can access the dapp like a website `localhost:4096/dapps//` in your browser. - - -## 11 Set Dapp Genesis Password - -Under `asch/config.json` set the genesis password for your dapp. Input your `` and the secret of your - -**before** -``` - "dapp": { - "masterpassword": "ytfACAMegjrK", - "params": {} - } -``` - -**after** -``` - "dapp": { - "masterpassword": "ytfACAMegjrK", - "params": { - "": [ - "sentence weasel match weather apple onion release keen lens deal fruit matrix" - ] - } - } -``` -In the future when the DApp is published in testnet or mainnet, it still needs a machine that configures the primary password. NOTE: Only one machine is required. - - -## 12 The folder structure - -Now we can see that there is a new folder added under `asch/dapps`, named as the DApp ID just created. - -``` -> ls -la dapps/ - -dapps -└─── - blockchain.json # the database description of DApp - config.json # the configuration file of DApp, which mainly contains the list of seed nodes. Developers can also add other configurations in it. - dapp.json # the meta information of DApp, including name, description, source code package, and etc. This file can also be used when registering the app to other networks. - genesis.json # indicate the genesis blcok. This file is generated by CLI automatically, but also can be written by yourself, by which the assets of genesis account can be distributed with more flexibility. - index.js # this file contains the entry of DApp - init.js # this file contains the initial code of each module. - LICENSE # this file describes the permit license of source code. - modules # main code - modules.full.json # this file indicates all the modules need to be loaded. You can add other necessary modules here. - modules.genesis.json # (the simplified version of modules.full.json, currently not need) - node_modules # - package.json # - public # this folders contains all front-end files - routes.json # this file contains the configuration of http route. If you want to add new interface, you need to revise this file. -``` -Don't worry about the complexity of the file structure. For now a first look is enough. - -All the essential files for developers can be found in ```modules/contracts/``` - -There are 4 build-in contract types in this folder: - -``` -> ls -1 dapps//modules/contracts/ - - -dapps -└─── - └───modules - └───contracts - delegates.js # registering delegate contract - insidetransfer.js # in-chain transfer contract - outsidetransfer.js # XAS deposit contract - withdrawaltransfer.js # XAS withdraw contract -``` - -Developers need to create a new contact to run business logic. That's all. - - - -## 13 Dapp Deposit - -In this project, we are able to conduct multiple tasks such as deposit, in-chain transfer, and withdraw. - -Currently deposit can only be executed via command line (this feature will be built into the main wallet in the future). - -``` -> asch-cli dapps --deposit - -? Enter secret ******************************************************************************* -? Enter amount 100 -? DApp Id 6299140990391157236 -? Enter secondary secret (if defined) -? Host and port localhost:4096 -null { success: true, transactionId: '10589988261732949004' } -10589988261732949004 -``` - -In the web wallet (`localhost:4096`) we can see (after approximately 30 seconds) that the balance was updated. diff --git a/docs/dapp_docs/dapp_dev_tutorials.md b/docs/dapp_docs/dapp_dev_tutorials.md deleted file mode 100644 index ed0f771..0000000 --- a/docs/dapp_docs/dapp_dev_tutorials.md +++ /dev/null @@ -1,545 +0,0 @@ -# Asch DAPP核心开发流程解析 - -标签(空格分隔): Asch DAPP - ---- - -## 1.准备工作 - - -`基础知识`:明白什么是区块链?什么是侧链?怎么用linux?怎么用nodejs?bitcoin的基本运行原理?什么是共识?什么是dpos?什么是受托人?什么是主密码?什么是私钥、公钥、地址?什么是创世块?什么是资产?这些弄明白了(最起码得大体了解)再往下看,否则就是事倍功半,真没必要往下看了。 - -`概念理解`:Asch的DAPP是运行在侧链上的,每个DAPP也可以简单理解为一条侧链,具有区块链的基本属性,比如共识机制(默认是dpos,高端玩家可以定制自己的共识算法)、区块信息、转账交易记录、P2P广播通讯、数据库文件等,跟Asch主链有相同的加密算法、地址生成算法,也就是说同一个账户在主链和DAPP中是通用的(通用指的是同一个密码登陆进去后地址相同)。 - -`OS`:Ubuntu 14.04.x 或者 16.04.x(物理机、虚拟机或者Bash on Ubuntu on Windows都可以) - -`IDE`:vscode - -`nodejs`: 8.4.0 - -`npm`:5.3.0 - -如下链接为 `DAPP开发前必读文章` (包含里面的那些链接文章也要读) -https://github.com/AschPlatform/asch/blob/master/docs/asch_dapps_introduction.md -https://github.com/AschPlatform/asch/blob/master/docs/dapp_docs/1_hello.md -https://github.com/AschPlatform/asch/blob/master/docs/asch_sdk_api.md -https://github.com/AschPlatform/asch/blob/master/docs/asch_dapp_default_api.md -https://github.com/AschPlatform/asch/blob/master/docs/asch_cli_usage.md -https://github.com/AschPlatform/asch/blob/master/docs/asch_http_interface.md - -在开发期间遇到的任何的技术问题都可以去https://github.com/AschPlatform/asch/issues 查找或者创建新的issue。 - -`友情提示`:区块链是块大蛋糕,但吃之前先给自己做个评估,看是否有能力吃的下、能吃多少、是否能吃的顺心。 - -## 2.搭建本地localnet - -localnet简单理解就是Asch私有链,这里是为了方便DAPP开发而搭建的。localnet上的DAPP如果开发、测试顺利通过,相当于整个DAPP已完成90%的工作。 - -``` -# Install dependency package -sudo apt-get install curl sqlite3 ntp wget git libssl-dev openssl make gcc g++ autoconf automake python build-essential -y -# libsodium for ubuntu 14.04 -sudo apt-get install libtool -y -# libsodium for ubuntu 16.04 -sudo apt-get install libtool libtool-bin -y - -# Install nvm -curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash -# This loads nvm -export NVM_DIR="$HOME/.nvm" -[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" -[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion - -# Install node and npm for current user. -nvm install v8 -# check node version and it should be v8.x.x -node --version - -# git clone sourece code -git clone https://github.com/AschPlatform/asch && cd asch && chmod u+x aschd - -# Install node packages -npm install -至此,完成localnet服务端部分的构建。 -``` - -``` -# Web Wallet -cd public/ - -npm install bower -g -npm install browserify -g -npm install yarn -g - -yarn install -# angular chose "angular#~1.5.3 which resolved to 1.5.11 and is required by ASCH" - - -npm run build -gulp build-test #This make the front-end files in public dir. -至此,完成localnet前端页面(钱包UI)的构建。 -``` - -``` -// 启动Asch -cd asch && node app.js // 日志打印到屏幕终端,ctrl+c结束进程 -或者 -cd asch && ./aschd start // 守护进程方式启动,日志记录到logs/debug.log中。./aschd stop结束进程 -或者其它的启动方式,比如pm2 start app.js - -``` -然后在浏览器中打开 ```http://localhost:4096```,如果能看到Asch钱包登陆页面说明localnet的搭建和启动成功(localnet的创世账户密码:"someone manual strong movie roof episode eight spatial brown soldier soup motor",里面有一亿XAS)。如果页面报错,则需要检查app.js进程是否存在、日志报错信息等。 - - -## 3.注册并启动第一个DAPP - -### 3.1 发行资产(UIA) -发行自己的资产,请参考这个链接http://docs.asch.mobi/docs/asch_issue_assets.html -这里我们在钱包页面生成一个新账户A,主密码为“almost journey future similar begin type write celery girl month forget breeze”,对应的地址是AAjoobuMcmkQ1gS8vTfBy3dQavBiH7sBCF,该账户将作为下面的cctime.XCT资产发行者、cctime DAPP的注册者以及给其它账户转账的发送者,创世账户给该地址转1000个xas。 - -A账户去注册发行商cctime,然后注册一个资产XCT(上限100亿,精度8,描述为:cctime.org的token时讯币,其它用默认的),最后发行10亿的cctime.XCT。 - -### 3.2 利用模板启动第一个DAPP -Asch作为一个区块链开发平台,为开发者提供了一个安全且高性能的虚拟机(asch-sandbox)以及一系列的内部接口、框架等。其中的一个脚手架就是利用模板来生成自定义的DAPP,通过回答几个问题就可以完成DAPP框架代码的开发工作。 -模板包含了启动一个dapp需要的最少数据 - -#### 3.2.1 生成DAPP元信息(创世块) - -``` -// 生成5个受托人账号 -zhenxi@MiAir:~/Codes/github/AschPlatform/asch$ asch-cli crypto -g -? Enter number of accounts to generate 5 -[ { address: 'A9pDhjc7NuYMWYLxkgAgVmHE2NQ7diMcWX', - secret: 'fit night someone unveil dwarf believe middle evidence puzzle hotel common choose', - publicKey: 'afdf69f0da9ff333218f2cd10cb0a907c2e76788f752b799cb1dab3a9f03bf63' }, - { address: 'A2jvQUNowLgP9hHMN3tSCAUkakuigGRytB', - secret: 'lawsuit ride civil slice kitchen unfold unable lumber prevent suspect finger chunk', - publicKey: '67d52a0265f9e5366660c8b384cee56d3f8b5737b2dd3c617d22df83b5ebef02' }, - { address: 'A7JjHgx7ACCJ6AxypBn4Qt9NrGaY4JuZDF', - secret: 'absurd sweet blast dinner battle zero ladder steak coral fork venture coffee', - publicKey: '39c2322600a0c81ecfa97119ec8e2d5bfb73394914d92b54e961846a987e4e22' }, - { address: 'AMu7kuP9TjywkUQQQgALid96So2VCve5QB', - secret: 'topic ramp throw cloud moment jungle bar series task protect erupt answer', - publicKey: '4740d2c16bf6c5a174eba1e0f859253a64851d30acbc9655b01394af82d3e325' }, - { address: 'A9BzaJDkyzb9RVAFjsePMemSVXMDLiQpjJ', - secret: 'shoot tired know dish rally kiwi snack patrol bunker ocean panel this', - publicKey: 'b433c226645981477642491f77de7b8d63274aa51f932bbe1fe3f445a8aaecc9' } ] -Done -``` - -``` -// 根据模板和自定义参数生成自己的dapp框架,包含创世块、配置文件、数据和合约、接口、日志等目录 -cd dapps -mkdir cctime && cd cctime -zhenxi@MiAir:~/Codes/github/AschPlatform/asch/dapps$ asch-cli dapps -a -Copying template to the current directory ... -? Enter DApp name cctime -? Enter DApp description cctime.org -? Enter DApp tags news -? Choose DApp category News -? Enter DApp link http://github/aschplatform/cctime.zip -? Enter DApp icon url http://a.com/x.png -? Enter public keys of dapp delegates - hex array, use ',' for separator afdf69f0da9ff333218f2cd10cb0a907c2e76788f752b799cb1dab3a9f03bf63,67d52a0265f9e5366660c8b384cee56d3f8b5737b2dd3c617d22 -df83b5ebef02,39c2322600a0c81ecfa97119ec8e2d5bfb73394914d92b54e961846a987e4e22,4740d2c16bf6c5a174eba1e0f859253a64851d30acbc9655b01394af82d3e325,b433c226645981477642491f77de7b8d63274aa51f932bb -e1fe3f445a8aaecc9 -? How many delegates are needed to unlock asset of a dapp? 3 -DApp meta information is saved to ./dapp.json ... -? Enter master secret of your genesis account [hidden] //这里输入的密码为:'almost journey future similar begin type write celery girl month forget breeze' -? Do you want publish a inbuilt asset in this dapp? Yes -? Enter asset name, for example: BTC, CNY, USD, MYASSET XCT -? Enter asset total amount 100000000 -? Enter asset precision 8 -New genesis block is created at: ./genesis.json -// 生成的文件如下 -zhenxi@MiAir:~/Codes/github/AschPlatform/asch/dapps/cctime$ ls -config.json contract dapp.json genesis.json init.js interface model public -``` - -#### 3.2.2 注册DAPP到localnet上 - -``` -zhenxi@MiAir:~/Codes/github/AschPlatform/asch/dapps/cctime$ asch-cli registerdapp -f dapp.json -e "almost journey future similar begin type write celery girl month forget breeze" -// 返回结果为dappId -75d084dc91221b380e7a3c6b3b7467935572b4ebaa1e9a3db91e1239377c1fed -``` - -此时钱包的“应用列表”就可以看到该应用了。 -![](http://asch-public.oss-cn-beijing.aliyuncs.com/pics/dapp%E6%A0%B8%E5%BF%83%E5%BC%80%E5%8F%91%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/2.png) - -将cctime目录改名为75d084dc91221b380e7a3c6b3b7467935572b4ebaa1e9a3db91e1239377c1fed,这样就完成了dappp在本地节点的安装(整个过程是手工安装,以后正式上线后,其他节点安装时无须这么麻烦,只需要在页面点击就可以安装)。 - -``` -cd .. -mv cctime 75d084dc91221b380e7a3c6b3b7467935572b4ebaa1e9a3db91e1239377c1fed -``` - -#### 3.2.3 启动DAPP - -重启asch服务,默认会加载dapps目录下的所有的dapp。此时dapp中只有模板预置的信息,虽然此时没有自定义的数据、合约、接口等信息,但dapp已经是一条具备最小功能的侧链了,只需要配置好受托人就可以产块和转账。 -此时钱包的“已安装应用列表”就可以看到该应用了。 -![](http://asch-public.oss-cn-beijing.aliyuncs.com/pics/dapp%E6%A0%B8%E5%BF%83%E5%BC%80%E5%8F%91%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/3.png) - -启动后,dapps/75d084dc91221b380e7a3c6b3b7467935572b4ebaa1e9a3db91e1239377c1fed下会多出一个blockchain.db文件。dapp第一次启动时会创建2种表,1:用户自定义表,由model下的数据模型文件决定,2:asch_sandbox预置表,这些都是区块链的系统表。 - -目前我们这个DAPP的blockchain.db包含如下表: - -`accounts` dapp内账户信息,asch_sandbox预置 - -`blocks` dapp区块表,asch_sandbox预置 - -`domains` 域名表,非asch_sandbox预置表,而是根据model下的domain.js定义生成的表,可以删除 - -`transactions` dapp交易表,asch_sandbox预置 - -`variables` dapp变量表,asch_sandbox预置 - -`balances` dapp余额表,asch_sandbox预置 - -`deposits` 主链往dapp上充值记录表,asch_sandbox预置 - -`round_fees` dapp的dpos共识下,每轮的手续费详情表,asch_sandbox预置 - -`transfers` dapp内部转账表,asch_sandbox预置 - -浏览器打开 `http://localhost:4096/dapps/75d084dc91221b380e7a3c6b3b7467935572b4ebaa1e9a3db91e1239377c1fed/` 如果能看到“Asch DApp Example 1 - hello world”页面说明dapp启动成功。 - -此时用'almost journey future similar begin type write celery girl month forget breeze'登陆后看到XCT(这是dapp内置的资产,只能在dapp内使用,不是我们之前在主链发行的用户资产cctime.XCT)余额为100000000,与我们注册dapp时设定的参数一致。 - -![](http://asch-public.oss-cn-beijing.aliyuncs.com/pics/dapp%E6%A0%B8%E5%BF%83%E5%BC%80%E5%8F%91%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/1.png) - -#### 3.2.4 配置DAPP的受托人 -编辑dapps/75d084dc91221b380e7a3c6b3b7467935572b4ebaa1e9a3db91e1239377c1fed/config.json文件,将上面5个受托人的密码加入到该文件中 -``` -{ - "secrets": [ - "fit night someone unveil dwarf believe middle evidence puzzle hotel common choose", - "lawsuit ride civil slice kitchen unfold unable lumber prevent suspect finger chunk", - "absurd sweet blast dinner battle zero ladder steak coral fork venture coffee", - "topic ramp throw cloud moment jungle bar series task protect erupt answer", - "hoot tired know dish rally kiwi snack patrol bunker ocean panel this" - ] -} -``` -然后重启asch,此时dapp已经可以产块了。具体可以看dapp的日志输出 dapps/75d084dc91221b380e7a3c6b3b7467935572b4ebaa1e9a3db91e1239377c1fed/logs/debug.20180125.log - -#### 3.2.5 DAPP基本操作 - -##### 3.2.5.1 往DAPP中进行充值 - -用密码“almost journey future similar begin type write celery girl month forget breeze”登陆Asch钱包,往DAPP中充值100 XAS(这个充值动作实质就是跨链操作),消耗0.1XAS手续费。 -![](http://asch-public.oss-cn-beijing.aliyuncs.com/pics/dapp%E6%A0%B8%E5%BF%83%E5%BC%80%E5%8F%91%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/4.png) - -10秒后(也有可能是1秒、3秒或者8秒,这里实质是要等一个区块确认后才能看到充值余额,而10秒是一个块的默认出块时间),去 `http://localhost:4096/dapps/75d084dc91221b380e7a3c6b3b7467935572b4ebaa1e9a3db91e1239377c1fed/` 页面验证充值 -![](http://asch-public.oss-cn-beijing.aliyuncs.com/pics/dapp%E6%A0%B8%E5%BF%83%E5%BC%80%E5%8F%91%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/5.png) - -此时AAjoobuMcmkQ1gS8vTfBy3dQavBiH7sBCF这个账户在主链的XAS余额减少了100.1(0.1是充值手续费),而在侧链cctime中XAS余额增加了100。 - -同理充值100 cctime.XCT资产。 -![](http://asch-public.oss-cn-beijing.aliyuncs.com/pics/dapp%E6%A0%B8%E5%BF%83%E5%BC%80%E5%8F%91%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/6.png) - -##### 3.2.5.2 DAPP内部转账 -生成另一个账户B,主密码“attack exist tuna tunnel enhance coach favorite safe buffalo faculty robot blue”,地址为APoBYfxx266FH5HCrkBdebAZ2wFPjJ3Q4z。 -A调用DAPP的系统内置合约给B用户转账10 cctime.XCT,这里展示的是通过页面调用接口(该页面的Contract invoke可以理解为postman),该合约的详细描述见[DAPP_默认API](https://github.com/AschPlatform/asch/blob/master/docs/asch_dapp_default_api.md#3122-dapp%E5%86%85%E9%83%A8%E8%BD%AC%E8%B4%A6type3) - -转账时的数额是 真实数额*10**资产精度数值(区块链上前端看到的有小数,但后端都是按照整数计算的) -这里选择编号为3的system合约就是dapp内部转账(小于1000的都是system内置合约,目前已经1-4共4个合约,详情见文档:https://github.com/AschPlatform/asch/blob/master/docs/asch_dapp_default_api.md#3-%E4%BA%8B%E5%8A%A1transactions) -![](http://asch-public.oss-cn-beijing.aliyuncs.com/pics/dapp%E6%A0%B8%E5%BF%83%E5%BC%80%E5%8F%91%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/7.png) - -![](http://asch-public.oss-cn-beijing.aliyuncs.com/pics/dapp%E6%A0%B8%E5%BF%83%E5%BC%80%E5%8F%91%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/8.png) - -![](http://asch-public.oss-cn-beijing.aliyuncs.com/pics/dapp%E6%A0%B8%E5%BF%83%E5%BC%80%E5%8F%91%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/9.png) - -此时A账户在DAPP中的XAS余额减少0.1(DAPP默认手续费是XAS,可以自定义为其它资产或者不收手续费),cctime.XCT余额减少10。B账户的cctime.XCT余额增加10. - -账户A的余额: -![](http://asch-public.oss-cn-beijing.aliyuncs.com/pics/dapp%E6%A0%B8%E5%BF%83%E5%BC%80%E5%8F%91%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/10.png) - -账户B的余额: -![](http://asch-public.oss-cn-beijing.aliyuncs.com/pics/dapp%E6%A0%B8%E5%BF%83%E5%BC%80%E5%8F%91%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/11.png) - -##### 3.2.5.3 DAPP内给地址设置昵称 -![](http://asch-public.oss-cn-beijing.aliyuncs.com/pics/dapp%E6%A0%B8%E5%BF%83%E5%BC%80%E5%8F%91%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/14.png) - -OK,上面BB了那么多,其实就干了一件事:没有写一行代码只是利用现有的工具就搭建起来一条具备跨连充值、跨链提现、内部转账功能的侧链,并且还可以创建内置资产。从下面章节开始,才是用户自定义数据、智能合约、外部接口的代码编写。 - -## 4 DAPP核心开发流程 -开发dapp跟把大象放进冰箱的步骤一毛一样,本章节就是围绕下面这三步来做 :) - -![](http://asch-public.oss-cn-beijing.aliyuncs.com/pics/dapp%E6%A0%B8%E5%BF%83%E5%BC%80%E5%8F%91%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/12.png) - -下面这些操作都是在dapps/75d084dc91221b380e7a3c6b3b7467935572b4ebaa1e9a3db91e1239377c1fed/目录下进行的。 - -### 4.1 自定义用户数据模型(RDBMS表) - -注意事项: - -- `表结构定义需要放到model目录下` - -- `字段属性都是RDBMS通用的,比如类型有string、nmber等,not_null,defaut值,length长度、主外键约束、唯一约束等` - -- `如果字段是String类型,则必须加上length属性` - -- `DAPP启动时会检查这些表是否存在,如果不存在则会自动创建,保存到blockchain.db文件中` - - -在model目下创建article.js文件,该文件定义了articles表,内容如下 -``` -module.exports = { - name: 'articles', - fields: [ - // 文章id - { - name: 'id', - type: 'String', - length: '20', - not_null: true, - primary_key: true - }, - // 发表文章时的交易id - { - name: 'tid', - type: 'String', - length: 64, - not_null: true, - unique: true - }, - // 文章作者的地址 - { - name: 'authorId', - type: 'String', - length: 50, - not_null: true - }, - // 时间戳,距离cctime创世块经历的秒数 - { - name: 'timestamp', - type: 'Number', - not_null: true - }, - // 文章标题 - { - name: 'title', - type: 'String', - length: 256, - not_null: true - }, - // 如果文章是引用的,其url地址定义 - { - name: 'url', - type: 'String', - length: 256 - }, - // 文章内容 - { - name: 'text', - type: 'String', - length: 4096, - not_null: true, - }, - // 文章标签 - { - name: 'tags', - type: 'String', - length: 20 - }, - // 文章得到的投票数 - { - name: 'votes', - type: 'Number', - not_null: true - }, - // 文章评论 - { - name: 'comments', - type: 'Number', - not_null: true, - default: 0 - }, - // 举报 - { - name: 'reports', - type: 'Number', - not_null: true, - default: 0 - } - ] -} -``` - -### 4.2 自定义用户合约 - -这一步里面主要用到的文档是:https://github.com/AschPlatform/asch/blob/master/docs/asch_sdk_api.md -app.xxx这种接口都来自asch_sandbox。 - -合约就是业务逻辑处理。 - -``` -// 在contrac目录下创建cctime.js -module.exports = { - // 定义发布文章的智能合约函数 - postArticle: async function (title, url, text, tags) { - // 下面这些if判断是用来校验文章信息是否合法,有些是可以用 app.validate(type, value) 接口进行重写的 - if (!url && !text) { - return 'Should provide url or text' - } - if (url && text) { - return 'Both url and text are not supported' - } - if (!tags) { - return 'Should provide tags' - } - if (tags.length > 20) { - return 'Invalid tags size' - } - if (!title) { - return 'Should provide title' - } - if (title.length > 256) { - return 'Invalid title size' - } - if (url && url.length > 256) { - return 'Url too long' - } - if (text && text.length > 4096) { - return 'Text too long' - } - //TODO validate url format - - // 对key进行加锁,防止重复数据。这里的意思是如果用户发表的文章是转载其它url的,则需要检查该url是否已经被发布过了。需要在内存中将这个url的key锁住,防止同一个区块内其他人再次发布这个url然后去检查db中是否已经有这个url了 - if (url) { - app.sdb.lock('postArticle@' + url) - let exists = await app.model.Article.exists({ url: url }) - if (exists) { - return 'Url already exists' - } - } - // 调用app.sdb.create将校验过的文章信息插入到articles表中 - app.sdb.create('Article', { - title: title, - url: url || '', - text: text || '', - tags: tags, - id: app.autoID.increment('article_max_id'), - votes: 0, - tid: this.trs.id, - authorId: this.trs.senderId, - timestamp: this.trs.timestamp, - comments: 0 - }) - } -} -``` - -``` -// 修改init.js -// 注册合约 -module.exports = async function () { - console.log('enter dapp init') - // 注册合约,用户自定义合约编号是从1000开始的,之前的都是system保留合约。 - app.registerContract(1000, 'cctime.postArticle') - - app.events.on('newBlock', (block) => { - console.log('new block received', block.height) - }) -} -``` - -### 4.3 自定义查询接口 - -// interface目录下新增index.js,内容如下 - -``` -// 根据条件查询被举报次数小于的文章,并按照时间倒序排 -async function getArticlesByTime(options) { - // 查询符合条件的记录数 - let count = await app.model.Article.count({ reports: { $lt: 3 } }) - // 查询符合条件的记录详情 - let articles = await app.model.Article.findAll({ - condition: { - reports: { $lt: 3 } - }, - limit: options.limit || 50, - offset: options.offset || 0, - sort: { timestamp: -1 } - }) - return { count: count, articles: articles } -} - -// 定义url路由,根据条件获取文章 -app.route.get('/articles', async (req) => { - // 获取url传进来的参数 - let query = req.query - // 默认按照timestamp来排序 - if (!query.sortBy) { - query.sortBy = 'timestamp' - } - - // 设定本次查询的key - let key = ['articles', query.sortBy, query.limit, query.offset].join('_') - // 如果内存中有本次查询的key,则直接返回其对应的结果 - if (app.custom.cache.has(key)) { - return app.custom.cache.get(key) - } - - let res = null - if (query.sortBy === 'timestamp') { - res = await getArticlesByTime(query) - } else { - throw new Error('Sort field not supported') - } - // 从articles表只能获取到地址,没有昵称,下面一系列的操作是把昵称加入到返回结果中 - let addresses = res.articles.map((a) => a.authorId) - let accounts = await app.model.Account.findAll({ - condition: { - // sql的in查询 - address: { $in: addresses } - }, - fields: ['str1', 'address'] - }) - let accountMap = new Map - for (let account of accounts) { - accountMap.set(account.address, account) - } - for (let article of res.articles) { - let account = accountMap.get(article.authorId) - if (account) { - article.nickname = account.str1 - } - } - // 将key和其值加入到内存中 - app.custom.cache.set(key, res) - return res - }) -``` - -4.4 测试 -重启asch服务。 -此时已经能看到我们刚才定义的“发布文章的”智能合约 -![](http://asch-public.oss-cn-beijing.aliyuncs.com/pics/dapp%E6%A0%B8%E5%BF%83%E5%BC%80%E5%8F%91%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/13.png) - -根据编号为1000的智能合约的定义,我们可以传4个参数给后台。 -titile:news_title -url:null -test:This is news text. -tags:tag1 - -![](http://asch-public.oss-cn-beijing.aliyuncs.com/pics/dapp%E6%A0%B8%E5%BF%83%E5%BC%80%E5%8F%91%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/15.png) - -成功创建文章,交易id为:746279f5c7831968fb8e507456651f946b4aa5127125de6070143a8f82f00ffb -![](http://asch-public.oss-cn-beijing.aliyuncs.com/pics/dapp%E6%A0%B8%E5%BF%83%E5%BC%80%E5%8F%91%E6%B5%81%E7%A8%8B%E8%A7%A3%E6%9E%90/16.png) - - -根据interface定义的接口去查询数据 - -``` -http://localhost:4096/api/dapps/75d084dc91221b380e7a3c6b3b7467935572b4ebaa1e9a3db91e1239377c1fed/articles -``` - -未完待续 - - - - - - - diff --git a/docs/exchange/XAS_integration_in_exchange_CN.md b/docs/exchange/XAS_integration_in_exchange_CN.md deleted file mode 100644 index da65f42..0000000 --- a/docs/exchange/XAS_integration_in_exchange_CN.md +++ /dev/null @@ -1,268 +0,0 @@ -# XAS与交易平台对接文档 - - ---- - -## 1 Asch基本信息 -代币名称:阿希币 -英文标识:XAS -主网上线时间:2016-08-16 -发行总量:1亿,目前总的供应量为1.11亿XAS(有一个动态变化的通胀率,发行时间越长,通胀率越低) -共识算法:dpos+pbft -交易模式:账户余额模式,非UTXO -官网:www.asch.io -在线钱包:mainnet.asch.io,基本功能可以在这里进行体验 -区块链浏览器:https://explorer.asch.io/ -Asch地址:分为2类 - -- 老地址:纯数字格式的,长度不低于10,比如3432613344807570257 -- 新地址:字母数字混合,base58格式且以大写字母A开头且长度不低于10,比如A7RD9YP37iUnYZ1SFnmAp6ySHUx3msC4r5 - - -Asch不是btc源码的山寨而是用nodejs全新开发的,目前都是纯http api,所以对接的时候请勿用btc模板的交易网站代码去生拉硬套,目前有java和nodejs版本的sdk,交易平台可以直接用,其它开发语言,需要自己封装http api。 -Asch没有钱包的概念,每个密码对应一个账户地址,也就是说一个“钱包”中只包含一个地址(实质为脑钱包),与btc、eth等区别较大。 -Asch的精度是小数点后8位,但后台处理的时候都是按照整数来处理,比如想转0.1XAS,后台实际处理的是0.1 * 100000000。 -Asch http接口文档-中文版:https://github.com/AschPlatform/asch/blob/master/docs/asch_http_interface.md -Asch http接口文档-英文版:https://github.com/AschPlatform/asch/blob/master/docs/asch_http_interface_en.md -该文档包含大部分的Asch接口,比如查询余额、转账、交易详情等,调用api返回结果为json数据。 - - -## 2 建议交易平台在局域网内搭建一个Asch全节点(重钱包) -需要用Linux服务器(建议用ubuntu 16.04),这样交易平台处理充值、提现性能要好很多并且安全,不需要有公网ip但需要能访问公网。 -下面是节点搭建命令 -``` -> sudo apt-get update && sudo apt-get install curl wget sqlite3 ntp -y -> wget http://www.asch.io/downloads/asch-linux-latest-mainnet.tar.gz -> tar zxvf asch-linux-latest-mainnet.tar.gz -> # cd 解压后的目录名字,一般是 “asch-linux-版本号-mainnet” -> chmod u+x init/*.sh && sudo ./aschd configure -> # 下面这个curl命令是加载快照,加速第一次区块链同步的速度 -> curl -sL http://www.asch.io/downloads/rebuild-mainnet3.sh | bash -> tail logs/debug.log # 查看节点同步日志,等待同步到最新的区块即可。最新高度可以在区块链浏览器中看到 https://explorer.asch.io/ -``` - -## 3 用户充值XAS -Asch1.3版本开始支持转账备注,因此交易平台可以有下面两种充值方案。 -- `为每个用户生成一个充值地址` -- `为所有用户生成同一个充值地址,根据转账备注判断具体是哪个用户进行了充值` - -### 3.1 方案1-为每个用户生成一个充值地址 -目前bit-z.com、chaoex.com、coinegg.com、coolcoin .com等早期上线XAS的交易平台都是采用这种方式。 - -#### 3.1.1 为用户生成充值地址 -用户UserA登陆交易平台,进入Asch币充值页面,平台通过调用下面的代码生成充值地址、写入数据库,并在页面上展示给用户。 -通过下面的代码为UserA生成一个Asch充值地址:ALu3f2GaGrWzG4iczamDmGKr4YsbMFCdxB,该充值地址的密码是'latin december swing love square parade era fuel circle over hub spy',这里只是举例,数据非真实。 - -##### 3.1.1.1 调用http接口生成地址 - -``` -> curl -k -X GET 'http://192.168.1.100:8192/api/accounts/new' -// JSON返回示例如下 -{ - success: true, - secret: "during crush zoo wealth horror left night upset spike iron divert lawn", // 密码 - publicKey: "261fa56f389c324fddbe8777dbc0ef3341ee7b75d1ffdc82192265633b90d503", // 公钥 - privateKey: "67c9523b7622704c4bcfe960cb32d7fa04d3eb94e30e7964d3c6a24a3647a0a3261fa56f389c324fddbe8777dbc0ef3341ee7b75d1ffdc82192265633b90d503", // 私钥 - address: "ANfXDQUZroMnrQ6vRGR7UXXtbPn3fhEVRJ" // 地址 -} -``` - -##### 3.1.1.2 用asch-cli命令行工具批量生成地址 -``` -// 如果用其他编程语言,觉得批量生成账户地址有困难还可以用asch-cli命令行工具批量生成钱包地址(含密码、地址、公钥),生成多个地址,加密存到数据库或者其它地方,然后程序直接用. -// 安装asch-cli工具 -> npm install -g asch-cli -// 批量生成钱包地址 -// 需要nodejs版本为8.x,node --version查看node版本 -> asch-cli crypto -g -? Enter number of accounts to generate 1 // 这里输入的的1表示生成一个地址,可以填写10、100或者1000等数字 -[ { address: 'AAW3Bh86U8RdHryp86KN19ScSVLpr2x6J4', - secret: 'actress south egg hen neutral salute section sign truck produce agent daughter', - publicKey: 'fd86a5bb9e06bd3a0555e27402f90b565300b0a7a6fb42ee4269aae0cfca60c6' } ] -Done -``` - -##### 3.1.1.3 nodejs代码生成地址 -``` -// 以下为nodejs编程语言的demo(目前Asch SDK支持nodejs、java这2种语言,其它语言后续会支持,当前需开发者自行编码) - -// 建议用ubuntu 16.04,nodejs 8.x最新版 -// 安装nodejs的版本管理工具nvm -> curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.0/install.sh | bash -// 上面命令执行完成后再开一个os shell窗口执行下面的命令,安装nodejs 8.x -> nvm install node 8 - -// 安装依赖库(asch-js、bitcore-mnemonic),在os shell中运行 -> npm install asch-js bitcore-mnemonic - -// 以下在node中运行 -var Mnemonic = require('bitcore-mnemonic'); -var secret = new Mnemonic(Mnemonic.Words.ENGLISH).toString(); // 生成密码 -console.log(secret); // 打印密码,'latin december swing love square parade era fuel circle over hub spy' -Mnemonic.isValid(secret); // 验证密码是否符合bip39规范 - -var AschJS = require('asch-js'); -var publicKey = AschJS.crypto.getKeys(secret).publicKey; // 根据密码生成公钥 -var address = AschJS.crypto.getAddress(publicKey); // 根据公钥生成地址 -console.log(address); // 打印地址,ALu3f2GaGrWzG4iczamDmGKr4YsbMFCdxB -然后将用户名、地址、加密后的密码存入到数据库或者文件中,从而完成用户和充值地址的绑定,然后将充值地址展示在前端页面上。 -``` - -#### 3.1.2 用户进行充值 -用户UserA在Asch钱包(比如mainnet.asch.io)往充值地址转阿希币,比如转0.8XAS。 - -#### 3.1.3 交易平台确认用户充值 -交易平台检测每个新的区块,可以每隔10秒(也可以是30秒或者一分钟,技术上都没有问题,只是用户体验不一样)检测一次,每次检查时区块高度加1,检查的高度建议持久化存储并增加一个标记位“是否已检查”。 -如果区块里面交易详情的接收地址是平台的充值地址,则该笔充值记录需要显示到前端页面上并入库。 -##### 3.1.3.1 检测最新区块是否包含交易 - -``` -// 通过区块高度获去检查该区块是否有交易并取到区块id,每个新区块都要检查 -// height=3183940表示区块高度 -> curl -k -X GET 'http://mainnet.asch.io/api/blocks/get?height=3183940' -// 返回结果如下,保存到变量res中,下面会用到 -{ - "success": true, - "block": { - "id": "951e14ef5100a9724a133f74e8f5c35e0d872aee654e7ea5323e57cd1c7b004e", // 区块id - "version": 0, - "timestamp": 36252710, - "height": 3183940, - "previousBlock": "5dbf4b80063153e3bb66b46b27f9041955d308c47d57e51b4934952591519589", - "numberOfTransactions": 1, //该区块包含的交易个数 - "totalAmount": 80000000, - "totalFee": 10000000, - "reward": 350000000, - "payloadLength": 143, - "payloadHash": "5a61b58b75a70a42a6d51deba4dba560c78b2d671dfac68d37984eb464421d81", - "generatorPublicKey": "65e318f0022e3a05cc1603610125cf42af6772ac1afed657eec44bb3f8b02e64", - "generatorId": "9537352069871373416", - "blockSignature": "7b26571e3a55798d83e531817a5971ebdca59b4cfbb1edd182aff3b25c31578356b3a8992714b543f004cd7b362d7069f5dd426f411caacf06659747de1e580e", - "confirmations": "17", // 该区块的确认数 - "totalForged": 360000000 - } -} -``` -##### 3.1.3.2 根据区块id查询交易详情 - -``` -// 如果res.block.numberOfTransactions > 0,则说明该区块包含交易。 -// 然后根据res.block.id并利用下面的接口去查询该区块包含的交易详情 -> curl -k -X GET 'http://mainnet.asch.io/api/transactions?blockId=951e14ef5100a9724a133f74e8f5c35e0d872aee654e7ea5323e57cd1c7b004e' -// 返回结果如下,保存为变量trs -{ - "success": true, - "transactions": [{ - "id": "5a61b58b75a70a42a6d51deba4dba560c78b2d671dfac68d37984eb464421d81", // 交易id - "height": "3183940", //区块高度 - "blockId": "951e14ef5100a9724a133f74e8f5c35e0d872aee654e7ea5323e57cd1c7b004e", //区块id - "type": 0, // 交易类型,0:XAS普通转账 - "timestamp": 36252686, // 交易时间戳,Asch时间,可以换算成现实世界的时间 - "senderPublicKey": "40e322be1ec9084f48a17b5fecf88d59d0c70ce7ab06b1c4f6d285acfa3b0525", - "senderId": "AC4i4srjg1TyW24p8M4B8NTcYApUgvTpkd", // 发送地址 - "recipientId": "ALu3f2GaGrWzG4iczamDmGKr4YsbMFCdxB", // 接收地址,如果是平台地址,则需要做处理 - "amount": 80000000, //转账金额,除以100000000后是真实的XAS个数,这里0.8XAS - "fee": 10000000, - "signature": "08a97ba29f7db324b31f782272e17c048f4b99d1761830bd7f541c484c28fcf14b1ee0dbbdd05ab2e80d186473e67d9bfed8e27b8c5e096d29a7f521236d8900", - "signSignature": "", - "signatures": null, - "confirmations": "20", // 区块确认数 - "args": [], - "message": "", // 转账备注 - "asset": { - - } - }], - "count": 1 // 该区块包含的交易个数 -} - -// 如果数组trs.transactions.length>0,则循环遍历trs.transactions得到元素i,如果(i.type == 0 and i.recipientId是平台的地址),那么前端页面就要展示该充值记录并将该记录(充值id、充值地址、数量、确认数、发送时间、充值状态、交易id)写入到本地数据库中。 - -// 充值状态是由确认数决定的,具体是几,由平台自己定,如果入库时确认数未满足平台标准,则充值状态是“未确认”,否则就是“已确认”.(目前Asch网络认为6个确认就是安全的,交易平台可适当增大该值。) - -// 每隔1分钟对本地数据库中所有的“未确认”充值记录进行再次确认,根据数据库中的“交易id”利用下面的接口去检查交易详情 -> curl -k -X GET 'http://mainnet.asch.io/api/transactions/get?id=5a61b58b75a70a42a6d51deba4dba560c78b2d671dfac68d37984eb464421d81' -{ - "success": true, - "transaction": { - "id": "5a61b58b75a70a42a6d51deba4dba560c78b2d671dfac68d37984eb464421d81", - "height": "3183940", - "blockId": "951e14ef5100a9724a133f74e8f5c35e0d872aee654e7ea5323e57cd1c7b004e", - "type": 0, - "timestamp": 36252686, - "senderPublicKey": "40e322be1ec9084f48a17b5fecf88d59d0c70ce7ab06b1c4f6d285acfa3b0525", - "senderId": "AC4i4srjg1TyW24p8M4B8NTcYApUgvTpkd", - "recipientId": "ALu3f2GaGrWzG4iczamDmGKr4YsbMFCdxB", //接收地址 - "amount": 80000000, // 金额 - "fee": 10000000, - "signature": "08a97ba29f7db324b31f782272e17c048f4b99d1761830bd7f541c484c28fcf14b1ee0dbbdd05ab2e80d186473e67d9bfed8e27b8c5e096d29a7f521236d8900", - "signSignature": "", - "signatures": null, - "confirmations": "7837", // 确认数 - "args": [], - "message": "", // 转账备注信息 - "asset": { - - } - } -} -// 当"confirmations"达到平台要求后,更改数据库中的“充值状态”为“已确认”并显示在前端页面,最后用户UserA的XAS余额做相应的增加。 - -``` -至此用户UserA完成了充值流程。 - -#### 3.1.4 交易平台将用户充值的XAS转到一个总账户中 -充值完成后,交易平台再将这些分散的用户xas转账到交易平台自己的总账户中(请一定保存好密码)。 -总账户:可以做为平台的Asch冷钱包或者热钱包供用户提现。 -举例,平台XAS总账户地址:A7RD9YP37iUnYZ1SFnmAp6ySHUx3msC4r5 -Asch提供了下面2种方式进行转账操作。 - -##### 3.1.4.1 通过不安全的api进行转账 -这种方式是把密钥放到请求里面并且明文发送给服务器进行交易的生成和签名,不安全,不建议使用。如果非要使用这种方式,务必在局域网内搭建一台Asch节点服务器,用来提供API服务。 - -- 汇总前通过查询本地数据库将XAS余额大于0的账户找到 - -- 可以利用如下api将充值的XAS转入到平台总账户中,该操作消耗0.1XAS手续费 -``` -> curl -k -H "Content-Type: application/json" -X PUT -d '{"secret":"latin december swing love square parade era fuel circle over hub spy","amount":70000000,"recipientId":"A7RD9YP37iUnYZ1SFnmAp6ySHUx3msC4r5","message":"beizhu"}' 'http://192.168.1.100:8192/api/transactions' && echo // 70000000表示0.7 XAS,因为网络需要收取固定的0.1XAS手续费,所以UserA的充值地址只可以转出0.7 XAS -// 返回结果如下 -{ - "success": true, // 转账状态,成功 - "transactionId": "6d9b9338ea71ca74a41995458959250e16e49f52b31f4887ac28d3cc3586b1a1" // 交易id -} -``` - -##### 3.1.4.2 通过安全的api进行转账 -建议使用这种安全的方法进行转账,此种方法是在本地生成交易信息并签名,然后广播到区块链网络中,这里对Asch Server没有安全性要求。 -``` -var asch = require('asch-js'); -var targetAddress = "A7RD9YP37iUnYZ1SFnmAp6ySHUx3msC4r5"; // 接受地址 -var amount = 0.7*100000000; // 0.7 XAS -var message = 'beizhuxinxi'; // 转账备注 -var password = 'latin december swing love square parade era fuel circle over hub spy'; // 发送者主密码 -var secondPassword=null; // 发送者二级密码,如果没有设置的话就是null -// 生成交易信息并签名 -var transaction = asch.transaction.createTransaction(targetAddress, amount, message, password, secondPassword || undefined); -JSON.stringify({"transaction":transaction}) -'{"transaction":{"type":0,"amount":70000000,"fee":10000000,"recipientId":"A7RD9YP37iUnYZ1SFnmAp6ySHUx3msC4r5","message":"beizhuxinxi","timestamp":43831575,"asset":{},"senderPublicKey":"d1cda821c7f98436f0c7824b96e9fe4dba50d54ed8fd69a92752cd923e416fc2","signature":"005e529e580010398424dbbd65b9c154b37f6cd575010a4f6d9396594311c1ef62487f1040a2cba1dd16a5dba3d12605d211fa08171967886ce9ef301ae82f05","id":"0f28435e9c395dd6b825bda167359bc23d41b5fc632afb59fedfafa298c27cde"}}' - -// 将上面生成的转账操作的交易数据通过post提交给asch server -curl -H "Content-Type: application/json" -H "magic:5f5b3cf5" -H "version:''" -k -X POST -d '{"transaction":{"type":0,"amount":70000000,"fee":10000000,"recipientId":"A7RD9YP37iUnYZ1SFnmAp6ySHUx3msC4r5","message":"beizhuxinxi","timestamp":43831575,"asset":{},"senderPublicKey":"d1cda821c7f98436f0c7824b96e9fe4dba50d54ed8fd69a92752cd923e416fc2","signature":"005e529e580010398424dbbd65b9c154b37f6cd575010a4f6d9396594311c1ef62487f1040a2cba1dd16a5dba3d12605d211fa08171967886ce9ef301ae82f05","id":"0f28435e9c395dd6b825bda167359bc23d41b5fc632afb59fedfafa298c27cde"}}' http://192.168.1.100:8192/peer/transactions -``` - - -### 3.2 方案2-为所有用户生成同一个充值地址 -所有的用户共用一个Asch充值地址,充值时填写备注信息为自己在交易平台的用户名或者id,这样就不需要生成多个Asch充值地址了,但是如果用户填写错备注信息的话处理起来较为麻烦,需要专人客服去处理。 -该种方式,大体流程和方案1一致,这里不再赘述。 - - -## 4 提币XAS -提现操作就是转账,把平台的币转给用户。 -### 4.1 用户绑定提币地址 -用户登陆Asch提现页面,参考其它代币,让用户可以自行绑定提现地址。 -### 4.2 用户进行提币 -输入提币数量,手机短信验证,点击确认。 -### 4.2 平台执行提币操作 -参考“3.1.4”章节,有2种转账方式,请自行决定用哪一种。接口会返回,提币的交易id,记录到数据库中并展示到前端页面,更新提币状态为“成功”。 -### 4.3 用户确认 -用户自行确认提币结果,如有疑问,可以拿着交易id来平台这里进行查询验证。 diff --git a/docs/exchange/XCT_integration_in_exchange_CN.md b/docs/exchange/XCT_integration_in_exchange_CN.md deleted file mode 100644 index d4e0430..0000000 --- a/docs/exchange/XCT_integration_in_exchange_CN.md +++ /dev/null @@ -1,345 +0,0 @@ -# CCTime.XCT与交易平台对接文档 - - - ---- - -写在前面的话,本文档同样适用于在Asch平台发行的其它资产与交易平台的对接,其它资产请将下面的CCTime.XCT 换成你的资产名即可。 - -## 1 CCTime.XCT基本信息 -中文名称:时讯币 -英文标识:CCTime.XCT(前台页面可以展示为XCT,但后端调用接口处理时则必须是CCTime.XCT) -发行总量:最大发行总量100亿(目前已空投10亿,精度为8位) -官网:http://cctime.org -在线钱包:http://asch.cn ,基本功能可以在这里进行体验。 -特别声明:XCT是在Asch发行的资产(UIA),所以可以跟xas共用一个地址,具体是否共用,由交易平台自行决定。 -发行说明:采用空投的方式将XCT分给XAS、BTC、ETH、BTS持有者。 - -备注:由于XCT是在Asch上面发行的资产,所以XCT的在Asch主链上的转账需要支付XAS做为手续费,目前每笔XCT转账都需要固定的0.1XAS手续费。(类比以太坊的ERC20资产转账需要消耗ETH) - -对XCT的操作可以通过Asch API来进行。 -Asch http接口文档-中文版:https://github.com/AschPlatform/asch/blob/master/docs/asch_http_interface.md -Asch http接口文档-英文版:https://github.com/AschPlatform/asch/blob/master/docs/asch_http_interfaceen.md -该文档包含大部分的Asch接口,比如查询余额、转账、交易详情等,调用api返回结果为json数据。 - - -## 2 建议交易平台在局域网内搭建一个Asch全节点 -需要用Linux服务器(建议用ubuntu 16.04),这样交易平台处理充值、提现性能要好很多并且安全,不需要有公网ip但需要能访问公网。 -下面是节点搭建命令 - -``` -> sudo apt-get update && sudo apt-get install curl wget sqlite3 ntp -y -> wget http://www.asch.io/downloads/asch-linux-latest-mainnet.tar.gz -> tar zxvf asch-linux-latest-mainnet.tar.gz -> # cd 解压后的目录名字,一般是 “asch-linux-版本号-mainnet” -> chmod u+x init/*.sh && sudo ./aschd configure -> # 下面这个curl命令是加载快照,加速第一次区块链同步的速度 -> curl -sL http://www.asch.io/downloads/rebuild-mainnet3.sh | bash -> tail logs/debug.log # 查看节点同步日志,等待同步到最新的区块即可。最新高度可以在区块链浏览器中看到 https://explorer.asch.io/ -``` -举例:这里搭建完成后局域网ip是:192.168.1.100 - -备注:交易平台开发对接阶段可以用我们提供的测试服务器http://101.200.84.232:4097 ,测试账户密码'found knife gather faith wrestle private various fame cover response security predict' - -## 3 充值XCT -Asch1.3版本开始支持转账备注,因此交易平台可以有两种充值方案。 - -- `为每个用户生成一个充值地址` -- `为所有用户生成同一个充值地址,根据转账备注判断具体是哪个用户进行了充值` - -### 3.1 方案1-为每个用户生成一个充值地址 -目前bit-z.com、chaoex.com、coinegg.com、coolcoin.com等早期上线XAS的交易平台都是采用这种方式。 - - -#### 3.1.1 为用户生成充值地址 -用户UserA登陆交易平台,进入XCT充值页面,平台通过调用下面的代码生成充值地址,并将地址、密码(需要加密存储)写入数据库或者其它持久化存储中,并在页面上展示给用户。 - -通过下面几种生成地址方法中的任意一种为UserA生成一个Asch充值账户。 -地址:ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M -密码:'found knife gather faith wrestle private various fame cover response security predict',这里只是举例,数据非真实。 - -##### 3.1.1.1 调用http接口生成地址 - -``` -curl -k -X GET 'http://192.168.1.100:4096/api/accounts/new' - -// JSON返回示例: -{ - success: true, - secret: "during crush zoo wealth horror left night upset spike iron divert lawn", // 主密码 - publicKey: "261fa56f389c324fddbe8777dbc0ef3341ee7b75d1ffdc82192265633b90d503", // 公钥 - privateKey: "67c9523b7622704c4bcfe960cb32d7fa04d3eb94e30e7964d3c6a24a3647a0a3261fa56f389c324fddbe8777dbc0ef3341ee7b75d1ffdc82192265633b90d503", // 私钥 - address: "ANfXDQUZroMnrQ6vRGR7UXXtbPn3fhEVRJ" // 地址 -} -``` - -##### 3.1.1.2 用asch-cli命令行工具批量生成地址 - -``` -// 用asch-cli命令行工具批量生成钱包地址(含密码、地址、公钥),生成多个地址,加密存到数据库或者其它地方,然后程序直接用. -// 安装asch-cli工具 -npm install -g asch-cli -// 批量生成钱包地址 -asch-cli crypto -g -? Enter number of accounts to generate 1 //这里的1表示生成一个地址,可以填写10、100等数字 -[ { address: 'AAW3Bh86U8RdHryp86KN19ScSVLpr2x6J4', - secret: 'actress south egg hen neutral salute section sign truck produce agent daughter', - publicKey: 'fd86a5bb9e06bd3a0555e27402f90b565300b0a7a6fb42ee4269aae0cfca60c6' } ] -Done -``` - -##### 3.1.1.3 nodejs代码生成地址 - -``` -// 以下为nodejs编程语言的demo(目前Asch SDK支持nodejs、java这2种语言,其它语言后续会支持,当前需开发者自行编码) - -// 建议用ubuntu 16.04,nodejs 8.x最新版 -// 安装nodejs的版本管理工具nvm -curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.0/install.sh | bash -// 上面命令执行完成后再开一个os shell窗口执行下面的命令,安装nodejs 8.x -nvm install node 8 - -// 安装依赖库(asch-js、bitcore-mnemonic),在os shell中运行 -npm install asch-js bitcore-mnemonic - -// 以下在node中运行 -var Mnemonic = require('bitcore-mnemonic'); -var secret = new Mnemonic(Mnemonic.Words.ENGLISH).toString(); // 生成密码 -console.log(secret); // 打印密码,'latin december swing love square parade era fuel circle over hub spy' -Mnemonic.isValid(secret); // 验证密码是否符合bip39规范 - -var AschJS = require('asch-js'); -var publicKey = AschJS.crypto.getKeys(secret).publicKey; // 根据密码生成公钥 -var address = AschJS.crypto.getAddress(publicKey); // 根据公钥生成地址 -console.log(address); // 打印地址,ALu3f2GaGrWzG4iczamDmGKr4YsbMFCdxB -然后将用户名、地址、加密后的密码存入到数据库或者文件中,从而完成用户和充值地址的绑定,然后将充值地址展示在前端页面上。 -``` - - - - -#### 3.1.2 用户进行充值 -用户UserA在XCT钱包(比如http://asch.cn)往充值地址转XCT,比如转10 XCT。 - -#### 3.1.3 交易平台确认用户充值 -交易平台检测每个新的区块,可以每隔10秒检测一次,每次检查时区块高度加1,检查的高度建议持久化存储并增加一个标记位“是否已检查”,这样做的优势:能最快地检测到用户的充值信息并保证充值金额的正确(用户在极短时间内充值多次相同的金额也能保证结果准确)。 - -下面演示UserA的充值确认过程。 -``` -// 通过区块高度获去检查该区块是否有交易,每个新区块都要检查 -// height=223994,表示最新的区块高度是223994 -curl -k -X GET 'http://192.168.1.100:4097/api/blocks/full?height=223994' -// 返回结果如下(该json结果保存到变量res中) -{ - success: true, // 接口是否成功被调用 - block: { - id: "322e0f70f1e9de584fcf60fdcd10306691dbcdb7d738db66062c860dc29e3333", // 区块id - version: 0, - timestamp: 41428170, - height: 223994, // 区块高度 - previousBlock: "20594953fed0d67c87639f0c42050d56b3d1ddc06a72990b916dbd6676288310", - numberOfTransactions: 1, - totalAmount: 0, - totalFee: 10000000, // 该区块中所有交易的手续费之和0.1XAS(xas精度是8) - reward: 350000000, - payloadLength: 177, - payloadHash: "a43f6d3fb54b27c90503cb5d619e63f33cf1e2b7df72354ebbe4d6aab7175145", - generatorPublicKey: "238bdc9d75760560d438a86adef6f3126c5cd0f0be43ebbd9a9053f705a30176", - generatorId: "15652667420882928094", - blockSignature: "ab322a2adf7fe1eb02c746bafa365e7bc0408b5fefc2d8ae3954cfbf0d3a6e74b44ac7b178a7d663610bd30296a7c1cf95af6ee2ed3417fbf5642ccd53e6480a", - totalForged: 360000000, - transactions: [{ // 该区块包含的所有交易详情列表,每个元素代表一个交易 - id: "a43f6d3fb54b27c90503cb5d619e63f33cf1e2b7df72354ebbe4d6aab7175145", // 充值交易id - height: 223994, - blockId: "322e0f70f1e9de584fcf60fdcd10306691dbcdb7d738db66062c860dc29e3333", - type: 14, // XCT转账的类型为14 - timestamp: 41428161, // 充值时间戳,Asch纪元,可以转换为unix timestamp - senderPublicKey: "b33b5fc45640cfc414981985bf92eef962c08c53e1a34f90dab039e985bb5fab", - requesterPublicKey: "", - senderId: "AMzDw5BmZ39we18y7Ty9VW79eL9k7maZPH", // 发送者地址 - recipientId: "ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M", // 接收者地址 - amount: 0, - fee: 10000000, // 本条交易转账手续费0.1XAS(目前每笔转账都是固定的0.1XAS手续费) - signature: "9e77b3868869af334d539d23feb5d4746db5c842466207f9c22f7e4dee91f4722c8738bc8bcc36abb7365d24dadb26727110ab18673b9bb86a32c29e4b96260c", - signSignature: "", - signatures: null, - args: null, - message: "deposit 10 XCT", // 冲值时的备注信息 - asset: { - uiaTransfer: { - transactionId: "a43f6d3fb54b27c90503cb5d619e63f33cf1e2b7df72354ebbe4d6aab7175145", // 充值交易id - currency: "CCTime.XCT", // 资产名字,CCTime.XCT代表XCT - amount: "1000000000" // 转账数额=真实数额10*XCT精度8,这里是10 XCT - } - } - }] - } -} - -// 如果上面的res.block.numberOfTransactions == 0则直接跳过该区块,否则循环遍历的res.block.transactions交易详情数组得到每条交易记录trs. -// 如果(trs.type == 14 and trs.recipientId在'交易平台的充值地址列表'中 and trs.asset.uiaTransfer.currency == 'CCTime.XCT')则代表该交易为XCT的冲值记录。此时前端页面就要展示该充值记录并将该记录(充值id、平台的充值地址、数量、确认数、发送时间、充值状态、交易id)写入到本地数据库中。 - -// 充值状态是由确认数决定的,具体是几,由平台自己定,如果入库时确认数未满足平台标准,则充值状态是“未确认”,否则就是“已确认”。(目前Asch网络认为6个确认就是安全的,交易平台可适当增大该值。) -// 每隔2分钟(交易平台可以自定义该时间,时间越短用户体验越好)对本地数据库中所有的“未确认”充值记录进行再次确认,根据数据库中的“交易id”利用下面的接口去检查交易详情 -curl -k -X GET 'http://192.168.1.100:4097/api/transactions/get?id=a43f6d3fb54b27c90503cb5d619e63f33cf1e2b7df72354ebbe4d6aab7175145' -{ - success: true, - transaction: { - id: "a43f6d3fb54b27c90503cb5d619e63f33cf1e2b7df72354ebbe4d6aab7175145", - height: "223994", - blockId: "322e0f70f1e9de584fcf60fdcd10306691dbcdb7d738db66062c860dc29e3333", - type: 14, - timestamp: 41428161, - senderPublicKey: "b33b5fc45640cfc414981985bf92eef962c08c53e1a34f90dab039e985bb5fab", - senderId: "AMzDw5BmZ39we18y7Ty9VW79eL9k7maZPH", - recipientId: "ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M", - amount: 0, - fee: 10000000, - signature: "9e77b3868869af334d539d23feb5d4746db5c842466207f9c22f7e4dee91f4722c8738bc8bcc36abb7365d24dadb26727110ab18673b9bb86a32c29e4b96260c", - signSignature: "", - signatures: null, - confirmations: "326", // 区块确认数 - args: null, - message: "deposit 10 XCT", - asset: { - - } - } -} -// 当"confirmations"达到平台要求后,更改数据库中的“充值状态”为“已确认”并显示在前端页面,最后用户UserA在交易平台的XCT余额做相应的增加。 - -``` -至此用户UserA完成了充值流程。 - -#### 3.1.4 交易平台将用户充值的XCT转到一个总账户中 -充值完成后,交易平台再将这些分散的用户XCT转账到交易平台自己的总账户中(请一定保存好密码)。 -总账户:可以做为平台的XCT冷钱包或者热钱包供用户提现。 -举例,平台XCT总账户地址:A7RD9YP37iUnYZ1SFnmAp6ySHUx3msC4r5 - -Asch提供了下面2种方式进行XCT转账操作,请选择其中一种即可。 - -##### 3.1.4.1 通过不安全的api进行XCT转账 -这种方式是把密钥放到请求里面并且明文发送给服务器进行交易的生成和签名,不安全,不建议使用。如果非要使用这种方式,务必在局域网内搭建一台Asch节点服务器,用来提供API服务。 - -- 汇总前需要确定UserA充值地址上有多少个XCT -``` -curl -X GET http://192.168.1.100:4097/api/uia/balances/ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M/CCTime.XCT -// 返回结果如下 -{ - success: true, - balance: { - currency: "CCTime.XCT", - balance: "990900000000", // 该值=余额*100000000 - maximum: "10000000000000000", - precision: 8, // XCT的精度 - quantity: "20000000000000000", - writeoff: 0, - allowWriteoff: 0, - allowWhitelist: 0, - allowBlacklist: 0, - maximumShow: "100000000", - quantityShow: "200000000", - balanceShow: "9909" // 该账户余额为9909个XCT,平台可以设定当该值大于某个值时才会进行向总钱包汇总 - } -} -``` - -- 确认UserA充值地址上是否有XAS(XCT每次转账都需要消耗0.1XAS) -``` -curl -X GET 'http://192.168.1.100:4097/api/accounts/getBalance?address=ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M' -// 返回结果 -{ - success: true, - balance: 0, // 0个XAS - unconfirmedBalance: 0 -} -``` - -- 如果UserA充值地址上的XAS余额小于0.1,则需要给该地址转一笔小额的XAS做XCT转账时的手续费 -``` -// 'object betray start purse camp remove lucky cry soccer middle harvest clerk'为有XAS余额的账户 -curl -k -H "Content-Type: application/json" -X PUT -d '{"secret":"object betray start purse camp remove lucky cry soccer middle harvest clerk","amount":100000000,"recipientId":"ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M"}' 'http://192.168.1.100:4097/api/transactions' && echo // 给用户充值地址转1XAS做为后面XCT转账时的手续费,该操作本身也消耗0.1XAS手续费 -// 返回结果 -{ - "success": true, - "transactionId": "0c8d1c0174ceb563d074a742934920b07fb8a29b5ff1d8450d0885c300dedd53" -} -``` - -- 将UserA充值地址上的全部XCT转入到平台总账户中 -``` -curl -k -H "Content-Type: application/json" -X PUT -d '{"secret":"found knife gather faith wrestle private various fame cover response security predict","amount":"99090000000","recipientId":"A7RD9YP37iUnYZ1SFnmAp6ySHUx3msC4r5","currency":"CCTime.XCT"}' 'http://192.168.1.100:4097/api/uia/transfers' && echo // 99090000000表示9909 XCT -// 返回结果如下 -{ - "success": true, // 转账状态,成功 - "transactionId": "ab0f548a3a3b56d437187d1c26a25a3d3c5411821955301ab44dcd8511f5da64" // 交易id -} - -``` - -##### 3.1.4.2 通过安全的api进行XCT转账(本地签名) -建议使用这种安全的方法进行转账,此种方法是在本地生成交易信息并签名,然后广播到区块链网络中,这里对Asch Server没有安全性要求。 - -- 只有XAS转账和XCT转账和上面章节不一样,其它查询操作一致。 - -- 如果UserA充值地址上的XAS余额小于0.1,则需要给该地址转一笔小额的XAS做XCT转账时的手续费 -``` -// asch-js安装参考《3.1.1.3 nodejs代码生成地址》章节 -var asch = require('asch-js'); -var targetAddress = "ANH2RUADqXs6HPbPEZXv4qM8DZfoj4Ry3M"; -var amount = 1*100000000; //1 XAS -var password = 'object betray start purse camp remove lucky cry soccer middle harvest clerk'; -var message = ''; // 转账备注 -// 生成交易信息并签名 -var transaction = asch.transaction.createTransaction(targetAddress, amount, message, password); -JSON.stringify({transaction:transaction}) -'{"transaction":{"type":0,"amount":100000000,"fee":10000000,"recipientId":"A7RD9YP37iUnYZ1SFnmAp6ySHUx3msC4r5","timestamp":5333378,"asset":{},"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","signature":"2d47810b7d9964c5c4d330a53d1382769e5092b3a53639853f702cf4a382aafcff8ef8663c0f6856a23f41c249944f0c3cfac0744847268853a62af5dd8fc90a","signSignature":"dfa9b807fff362d581170b41c56a2b8bd723c48d1f100f2856d794408723e8973016d75aeff4705e6837dcdb745aafb41aa10a9f1ff8a77d128ba3d712e90907","id":"a95c3a5bda15f3fd38295950268c234e922aae97cf803dd8c38c73a6ccf7c561"}}' - -// 将上面生成的转账操作的交易数据通过post提交给asch server -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":0,"amount":100000000,"fee":10000000,"recipientId":"A7RD9YP37iUnYZ1SFnmAp6ySHUx3msC4r5","timestamp":5333378,"asset":{},"senderPublicKey":"3e6e7c90571b9f7dabc0abc2e499c2fcee8e436af3a9d5c8eadd82ac7aeae85f","signature":"2d47810b7d9964c5c4d330a53d1382769e5092b3a53639853f702cf4a382aafcff8ef8663c0f6856a23f41c249944f0c3cfac0744847268853a62af5dd8fc90a","signSignature":"dfa9b807fff362d581170b41c56a2b8bd723c48d1f100f2856d794408723e8973016d75aeff4705e6837dcdb745aafb41aa10a9f1ff8a77d128ba3d712e90907","id":"a95c3a5bda15f3fd38295950268c234e922aae97cf803dd8c38c73a6ccf7c561"}}' http://192.168.1.100:4096/peer/transactions -// 返回结果 -{ - "success":true, //转账成功 - "transactionId":"a95c3a5bda15f3fd38295950268c234e922aae97cf803dd8c38c73a6ccf7c561" -} -``` - -- 将UserA充值地址上的全部XCT转入到平台总账户中 -``` -var asch = require('asch-js'); -var currency = 'CCTime.XCT'; // 资产名 -// 本次转账数(9909)=真实数量(9909)*10**精度(8) -var amount = String(9909 * 100000000); -var recipientId = 'A7RD9YP37iUnYZ1SFnmAp6ySHUx3msC4r5'; // 接收地址,即总账户地址 -var message = 'memo'; // 转账备注 -var secret = 'found knife gather faith wrestle private various fame cover response security predict'; -var trs = asch.uia.createTransfer(currency, amount, recipientId, message, secret); - -JSON.stringify({transaction:trs}) -'{"transaction":{"type":14,"amount":0,"fee":10000000,"recipientId":"A7RD9YP37iUnYZ1SFnmAp6ySHUx3msC4r5","senderPublicKey":"2856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec4","timestamp":42795778,"message":"memo","asset":{"uiaTransfer":{"currency":"CCTime.XCT","amount":"990900000000"}},"signature":"a09e2cd425e32656c8a1411ffde48dd53917f65af562dd235e47bca6e151ed8d9742ed1e799a5a2ed26dfce0761ff518ced691953a3f150ecab5bfa740a1590c","id":"5c61ce9c88c7a957d6dd4e2585c7382d0bdd9a4f889976aefae172f5211610fb"}}' - -// 广播该交易 -curl -H "Content-Type: application/json" -H "magic:594fe0f3" -H "version:''" -k -X POST -d '{"transaction":{"type":14,"amount":0,"fee":10000000,"recipientId":"A7RD9YP37iUnYZ1SFnmAp6ySHUx3msC4r5","senderPublicKey":"2856bdb3ed4c9b34fd2bba277ffd063a00f703113224c88c076c0c58310dbec4","timestamp":42795778,"message":"memo","asset":{"uiaTransfer":{"currency":"CCTime.XCT","amount":"990900000000"}},"signature":"a09e2cd425e32656c8a1411ffde48dd53917f65af562dd235e47bca6e151ed8d9742ed1e799a5a2ed26dfce0761ff518ced691953a3f150ecab5bfa740a1590c","id":"5c61ce9c88c7a957d6dd4e2585c7382d0bdd9a4f889976aefae172f5211610fb"}}' 'http://localhost:4096/peer/transactions' && echo -// 返回结果 -{"success":true} -``` - - - -### 3.2 方案2-转账备注方式 -所有的用户共用一个XCT充值地址,充值时填写备注信息为自己在交易平台的用户名或者id,这样就不需要生成多个地址了,但是用户填写错备注的话处理起来较为麻烦。 -该种方式,大体流程和方案1一致,这里不再赘述。 - - -## 4 提币XCT -提现操作就是转账,把平台的币转给用户。 -### 4.1 用户绑定提币地址 -用户登陆Asch提现页面,参考其它代币,让用户可以自行绑定提现地址。 -XCT地址符合base58规则、以大写字母A开头、地址长度至少是24个字母数字的混合体。 -### 4.2 用户进行提币 -输入提币数量,手机短信验证,点击确认。 - -### 4.2 平台执行提币操作 -参考“3.1.4”章节,有2种转账方式,请自行决定用哪一种。接口会返回,提币的交易id,记录到数据库中并展示到前端页面,更新提币状态为“成功”。 -### 4.3 用户确认 -用户自行确认提币结果,如有疑问,可以拿着交易id来平台这里进行查询验证。 diff --git a/docs/whitepaper/assets/chart.png b/docs/whitepaper/assets/chart.png deleted file mode 100644 index 8d66271d17af7610c105dffc62f4f4a4f3e9052e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29796 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 Xp#lT8VKvzFP&j3I4Y_(5i}3#kmkm!1 diff --git a/docs/whitepaper/assets/chart2.png b/docs/whitepaper/assets/chart2.png deleted file mode 100644 index 0fcf1529994e91ed28cefaef3811aa9eaa1b1c0c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45085 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 diff --git a/docs/whitepaper/assets/math.png b/docs/whitepaper/assets/math.png deleted file mode 100644 index 32bcabb371a0933d43cd73a68fccd3d18c4a704d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76160 zcmdpdMOYnO&?a2m-Q6{~ySoMV-~@NKi)(;DaQEOAoZuQD1cJM}yE7N^{WHti&NB-Z zeVaaAr%uURZ&gRCC`lv1Ym_7 zSx_SCBe#R6(987sK~bSbxwP1{^w^Ci9)Upyymx}lMUs-{zm@qoeA()+;3}wUTFm>Ltj{%i}_ES zc=g=Qf3HK6p%76e`vO(;pJ0W6XC&13TO#=23Gh~ow37c8pv2m9_-|j6u<`0LrlNH3 z@`6MW34r*&Z$(m@zHeZFSirN!xHs(J;Gn^JdZEq3!Pi$nYG-$s+i|U{&U~cNVfAIM z*3`+#$*MO=PSEo#_fx0;_DBjhJ9`GFO>$FH)7H*x^{3tOoH)M2nM$9%KV+pew6bp! z(!M~xXpzhUFMm!1M< z7K9Yp&!?TQTy_gn?RVg?r{H+N^i>q~)j+(Ls*cv3fLjWUgL3uEK2*CEJOXn1&$a@Mm|l@%3? zUfs;9Rll?NQ|Q#7p`s4;N}S%$n~g#xgi|Jg%=o0SwiYc?B0D=fb(=)kzal?hwc7A! zg(M*R`RV>LgWDnZGaDyozj6gjjl|u}vEJ>;@>f}MvieTkUo;@8JTYi{Y@lxX=N1+W z+uV<5D)rLS)5kKn!v#tCUHA%nKpW4aqc>>f=So@$|lPiOQvSa=|?&|7FE{Wc4a{wt7lJUa_bE(3z zGWbn!Oo<~lau$}e(KL2#2BTZFA5z+OA~GWRq?Ogx%+EZC69WSSET8|ff&8f`5@Zuq zkWn|fqU7i-CEPYMh%=$Tk{C=|P*G7yFB{i^XW2zQ>V5v&{BRfFB}KP!vdg z!8cxZ+@GXMv#f=r`ISQZvVovr46ElMMidabo{*7Xm@=u9q@Dq&YPE)M>YX4hB-J{Zd+bnCL>UZ zOi#zh#`ElEp{S+tMnbsBrOo{Q{7Zo9mEC1 zVp^`6Se7Rt6e+z@ju6tKcnXt&w%Iq3nSoSq3TV+~uw7}_xfru|a6p+xVv&@T^t-=+ z>fUET=pD!)S<9sh+Q&^%*iPH-)j$G3NSWf|uFU`;nbIuJG3rDuZqe9kKVY>b@wx7S z;qXSP4BwG%zX!S~j6i)^sP8⪻@aJqQTI3`1nBxH{RrTdzrj0*i8C!`H~1Nmk!{Y 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 diff --git a/docs/whitepaper/assets/score.png b/docs/whitepaper/assets/score.png deleted file mode 100644 index 48955409854b79cdbeddd76d9b639341238f3493..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1470 zcmV;v1ws0WP)YjRCRj+%m_>-S@9@yXCUszZuieh(n_wMe_4>~WAKR-V^I}6HTUo%b}{AoBnKR^31H#avM z8yj9T4LRe~!K+oAh^>c*hqbk}4pw?~%{X;%+v4IPy&(}AL&iHeIMD0#gp5-+-$Lq? z_hysvY<(H0Za9(p45yi8yo^&fgsiu4f}_tS<7J$B;`H|R1`FTW+37RB@0gtTx_Qnh zA5hJJ>vm)u6 zXUuB+)LHf(DC-kN==Sy&v>F14nBxxLsuw5om6a8BUAD- z8X9bB2osqSJ@v0Tms!hy<$*Gu48y0VC-y$i)zuZQ^xL01NAXbv3mU@0>oGDKjqp1H zrH+s~JUqmv8MnV26)?i9yGp{EKdDMY{p6HvNzhOGEU(S1SPQ3tn z#EnA7z$7dH$pcF<@Ie3=_UiR0AqyHsTJxDxdXzrM=%zfWKJzJ%Y@k}>o&N8^!(v|J zc*1d1a>_f~-15@;`nq_t!HZ|%3p!wdqD27ulamuH8105QXgff-6_HXR5UDJKR#U>` ztHI>^Pbd?tY&#L639U^&-0s?|pN#8RCr(xqOs#Za@;f&qhA;nKBB8n@G72#e*2ZpD z4l8SZ=#<7QpX!q;ITmVTCpl6IG7ka|N|T5BaOPrmAfcxCJdb@|Y4Q^R62as($bRLC z;}i-cV6dI#jsOhq!?|jmM8J+FA|}X|0S3P?t2OFhJ8yZvH+km$ZWgEnWqvOT2&%7z zyi!xy>{>SESp`_iAYhaKz7mwxS8BEjFnpN(0R!;eScz&mal?*LS)!oA72wI++uO)C zDrKCwQt>eGAMN;ZISV?2?2irXXb6-#Od?8$2k!6jo^T zp$&5j1L1p^_3R^b@UJjBaQz4*_`*la^F~ZgmhXw?R=*hy#ffcR+ccDtO+Z=`NDVR9 zX2z8B9weJXlE2P3kJwL?Q^koXNUhL33t1>b;N^7aw1AXx!cD}D$B9jizwG1$*@KsJ z5cVC~Z0$CEzyNG~8DlYiAZy^L>ouRqo>U|zlXmdeupiZf@6|4#>(MRcc%nq%4l+y| zUiZm%esA_SPw%?U|B?*-g;uNawP>fL#3SG8bBOXDOG@^fD{Sx!$x5$ZF0dGu)O8tu Y0k$!pT)iuB4FCWD07*qoM6N<$f^9Lh7ytkO diff --git a/docs/whitepaper/assets/wechat.png b/docs/whitepaper/assets/wechat.png deleted file mode 100644 index 5a60a1bbfa2a2698f1aff6670386c5fa9d710277..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30218 zcmV*dKvKVnP)Z*a$`HR%w z{`R+vFTQwUJ%9@WBU9J@wREZ@m?_4?XnI;)^eyV!FTH zdh2bo%{J4fP3uZQrYXSHtXZ>+yg^1JFb%TmG9!r~BEcu-@4ffl<(FSRip;5e;~Ys` zA)@-ENt5>2V~;*#KG6RlLg|r59{K(6e;+NdzSX}Pi(~?l!9k2dBx_h{CIMvPkV6h3 zKv7F?KkL!EGwdiTdyylu~PCxzhUZlnl9jeUJxuoR8 z6Ld#Xjj8fT1~8uAS}u*0$>>_kDBpC`&0UL#&h59~o<%S{nd}49O+&lxy6bu&&z(EB z7ft%OSFJwzB$bNogOEj3=?ypBkjWb8Gh8*=Q-P_yUe(9;bwUoh4xG%o6r5-^+^g-* z{4KZKa)S*vxcu_VlTMBE>r+mdx$(xEZn`OBWWu6XcieHuamO7;A{a}s{p%U))6WfDO8HOG4hCbQH`1Pw8^YEw|{Ri<*Gw z6+e;5hh|u3&YZdKy6bXymtA(*q_5V0|M!3Y^{;=0|KbFr7tn`Q>RW1CWB8!k_JJeN<-x! zGJX1V17*03q%qWGRvX|6vii*hYl z2F+|DaN<|dW}9vH+0TA9n}~eYwOa4?Jhs~!4KxH zD)Sczc>nv~UyDwviB2N(Y1+=>$cZ7Se|up*jrnHIFpZPoj2SapoBXVJ;e{9G4 zFpGKt@VU>PL{KqdfW^}(H}Xj~iO=ThDxI)hcS~;ISgSAJZy)-h6JHL>;EuDcK8s`eTBG}Uy;yCv)y6}U{$Mc!lb);HaG5ky==l~YYHXbD z2u$&(R`p0;e95JDm|crxc5Sy8^1n2H41Q(mYwx(f;865^&D`9{e#COEw9-n#2Yj!(=UbRcEV6G$q2&yRon<08M2)7e`&CYx`;sGEa8!)QGyHJp?KAaGoVtFOMA z{f0(9h@)8)1pC>~epVZiPTrE#$}6w@z3+Vw5zaNcmVP~iKDCqzf(G1Ma-!VjoUiBoo1cJ~v zzxmDB1Vs{O$sEjpNip|Au;11u(5yM7p*iHVXa-LHnj5>AOae?l%|U?9IOB}Ww}uk# z1PBeEv@_qh)C@!DlguJ$**g>SwXc2cr7wMHJ;Y9IcG+c@op;{ZPKuMB6>YFT`N>aq z`Zow#3F2?TVc=)2$jslI)oVOLxi^$`LqxNh|+!n)Vmpe`K!+7>S~OT8?J(Qvp?&l&5`RcZ$396Pc8Et(p2@wu*YHqr@{$`d>d;M1LgQ2T<3#uMui$;JOIhh-z;?F_1-5 zk|rI#`|i6h1d)t_wCc9l>*TP;Z!OchNVG7RM1i)*m7O@zQ~HK}>eWiGd_*+ufzXLV zTeM7DHrm3+m?ukH1Uo4w<``Os@J7HbDzH9jXyl|16%DkSsgt!<5H_eKqb7*vKmYm9 z?|%2Y0&6?%w9{MO@)qVYd949kcm5M6Mzn*=DGXSbnhZsv!(xCOkzOKhE)P5Gu%nJT zD%?iCREnd8Xh72r8U+59(Lgg?^6Xt7)nzv)#`vA@d`H}pQF!GmUs*FLrYz26AE2#} zp`=-(wP5|t97E^H!Q|BAE#f++23!-Y;iLdCr?uCpRuWViQM4LA;qDWY#r8*7!4q=Y z4w1~#oRVxT0mwC6@36vOu1k}kh7LXSP|~B+jG8>s)2q+VA9}KG0($$gk9~~eiHMmq zi2Luqf0ot&$~z7{b!LCqG&`0*>#VcPSzz`O?kMG`9e()Xoiqs(zlSSb7v-4LnJqZ4 zRkZRY`B*t4)&RLrg7tK?Dw@+;Kh-cyn~WBICdW2dP&KT9tkVLNdRm#7?#yiAbS62} zcG1ycb0eCCa3?MQ=&U#CS*lseHCE=L$*yY03M;z3~{I8@QL*?wvvcnF=h z5EY;HDm?`vS~5oYbZwh_Kv0x|0*I$8e*a8Ms+M}nc_C)qYO6JYcu5-8{;iL*v}Fhw zENXI`brVfIY~f_CwLeIL|M$Qc28&ok4@m>&LQ0a$RNC?bA$|k17NB~V!m=i2QUf>} zvZu9^hZ8i#jrQ4RA8OzBq?W3>RttuVh^>1NF|}fJuXx2P?2VoBq)KnqlGGxL$rWQ> zDeBsJRLWhW&;Id`e+ZUH*8DSJZ+zn$r%#{GIpq(fO|khR#3{#QPU|8)_ERnZB?Cz+ zhgVL*i3Y&co8I)MI;V#9G-m{mFq~cl>*@j5wdB-pPz!ks(J|#Qg;TV^^@9)G|MOq`(s__08;@Be4V;7VNDr;!S{=94>A|ml^(&JdMA%$J zh*8dEYb?wt*PH0DN(UTpKz;X*+s=O?I>BvrJSgzWwHS_I-Rl;zVSyvlsG@*RHvrus zk(ostH5Wg^xlH!R;;UZyZ>z1ohTt^;&HNS+lNFgY+(K(5gP+U{o-^5+tjq_DAv&h2 zo~_o9DbiA8Mw2lF*+67Ms3S`z212sfq6t$#7Q(jMZU1lo_HVH@(}Car{`dA==01t{ z0SE^l8iFd$nIqnfH+SBI@9fDt>rw{C9CJ*ZRWWeKAAh{MdGCkUm2wkxTl`CgKq&1j z%I5HpFb=JgdU&H~opsjv$VWbsXvRkuh;rui0;sgql*lFwKUwOmi++t+!;oXLI%~-p z!`FeKRgVTdEfSVX?nmZDhnx?wC_NyzY@njk+`leHE)ZJnGZF68H!R+jKXx2F7xE9m8s0HJsZmw0@ zCpot0L}dflId;x932Ej7QoKTp)CEu^F#9mkt0*q9C;eV%ee#(+&PR>lGOvwsof9yl zfXU=vqf}HxT%1a#7ZleM~*c4oroy5(j57Q(=U(Eyzy65y<`br#mD(wP*Bq3g6|6&~*cX|a{xDm!(ExHasqQ&LvKx%B7l4c*t zV676ZX>_a*b21hlgInLU1tR2|G7qlYGIQh3u)0Xyq=dDS zh$xpk6-Gd(Qn3@S)asg$6jRYCD_MJZ!JCSRSQ2k|!yCr0OPsUf#3ew!5i^%fXMY2* zA9>Y>u$X8rGb&>_eX&?iiw@)r>4@SkFDlv5lh51^<9v z2}_^7!U0}!DJQ2VDjGY0qDams97%czFm2ERvq9^ynDe6#r`R1w!B<^%RaC^V(c!q5 z^8fwc|0U?WTCq4UvN+$ye-g3yTs0I+G~8l|G)-RFF%x3eTyLuxS)EF@?VAiyBo)P) zF^d9JE@l{Tw`C3;r3$b(~lh5?| z&wpMV9Ji(;ix4D9))LN5O$N}TR?c7~TXR=8H-_j8iAvj{sq2I77+X30li7#Q}!yF7>_qmech%WA}E4a$6Ky zl2lh5RUvh5!U)BaIXNYn^REMVDoI?s*IjpgCi?)iMQv4Um};ymT6}a&os+QFDr)^o zrH@}vB$3uw&6zvb|5@4#xZ#EyYo1$Z<6n5KicfoT46ReQM}~}rWok*qpis_~WaOI$ z$f>%S{3wzMIn;PiYhBf-n+TZ0!L;Wa5sC2oGtO9N-F00Y^V&mLy(|LI>S|FrM<0E3 zoljhxr^ZUP{jQ5t`PR3-#bdKHTX*$!s>W<373qatnB6ft$#5Z(H3*gmV760dd z{zr>cf|n(1Zj&*N1wY0S7#vJ$dW$VKUu?0(O@`a)E>iI{AzRHz2{*epLphmX@2PkP zz&JVv^%8M9ys;9JNzBxm;17TJ0}qslqvPzIC?qEiCA{%Nnd!1B))Idl&sSdg_dD)r zUZr*Ui?7Xwx;KK)sK^p|3&Ng`e~o{cR*08F+@wnj8<;IOHroXd%@2Iw1Hm&Q9<67s zoHaR`OBV-0Rnjm;3@pjk2lbg5z!;*VZ<;sU!4M#VA33I|L}`uFY9s4Le%E9a*%MI% zdGipaX^89JBKL$tEA*MoDjBkZL-&|wwdy7A`i`g?=8fjt-u5<2IVav;kN2vgE&4m& z@eVVs2!gn?*~+V;5VWqjV2nuR(9<_x{pwfa&M)cVx4PgF){TUH`O9A>k=aus5?4p~ zx#rcJS=I#0#aVZgGiKq%XF=p-k}T>S6R9m75giDEescw8P6EcER}i7@OW^BrR_p_$ za_Ynx!`HENJe>_Ep_G`+f$Wit-^}j?mBh**b2WX3 z+p(Z$%$SjiBoL^a5IFjbKFC_usJEOl*>adNA3z-IrD-ddr6w;oWsylihRiXDb@+sK ztUoj0=6uSHid0~@R(t~tC;d*K9=*=e%&CViGsgq;*_@9dI`#|kc8IovOF+VP+jZtR z`=h#Abx>jYT5Bz~*yw#iQ=5vE1SF})?RRr5(>1$$P%&3Rn} zIb_0Wah}zy7dWXsXfo%+13?Et$(m-$G=Ym#jw~f};aKpQT1B>ai6$VPa0?(ox~Du1H_d6h(1PGMo~|%7PZR|VSu)@#@+;G?H?7|K*0-is zqzNWYoMdA~^G}~X-Ae-LPLd&_!xrE~NbMsZ`EbOVgR(VkLvG?@zMWR`av*z&lR&`9 zN0MN{bOVdEO8LMKYa(!B7QM+pbZRwV{V;-|KPV*8LL3H775QPvdc)?2Kl~xF%eDXl zj6?({T=m*Us1?o@R^1g$Lql0QW%CL^3=|4J+)*1WoaB{Aax>&bU8&K)k5TojV#0vd zqco;Keho)5kWqH65i@D2Vb;&6Ij?hDFzp&6f~c|1UuZG(bq?5|`)v{Fnq)iDl?w!Q zxr+0id=l%6c6?m`CyatBVRUMmRxkx)l(|H;xZuQjD!1CqIT+_P*WzMT9enV?CX8=k zl9FKXpO{2kv=B=W$N_3N31paw)~eM?CUHPrE0UbBcfRwTu29k?scRJp3KHS|%!eK_GidUo4wH~OC& zo19oQ{8NjS8nX|#AYY57lea|;dI z%XY1swk%3(h1wPW|19(WZ=z${MZ?#_=kOs#$7`1^>*PA-uhkmbe?ip5>ysb;$cLv)X~$}_ z31iCD)eurV56Z@`=0c^j)3#k4J<;1*qu}JHKmDm!8u-ZEra<-^a>I*K5e`zFk_0U< z<2Ml`9fWZ>2o|Z5OePa2aws{DKYu*w*T``AI&vapC+OgjDQ9Q{F;V1#luM%H#-O8q zZ;ZDnWYaZ(4adDEOV`+Cr?9$bt}PUJF$lk|}?pbm{| ziLA#lV8`P^f*Bk_!So9)I$I!r?|a|-#HN#Gi+(GKj!P7fZOtNX8BIU~BoX}h=BAj9 z`TN2bzF?cy$yH|#B3=cIdxNGQg>;HVC~P5HM<|^XbPaA%2N^@QjZUhQ6NJZmy@h} z*lMy)!bBuu_7mYH1vamDoTAk-np8eh1p9#}J* zb6TSXJg&`oXSK))yPLz2`wmS~LU6JuU`g{Dq9zAm!|aqNsQGo$`ERdy#c{_Uue#py zpX&L8&&mksi5WV84B`j^2(F=lU_rY|*BTlINGE(K}aXFpV<#NwTwgKs5*qAZy5!X zVZI?4K3_X;S(dlG{q5U4|M|9{CNDq9g975511FcJAFMiyW3nv^)X*dlhLxfsju^;J z(gcpgDfW=9;28z2Lo=gZ(W33BoSGA`SHQTFylI~iA$i%mq?~|A5*HzpHNb!3ma>B) zezkt>Lrrx(a;`4mCMJF*5=CYm*G zI7!SF(6gY0*ELBXG?Oi*29^`rB8qThIxWpwg>)qtnO(nyqhqcmgfa^>-_PT z?OJL`Ypp|k@4fGVu9)M`Bs8IK#$P2cpOWa5|6|i(SwkZ(BM`%5@2W1-0i| zQ05Y!+_)2y1VbOp==;||)HTXfbS-d6FaS1Q}%$K@xtbi5xL^> z%NxJ^-g_w9k%0b;|R;e?=B0WA0p$eP5<{GO{pRx9V z2Obz3>A-aK>3ZQMm;ANf%(HIs9+t^iZPis59l6edj>n%3;346MKVj@F1Mk+vN@%q% z>AF^Z5vS%8?7E@enX=$JcS=9_AJch4hCiqZhB^(7Gfpz$t{PFvkWS3xXz3n#da+{~PfrU{G z1h3hW)o)uQ*|jv#T1BlS;d5#5Ia_W~2HMKiU>`4LR$0^MMEI?~y1CqV$$tyLq*!PfoOk^VH+=T9pToS!yT_d&QpI%(>Br1xKleEU z9&?>gvtq*deVUOKi zr+SZVE8|SQKu6D80?|6^{# zMEA%9b^{aV#yz&yb=`z(WtN!<&`C?#`Y*GLdp5l~ZZ+5R5!7f>0N98vv&^!+s@Irs z@W1xj>*SX`m7->*;^0EkLZwSuO#~5~*r*4bzep}JZBcvp@x-R1))=DG>Is)Buf1if z0Z^FrQ4ywFbzArgk(_nwZCz{4y7kspaIZ!a!)@I$jZz%emsus*#IEuuEY!zg((7EB z8cLO1^AIpcFmHQVfi2T89+#^{vlU9F#&XPcq}NeAB6S#|rfGg_l~WgW!ebaL6+#Gt zC$J+lnbgem>C@A4%ON_BoSZ7>0*#8MWm{i;2Izla<90&<|(}0nx*>EWBNXQXHgoqTG4C~mPWiwr4)^Kp1 zzZ&gYDwA1pB*aqSSx2%8K&h)_@v0$McbG^W5fc+>>exd{t){rkWFdl)ILMn1sa z*lHH4nNe+Xc%4FLCfHq1SLwQrU{Fw<=^=S6V7+uyF0j#6Z;4&@r!8Z5@3Mf~{W-IqfHl!HHJv zAe>o36Hwq|B5U}9pX3%`MqT2jSz-R@sH2Yf#y5;fAjEGp1UBUX2ZzQz&L8-*Uic!- zfv+^sTEB#^&LN|2zFJFMDfzS!bye^6xR^dmP^KbC{lF zJF9d8(R$?5F1a-!Sgc-+AIiJVSx}fR>?Jq-NsS>oD#!4}h$O8@(km^~7zj%HM^Txx zAZt_5GFTQtn38NOcyIxz&S}AvZ7=`5#x#Gid}U&iv}JI}!tKQ~O!_7(iY)ivt7nVQ zLLBArOtp?wmW~r3rn&UPPpB)}wY3ygT{<3^K@VFt9^@Kl41+};)2_F=ElK5YclgU* zwBsY^+bzUGfBe=}YM6%PbMOGnHzIWrpT^}kUWIujnpP_FXYWI#YBYVQlQ3CjM?dzK zmZ_!<2X~ksL))hZKn-~DnXhW?8Zve>i`Xfht!YLRzvO_cFb|?noV)~72FC+--3j+WU1s?IS=vIblfxv2{>kc6R(AXb zP@{p(w2$IiF^1BM;$}S%5;*`1l%;DqWTulHX$eZSm95}}hwCkLn6=yl=QaPqbN(8x znn=rUBTNh*507TeDgl^yeW6|6^X_*Ak;vB(y{M6KF0gJ5)O#QE?NUl^IBI;bJs_JN znQ&SmZ_U{UFvOw*t&m`g|C;O=qLTxm4!EvqfFc?BlFUlvfV=uYb@itX=W;h6o?Zl5 zx{%{u2$7FMttlz9@M=42LCdCluk$<78$pU<}bwjbx;7)KoG*aQylLNF11p6ZB%Prtnl?Ytb!wTaSky zdeAkibSXM%vQ3WR#`GnH0iA$GPyO0?<>shGQxHX1GBGK?K6BQpn@MM`X)Qt~aflfG!I>MSqUSg@y$IuYX$V&*!`m@%XNW7W7~ zID$!V?Ivd{0WgAG7K|A*_KP<*+O?5gZD7jB5+_EFbkM62x#4QjG*h+DUY8n>Od<%) zYY$$7H(B_Mrg7U@y^lvfhUgf+)T_~emM{SZ1RTG?+0d+wUdD?e$gDUbS10q|a=aJYrL2{01q0btp=W0ZxzkR32M(gK`j0V!Nd4F@@e&fD1{kSY z4(g&7%mH%uw3R7|D>9KPuw?{W_|}p`l2&FzWQb1Y>#|2rJ+|U>o{eFa)_|F+Eoog; zuNKr4`86iBM_l74yzp+au?Q*&L^7Js23n<^RZME9+(2_9n88ju08<;wo%vU*)liLD z!-#as4FvImjI0E{sBvBK>4kAiPe1K6Yl4n$>f|`#aSr1+sRh~?S|^Z5hPFdK;y04P zP+eNLU9&6pPaj%^H3HZsT#@Ax%fgbisYx6m=?tW1W&qJ>W?DT|OV=ebW5$d+0$cBv zv-;Bo2z5RUqBAgH1C<-17H{biwetHXx%?Coz11IWflAwR*{W z-(pO=TFgvIG&5NPnyag~rdC{v6(H86R#9$qz-pztL%zu+0o8FwB8e6aF@?^31-For zlg$|f-A`t8gnJb4$RVXs)P$p)j~baANd&}`e9#%$a0FFMA~nIx3;@sdnAD}hfZFxu zUW97vqW*C0iMBAu5FOL6OEDJF0bUC;Z+Bq%>YL6h^@NDfA7E`LGQN6ZA$n26FOS%x zC=gJy6uf4;)>^BVhp#VB-c}|I$wzhk=g*K#8$AhbaW1wxe~#D(TQM-PEH=GN82xGl zHtL}#B3aGK=GTj-K}fEmv@;n*V zA&b?rYtfl6NewMAwY=`gveM}LE7fXlaO@T4Op;+-t8r2j)Fm{`!@2&E4g( zC(HeFyZ?XR-10#6e=juo56vw%JyI?@qReehPR4xtDE~fnjR_^12zJg11BOib#B%2M z%lF<^W?h~|YV}#cgs-bI!tO{Txh(Yv*#38PS+q-r z(kav-Kxw?XBDXRP)|@#$0)3Z{lC+8#JNL|+v*??@Rn9o2%o{9=tyVU8NtrlmXhy3% zc3-*tN5jc^6Uy2zDl4orTAI+jIpv?fFZW+v&Of)T|C6%z+bl_ieJ0F>Kws)u2m!k2 zq6`0d%{7ZJv4l8pYs)t5hTr;^a`g#=JMW*0)Bt*t*-qfsC!f6QZo9?#e5_c)M5K68 zHL{{iuC($h_UfrPb;OrY#TSG(wWZ_c3;v>u@*+lcgq2L|2&l5BNvbP=8IE1oBAH`| z4qck70TZ~XS?@(uKFr_#_Ba0f$5mH_qiWYcnbXN=iuiduxXih&T=?Dc5D#TidBOY3 zF7N8Rvfeat+TrEWA2ps$GidY5V#}3Re5p(vby*sm<{2!1KDwOr_VVB(<&XbUR@tj8 zx|UpyVLfNH-{1h*LApcZ7-c=p{TC*UJL|y2*q~*oW~d?GzrEqjZ+VO5tJDP4^eN`R zY5i)#Q)9LeTpv5;*kgr5waek<^>g8!=isEqtT|x;9HSBfXoL(tx5<4!ZU7>>gNWbh z)7LuaptojlM3IXCCW7xJAj#pwST=z}gCN*pvV>22h1B79?`INX>cTH0F^Fo_lcjwC z*Z)5Exz9(pRTTd6xt)6B-3Y-A-z$F`Qt2ygRs6uKe@cW#dE3z~s0}mdGg_axf+W z>B-Vgz_2=y7kedhU_COgo`9`OvXaY*LsR=JH8uMU%iVaQ5QABl;>0+sPKA(H$)Jgv zxu;G-Kvg%Abw$35(6$`P$+0}?ame7Qak$%e-F3GE`OHK|xYfhE_rV@}!z|LegIHHu zTmE<=Brt~PZR#d&AaQgNAA09toECepe;;rQcU{NlZqT6!6RXd3j_ zWUGsK%Z*KfRM@-T^)8nmPX5)ees|hwNM(__zOnkMSG{tHC6=To5X_>Go4Ai`rg_aR z(Me1nx)V|-I+>FI_6U}^07a6S0oVyLNn{I7_(wtXimA}zsp~*Zt70ot!!aK)XfjL_AljcKWr|BZ2F2aeai;td2cSi{b;%N z^m55>%X42IO*?XO_H^8F$8WRE^H*7a`?C3~$_3vn*WOt!{#@DqC~qLx=%zz3+?PA9 z9lZDYn)7Dvms+)~yg_(KP0>Sl58ixvnb*kNawDh%ORZ35ZnDbCD=%mD-};Zidz&t# z=l} z!oy8>{6kV5`T4wSM@f0^bGIU|X~(HCgV~AJnKQQNI2m>lWbREo7p%3zVq)DnvNR2! z$C|V99HH~}H5O|TASB3O2~4fO{{#|*ujCpO)d!+pO;DIMc z3(K@+%ASW!+xATd9{6VQmGjTPAR4y`_dSGi*~#T62TpkK?nY=Z5Ncp>N_p#vOV8Z> zfCCShJTO>(`(Fd6e|BJS?yz9VS!{*Dmw$b5i+#;~ZHu#80hkD{cys$4@2s=V+FmzI zgf-V(%eOcL4p87E3EGX*CmBO@G$2&PS90jjX<&3lr?wPM219Gk>c&_!bF5;@4LIb9 zP5t`UzqZ6;lgpLgF4x`NaKHJ>%R0}!>&`nJ2(!?FC2qvpLnN?GeU!?+U`DO(*>R$hNN`PlvC;-easIq%77JH377 zl}BS7%_@KLiSp}18wY34PnSiP^#=#N+&olqVp((3iIXM^-j_fBxN-lNUUhJ@*OtkP zG{Mg&9vryf2Lr$SK$*7mvK#H@?y0yR`G^)dVLR=(CB?eR=tp z$`pU%bYAEdJUlsXaCl57OdZ_n6$9&RJKTyG%qla>k6%+}T~Y?0tgq1X)d)>_@TRiD z#%1>pmPzwPD9E}KmVv9zF27W?NO{E(#R!C^LvzX1%4vs`lMWtS@gy>VREmxZxQ85i zh<%RtmRuo^m1B(=2N!^x3uX67PummCvfjYBwoARLhXY}}Jb@EHt#7ifvx~;oGC=44 zXPI?xv!B}fjb+sh@44r0UqNuvNuzKBhkdDYzFY3Sv^+Vv?D@%o#g?U(czMDVS6p#< zS!Btw<9o`)Wy(W0m2X6z)Z$jVkg9!ofqwK1Oil8NPe@w^PcT2M2dOgxuVF z-~Ipd)vtcf%TxC4+rO!-w@10_vVm*QjU8N)wKa)%hb`Lr9y^5bA4DXzPGD@U(^)5S zY*{1JsE=|8O#o2}PI;1J)_HkNSoy|pmB0M4S;tFlTAqJ^30rpA<*3;}X8828+J`4=+EeTzpK~`c>1`+UmXUeUFPu(e$vrV+t=g zzT9|fx$^pQ{Wk`l{e}JC^d@?njK2ESL+1S4AC*6Rr|=twpTY9jtTJhM4KzZdTeB`J zH@T!SyucjYYJPw7o8SKRuftz|(rX7d!}Ny!(J$I`R5Z#(mRNqs*Wn0GVef{&Mm_r>pVb>&WrHVX&v7%!(F9#9G|+r9Z0R+87p_d0 zILUeAFk{V8R~>X{F+lZ_NLp%yg@yTdfklU#>2pT3AKRIG1TBZ$VA1sF&NGF{Wtv9t zXU}T$PjFxw&cJ3@zbHdYAm7{OWyW&g?RE*-`14 z`|v1zBKy~$l=Ht;E;xEP6QiqcUS4&0S!KQv=iO&FVb%*q()J?Wf^eg4`Y@rPYj&=zJc%WLqvu&-@Gzy@v_5vC+_&xGI4ZQYx`~RRb+Z>+V|UU-)0>S zJp`G~G6m$@Tjg#(WlOb3A(P=2DX=rAneZT>8Co z>5+}S7#W=k-#U{TEZ6_8Tz__zUxUWUY`3cZea5#Jmx%Fe)ZvIq5s=A z%es7#p`mAU&poo7_UYmJ%TF(_{!Wwg#E?5bZI$xC&E@J-%J*JZ-g|o8Mr#mEYF%oA z**NoUGKfU|OrJjeu)_}H^fZSL%-OcDZ+xbk|J(#iB}I5Gt>1mTEV)W~-ssl_%x^^MCbMjRK}58hdhxW3$RZNX&qY_jppxXd4U4gGOE zn{2!>H&!qraR(+ZGPvVg%HUgub8OFl|FwZr-dCOw8H(lep5Ww&<^>22-M3eAkRANz|7 zjw`?UNEv**Z1;|`!`tRVyXfb|xDP&7rcNmPexR)MGS%IrArleh6AmhKpBR|B`0&y6 zZC8~`P6%H|2N#_-^yTkr;WnpcgTwCBz-;n5IB<_^MsxQ+;J{bC`ZdYhu&0&j9ss$a zjRzmOw=6pP8L#G$vhJv@Rwmclx}1OHz;8ZTR+wJa+9Ieny5!=YmA@TRmRx;sxf%9> z{P`XYE@XDS6Ks)KFwxOr=X2LxcU`S)5>7D!(9e+{?Xhu(AO1C$-xgi<4dvwzl%qaY z9(t_&^+#pK*5x^`GKdY@qxYA~eo_W!m!;P$JH5RuH5~b1jHgU$R+4y8x`ANPjm_qoE9JV@8$XbQKk$@w(!!KUn-A1IJocU%evb<>iXp()22@CqII%g3ktNHq`LZo ziH+@+10q*Dh z`@nPd;RA^Rl)XRS)V=t~@{|3C^((d=)bIAmfo)#@$YYNmcl-(7E=q^D>DS29$5xD> z4FB86G$T0jq9m*#AmcRYDT=avo<;%))YnEf*RqnpDiO_7dVcGJ(%cP~E%6z}8 z%^ZBk?+5;V+TeuAL*`IKe;Imi;HJNpwTD85E3Q{w{jH%v9Fhz_oTur}8CY|3%-BLM zK4YuF15X;b<+4FmCLh*()eW1}^InV2;PPuT@uMGBn*3zh@4uS!|Hd#)7})lWgEMy@ z5P}NtWUH4AuC;Me0t`%@CN?o|;?z@qeTr@Oi(a(n;LE>I*4=*a$=NYJjYuuI(!hqh z2sC+D$%d=f-?Oz`lOB}N4-u;@fxr0EZ*xQ**DB06qpN2w-5 zq!QV=ZZhFRwTmpWeA(`Y<>8l?bIvc1+*E$?fwJuS<*}=XU)lQ;1Jjm_iV*+}xbs&4 z`e#4?`Tnl1Zu_=!^=akt+sYY-JMt*A&S{Wmu2%LuqAamC1!?QoxfTajSi8L7twv}_ zG@2SsOku69#9;;>e{^8V;*++0Q;c9!Ry}m5XzbhH_O@l#*lb|UE#P!9N$bC$tp9?f zJY0K;70UJpj#8R9X<*q#xq2Rc_@SvYo7R^5-v?D~^u3WyZ2)-*1#9w-<%>YJnI=bNJQo@$HiH{B?U~h1YDLJ#Jxl zoeY9V9N+N9H`1&&1g`pa{V0FG*5)sBc;}B*5e|>hvuDPz&}Cp5tB4A^1T74!MRr_f zFzLYDigozV$0-pdaqT4A>@%c^Gag`U(ZLfraPVP&Z~JY$l5QM2N|F-4Vzo|2rca;l zgDIpZ^8tCV0u~;0Gt1s`g%vh0`+T`P@{V%j?akUBaKiAeGI`q7S6%g+-~N_I#d!+K zYIQ!=C1>kTe>%7MsNzoVD3_j89=pErR90BB?E9&*?2GW=5BfRz^1gwq7q-nt&4>$5 zZoO3#E*r3En&;ef-mF=-3b7dCgFpCzb=RJu=-TUV=+SiZ<(~ij->=?r+pTAub&deU z@TZVPiMs8IJK65cVbnhIkq@u1{PMyC6qxWwd}}P`Sfs-~@ ze&LH>io4RpNbeHUPQ@6qVwAU=3%Y|i-;3}?#4j*Sq9PAN?2%c^R&70!asXq94!Lpe z=u1j?Lebqn)1a%vmHB8Ra-(f9F7s0~~)|=6&Uk2aQ9y z?mRnB%lg`D|JnKF^9Fz9AvgB_UZLH{_x-qaxBRWl8}e|cO(`#WLs{j(*-y;zrcSs@ z4on=ZMpXjjgmu6s>-q}|b#=#81B)%c(kiPuAT*#eXKuXc12>SrMP|;doW+q={riuz z%UYW+{oqYYKWoGFpS{sYfpFr{WxF>HC!d^CE?N<$6BSJXzaG7~; zo=HD134M#49SZMu>Av$!auNx&Tw^`kNm7U{PX5Yhyvu)ePG`S|brkdPj+f6nm z+~LlgY}>YN`_6X#`mXi-1J8MN)_Hr*+Gp?m`CQi?c~Vd)!%=(gFPMbyDZQ2ow*0qT z+4Tf+8uwevNmNClAFJ$GKJ@Z=GyZtxQNvZUQi&6DS+`LJ3v z{#L(tZVcd!u%mo&owMpViMH4DX;?_3uMfzsQN!Hey(|K{`yDCr+h~xq){S>g1(Tmt z1ccV^=a&rRsCbIIuj?l17kMlgK68!cp(bqkI{$(68%sTCCAYH;ar5-yy=QE#JEnuG1WTX`fM=>0o>UqO;Hj#6xQgoy&hjZP{W zh{&PKzHnL5{_1b-5%WRvP$DmC0_K)#lD6YOL-r|5jK*GTr*N6F;^S2`(94dlOQ2Z* z#AYM9;+S0foD4(Da{nKid`wCz7CB!Y7^0uvRl{?19U%Ns-2Sv(=+b~Z=6b{(Po?5? z<~5cv6cOnsSE)>+Kv;Q7WB|nF%K7(|_EZTtS!^-CUP}d%x{K@y>jpX zi?}|Owp!2LDk*l|Ki^H0AHS*jy)Fz!>)5wBtr{IjTvEpcEoJZb3-k~9e!-lS3It4D(R^+QIHtTRL< zLe@Igo)2fVg-?-#gy-6m!kuRy7dNC`bf}v%>!F*sf(N92Ol#k~@awp`rMZTP#impk zliI478LQTyVwos%0#aFR5K>|ee-1RH^QY&w#3aMou~xcIcr*(P1Jjq~{Z8?A&X*DflI&1)NeNrK@274F)SAW#4sx?m+n<88GuVbm z6|&fxhcOO%vlBNqueFYCSwY#qdZ;QHf=l@lfEB&i1~q|Dqt(4X}hQ#*7o?XyiDMZasd|Qw9E@` zdRdbsn%egs*1Sz;XAGRMqa<`Du6r|v#*mW}1UH97vU)Z4HY3W>!u>qGtix`S_tFq= zowMltgd1!+HB^%kRt&;8+)Z{heBGX3FUN3R8R-4^8yusn_`cfpwy=sH-Ybus2k=Zj z1!wm;G_5}O&=Y@01#uHEHx_h3={(tuD88Y7ORMGO>~$F(CM#B5JI45cz5Nn9B2>Gt zNGcoPGWL&MrjobLv#l#{-Pu{o=~;AR(^*Vh8us4kA`db~&}B25^<&-~W$v*Wb@Oj3 zyK(3mt`C)gkfN-|N8=hV$o$lj>=o759FZLO^|NWufCQSSS=$;?B#tUM`6s0N*GZeh z#nQqpHnjgezc6-Iwq0UP^xD*{Y;Do~yuAS)j9P!bLi1l7e^PNEX!e^EE3>?rIS&dM zhtyu;jv=tBef1~h;wO_DCL0fhPTGBXwDiYG=P^&XNZm6>eRWfy| zv|Ldo7mdbUGARkDxcNF$T5;J4-=LYVz%}Jjho{WSnA(5z@5lsMo!6UVvRLlqlrtoG&Fr8TZY9J6XPI znj@qg_O18tIoPRA=rU0Bw&~s zVmRby_$@qj>mkc7KXI|^D}eSvLlronG~tz@i_iOp_Qo*kAxn1c1>Ts~__fJ+ILBC3 z+qb=`kH_;ue6aYM=1#8oyYB3MXXh)#B-DSDQsOU164J)e&p-1u&^kDXCct~C?i`!X zh5xPdxpt83#c8G`wd?Td>}`Ef2xsN%;{diL_*bU-?~ z7sJ)<)0Bj$Xo5~qbQI^6Hq3##WSpg*qI}U@SpHD%bh|Yw*pzS|3L!m@lzR0UJTg)7 zb1Fe5ddX(ZG)Gyn{rAYqqbfNhovyRq%Jy^6sf}QB@9NjL!{abp1Vf{Um*IKwCr#prj}Udjk}Jw| z=n$?-aDxZYRhXBB4w*nW-ImU1d@fD;jU?)8={cJ7f-nz0!oC8zuen*C&FvssBsyQv z0Z2FjD69=b%Fwv`+F4NkIK#n4U|Tx|r%cjA`o4q>q2cyl%ezPIJJB{`RkK|lIZ5Zx z`_-TpxP6Pcv(SMVsC)g;rvJtFuCtf9z^RaF)5fEDFp^a;d#`rBG>BXOd-dk`gW0*! zKKDds{n_HAF+ZJ)_T1|~7wy$V9$+Cee~i8S3QH7M^{xg7vpXK%4iC||SDeqYVT614p6Wjio^rWB$ZZg_(J98V5LFgM(FV^S^&7s@w| zuv7{6lBSGyRyAd9z9VLTX%5Q6Gk?MxwdwUb$<%-MwR0NA)kbzZ;S)u30NY+)4&r}} zOTCi7I!E2Q&2m@Ldhf1%ygxXu;tq=w_OjQqIj9|podvvnpQ3GV6YvysM)Y|U932-U zidaa9iaXAU2Duh9*I^tGh_*Dn?woF4IWXP%+dJB&a_L5p)q|i%1R|%s#cpkevY5 zTxo3kHLvrszl64TCAG{{BHRx<`((oIZDGvkae;7vhB1D!OaoSs|d zW@}8F&J(-`5x_A8+~nwzf&xN`ftJuOnz`epUWRM|J4hVo`b zv06*h>bLi(+F3s2+k48amcwz5Q_|=(k1_YL=;Q>>F2Uvv!cg5Bbon$UQtlnyB*aMk zRHmnCfNR|Z_v36h3*!6I19=$?+4|)r{;FhLN=CDxEah%^_#9!?#@!3k;Bsydl!7W_ zdK#)u=SQ26xf<0HKja8SVEi>KRGjNu)=^=j&37r}cX+v^iY`?WFA3fSx4Z0vl%P=^ zfIU{${n?0!mhfM*GDDvY^+c>PHb%tLDo6hUvY+C`VZ$qmq5+KQ`krv!(a9 zrDR~2G$`$8CTvs;U;rDEzBemP$#`wq)0M4t(OR{`~{9M(w?vznc@GiL!+EX2_%&c* z#yw1SlC%$BZp~cQ0c_; zu>vcL#yCS$mJYyEPRpahX~1zJ$?8Scw5lqhpz(YZMuAX_sNl=5CB5U;^J|5SHgsM7 z_d1S2De~BZJzb;pwarJoS(id)d6SryujI-prGir;GGPc*_)rBB|3gV6GE2)%_bg-b z#-?RL8BPn=Eld%UEGoCk(^<~X9geaD;s^W9)UEULARx|HY8|uXwsut2v3~=YBG6j4 zcnqM{z*~O>ny%ysFYh^Rk8i*Z#GUu%N*Lxeq>DA}40W9N2q|wl+fKvbv)U5H;7OhK zvG_2+hukr|Cr6^Jd3+TE8q&;Dm{58o{T?bjY_0a$VNt?-zRI@${w^`sT6zqij%6$* z`fch}3K!^3buWjos6V`$Xjxw7^h-~G^aG@>qy99lN2%Bc!YQ-B_>9tb=~;~wq(pr= zO5A58aGklW0v!~E#BSK#4Q9`f-3Yz&pSPVd8lJHOu*iCx_qZaVP`EC4hnTrHhCSeC zdWdN^wvhd<0$`tQ3GHjIDW+DMlx51ktvW6;H@)qZ`mOuE5)WlN1TF>9*w*g^2gn3* zZyZk>facql0jY8oe2yv>Y^1QMaq?V`7`&5|Q~q^;`&QO;^n|QW70%p{{36=HH|WKk zH~hR3Wm3~`Rjm7zi!k#!UEBrHUOusQaDOEB6QUimjC#W%Xh#f1`Nl-n*w9gIR@&m2 zWgw$zf*=Coe{!WB5NmxAbeP;g9iH=wt%nr0ZkYh<%M7QFZGcN=VjK z1H4d7<(xI>uN>bhp(wueX_^1kz1PNMVQ$_t@;AyOVS1*HOM#z>>sQH>2qj^H|ECpK zC?ZKawcHm^D|>n|Uwsml4_ zXuQ|RrsMZ6+2vsm@ZKs48Hx6E;vSVM9c>hGRDhk<8cSnanx1{ix^S9tdM}~`r*JSaOFf0dm?VAp-68c`k%|Edk<2Q znC#`83DqElLkr;6Ld542c54bpbWkTgtAM$C7tQ!b@YYYi>iDYd$sLO-8Wzv3_n54Y z*K88M-oJ(Y{1tu4EZX~$@!y2|h92r5?l^08K~@1883D^L=c*2-@t8KyQCdka37NT66h zR(@^kZ$luGBSC3Vw`ap@O)Ux*dda`_vB*C30VS02l$fd~9lb>nFR;V|j`*v!m25r~ zYavn5|H5BwKi0FSSe4NP)1euc2|CX{27lABEa%7J*b#p+%=*36;J1)}xWLeX@6?Ix zLLO!ptqzwfjS|ol1{T+deKRZXl~6ot;a%p*l_<^$$mnv&lhWcGDr-mn!EMpYVOly zA~nP_4!dI5cn3k?#imqH>1SE(<3l+u>D%L;0O;+}M`(&=CQCB&KsGgU5?q-EOs8h( zM}^6<(ivb((uk~_Jy07#g(8YN;N%00vBdf|%{l3@c9V|fT?X--4xocrP?^i zM-~#6zSAW89@nC^uiW1Y-DD>Cfu6i@jx-_&2OFG&lYUMlU?WIg%&-X?3NlAB67;-Q zRE#sBuA?RBAEho{i#h@QUDH)AkWY6elC`z?uSS$OQ>_f8;*{6chJI|`$Y}&q+1TUv z*habgBv?R?>B%z`1m_2djU7G+1g-<{)*%6d2e7(HbQVl?xgiXn8#G4!GT(4Kbg*w( z4u5<(H5CbiE#%kz(O8RW>a>l?i3LU*69xv@C#TrBDXpkJ`5$a$M`<6=P0`O*Iu@9oFTLr zKUu+fDNUZ%;eA?+De70%&%=s3JM@nTHkf2gLRTc)qnsfk9!PXCYZ>$J^Q7DJubqL$ z(H|C`?}gkQ^l8(lAH$whn$WN`OGndUC@bEPhwn4xru0q-EoHr(-zftAVk*XWa6g8N zf~W=C?~^8_Ya15hQiXgesHU~cJXTZS;036Ixa3U@0z(wV`qBEU?)P=_GoA7x(2D$j zI!(h?8(K0aiwoVB*M&_jhY10}I3qEtRb=$eYYvhc z*8dHzJ#E8o>Q8;seDcqxn*PV{W9BoiNZqSC(=W4sf|f~cl*8amMzrOUNZ8zwV0Dw= zuPhgs3eQ$0>T$no4B;7fevq>S#cz1t_{*JEai1w;y?CsD>9_Pty)rXtl&^Du>NkuXnFY$r z3Jkf|zK!lnGe8^JN;As^-}h2oRA$Wa+m8#gPP5BCAniVcS-JIsgz5~Fb|h-ikF$AC zOG{JyE!#J+C^NT?1gVp}=nyH&T2VFX%^s5`uCa{ZY;)T29Nu5OzP|*5>gEpLw3?nG zc3b{{W?imf3>p45B#-3Xh+m?MnQKxklSb84dp^dIRxT%C!8#f))W;50p_q%Lg%{+B zn_XPd308O*%$RX|BD&OC>OR4(GdznXU+uWRK;qC19x8-?>si}n3mhjiij;Cb*2vH{ zS6%{Vhx-nd{q!`nsOelm5RhlgX^6@?FL!N%PQvs{pX~rGSN~Mo=h1OaPXua7=JP4c z`J(leq(*&G6~hMnqfz?Zay7+%DQc+Q1m7_j`B$SsGr03SnBJ68*AvgS#+4f{PT@+G z4zkUvj%<^1&Ib9GJRGks%n?YGE$DgL;lE>2!ZoRt#ty;Ir6Trp@jR^o-sBMXU z?Tfc|ny*`B@i!4`@qN)hyI*zYBmLLaCDoYgz|7cZtYV?DdUZMn%1NnH(+aY;V<}-L zaIzxiLnOzs$J^}JGqZI2IHU!CdP7fsZZ3zHNJVLeZOr4P6wi(r;~=|B2;S(=iK z6LpSto z8&eHR@rKxAWOJcA+zfWVE!}DTiYJly?K9L`#0>KlFQ8uo6$R)IBu!b|mmo`UHuz)$ zA_FkUQhQ9_WOM)1#nmPsH|rS-S*ai*=)8o79}k6opO>Q~zTSvWS3!fmhEzYtj8zqEUd3>=?cc+Nr44eKl_!nuyW|cA6TFrjCRpmHu zaPZ1?{PFC$OU3wewjo+5HGIBzsW*SeEAhdxLR|Wmq*wAoTcWX@!K0fqm=A;9(ijMwXenBua4Iy8mjEc`Y;# zLlKa~?@ak<==l>*aTMg#JCA;lb^3oo{66(Vj^^E%%!-%3cPpeSr{M25HC6Y+DD6P z^BllVo=S5q`+N7umZasj^5vU$`+P?&&QlXrgCMa9HfR~f@S{tog$j3ovjS*YC=2<* zzh72aE~*<`0G&Ik`a9W*+3iBQeo3d2&jorY=#vIANivh6uO0U_eVIt+c4|Na9(Ku`cs# zArZJe?&L&l+qh48A$D!=T}S(#?jjT@gX|G+*iUH*4yJ9}5U*#IGwu>iYNoXLHNvJ~ zoz&E+7A&fbh(#lz(6Im8D=%ZL&v{yDN<}A z^&V{b)u+AK(%YPW2XB&ImI=}ZJH&665~VkEfK>m+IXrj5gYgTOg^f|sAqgUoiK84- zTU-M9GO87;8fgftL3S9exHDQ*us$fH&yx!=u(yUsI}ai#mh-Mv!{jY!1%|)Sf%RB5 zw>NLS@Uei?Jbfr*mTqa@Xm@n>3fdBmt_u@0KgV9BZU(cLe%HZizWHQpMpxPmWG>_s zv`HsR=B4_NId*%$A%5_rH2!4At$CXh;mMoQWBp0z6|*}PcO=~pgp$8Cx!JtG!L#Kp zO1dj8IFK{!bqlv2M8~}O;^|V(gvfiu8^c?k^V=Ew+|+g(*=z zKUUd*neVIWK}os=s$d_2mumC9hh8xWLclU4zZMCrtx;6rW7g1Tb1i2#V-%banWy?- z-b>!7`$1WZ-Elw08Lj;-`khzPOyEBGXJyyUV5JQ-O&IPpcFtsZ0WU$R93)C$f^2rd zoR%EQ0N^t%IylJ8RQ|n;w6DlyIZ7=Bx$Xi-fu;gJO0sYD_ICzd{D@>|)-Tz3keKUm zD*iGU7fX9N(mo$B`9X_mB;Mv{^6f_1G}fH5Ov!cCia9vcGE5@GGoPk{Y?f`M91 zIXwL;zn5mPUnrTlKSQ6L`{8)miEW;zA-Kwe{OPQQkx@9%Dim_H!+(Ncs2py%;Tyr= zoG_TI*?p~xfplDqis8ll*3!d8 z&sW#Od4`>(m^My(l|N5`Qv&4rwT7k@NL`ZAheexc{W19(0wcxbD7aHb*n7L2CvNrK z0~b1q1s;Vl1hNk$5wQqP zoWU$BJmAe>*8cc=j;K9IT=@;*i0I3m-^&O?1Y|4WL&;r33uP=_dg?RLv2ite%RZRS z*pG?aXplfD8OXFpCe+f0IF4AMox5}1cp~y~c)?{)=w$o#Y9-k?g@>Tn%RQId^q-a= zR3IPn3P33;s*~7@wg1~B3m>N07&1Rv1vCk#9PcW}uk#FfwF0jw^C$njm{%443}Id7 zkwQOl*{appwnYkB$o*hd&@S(|;ILZa=s3<*UJ3}%gfok>G%t4wIMxI_h`1(tdV;*! zN^VY|)sErWuNS{>?igsa7^1$4-~KvbL{xpbGA}Ogza<6)Egn-1@86|OK|02q-9Z5DjM6(I` z`@ehL2n{ zMoaP-wsZIbw7{gr3mQ=^wCT9N1)0{5bBsA*U45TvsXN8&MC5hc-BTLx-0npT*?!7* z6@!Rk>PTr#jVDFjWO{B!6yb?EVO>X6S8cnWC6v~fA&!4q8zxNPkwDGLB zR`p);?uJu-I38?WS06YZuJtUe2flakc>xG3yFSY6rU2)L6!S@|?R*8aqmw$r$3Q<@}7hSONG5eO^gvA0EOGodfCAARY%R{Hd~v~mmnF>VfrL+@N5 z)8GlRLQ8z4snJ+#9s&+ZDL3(XHn~Io?sqratwJ3u^PssnCnp%VBkXF$_%#)Lz`-wm z%)Jumum!xB9e+z@50{}4;VOZXwK!^~=A(fDp5sF1&WHOd9Yx2(AZ}tM`BPrTco^r^ zS(d*m5Gt$M&+*1je9Itbi6-E>=sr`dEAd*+nQF~cI)eUs&E!j&Pzya z`t?t{9g6}Kk9yhj0>RW19(#c$x#Da-s+5H`2p6d(@BcVe*G&MrcD~mS2=3Fa1&o4VPnYN ziF`|-v0Q}yt{bdMyTF|oZC=%Ian9MdPS?DZ)^c0AEaIZuel1S~;lEO>Z#UewTg_A9 z&aU*o`*q|S0U{q?5U(Ge(|L#IjFayGj8Ejss)TGs)X%&aGZgem>>X7=QD9+ZL(OtCa+5q_@GmD`}CN3_{e-z{cj6)4_9w$rP754c58JdwFYjv6;G z377A;)Er>sf#ERm3Z4|vPonB=1TNVte)tI-k#3D6(t|J`7$|JiG1d9HTfs7`RfAtx zu^F@fqmOF0B)FLFlCSW1`INbMoy_9V_agfvAy-w-e^xsgD*ItS%l}rRN@pxDaXzGy z#XtoQ6ORklIQL_VZ2z0J-Nz>2L#+{dH~2j7HWvYLf%i_vcH@50dPD)su;h^8x(%Ws z6jSFUg46799R$2#HW}h-K%8Ni$j@42sna{+Ucxw{hxk(T0J%TkTrB~cdB51r=LK?< zi+iSHaiZVdepf8Mxqd+O>}AV2?L{r3=K;b4EebR?v)i0WL8mbN~J-H!0 zyHpE9SQknNm{CW$whBbLat_vS(91-9Ipb;KaqKZ58)Rq6>g}f_1?!9rr$>T7n@Z}mCHa!1sNU@gDly08v91Qsx!6hnSY+PGjxmIG|IS-7quc| z%gDMK+;z(Dp;#256EK#z9RhkSf4^rxuEqeVI&Jmx2!ix!AbU!4Yl!d7IW{3z?gVaiW^FZU>u5#?a;Cn$@mYO!uB4IC$b#BfeB z=VeXfj(ez9sBLhZ!XLXZ(me67fpFw@{-RJ$anuw~KYP1)SE|~!ybz%z-R0YdD@XtD zDg`~aoOp*fJWACVC9i!KW$}&qi|@8hL~*Ysz?ApNVy zf3(fyXL4fm`PZnTj-SRvUsv<>7$R)Gi>M!rTQTfpgPL%SK96Ns^WgVD&nionZUJ1+ z9u?C2=F^#WgbgI?{^^sGMDmBW!k|dyW!28Fm*WpZCoe5Ah1XOfuox%$Er2)8dQdh* zv$bas!Ra5G2~o~X2d@po7~~*NAygl4jM^SI-xaR$uL`~MT_J;BD>^Mc#+N!&F)E+1 zMNjVn~HIe-ckt$!z4) z1pfix8)VNf@Rn;}l>6@fPE)n1xRrA%-~#K^&weI$6rPOzOX#!qp&PqNo$dG0 z^tkou-`B5?(|oE$SiKO-I&;;G-{ma2$;0#@`_vIrn#5v4Ps7j7Y3_+MKdMsAHm9Q1 z2zptW>$w7e48p}dQ|HNR`g)Yzxyb1KNrq*MtI_z-7nE_gF0mjA`2=qkO9Bjgb4(He zGU#L-ipP5hurKW=FK|xCK}Mm&bQWB(MfTSNvscuD5~}O#JFsnA@`WOSwgWpl`7V^Q z%-)eDZo8TawEE60uwiz%Jn4j&(S1WB1_3rYZj`|?Gh}^|3xLg9KNKI&2w=2+nTCb} zo7R!~J-0eO!xrpKs(&$bw^s3&vAK7Lk)VhByh ztK^4_6stxQ9JB96p=Cwg1ex#yYjO_L-H>y*&U}jL4o(?%4POy`;a344#BKz*>qsyKF#avQm*Kx+P5! zfr95uzZNXXtU(GUx&@@QZEMPGve)ps3YrB!st-Job-jA+9a49z1&gvM#Y<01QCeh- zA$joRUoXLaJKiDQC##O@_;<)tsMiv8kwz|a4TfaC4SrSzxDNR1i9ka2!dU;IeIrZ?Ol;XvTb`cl`9PNv>OlsyNx6Q6ykD;WMCADAFfO9saaxTF^!wb6M7_wW zr@A809-TGN|8vq%B>AJYu#_+^LAHD=6F$;wtR=GD0-yCr<(5dVmIhEn;TDo;UXm zAM=A}S9%8yutE=LI;jWC^Qy_Er!l~kNh(ix-gi;P%hB7;@qM#+`^PGXWdd)U1f*3C zPBJ*}oUxe|iyb8NZ7p2ynI`H0x^x3T7U?rT<H5-&X!+6!Aovx+PYoBMEn@g zv7gbV4AT*l8gQ<2mp--xv`Uxbx)Y@B%GQu7S{{3*xS;9GJ2Ic)Kf72NY>0f~ZO7@U zEjwNMkWzS7xZ`x>2xf`&^UW-fjwak~Zpbigw~$0dIqON;e2W6q&hm3pHgyqXx-l|J z(38I*S15@f7DscLOoQP)e4=@cre0NT`6O>*)i&;*g<-|@ZC;^!!ucTnzLnDh&xiqf ziZ$`|=t0>S36^lzf~-!ut2B%RiV(fyy@Ll{UD)ZmVnG>qjYd=|zyx552wXSHqiK5< zPK(S1fdK}7M{Ov*k7fw+xXHDfm$XI~N1v&HCVDbaApG$|L(yFP^#~N_@JPV*+Lljq z4xh=a;I$s~$^8<_-l7zx=cvpw+b|NO$WU~}sh*X2FUNc+_*n%8En8Q3KD+g-oaI~K z?Whzw$rW?>eCf5*?W*DDpPm(#K^R5y_UA)XJ+E_qlmane@gA}@Ss(q*LHP|+j$(Q{#Tw_yhv@+lLy+AfU5Hpy7j!n%Z~T)SG%j?+ z;MHqvi^^KO#+1vZIoJu}1^nf`g~A%R2x$UULoiD=Vg}yb!ZTRd-k!5f#%YA2;sE}Y z8OBH9kPD&-Y<2 z`|al3{i$&bkYIhu*U+3!PUGV2EcUrrj$-1BlbqW8=l7e|V4u-+2wF6Spg?i)+0UMw zE$|6<$~iGhaooRhq`0Dm^PY(p)~r||9pv)-E_{*o%(yo9k4a8@>%6Rfq=AAWkU##& zIJC3k@e^(nFDUygS-S{k1|tXvn&NI|as1Nwj8NWQXmT4){$b2u)edqxC9c`ip2qOO zF=}ggJPddLTgH&vH_k7x;teI8e}C@o>srWe4CBP%kRHG{Z5+0K88m~0^!vJZq@XfYz_YvJ_OY2U%w_=xN(sub%FJxw+i*l~+`*xMjd(Shd zQ&P$=QlEAyO@OUC79cX}xFC9bTh&qdF-;{~9tBJDcI# z6CQ_?jKEbD0Dj1oZpVHrXx+_^nS?DK^U8i!IKso?w9*F}NXzdFE01DWADe(1Zq%)* zC8s$}qv-5Ei3)hF>6q!gmKE;5v*B>yfg|?WgnywC*}HtTZ|_-nzopIo$)rWZMI7b) zW?d5D64c5kyl^$&Tk5Dk?p}I@pWZOR!-?xYQ6EVlf?m62#iZh?=sKRohS976Ths+I zyFigzGyU@h>^d}%iTXMwO+N{s4a+8t0OCk+Y~P(8)(`0_nv$SXdXDgo@6TUXUz|U6)xk42f$EcHhbS6!Tc-A zm9g06`;gkz+oVve!PE63X8u%>7+w$oPV8u2PX`@Msr#wu&y`!Kd$|)BjDLztDwGTO zRp&yjwO`KTlZ$3|q}fNqc&{Fzk+ySP%G>T*2J5}b>ux9BlW_1dO{I*XO=tzyC)T5w zG`c9e$toxE%;&qE2`@)DSS&m83C@;;)FBx~tx?zUu+C}7cf=Oz&njnpAW%qR=&OjN zl%cm+rEJ}B9PztoD`e7g+gbx5iOKyO=&}z!=lgAjTl(z~{TaFr&1J0BCPCYaYdBLQ z=QK?$pjDC4h+FSvn(&0s8B@pf)xM&Ycp)c7?4NaTrQ)UfIR(WZ#1GffK9Usmi113# zWY|}d+QNn%kWq>bPYV{rqs15Fc6g5f*5lBuqnknB38kt$HpL(@yuzzByK=nC1^hb< z0Hu`D-z;>r?K|b;XWL;g58F;L8@aHu7{{QQ^sz8p=@M%elh^}@<@&VfG>j$S)px;|Kh1kkCWbn zr#HdmG$#WmI!&cYUTCYDz29bq3x@5gM!zc{n>Tv-HBs@|ThO2mHB{5IT!ZLK*UCe6 zmxIX|^1LNQ7f~pR*Cxf5=SG+`H$2&=l~5&Kil@zyl*1Mh4;P!J!wSZ)2;)`RfGc<^ z@TUnsiA$&1>ylG(mH*do?{}KcD%^hShrZ2U79wNp-|Fs&40DIl6snO=DJx`R0R~6y zoCNEn_ozl&4C^5MPtL%+7gP-E{dKqfGm|A6vhxQ-7)Y0_9J1m6^WYQgK^4)JdoPgh R>x@@083{%4N>PKr{{iuBA