欢迎来到墨客链中文文档¶
墨客系统介绍¶
介绍¶
区块链技术、加密货币和智能合约都有改变开发人员构建去中心化应用程序(DApp)方式的巨大潜力,并且已经在改变全球商业运作模式。
自2008年比特币问世以来,以加密货币身份亮相的区块链技术,已奠定其通过分布式账本技术提供数字化金融交易的身份,并且成为了一种非常有效的价值储存手段。不需要依靠中心化货币当局,比特币使用单一的去中心化共识模型就能验证交易并保障安全性()。详情参阅https://bitcoin.org/bitcoin.pdf以阅读更多内容。
2015年,以太坊等平台提出并且实现了在区块链平台上的智能合约,并进一步开创了Decentralized Application(DApp)的概念。智能合约是一种计算机程序,在特定方或开发者定义的程序条件下,直接控制各方之间进行数字货币或有价资产的转移。详情可参阅https://github.com/ethereum/wiki/wiki/White-Paper。
第二代区块链技术的“DApp”是一种去中心化的应用,不依赖中心服务器运行,但依赖类似BitTorrent,Napster和Kazaa的点对点(P2P)网络进行互连。P2P网络要维持来自多个数据源的最佳数据传输。智能合约和DApp都使用区块链处理和存储数据,并提供额外的计算功能,与比特币这样的纯粹提供交易功能的第一代区块链技术已大为不同。
自比特币创建以来,区块链技术(即分布式平台和通证)已经得到长足发展,但在功能、性能、安全性和可扩展性方面尚需进一步加强才能真正获得用户接纳,从而最终使得区块链技术可以在广阔的商用领域满足真实商业需求。
墨客项目将试图通过一种开创性解决方案,将现有区块链最佳实践与新型可扩展群链技术相结合,从而显著推进智能合约性能。 墨客项目所阐述的技术已不是停留在纸面上的纯理论探讨,而是已经在开发、测试并即将投入生产的真实落地技术。
墨客区块链¶
现有技术和区块链平台对于用户来说学习曲线非常陡峭,技术复杂的同时使用费用也很高昂——所有这些都会影响区块链技术的市场接受度以及可扩展性。现有平台交易处理速度很低,共识模型固定,并且无法快速适应开发人员不断增长的需求。迄今,区块链社区的挖矿高度集中,并且由于复杂性和硬件成本的问题,未能有效激励更多的新用户和感兴趣的消费者进入区块链领域。
这些区块链平台也彼此隔离,每个区块链平台上的通证和智能合约与其他区块链底层难以进行有效沟通。于是现有区块链市场根据不同的平台技术形成了各自封闭的圈子,其平台、技术、用户基础和行业也是彼此隔离的。
即使对于有经验的技术开发人员来说,构建新的区块链目前也极具挑战性。导致局面更加复杂的是大多数区块链底层技术很难升级;同时,不同底层技术使得整个区块链的用户被低效的分离到不同的区块链底层平台上。
墨客基金会(MOAC)通过开发分层分片的群链技术解决了现有区块链平台的低效问题。墨客平台采用先进的分层架构,可降低DApp开发人员的成本,提供可扩展性并降低开发复杂度,同时使用分片技术提高交易速度和交易量。墨客在其平台内利用群链技术,包括母链(基于工作量证明的底层区块链)和子链(使用多种共识机制的上层区块链),来支持多种共识机制的智能合约。墨客平台还具有跨链功能, 不但支持墨客平台上不同子链间的互联,也支持与其他区块链底层及其上的加密货币的互联互通。
墨客首先提出并实现了为每个智能合约提供定制子链的区块链解决方案,比现有智能合约执行的解决方案效率更高,且扩展性更强。
墨客平台使用子链来实现智能合约的业务逻辑,从而避免了在同一条链上同时处理常规的区块链任务(如交易的共识和记录)和与业务紧密相关的逻辑(通过智能合约方式实现)。通过为每个智能合约提供为其定制的子链,开发人员可以自由选择最适合其使用场景的共识算法,并确定分配给智能合约的节点数量,从而可以支持更多的使用场景。智能合约的所有状态都保存在本地子链中,且可根据需要将数据写入母链。

母链¶
母链是一个使用工作量证明为共识算法的区块链,可为智能合约和DApp解决数据存储和计算处理工作,是墨客的主要部分。
工作量证明 Proof-of-Work(PoW)算法是一种行之有效的措施,可以阻止并最终禁止第三方干扰,包括拒绝服务攻击,其他服务以及网络滥用(如垃圾邮件)。 PoW要求服务请求者提供一些工作量证明,通常是在规定的处理时间内由计算机完成特定处理任务,从而消除错误的系统威胁。 在墨客平台上,母链是处理交易和其他区块链操作、共识和数据访问的公共区块链层。墨客还支持使用子链来实现其他共识算法 。
Besides the POW consensus on transaction and data store set, each POW node is associated with one or more Smart Contract Server(SCS). SCS node could be local to the POW node, or it could be a remote node. The SCS identity is fully verifiable by the corresponding POW node, or Validating Node (VNODE).
Block is mined every 10s, with reward of 2 MOAC coins per block.
The reward schedule halves every 12,500,000 blocks, equivalent to approx. four years.
After block 15,000,000, the reward will be constant of 0.1 MOAC per block. See below.
We define 1 MOAC = 1,000,000 Sand. 1 Sand = 1,000 Xiao.
Block# | Reward (1 MOAC = 1,000,000 Sand) |
---|---|
1-12,500,000 | 2 MOAC |
12,500,001 - 25,000,000 | 1 MOAC |
25,000,000 - 37,500,000 | 0.5 MOAC |
37,500,001 - 50,00,000 | 0.25 MOAC |
50,000,001 - 62,500,000 | 0.125 MOAC |
> 62,500,001 | 0.1 MOAC |
Transaction fee is paid in two ways. One is through Transaction. The other is for Smart Contract or sub chain. Smart Contract Call cost is set lower than underlying transaction in purpose, thus encouraging the usage of SCS. This can alleviate the pressure on the underlying layer, and also benefit the SCS providers.
母链交易数据结构¶
墨客母链的交易数据结构与以太坊的相比,加入了三个新变量:
type txdata struct {
AccountNonce `json:"nonce" gencodec:"required"`
SystemContract `json:"syscnt" gencodec:"required"`
`json:"gasPrice" gencodec:"required"`
GasLimit `json:"gas" gencodec:"required"`
Recipient `json:"to" rlp:"nil"` // nil means contract creation
Amount `json:"value" gencodec:"required"`
Payload `json:"input" gencodec:"required"`
ShardingFlag `json:"shardingFlag" gencodec:"required"`
Via `json:"via" rlp:"nil"`
// Signature values
V `json:"v" gencodec:"required"`
R `json:"r" gencodec:"required"`
S `json:"s" gencodec:"required"`
}
母链节点客户端(VNODE)¶
VNODE client is used to form the MotherChain network. It used a Proof of Work consensus method similar to Ethereum. VNODE not only handles data storage and compute processing for smart contracts but also pass data for the MicroChain Dapps.
子链¶
子链是MOAC区块链中非常重要的一个模块。其主要目的在于分流母链中的业务逻辑,把一些比较繁琐的业务操作放在子链中执行。
子链架构于母链上层,每个子链都可以拥有自己独特的共识系统和算法。
例如,想要获得快速高并发的交易效果,您可以创建一个使用股权证明Proof-of-Stake(POS)共识模式的子链。POS是区块链网络旨在实现分布式共识的一种算法。
采取股权证明共识的区块链,依赖网络中的验证节点来检验交易,而不像严格的工作量证明(PoW)那样需要处理大量数据。在股权证明共识中,下一个区块的创建者是根据诸如持币量或币龄等因素(即股份)的随机算法来选择的。
股权证明系统的优点在于它可以完全扩展到企业量级的交易、能效高并支持多种交易。随着网络中的节点数量增加,其验证能力也会同步提升,在无需不断地访问母链的情况下,允许DApp子链开展小额交易。
除了股权证明和工作量证明外,墨客平台还可以支持额外的即插即用共识系统,例如活动证明(Prove of Activity)、销毁证明(Proof of Burn)、耗时证明(Proof of Elapsed Time),存储证明(Proof of Capacity)等。
由于子链间是隔离的,因此它们可以在一个实例中为智能合约运行不同的虚拟机。这使子链能够启动各种业务逻辑并为DApp提供公共服务,包括部署类似IPFS的文件系统、构建用于数据存储的传感器网络,甚至还可以通过子链实现人工智能服务。
由于DApp部署在开发人员选择的虚拟机中,因此不需要额外编程。墨客可以通过更低的费用运行现有的以太坊智能合约,开发人员可以利用平台的API扩展现有的智能合约功能,而无需学习如何编程区块链。
通过使用自己独特的虚拟机和子链隔离每个智能合约,墨客平台可提高智能合约执行效率,并使低成本的处理费用成为可能。这显著降低了开发人员的部署成本,并使他们能够构建基于高交易量的DApp。
子链本身是以智能合约的方式部署到MOAC母链上,其共识方式、节点组成和业务逻辑都在智能合约中定义。
- 子链节点控制合约microchainprotocolbase,用于定义SCS节点共识方式和如何包括SCS节点矿工加入子链;
- 子链逻辑控制合约microchainbase:用于子链控制逻辑,子链生成前和生成后的一系列控制逻辑;
- 子链DAPP智能合约:用于部署子链业务逻辑的合约,每个子链只能部署一个DAPP合约;
子链的验证过程由合约节点SCS完成,SCS节点随机组合,支持动态增减。
子链支持分片,每个分片都能独立完成业务逻辑。
同时,在主链上,我们增加了代理的Vnode节点来保证子链的稳定性,这部分我们会在最后介绍。
当前,按功能分,有如下几种SCS节点类型: * 参与业务逻辑的SCS * 用于业务监控的SCS * 准备参与业务逻辑的SCS
墨客通证¶
墨客通证的起始供应总量为1.5亿枚。墨客基金会本身持有6300万,墨客区块链科技公司持有3100万个通证。3100万用于资助正在进行的群链技术发展。墨客通证的价值可以在CoinMarketcap.com上查询。
墨客通证最初在2017年7月以ERC20形式在以太坊平台发行。墨客主网在2018年4月上线以后,已经将以太坊上的ERC20合约关闭,按地址将ERC20通证全部1:1转换成为墨客主网的原生通证。
墨客区块链每年将通过挖矿产生600万个通证,进一步增加流通中的供应量。4年后,产量减半至300万,接下来的4年再减半。到2058年,总供应量将达到2.1亿枚。
墨客的小写 moac 或者 mc 是墨客平台上原生通证的名字,如同以太坊的ether,井通平台的swt一样。原生通证被用来支付母链上交易和合约执行的手续费,和子链的运行费用。可以参考 Gas 费用和 mc.
计量系统¶
MOAC具有用作mc单位的计量系统。 mc的最小单位,又称为基本单位为Sha,1 mc = 1e+18 Sha,其它的额度有自己的名称。 以下是额度名称的列表 他们在沙的价值。 按照共同的模式,mc还指定货币的单位(1e + 18或一个quintillion Sha)。
Unit | Sha Value | Sha |
---|---|---|
sha | 1 sha | 1 |
Ksha (femtomc) | 1e3 sha | 1,000 |
Msha (picomc) | 1e6 sha | 1,000,000 |
Gsha (xiao) | 1e9 sha | 1,000,000,000 |
micromc (sand) | 1e12 sha | 1,000,000,000,000 |
millimc | 1e15 sha | 1,000,000,000,000,000 |
mc (moac) | 1e18 sha | 1,000,000,000,000,000,000 |
交易墨客¶
墨客平台提供了一个在线钱包 MOAC Wallet 来方便用户使用简单的交易功能。
MOAC can also be transferred using the MOAC console.
> var sender = mc.accounts[0];
> var des = mc.accounts[1];
> var amount = chain3.toSha(0.01, "mc")
> mc.sendTransaction({from:sender, to:des, value: amount})
MOAC network, like Ethereum, use mc as a cryptofuel, commonly referred to as “gas”. Beyond transaction fees, gas is a central part of every network request and requires the sender to pay for the computing resources consumed. The gas cost is dynamically calculated, based on the volume and complexity of the request and multiplied by the current gas price. Its value as a cryptofuel has the effect of increasing the stability and long-term demand for mc and MOAC as a whole.
Gas 费用和 mc¶
Gas is supposed to be the constant cost of network resources/utilisation. You want the real cost of sending a transaction to always be the same, so you can’t really expect Gas to be issued, currencies in general are volatile.
So instead, we issue mc whose value is supposed to vary, but also implement a Gas Price in terms of MOAC. If the price of mc goes up, the Gas Price in terms of mc should go down to keep the real cost of Gas the same.
Gas has multiple associated terms with it: Gas Prices, Gas Cost, Gas Limit, and Gas Fees. The principle behind Gas is to have a stable value for how much a transaction or computation costs on the Ethereum network.
- Gas Cost is a static value for how much a computation costs in terms of Gas, and the intent is that the real value of the Gas never changes, so this cost should always stay stable over time.
- Gas Price is how much Gas costs in terms of another currency or token like MOAC. To stabilise the value of gas, the Gas Price is a floating value such that if the cost of tokens or currency fluctuates, the Gas Price changes to keep the same real value. The Gas Price is set by the equilibrium price of how much users are willing to spend, and how much processing nodes are willing to accept.
- Gas Limit is the maximum amount of Gas that can be used per block, it is considered the maximum computational load, transaction volume, or block size of a block, and miners can slowly change this value over time.
- Gas Fee is effectively the amount of Gas needed to be paid to run a particular transaction or program (called a contract). The Gas Fees of a block can be used to imply the computational load, transaction volume, or size of a block. The gas fees are paid to the miners (or bonded contractors in PoS).
项目路线图¶

1.盘古 (Pangu)
内部版本识别号 (Version):0.8
Release Date: 3/31/2018
Major Progress:
- VNODE mining;
- SCS mining;
- System contract for auto trigger;
- Subchain Protocol contract for SCS miner registration;
- Subchain contract for Dapp configuration and flush control;
Documents:
2.女娲(Nuwa)
内部版本识别号(Version):1.0
Release Date: 7/30/2018
Major Progress:
- Fully functional VNODE to support MicroChain;
- Fully functional SCS server to support MicroChain;
- Enabled VNODE to get rewards from MicroChain mining;
- MicroChain protocol smart contract;
- MicroChain base smart contract that supports POS consensus;
- Fully functional MicroChain supports sharding;
- Supports FileStorm Protocol for IPFS MicroChain;
- Supports MicroChain without token;
3.伏羲(Fuxi)
内部版本识别号(Version):1.1
Release Date: 12/30/2019
Available features:
- Supports MicroChain with cross-chain features;
- Supports MicroChain with IOT mining features;
4. 神农(Shennong)
内部版本识别号(Version):1.2
Release Date: 12/30/2020
Available features:
- VNODE consensus protocol upgrade;
- High performance (>10k TPS);
- Zero knowledge support;
- Data store/exchange market;
墨客区块链系统和工具¶
安装母链节点¶
官方发布版本¶
最新的墨客软件可以从官方的发布地址下载 release link
Debian/Ubuntu/CentOS¶
- Untar the file using tar, under the directory, run ./moac
To see the help, use ./moac –help
To enable the console, run: ./moac console
A mainnet directory will be created under $HOME/.moac/ and some info should be seen as:
INFO [04-24|11:24:26.506] 86161:IPC endpoint closed: /home/user/.moac/moac.ipc
from another terminal, run moac again to attach the running node
./moac attach
or
./moac attach $HOME/.moac/moac.ipc
from console prompt, create coinbase account
>personal.newAccount()
from console prompt, start mining by running
>miner.start()
from another terminal, run moac again to attach the running node
./moac attach
from prompt, load script
>loadScript("mctest.js")
check if miner has mined any moac by checking:
>mc.accounts
create another account
>personal.newAccount()
try send from one account to another:
>Send(mc.accounts[0], '', mc.accounts[1], 0.1)
WINDOWS¶
Unzip the file to a directory, under the directory, run moac.exe
To see the help, use moac.exe –help
To enable the console, run: moac.exe console
A mainnet directory will be created under and some info should be seen as:
打开命令(cmd)终端,转到墨客解压目录,在命令行中执行:
D:\moacPangu0.8.2-win>moac --help
显示帮助信息,包含但不限于以下内容:
查看moac帮助
打开命令(cmd)终端,转到墨客解压目录,在命令行中执行:
D:\ moacPangu0.8.2-win>moac --help
显示帮助信息,包含但不限于以下内容:
Start MOAC.... 2
NAME:
moac - the MOAC-core command line interface
Copyright 2017 The MOAC Authors
USAGE:
moac [options] command [command options] [arguments...]
VERSION:
0.8.2-develop-ed4070bf
MOAC CORE OPTIONS:
--config value TOML configuration file
--datadir "C:\Users\[userName]\AppData\Roaming\MoacNode" Data directory for the databases and keystore
--keystore Directory for the keystore (default = inside the datadir)
--nousb Disables monitoring for and managing USB hardware wallets
--networkid value Network identifier (integer, 1=Pangu, 2=Testnet) (default: 1)
--testnet MOAC test network: pre-configured proof-of-work test network
打开命令(cmd)终端,转到墨客当前目录,在命令行中执行:
D:\ moacPangu0.8.2-win>moac
显示如下信息:

moac_install_win_0
至最后三行显示如下:
INFO [04-01|20:44:42.851] 1:[node/node.go->Node.startIPC]
INFO [04-01|20:44:42.852] 145:IPC endpoint opened: \\.\pipe\moac.ipc
INFO [04-01|20:45:12.846] 152:Block synchronisation started
表示节点安装成功,如果网络正常,就开始同步区块。
系统将MOAC节点默认安装在目录:
C:\Users\[userName]\AppData\Roaming\MoacNode\
该目录下包含两个文件夹:moac和keystore。
系统关机或主动关闭运行中的节点后,如果需要重新启动节点,在命令行中执行:
D:\ moacPangu0.8.2-win>moac console
之后一直滚屏以同步区块数据。
打开另一个命令(cmd)终端,转到墨客当前目录,在命令行中执行:
D:\ moacPangu0.8.2-win>moac attach

moac_install_win_1
该命令行不会主动滚屏,而是等待命令。
3. 挖矿¶
挖矿前必须建立一个自己的账户。
进入MOAC console界面,执行命令:
> personal.newAccount()
系统会提示输入一个密码,例如”passwd”,并再次输入相同密码确认后,会显示一个以0x开头的字符串,即为MOAC帐号的公开地址。

moac_install_win_2
系统同时会在以下目录:
C:\Users\[userName]\AppData\Roaming\MoacNode\testnet\keystore
记录一个账号文件。请保存好该文件,并牢记密码,之后用于解密帐号和操作。
进入MOAC console界面,执行命令:
> mc.getBalance(mc.accounts[0])
可以查看本节点下的账号余额。0表示第一个账户,也是默认挖矿账户。
或者:导入“mctest.js”的情况下(见4.1),执行命令:
> checkBalance()
该命令用于查看当前节点所有账号的余额。
进入MOAC console界面,执行命令:
> miner.start()
挖矿状态下,数据显示有明显不同。

moac_install_win_4
挖到矿之后,可以查看余额

moac_install_win_5
登录墨客区块链浏览器页面: http://explorer.moac.io。

moac_explorer_0
在搜索栏输入你的挖矿账号地址,会显示该账号的余额等信息。

moac_explorer_1
在搜索栏输入你挖到矿的区块号,会显示该区块的信息。
Miner正是你的账号地址。

moac_explorer_2
4. 交易¶
为执行交易,需要至少两个帐号,其中一个有足够的mc。
如果没有目标账号,可以用步骤2.3.1的命令创建一个本地账号。并用命令:
> mc.accounts
显示当前节点中存储的账号,应该至少有一个挖矿账号。
进入MOAC console界面,执行命令:
> Send(mc.accounts[0], 'passwd', mc.accounts[1], 0.1)
这个过程需要第一个账号的密码。比如’passwd’,发送额为0.1 mc。

moac_install_win_6
在系统挖矿的情况下,发送应该在下一个区块产生时完成。
系统显示的是以 sha(Sand) 为单位的余额, 1 mc = 1e18 sha。
母链节点命令行¶
Most Commonly Used Commands:¶
--testnet: connect to MOAC testnet (networkid = 101);
--rpc: initiate RPC service of HTTP, so as to nonlocally access the specific MOAC node service;
--rpcaddr value: default as "localhost", only local accessibility; can be reset to "0.0.0.0", so as to nonlocally access the specific MOAC node service, but the current RPC service is based on HTTP using plaintext,so users need to be aware of the safety risks;
--rpcport value: default as"8545", normally no changes are needed, users can use the default port;
--rpcapi value: command RPC as to which API service will be open,default as "chain3,mc,net",the commonly used will also be configured such as: personal,admin,debug,miner,txpool,db,shh and so on,but because of RPC services' cleartext nature,if users choose to use personal,they should be aware of the safety risks;
--rpccorsdomain value: in general,if users wish to use this option, they can just use ""; to be more specifical, users are recommended to search up "Cross-origin resource sharing" to further understand some key phrases;
--jspath loadScript: default value is ".", the main directory of loadScript when installing javascript file;
As shown below:¶
Initiate MOAC VNODEs and connect to mainnet (network ID = 99)
./moac
Through local ipc port connecting to MOAC mainnet nodes and start the command line
./moac attach
Initiate MOAC nodes and connect to testnet (network ID = 101)
./moac --testnet
Initiate MOAC testnet nodes and interactive command line
./moac --testnet console
Through local ipc port connecting to MOAC nodes
./moac attach /xx/xxx/moac.ipc
Through HTTP-based rpc port connecting to local or remote MOAC nodes
./moac attach http://xxx.xxx.xxx.xxx:8545
Initiate MOAC testnet nodes and RPC service
./moac --testnet --rpc
Initiate MOAC testnet nodes which is nonlocally accessible; personal and debug services can also be nonlocally used while providing cross-domain resource sharing service.
./moac --testnet --rpc --rpcaddr=0.0.0.0 --rpcapi="db,mc,net,chain3,personal,debug" --rpccorsdomain=""
All command line parameters¶
On the command line, type:
$ ./moac help
or
$ ./moac --help
moac - the MOAC-core command line interface
Copyright 2017 The MOAC Authors
USAGE:
moac [options] command [command options] [arguments...]
VERSION:
1.0.9-stable-f98b7fea
account Manage accounts
attach Start an interactive JavaScript environment (connect to node)
bug opens a window to report a bug on the moac repo
console Start an interactive JavaScript environment
dump Dump a specific block from storage
dumpconfig Show configuration values
export Export blockchain into file
import Import a blockchain file
init Bootstrap and initialize a new genesis block
js Execute the specified JavaScript files
license Display license information
makecache Generate ethash verification cache (for testing)
makedag Generate ethash mining DAG (for testing)
monitor Monitor and visualize node metrics
removedb Remove blockchain and state databases
version Print version numbers
wallet Manage MoacNode presale wallets
help, h Shows a list of commands or help for one command
--config value TOML configuration file
--datadir "/Users/zpli/Library/MoacNode" Data directory for the databases and keystore
--keystore Directory for the keystore (default = inside the datadir)
--nousb Disables monitoring for and managing USB hardware wallets
--networkid value Network identifier (integer, 99=mainnet, 101=testnet, 100=devnet) (default: 99)
--testnet MOAC test network: pre-configured proof-of-work test network
--dev Developer mode: pre-configured private network with several debugging flags
--syncmode "fast" Blockchain sync mode ("fast", "full", or "light")
--mcstats value Reporting URL of a mcstats service (nodename:secret@host:port)
--identity value Custom node name
--lightserv value Maximum percentage of time allowed for serving LES requests (0-90) (default: 0)
--lightpeers value Maximum number of LES client peers (default: 20)
--lightkdf Reduce key-derivation RAM & CPU usage at some expense of KDF strength
--ethash.cachedir Directory to store the ethash verification caches (default = inside the datadir)
--ethash.cachesinmem value Number of recent ethash caches to keep in memory (16MB each) (default: 2)
--ethash.cachesondisk value Number of recent ethash caches to keep on disk (16MB each) (default: 3)
--ethash.dagdir "/Users/zpli/.ethash" Directory to store the ethash mining DAGs (default = inside home folder)
--ethash.dagsinmem value Number of recent ethash mining DAGs to keep in memory (1+GB each) (default: 1)
--ethash.dagsondisk value Number of recent ethash mining DAGs to keep on disk (1+GB each) (default: 2)
--txpool.nolocals Disables price exemptions for locally submitted transactions
--txpool.journal value Disk journal for local transaction to survive node restarts (default: "transactions.rlp")
--txpool.rejournal value Time interval to regenerate the local transaction journal (default: 1h0m0s)
--txpool.pricelimit value Minimum gas price limit to enforce for acceptance into the pool (default: 1)
--txpool.pricebump value Price bump percentage to replace an already existing transaction (default: 10)
--txpool.accountslots value Minimum number of executable transaction slots guaranteed per account (default: 16)
--txpool.globalslots value Maximum number of executable transaction slots for all accounts (default: 40960)
--txpool.accountqueue value Maximum number of non-executable transaction slots permitted per account (default: 64)
--txpool.globalqueue value Maximum number of non-executable transaction slots for all accounts (default: 1024)
--txpool.lifetime value Maximum amount of time non-executable transaction are queued (default: 3h0m0s)
--cache value Megabytes of memory allocated to internal caching (min 16MB / database forced) (default: 128)
--trie-cache-gens value Number of trie node generations to keep in memory (default: 120)
--unlock value Comma separated list of accounts to unlock
--password value Password file to use for non-inteactive password input
--rpc Enable the HTTP-RPC server
--rpcaddr value HTTP-RPC server listening interface (default: "localhost")
--rpcport value HTTP-RPC server listening port (default: 8545)
--rpcapi value API's offered over the HTTP-RPC interface
--ws Enable the WS-RPC server
--wsaddr value WS-RPC server listening interface (default: "localhost")
--wsport value WS-RPC server listening port (default: 8546)
--wsapi value API's offered over the WS-RPC interface
--wsorigins value Origins from which to accept websockets requests
--ipcdisable Disable the IPC-RPC server
--ipcpath Filename for IPC socket/pipe within the datadir (explicit paths escape it)
--rpccorsdomain value Comma separated list of domains from which to accept cross origin requests (browser enforced)
--jspath loadScript JavaScript root path for loadScript (default: ".")
--exec value Execute JavaScript statement
--preload value Comma separated list of JavaScript files to preload into the console
--bootnodes value Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)
--bootnodesv4 value Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)
--bootnodesv5 value Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)
--port value Network listening port (default: 30333)
--maxpeers value Maximum number of network peers (network disabled if set to 0) (default: 25)
--maxpendpeers value Maximum number of pending connection attempts (defaults used if set to 0) (default: 0)
--nat value NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>) (default: "any")
--nodiscover Disables the peer discovery mechanism (manual peer addition)
--v5disc Enables the experimental RLPx V5 (Topic Discovery) mechanism
--netrestrict value Restricts network communication to the given IP networks (CIDR masks)
--nodekey value P2P node key file
--nodekeyhex value P2P node key as hex (for testing)
--mine Enable mining
--minerthreads value Number of CPU threads to use for mining (default: 8)
--moacbase value Public address for block mining rewards (default = first account created) (default: "0")
--targetgaslimit value Target gas limit sets the artificial target gas floor for the blocks to mine (default: 9000000)
--gasprice "18000000000" Minimal gas price to accept for mining a transactions
--extradata value Block extra data set by the miner (default = client version)
--gpoblocks value Number of recent blocks to check for gas prices (default: 10)
--gpopercentile value Suggested gas price is the given percentile of a set of recent transaction gas prices (default: 50)
--vmdebug Record information useful for VM and contract debugging
--metrics Enable metrics collection and reporting
--fakepow Disables proof-of-work verification
--nocompaction Disables db compaction after import
--verbosity value Logging verbosity: 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail (default: 3)
--vmodule value Per-module verbosity: comma-separated list of <pattern>=<level> (e.g. mc/=5,p2p=4)
--backtrace value Request a stack trace at a specific logging statement (e.g. "block.go:271")
--debug Prepends log messages with call-site location (file and line number)
--pprof Enable the pprof HTTP server
--pprofaddr value pprof HTTP server listening interface (default: "127.0.0.1")
--pprofport value pprof HTTP server listening port (default: 6060)
--memprofilerate value Turn on memory profiling with the given rate (default: 524288)
--blockprofilerate value Turn on block profiling with the given rate (default: 0)
--cpuprofile value Write CPU profile to the given file
--trace value Write execution trace to the given file
--fast Enable fast syncing through state downloads
--light Enable light client mode
--help, -h show help
Copyright 2017-2018 MOAC Authors
交互命令行¶
墨客母链客户端使用了和以太坊类似的交互式命令行。用户可以在命令行(console)中执行内置的JAVA script命令或者利用脚本(script),输出结果显示在命令行中。 这里使用的chain3对象,是MOAC参考以太坊,而开发的一套javascript库,目的是让应用程序能够与MOAC的VNODE和SCS节点进行通信。注意,这里有两层,moac启动了一个MOAC VNODE节点,console参数开启了一个javascript的控制台,这个控制台注入了chain3.js这个库,以使我们可以通过chain3对象与MOAC VNODE节点做交互。
Interactive use: the JSRE REPL Console¶
The MOAC VNODE CLI executable moac has a JavaScript console (a Read, Evaluate & Print Loop = REPL exposing the JSRE), which can be started with the console or attach subcommand. The console subcommands starts the moac node and then opens the console. The attach subcommand will not start the moac node but instead tries to open the console on a running moac instance.
$ moac console
$ moac attach
The attach node accepts an endpoint in case the moac node is running with a non default ipc endpoint or you would like to connect over the rpc interface.
$ moac attach ipc:/some/custom/path
$ moac attach http://127.0.0.1:8545
$ moac attach ws://127.0.0.1:8546
参数说明 –datadir 数据库和秘钥存储路径 –dev 开发环境,采用权威证明(PoA),开发帐号有预存金额,自动封装交易数据到区块链 –rpc 开启HTTP-RPC服务,默认8545端口 –rpccorsdomain 允许连接到rpc的url匹配模式 *代表任意 console 启动一个交互式的JavaScript环境
Note that by default the moac node doesn’t start the http and weboscket service and not all functionality is provided over these interfaces due to security reasons. These defaults can be overridden when the –rpcapi and –wsapi arguments when the moac node is started, or with admin.startRPC and admin.startWS.
If you need log information, start with:
$ moac --verbosity 4 console 2>> /tmp/vnode.log
Otherwise mute your logs, so that it does not pollute your console:
$ moac console 2>> /dev/null
or
$ moac --verbosity 0 console
Geth has support to load custom JavaScript files into the console through the –preload argument. This can be used to load often used functions, setup chain3 contract objects, or
$ moac --preload "/my/scripts/folder/utils.js,/my/scripts/folder/contracts.js" console
Non-interactive use: JSRE script mode¶
It’s also possible to execute files to the JavaScript interpreter. The console and attach subcommand accept the –exec argument which is a javascript statement.
$ moac --exec "mc.blockNumber" attach
This prints the current block number of a running moac instance.
Or execute a local script with more complex statements on a remote node over http:
$ moac --exec 'loadScript("/tmp/checkbalances.js")' attach http://127.0.0.1:8545
$ moac --jspath "/tmp" --exec 'loadScript("checkbalances.js")' attach http://127.0.0.1:8545
Use the –jspath <path/to/my/js/root> to set a libdir for your js scripts. Parameters to loadScript() with no absolute path will be understood relative to this directory.
You can exit the console cleanly by typing exit or simply with CTRL-C.
Caveat¶
Just like go-ethereum, MOAC’s JSRE uses the Otto JS VM which has some limitations:
“use strict” will parse, but does nothing. The regular expression engine (re2/regexp) is not fully compatible with the ECMA5 specification. Note that the other known limitation of Otto (namely the lack of timers) is taken care of. Ethereum JSRE implements both setTimeout and setInterval. In addition to this, the console provides admin.sleep(seconds) as well as a “blocktime sleep” method admin.sleepBlocks(number).
Since chain3.js uses the bignumber.js library (MIT Expat Licence), it is also autoloded.
Timers¶
In addition to the full functionality of JS (as per ECMA5), the moac JSRE is augmented with various timers. It implements setInterval, clearInterval, setTimeout, clearTimeout you may be used to using in browser windows. It also provides implementation for admin.sleep(seconds) and a block based timer, admin.sleepBlocks(n) which sleeps till the number of new blocks added is equal to or greater than n, think “wait for n confirmations”.
Management APIs¶
Beside the official DApp API interface the VNODE has support for additional management API’s. These API’s are offered using JSON-RPC and follow the same conventions as used in the DApp API. The VNODE package comes with a console client which has support for all additional API’s.
JSON RPC 接口命令¶
JSON <http://json.org/> is a lightweight data-interchange format. It can represent numbers, strings, ordered sequences of values, and collections of name/value pairs.
JSON-RPC <http://www.jsonrpc.org/specification>`is a stateless, light-weight remote procedure call (RPC) protocol. Primarily this specification defines several data structures and the rules around their processing. It is transport agnostic in that the concepts can be used within the same process, over sockets, over HTTP, or in many various message passing environments. It uses JSON (`RFC 4627 <http://www.ietf.org/rfc/rfc4627.txt>) as data format.
MOAC JSON-RPC has some compatibility with ETHEREUM JSON-RPC,
Chain3 | Web3.js |
---|---|
chain3 | web3 |
mc | eth |
net | net |
admin | admin |
personal | personal |
vnode | n/a |
scs | n/a |
MOAC has two additional JSON-RPC objects (vnode and scs) for VNODE and SCS services. These RPCs are supported by Nuwa 1.0.4 version and later. The most recent RPC is Nuwa 1.0.9.
JSON-RPC Endpoint¶
默认 JSON-RPC 的接入为:
Client | URL |
---|---|
Go | http://localhost:8545 |
在VNODE和SCS监听节点启动时,可以使用 HTTP JSON-RPC 选项``–rpc`` 命令来开启:
–rpc: 启用HTTP的RPC服务,以便非本机访问该MOAC节点服务;
moac --rpc
change the default port (8545) and listing address (localhost) with:
moac --rpc --rpcaddr <ip> --rpcport <portnumber>
If accessing the RPC from a browser, CORS will need to be enabled with the appropriate domain set. Otherwise, JavaScript calls are limit by the same-origin policy and requests will fail:
moac --rpc --rpccorsdomain "http://localhost:3000"
–rpcapi value: 指定RPC要开放的API服务,默认为”chain3,mc,net”,常用的一般还会配置比如personal,admin,debug,miner,txpool,db,shh等,但是因为RPC服务是明文传输,所以,如果使用personal的时候,要注意安全问题;
For SCS:
scsserver --rpc
HEX value encoding¶
At present there are two key datatypes that are passed over JSON: unformatted byte arrays and quantities. Both are passed with a hex encoding, however with different requirements to formatting:
When encoding QUANTITIES (integers, numbers): encode as hex, prefix with “0x”, the most compact representation (slight exception: zero should be represented as “0x0”). Examples: - 0x41 (65 in decimal) - 0x400 (1024 in decimal) - WRONG: 0x (should always have at least one digit - zero is “0x0”) - WRONG: 0x0400 (no leading zeroes allowed) - WRONG: ff (must be prefixed 0x)
When encoding UNFORMATTED DATA (byte arrays, account addresses, hashes, bytecode arrays): encode as hex, prefix with “0x”, two hex digits per byte. Examples: - 0x41 (size 1, “A”) - 0x004200 (size 3, “:raw-latex:`\0`B:raw-latex:`0`”) - 0x (size 0, “”) - WRONG: 0xf0f0f (must be even number of digits) - WRONG: 004200 (must be prefixed 0x)
Currently MOAC <https://github.com/MOACChain/moac-core/releases> VNODE server provides JSON-RPC communication over http and IPC (unix socket Linux and OSX/named pipes on Windows). SCS server provides rovides JSON-RPC communication over http only.
The default block parameter¶
The following methods have an extra default block parameter:
When requests are made that act on the state of moac, the last default block parameter determines the height of the block.
The following options are possible for the defaultBlock parameter:
HEX String
- an integer block numberString "earliest"
for the earliest/genesis blockString "latest"
- for the latest mined blockString "pending"
- for the pending state/transactions
Curl 命令示例¶
The curl options below might return a response where the node complains about the content type, this is because the –data option sets the content type to application/x-www-form-urlencoded . If your node does complain, manually set the header by placing -H “Content-Type: application/json” at the start of the call.
The examples assume a local MOAC node is running and connected to testnet (network id = 101). The URL/IP & port combination is localhost:8545 or ‘127.0.0.1’, which must be the last argument given to curl.
JSON-RPC 命令¶
- chain3
- net
- mc
- mc_protocolVersion
- mc_syncing
- mc_coinbase
- mc_mining
- mc_hashrate
- mc_gasPrice
- mc_accounts
- mc_blockNumber
- mc_getBalance
- mc_getStorageAt
- mc_getTransactionCount
- mc_getBlockTransactionCountByHash
- mc_getBlockTransactionCountByNumber
- mc_getUncleCountByBlockHash
- mc_getUncleCountByBlockNumber
- mc_getCode
- mc_sign
- mc_sendTransaction
- mc_sendRawTransaction
- mc_call
- mc_estimateGas
- mc_getBlockByHash
- mc_getBlockByNumber
- mc_getTransactionByHash
- mc_getTransactionByBlockHashAndIndex
- mc_getTransactionByBlockNumberAndIndex
- mc_getTransactionReceipt
- mc_getUncleByBlockHashAndIndex
- mc_getUncleByBlockNumberAndIndex
- mc_newFilter
- mc_newBlockFilter
- mc_newPendingTransactionFilter
- mc_uninstallFilter
- mc_getFilterChanges
- mc_getFilterLogs
- mc_getLogs
- mc_getWork
- mc_submitWork
- vnode
- scs
- scs_directcall
- scs_getblock
- scs_getBlockNumber
- scs_getDappList
- scs_getDappState
- scs_getMicroChainInfo
- scs_getMicroChainList
- scs_getNonce
- scs_getSCSId
- scs_getTransactionByHash
- scs_getTransactionByNonce
- scs_getReceiptByHash
- scs_getReceiptByNonce
- scs_getExchangeByAddress
- scs_getExchangeInfo
- scs_getTxpool
CHAIN3¶
Chain3_clientVersion
Returns the current client version.
Parameters
none
Returns
String
- The current client version
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"chain3_clientVersion","params":[],"id":101}' 'localhost:8545'
// Result
{
"jsonrpc":"2.0",
"id":101,
"result":"Moac/v0.8.3-release-ad500ab5/darwin-amd64/go1.10"
}
Chain3_sha3
返回输入数据的 Keccak-256 (not the standardized SHA3-256) 哈希值(HASH).
Parameters
DATA
- the data to convert into a SHA3 hash
params: [
"0x68656c6c6f20776f726c64"
]
Returns
DATA
- The SHA3 result of the given string.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"chain3_sha3","params":["0x68656c6c6f20776f726c64"],"id":101}' localhost:8545
// Result
{
"jsonrpc":"2.0",
"id":101,
"result":"0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad"
}
NET¶
net_version
返回当前网络 ID,墨客网络主网为99, 测试网为101,本地调试私网默认为100.
Parameters
none
Returns
String
- The current network id. - "99"
: MOAC Mainnet -
"101"
: MOAC Testnet - "100"
: Devnet
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"net_version","params":[],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "101"
}
net_listening
Returns true
if client is actively listening for network
connections.
Parameters
none
Returns
Boolean
- true
when listening, otherwise false
.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"net_listening","params":[],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc":"2.0",
"result":true
}
net_peerCount
Returns number of peers currently connected to the client.
Parameters
none
Returns
QUANTITY
- integer of the number of connected peers.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":101}' localhost:8545
// Result
{
"id":74,
"jsonrpc": "2.0",
"result": "0x4" // 4 net peers are connecting
}
MC¶
mc_protocolVersion
Returns the current MOAC protocol version.
Parameters
none
Returns
String
- The current MOAC protocol version
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_protocolVersion","params":[],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0x3f"
}
mc_syncing
Returns an object with data about the sync status or false
.
Parameters
none
Returns
Object|Boolean
, An object with sync status data or FALSE
, when
not syncing:
startingBlock
:QUANTITY
- The block at which the
import started (will only be reset, after the sync reached his head) -
currentBlock
: QUANTITY
- The current block, same as
mc_blockNumber - highestBlock
: QUANTITY
- The estimated highest
block
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_syncing","params":[],"id":101}' localhost:8545
// Result
{
"id":1,
"jsonrpc": "2.0",
"result": {
startingBlock: '0x384',
currentBlock: '0x386',
highestBlock: '0x454'
}
}
// Or when not syncing
{
"id":101,
"jsonrpc": "2.0",
"result": false
}
mc_coinbase
Returns the client coinbase address.
Parameters
none
Returns
DATA
, 20 bytes - the current coinbase address.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_coinbase","params":[],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0x407d73d8a49eeb85d32cf465507dd71d507100c1"
}
mc_mining
Returns true
if client is actively mining new blocks.
Parameters
none
Returns
Boolean
- returns true
of the client is mining, otherwise
false
.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_mining","params":[],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": true
}
mc_hashrate
Returns the number of hashes per second that the node is mining with.
Parameters
none
Returns
QUANTITY
- number of hashes per second.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_hashrate","params":[],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0x38a"
}
mc_gasPrice
Returns the current price per gas in sha.
Parameters
none
Returns
QUANTITY
- integer of the current gas price in sha.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_gasPrice","params":[],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0x09184e72a000" // 10000000000000
}
mc_accounts
Returns a list of addresses owned by client.
Parameters
none
Returns
Array of DATA
, 20 Bytes - addresses owned by the client.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_accounts","params":[],"id":101}' localhost:8545
// Result
{
"id":1,
"jsonrpc": "2.0",
"result": ["0x407d73d8a49eeb85d32cf465507dd71d507100c1","0x87dc9d8014e189b9d32c622a9ad1d02f72383979"]
}
mc_blockNumber
Returns the number of most recent block.
Parameters
none
Returns
QUANTITY
- integer of the current block number the client is on.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_blockNumber","params":[],"id":101}' 'localhost:8545'
// Result
{
"id":83,
"jsonrpc": "2.0",
"result": "0x4b7" // 1207
}
mc_getBalance
Returns the balance of the account of given address.
Parameters
DATA
, 20 Bytes - address to check for balance.QUANTITY|TAG
- integer block number, or the string"latest"
,"earliest"
or"pending"
, see the default block parameter <#the-default-block-parameter>
params: [
'0x407d73d8a49eeb85d32cf465507dd71d507100c1',
'latest'
]
Returns
QUANTITY
- integer of the current balance in sha.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getBalance","params":["0x87dc9d8014e189b9d32c622a9ad1d02f72383979", "latest"],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0x12f8b3a319c000" // 5340000000000000
}
mc_getStorageAt
Returns the value from a storage position at a given address.
Parameters
DATA
, 20 Bytes - address of the storage.QUANTITY
- integer of the position in the storage.QUANTITY|TAG
- integer block number, or the string"latest"
,"earliest"
or"pending"
, see the default block parameter <#the-default-block-parameter>
Returns
DATA
- the value at this storage position.
Example
Calculating the correct position depends on the storage to retrieve.
Consider the following contract deployed at
0x02701dc451e126316ece6870fd70ea140efa7b15
by address
0xa8863fc8ce3816411378685223c03daae9770ebb
.
contract Storage {
uint pos0;
mapping(address => uint) pos1;
function Storage() {
pos0 = 1234;
pos1[msg.sender] = 5678;
}
}
Retrieving the value of pos0 is straight forward:
curl -X POST --data '{"jsonrpc":"2.0", "method": "mc_getStorageAt", "params": ["0x02701dc451e126316ece6870fd70ea140efa7b15", "0x0", "latest"], "id": 101}' localhost:8545
{"jsonrpc":"2.0","id":1,"result":"0x00000000000000000000000000000000000000000000000000000000000004d2"}
Retrieving an element of the map is harder. The position of an element in the map is calculated with:
keccack(LeftPad32(key, 0), LeftPad32(map position, 0))
This means to retrieve the storage on pos1[“0x391694e7e0b0cce554cb130d723a9d27458f9298”] we need to calculate the position with:
keccak(decodeHex("000000000000000000000000391694e7e0b0cce554cb130d723a9d27458f9298" + "0000000000000000000000000000000000000000000000000000000000000001"))
The moac console which comes with the chain3 library can be used to make the calculation:
> var key = "000000000000000000000000391694e7e0b0cce554cb130d723a9d27458f9298" + "0000000000000000000000000000000000000000000000000000000000000001"
undefined
> chain3.sha3(key, {"encoding": "hex"})
"0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9"
Now to fetch the storage:
curl -X POST --data '{"jsonrpc":"2.0", "method": "mc_getStorageAt", "params": ["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9", "latest"], "id": 101}' localhost:8545
{"jsonrpc":"2.0","id":101,"result":"0x000000000000000000000000000000000000000000000000000000000000162e"}
mc_getTransactionCount
Returns the number of transactions sent from an address.
Parameters
DATA
, 20 Bytes - address.QUANTITY|TAG
- integer block number, or the string"latest"
,"earliest"
or"pending"
, see the default block parameter <#the-default-block-parameter>
params: [
'0x407d73d8a49eeb85d32cf465507dd71d507100c1',
'latest' // state at the latest block
]
Returns
QUANTITY
- integer of the number of transactions send from this
address.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getTransactionCount","params":["0x57d83802a772adf506a89f5021c93a05749e3c6e","latest"],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0x29" // 41
}
mc_getBlockTransactionCountByHash
Returns the number of transactions in a block from a block matching the given block hash.
Parameters
DATA
, 32 Bytes - hash of a block
params: [
'0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238'
]
Returns
QUANTITY
- integer of the number of transactions in this block.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getBlockTransactionCountByHash","params":["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],"id":101}' localhost:8545
// Result
{
"id":1,
"jsonrpc": "2.0",
"result": "0xb" // 11
}
mc_getBlockTransactionCountByNumber
Returns the number of transactions in a block matching the given block number.
Parameters
QUANTITY|TAG
- integer of a block number, or the string"earliest"
,"latest"
or"pending"
, as in the default block parameter <#the-default-block-parameter>.
params: [
'0xe8', // 232
]
Returns
QUANTITY
- integer of the number of transactions in this block.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getBlockTransactionCountByNumber","params":["0xe8"],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0xa" // 10
}
mc_getUncleCountByBlockHash
Returns the number of uncles in a block from a block matching the given block hash.
Parameters
DATA
, 32 Bytes - hash of a block
params: [
'0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238'
]
Returns
QUANTITY
- integer of the number of uncles in this block.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getUncleCountByBlockHash","params":["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0x1" // 1
}
mc_getUncleCountByBlockNumber
Returns the number of uncles in a block from a block matching the given block number.
Parameters
QUANTITY|TAG
- integer of a block number, or the string “latest”, “earliest” or “pending”, see the default block parameter <#the-default-block-parameter>
params: [
'0xe8', // 232
]
Returns
QUANTITY
- integer of the number of uncles in this block.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getUncleCountByBlockNumber","params":["0xe8"],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0x1" // 1
}
mc_getCode
Returns code at a given address.
Parameters
DATA
, 20 Bytes - addressQUANTITY|TAG
- integer block number, or the string"latest"
,"earliest"
or"pending"
, see the default block parameter <#the-default-block-parameter>
params: [
'0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b',
'0x2' // 2
]
Returns
DATA
- the code from the given address.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getCode","params":["0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x2"],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0x600160008035811a818181146012578301005b601b6001356025565b8060005260206000f25b600060078202905091905056"
}
mc_sign
The sign method calculates an MOAC specific signature with:
sign(keccak256("\x19MOAC Signed Message:\n" + len(message) + message)))
.
By adding a prefix to the message makes the calculated signature recognisable as an MOAC specific signature. This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to impersonate the victim.
Note the address to sign with must be unlocked.
Parameters
account, message
DATA
, 20 Bytes - addressDATA
, N Bytes - message to sign
Returns
DATA
: Signature
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_sign","params":["0x57d83802a772adf506a89f5021c93a05749e3c6e", "0xdeadbeaf"],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0xefa354f816ab378a7da6ec25afe9e6393b72a3c06b2d08550815cc43d1993f6c58afbf228559df6a39ac419bef847ca2dc3047886df6a0f06a4c5e6a4e2dc9a61c"
}
An example how to use solidity ecrecover to verify the signature calculated with :ref:`mc_sign` can be found here <https://gist.github.com/bas-vk/d46d83da2b2b4721efb0907aecdb7ebd>. The contract is deployed on the testnet Ropsten and Rinkeby.
mc_sendTransaction
Creates new message call transaction or a contract creation, if the data field contains code.
Note the address to sign with must be unlocked.
Parameters
Object
- The transaction object
from
:DATA
, 20 Bytes - The address the transaction is send from.to
:DATA
, 20 Bytes - (optional when creating new contract) The address the transaction is directed to.gas
:QUANTITY
- (optional, default: 90000) Integer of the gas provided for the transaction execution. It will return unused gas.gasPrice
:QUANTITY
- (optional, default: To-Be-Determined) Integer of the gasPrice used for each paid gasvalue
:QUANTITY
- (optional) Integer of the value sent with this transactiondata
:DATA
- The compiled code of a contract OR the hash of the invoked method signature and encoded parameters. MOAC used the solidity ABI. For details see Ethereum Contract ABI <https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI>nonce
:QUANTITY
- (optional) Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce.
params: [{
"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
"to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
"gas": "0x76c0", // 30400
"gasPrice": "0x9184e72a000", // 10000000000000
"value": "0x9184e72a", // 2441406250
"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
}]
Returns
DATA
, 32 Bytes - the transaction hash, or the zero hash if the
transaction is not yet available.
Use mc_getTransactionReceipt to get the contract address, after the transaction was mined, when you created a contract.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_sendTransaction","params":[{see above}],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331"
}
mc_sendRawTransaction
Creates new message call transaction or a contract creation for signed transactions.
Parameters
DATA
, The signed transaction data.
params: ["0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"]
Returns
DATA
, 32 Bytes - the transaction hash, or the zero hash if the
transaction is not yet available.
Use mc_getTransactionReceipt to get the contract address, after the transaction was mined, when you created a contract.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_sendRawTransaction","params":[{see above}],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331"
}
mc_call
Executes a new message call immediately without creating a transaction on the block chain.
Parameters
Object
- The transaction call object
from
:DATA
, 20 Bytes - (optional) The address the transaction is sent from.to
:DATA
, 20 Bytes - The address the transaction is directed to.gas
:QUANTITY
- (optional) Integer of the gas provided for the transaction execution. mc_call consumes zero gas, but this parameter may be needed by some executions.gasPrice
:QUANTITY
- (optional) Integer of the gasPrice used for each paid gasvalue
:QUANTITY
- (optional) Integer of the value sent with this transactiondata
:DATA
- (optional) Hash of the method signature and encoded parameters. For details see Ethereum Contract ABI <https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI>
QUANTITY|TAG
- integer block number, or the string"latest"
,"earliest"
or"pending"
, see the default block parameter <#the-default-block-parameter>
Returns
DATA
- the return value of executed contract.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_call","params":[{see above}],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0x"
}
mc_estimateGas
Generates and returns an estimate of how much gas is necessary to allow the transaction to complete. The transaction will not be added to the blockchain. Note that the estimate may be significantly more than the amount of gas actually used by the transaction, for a variety of reasons including EVM mechanics and node performance.
Parameters
See mc_call parameters, expect that all properties are optional. If no gas limit is specified moac uses the block gas limit from the pending block as an upper bound. As a result the returned estimate might not be enough to executed the call/transaction when the amount of gas is higher than the pending block gas limit.
Returns
QUANTITY
- the amount of gas used.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_estimateGas","params":[{see above}],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0x5208" // 21000
}
mc_getBlockByHash
Returns information about a block by hash.
Parameters
DATA
, 32 Bytes - Hash of a block.Boolean
- Iftrue
it returns the full transaction objects, iffalse
only the hashes of the transactions.
params: [
'0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331',
true
]
Returns
Object
- A block object, or null
when no block was found:
number
:QUANTITY
- the block number.null
when its pending block.hash
:DATA
, 32 Bytes - hash of the block.null
when its pending block.parentHash
:DATA
, 32 Bytes - hash of the parent block.nonce
:DATA
, 8 Bytes - hash of the generated proof-of-work.null
when its pending block.sha3Uncles
:DATA
, 32 Bytes - SHA3 of the uncles data in the block.logsBloom
:DATA
, 256 Bytes - the bloom filter for the logs of the block.null
when its pending block.transactionsRoot
:DATA
, 32 Bytes - the root of the transaction trie of the block.stateRoot
:DATA
, 32 Bytes - the root of the final state trie of the block.receiptsRoot
:DATA
, 32 Bytes - the root of the receipts trie of the block.miner
:DATA
, 20 Bytes - the address of the beneficiary to whom the mining rewards were given.difficulty
:QUANTITY
- integer of the difficulty for this block.totalDifficulty
:QUANTITY
- integer of the total difficulty of the chain until this block.extraData
:DATA
- the “extra data” field of this block.size
:QUANTITY
- integer the size of this block in bytes.gasLimit
:QUANTITY
- the maximum gas allowed in this block.gasUsed
:QUANTITY
- the total used gas by all transactions in this block.timestamp
:QUANTITY
- the unix timestamp for when the block was collated.transactions
:Array
- Array of transaction objects, or 32 Bytes transaction hashes depending on the last given parameter.uncles
:Array
- Array of uncle hashes.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getBlockByHash","params":["0x9d88f2a2a348eec743b149f461fddcf0843d3920ddf998896672cee476b99127", true],"id":101}' localhost:8545
// Result
{
"jsonrpc":"2.0",
"id":101,
"result":{
"difficulty":"0x9ad5136",
"extraData":"0xdd854d4f41432d85302e382e332d87676f312e382e338777696e646f7773",
"gasLimit":"0x895440",
"gasUsed":"0x0",
"hash":"0x9d88f2a2a348eec743b149f461fddcf0843d3920ddf998896672cee476b99127",
"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner":"0x0a2168d2f08161c01745fec4e6e8fe06f314ab41",
"mixHash":"0xd6e9f8d36f8f0f57abff5ccf6390ece4d5a14eb624779628fd6e6119451589e2",
"nonce":"0x423e7acb4d05a23c",
"number":"0x4803d",
"parentHash":"0xc494dbda1ef4f673fd14fc487a1346a7747a41910d1a1f0e72d6e0e660c0e792",
"receiptsRoot":"0x9287370eb27f11b0c2188431cbc58a23b685f02dbd851ed4d974f932bd780839",
"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size":"0x24e",
"stateRoot":"0xff791a26fd0cb6addfe4bec0287b3905bf44898f0fd71e446cb1385f94333e18",
"timestamp":"0x5b1f3a14",
"totalDifficulty":"0x325dc638b38e",
"transactions":[{"blockHash":"0x9d88f2a2a348eec743b149f461fddcf0843d3920ddf998896672cee476b99127","blockNumber":"0x4803d","from":"0x0000000000000000000000000000000000000064","gas":"0x0","gasPrice":"0x4a817c800","hash":"0x52ccd05bdfb137fcbb6154f1cb7c006ba53cd8ce80511841d2e7b3c6324d49df","input":"0xc1c0e9c4","nonce":"0x4803c","syscnt":"0x65","to":"0x0000000000000000000000000000000000000065","transactionIndex":"0x0","value":"0x0","v":"0x0","r":"0x0","s":"0x0","shardingFlag":"0x0"}],
"transactionsRoot":"0xa29e25d8e3db000e44122a594cc52a7bf050850b3a7e028fd54cb83784fc1bc3",
"uncles":[]
}
}
mc_getBlockByNumber
Returns information about a block by block number.
Parameters
QUANTITY|TAG
- integer of a block number, or the string"earliest"
,"latest"
or"pending"
, as in the default block parameter <#the-default-block-parameter>.Boolean
- Iftrue
it returns the full transaction objects, iffalse
only the hashes of the transactions.
params: [
'0x1b4', // 436
true
]
Returns
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getBlockByNumber","params":["0x1b4", true],"id":101}' localhost:8545
Result see mc_getBlockByHash
mc_getTransactionByHash
Returns the information about a transaction requested by transaction hash.
Parameters
DATA
, 32 Bytes - hash of a transaction
params: [
"0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"
]
Returns
Object
- A transaction object, or null
when no transaction was
found:
hash
:DATA
, 32 Bytes - hash of the transaction.nonce
:QUANTITY
- the number of transactions made by the sender prior to this one.blockHash
:DATA
, 32 Bytes - hash of the block where this transaction was in.null
when its pending.blockNumber
:QUANTITY
- block number where this transaction was in.null
when its pending.transactionIndex
:QUANTITY
- integer of the transactions index position in the block.null
when its pending.from
:DATA
, 20 Bytes - address of the sender.to
:DATA
, 20 Bytes - address of the receiver.null
when its a contract creation transaction.value
:QUANTITY
- value transferred in Wei.gasPrice
:QUANTITY
- gas price provided by the sender in Wei.gas
:QUANTITY
- gas provided by the sender.input
:DATA
- the data send along with the transaction.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getTransactionByHash","params":["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc":"2.0",
"result": {
"hash":"0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b",
"nonce":"0x",
"blockHash": "0xbeab0aa2411b7ab17f30a99d3cb9c6ef2fc5426d6ad6fd9e2a26a6aed1d1055b",
"blockNumber": "0x15df", // 5599
"transactionIndex": "0x1", // 1
"from":"0x407d73d8a49eeb85d32cf465507dd71d507100c1",
"to":"0x85h43d8a49eeb85d32cf465507dd71d507100c1",
"value":"0x7f110", // 520464
"gas": "0x7f110", // 520464
"gasPrice":"0x09184e72a000",
"input":"0x603880600c6000396000f300603880600c6000396000f3603880600c6000396000f360",
}
}
mc_getTransactionByBlockHashAndIndex
Returns information about a transaction by block hash and transaction index position.
Parameters
DATA
, 32 Bytes - hash of a block.QUANTITY
- integer of the transaction index position.
params: [
'0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331',
'0x0' // 0
]
Returns
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getTransactionByBlockHashAndIndex","params":["0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b", "0x0"],"id":101}' localhost:8545
Result see mc_getTransactionByHash
mc_getTransactionByBlockNumberAndIndex
Returns information about a transaction by block number and transaction index position.
Parameters
QUANTITY|TAG
- a block number, or the string"earliest"
,"latest"
or"pending"
, as in the default block parameter <#the-default-block-parameter>.QUANTITY
- the transaction index position.
params: [
'0x29c', // 668
'0x0' // 0
]
Returns
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getTransactionByBlockNumberAndIndex","params":["0x29c", "0x0"],"id":101}' localhost:8545
Result see mc_getTransactionByHash
mc_getTransactionReceipt
Returns the receipt of a transaction by transaction hash.
Note That the receipt is not available for pending transactions.
Parameters
DATA
, 32 Bytes - hash of a transaction
params: [
'0x7bb694c3462764cb113e9b742faaf06adc728e70b607f8b7aa95207ee32b1c5e'
]
Returns
Object
- A transaction receipt object, or null
when no receipt
was found:
transactionHash
:DATA
, 32 Bytes - hash of the transaction.transactionIndex
:QUANTITY
- integer of the transactions index position in the block.blockHash
:DATA
, 32 Bytes - hash of the block where this transaction was in.blockNumber
:QUANTITY
- block number where this transaction was in.cumulativeGasUsed
:QUANTITY
- The total amount of gas used when this transaction was executed in the block.gasUsed
:QUANTITY
- The amount of gas used by this specific transaction alone.contractAddress
:DATA
, 20 Bytes - The contract address created, if the transaction was a contract creation, otherwisenull
.logs
:Array
- Array of log objects, which this transaction generated.logsBloom
:DATA
, 256 Bytes - Bloom filter for light clients to quickly retrieve related logs.
It also returns either :
root
:DATA
32 bytes of post-transaction stateroot (pre Byzantium)status
:QUANTITY
either1
(success) or0
(failure)
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getTransactionReceipt","params":["0x7bb694c3462764cb113e9b742faaf06adc728e70b607f8b7aa95207ee32b1c5e"],"id":101}' localhost:8545
// Result
{
{"jsonrpc":"2.0",
"id":101,
"result":{
"blockHash":"0xad7d2eec610b3e04ea4676c11a3184cb07df43ed7ab717f331d3c952fc1b55cf",
"blockNumber":"0x1b943",
"contractAddress":"0xf2f4eec6c2adfcf780aae828de0b25f86506ffae",
"cumulativeGasUsed":"0x1b337c",
"from":"0x7312f4b8a4457a36827f185325fd6b66a3f8bb8b",
"gasUsed":"0x1b337c",
"logs":[],
"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status":"0x1",
"to":null,
"transactionHash":"0x7bb694c3462764cb113e9b742faaf06adc728e70b607f8b7aa95207ee32b1c5e",
"transactionIndex":"0x1"}
}
mc_getUncleByBlockHashAndIndex
Returns information about a uncle of a block by hash and uncle index position.
Parameters
DATA
, 32 Bytes - hash a block.QUANTITY
- the uncle’s index position.
params: [
'0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b',
'0x0' // 0
]
Returns
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getUncleByBlockHashAndIndex","params":["0x696d389aa9b6b44e08af9f3528c51587aac435b75a54ece42f4b2d1289043497", "0x0"],"id":101}' localhost:8545
Result see mc_getBlockByHash
Note: An uncle doesn’t contain individual transactions.
mc_getUncleByBlockNumberAndIndex
Returns information about a uncle of a block by number and uncle index position.
Parameters
QUANTITY|TAG
- a block number, or the string"earliest"
,"latest"
or"pending"
, as in the default block parameter <#the-default-block-parameter>.QUANTITY
- the uncle’s index position.
params: [
'0x29c', // 668
'0x0' // 0
]
Returns
Note: An uncle doesn’t contain individual transactions.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getUncleByBlockNumberAndIndex","params":["0x29c", "0x0"],"id":101}' localhost:8545
Result see mc_getBlockByHash
mc_newFilter
Creates a filter object, based on filter options, to notify when the state changes (logs). To check if the state has changed, call mc_getFilterChanges.
*A note on specifying topic filters:*
Topics are order-dependent. A transaction with a log with topics [A, B]
will be matched by the following topic filters: * []
“anything” *
[A]
“A in first position (and anything after)” * [null, B]
“anything in first position AND B in second position (and anything
after)” * [A, B]
“A in first position AND B in second position (and
anything after)” * [[A, B], [A, B]]
“(A OR B) in first position AND
(A OR B) in second position (and anything after)”
Parameters
Object
- The filter options:
fromBlock
:QUANTITY|TAG
- (optional, default:"latest"
) Integer block number, or"latest"
for the last mined block or"pending"
,"earliest"
for not yet mined transactions.toBlock
:QUANTITY|TAG
- (optional, default:"latest"
) Integer block number, or"latest"
for the last mined block or"pending"
,"earliest"
for not yet mined transactions.address
:DATA|Array
, 20 Bytes - (optional) Contract address or a list of addresses from which logs should originate.topics
:Array of DATA
, - (optional) Array of 32 BytesDATA
topics. Topics are order-dependent. Each topic can also be an array of DATA with “or” options.
params: [{
"fromBlock": "0x1",
"toBlock": "0x2",
"address": "0x8888f1f195afa192cfee860698584c030f4c9db1",
"topics": ["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", null, ["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x0000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebccc"]]
}]
Returns
QUANTITY
- A filter id.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_newFilter","params":[{"topics":["0x12341234"]}],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0x1" // 1
}
mc_newBlockFilter
Creates a filter in the node, to notify when a new block arrives. To check if the state has changed, call mc_getFilterChanges.
Parameters
None
Returns
QUANTITY
- A filter id.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_newBlockFilter","params":[],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0x244afc5c2cb35b24c5b91bba7f7ab19d" // 1
}
mc_newPendingTransactionFilter
Creates a filter in the node, to notify when new pending transactions arrive. To check if the state has changed, call mc_getFilterChanges.
Parameters
None
Returns
QUANTITY
- A filter id.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_newPendingTransactionFilter","params":[],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0x1" // 1
}
mc_uninstallFilter
Uninstalls a filter with given id. Should always be called when watch is no longer needed. Additonally Filters timeout when they aren’t requested with mc_getFilterChanges for a period of time.
Parameters
QUANTITY
- The filter id.
params: [
"0xb" // 11
]
Returns
Boolean
- true
if the filter was successfully uninstalled,
otherwise false
.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_uninstallFilter","params":["0xb"],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": true
}
mc_getFilterChanges
Polling method for a filter, which returns an array of logs which occurred since last poll.
Parameters
QUANTITY
- the filter id.
params: [
"0x16" // 22
]
Returns
Array
- Array of log objects, or an empty array if nothing has
changed since last poll.
- For filters created with :ref:`mc_newBlockFilter` the return are block
hashes (
DATA
, 32 Bytes), e.g.["0x3454645634534..."]
. - For filters created with :ref:`mc_newPendingTransactionFilter` the
return are transaction hashes (
DATA
, 32 Bytes), e.g.["0x6345343454645..."]
. - For filters created with :ref:`mc_newFilter` logs are objects with following params:
removed
:TAG
-true
when the log was removed, due to a chain reorganization.false
if its a valid log.logIndex
:QUANTITY
- integer of the log index position in the block.null
when its pending log.transactionIndex
:QUANTITY
- integer of the transactions index position log was created from.null
when its pending log.transactionHash
:DATA
, 32 Bytes - hash of the transactions this log was created from.null
when its pending log.blockHash
:DATA
, 32 Bytes - hash of the block where this log was in.null
when its pending.null
when its pending log.blockNumber
:QUANTITY
- the block number where this log was in.null
when its pending.null
when its pending log.address
:DATA
, 20 Bytes - address from which this log originated.data
:DATA
- contains one or more 32 Bytes non-indexed arguments of the log.topics
:Array of DATA
- Array of 0 to 4 32 BytesDATA
of indexed log arguments. (In solidity: The first topic is the hash of the signature of the event (e.g.Deposit(address,bytes32,uint256)
), except you declared the event with theanonymous
specifier.)
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getFilterChanges","params":["0x16"],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc":"2.0",
"result": [{
"logIndex": "0x1", // 1
"blockNumber":"0x1b4", // 436
"blockHash": "0x8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcfdf829c5a142f1fccd7d",
"transactionHash": "0xdf829c5a142f1fccd7d8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcf",
"transactionIndex": "0x0", // 0
"address": "0x16c5785ac562ff41e2dcfdf829c5a142f1fccd7d",
"data":"0x0000000000000000000000000000000000000000000000000000000000000000",
"topics": ["0x59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a5"]
},{
...
}]
}
mc_getFilterLogs
Returns an array of all logs matching filter with given id.
Parameters
QUANTITY
- The filter id.
params: [
"0x16" // 22
]
Returns
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getFilterLogs","params":["0x16"],"id":101}' localhost:8545
Result see mc_getFilterChanges
mc_getLogs
Returns an array of all logs matching a given filter object.
Parameters
Object
- the filter object, see mc_newFilter parameters.
params: [{
"topics": ["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b"]
}]
Returns
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getLogs","params":[{"topics":["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b"]}],"id":101}'
Result see mc_getFilterChanges
mc_getWork
Returns the hash of the current block, the seedHash, and the boundary condition to be met (“target”).
Parameters
none
Returns
Array
- Array with the following properties: 1. DATA
, 32 Bytes -
current block header pow-hash 2. DATA
, 32 Bytes - the seed hash used
for the DAG. 3. DATA
, 32 Bytes - the boundary condition (“target”),
2^256 / difficulty.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"mc_getWork","params":[],"id":101}' localhost:8545
// Result
{
"jsonrpc":"2.0",
"id":101,
"result":["0x367ebe7ed77dde0a4cc134adaa769f93a833e08a86a0d38ab18e32cc3740b5f8","0x9b2baad7528ecec612c5751a6bd525905892d7892e155c3b05e61363154a940b","0x0000001dd67ebb66a2c0fc63b9907077f70b5315e1780a8b74f33d40e2a9a7e4"]
}
mc_submitWork
Used for submitting a proof-of-work solution.
Parameters
DATA
, 8 Bytes - The nonce found (64 bits)DATA
, 32 Bytes - The header’s pow-hash (256 bits)DATA
, 32 Bytes - The mix digest (256 bits)
params: [
"0x0000000000000001",
"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"0xD1FE5700000000000000000000000000D1FE5700000000000000000000000000"
]
Returns
Boolean
- returns true
if the provided solution is valid,
otherwise false
.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0", "method":"mc_submitWork", "params":["0x0000000000000001", "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", "0xD1GE5700000000000000000000000000D1GE5700000000000000000000000000"],"id":101}'
// Result
{
"id":101,
"jsonrpc":"2.0",
"result": true
}
VNODE¶
vnode_address
Returns the VNODE benificial address. This is needed for SCS to use in the communication.
Parameters
none
Returns
address
: DATA
, 20 Bytes - address from which the VNODE settings
in the vnodeconfig.json file.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"vnode_address","params":[],"id":101}' localhost:8545
// Result
{
"jsonrpc":"2.0",
"id":101,
"result":"0xa8863fc8ce3816411378685223c03daae9770ebb"
}
vnode_scsService
Returns if the VNODE enable the service for SCS servers.
Parameters
none
Returns
Bool
- true, enable the SCS service; false, not open.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"vnode_scsService","params":[],"id":101}' 'localhost:8545'
// Result
{
"jsonrpc":"2.0",
"id":101,
"result":true
}
vnode_serviceCfg
Returns the VNODE SCS service ports for connecting with.
Parameters
none
Returns
String
- The current service port set in the vnodeconfig.json.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"vnode_serviceCfg","params":[],"id":101}' 'localhost:8545'
// Result
{
"jsonrpc":"2.0",
"id":101,
"result":":50062"
}
vnode_showToPublic
Returns if the VNODE enable the public view.
Parameters
none
Returns
Bool
- true, open to the public; false, not open.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"vnode_showToPublic","params":[],"id":101}' 'localhost:8545'
// Result
{
"jsonrpc":"2.0",
"id":101,
"result":true
}
vnode_vnodeIP
Returns VNODE IP for users to access. Note for cloud servers, this could be different from the cloud server IP.
Parameters
none
Returns
String
- The current IP that can be used to access. This is set in
the vnodeconfig.json.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"vnode_vnodeIP","params":[],"id":101}' 'localhost:8545'
// Result
{
"jsonrpc":"2.0",
"id":101,
"result":"127.0.0.1"
}
SCS¶
scs_directCall
Executes a new constant call of the MicroChain Dapp function without creating a transaction on the MicroChain. This RPC call is used by API/lib to call MicroChain Dapp functions.
Parameters
Object
- The transaction call object
- from
: DATA
, 20 Bytes - (optional) The address the transaction is sent from.
- to
: DATA
, 20 Bytes - The address the transaction is directed to. This
parameter is the MicroChain address.
- data
: DATA
- (optional) Hash of the method signature and encoded parameters. For details see
Ethereum Contract ABI <https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI>
Returns
DATA
- the return value of executed Dapp constant function call.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"scs_directCall","params":[{see above}],"id":101}' localhost:8545
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0x"
}
scs_getBlock
Returns information about a block on the MicroChain by block number.
Parameters
String
- the address of the MicroChain that Dapp is on.QUANTITY|TAG
- integer of a block number, or the string"earliest"
or"latest"
, as in the default block parameter <#the-default-block-parameter>. Note, scs_getBlock does not support"pending"
.
Returns
DATA
- Data in the block on the MicroChain.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"scs_getBlock","params":["0x9d711986ccc8c89db2dfaf0894acadeb5a383ee8","0x1"],"id":101}' localhost:8548
// Result
{"jsonrpc":"2.0","id":101,"result":{"extraData":"0x","hash":"0xc80cbe08bc266b1236f22a8d0b310faae3135961dbef6ad8b6ad4e8cd9537309","number":"0x1","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","stateRoot":"0x1a065207da60d8e7a44db2f3b5ed9d3e81052a3059e4108c84701d0bf6a62292","timestamp":"0x0","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"}}
scs_getBlockList
Returns information about multiple MicroChain blocks by block number.
Parameters
String
- the address of the MicroChain that Dapp is on.QUANTITY
- integer of the start block number.QUANTITY
- integer of the end block number, need to be larger or equal the start block number.
Returns
ARRAY
- Array of the block infromation on the MicroChain.
Example
// Request
curl -X POST --data curl -X POST --data '{"jsonrpc":"2.0","method":"scs_getBlock","params":["0x9d711986ccc8c89db2dfaf0894acadeb5a383ee8","0x370", "0x373"],"id":101}' localhost:8548
// Result
{"jsonrpc":"2.0","id":101,"result":{"blockList":[{"extraData":"0x","hash":"0x56075838e0fffe6576add14783b957239d4f3c57989bc3a7b7728a3b57eb305a","miner":"0xecd1e094ee13d0b47b72f5c940c17bd0c7630326","number":"0x370","parentHash":"0x56352a3a8bd0901608041115817204cbce943606e406d233d7d0359f449bd4c2","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","stateRoot":"0xde741a2f6b4a3c865e8f6fc9ba11eadaa1fa04c61d660bcdf0fa1195029699f6","timestamp":"0x5bfb7c1c","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"},{"extraData":"0x","hash":"0xbc3f5791ec039cba99c37310a4f30a68030dd2ab79efb47d23fd9ac5343f54e5","miner":"0xecd1e094ee13d0b47b72f5c940c17bd0c7630326","number":"0x371","parentHash":"0x56075838e0fffe6576add14783b957239d4f3c57989bc3a7b7728a3b57eb305a","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","stateRoot":"0xde741a2f6b4a3c865e8f6fc9ba11eadaa1fa04c61d660bcdf0fa1195029699f6","timestamp":"0x5bfb7c3a","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"},{"extraData":"0x","hash":"0x601be17c47cb4684053457d1d5f70a6dbeb853b27cda08d160555f857f2da33b","miner":"0xecd1e094ee13d0b47b72f5c940c17bd0c7630326","number":"0x372","parentHash":"0xbc3f5791ec039cba99c37310a4f30a68030dd2ab79efb47d23fd9ac5343f54e5","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","stateRoot":"0xde741a2f6b4a3c865e8f6fc9ba11eadaa1fa04c61d660bcdf0fa1195029699f6","timestamp":"0x5bfb7c58","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"},{"extraData":"0x","hash":"0x8a0bea649bcdbd2b525690ff485e56d5a83443e9013fcdccd1a0adee56ba4092","miner":"0xecd1e094ee13d0b47b72f5c940c17bd0c7630326","number":"0x373","parentHash":"0x601be17c47cb4684053457d1d5f70a6dbeb853b27cda08d160555f857f2da33b","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","stateRoot":"0xde741a2f6b4a3c865e8f6fc9ba11eadaa1fa04c61d660bcdf0fa1195029699f6","timestamp":"0x5bfb7c76","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"}],"endBlk":"0x373","microchainAddress":"0x7D0CbA876cB9Da5fa310A54d29F4687f5dd93fD7","startBlk":"0x370"}}
scs_getBlockNumber
Returns the number of most recent block .
Parameters
String
- the address of the MicroChain that Dapp is on.
Returns
QUANTITY
- integer of the current block number the client is on.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"scs_getBlockNumber","params":["0x9d711986ccc8c89db2dfaf0894acadeb5a383ee8"],"id":101}' 'localhost:8545'
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0x4b7" // 1207
}
scs_getDappList
Returns the Dapp addresses on the MicroChain. For nuwa 1.0.8 and later version only,
Parameters
String
- the address of the MicroChain that has Dapps.
Returns
ARRAY
- Array of the DAPP addresses on the MicroChain.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"scs_getDappList","params":[],"id":101}' 'localhost:8545'
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": ["0x9d711986ccc8c89db2dfaf0894acadeb5a383ee8","0x7cfd775c7a97aa632846eff35dcf9dbcf502d0f3"]
}
scs_getDappState
Returns the Dapp state on the MicroChain.
Parameters
String
- the address of the MicroChain that Dapp is on.
Returns
QUANTITY
- 0, no DAPP is deployed on the MicroChain; 1, DAPP is
deployed on the MicroChain.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"scs_getDappState","params":["0x9d711986ccc8c89db2dfaf0894acadeb5a383ee8"],"id":101}' 'localhost:8545'
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": 1
}
Returns the requested MicroChain information on the connecting SCS. This information is the same as the information defined in the MicroChain contract.
Parameters
- String - the address of the MicroChain on the SCS.
Returns
Object
A Micro Chain information object as defined in the MicroChain contract.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"scs_getMicroChainInfo","params":[],"id":101}' 'localhost:8545'
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": {"balance":"0x0","blockReward":"0x1c6bf52634000","bondLimit":"0xde0b6b3a7640000","owner":"0xa8863fc8Ce3816411378685223C03DAae9770ebB","scsList":["0xECd1e094Ee13d0B47b72F5c940C17bD0c7630326","0x50C15fafb95968132d1a6ee3617E99cCa1FCF059","0x1b65cE1A393FFd5960D2ce11E7fd6fDB9e991945"],"txReward":"0x174876e800","viaReward":"0x9184e72a000"}
}
Returns the list of MicroChains on the SCS that is connecting with.
Parameters
None
Returns
Array
- A list of Micro Chain addresses on the SCS.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"scs_getMicroChainList","params":[],"id":101}' 'localhost:8545'
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": ["0x9d711986ccc8c89db2dfaf0894acadeb5a383ee8","0x7cfd775c7a97aa632846eff35dcf9dbcf502d0f3"]
}
scs_getNonce
Returns the account nonce on the MicroChain.
Parameters
String
- the address of the MicroChain that Dapp is on.String
- the address of the accountn.
Returns
QUANTITY
integer of the number of transactions send from this address on the MicroChain;
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"scs_getNonce","params":["0x9d711986ccc8c89db2dfaf0894acadeb5a383ee8", "0x7312F4B8A4457a36827f185325Fd6B66a3f8BB8B"],"id":101}' 'localhost:8545'
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": 1
}
scs_getSCSId
Returns the SCS id.
Parameters
None
Returns
1. String
- SCS id in the scskeystore directory, used for SCS
identification to send deposit and receive MicroChain mining rewards.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"scs_getSCSId","params":[],"id":101}' 'localhost:8545'
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": "0x9d711986ccc8c89db2dfaf0894acadeb5a383ee8"
}
scs_getReceiptByHash
Returns the receipt of a transaction by transaction hash. Note That the receipt is not available for pending transactions.
Parameters
String
- The MicroChain address.String
- The transaction hash.
Returns
Object
- A transaction receipt object, or null when no receipt was
found:.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"scs_getReceiptByHash","params":["0x299afff2da4a57e7e0a0a16bf626f8822b8a3158","0x67bfaa5a704e77a31d5e7eb866f8c662fa8313a7882d13d0d23e377cd66d2a69"],"id":101}' 'localhost:8545'
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": {contractAddress: '0x0a674edac2ccd47ae2a3197ea3163aa81087fbd1',
failed: false,"logs":[{"address":"0x2328537bc943ab1a89fe94a4b562ee7a7b013634","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000a8863fc8ce3816411378685223c03daae9770ebb","0x0000000000000000000000007312f4b8a4457a36827f185325fd6b66a3f8bb8b"],"data":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQ=","blockNumber":0,"transactionHash":"0x67bfaa5a704e77a31d5e7eb866f8c662fa8313a7882d13d0d23e377cd66d2a69","transactionIndex":0,"blockHash":"0x78f092ca81a891ad6c467caa2881d00d8e19c8925ddfd71d793294fbfc5f15fe","logIndex":0,"removed":false}],"logsBloom":"0x00000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000008000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000800000000000080000000000000000000000000002000000000000000000000000000000000000080100002000000000000000000000000000000000000000000000000000000000000000000000000000","status":"0x1","transactionHash":"0x67bfaa5a704e77a31d5e7eb866f8c662fa8313a7882d13d0d23e377cd66d2a69"}
}
scs_getReceiptByNonce
Returns the transaction result by address and nonce on the MicroChain. Note That the nonce is the nonce on the MicroChain. This nonce can be checked using scs_getNonce.
Parameters
1. String
- The MicroChain address.
1. String
- The transaction nonce.
1. QUANTITY
- The nonce of the transaction.
Returns
Object
- A transaction receipt object, or null when no receipt was
found:.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"scs_getReceiptByNonce","params":["0x299afff2da4a57e7e0a0a16bf626f8822b8a3158","0xa8863fc8ce3816411378685223c03daae9770ebb", 0],"id":101}' 'localhost:8545'
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": {contractAddress: '0x0a674edac2ccd47ae2a3197ea3163aa81087fbd1',
failed: false,"logs":[{"address":"0x2328537bc943ab1a89fe94a4b562ee7a7b013634","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000a8863fc8ce3816411378685223c03daae9770ebb","0x0000000000000000000000007312f4b8a4457a36827f185325fd6b66a3f8bb8b"],"data":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQ=","blockNumber":0,"transactionHash":"0x67bfaa5a704e77a31d5e7eb866f8c662fa8313a7882d13d0d23e377cd66d2a69","transactionIndex":0,"blockHash":"0x78f092ca81a891ad6c467caa2881d00d8e19c8925ddfd71d793294fbfc5f15fe","logIndex":0,"removed":false}],"logsBloom":"0x00000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000008000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000800000000000080000000000000000000000000002000000000000000000000000000000000000080100002000000000000000000000000000000000000000000000000000000000000000000000000000","status":"0x1","transactionHash":"0x67bfaa5a704e77a31d5e7eb866f8c662fa8313a7882d13d0d23e377cd66d2a69"}
}
scs_getTransactionByHash
Returns the receipt of a transaction by transaction hash. Note That the receipt is not available for pending transactions.
Parameters
String
- The MicroChain address.String
- The transaction hash.
Returns
Object
- A transaction object, or null when no transaction was found.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"scs_getTransactionByHash","params":["0x299afff2da4a57e7e0a0a16bf626f8822b8a3158","0x67bfaa5a704e77a31d5e7eb866f8c662fa8313a7882d13d0d23e377cd66d2a69"],"id":101}' 'localhost:8545'
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": {contractAddress: '0x0a674edac2ccd47ae2a3197ea3163aa81087fbd1',
failed: false,"logs":[{"address":"0x2328537bc943ab1a89fe94a4b562ee7a7b013634","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000a8863fc8ce3816411378685223c03daae9770ebb","0x0000000000000000000000007312f4b8a4457a36827f185325fd6b66a3f8bb8b"],"data":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQ=","blockNumber":0,"transactionHash":"0x67bfaa5a704e77a31d5e7eb866f8c662fa8313a7882d13d0d23e377cd66d2a69","transactionIndex":0,"blockHash":"0x78f092ca81a891ad6c467caa2881d00d8e19c8925ddfd71d793294fbfc5f15fe","logIndex":0,"removed":false}],"logsBloom":"0x00000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000008000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000800000000000080000000000000000000000000002000000000000000000000000000000000000080100002000000000000000000000000000000000000000000000000000000000000000000000000000","status":"0x1","transactionHash":"0x67bfaa5a704e77a31d5e7eb866f8c662fa8313a7882d13d0d23e377cd66d2a69"}
}
scs_getTransactionByNonce
Returns the receipt of a transaction by transaction hash. Note That the receipt is not available for pending transactions.
Parameters
1. String
- The MicroChain address.
1. String
- The transaction nonce.
1. QUANTITY
- The nonce of the transaction.
Returns
Object
- A transaction receipt object, or null when no receipt was
found:.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"scs_getTransactionByNonce","params":["0x299afff2da4a57e7e0a0a16bf626f8822b8a3158","0x67bfaa5a704e77a31d5e7eb866f8c662fa8313a7882d13d0d23e377cd66d2a69"],"id":101}' 'localhost:8545'
// Result
{
"id":101,
"jsonrpc": "2.0",
"result": {contractAddress: '0x0a674edac2ccd47ae2a3197ea3163aa81087fbd1',
failed: false,"logs":[{"address":"0x2328537bc943ab1a89fe94a4b562ee7a7b013634","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000a8863fc8ce3816411378685223c03daae9770ebb","0x0000000000000000000000007312f4b8a4457a36827f185325fd6b66a3f8bb8b"],"data":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQ=","blockNumber":0,"transactionHash":"0x67bfaa5a704e77a31d5e7eb866f8c662fa8313a7882d13d0d23e377cd66d2a69","transactionIndex":0,"blockHash":"0x78f092ca81a891ad6c467caa2881d00d8e19c8925ddfd71d793294fbfc5f15fe","logIndex":0,"removed":false}],"logsBloom":"0x00000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000008000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000800000000000080000000000000000000000000002000000000000000000000000000000000000080100002000000000000000000000000000000000000000000000000000000000000000000000000000","status":"0x1","transactionHash":"0x67bfaa5a704e77a31d5e7eb866f8c662fa8313a7882d13d0d23e377cd66d2a69"}
scs_getExchangeByAddress
Returns the Withdraw/Deposit exchange records between MicroChain and MotherChain for a certain address. This command returns both the ongoing exchanges and processed exchanges. To check all the ongoing exchanges, please use scs_getExchangeInfo.
Parameters
1. String - The MicroChain address. 1. String - The address to be checked. 1. Int - Index of Deposit records >= 0. 1. Int - Number of Deposit records extracted. 1. Int - Index of Depositing records >= 0. 1. Int - Number of Depositing records extracted. 1. Int - Index of Withdraw records >= 0. 1. Int - Number of Withdraw records extracted. 1. Int - Index of Withdrawing records >= 0. 1. Int - Number of Withdrawing records extracted.
Returns
Object
- A JSON format object contains the token exchange info.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"scs_getExchangeByAddress","params":["0x2e4694875de2a7da9c3186a176c52760d58694e4","0xa8863fc8ce3816411378685223c03daae9770ebb", 0,10,0,10,0,10,0,10],"id":100}' localhost:8548
// Result
{"jsonrpc":"2.0","id":100,"result":{"DepositRecordCount":2,"DepositRecords":[null,null,{"DepositAmt":"0x18abedda5a37000","Deposittime":"0x5c7f03c4"},{"DepositAmt":"0x2bdbb64bc09000","Deposittime":"0x5c7e8aaa"}],"DepositingRecordCount":0,"DepositingRecords":null,"WithdrawRecordCount":0,"WithdrawRecords":null,"WithdrawingRecordCount":0,"WithdrawingRecords":null,"microchain":"0x2e4694875de2a7da9c3186a176c52760d58694e4","sender":"0xa8863fc8ce3816411378685223c03daae9770ebb"}}
scs_getExchangeInfo
Returns the Withdraw/Deposit exchange records between MicroChain and MotherChain for a certain address. This command returns both the ongoing exchanges and processed exchanges. To check all the ongoing exchanges, please use scs_getExchangeInfo.
Parameters
1. String - The MicroChain address. 1. String - The transaction hash. 1. Int - Index of Depositing records >= 0. 1. Int - Number of Depositing records extracted. 1. Int - Index of Withdrawing records >= 0. 1. Int - Number of Withdrawing records extracted.
Returns
Object
- A JSON format object contains the token exchange info.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"scs_getExchangeInfo","params":["0x2e4694875de2a7da9c3186a176c52760d58694e4",0,10,0,10],"id":101}' 'localhost:8545'
// Result
{"jsonrpc":"2.0","id":100,"result":{"DepositingRecordCount":0,"DepositingRecords":null,"WithdrawingRecordCount":0,"WithdrawingRecords":null,"microchain":"0x2e4694875de2a7da9c3186a176c52760d58694e4","scsid":"0x50c15fafb95968132d1a6ee3617e99cca1fcf059"}}
scs_getTxpool
Returns the ongoing transactions in the MicroChain.
Parameters
- String - The MicroChain address.
Returns
Object
- A JSON format object contains two fields pending and queued. Each of these fields are associative arrays, in which each entry maps an origin-address to a batch of scheduled transactions. These batches themselves are maps associating nonces with actual transactions.
Example
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"scs_getTxpool","params":["0x2e4694875de2a7da9c3186a176c52760d58694e4"],"id":101}' 'localhost:8545'
// Result
{"jsonrpc":"2.0","id":100,"result":{"pending":{},"queued":{}}}
Chain3 JavaScript 软件库¶
Chain3 JavaScript 软件库是墨客开发的一套javascript库,目的是让应用程序能够使用简便的方式与墨客节点进行通信。 注意,这里有两层,moac启动了一个墨客母链节点,console参数开启了一个javascript的控制台,这个控制台注入了chain3.js这个库,以使我们可以通过chain3对象与墨客节点的JSON-RPC接口做交互。
开发者可以通过``chain3``对象来对DApp的函数进行调用。chain3 通过 RPC calls 来和母链服务器 VNODE. 但注意要求连接的VNODE服务器打开 RPC 接口:
./moac –rpc –rpcport 8545
chain3
除了包含 mc
对象 - chain3.mc
与母链节点互动之外,在 accounts 下面的文件中提供了交易签名功能,
以及对消息签名和验证的功能,以方便用户使用。
chain3
还提供了和子链客户端 SCS 交互的对象 scs
Over time we’ll introduce other objects such as SCS for the other chain3
protocols. 更多的例子可以在源文件中的example下找到:
here.
使用回调函数(CALLBACK)¶
As this API is designed to work with a local RPC node and all its functions are by default use synchronous HTTP requests.con
If you want to make an asynchronous request, you can pass an optional callback as the last parameter to most functions. All callbacks are using an error first callback style:
chain3.mc.getBlock(48, function(error, result){
if(!error)
console.log(result)
else
console.error(error);
})
批处理执行命令¶
Batch requests allow queuing up requests and processing them at once.
var batch = chain3.createBatch();
batch.add(chain3.mc.getBalance.request('0x0000000000000000000000000000000000000000', 'latest', callback));
batch.add(chain3.mc.contract(abi).at(address).balance.request(address, callback2));
batch.execute();
A note on big numbers in chain3.js¶
You will always get a BigNumber object for balance values as JavaScript is not able to handle big numbers correctly. Look at the following examples:
"101010100324325345346456456456456456456"
// "101010100324325345346456456456456456456"
101010100324325345346456456456456456456
// 1.0101010032432535e+38
chain3.js depends on the BigNumber Library and adds it automatically.
var balance = new BigNumber('123456786979284780000000000');
// or var balance = chain3.mc.getBalance(someAddress);
balance.plus(21).toString(10); // toString(10) converts it to a number string
// "123456786979284780000000021"
The next example wouldn’t work as we have more than 20 floating points, therefore it is recommended that you always keep your balance in sha and only transform it to other units when presenting to the user:
var balance = new BigNumber('13124.234435346456466666457455567456');
balance.plus(21).toString(10); // toString(10) converts it to a number string, but can only show max 20 floating points
// "13145.23443534645646666646" // you number would be cut after the 20 floating point
Chain3 Javascript Ðapp API Reference¶
- chain3
- version
- isConnected()
- setProvider(provider)
- currentProvider
- reset()
- sha3(string)
- toHex(stringOrNumber)
- toAscii(hexString)
- fromAscii(textString, [padding])
- toDecimal(hexString)
- toChecksumAddress(string)
- fromDecimal(number)
- fromSha(numberStringOrBigNumber, unit)
- toSha(numberStringOrBigNumber, unit)
- toBigNumber(numberOrHexString)
- isAddress(hexString)
- net
- mc
- defaultAccount
- defaultBlock
- syncing/getSyncing
- isSyncing
- coinbase/getCoinbase
- hashrate/getHashrate
- gasPrice/getGasPrice
- accounts/getAccounts
- mining/getMining
- blockNumber/getBlockNumber
- getBalance(address)
- getStorageAt(address, position)
- getCode(address)
- getBlock(hash/number)
- getBlockTransactionCount(hash/number)
- getUncle(hash/number)
- getBlockUncleCount(hash/number)
- getTransaction(hash)
- getTransactionFromBlock(hashOrNumber, indexNumber)
- getTransactionReceipt(hash)
- getTransactionCount(address)
- sendTransaction(object)
- call(object)
- estimateGas(object)
- filter(array (, options) )
- contract(abiArray)
- contract.myMethod()
- contract.myEvent()
- contract.allEvents()
- encodeParams
- namereg
- sendIBANTransaction
- iban
- fromAddress
- fromBban
- createIndirect
- isValid
- isDirect
- isIndirect
- checksum
- institution
- client
- address
- toString
Usage¶
chain3.version.api
The chain3
object provides all methods.
Example¶
var Chain3 = require('chain3');
// create an instance of chain3 using the HTTP provider.
var chain3 = new Chain3(new Chain3.providers.HttpProvider("http://localhost:8545"));
chain3.version.api
chain3.version.api
// or async
chain3.version.getApi(callback(error, result){ ... })
Returns¶
String
- The moac js api version.
Example¶
var version = chain3.version.api;
console.log(version); // "0.2.0"
chain3.version.node
chain3.version.node
// or async
chain3.version.getClient(callback(error, result){ ... })
Returns¶
String
- The client/node version.
Example¶
var version = chain3.version.node;
console.log(version); // "Moac/v0.1.0-develop/darwin-amd64/go1.9"
chain3.version.network
chain3.version.network
// or async
chain3.version.getNetwork(callback(error, result){ ... })
Returns¶
String
- The network protocol version.
Example¶
var version = chain3.version.network;
console.log(version); // 54
chain3.version.moac
chain3.version.moac
// or async
chain3.version.getMoac(callback(error, result){ ... })
Returns¶
String
- The moac protocol version.
Example¶
var version = chain3.version.moac;
console.log(version); // 0x3f
chain3.isConnected
chain3.isConnected()
Should be called to check if a connection to a node exists
Parameters¶
none
Returns¶
Boolean
Example¶
if(!chain3.isConnected()) {
// show some dialog to ask the user to start a node
} else {
// start chain3 filters, calls, etc
}
chain3.setProvider
chain3.setProvider(provider)
Should be called to set provider.
Parameters¶
none
Returns¶
undefined
Example¶
chain3.setProvider(new chain3.providers.HttpProvider('http://localhost:8545')); // 8545 for go/moac
chain3.currentProvider
chain3.currentProvider
Will contain the current provider, if one is set. This can be used to check if moac etc. set already a provider.
Returns¶
Object
- The provider set or null
;
Example¶
// Check if moac etc. already set a provider
if(!chain3.currentProvider)
chain3.setProvider(new chain3.providers.HttpProvider("http://localhost:8545"));
chain3.reset
chain3.reset(keepIsSyncing)
Should be called to reset state of chain3. Resets everything except manager. Uninstalls all filters. Stops polling.
Parameters¶
Boolean
- Iftrue
it will uninstall all filters, but will keep the chain3.mc.isSyncing() polls
Returns¶
undefined
Parameters¶
String
- The string to hash using the SHA3 algorithmFunction
- (optional) If you pass a callback the HTTP request is made asynchronous. See this note for details.
Returns¶
String
- The SHA3 of the given data.
Example¶
var str = chain3.sha3("Some ASCII string to be hashed in MOAC");
console.log(str); // "0xbfa24877cd68e6734710402a2af3e29cf18bd6d2f304aa528ffa3a32fa7652d2"
chain3.toHex
chain3.toHex(mixed);
Converts any value into HEX.
Parameters¶
String|Number|Object|Array|BigNumber
- The value to parse to HEX. If its an object or array it will beJSON.stringify
first. If its a BigNumber it will make it the HEX value of a number.
Returns¶
String
- The hex string of mixed
.
Example¶
var str = chain3.toHex("moac network");
console.log(str); // '0x6d6f6163206e6574776f726b'
console.log(chain3.toHex({moac: 'test'}));
//'0x7b226d6f6163223a2274657374227d'
chain3.toAscii
Parameters¶
String
- A HEX string to be converted to ascii.
Returns¶
String
- An ASCII string made from the given hexString
.
Example¶
var str = chain3.toAscii("0x0x6d6f6163206e6574776f726b");
console.log(str); // "moac network"
chain3.fromAscii
chain3.fromAscii(string);
Converts any ASCII string to a HEX string.
Parameters¶
String
- An ASCII string to be converted to HEX.
Returns¶
String
- The converted HEX string.
Example¶
var str = chain3.fromAscii('moac network');
console.log(str); // "0x6d6f6163206e6574776f726b"
chain3.toChecksumAddress
chain3.toChecksumAddress(hexString);
Converts a string to the checksummed address equivalent.
Parameters¶
String
- A string to be converted to a checksummed address.
Returns¶
String
- A string containing the checksummed address.
Example¶
var myAddress = chain3.toChecksumAddress('0xa0c876ec9f2d817c4304a727536f36363840c02c');
console.log(myAddress); // '0xA0C876eC9F2d817c4304A727536f36363840c02c'
chain3.toDecimal
chain3.toDecimal(hexString);
Converts a HEX string to its number representation.
Parameters¶
String
- An HEX string to be converted to a number.
Returns¶
Number
- The number representing the data hexString
.
Example¶
var number = chain3.toDecimal('0x15');
console.log(number); // 21
chain3.fromDecimal
chain3.fromDecimal(number);
Converts a number or number string to its HEX representation.
Parameters¶
Number|String
- A number to be converted to a HEX string.
Returns¶
String
- The HEX string representing of the given number
.
Example¶
var value = chain3.fromDecimal('21');
console.log(value); // "0x15"
chain3.fromSha
chain3.fromSha(number, unit)
Converts a number of sha into the following moac units:
ksha
/femtomc
msha
/picomc
gsha
/nano
/xiao
micro
/sand
milli
mc
kmc
/grand
mmc
gmc
tmc
Parameters¶
Number|String|BigNumber
- A number or BigNumber instance.String
- One of the above moac units.
Returns¶
String|BigNumber
- Either a number string, or a BigNumber instance,
depending on the given number
parameter.
Example¶
var value = chain3.fromSha('21000000000000', 'Xiao');
console.log(value); // "21000"
chain3.toSha
chain3.toSha(number, unit)
Converts a moac unit into sha. Possible units are:
ksha
/femtomc
msha
/picomc
gsha
/nano
/xiao
micro
/sand
milli
mc
kmc
/grand
mmc
gmc
tmc
Parameters¶
Number|String|BigNumber
- A number or BigNumber instance.String
- One of the above moac units.
Returns¶
String|BigNumber
- Either a number string, or a BigNumber instance,
depending on the given number
parameter.
Example¶
var value = chain3.toSha('1', 'mc');
console.log(value); // "1000000000000000000" = 1e18
chain3.toBigNumber
chain3.toBigNumber(numberOrHexString);
Converts a given number into a BigNumber instance.
See the note on BigNumber.
Parameters¶
Number|String
- A number, number string or HEX string of a number.
Returns¶
BigNumber
- A BigNumber instance representing the given value.
Example¶
var value = chain3.toBigNumber('200000000000000000000001');
console.log(value); // instanceOf BigNumber, { [String: '2.00000000000000000000001e+23'] s: 1, e: 23, c: [ 2000000000, 1 ] }
console.log(value.toNumber()); // 2.0000000000000002e+23
console.log(value.toString(10)); // '200000000000000000000001'
chain3.net
chain3.net.listening
chain3.net.listening
// or async
chain3.net.getListening(callback(error, result){ ... })
This property is read only and says whether the node is actively listening for network connections or not.
Returns¶
Boolean
- true
if the client is actively listening for network
connections, otherwise false
.
Example¶
var listening = chain3.net.listening;
console.log(listening); // true of false
chain3.net.peerCount
chain3.net.peerCount
// or async
chain3.net.getPeerCount(callback(error, result){ ... })
This property is read only and returns the number of connected peers.
Returns¶
Number
- The number of peers currently connected to the client.
Example¶
var peerCount = chain3.net.peerCount;
console.log(peerCount); // 4
chain3.mc
Contains the MOAC blockchain related methods.
Example¶
var mc = chain3.mc;
chain3.mc.defaultAccount
chain3.mc.defaultAccount
This default address is used for the following methods (optionally you
can overwrite it by specifying the from
property):
Values¶
String
, 20 Bytes - Any address you own, or where you have the
private key for.
Default is undefined
.
Returns¶
String
, 20 Bytes - The currently set default address.
Example¶
var defaultAccount = chain3.mc.defaultAccount;
console.log(defaultAccount); // 'undefined'
// set the default block
chain3.mc.defaultAccount = '0x8888f1f195afa192cfee860698584c030f4c9db1';
console.log(chain3.mc.defaultAccount);//'0x8888f1f195afa192cfee860698584c030f4c9db1'
chain3.mc.defaultBlock
chain3.mc.defaultBlock
This default block is used for the following methods (optionally you can overwrite the defaultBlock by passing it as the last parameter):
Values¶
Default block parameters can be one of the following:
Number
- a block numberString
-"earliest"
, the genisis blockString
-"latest"
, the latest block (current head of the blockchain)String
-"pending"
, the currently mined block (including pending transactions)
Default is latest
Returns¶
Number|String
- The default block number to use when querying a
state.
Example¶
var defaultBlock = chain3.mc.defaultBlock;
console.log(defaultBlock); // 'latest'
// set the default block
chain3.mc.defaultBlock = 12345;
console.log(chain3.mc.defaultAccount);//'12345'
chain3.mc.syncing
chain3.mc.syncing
// or async
chain3.mc.getSyncing(callback(error, result){ ... })
This property is read only and returns the either a sync object, when
the node is syncing or false
.
Returns¶
Object|Boolean
- A sync object as follows, when the node is
currently syncing or false
: - startingBlock
: Number
- The
block number where the sync started. - currentBlock
: Number
-
The block number where at which block the node currently synced to
already. - highestBlock
: Number
- The estimated block number to
sync to.
Example¶
var sync = chain3.mc.syncing;
console.log(sync);
/*
{
startingBlock: 300,
currentBlock: 312,
highestBlock: 512
}
*/
chain3.mc.isSyncing
chain3.mc.isSyncing(callback);
This convenience function calls the callback
everytime a sync
starts, updates and stops.
Returns¶
Object
- a isSyncing object with the following methods:
syncing.addCallback()
: Adds another callback, which will be called when the node starts or stops syncing.syncing.stopWatching()
: Stops the syncing callbacks.
Callback return value¶
Boolean
- The callback will be fired withtrue
when the syncing starts and withfalse
when it stopped.Object
- While syncing it will return the syncing object:startingBlock
:Number
- The block number where the sync started.currentBlock
:Number
- The block number where at which block the node currently synced to already.highestBlock
:Number
- The estimated block number to sync to.
Example¶
chain3.mc.isSyncing(function(error, sync){
if(!error) {
// stop all app activity
if(sync === true) {
// we use `true`, so it stops all filters, but not the chain3.mc.syncing polling
chain3.reset(true);
// show sync info
} else if(sync) {
console.log(sync.currentBlock);
// re-gain app operation
} else {
// run your app init function...
}
}
});
chain3.mc.coinbase
chain3.mc.coinbase
// or async
chain3.mc.getCoinbase(callback(error, result){ ... })
This property is read only and returns the coinbase address were the mining rewards go to.
Returns¶
String
- The coinbase address of the client.
Example¶
var coinbase = chain3.mc.coinbase;
console.log(coinbase); // "0x407d73d8a49eeb85d32cf465507dd71d507100c1"
chain3.mc.mining
chain3.mc.mining
// or async
chain3.mc.getMining(callback(error, result){ ... })
This property is read only and says whether the node is mining or not.
Returns¶
Boolean
- true
if the client is mining, otherwise false
.
Example¶
var mining = chain3.mc.mining;
console.log(mining); // true or false
chain3.mc.hashrate
chain3.mc.hashrate
// or async
chain3.mc.getHashrate(callback(error, result){ ... })
This property is read only and returns the number of hashes per second that the node is mining with.
Returns¶
Number
- number of hashes per second.
Example¶
var hashrate = chain3.mc.hashrate;
console.log(hashrate); // 493736
chain3.mc.gasPrice
chain3.mc.gasPrice
// or async
chain3.mc.getGasPrice(callback(error, result){ ... })
This property is read only and returns the current gas price. The gas price is determined by the x latest blocks median gas price.
Returns¶
BigNumber
- A BigNumber instance of the current gas price in sha.
See the note on BigNumber.
Example¶
var gasPrice = chain3.mc.gasPrice;
console.log(gasPrice.toString(10)); // "20000000000"
chain3.mc.accounts
chain3.mc.accounts
// or async
chain3.mc.getAccounts(callback(error, result){ ... })
This property is read only and returns a list of accounts the node controls.
Returns¶
Array
- An array of addresses controlled by client.
Example¶
var accounts = chain3.mc.accounts;
console.log(accounts); // ["0x407d73d8a49eeb85d32cf465507dd71d507100c1"]
chain3.mc.blockNumber
chain3.mc.blockNumber
// or async
chain3.mc.getBlockNumber(callback(error, result){ ... })
This property is read only and returns the current block number.
Returns¶
Number
- The number of the most recent block.
Example¶
var number = chain3.mc.blockNumber;
console.log(number); // 2744
chain3.mc.getBalance
chain3.mc.getBalance(addressHexString [, defaultBlock] [, callback])
Get the balance of an address at a given block.
Parameters¶
String
- The address to get the balance of.Number|String
- (optional) If you pass this parameter it will not use the default block set with chain3.mc.defaultBlock.Function
- (optional) If you pass a callback the HTTP request is made asynchronous. See this note for details.
Returns¶
String
- A BigNumber instance of the current balance for the given
address in sha.
See the note on BigNumber.
Example¶
var balance = chain3.mc.getBalance("0x407d73d8a49eeb85d32cf465507dd71d507100c1");
console.log(balance); // instanceof BigNumber
console.log(balance.toString(10)); // '1000000000000'
console.log(balance.toNumber()); // 1000000000000
chain3.mc.getStorageAt
chain3.mc.getStorageAt(addressHexString, position [, defaultBlock] [, callback])
Get the storage at a specific position of an address.
Parameters¶
String
- The address to get the storage from.Number
- The index position of the storage.Number|String
- (optional) If you pass this parameter it will not use the default block set with chain3.mc.defaultBlock.Function
- (optional) If you pass a callback the HTTP request is made asynchronous. See this note for details.
Returns¶
String
- The value in storage at the given position.
Example¶
var state = chain3.mc.getStorageAt("0x407d73d8a49eeb85d32cf465507dd71d507100c1", 0);
console.log(state); // "0x03"
chain3.mc.getCode
chain3.mc.getCode(addressHexString [, defaultBlock] [, callback])
Get the code at a specific address. For a contract address, return the binary code of the contract.
Parameters¶
String
- The address to get the code from.Number|String
- (optional) If you pass this parameter it will not use the default block set with chain3.mc.defaultBlock.Function
- (optional) If you pass a callback the HTTP request is made asynchronous. See this note for details.
Returns¶
String
- The data at given address addressHexString
.
Example¶
var code = chain3.mc.getCode("0x1d12aec505caa2b8513cdad9a13e9d4806a1b704");
console.log(code); // "0x600160008035811a818181146012578301005b601b6001356025565b8060005260206000f25b600060078202905091905056"
chain3.mc.getBlock
chain3.mc.getBlock(blockHashOrBlockNumber [, returnTransactionObjects] [, callback])
Returns a block matching the block number or block hash.
Parameters¶
String|Number
- The block number or hash. Or the string"earliest"
,"latest"
or"pending"
as in the default block parameter.Boolean
- (optional, defaultfalse
) Iftrue
, the returned block will contain all transactions as objects, iffalse
it will only contains the transaction hashes.Function
- (optional) If you pass a callback the HTTP request is made asynchronous. See this note for details.
Returns¶
Object
- The block object:
number
:Number
- the block number.null
when its pending block.hash
:String
, 32 Bytes - hash of the block.null
when its pending block.parentHash
:String
, 32 Bytes - hash of the parent block.nonce
:String
, 8 Bytes - hash of the generated proof-of-work.null
when its pending block.sha3Uncles
:String
, 32 Bytes - SHA3 of the uncles data in the block.logsBloom
:String
, 256 Bytes - the bloom filter for the logs of the block.null
when its pending block.transactionsRoot
:String
, 32 Bytes - the root of the transaction trie of the blockstateRoot
:String
, 32 Bytes - the root of the final state trie of the block.miner
:String
, 20 Bytes - the address of the beneficiary to whom the mining rewards were given.difficulty
:BigNumber
- integer of the difficulty for this block.totalDifficulty
:BigNumber
- integer of the total difficulty of the chain until this block.extraData
:String
- the “extra data” field of this block.size
:Number
- integer the size of this block in bytes.gasLimit
:Number
- the maximum gas allowed in this block.gasUsed
:Number
- the total used gas by all transactions in this block.timestamp
:Number
- the unix timestamp for when the block was collated.transactions
:Array
- Array of transaction objects, or 32 Bytes transaction hashes depending on the last given parameter.uncles
:Array
- Array of uncle hashes.
Example¶
var info = chain3.mc.getBlock(0);
console.log(info);
/*
{ difficulty: { [String: '100000000000'] s: 1, e: 11, c: [ 100000000000 ] },
extraData: '0x31393639415250414e4554373354435049503039425443323031384d4f4143',
gasLimit: 9000000,
gasUsed: 0,
hash: '0x6b9661646439fab926ffc9bccdf3abb572d5209ae59e3390abf76aee4e2d49cd',
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
miner: '0x0000000000000000000000000000000000000000',
mixHash: '0x0000000000000000000000000000000000000000000000000000000000000000',
nonce: '0x0000000000000042',
number: 0,
parentHash: '0x0000000000000000000000000000000000000000000000000000000000000000',
receiptsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
size: 540,
stateRoot: '0xe221c9e4ad19514d7ce3e6b0bec3ad7f6cc293336e59c301cda293cfbda83df6',
timestamp: 0,
totalDifficulty: { [String: '100000000000'] s: 1, e: 11, c: [ 100000000000 ] },
transactions: [],
transactionsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
uncles: [] }
*/
chain3.mc.getBlockTransactionCount
chain3.mc.getBlockTransactionCount(hashStringOrBlockNumber [, callback])
Returns the number of transaction in a given block.
Parameters¶
String|Number
- The block number or hash. Or the string"earliest"
,"latest"
or"pending"
as in the default block parameter.Function
- (optional) If you pass a callback the HTTP request is made asynchronous. See this note for details.
Returns¶
Number
- The number of transactions in the given block.
Example¶
var number = chain3.mc.getBlockTransactionCount("0xddfb8508bff841242099e640efe59f5e5252be1a60fa701d333e1a8bfdee6263");
console.log(number); // 1
chain3.mc.getUncle
chain3.mc.getUncle(blockHashStringOrNumber, uncleNumber [, returnTransactionObjects] [, callback])
Returns a blocks uncle by a given uncle index position.
Parameters¶
String|Number
- The block number or hash. Or the string"earliest"
,"latest"
or"pending"
as in the default block parameter.Number
- The index position of the uncle.Boolean
- (optional, defaultfalse
) Iftrue
, the returned block will contain all transactions as objects, iffalse
it will only contains the transaction hashes.Function
- (optional) If you pass a callback the HTTP request is made asynchronous. See this note for details.
Returns¶
Object
- the returned uncle. For a return value see
chain3.mc.getBlock().
Note: An uncle doesn’t contain individual transactions.
Example¶
var uncle = chain3.mc.getUncle(500, 0);
console.log(uncle); // see chain3.mc.getBlock
chain3.mc.getTransaction
chain3.mc.getTransaction(transactionHash [, callback])
Returns a transaction matching the given transaction hash.
Parameters¶
String
- The transaction hash.Function
- (optional) If you pass a callback the HTTP request is made asynchronous. See this note for details.
Returns¶
Object
- A transaction object its hash transactionHash
:
hash
:String
, 32 Bytes - hash of the transaction.nonce
:Number
- the number of transactions made by the sender prior to this one.blockHash
:String
, 32 Bytes - hash of the block where this transaction was in.null
when its pending.blockNumber
:Number
- block number where this transaction was in.null
when its pending.transactionIndex
:Number
- integer of the transactions index position in the block.null
when its pending.from
:String
, 20 Bytes - address of the sender.to
:String
, 20 Bytes - address of the receiver.null
when its a contract creation transaction.value
:BigNumber
- value transferred in Sha.gasPrice
:BigNumber
- gas price provided by the sender in Sha.gas
:Number
- gas provided by the sender.input
:String
- the data sent along with the transaction.
Example¶
var txhash = "0x687751dd47684f4b5df263ae4ec39f54f057d0e2a1dde56f9d52766849c9c7fe";
var transaction = chain3.mc.getTransaction(txhash);
console.log(transaction);
/*
{ blockHash: '0x716c602d49055b4e24fbe7da952c1ad81820ad0401f3cb3ce12e832fbcc368f5',
blockNumber: 57259,
from: '0x7cfd775c7a97aa632846eff35dcf9dbcf502d0f3',
gas: 1000,
gasPrice: { [String: '200000000000'] s: 1, e: 11, c: [ 200000000000 ] },
hash: '0xf1c1771204431c1c584e793b49d41586a923c370be93673aac42d66252bc8d0a',
input: '0x',
nonce: 840,
syscnt: '0x0',
to: '0x3435410589ebd06b74079a1e141759d8502aeb8b',
transactionIndex: 689,
value: { [String: '1000000000'] s: 1, e: 9, c: [ 1000000000 ] },
v: '0xea',
r: '0x77aa72d0900e436b60f8be377e43dead3567241a85fbeb5517283e2dc8aca2b4',
s: '0x24477ec130fc4101289b37e6107acfe64026c898994273110faa8f19b8ea6985',
shardingFlag: '0x0' }
*/
chain3.mc.getTransactionFromBlock
getTransactionFromBlock(hashStringOrNumber, indexNumber [, callback])
Returns a transaction based on a block hash or number and the transactions index position.
Parameters¶
String
- A block number or hash. Or the string"earliest"
,"latest"
or"pending"
as in the default block parameter.Number
- The transactions index position.Function
- (optional) If you pass a callback the HTTP request is made asynchronous. See this note for details.
Returns¶
Object
- A transaction object, see
chain3.mc.getTransaction:
Example¶
var transaction = chain3.mc.getTransactionFromBlock(921, 2);
console.log(transaction); // see chain3.mc.getTransaction
chain3.mc.getTransactionReceipt
chain3.mc.getTransactionReceipt(hashString [, callback])
Returns the receipt of a transaction by transaction hash.
Note That the receipt is not available for pending transactions.
Parameters¶
String
- The transaction hash.Function
- (optional) If you pass a callback the HTTP request is made asynchronous. See this note for details.
Returns¶
Object
- A transaction receipt object, or null
when no receipt
was found:
blockHash
:String
, 32 Bytes - hash of the block where this transaction was in.blockNumber
:Number
- block number where this transaction was in.transactionHash
:String
, 32 Bytes - hash of the transaction.transactionIndex
:Number
- integer of the transactions index position in the block.from
:String
, 20 Bytes - address of the sender.to
:String
, 20 Bytes - address of the receiver.null
when its a contract creation transaction.cumulativeGasUsed
:Number
- The total amount of gas used when this transaction was executed in the block.gasUsed
:Number
- The amount of gas used by this specific transaction alone.contractAddress
:String
- 20 Bytes - The contract address created, if the transaction was a contract creation, otherwisenull
.logs
:Array
- Array of log objects, which this transaction generated.
Example¶
var receipt = chain3.mc.getTransactionReceipt('0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b');
console.log(receipt);
{
"transactionHash": "0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b",
"transactionIndex": 0,
"blockHash": "0xef95f2f1ed3ca60b048b4bf67cde2195961e0bba6f70bcbea9a2c4e133e34b46",
"blockNumber": 3,
"contractAddress": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"cumulativeGasUsed": 314159,
"gasUsed": 30234,
"logs": [{
// logs as returned by getFilterLogs, etc.
}, ...]
}
chain3.mc.getTransactionCount
chain3.mc.getTransactionCount(addressHexString [, defaultBlock] [, callback])
Get the numbers of transactions sent from this address.
Parameters¶
String
- The address to get the numbers of transactions from.Number|String
- (optional) If you pass this parameter it will not use the default block set with chain3.mc.defaultBlock.Function
- (optional) If you pass a callback the HTTP request is made asynchronous. See this note for details.
Returns¶
Number
- The number of transactions sent from the given address.
Example¶
var number = chain3.mc.getTransactionCount("0x407d73d8a49eeb85d32cf465507dd71d507100c1");
console.log(number); // 1
chain3.mc.sendTransaction
chain3.mc.sendTransaction(transactionObject [, callback])
Sends a transaction to the network.
Parameters¶
Object
- The transaction object to send:
from
:String
- The address for the sending account. Uses the chain3.mc.defaultAccount property, if not specified.to
:String
- (optional) The destination address of the message, can be an account address or a contract address, left undefined for a contract-creation transaction.value
:Number|String|BigNumber
- (optional) The value transferred for the transaction in Sha, also the endowment if it’s a contract-creation transaction.gas
:Number|String|BigNumber
- (optional, default: To-Be-Determined) The amount of gas to use for the transaction (unused gas is refunded).gasPrice
:Number|String|BigNumber
- (optional, default: To-Be-Determined) The price of gas for this transaction in sha, defaults to the mean network gas price.data
:String
- (optional) Either a byte string containing the associated data of the message, or in the case of a contract-creation transaction, the initialisation code.nonce
:Number
- (optional) Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce.shardingFlag
:Number|String
- (optional) Set to 1 for micro/subchain direct contract-call, 0 or undefine for global contract-creation transaction.
Function
- (optional) If you pass a callback the HTTP request is made asynchronous. See this note for details.
Returns¶
String
- The 32 Bytes transaction hash as HEX string.
If the transaction was a contract creation use chain3.mc.getTransactionReceipt() to get the contract address, after the transaction was mined.
Example¶
// compiled solidity source code using https://chriseth.github.io/cpp-ethereum/
var code = "603d80600c6000396000f3007c01000000000000000000000000000000000000000000000000000000006000350463c6888fa18114602d57005b600760043502
8060005260206000f3";
chain3.mc.sendTransaction({data: code}, function(err, address) {
if (!err)
console.log(address); // "0x7f9fade1c0d57a7af66ab4ead7c2eb7b11a91385"
});
chain3.mc.call
chain3.mc.call(callObject [, defaultBlock] [, callback])
Executes a message call transaction, which is directly executed in the VM of the node, but never mined into the blockchain.
Parameters¶
Object
- A transaction object see chain3.mc.sendTransaction, with the difference that for calls thefrom
property is optional as well.Number|String
- (optional) If you pass this parameter it will not use the default block set with chain3.mc.defaultBlock.Function
- (optional) If you pass a callback the HTTP request is made asynchronous. See this note for details.
Returns¶
String
- The returned data of the call, e.g. a codes functions
return value.
Example¶
var result = chain3.mc.call({
to: "0xc4abd0339eb8d57087278718986382264244252f",
data: "0xc6888fa10000000000000000000000000000000000000000000000000000000000000003"
});
console.log(result); // "0x0000000000000000000000000000000000000000000000000000000000000015"
chain3.mc.estimateGas
chain3.mc.estimateGas(callObject [, defaultBlock] [, callback])
Executes a message call or transaction, which is directly executed in the VM of the node, but never mined into the blockchain and returns the amount of the gas used.
Parameters¶
See chain3.mc.sendTransaction, expect that all properties are optional.
Returns¶
Number
- the used gas for the simulated call/transaction.
Example¶
var result = chain3.mc.estimateGas({
to: "0xc4abd0339eb8d57087278718986382264244252f",
data: "0xc6888fa10000000000000000000000000000000000000000000000000000000000000003"
});
console.log(result); // "1465"
chain3.mc.filter
// can be 'latest' or 'pending'
var filter = chain3.mc.filter(filterString);
// OR object are log filter options
var filter = chain3.mc.filter(options);
// watch for changes
filter.watch(function(error, result){
if (!error)
console.log(result);
});
// Additionally you can start watching right away, by passing a callback:
chain3.mc.filter(options, function(error, result){
if (!error)
console.log(result);
});
Parameters¶
String|Object
- The string"latest"
or"pending"
to watch for changes in the latest block or pending transactions respectively. Or a filter options object as follows:
fromBlock
:Number|String
- The number of the earliest block (latest
may be given to mean the most recent andpending
currently mining, block). By defaultlatest
.toBlock
:Number|String
- The number of the latest block (latest
may be given to mean the most recent andpending
currently mining, block). By defaultlatest
.address
:String
- An address or a list of addresses to only get logs from particular account(s).topics
:Array of Strings
- An array of values which must each appear in the log entries. The order is important, if you want to leave topics out usenull
, e.g.[null, '0x00...']
. You can also pass another array for each topic with options for that topic e.g.[null, ['option1', 'option2']]
Returns¶
Object
- A filter object with the following methods:
filter.get(callback)
: Returns all of the log entries that fit the filter.filter.watch(callback)
: Watches for state changes that fit the filter and calls the callback. See this note for details.filter.stopWatching()
: Stops the watch and uninstalls the filter in the node. Should always be called once it is done.
Watch callback return value¶
String
- When using the"latest"
parameter, it returns the block hash of the last incoming block.String
- When using the"pending"
parameter, it returns a transaction hash of the last add pending transaction.Object
- When using manual filter options, it returns a log object as follows:logIndex
:Number
- integer of the log index position in the block.null
when its pending log.transactionIndex
:Number
- integer of the transactions index position log was created from.null
when its pending log.transactionHash
:String
, 32 Bytes - hash of the transactions this log was created from.null
when its pending log.blockHash
:String
, 32 Bytes - hash of the block where this log was in.null
when its pending.null
when its pending log.blockNumber
:Number
- the block number where this log was in.null
when its pending.null
when its pending log.address
:String
, 32 Bytes - address from which this log originated.data
:String
- contains one or more 32 Bytes non-indexed arguments of the log.topics
:Array of Strings
- Array of 0 to 4 32 BytesDATA
of indexed log arguments. (In solidity: The first topic is the hash of the signature of the event (e.g.Deposit(address,bytes32,uint256)
), except you declared the event with theanonymous
specifier.)
Note For event filter return values see Contract Events
Example¶
var filter = chain3.mc.filter('pending');
filter.watch(function (error, log) {
console.log(log); // {"address":"0x0000000000000000000000000000000000000000", "data":"0x0000000000000000000000000000000000000000000000000000000000000000", ...}
});
// get all past logs again.
var myResults = filter.get(function(error, logs){ ... });
...
// stops and uninstalls the filter
filter.stopWatching();
chain3.mc.contract
chain3.mc.contract(abiArray)
Creates a contract object for a solidity contract, which can be used to initiate contracts on an address. You can read more about events here.
Parameters¶
Array
- ABI array with descriptions of functions and events of the contract.
Returns¶
Object
- A contract object, which can be initiated as follows:
var MyContract = chain3.mc.contract(abiArray);
// instantiate by address
var contractInstance = MyContract.at([address]);
// deploy new contract
var contractInstance = MyContract.new([contructorParam1] [, contructorParam2], {data: '0x12345...', from: myAccount, gas: 1000000});
// Get the data to deploy the contract manually
var contractData = MyContract.new.getData([contructorParam1] [, contructorParam2], {data: '0x12345...'});
// contractData = '0x12345643213456000000000023434234'
And then you can either initiate an existing contract on an address, or deploy the contract using the compiled byte code:
// Instantiate from an existing address:
var myContractInstance = MyContract.at(myContractAddress);
// Or deploy a new contract:
// Deploy the contract asyncronous:
var myContractReturned = MyContract.new(param1, param2, {
data: myContractCode,
gas: 300000,
from: mySenderAddress}, function(err, myContract){
if(!err) {
// NOTE: The callback will fire twice!
// Once the contract has the transactionHash property set and once its deployed on an address.
// e.g. check tx hash on the first call (transaction send)
if(!myContract.address) {
console.log(myContract.transactionHash) // The hash of the transaction, which deploys the contract
// check address on the second call (contract deployed)
} else {
console.log(myContract.address) // the contract address
}
// Note that the returned "myContractReturned" === "myContract",
// so the returned "myContractReturned" object will also get the address set.
}
});
// Deploy contract syncronous: The address will be added as soon as the contract is mined.
// Additionally you can watch the transaction by using the "transactionHash" property
var myContractInstance = MyContract.new(param1, param2, {data: myContractCode, gas: 300000, from: mySenderAddress});
myContractInstance.transactionHash // The hash of the transaction, which created the contract
myContractInstance.address // undefined at start, but will be auto-filled later
Note When you deploy a new contract, you should check for the next 12 blocks or so if the contract code is still at the address (using chain3.mc.getCode()), to make sure a fork didn’t change that.
Example¶
// contract abi
var abi = [{
name: 'myConstantMethod',
type: 'function',
constant: true,
inputs: [{ name: 'a', type: 'string' }],
outputs: [{name: 'd', type: 'string' }]
}, {
name: 'myStateChangingMethod',
type: 'function',
constant: false,
inputs: [{ name: 'a', type: 'string' }, { name: 'b', type: 'int' }],
outputs: []
}, {
name: 'myEvent',
type: 'event',
inputs: [{name: 'a', type: 'int', indexed: true},{name: 'b', type: 'bool', indexed: false]
}];
// creation of contract object
var MyContract = chain3.mc.contract(abi);
// initiate contract for an address
var myContractInstance = MyContract.at('0xc4abd0339eb8d57087278718986382264244252f');
// call constant function
var result = myContractInstance.myConstantMethod('myParam');
console.log(result) // '0x25434534534'
// send a transaction to a function
myContractInstance.myStateChangingMethod('someParam1', 23, {value: 200, gas: 2000});
// short hand style
chain3.mc.contract(abi).at(address).myAwesomeMethod(...);
// create filter
var filter = myContractInstance.myEvent({a: 5}, function (error, result) {
if (!error)
console.log(result);
/*
{
address: '0x8718986382264244252fc4abd0339eb8d5708727',
topics: "0x12345678901234567890123456789012", "0x0000000000000000000000000000000000000000000000000000000000000005",
data: "0x0000000000000000000000000000000000000000000000000000000000000001",
...
}
*/
});
// Automatically determines the use of call or sendTransaction based on the method type
myContractInstance.myMethod(param1 [, param2, ...] [, transactionObject] [, callback]);
// Explicitly calling this method
myContractInstance.myMethod.call(param1 [, param2, ...] [, transactionObject] [, callback]);
// Explicitly sending a transaction to this method
myContractInstance.myMethod.sendTransaction(param1 [, param2, ...] [, transactionObject] [, callback]);
// Explicitly sending a transaction to this method
myContractInstance.myMethod.sendTransaction(param1 [, param2, ...] [, transactionObject] [, callback]);
// Get the call data, so you can call the contract through some other means
var myCallData = myContractInstance.myMethod.getData(param1 [, param2, ...]);
// myCallData = '0x45ff3ff6000000000004545345345345..'
The contract object exposes the contracts methods, which can be called using parameters and a transaction object.
Parameters¶
String|Number
- (optional) Zero or more parameters of the function.Object
- (optional) The (previous) last parameter can be a transaction object, see chain3.mc.sendTransaction parameter 1 for more.Function
- (optional) If you pass a callback as the last parameter the HTTP request is made asynchronous. See this note for details.
Returns¶
String
- If its a call the result data, if its a send transaction a
created contract address, or the transaction hash, see
chain3.mc.sendTransaction for details.
Example¶
// creation of contract object
var MyContract = chain3.mc.contract(abi);
// initiate contract for an address
var myContractInstance = MyContract.at('0x78e97bcc5b5dd9ed228fed7a4887c0d7287344a9');
var result = myContractInstance.myConstantMethod('myParam');
console.log(result) // '0x25434534534'
myContractInstance.myStateChangingMethod('someParam1', 23, {value: 200, gas: 2000}, function(err, result){ ... });
var event = myContractInstance.MyEvent({valueA: 23} [, additionalFilterObject])
// watch for changes
event.watch(function(error, result){
if (!error)
console.log(result);
});
// Or pass a callback to start watching immediately
var event = myContractInstance.MyEvent([{valueA: 23}] [, additionalFilterObject] , function(error, result){
if (!error)
console.log(result);
});
You can use events like filters and they have the same methods, but you pass different objects to create the event filter.
Parameters¶
Object
- Indexed return values you want to filter the logs by, e.g.{'valueA': 1, 'valueB': [myFirstAddress, mySecondAddress]}
. By default all filter values are set tonull
. It means, that they will match any event of given type sent from this contract.Object
- Additional filter options, see filters parameter 1 for more. By default filterObject has field ‘address’ set to address of the contract. Also first topic is the signature of event.Function
- (optional) If you pass a callback as the last parameter it will immediately start watching and you don’t need to callmyEvent.watch(function(){})
. See this note for details.
Callback return¶
Object
- An event object as follows:
args
:Object
- The arguments coming from the event.event
:String
- The event name.logIndex
:Number
- integer of the log index position in the block.transactionIndex
:Number
- integer of the transactions index position log was created from.transactionHash
:String
, 32 Bytes - hash of the transactions this log was created from.address
:String
, 32 Bytes - address from which this log originated.blockHash
:String
, 32 Bytes - hash of the block where this log was in.null
when its pending.blockNumber
:Number
- the block number where this log was in.null
when its pending.
Example¶
var MyContract = chain3.mc.contract(abi);
var myContractInstance = MyContract.at('0x78e97bcc5b5dd9ed228fed7a4887c0d7287344a9');
// watch for an event with {some: 'args'}
var myEvent = myContractInstance.MyEvent({some: 'args'}, {fromBlock: 0, toBlock: 'latest'});
myEvent.watch(function(error, result){
...
});
// would get all past logs again.
var myResults = myEvent.get(function(error, logs){ ... });
...
// would stop and uninstall the filter
myEvent.stopWatching();
var events = myContractInstance.allEvents([additionalFilterObject]);
// watch for changes
events.watch(function(error, event){
if (!error)
console.log(event);
});
// Or pass a callback to start watching immediately
var events = myContractInstance.allEvents([additionalFilterObject,] function(error, log){
if (!error)
console.log(log);
});
Will call the callback for all events which are created by this contract.
Parameters¶
Object
- Additional filter options, see filters parameter 1 for more. By default filterObject has field ‘address’ set to address of the contract. Also first topic is the signature of event.Function
- (optional) If you pass a callback as the last parameter it will immediately start watching and you don’t need to callmyEvent.watch(function(){})
. See this note for details.
Callback return¶
Object
- See Contract Events for more.
Example¶
var MyContract = chain3.mc.contract(abi);
var myContractInstance = MyContract.at('0x78e97bcc5b5dd9ed228fed7a4887c0d7287344a9');
// watch for an event with {some: 'args'}
var events = myContractInstance.allEvents({fromBlock: 0, toBlock: 'latest'});
events.watch(function(error, result){
...
});
// would get all past logs again.
events.get(function(error, logs){ ... });
...
// would stop and uninstall the filter
myEvent.stopWatching();
chain3.encodeParams
chain3.encodeParams
Encode a list of parameters array into HEX codes. ##### Parameters
types
- list of types of paramsparams
- list of values of params
Example¶
var types = ['int','string'];
var args = [100, '4000'];
var dataHex = '0x' + chain3.encodeParams(types, args);
console.log("encoded params:", dataHex);
// outputs
encoded params:0x0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000043430303000000000000000000000000000000000000000000000000000000000
chain3.mc.namereg
chain3.mc.namereg
Returns GlobalRegistrar object.
Usage¶
see namereg example
chain3.mc.sendIBANTransaction
var txHash = chain3.mc.sendIBANTransaction('0x00c5496aee77c1ba1f0854206a26dda82a81d6d8', 'XE66MOACXREGGAVOFYORK', 0x100);
Sends IBAN transaction from user account to destination IBAN address.
Parameters¶
string
- address from which we want to send transactionstring
- IBAN address to which we want to send transactionvalue
- value that we want to send in IBAN transaction
chain3.mc.iban
var i = new chain3.mc.iban("XE81ETHXREGGAVOFYORK");
chain3.mc.iban.fromAddress
var i = chain3.mc.iban.fromAddress('0xd814f2ac2c4ca49b33066582e4e97ebae02f2ab9');
console.log(i.toString()); // 'XE72P8O19KRSWXUGDY294PZ66T4ZGF89INT
chain3.mc.iban.fromBban
var i = chain3.mc.iban.fromBban('XE66MOACXREGGAVOFYORK');
console.log(i.toString()); // "XE71XE66MOACXREGGAVOFYORK"
chain3.mc.iban.createIndirect
var i = chain3.mc.iban.createIndirect({
institution: "XREG",
identifier: "GAVOFYORK"
});
console.log(i.toString()); // "XE66MOACXREGGAVOFYORK"
chain3.mc.iban.isValid
var valid = chain3.mc.iban.isValid("XE66MOACXREGGAVOFYORK");
console.log(valid); // true
var valid2 = chain3.mc.iban.isValid("XE76MOACXREGGAVOFYORK");
console.log(valid2); // false, cause checksum is incorrect
var i = new chain3.mc.iban("XE66MOACXREGGAVOFYORK");
var valid3 = i.isValid();
console.log(valid3); // true
chain3.mc.iban.isDirect
var i = new chain3.mc.iban("XE66MOACXREGGAVOFYORK");
var direct = i.isDirect();
console.log(direct); // false
chain3.mc.iban.isIndirect
var i = new chain3.mc.iban("XE66MOACXREGGAVOFYORK");
var indirect = i.isIndirect();
console.log(indirect); // true
chain3.mc.iban.checksum
var i = new chain3.mc.iban("XE66MOACXREGGAVOFYORK");
var checksum = i.checksum();
console.log(checksum); // "66"
chain3.mc.iban.institution
var i = new chain3.mc.iban("XE66MOACXREGGAVOFYORK");
var institution = i.institution();
console.log(institution); // 'XREG'
chain3.mc.iban.client
var i = new chain3.mc.iban("XE66MOACXREGGAVOFYORK");
var client = i.client();
console.log(client); // 'GAVOFYORK'
chain3.mc.iban.address
var i = new chain3.mc.iban('XE72P8O19KRSWXUGDY294PZ66T4ZGF89INT');
var address = i.address();
console.log(address); // 'd814f2ac2c4ca49b33066582e4e97ebae02f2ab9'
chain3.mc.iban.toString
var i = new chain3.mc.iban('XE72P8O19KRSWXUGDY294PZ66T4ZGF89INT');
console.log(i.toString()); // 'XE72P8O19KRSWXUGDY294PZ66T4ZGF89INT'
Chain3 GO 软件库¶
MOAC Go API was built for MOAC chain. It was developed from MOAC RPC API, which can be used to develop Ðapp on MOAC chain. It supports both VNODE and SCS JSON RPC API methods in MOAC network.
Chain3Go Installation¶
MOAC Configuration¶
Install MOAC¶
Download latest MOAC Vnode and SCS Releases from here: https://github.com/MOACChain/moac-core/releases
Run MOAC¶
Run moac vnode on testnet
./moac –testnet
Run moac scs to connect the VNODE locally
./scsserver
Create new accounts and send transactions
mc.coinbase
mc.accounts
personal.newAccount()
passphrase:
repeat passphrase:
miner.start()
--wait a few seconds
miner.stop()
personal.unlockAccount("0x18833df6ba69b4d50acc744e8294d128ed8db1f1")
mc.sendTransaction({from: '0x18833df6ba69b4d50acc744e8294d128ed8db1f1', to: '0x2a022eb956d1962d867dcebd8fed6ae71ee4385a', value: chain3.toSha(12, "moac")})
Chain3Go Execution¶
go run main.go
Chain3 Java 软件库¶
chain3j <https://github.com/MOACChain/chain3j> is a lightweight, highly modular, reactive, type safe Java and Android library for working with Smart Contracts and integrating with clients (nodes) on the MOAC network:
This allows you to work with the MOAC blockchain, without the additional overhead of having to write your own integration code for the platform.
特点¶
- Complete implementation of MOAC’s JSON-RPC client API over HTTP and IPC
- Auto-generation of Java smart contract wrappers to create, deploy, transact with and call smart contracts from native Java code (Solidity and
- Reactive-functional API for working with filters
- Support for MOAC gateway, so you don’t have to run an MOAC client yourself
- Comprehensive integration tests demonstrating a number of the above scenarios
- Command line tools
- Android compatible
It has five runtime dependencies:
- RxJava for its reactive-functional API
- OKHttp for HTTP connections
- Jackson Core for fast JSON serialisation/deserialisation
- Bouncy Castle (Spongy Castle on Android) for crypto
- Jnr-unixsocket for *nix IPC (not available on Android)
It also uses JavaPoet for generating smart contract wrappers.
Quickstart¶
A chain3j sample project is available that demonstrates a number of core features of MOAC with chain3j, including:
- Connecting to a node on the MOAC network
- Loading an MOAC keystore file
- Sending MOAC from one address to another
- Deploying a smart contract to the network
- Reading a value from the deployed smart contract
- Updating a value in the deployed smart contract
- Viewing an event logged by the smart contract
Getting started¶
Typically your application should depend on release versions of chain3j, but you may also use snapshot dependencies for early access to features and fixes, refer to the `Snapshot Dependencies`_ section.
Maven¶
Java 8:
<dependency>
<groupId>io.github.moacchain</groupId>
<artifactId>chain3j</artifactId>
<version>0.1.0</version>
</dependency>
Android:
<dependency>
<groupId>io.github.moacchain</groupId>
<artifactId>chain3j</artifactId>
<version>0.1.0-android</version>
</dependency>
Gradle¶
Java 8:
compile ('io.github.moacchain:chain3j:0.1.0')
Android:
compile ('io.github.moacchain:chain3j:0.1.0-android')
Start a client¶
Start up an MOAC client if you don’t already have one running, check _:
$ ./moac --rpcapi "personal,mc,net,chain3" --rpc --testnet
Chain3j chain3 = Chain3j.build(new HttpService("http://gateway.moac.io/testnet"));
Start sending requests¶
To send synchronous requests:
Chain3j chain3 = Chain3j.build(new HttpService()); // defaults to http://localhost:8545/
Chain3ClientVersion chain3ClientVersion = chain3.chain3ClientVersion().send();
String clientVersion = chain3ClientVersion.getChain3ClientVersion();
To send asynchronous requests using a CompletableFuture (Future on Android):
Chain3j chain3 = Chain3j.build(new HttpService()); // defaults to http://localhost:8545/
Chain3ClientVersion chain3ClientVersion = chain3.chain3ClientVersion().sendAsync().get();
String clientVersion = chain3ClientVersion.getChain3ClientVersion();
To use an RxJava Observable:
Chain3j chain3 = Chain3j.build(new HttpService()); // defaults to http://localhost:8545/
chain3.chain3ClientVersion().observable().subscribe(x -> {
String clientVersion = x.getChain3ClientVersion();
...
});
Note: for Android use:
Chain3j chain3 = Chain3jFactory.build(new HttpService()); // defaults to http://localhost:8545/
...
IPC¶
chain3j also supports fast inter-process communication (IPC) via file sockets to clients running on the same host as chain3j. To connect simply use the relevant IpcService implementation instead of HttpService when you create your service:
// OS X/Linux/Unix:
Chain3j chain3 = Chain3j.build(new UnixIpcService("/path/to/socketfile"));
...
// Windows
Chain3j chain3 = Chain3j.build(new WindowsIpcService("/path/to/namedpipefile"));
...
Note: IPC is not currently available on chain3j-android.
Working with smart contracts with Java smart contract wrappers¶
chain3j can auto-generate smart contract wrapper code to deploy and interact with smart contracts without leaving the JVM.
To generate the wrapper code, compile your smart contract:
$ solc <contract>.sol --bin --abi --optimize -o <output-dir>/
Then generate the wrapper code using chain3j’s Command line tools:
chain3j solidity generate /path/to/<smart-contract>.bin /path/to/<smart-contract>.abi -o /path/to/src/main/java -p com.your.organisation.name
Now you can create and deploy your smart contract:
Chain3j chain3 = Chain3j.build(new HttpService()); // defaults to http://localhost:8545/
Credentials credentials = WalletUtils.loadCredentials("password", "/path/to/walletfile");
YourSmartContract contract = YourSmartContract.deploy(
<chain3j>, <credentials>,
GAS_PRICE, GAS_LIMIT,
<param1>, ..., <paramN>).send(); // constructor params
Alternatively, if you use MOAC wallet, you can make use of its .json output files:
# Open MOAC wallet and start a local MOAC node
# Click CONTRACTS tab and choose the "DEPLOY NEW CONTRACT" button
# Copy the contract codes to the "SOLIDITY CONTRACT SOURCE CODE"
# The codes will be auto compiled.
Then generate the wrapper code using chain3j’s Command line tools:
$ cd /path/to/your/chain3j/java/project
$ chain3j truffle generate /path/to/<truffle-smart-contract-output>.json -o /path/to/src/main/java -p com.your.organisation.name
Whether using Truffle or solc directly, either way you get a ready-to-use Java wrapper for your contract.
So, to use an existing contract:
YourSmartContract contract = YourSmartContract.load(
"0x<address>|<ensName>", <chain3j>, <credentials>, GAS_PRICE, GAS_LIMIT);
To transact with a smart contract:
TransactionReceipt transactionReceipt = contract.someMethod(
<param1>,
...).send();
To call a smart contract:
Type result = contract.someMethod(<param1>, ...).send();
To fine control your gas price:
contract.setGasProvider(new DefaultGasProvider() {
...
});
For more information refer to Smart Contracts.
Filters¶
chain3j functional-reactive nature makes it really simple to setup observers that notify subscribers of events taking place on the blockchain.
To receive all new blocks as they are added to the blockchain:
Subscription subscription = chain3j.blockObservable(false).subscribe(block -> {
...
});
To receive all new transactions as they are added to the blockchain:
Subscription subscription = chain3j.transactionObservable().subscribe(tx -> {
...
});
To receive all pending transactions as they are submitted to the network (i.e. before they have been grouped into a block together):
Subscription subscription = chain3j.pendingTransactionObservable().subscribe(tx -> {
...
});
Or, if you’d rather replay all blocks to the most current, and be notified of new subsequent blocks being created:
There are a number of other transaction and block replay Observables described in the docs.
Topic filters are also supported:
McFilter filter = new McFilter(DefaultBlockParameterName.EARLIEST,
DefaultBlockParameterName.LATEST, <contract-address>)
.addSingleTopic(...)|.addOptionalTopics(..., ...)|...;
chain3j.mcLogObservable(filter).subscribe(log -> {
...
});
Subscriptions should always be cancelled when no longer required:
subscription.unsubscribe();
Note: filters are not supported on Infura.
For further information refer to Filters and Events and the Chain3jRx interface.
Transactions¶
chain3j provides support for both working with MOAC wallet files (recommended) and MOAC client admin commands for sending transactions.
To send Mc to another party using your MOAC wallet file:
Chain3j chain3 = Chain3j.build(new HttpService()); // defaults to http://localhost:8545/
Credentials credentials = WalletUtils.loadCredentials("password", "/path/to/walletfile");
TransactionReceipt transactionReceipt = Transfer.sendFunds(
chain3, credentials, "0x<address>|<ensName>",
BigDecimal.valueOf(1.0), Convert.Unit.MC)
.send();
Or if you wish to create your own custom transaction:
Chain3j chain3 = Chain3j.build(new HttpService()); // defaults to http://localhost:8545/
Credentials credentials = WalletUtils.loadCredentials("password", "/path/to/walletfile");
// get the next available nonce
McGetTransactionCount mcGetTransactionCount = chain3j.mcGetTransactionCount(
address, DefaultBlockParameterName.LATEST).sendAsync().get();
BigInteger nonce = mcGetTransactionCount.getTransactionCount();
// create our transaction
RawTransaction rawTransaction = RawTransaction.createMcTransaction(
nonce, <gas price>, <gas limit>, <toAddress>, <value>);
// sign & send out transaction with EIP155 signature
byte[] signedMessage = TransactionEncoder.signTxEIP155(rawTransaction, <chainId>, credentials);
String hexValue = Hex.toHexString(signedMessage);
McSendTransaction mcSendTransaction = chain3j.SendRawTransaction(hexValue).send();
// ...
Although it’s far simpler using chain3j’s Transfer for transacting with Mc.
Using an MOAC client’s admin commands (make sure you have your wallet in the client’s keystore):
Admin chain3j = Admin.build(new HttpService()); // defaults to http://localhost:8545/
PersonalUnlockAccount personalUnlockAccount = chain3j.personalUnlockAccount("0x000...", "a password").sendAsync().get();
if (personalUnlockAccount.accountUnlocked()) {
// send a transaction
}
Command line tools¶
A chain3j fat jar is distributed with each release providing command line tools. The command line tools allow you to use some of the functionality of chain3j from the command line:
- Wallet creation
- Wallet password management
- Transfer of funds from one wallet to another
- Generate Solidity smart contract function wrappers
Further details¶
In the Java 8 build:
- chain3j provides type safe access to all responses. Optional or null responses are wrapped in Java 8’s Optional type.
- Asynchronous requests are wrapped in a Java 8 CompletableFutures. chain3j provides a wrapper around all async requests to ensure that any exceptions during execution will be captured rather then silently discarded. This is due to the lack of support in CompletableFutures for checked exceptions, which are often rethrown as unchecked exception causing problems with detection. See the Async.run() and its associated test for details.
In both the Java 8 and Android builds:
- Quantity payload types are returned as BigIntegers. For simple results, you can obtain the quantity as a String via Response.getResult().
- It’s also possible to include the raw JSON payload in responses via the includeRawResponse parameter, present in the HttpService and IpcService classes.
Build instructions¶
chain3j includes integration tests for running against a live MOAC client. If you do not have a client running, you can exclude their execution as per the below instructions.
To see the compile options:
$ ./gradlew tasks
To run a full build (excluding integration tests):
$ ./gradlew check
Sample maven configuration:
<repositories>
<repository>
<id>sonatype-snasphots</id>
<name>Sonatype snapshots repo</name>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
</repositories>
Thanks and credits¶
- The Web3j project for the framework
- The Nethereum project for the inspiration
- Othera for the great things they are building on the platform
- Finhaus guys for putting me onto Nethereum
- bitcoinj for the reference Elliptic Curve crypto implementation
- Everyone involved in the Ethererum project and its surrounding ecosystem
- And of course the users of the library, who’ve provided valuable input & feedback
Chain3 Python 软件库¶
安装¶
Chain3 python package supports python3.5.3 and up.
Chain3 python can be installed (preferably in a virtualenv) using pip as follows:
$ pip install chain3
If you run into problems during installation, you might have a broken environment, such as you are on an unsupported version of Python or another package might be installed that has a name or version conflict Often, the best way to guarantee a correct environment is with virtualenv, like:
$ which pip || curl https://bootstrap.pypa.io/get-pip.py | python
$ which virtualenv || pip install --upgrade virtualenv
$ sudo pip install virtualenv
$ virtualenv -p python3 ~/.venv-py3
$ source ~/.venv-py3/bin/activate
$ pip install --upgrade pip setuptools
$ pip install --upgrade chain3
To use the virtualenv next time, run the following command:
$ source ~/.venv-py3/bin/activate
Using Chain3¶
from chain3 import Chain3
chain3 = Chain3(Chain3.HTTPProvider("http://127.0.0.1:8545", request_kwargs={'timeout': 30}))
Chain3 API¶
1. chain3.version.network:¶
Returns the current network id. For MOAC, mainnet network id = 99, testnet network id = 101.
print('network id:'+ str(chain3.version.network))
2. chain3.HTTPProvider:¶
Convenience API to access chain3.providers.rpc.HTTPProvider
Chain3(Chain3.HTTPProvider("http://127.0.0.1:8545", request_kwargs={'timeout': 30}))
3. chain3.sha3(string,options)¶
string:The string to hash using the SHA3 algorithm. options:optional,need set to hex for HEX string.
hash = chain3.sha3("the string to be hashed");
print(hash);
hashOfHash = chain3.sha3(hash,{encoding:'hex'});
print(hashOfHash);
4. chain3.net.peerCount:¶
This property is read only and returns the number of connected peers.
peerCount = chain3.net.peerCount;
print(peerCount);
5. chain3.net.listening:¶
This property is read only and says whether the node is actively listening for network connections or not.
listenState = chain3.net.listening;
print(listenState);
6. chain3.mc.coinbase:¶
Returns the current Coinbase address.
nodeCoinbase = chain3.mc.coinbase;
print(nodeCoinbase);
7. chain3.mc.mining:¶
Returns boolean as to whether the node is currently mining.
miningState = chain3.mc.mining;
print(miningState); //true or false
8. chain3.mc.accounts:¶
Returns the list of known accounts.
nodeAccounts = chain3.mc.accounts;
print(nodeAccounts);
9. chain3.mc.blockNumber:¶
Returns the number of the most recent block
nowBlockNumber = chain3.mc.blockNumber;
print(nowBlockNumber);
10. chain3.mc.getBlockTransactionCount(block_identifier):¶
Returns the number of transactions in the block specified by block_identifier.
Delegates to mc_getBlockTransactionCountByNumber if block_identifier is an integer or one of the predefined block parameters ‘latest’, ‘earliest’, ‘pending’, otherwise delegates to mc_getBlockTransactionCountByHash.
transactionCount = chain3.mc.getBlockTransactionCount(96160);
print(transactionCount);
11. chain3.mc.getBalance(account, block_identifier=mc.defaultBlock):¶
Returns the balance of the given account at the block specified by block_identifier.
account may be a hex address or an ENS name
balance = chain3.mc.getBalance("0x36eaa71d7383be53cb600743aad08a55222a4915", block_identifier=chain3.mc.defaultBlock);
print("getBalance1" + balance); //instanceof BigNumber
print("getBalance2" + balance.toString(10));
//Result: getBalance1:3.04527226722e+21
// getBalance2:3045272267220000000000
12. chain3.mc.defaultBlock:¶
The default block number that will be used for any RPC methods that accept a block identifier. Defaults to ‘latest’.
defultBlock = chain3.mc.defaultBlock;
print("defaultBlock" + defultBlock);
//default is latest,
chain3.mc.defaultBlock = 123;
print("defaultBlock" + defultBlock);
13. chain3.mc.gasPrice:¶
Returns the current gas price in Sha = 1e-18 mc. GasPrice is calculated from most recent blocks.
gasPrice = chain3.mc.gasPrice;
print(gasPrice.toString(10));
14. chain3.mc.estimateGas(transaction_params=None):¶
Uses the selected gas price strategy to calculate a gas price. This method returns the gas price denominated in sha. The transaction_params argument is optional however some gas price strategies may require it to be able to produce a gas price.
result = chain3.mc.estimateGas({
to :"0xf7ebc6b854a202efe08e91422a44ba2161ed50dc",
data: '0x23455654'
//gas: 11, //Optional, gaslimit of the TX
//gasPrice: 11 //Optional, gasPrice
});
print('estimateGas :'+ result);
//Output:gasprice :20000000000
// estimateGas :1273
15. chain3.mc.getCode(account, block_identifier=mc.defaultBlock):¶
Returns the bytecode for the given account at the block specified by block_identifier. account may be a hex address or an ENS name
code = chain3.mc.getCode("0x0000000000000000000000000000000000000065");//contract address
16. chain3.mc.syncing:¶
Returns either False if the node is not syncing or a dictionary showing sync status.
sync = chain3.mc.syncing;
print('syncing :'+ sync );
//
AttributeDict({
'currentBlock': 2177557,
'highestBlock': 2211611,
'knownStates': 0,
'pulledStates': 0,
'startingBlock': 2177365,
})
17. chain3.mc.getTransaction(transaction_hash):¶
blockHash = "0x6aa4a0db1fc155009bd9ba3a64c1aef109e1418dc05ee241d3e9e3e58d7f3eeb";
transaction = chain3.mc.getTransaction(blockHash);
print('get transaction:'+ str(transaction));
/* Result:
get transaction: AttributeDict({
'blockHash': HexBytes('0x77483002572dd29b58640c4ccf5ef30278679037ff17b51cf613f3df562e5e0a'),
'blockNumber': 815006,
'from': '0x0000000000000000000000000000000000000064',
'gas': 0,
'gasPrice': 20000000000,
'hash': HexBytes('0x6aa4a0db1fc155009bd9ba3a64c1aef109e1418dc05ee241d3e9e3e58d7f3eeb'),
'input': '0xc1c0e9c4',
'nonce': 815005,
'syscnt': '0x65',
'to': '0x0000000000000000000000000000000000000065',
'transactionIndex': 0,
'value': 0,
'v': 0, 'r': HexBytes('0x00'), 's': HexBytes('0x00'),
'shardingFlag': 0})
*/
18. chain3.mc.getBlock(block_identifier=mc.defaultBlock, full_transactions=False):¶
Returns the block specified by block_identifier. Delegates to mc_getBlockByNumber if block_identifier is an integer or one of the predefined block parameters ‘latest’, ‘earliest’, ‘pending’, otherwise delegates to mc_getBlockByHash.
If full_transactions is True then the ‘transactions’ key will contain full transactions objects. Otherwise it will be an array of transaction hashes.
getTheBlock = chain3.mc.getBlock(815006);
print('get the block: '+ str(getTheBlock));
/* Result:
get the block({
'difficulty': 86803583,
'extraData': HexBytes('0xdd854d4f41432d85312e302e312d87676f312e392e358777696e646f7773'),
'gasLimit': 9000000,
'gasUsed': 0,
'hash': HexBytes('0x77483002572dd29b58640c4ccf5ef30278679037ff17b51cf613f3df562e5e0a'),
'logsBloom': HexBytes('0x00000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000'),
'miner': '0x0a2168D2f08161c01745fEC4e6E8FE06F314Ab41',
'mixHash': HexBytes('0xc154897a85ca63bbbbb76b618a288f6b33f7d2994848dc9c43c6d65e6a5da355'),
'nonce': HexBytes('0x829f5b23cdf8224f'),
'number': 815006,
'parentHash': HexBytes('0x73c0e4a94b48b41bf5a6a22151e38799a0e17e8b798848af5340f6d725027af1'),
'receiptsRoot': HexBytes('0x9287370eb27f11b0c2188431cbc58a23b685f02dbd851ed4d974f932bd780839'),
'sha3Uncles': HexBytes('0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347'),
'size': 590,
'stateRoot': HexBytes('0x615d0a39783ae546e11aa0cd6e00c70c2ec989f51316c0f9e07cfc99f1088669'),
'timestamp': 1535530608,
'totalDifficulty': 136959813601540,
'transactions': [HexBytes('0x6aa4a0db1fc155009bd9ba3a64c1aef109e1418dc05ee241d3e9e3e58d7f3eeb')],
'transactionsRoot': HexBytes('0x7aba2a9c974693f1cfb96d506e6aa62942a174b4df39c831cf844a35e03249f0'),
'uncles': []
})
*/
19. chain3.personal.unlockAccount(account, passphrase, duration=None):¶
Unlocks the given account for duration seconds. If duration is None then the account will remain unlocked indefinitely. Returns boolean as to whether the account was successfully unlocked.
chain3.personal.unlockAccount(mc.accounts[0], 'password')
20. chain3.miner.start(num_threads):¶
Start the CPU mining process using the given number of threads.
chain3.miner.start(2) # number of threads
22. chain3.miner.setGasPrice(gas_price):¶
Sets the minimum accepted gas price that this node will accept when mining transactions. Any transactions with a gas price below this value will be ignored.
chain3.miner.setGasPrice(19999999999)
23. chain3.mc.getTransactionReceipt((transaction_hash, timeout=120):¶
Returns the transaction receipt specified by transaction_hash. If the transaction has not yet been mined returns None
txr = chain3.mc.getTransactionReceipt('0x77483002572dd29b58640c4ccf5ef30278679037ff17b51cf613f3df562e5e0a')
print(txr)
/* Result:
AttributeDict({
'blockHash': HexBytes('0x77483002572dd29b58640c4ccf5ef30278679037ff17b51cf613f3df562e5e0a'),
'blockNumber': 815006,
'contractAddress': '0x0000000000000000000000000000000000000065',
'cumulativeGasUsed': 0,
'from': '0x0000000000000000000000000000000000000064',
'gasUsed': 0,
'logs': [],
'logsBloom': HexBytes('0x00000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000'),
'status': 1,
'to': '0x0000000000000000000000000000000000000065',
'transactionHash': HexBytes('0x6aa4a0db1fc155009bd9ba3a64c1aef109e1418dc05ee241d3e9e3e58d7f3eeb'),
'transactionIndex': 0})
*/
24. chain3.mc.getTransactionCount((block_identifier):¶
Returns the number of transactions that have been sent from account as of the block specified by block_identifier.
chain3.mc.getTransactionCount('0x87E369172Af1e817ebD8d63bcD9f685A513a6736', block_identifier=chain3.mc.defaultBlock)
25. chain3.mc.sendTransaction(transaction, passphrase):¶
Signs and sends the given transaction
The transaction parameter should be a dictionary with the following fields.
- from: bytes or text, hex address or ENS name - (optional, default: chain3.mc.defaultAccount) The address the transaction is send from.
- to: bytes or text, hex address or ENS name - (optional when creating new contract) The address the transaction is directed to.
- gas: integer - (optional) Integer of the gas provided for the transaction execution. It will return unused gas.
- gasPrice: integer - (optional, default: To-Be-Determined) Integer of the gasPrice used for each paid gas
- value: integer - (optional) Integer of the value send with this transaction
- data: bytes or text - The compiled code of a contract OR the hash of the invoked method signature and encoded parameters.
- nonce: integer - (optional) Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce.
If the transaction specifies a data value but does not specify gas then the gas value will be populated using the estimateGas() function with an additional buffer of 100000 gas up to the gasLimit of the latest block. In the event that the value returned by estimateGas() method is greater than the gasLimit a ValueError will be raised.
- shardingFlag:integer - (optional for Global Transactions), MicroChain flag, default value is 0 for Global TXs. To call MicroChain, this value has to be 1.
- via: bytes or text, hex addres - (optional for Global Transactions), vode beneficial address, default is null for Global TXs. For microChain call
chain3.mc.sendTransaction({
'to':'0xf103BC1c054baBcecD13e7AC1CF34F029647B08C',
'from':'0x87E369172Af1e817ebD8d63bcD9f685A513a6736',
'value': 100000,
'gasPrice': chain3.mc.gasPrice,
'shardingFlag': 0,
'via': '0x0000000000000000000000000000000000000000',})
26. chain3.mc.sendRawTransaction(raw_transaction):¶
Sends a signed and serialized transaction. Returns the transaction hash.
private_key = '0x94645c7a048771045f90e0b88adf3ddf5afbb5029c2b1b5586d5afa9ba87c8f5'
signed_txn = chain3.mc.account.signTransaction(
dict(
nonce=chain3.mc.getTransactionCount(chain3.mc.coinbase),
gasPrice=chain3.mc.gasPrice,
gas=100000,
to='0xf103BC1c054baBcecD13e7AC1CF34F029647B08C',
value=100000,
data='0x',
'chainId': networkid,
'shardingFlag': 0,
'via': '0x',
),
private_key,
)
chain3.mc.sendRawTransaction(signed_txn.rawTransaction)
/* Result: tx hash
'0xd7e3a30f9eec70d5626b70a2082bd2573a2b0a282756479c2f48a57a833204ab'
*/
子链¶
名词解释¶
Vnode¶
墨客主网(母链)节点,用于主网挖矿,主网账本同步,主网交易以及子链数据传输的节点。
Scs¶
墨客子链节点,用于子链挖矿,子链账本同步以及子链业务逻辑执行的节点,也称为子链矿工
子链矿工池¶
存储子链矿工的池子,本质上池子是一个智能合约,需要子链节点注册
vnode代理池¶
存储vnode代理节点,本质上池子是一个智能合约,需要vnode节点
子链控制合约¶
用于控制整个子链的流程
监听节点(Monitor)¶
监听节点是一个特殊的Scs节点,可以用来监听某条子链的运行情况,当一个节点成为监听节点后,其只负责同步该子链的区块信息,不参与子链出块。Dapp用户可以通过该节点监控子链运行情况
flush¶
子链的一个特殊操作,每条正常运行的子链每隔一段时间需要向母链进行状态刷新,并且同时完成:Scs矿工的收益发放;有币子链和母链之间的货币充提等操作。flush周期可在部署子链控制合约时设置,当子链交易数不活跃时,flush周期将变大,直到有交易时收敛到设置值
子链多合约基础合约¶
1.0.8版本后的新功能,用于在子链上部署多合约的基础控制合约
子链要点¶
概述¶
子链是在母链之上的独立的区块链系统,子链中的每个节点称为scs,scs的通讯通过母链,并定期向母链进行数据背书。子链上可以单独跑业务逻辑,母链无需知道。
母链账户地址和子链账户地址是同一体系,可以通用,但在在不同的链上为不同链的货币进行服务,互相之间除非充提否则没有联系。
母链上可以跑多条子链,墨客采用分片技术,随机将scs分配给不同的子链。
子链需要依赖于母链来运行,因此,运行一条子链需要M个母链节点(vnode)和N个子链节点(scs)。
普通子链节点scs可以称作子链矿工,其主要负责子链的出块,是维持一条子链稳定安全运行的根本。
子链节点下的母链节点,需要选取一部分注册成vnode代理的节点,vnode代理节点的作用是用于维护子链稳定运行,vnode代理节点同样有一个代理矿工池
部署子链控制合约时需要指定以上两个池子的地址。
子链合约部署完后,即可调用registeropen来召唤池子里的scs注册;当数量达到预期后,就可以调用registerclose来初始化子链区块,让子链开始运行。
子链需要每隔一段时间发起flush操作,将关键状态写入母链进行背书。除此之外,flush还将完成节点收益分配和有币区块链的母子链充提操作。
可以调用子链控制合约里的registerasmonitor来将一个子链节点注册成一个侦听节点。侦听节点只负责信息查询,不参与普通子链节点的服务,适合dapp用户部署来监控子链运行状态。
如果普通子链节点状态不稳定或弄虚作假,在flush的时候,有几率被没收押金,强制退出这条子链的服务。这时,可以调用子链控制合约的registeradd方法,将scs池子里的其他scs作为备用节点来为这条子链服务。
部署子链方可以调用子链控制合约的close方法关闭这条子链。此时会进入清算状态,待所有子链收益结清后,即关闭子链。请注意,子链业务逻辑清算不包含。
子链节点本身可以调用子链控制合约的withdraw方法来结束为某一子链服务,并得到返还的押金。
子链中的MOAC押金和消耗¶
为了使子链安全稳定的运行,MOAC引入的押金机制,主要体现在以下几个方面:
1、每个子链节点在第一次启动后,将会有一个唯一的墨客钱包地址,在部署子链前,需要在向这个地址打入至少1个MOAC作为运行费用;
2、每个子链节点注册进入子链矿工池时,需要向矿工池缴纳一定的押金,最小值由子链控制合约设置,最大值不限。子链节点每被选中一次,将会扣除一定数额的押金,当押金被扣完后,该节点将不会再参与新的子链,退出子链时,可以调用方法取回押金;
3、当一个子链节点注册成一个监听节点时,需要缴纳一定的押金;当退出子链时可以取回押金;
4、押金一般不会扣除,但在flush时,如果有企图作弊的节点,将会按照规则踢出子链,并扣除押金,不再返还;
维护子链的MOAC消耗:
首先,调用子链方法不会消耗任何gas,但是,dapp运营方需要向子链控制合约地址打入一定量的MOAC维持子链运行,这部分MOAC将会消耗在给子链矿工费用、子链向母链flush状态,以及母链充提gas返还上。这个维护消耗可以通过调整子链的flush周期来部分改变。
子链部署的注意点¶
1、子链scs的vnode需要互相addPeer以保证通讯畅通。同时,这些vnode建议尽量add外面的节点以保证主链高度一致,并且保证时钟同步。
2、子链scs的时钟请同步互联网标准时间。
部署子链前的准备工作¶
Vnode节点¶
墨客主网节点 版本来源: https://github.com/MOACChain/moac-core/releases/
此文档采用的版本: 1.0.9 环境:windows testnet浏览器: http://testnet.moac.io/home
- 在测试环境testnet启动节点:
- moac-windows-4.0-amd64.exe –testnet –rpc –rpcapi “chain3,mc,net,db,personal,admin,miner”
验证:
windows command 执行 moac-windows-4.0-amd64.exe attach \\.\pipe\moac.ipc
运行concole命令 mc.blockNumber 检查是否同步到最新区块
SCS节点¶
墨客子链节点 版本来源: https://github.com/MOACChain/moac-core/releases/
此文档采用的版本: 1.0.9 环境:windows
userconfig.json配置:
VnodeServiceCfg为代理vnode地址: 192.168.10.209:50062 (对应上面部署的vnode的IP)
Beneficiary为收益账号
- 启动节点:
- scsserver-windows-4.0-amd64 –password “123456” (生成scs keystore的密码)
验证:
scs启动后,并开始从vnode同步块号信息。
在scskeystore目录内生成的keystore文件中生成scs账号的scskeystore文件。
各类账号¶
可以运行concole命令 personal.newAccount() 创建账号; mc.accounts查看账号;
按序号查询余额:mc.getBalance(mc.accounts[0])
测试环境的公共提币地址:https://faucet.moacchina.com
注意:后续消耗gas的操作都需要执行personal.unlockAccount(mc.accounts[0]) 对应账号进行解锁
准备账号列表:(示例地址参考后续的命令操作)
子链操作账号:进行创建合约,发起交易等基本操作: 0x87e369172af1e817ebd8d63bcd9f685a513a6736
主链vnode收益账号: 0xf103bc1c054babcecd13e7ac1cf34f029647b08c
子链scs收益账号:0xa934198916cd993c73c1aa6e0c0e7b21ce7c735b 0x2e7c076dbf6e61207a0ddb1b942ef7da8fd139f0
chain3 的 nodejs 环境¶
安装: npm install chain3
验证:
> chain3 = require('chain3');
> chain3 = new chain3();
> chain3.setProvider(new chain3.providers.HttpProvider('http://localhost:8545'));
> chain3.mc.blockNumber 检查是否获得当前区块
子链的部署方法¶
部署Vnode矿池合约¶
首先部署vnode矿池合约,VnodeProtocolBase,如果加入现成的vnode矿池,则可以忽略此步骤。
加入矿池的代理Vnode节点被用于提供子链调用服务和子链历史数据中转服务的节点。
以下为nodejs部署示例:最低保证金为 2 moac
> chain3 = require('chain3')
> solc = require('solc')
> chain3 = new chain3();
> chain3.setProvider(new chain3.providers.HttpProvider('http://localhost:8545'));
> solfile = 'VnodeProtocolBase.sol';
> contract = fs.readFileSync(solfile, 'utf8');
> output = solc.compile(contract, 1);
> abi = output.contracts[':VnodeProtocolBase'].interface;
> bin = output.contracts[':VnodeProtocolBase'].bytecode;
> VnodeProtocolBaseContract = chain3.mc.contract(JSON.parse(abi));
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> VnodeProtocolBase = VnodeProtocolBaseContract.new( 2, { from: chain3.mc.accounts[0], data: '0x' + bin, gas: '5000000'});
> chain3.mc.getTransactionReceipt(VnodeProtocolBase.transactionHash).contractAddress
部署完毕后,获得 vnode矿池合约地址 0x22f141dcc59850707708bc90e256318a5fe0b928
vnode 设置代理并加入矿池¶
修改vnode目录配置文件vnodeconfig.json: VnodeBeneficialAddress里设置收益账号: 0xf103bc1c054babcecd13e7ac1cf34f029647b08c
这个账号也作为vnode的address,矿池中对应这个vnode的唯一编号
调用vnode矿池合约register方法加入矿池
参数:
from: 子链测试账号
value:押金,必须大于矿池合约的设置值
to: vnode矿池合约地址
data: register(address,string)
关于data传递调用register参数说明:
根据ABI chain3.sha3("register(address,string)") = 0x32434a2e90725ed590daff07a244305001c58c49f7bef73ce5e7249acf69f561
取前4个字节 0x32434a2e
第一个参数address 传 vnodeconfig.json的VnodeBeneficialAddress (前面补24个0, 凑足32个字节)
000000000000000000000000f103bc1c054babcecd13e7ac1cf34f029647b08c
第二个参数string传 vnode提供给子链的调用地址 192.168.10.209:50062
端口号对应vnodeconfig.json的VnodeServiceCfg
string数据类型 + string数据长度 + string内容
string数据类型: 0000000000000000000000000000000000000000000000000000000000000040
string内容: data = new Buffer('192.168.10.209:50062', 'utf8').toString('hex');
后面补0, 凑足32个字节 3139322e3136382e31302e3230393a3530303632000000000000000000000000
string数据长度: 3139322e3136382e31302e3230393a3530303632 20字节
0000000000000000000000000000000000000000000000000000000000000014
data = '0x32434a2e000000000000000000000000f103bc1c054babcecd13e7ac1cf34f029647b08c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000143139322e3136382e31302e3230393a3530303632000000000000000000000000'
也可以调用合约对象的getData方法获得data参数
data = VnodeProtocolBase.register.getData(via, '192.168.10.209:50062')
调用示例:
> amount = chain3.toSha(5,'mc')
> data = '0x32434a2e000000000000000000000000f103bc1c054babcecd13e7ac1cf34f029647b08c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000143139322e3136382e31302e3230393a3530303632000000000000000000000000';
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> chain3.mc.sendTransaction({ from: chain3.mc.accounts[0], value:amount, to: '0x22f141dcc59850707708bc90e256318a5fe0b928', gas: "5000000", gasPrice: chain3.mc.gasPrice, data: data });
验证: 访问Vnode矿池合约的vnodeCount
> VnodeProtocolBase.vnodeCount()
> chain3.mc.getStorageAt("0x22f141dcc59850707708bc90e256318a5fe0b928",0x02) // 注意vnodeCount变量在合约中变量定义的位置(16进制)
部署子链矿池¶
目前针对不同的共识协议,可以创建对应的子链矿池,接受对应SCS的注册,并缴纳保证金,进入矿池后,成为子链的候选节点
如果加入现成的子链矿池,则可以忽略此步骤
部署SubChainProtocolBase.sol示例: 共识:POR 最低保证金: 2 moac
> chain3 = require('chain3')
> solc = require('solc')
> chain3 = new chain3();
> chain3.setProvider(new chain3.providers.HttpProvider('http://localhost:8545'));
> solfile = 'SubChainProtocolBase.sol';
> contract = fs.readFileSync(solfile, 'utf8');
> output = solc.compile(contract, 1);
> abi = output.contracts[':SubChainProtocolBase'].interface;
> bin = output.contracts[':SubChainProtocolBase'].bytecode;
> subchainprotocolbaseContract = chain3.mc.contract(JSON.parse(abi));
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> subchainprotocolbase = subchainprotocolbaseContract.new( "POR", 2, { from: chain3.mc.accounts[0], data: '0x' + bin, gas: '5000000'});
> chain3.mc.getTransactionReceipt(subchainprotocolbase.transactionHash).contractAddress
部署完毕后,获得子链矿池合约地址 0xe42f4f566aedc3b6dd61ea4f70cc78d396130fac
设置启动scs¶
这里我们设置三个scs节点
确认 userconfig.json配置
VnodeServiceCfg为代理vnode地址: 192.168.10.209:50062
Beneficiary为收益账号:
0xa934198916cd993c73c1aa6e0c0e7b21ce7c735b
0x2e7c076dbf6e61207a0ddb1b942ef7da8fd139f0
0xea1a118e94344be69f02753d1e6f7fe19dda89ac
分别通过命令启动 scsserver-windows-4.0-amd64 –password “123456” (生成scs keystore的密码)
然后在scskeystore目录内生成的keystore文件中分别获得 scs 地址
0xd4057328a35f34507dbcd295d43ed0cccf9c368a
0x3e21ba36b396936c6cc9adc3674655b912e5fa54
0x03c74ecc8ad9493a6a3d14f4e48d5eb551fe1be5
最后给scs转入moac以支付必要的交易费用
> amount = 20;
> scsaddr = '0xd4057328a35f34507dbcd295d43ed0cccf9c368a';
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> chain3.mc.sendTransaction( { from: chain3.mc.accounts[0], value:chain3.toSha(amount,'mc'), to: scsaddr, gas: "2000000", gasPrice: chain3.mc.gasPrice, data: ''});
> scsaddr = '0x3e21ba36b396936c6cc9adc3674655b912e5fa54';
> chain3.mc.sendTransaction( { from: chain3.mc.accounts[0], value:chain3.toSha(amount,'mc'), to: scsaddr, gas: "2000000", gasPrice: chain3.mc.gasPrice, data: ''});
> scsaddr = '0x03c74ecc8ad9493a6a3d14f4e48d5eb551fe1be5';
> chain3.mc.sendTransaction( { from: chain3.mc.accounts[0], value:chain3.toSha(amount,'mc'), to: scsaddr, gas: "2000000", gasPrice: chain3.mc.gasPrice, data: ''});
可以通过查询余额进行验证
> chain3.mc.getBalance('0xd4057328a35f34507dbcd295d43ed0cccf9c368a')
> chain3.mc.getBalance('0x3e21ba36b396936c6cc9adc3674655b912e5fa54')
> chain3.mc.getBalance('0x03c74ecc8ad9493a6a3d14f4e48d5eb551fe1be5')
将scs加入子链矿池¶
调用子链矿池合约register方法加入矿池
参数:
from: 子链测试账号
value:押金,必须大于矿池合约的设置值
to: 子链矿池合约地址
data: register(address)
关于data传递调用register参数说明:
根据ABI chain3.sha3("register(address)") = 0x4420e4869750c98a56ac621854d2d00e598698ac87193cdfcbb6ed1164e9cbcd
取前4个字节 0x4420e486
参数address传scs 地址 d4057328a35f34507dbcd295d43ed0cccf9c368a (前面补24个0, 凑足32个字节)
000000000000000000000000d4057328a35f34507dbcd295d43ed0cccf9c368a
data = '0x4420e486000000000000000000000000d4057328a35f34507dbcd295d43ed0cccf9c368a'
调用示例:
> amount = chain3.toSha(5,'mc')
> data = '0x4420e486000000000000000000000000d4057328a35f34507dbcd295d43ed0cccf9c368a';
> chain3.mc.sendTransaction({ from: chain3.mc.accounts[0], value:amount, to: '0xe42f4f566aedc3b6dd61ea4f70cc78d396130fac', gas: "5000000", gasPrice: chain3.mc.gasPrice, data: data });
验证: 访问子链矿池合约的scsCount
> subchainprotocolbase.scsCount()
同上将另两个scs也加入子链矿池
部署子链合约¶
现在我们可以部署一个子链合约
部署SubChainBase.sol示例:
> chain3 = require('chain3')
> solc = require('solc')
> chain3 = new chain3();
> chain3.setProvider(new chain3.providers.HttpProvider('http://localhost:8545'));
> input = {'': fs.readFileSync('SubChainBase.sol', 'utf8'), 'SubChainProtocolBase.sol': fs.readFileSync('SubChainProtocolBase.sol', 'utf8')};
> output = solc.compile({sources: input}, 1);
> abi = output.contracts[':SubChainBase'].interface;
> bin = output.contracts[':SubChainBase'].bytecode;
> proto = '0xe42f4f566aedc3b6dd61ea4f70cc78d396130fac' ; // 子链矿池合约
> vnodeProtocolBaseAddr = '0x22f141dcc59850707708bc90e256318a5fe0b928' ; // Vnode矿池合约
> min = 1 ; // 子链需要SCS的最小数量,当前需要从如下值中选择:1,3,5,7
> max = 11; // 子链需要SCS的最大数量,当前需要从如下值中选择:11,21,31,51,99
> thousandth = 1 ; // 千分之几,控制选择scs的概率,对于大型子链矿池才有效
> flushRound = 40 ; // 子链刷新周期 单位是主链block生成对应数量的时间,当前的取值范围是40-99
> SubChainBaseContract = chain3.mc.contract(JSON.parse(abi));
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> SubChainBase = SubChainBaseContract.new( proto, vnodeProtocolBaseAddr, min, max, thousandth, flushRound,{ from: chain3.mc.accounts[0], data: '0x' + bin, gas:'9000000'} , function (e, contract){console.log('Contract address: ' + contract.address + ' transactionHash: ' + contract.transactionHash); });
部署完毕后, 获得子链合约地址 0x1195cd9769692a69220312e95192e0dcb6a4ec09
子链开放注册¶
首先子链合约需要最终提供gas费给scs,需要给子链控制合约发送一定量的moac,调用合约里的函数addFund
根据ABI chain3.sha3("addFund()") = 0xa2f09dfa891d1ba530cdf00c7c12ddd9f6e625e5368fff9cdf23c9dc0ad433b1
取前4个字节 0xa2f09dfa
> amount = 20;
> subchainaddr = '0x1195cd9769692a69220312e95192e0dcb6a4ec09';
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> chain3.mc.sendTransaction( { from: chain3.mc.accounts[0], value:chain3.toSha(amount,'mc'), to: subchainaddr, gas: "2000000", gasPrice: chain3.mc.gasPrice, data: '0xa2f09dfa'});
可以通过查询余额进行验证
> chain3.mc.getBalance('0x1195cd9769692a69220312e95192e0dcb6a4ec09')
然后调用 调用合约里的函数registerOpen 开放注册 (按子链矿池合约中SCS注册先后排序进行选取)
根据ABI chain3.sha3("registerOpen()") = 0x5defc56ce78f178d760a165a5528a8e8974797e616a493970df1c0918c13a175
取前4个字节 0x5defc56c
> subchainaddr = '0x1195cd9769692a69220312e95192e0dcb6a4ec09';
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> chain3.mc.sendTransaction( { from: chain3.mc.accounts[0], value:0, to: subchainaddr, gas: "2000000", gasPrice: chain3.mc.gasPrice, data: '0x5defc56c'});
验证: 等待scs注册 (vnode 一个 flush周期后 ) , 可不断访问子链合约的 nodeCount,等待3个scs注册完成
> SubChainBase.nodeCount()
> chain3.mc.getStorageAt(subchainaddr,0x0e) // 注意nodeCount变量在合约中变量定义的位置(16进制)
子链关闭注册¶
等到两个scs都注册完毕后,即注册SCS数目大于等于子链要求的最小数目时,调用子链合约里的函数 registerClose关闭注册
根据ABI chain3.sha3("registerClose()") = 0x69f3576fc10c82561bd84b0045ee48d80d59a866174f2513fdef43d65702bf70
取前4个字节 0x69f3576f
> subchainaddr = '0x1195cd9769692a69220312e95192e0dcb6a4ec09';
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> chain3.mc.sendTransaction( { from: chain3.mc.accounts[0], value:0, to: subchainaddr, gas: "2000000", gasPrice: chain3.mc.gasPrice, data: '0x69f3576f'});
验证: SCS自身完成初始化并开始子链运行,可观察scs的concole界面,scs开始出块即成功完成部署子链。
子链业务逻辑的部署¶
同主链相同,业务逻辑的实现也通过智能合约的方式。
在1.0.8及之后的版本中,加入的子链多合约的功能。子链多合约功能指的是在一条子链上部署多个子链业务逻辑合约,又称DAPP的功能。
多合约部署准备工作¶
需要有一条已经在运行的子链,具体部署方法可参见“子链部署方法”。
假设有两个业务逻辑合约dapp1.sol和dapp2.sol。
从发布链接下载多合约基础合约dappbase.sol
DAPP智能合约的部署(多合约版)¶
DAPP智能合约也通过主链的sendTransaction发送交易到 proxy vnode 的方式进行部署。
参数:
to: 子链控制合约subchainbase的地址
gas: 不需要消耗gas费用,传值:0
shardingflag:表示操作子链, 传值:0x3,请注意,多合约版本部署任何合约shardingflag都为0x3
via: 对应 proxy vnode 的收益地址
STEP1:在子链上部署多合约基础合约 DappBase.sol
!!!特别注意!!!:目前子链原生币支持moac和erc20两种兑换方式,交易values分别对应subchainbase的tokensupply和erc20的totalsupply,这个值必须对应,否则将会导致dappbase部署失败。细节详见母子链货币交互章节
部署示例(以下在nodeJs console中进行):
> chain3 = require('chain3')
> solc = require('solc')
> chain3 = new chain3();
> chain3.setProvider(new chain3.providers.HttpProvider('http://localhost:8545'));
> solfile = 'DappBase.sol';
> contract = fs.readFileSync(solfile, 'utf8');
> output = solc.compile(contract, 1);
> abi = output.contracts[':DappBase'].interface;
> bin = output.contracts[':DappBase'].bytecode;
> subchainaddr = '0x1195cd9769692a69220312e95192e0dcb6a4ec09';
> via = '0xf103bc1c054babcecd13e7ac1cf34f029647b08c';
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> amount = tokensupply // 注意:amount分别对应subchainbase的tokensupply和erc20的totalsupply,细节详见母子链货币交互章节
> chain3.mc.sendTransaction({from: chain3.mc.accounts[0], value:chain3.toSha(amount,'mc'), to: subchainaddr, gas:0, shardingFlag: "0x3", data: '0x' + bin, nonce: 0, via: via, });
- 验证:
合约部署成功后,Nonce值应该是1 可调用monitor的rpc接口ScsRPCMethod.GetNonce进行检查,具体详见子链接口调用部分。
dapp合约地址:6ab296062d8a147297851719682fb5ffe081f1d3 dapp合约地址可调用monitor的rpc接口ScsRPCMethod.GetReceipt,传入对应Nonce,获得contractAddress字段内容
- STEP2:在子链上部署业务逻辑合约 dapp1.sol,部署方法和上面雷同
- 合约地址可调用monitor的rpc接口ScsRPCMethod.GetReceipt,传入对应Nonce,获得contractAddress字段内容
- STEP3:在子链上部署业务逻辑合约 dapp2.sol,部署方法和上面雷同
- 合约地址可调用monitor的rpc接口ScsRPCMethod.GetReceipt,传入对应Nonce,获得contractAddress字段内容
DAPP智能合约的调用¶
DAPP智能合约的调用也通过主链的sendTransaction发送交易到 proxy vnode 的方式进行。
在多合约版本中,调用dapp方法前,需要先调用dappbase中的registerDapp方法来注册每一个dapp,具体方式如下:
请注意,与母链调用不同,子链的任何调用需要在data前加上dapp的合约地址!!
dappbase.sol有个方法 registerDapp(address,address,string)
参数:
to: 子链控制合约subchainbase的地址
nonce:调用monitor的rpc接口ScsRPCMethod.GetNonce获得
gas: 0 不需要消耗gas费用
shardingflag: 0x1 表示子链调用操作
via: 对应 proxy vnode 的收益地址
data: 调用合约地址 + registerDapp(address,address,string)对应参数
registerDapp中,第一个参数是想要注册的dapp的地址(dapp1和dapp2的地址),可以通过RPC getReciipt方法获得部署时contract address;第二个参数是创建dappbase时的from,也就是只有创建dappbase的人才能调用此方法;第三个参数是这个dapp的ABI。
调用示例:
> nonce = 3
> addr_dapp = 需要注册dapp的合约地址
> abi = 需要注册dapp的abi
> data = dappbase.address + dappbase.registerDapp.getData(addr_dapp, chain3.mc.accounts[0], abi).substring(2)
> subchainaddr = '0x1195cd9769692a69220312e95192e0dcb6a4ec09';
> via = '0xf103bc1c054babcecd13e7ac1cf34f029647b08c';
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> chain3.mc.sendTransaction( { nonce: nonce, from: chain3.mc.accounts[0], value:0, to: subchainaddr, gas:0, shardingFlag:'0x1', data: data, via: via,});
- 验证:
- 每次操作成功后,Nonce会自动增加1 或者直接调用monitor的rpc接口ScsRPCMethod.GetDappAddrList获得合约注册列表的方式进行验证。
以部署dapp1和dapp2为例,需要将这两个业务逻辑合约注册到dappbase中去:
STEP4: 调用dappbase中的registerDapp方法来注册dapp1
STEP5: 调用dappbase中的registerDapp方法来注册dapp2
STEPX: 调用dapp1或dapp2中的业务逻辑
子链的监听及子链接口调用¶
SCS Monitor¶
Monitor是一种特殊的子链SCS节点,其主要可以用于监控子链的状态和数据。
Monitor不参与子链的交易共识,只是同步区块数据,提供数据查询
子链启动的方式与scs区别在于参数不同,主要定义了rpc接口的访问控制
scsserver-windows-4.0-amd64 --password "123456" --rpcdebug --rpcaddr 0.0.0.0 --rpcport 2345 --rpccorsdomain "*"
子链运行后,Monitor可以调用子链控制合约subchainbase中的registerAsMonitor方法进行注册
调用registerAsMonitor参数说明:
> data = subchainbase.registerAsMonitor.getData('0xd135afa5c8d96ba11c40cf0b52952d54bce57363','127.0.0.1:2345')
调用示例:
> subchainbase = SubChainBaseContract.at('0xb877bf4e4cc94fd9168313e00047b77217760930')
> amount = chain3.toSha(1,'mc')
> subchainaddr = '0x1195cd9769692a69220312e95192e0dcb6a4ec09';
> data = subchainbase.registerAsMonitor.getData('0xd135afa5c8d96ba11c40cf0b52952d54bce57363','127.0.0.1:2345')
> chain3.mc.sendTransaction({ from: chain3.mc.accounts[0], value:amount, to: subchainaddr, gas: "5000000", gasPrice: chain3.mc.gasPrice, data: data });
验证: 观察SCS monitor concole界面开始同步子链区块,或者调用子链合约的getMonitorInfo方法
> subchainbase = SubChainBaseContract.at('0xb877bf4e4cc94fd9168313e00047b77217760930')
> subchainbase.getMonitorInfo.call()
子链RPC接口¶
根据子链启动的参数,用户可以访问对应端口,调用接口获取子链相关数据
以调用接口GetScsId为列,获得当前的scs编号,即scs keystore文件中的地址。
关于rpc http的接口访问,可以用类似postman之类的工具进行快捷测试
header设置:
Content-Type = application/json
Accept = application/json
Body设置:
{"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.GetScsId","params":{}}
post返回结果:
{
"jsonrpc": "2.0",
"id": 0,
"result": "0xd135afa5c8d96ba11c40cf0b52952d54bce57363"
}
同时也可以通过nodejs的方式调用
> request = require('request');
> url = "http://127.0.0.1:2345/rpc";
> data = {"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.GetScsId","params":{}};
> request({ url: url, method: "POST", json: true, body: data, headers: {"Content-Type": 'application/json', "Accept": 'application/json'}}, function(error, response, result) {if (!error && response.statusCode == 200) {console.log(result)}});
以下是几个常用的RPC接口及调用body示例(v1.0.9)
*通用类*
此部分接口和子链区块本身相关,业务逻辑无关。
GetNonce:获得子链的nonce,这是调用子链DAPP合约的必要参数之一,每当子链交易发送后会自动加1
SubChainAddr: 子链合约地址
Sender:查询账号, 每个账号在子链有不同的nonce
Body: {"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.GetNonce",
"params":{"SubChainAddr":"0x1195cd9769692a69220312e95192e0dcb6a4ec09",
"Sender":"0x87e369172af1e817ebd8d63bcd9f685a513a6736"
}
}
GetBlockNumber:获得当前子链的区块高度
SubChainAddr: 子链合约地址
Body: {"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.GetBlockNumber",
"params":{"SubChainAddr":"0x1195cd9769692a69220312e95192e0dcb6a4ec09"}
}
GetBlock: 获得当前子链的指定的区块信息
SubChainAddr: 子链合约地址
Sender:查询账号
Body: {"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.GetBlock",
"params":{"number":1000,"SubChainAddr":"0x1195cd9769692a69220312e95192e0dcb6a4ec09"}
}
GetBlocks: 获取某一区间内的区块信息
SubChainAddr: 子链合约地址
Start: 开始block
End: 结束block
Body: {"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.GetBlocks",
"params":{"SubChainAddr":"0x1195cd9769692a69220312e95192e0dcb6a4ec09"
"Start":10, "End":20}
}
GetSubChainInfo:获得当前子链的信息
SubChainAddr: 子链合约地址
Body: {"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.GetSubChainInfo",
"params":{"SubChainAddr":"0x1195cd9769692a69220312e95192e0dcb6a4ec09"}
}
GetTxpool:获得子链交易池信息
SubChainAddr: 子链合约地址
Body: {"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.GetTxpool",
"params":{"SubChainAddr":"0x1195cd9769692a69220312e95192e0dcb6a4ec09"
}
}
GetTxpoolCount:获得子链交易池中不同类型交易的数量
SubChainAddr: 子链合约地址
Body: {"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.GetTxpoolCount",
"params":{"SubChainAddr":"0x1195cd9769692a69220312e95192e0dcb6a4ec09"
}
}
GetBalance:获得对应账号在子链中的余额
SubChainAddr: 子链合约地址
Sender:查询账号
Body: {"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.GetBalance",
"params":{"SubChainAddr":"0x1195cd9769692a69220312e95192e0dcb6a4ec09",
"Sender":"0x87e369172af1e817ebd8d63bcd9f685a513a6736"
}
}
GetDappState:获得子链基础合约合约的状态
SubChainAddr: 子链合约地址
Sender:子链合约地址创建者地址
Body: {"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.GetDappState",
"params":{"SubChainAddr":"0x1195cd9769692a69220312e95192e0dcb6a4ec09",
"Sender":"0x87e369172af1e817ebd8d63bcd9f685a513a6736"
}
}
GetDappAddrList:通过subchainaddr获取子链内所有多合约的地址列表,需要子链业务逻辑合约调用基础合约registerDapp方法后才能生效,具体请参见“母子链货币交互简介”中的示例
SubChainAddr: 子链合约地址
Body: {"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.GetDappAddrList",
"params":{"SubChainAddr":"0x1195cd9769692a69220312e95192e0dcb6a4ec09"
}
}
返回result中,第零位是dappbase的地址,从第一位开始时业务逻辑合约地址
*充提类*
GetExchangeInfo:获得子链指定数量正在充提的信息
SubChainAddr: 子链合约地址
EnteringRecordIndex: 正在充值记录的起始位置(0)
EnteringRecordSize: 正在充值记录的长度
RedeemingRecordIndex: 正在提币记录的起始位置(0)
RedeemingRecordSize: 正在提币记录的长度
Body: {"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.GetExchangeInfo",
"params":{"SubChainAddr":"0x1195cd9769692a69220312e95192e0dcb6a4ec09",
"EnteringRecordIndex":0, "EnteringRecordSize": 10,
"RedeemingRecordIndex":0, "RedeemingRecordSize", 10
}
}
返回中,XXXRecordCount是指总数量
GetExchangeByAddress:获得子链指定账号指定数量的充提信息
SubChainAddr: 子链合约地址
Sender:需要查询的账号地址
EnterRecordIndex: 已经充值记录的起始位置(0)
EnterRecordSize: 已经充值记录的长度
RedeemRecordIndex: 已经提币记录的起始位置(0)
RedeemRecordSize: 已经提币记录的长度
EnteringRecordIndex: 正在充值记录的起始位置(0)
EnteringRecordSize: 正在充值记录的长度
RedeemingRecordIndex: 正在提币记录的起始位置(0)
RedeemingRecordSize: 正在提币记录的长度
Body: {"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.GetExchangeByAddress",
"params":{"SubChainAddr":"0x1195cd9769692a69220312e95192e0dcb6a4ec09",
"EnterRecordIndex":0, "EnterRecordSize": 10,
"RedeemRecordIndex":0, "RedeemRecordSize", 10
"EnteringRecordIndex":0, "EnteringRecordSize": 10,
"RedeemingRecordIndex":0, "RedeemingRecordSize", 10
}
}
返回中,XXXRecordCount是指总数量
*交易类*
此部分接口和交易相关,当有子链交易发生(sf>0),即可以在这里查看交易和交易结果
GetTransactionByNonce: 通过账号和Nonce获取子链的tx信息
SubChainAddr: 子链合约地址
Sender:查询账号
Body: {"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.GetTransactionByNonce",
"params":{"SubChainAddr":"0x1195cd9769692a69220312e95192e0dcb6a4ec09",
"Sender":"0x87e369172af1e817ebd8d63bcd9f685a513a6736", "Nonce":9,
}
}
GetTransactionByHash: 通过交易hash获取子链的tx信息
SubChainAddr: 子链合约地址
Hash: 交易hash
Body: {"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.GetTransactionByHash",
"params":{"SubChainAddr":"0x1195cd9769692a69220312e95192e0dcb6a4ec09",
"Hash":"0x87e369172af1e817ebd8d63bcd9f685a513a6736fsne3lkgkvu65kkwlcd"
}
}
GetReceiptByNonce: 通过账号和Nonce获取子链的tx执行结果
SubChainAddr: 子链合约地址
Sender:查询账号
Body: {"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.GetReceiptByNonce",
"params":{"SubChainAddr":"0x1195cd9769692a69220312e95192e0dcb6a4ec09",
"Sender":"0x87e369172af1e817ebd8d63bcd9f685a513a6736", "Nonce":9
}
}
注意:如果这是个合约部署的交易,则在contractAddress将会显示合约地址;如果是一个有返回值的方法调用,则在result中显示调用结果
GetReceiptByHash: 通过交易hash获取子链的tx执行结果
SubChainAddr: 子链合约地址
Sender:查询账号
Body: {"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.GetReceiptByHash",
"params":{"SubChainAddr":"0x1195cd9769692a69220312e95192e0dcb6a4ec09",
"Hash":"0x87e369172af1e817ebd8d63bcd9f685a513a6736fsne3lkgkvu65kkwlcd"
}
}
注意:如果这是个合约部署的交易,则在contractAddress将会显示合约地址;如果是一个有返回值的方法调用,则在result中显示调用结果
*业务类*
此部分合约需要指明是哪个业务逻辑合约
AnyCall: 获取dapp合约函数的返回值,调用此接口前必须将dapp注册入dappbase
Params: 第一个参数是调用的方法,之后是方法传入参数
SubChainAddr: 子链合约地址
Sender:查询账号
DappAddr:子链业务逻辑地址
Body: {"jsonrpc":"2.0","id":0,"method":"ScsRPCMethod.AnyCall",
"params":{"SubChainAddr":"0x1195cd9769692a69220312e95192e0dcb6a4ec09",
"DappAddr":"0xcc0D18E77748AeBe3cC6462be0EF724e391a4aD9",
"Sender":"0x87e369172af1e817ebd8d63bcd9f685a513a6736", "Params" :["funcA", "param1", param2]
}
}
子链节点的更替¶
子链节点添加¶
子链合约提供了registerAdd方法来支持子链添加,必须由子链部署账号来发送交易请求。
需要对应SubChainProtocolBase矿池合约有等待加入的scs节点。
子链收到请求后,在矿池合约选取scs,开始同步子链区块,等一轮flush后生效,正式加入子链。
registerAdd参数:
nodeToAdd: 当前scs数+需要加入scs数
调用示例:
> data = subchainbase.registerAdd.getData(20)
> subchainaddr = '0x1195cd9769692a69220312e95192e0dcb6a4ec09';
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> chain3.mc.sendTransaction( { from: chain3.mc.accounts[0], value:0, to: subchainaddr, gas: "2000000", gasPrice: chain3.mc.gasPrice, data: data});
验证:scs对应日志开始同步区块,合约公共变量codeCount更新为scs最新数量
> SubChainBase.nodeCount()
子链节点退出¶
子链节点退出有两种方式:
- 当子链工作正常时,调用子类合约requestRelease方法请求退出子链,等待一轮flush后生效。
requestRelease参数:
senderType: 1:scs发起请求 2:收益账号发出请求
index: scs序号(参考ScsRPCMethod.GetSubChainInfo中scs的列表)
调用示例:
> data = subchainbase.requestRelease.getData(senderType, index)
> subchainaddr = '0x1195cd9769692a69220312e95192e0dcb6a4ec09';
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> chain3.mc.sendTransaction( { from: chain3.mc.accounts[0], value:0, to: subchainaddr, gas: "2000000", gasPrice: chain3.mc.gasPrice, data: data});
验证:等待一轮flush后,关注合约公共变量codeCount是否变化
> SubChainBase.nodeCount()
- 当子链工作不正常时,可以调用子类合约requestReleaseImmediate方法请求立即退出子链。
requestReleaseImmediate参数:
senderType: 1:scs发起请求 2:收益账号发出请求
index: scs序号(参考ScsRPCMethod.GetSubChainInfo中scs的列表)
调用示例:
> data = subchainbase.requestReleaseImmediate.getData(senderType, index)
> subchainaddr = '0x1195cd9769692a69220312e95192e0dcb6a4ec09';
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> chain3.mc.sendTransaction( { from: chain3.mc.accounts[0], value:0, to: subchainaddr, gas: "2000000", gasPrice: chain3.mc.gasPrice, data: data});
验证:合约公共变量codeCount是否变化
> SubChainBase.nodeCount()
关闭子链¶
子链关闭请求¶
子链合约提供了close的方法来支持关闭子链,必须由子链部署账号来发送交易请求。
调用示例:
根据ABI chain3.sha3("close()") = 0x43d726d69bfad97630bc12e80b1a43c44fecfddf089a314709482b2b0132f662
取前4个字节 0x43d726d6
> subchainaddr = '0x1195cd9769692a69220312e95192e0dcb6a4ec09';
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> chain3.mc.sendTransaction( { from: chain3.mc.accounts[0], value:0, to: subchainaddr, gas: "2000000", gasPrice: chain3.mc.gasPrice, data: '0x43d726d6'});
关闭请求发送后,需等待一轮flush后生效,相关子链维护费用也将退回到子链部署账号中。 可以通过查询余额进行验证
> chain3.mc.getBalance('0x1195cd9769692a69220312e95192e0dcb6a4ec09')
母子链货币交互简介¶
墨客支持有币子链,并且提供母链货币和子链原生币之间的兑换。
当前,墨客提供三种类型的母子链货币交互,以下一一介绍
母链MOAC和子链原生币交互¶
这个是最基础的一种货币兑换。使用者可以在主链上充值MOAC,然后最早在下一个flush周期在子链上获取子链原生币。同理,使用者可以提出子链原生币,并最早在下一个flush周期获得主链MOAC。
对应release中的ASM版本包
子链部署准备¶
参考子链部署章节,完成部署子链的准备工作。
子链操作账号: 0x87e369172af1e817ebd8d63bcd9f685a513a6736
vnode矿池合约地址: 0x22f141dcc59850707708bc90e256318a5fe0b928
vnode代理地址: 0xf103bc1c054babcecd13e7ac1cf34f029647b08c 192.168.10.209:50062
子链矿池合约地址: 0xe42f4f566aedc3b6dd61ea4f70cc78d396130fac
scs0: 0x075447a6df1fde4f39243bc67a945312ff36c193 确保启动并加入子链矿池
scs1: 0x7932f827c90c5f06c0177f642a07edfa73ee3044 确保启动并加入子链矿池
scs2 兼 monitor: 0xa5966600efb221097ce6a8ba1dc6eb1d5b43ef83 确保启动并加入子链矿池
subchainbase 部署¶
注意这个子链合约在官方基础上进行了修改,对应v1目录下的SubChainBase.sol(带tokensupply和exchangerate参数)。 部署SubChainBase.sol示例:
> chain3 = require('chain3')
> solc = require('solc')
> chain3 = new chain3();
> chain3.setProvider(new chain3.providers.HttpProvider('http://localhost:8545'));
> input = {'': fs.readFileSync('SubChainBase.sol', 'utf8'), 'SubChainProtocolBase.sol': fs.readFileSync('SubChainProtocolBase.sol', 'utf8')};
> output = solc.compile({sources: input}, 1);
> abi = output.contracts[':SubChainBase'].interface;
> bin = output.contracts[':SubChainBase'].bytecode;
> proto = '0xe42f4f566aedc3b6dd61ea4f70cc78d396130fac' ; // 子链矿池合约
> vnodeProtocolBaseAddr = '0x22f141dcc59850707708bc90e256318a5fe0b928' ; // Vnode矿池合约
> min = 1 ; // 子链需要SCS的最小数量,当前需要从如下值中选择:1,3,5,7
> max = 11 ; // 子链需要SCS的最大数量,当前需要从如下值中选择:11,21,31,51,99
> thousandth = 1 ; // 千分之几
> flushRound = 40 ; // 子链刷新周期 单位是主链block生成对应数量的时间(10秒一个block)
> tokensupply = 1000; // 子链原生币总额
> exchangerate = 100; // 与moac兑换比例
> SubChainBaseContract = chain3.mc.contract(JSON.parse(abi));
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> SubChainBase = SubChainBaseContract.new( proto, vnodeProtocolBaseAddr, min, max, thousandth, flushRound, tokensupply, exchangerate { from: chain3.mc.accounts[0], data: '0x' + bin, gas:'9000000'} , function (e, contract){console.log('Contract address: ' + contract.address + ' transactionHash: ' + contract.transactionHash); });
部署完毕后, 获得子链合约地址 0xe9463e215315d6f1e5387a161868d7d0a4db89e8
- 验证:
- 访问子链合约的 BALANCE 与 tokensupply 对应应该是10的21次方 : 即 tokensupply * 10的18次方(子链原生币decimals)
调用示例:
> subchainaddr = '0xe9463e215315d6f1e5387a161868d7d0a4db89e8';
> SubChainBase = SubChainBaseContract.at(subchainaddr);
> SubChainBase.BALANCE()
调用monitor的方法 ScsRPCMethod.GetBalance 查询对应部署账号地址的余额,应该也等于10的21次方
dappbase合约部署¶
子链开放注册后,待scs开始出块即成功完成部署子链,方法请参见”子链的部署方法”。 按照多合约部署步骤,需要首先部署dappbase合约,方法请参见”子链业务逻辑的部署”。
# 注意部署dappbase合约的value为 1000(tokensupply) * 10的18次方(子链原生币decimals)
部署示例:
> chain3 = require('chain3')
> solc = require('solc')
> chain3 = new chain3();
> chain3.setProvider(new chain3.providers.HttpProvider('http://localhost:8545'));
> solfile = 'DappBase.sol';
> contract = fs.readFileSync(solfile, 'utf8');
> output = solc.compile(contract, 1);
> abi = output.contracts[':DappBase'].interface;
> bin = output.contracts[':DappBase'].bytecode;
> amount = chain3.toSha(1000,'mc')
> subchainaddr = '0xb877bf4e4cc94fd9168313e00047b77217760930';
> via = '0xf103bc1c054babcecd13e7ac1cf34f029647b08c';
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> chain3.mc.sendTransaction({from: chain3.mc.accounts[0], value:chain3.toSha(amount,'mc'), to: subchainaddr, gas:0, gasPrice: 0, shardingFlag: "0x3", data: '0x' + bin, nonce:0, via: via });
- 验证:
- 调用monitor的方法 ScsRPCMethod.GetNonce Nonce值应该是1调用monitor的方法 ScsRPCMethod.GetBalance 查询对应dappbase合约地址的余额,应该等于10的21次方调用monitor的方法 ScsRPCMethod.GetBalance 查询对应部署账号地址的余额,应该等于0调用monitor的方法 ScsRPCMethod.GetReceipt 传入对应Nonce,从contractAddress字段内容获得合约地址
dapp 充值¶
调用 subchainbase 的 buyMintToken方法充值, 用户账号为发出sendTransaction的账号 数量为sendTransaction的amount参数
调用示例:
根据ABI chain3.sha3("buyMintToken()") = 0x6bbded701cd78dee9626653dc2b2e76d3163cc5a6f81ac3b8e69da6a057824cb
取前4个字节 0x6bbded70
> amount = 1;
> subchainaddr = '0xe9463e215315d6f1e5387a161868d7d0a4db89e8';
> chain3.personal.unlockAccount(chain3.mc.accounts[1], '123456');
> chain3.mc.sendTransaction( { from: chain3.mc.accounts[1], value: chain3.toSha(amount,'mc'), to: subchainaddr, gas:"2000000", gasPrice: chain3.mc.gasPrice, data: '0x6bbded70'});
- 验证:
- 检查账号的moac是否减少: > chain3.mc.getBalance(chain3.mc.accounts[1])检查子链的token是否增加: 调用monitor的方法 ScsRPCMethod.GetBalance 获得子链chain3.mc.accounts[1]地址对应token检查子链dappbase合约地址的原生币是否减少: 调用monitor的方法 ScsRPCMethod.GetBalance
dapp 提币¶
请注意data前需要加上dappbase合约地址
- 调用 dappbase合约 的 redeemFromMicroChain方法,用户账号为发出sendTransaction的账号 数量为sendTransaction的amount参数
- redeemFromMicroChain方法将用户账号和对应token数量加入推送结构体redeem,等待一轮flush后生效
调用示例:
根据ABI chain3.sha3("redeemFromMicroChain()") = 0x89739c5bf1ef36273bf0e7aeb59ffe71213a58e1f01965e75662cb21b03abb13
取前4个字节 0x89739c5b
调用dapp合约方法,需要再data前加入dappaddr
> nonce = 1 // 调用ScsRPCMethod.GetNonce获得
> subchainaddr = '0x1195cd9769692a69220312e95192e0dcb6a4ec09';
> dappbassaddr = dappbase合约地址
> via = '0xf103bc1c054babcecd13e7ac1cf34f029647b08c';
> amount = 10 // 对应子链原生币 10 * 18次方 即0.1 moac
> chain3.personal.unlockAccount(chain3.mc.accounts[1], '123456');
> chain3.mc.sendTransaction( { nonce: nonce, from: chain3.mc.accounts[1], value:chain3.toSha(amount,'mc'), to: subchainaddr, gas:0, shardingFlag:'0x1', data: dappbassaddr + '89739c5b', via: via,});
- 验证:
- 检查账号的moac是否增加: > chain3.mc.getBalance(chain3.mc.accounts[1])检查子链的token是否减少: 调用monitor的方法 ScsRPCMethod.GetBalance 获得子链token检查子链dappbase合约地址的原生币是否增加: 调用monitor的方法 ScsRPCMethod.GetBalance
母链ERC20和子链原生币交互¶
这是非常通用的一种货币兑换。使用者可以使用预先已经部署好的ERC20,或者当场部署一个主链ERC20,和子链的原生币进行兑换。
对应release中的AST版本包
子链部署准备¶
参考子链部署章节,完成部署子链的准备工作。
子链操作账号: 0x87e369172af1e817ebd8d63bcd9f685a513a6736
vnode矿池合约地址: 0x22f141dcc59850707708bc90e256318a5fe0b928
vnode代理地址: 0xf103bc1c054babcecd13e7ac1cf34f029647b08c 192.168.10.209:50062
子链矿池合约地址: 0xe42f4f566aedc3b6dd61ea4f70cc78d396130fac
scs0: 0xd81043d85c9c959d2925958c54c1a49c7bfd1fc8 确保启动并加入子链矿池
scs1: 0xe767059d768fcef12e527fab63fda68cc13e24b3 确保启动并加入子链矿池
scs2 兼 monitor: 0x0964e5d73d6a40f2fc707aa3e1361028a34923f0 确保启动并加入子链矿池
erc20 部署¶
默认一个标准的erc20合约,通过allowance,transferFrom,balanceOf,transfer等标准的方法支持货币的转移。
参考官方示例的erc20合约erc20.sol,默认decimals为2,totalSupply为10000乘以10的2次方。 调用示例:
> chain3 = require('chain3')
> solc = require('solc')
> chain3 = new chain3();
> chain3.setProvider(new chain3.providers.HttpProvider('http://localhost:8545'));
> solfile = 'erc20.sol';
> contract = fs.readFileSync(solfile, 'utf8');
> output = solc.compile(contract, 1);
> abi = output.contracts[':TestCoin'].interface;
> bin = output.contracts[':TestCoin'].bytecode;
> erc20Contract = chain3.mc.contract(JSON.parse(abi));
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> dtoken = erc20Contract.new( { from: chain3.mc.accounts[0], data: '0x' + bin, gas:'9000000'} , function (e, contract){console.log('Contract address: ' + contract.address + ' transactionHash: ' + contract.transactionHash); });
部署完毕后, 获得erc20合约地址 0x5042086887a86151945d2c2bb60628addf49d48c
验证: 调用合约balanceOf方法查询部署者的余额,应该是1000000
> contractInstance = erc20Contract.at('0x5042086887a86151945d2c2bb60628addf49d48c')
> contractInstance.balanceOf.call('0x87e369172af1e817ebd8d63bcd9f685a513a6736')
subchainbase 部署¶
注意这个子链合约在官方基础上进行了修改,增加了erc20合约地址和兑换比例的参数 部署SubChainBase.sol示例:
> chain3 = require('chain3')
> solc = require('solc')
> chain3 = new chain3();
> chain3.setProvider(new chain3.providers.HttpProvider('http://localhost:8545'));
> input = {'': fs.readFileSync('SubChainBase.sol', 'utf8'), 'SubChainProtocolBase.sol':fs.readFileSync('SubChainProtocolBase.sol', 'utf8')};
> output = solc.compile({sources: input}, 1);
> abi = output.contracts[':SubChainBase'].interface;
> bin = output.contracts[':SubChainBase'].bytecode;
> proto = '0xe42f4f566aedc3b6dd61ea4f70cc78d396130fac' ; // 子链矿池合约
> vnodeProtocolBaseAddr = '0x22f141dcc59850707708bc90e256318a5fe0b928' ; // Vnode矿池合约
> ercAddr = '0x5042086887a86151945d2c2bb60628addf49d48c'; // erc20合约地址
> ercRate = 10; // 兑换比率
> min = 1 ; // 子链需要SCS的最小数量,当前需要从如下值中选择:1,3,5,7
> max = 11 ; // 子链需要SCS的最大数量,当前需要从如下值中选择:11,21,31,51,99
> thousandth = 1 ; // 千分之几
> flushRound = 40 ; // 子链刷新周期 单位是主链block生成对应数量的时间(10秒一个block)
> SubChainBaseContract = chain3.mc.contract(JSON.parse(abi));
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> SubChainBase = SubChainBaseContract.new( proto, vnodeProtocolBaseAddr, ercAddr, ercRate, min, max, thousandth, flushRound,{ from: chain3.mc.accounts[0], data: '0x' + bin, gas:'9000000'} , function (e, contract){console.log('Contract address: ' + contract.address + ' transactionHash: ' + contract.transactionHash); });
部署完毕后, 获得子链合约地址 0xb877bf4e4cc94fd9168313e00047b77217760930
- 验证:
- 访问子链合约的 BALANCE 与 ERC20的 totalsupply 对应应该是10的23次方 : 即 1000000(ERC20的totalsupply) * 10(兑换比率) * 10的18次方(子链原生币decimals) / 10的2次方(ERC20的decimals)
调用示例:
> subchainaddr = '0xb877bf4e4cc94fd9168313e00047b77217760930';
> SubChainBase = SubChainBaseContract.at(subchainaddr);
> SubChainBase.BALANCE()
调用monitor的方法 ScsRPCMethod.GetBalance 查询对应部署账号地址的余额,应该等于10的23次方
dappbase合约部署¶
子链开放注册后,待scs开始出块即成功完成部署子链,方法请参见”子链的部署方法”。 按照多合约部署步骤,需要首先部署dappbase合约,方法请参见”子链业务逻辑的部署”。
注意部署dappbase合约的value为 ERC20的totalsupply * 10(兑换比率) * 10的18次方(子链原生币decimals) / 10的2次方(ERC20的decimals)
部署示例:
> chain3 = require('chain3')
> solc = require('solc')
> chain3 = new chain3();
> chain3.setProvider(new chain3.providers.HttpProvider('http://localhost:8545'));
> solfile = 'DappBase.sol';
> contract = fs.readFileSync(solfile, 'utf8');
> output = solc.compile(contract, 1);
> abi = output.contracts[':DappBase'].interface;
> bin = output.contracts[':DappBase'].bytecode;
> amount = chain3.toSha(100000,'mc')
> subchainaddr = '0xb877bf4e4cc94fd9168313e00047b77217760930';
> via = '0xf103bc1c054babcecd13e7ac1cf34f029647b08c';
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> chain3.mc.sendTransaction({from: chain3.mc.accounts[0], value:chain3.toSha(amount,'mc'), to: subchainaddr, gas:0, gasPrice: 0, shardingFlag: "0x3", data: '0x' + bin, nonce:0, via: via });
- 验证:
- 调用monitor的方法 ScsRPCMethod.GetBalance 查询对应dappbase合约地址的余额,应该等于10的23次方调用monitor的方法 ScsRPCMethod.GetBalance 查询对应部署账号地址的余额,应该等于0调用monitor的方法 ScsRPCMethod.GetReceipt 传入对应Nonce,从contractAddress字段内容获得合约地址
dapp 充值¶
调用 subchainbase 的 buyMintToken方法充值, 用户账号为发出sendTransaction的账号 ,参数分别为子链合约地址和erc20的数量。 注意:buyMintToken方法首先调用erc20合约的allowance检查授权,再调用transferFrom方法将token从用户账号地址转到合约地址 所以要先调用erc20的approve方法授权对应的erc20给subchainbase合约地址。
调用示例:
> amount = 200
> data = erc20.approve.getData(subchainaddr, amount);
> chain3.mc.sendTransaction( { from: chain3.mc.accounts[0], value: 0, to: erc20.address, gas: "2000000", gasPrice: chain3.mc.gasPrice, data: data});
> subchainaddr = '0xb877bf4e4cc94fd9168313e00047b77217760930';
> SubChainBase = SubChainBaseContract.at(subchainaddr);
> data = SubChainBase.buyMintToken.getData(amount)
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> chain3.mc.sendTransaction( { from: chain3.mc.accounts[0], value: 0, to: subchainaddr, gas: "2000000", gasPrice: chain3.mc.gasPrice, data: data});
- 验证:
- 检查账号的erc20 token是否减少200: 调用erc20合约的balanceOf方法检查子链对应账号的原生币是否增加20000000000000000000: 调用monitor的方法 ScsRPCMethod.GetBalance检查子链dappbase合约地址的原生币是否减少20000000000000000000: 调用monitor的方法 ScsRPCMethod.GetBalance
dapp 提币¶
请注意data前需要加上dappbase合约地址
- 调用 dappbase合约 的 redeemFromMicroChain方法,用户账号为发出sendTransaction的账号 数量为sendTransaction的amount参数
- redeemFromMicroChain方法将用户账号和对应token数量加入推送结构体redeem,等待一轮flush后,自动会调用子链合约的redeemFromMicroChain方法调用erc20合约的transfer给用户账号转对应的token数量
调用示例:
根据ABI chain3.sha3("redeemFromMicroChain()") = 0x89739c5bf1ef36273bf0e7aeb59ffe71213a58e1f01965e75662cb21b03abb13
取前4个字节 89739c5b
调用dapp方法,需要再data前加入dappaddr
> nonce = 5 // 调用ScsRPCMethod.GetNonce获得
> subchainaddr = '0xb877bf4e4cc94fd9168313e00047b77217760930';
> dappbassaddr = dappbase合约地址
> via = '0xf103bc1c054babcecd13e7ac1cf34f029647b08c';
> amount = chain3.toSha(10,'mc') // * 10的2次方(ERC20的decimals) / 10(兑换比率) 100 即为对应erc20数量
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> chain3.mc.sendTransaction( { nonce: nonce, from: chain3.mc.accounts[0], value:amount, to: subchainaddr, gas:0, shardingFlag:'0x1', data: dappbassaddr + '89739c5b', via: via,});
- 验证:
- 检查账号的erc20 token是否增加100: 调用erc20合约的balanceOf方法等待一轮flush后,检查子链对应账号的原生币是否减少10000000000000000000: 调用monitor的方法 ScsRPCMethod.GetBalance
ATO方式¶
TODO
多合约的进阶操作¶
1.0.8以后,子链引入了多合约的概念。子链多合约指的是在一条子链中部署多个智能合约,多合约可以将业务逻辑进行拆分,相互调用,合约之间也可以进行升级。
子链业务逻辑合约间的调用¶
本实例完成一个合约调用另外一个合约中的方法。
STEP0:部署dappbase.sol
STEP1:部署合约dapp1.sol,并注册到dappbase中去
contract Dapp1 {
struct tup {
uint amount;
string desc;
}
tup[] public tups;
function addTup(uint amount, string desc) public {
tups.push(tup(desc));
}
function getString() public view returns (string) {
return tups[0].desc;
}
function getTup(address addr) public view returns (tup) {
for (uint i=0; i<tups.length; i++) {
if (tups[i].owner == addr) {
return tups[i];
}
}
}
STEP2:部署合约dapp2.sol,要求可以调用dapp1的getString方法
contract Dapp1 {
struct tup {
uint amount;
string desc;
}
function getUint() public view returns (uint);
function getString() public view returns (string);
function getTup(address addr) public view returns (tup);
}
contract Dapp2 {
struct tup {
uint amount;
string desc;
}
function Dapp2(address dapp1addr) public {
Dapp1 dp1 = Dapp1(addr1);
}
function getString(address addr1) public view returns (string) {
return dp1.getString();
}
}
调用示例:
> nonce = 1 // 调用ScsRPCMethod.GetNonce获得
> subchainaddr = '0xb877bf4e4cc94fd9168313e00047b77217760930';
> dappaddr = '0xcc0D18E77748AeBe3cC6462be0EF724e391a4aD9';
> via = '0xf103bc1c054babcecd13e7ac1cf34f029647b08c';
> data = dappaddr + '89ea642f';
> chain3.personal.unlockAccount(chain3.mc.accounts[0], '123456');
> chain3.mc.sendTransaction( { nonce: nonce, from: chain3.mc.accounts[0], value:0, to: subchainaddr, gas:0, shardingFlag:'0x1', data: data, via: via,});
子链合约的升级(版本迭代)¶
本实例完成一个合约获取另外一个合约中的数据,进而替代另外一个合约中的功能。
STEP0:部署dappbase.sol
STEP1:部署合约dapp1.sol,并注册到dappbase中去
contract Dapp1 {
struct tup {
uint amount;
address addr;
}
tup[] public tups;
tup[] private mytups;
function addTup(uint amount, address addr) public {
tups.push(tup(amount, addr));
}
function getAmountByAddr(address myaddr) public view returns (tup[]) {
for (uint i=0;i<tups.length;i++){
if (tups[i].addr == myaddr){
mytups.push(tups[i]);
}
}
return mytups;
}
}
STEP2:部署合约dapp3.sol,要求可以访问dapp1中的数据
contract Dapp1 {
struct tup {
uint amount;
address addr;
}
function getAmountByAddr(address) public view returns (tup[]);
}
contract Dapp3 {
struct tup {
uint amount;
address addr;
}
Dapp1 public dp1;
tup[] public tups;
tup[] private mytups;
function Dapp3(address dapp1addr) public{
dp1 = Dapp1(dapp1addr);
}
function addTup(uint amount, address addr) public {
tups.push(tup(amount, addr));
}
function getAmountByAddr(address addr) public view returns (tup[]) {
Dapp1.tup[] memory oldtups = new Dapp1.tup[](10);
oldtups = dp1.getAmountByAddr(addr);
for (uint i=0;i<oldtups.length;i++){
if (oldtups[i].addr == addr){
mytups.push(tup(oldtups[i].amount, oldtups[i].addr));
}
}
for (i=0;i<tups.length;i++){
if (tups[i].addr == addr){
mytups.push(tups[i]);
}
}
return mytups;
}
}
说明:getAmountByAddr方法将dapp1中的老数据放入dapp3中的mytups。
STEP3:部署合约dapp4.sol,要求可以访问dapp3中的数据
contract Dapp3 {
struct tup {
uint amount;
address addr;
}
function getUint() public view returns (uint);
function getString() public view returns (string);
function getAmountByAddr(address) public view returns (tup[]);
}
contract Dapp4 {
struct tup {
uint amount;
address addr;
}
tup[] public tups;
Dapp3 dp3;
tup[] private mytups;
function Dapp4(address dapp3addr) public {
dp3 = Dapp3(dapp3addr);
}
function addTup(uint amount, address addr) public {
tups.push(tup(amount, addr));
}
function getAmountByAddr(address addr) public view returns (tup[]) {
//get dapp3 data
Dapp3.tup[] memory oldtups = new Dapp3.tup[](10);
oldtups = dp3.getAmountByAddr(addr);
for (uint i=0;i<oldtups.length;i++){
if (oldtups[i].addr == addr){
mytups.push(tup(oldtups[i].amount, oldtups[i].addr));
}
}
//new data
for (i=0;i<tups.length;i++){
if (tups[i].addr == addr){
mytups.push(tups[i]);
}
}
return mytups;
}
}
说明:getAmountByAddr方法将dapp3中的老数据放入dapp3中的mytups,因为dapp3的方法中包含dapp1的数据,所以这个方法最终返回dapp1,dapp3,dapp4中所有符合addr的数据。
Restful API¶
Restful API 简介¶
MOAC以Restful API提供给用户的一种接入方式。包括了对钱包,主链,子链,各交易查询的一系列封装。
DAPP用户当调用客户端SDK有困难时,可以通过服务端调用的方式实现对MOAC的接入。
URL设计¶
使用http作为API的通信协议,目前采用较多的POST方法。
url格式: http(s)://server.com/api/{module}/{version}/{method}
关于version,各模块支持多版本,默认version为v1.0
POST提交格式采用form表单参数 Content-Type: application/x-www-form-urlencoded (a=name&b=666)
结构返回¶
返回体格式采用json格式
{
"success": true,
"message": "",
"data": "*********"
}
success: true - 成功 false - 失败
message: 失败时的错误信息
data: 接口返回数据
相关状态码 200 OK 403 token权限受限
接口访问控制¶
API访问控制,需先请求访问的用户名和密码,先调用auth接口请求访问token。
各api接口需要token参数调用,不然会返回403错误。
token有过期机制,目前是2小时有效。
私钥安全¶
对于账号私钥的安全提供了两种方案。
- dapp注册账户后,收到返回的私钥(privatekey),后续发送交易直接传递私钥
- dapp注册账户后,也会返回一个加密串(encode),后续发送交易传递加密串和账户密码,系统会解码获得私钥进行签名。
节点控制¶
测试环境地址:http://139.198.126.104:8080
测试环境获取access token,可使用测试账号:test 密码:123456
正式环境地址:https://api.moac.io:8080
正式环境获取access token,请联系开发团队:moacapi@mossglobal.net。
目前设计需要vnode节点的相关API,可通过参数传入地址和端口的方式指定连接的节点。 参数传入为空的情况下,会使用平台默认的节点信息(测试环境对应testnet的默认节点,正式环境默认主网节点)。
Restful API 接口¶
管理模块¶
API认证¶
请求访问token,提供权限调用API的其他接口
方法:auth
参数:
account: 授权账号
pwd: 授权账号密码
调用示例:
POST: http://139.198.126.104:8080/auth
BODY:account=******&pwd=******
返回数据示例
{
"success": true,
"message": "",
"data": "token内容"
}
账户模块¶
账户注册¶
方法:register
参数:
pwd: 账户密码
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/account/v1.0/register
BODY:pwd=********&token=********************************
返回数据示例
{
"success": true,
"message": "",
"address": 账户地址,
"encode": 账户加密串,
"keystore": 账户keystore信息,
"privateKey": 账户私钥
}
账户登录¶
方法:login
参数:
address: 账户地址
pwd: 账户密码
encode: 账户加密串
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/account/v1.0/login
BODY:address=0x********&pwd=*****&encode=*******&token=************
返回数据示例
{
"success": true,
"message": "",
"data": 账户地址
}
账户导入¶
方法:import 将账户通过keystore导入系统
参数:
address: 账户地址
pwd: 账户密码
keystore: 账户keystore
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/account/v1.0/import
BODY:address=0x********&pwd=*****&keystore={*******}&token=************
返回数据示例
{
"success": true,
"message": "",
"address": 账户地址,
"encode": 账户加密串,
"privateKey": 账户私钥
}
主网模块¶
账户余额¶
方法:getBalance
参数:
vnodeip: vnode节点地址
vnodeport: vnode节点端口
address: 账号地址
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/vnode/v1.0/getBalance
BODY:vnodeip=127.0.0.1&vnodeport=8545&address=0x******&token=*****************
返回数据示例
{
"success": true,
"message": "",
"data": 账户余额 (单位 moac)
}
区块高度¶
方法:getBlockNumber
参数:
vnodeip: vnode节点地址
vnodeport: vnode节点端口
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/vnode/v1.0/getBlockNumber
BODY:vnodeip=127.0.0.1&vnodeport=8545&token=***************
返回数据示例
{
"success": true,
"message": "",
"data": 区块高度
}
区块信息¶
方法:getBlockInfo
参数:
vnodeip: vnode节点地址
vnodeport: vnode节点端口
block: 区块号或者区块hash
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/vnode/v1.0/getBlockInfo
BODY:vnodeip=127.0.0.1&vnodeport=8545&block=2002326&token=******************
返回数据示例
{
"success": true,
"message": "",
"data": 区块信息
}
交易明细¶
方法:getTransactionByHash
参数:
vnodeip: vnode节点地址
vnodeport: vnode节点端口
hash: 交易hash
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/vnode/v1.0/getTransactionByHash
BODY:vnodeip=127.0.0.1&vnodeport=8545&hash=0x**&token=******************
返回数据示例
{
"success": true,
"message": "",
"data": 交易明细
}
交易详情¶
方法:getTransactionReceiptByHash
参数:
vnodeip: vnode节点地址
vnodeport: vnode节点端口
hash: 交易hash
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/vnode/v1.0/getTransactionReceiptByHash
BODY:vnodeip=127.0.0.1&vnodeport=8545&hash=0x**&token=******************
返回数据示例
{
"success": true,
"message": "",
"data": 交易详情
}
转账¶
方法:sendRawTransaction
参数:
vnodeip: vnode节点地址
vnodeport: vnode节点端口
from: 源账号地址
to: 目标账号地址
amount: 数量(单位 moac)
method: dapp合约方法 比如:buyMintToken(uint256)
paramtypes: dapp合约方法对应的参数类型 比如:["uint256"]
paramvalues: dapp合约方法对应的参数值 比如:[100000000]
privatekey: 源账号私钥 (传privatekey,可忽略参数pwd和encode,不传privatekey,则必须传pwd和encode认证)
pwd: 账户密码
encode:账户加密串
gasprice: 可选参数,默认gasprice为chain3的gasPrice,当交易堵塞时,需要传原交易的110%进行覆盖。
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/vnode/v1.0/sendRawTransaction
BODY:vnodeip=127.0.0.1&vnodeport=8545&from=0x**&to=0x***&amount=10&method=buyMintToken(uint256)¶mtypes=["uint256"]¶mvalues=[100000000]&privatekey=0x**&token=*******
返回数据示例
{
"success": true,
"message": "",
"data": 交易hash
}
调用智能合约¶
方法:callContract
参数:
vnodeip: vnode节点地址
vnodeport: vnode节点端口
contractaddress: 合约地址
method: dapp合约方法 比如:buyMintToken(uint256)
paramtypes: dapp合约方法对应的参数类型 比如:["uint256"]
paramvalues: dapp合约方法对应的参数值 比如:[100000000]
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/vnode/v1.0/callContract
BODY:vnodeip=127.0.0.1&vnodeport=8545&contractaddress=0x*****&method=buyMintToken(uint256)¶mtypes=["uint256"]¶mvalues=[100000000]0x****&token=***************
返回数据示例
{
"success": true,
"message": "",
"data": 调用合约返回结果
}
erc20转账¶
方法:transferErc
参数:
vnodeip: vnode节点地址
vnodeport: vnode节点端口
from: 源账号地址
to: 目标账号地址
contractaddress: erc20合约地址
amount: erc20代币数量
privatekey: 源账号私钥(传privatekey,可忽略参数pwd和encode,不传privatekey,则必须传pwd和encode认证)
pwd: 账户密码
encode:账户加密串
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/vnode/v1.0/transferErc
BODY:vnodeip=&vnodeport=&from=0x**&to=0x**&contractaddress=0x**&amount=10&privatekey=0x**&token=*******
返回数据示例
{
"success": true,
"message": "",
"data": 交易hash
}
erc20余额¶
方法:getErcBalance
参数:
vnodeip: vnode节点地址
vnodeport: vnode节点端口
address: 账户地址
contractaddress: erc20合约地址
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/vnode/v1.0/getErcBalance
BODY:vnodeip=127.0.0.1&vnodeport=8545&address=0x*****&contractaddress=0x**&token=*********
返回数据示例
{
"success": true,
"message": "",
"data": 余额(最小精度,10进制)
}
erc20授权给子链¶
方法:ercApprove
参数:
vnodeip: vnode节点地址
vnodeport: vnode节点端口
address: 账户地址
amount: 授权erc20数量
privatekey: 账号私钥(传privatekey,可忽略参数pwd和encode,不传privatekey,则必须传pwd和encode认证)
pwd: 账户密码
encode:账户加密串
microchainaddress 子链地址
contractaddress: erc20合约地址
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/vnode/v1.0/ercApprove
BODY:vnodeip=127.0.0.1&vnodeport=8545&address=0x*****&amount=***&privatekey=0x***µchainaddress=0x***&contractaddress=0x**&token=*********
返回数据示例
{
"success": true,
"message": "",
"data": 交易hash
}
充值子链 erc20兑换子链原生币¶
方法:buyErcMintToken 注:前提是erc20对应数量已经授权给子链
参数:
vnodeip: vnode节点地址
vnodeport: vnode节点端口
address: 账户地址
privatekey: 源账号私钥(传privatekey,可忽略参数pwd和encode,不传privatekey,则必须传pwd和encode认证)
pwd: 账户密码
encode:账户加密串
microchainaddress: 子链地址
method: dapp合约方法 默认为:buyMintToken(uint256)
paramtypes: dapp合约方法对应的参数类型 默认为:["uint256"]
paramvalues: dapp合约方法对应的参数值 比如:[100000000]
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/vnode/v1.0/buyErcMintToken
BODY:vnodeip=&vnodeport=&address=0x**&privatekey=0x**µchainaddress=0x**&method=buyMintToken(uint256)¶mtypes=["uint256"]¶mvalues=[100000000]&token=****
返回数据示例
{
"success": true,
"message": "",
"data": 交易hash
}
充值子链 moac兑换子链原生币¶
方法:buyMoacMintToken
参数:
vnodeip: vnode节点地址
vnodeport: vnode节点端口
address: 账户地址
privatekey: 源账号私钥
pwd: 账户密码
encode:账户加密串
microChainaddress: 子链地址
method: dapp合约方法 默认为:buyMintToken(uint256)
paramtypes: dapp合约方法对应的参数类型 默认为:["uint256"]
paramvalues: dapp合约方法对应的参数值 比如:[100000000]
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/vnode/v1.0/buyMoacMintToken
BODY:vnodeip=&vnodeport=&address=0x**&privatekey=0x**µChainaddress=0x**&method=buyMintToken(uint256)¶mtypes=["uint256"]¶mvalues=[100000000]&token=****
返回数据示例
{
"success": true,
"message": "",
"data": 交易hash
}
子链模块¶
获得子链区块高度¶
方法:getBlockNumber
参数:
microip: monitor节点地址
microport: monitor节点端口
microchainaddress: 子链SubChain地址
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/micro/v1.0/getBlockNumber
BODY:microip=127.0.0.1µport=8546µchainaddress=0x***&token=***********
返回数据示例
{
"success": true,
"message": "",
"data": 子链区块高度
}
获得子链dapp地址列表¶
方法:getDappAddrList
参数:
microip: monitor节点地址
microport: monitor节点端口
microchainaddress: 子链SubChain地址
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/micro/v1.0/getDappAddrList
BODY:microip=127.0.0.1µport=8546µchainaddress=0x***&token=***********
返回数据示例
{
"success": true,
"message": "",
"data": 子链dapp地址列表(按合约注册次序)
}
获取子链区块信息¶
方法:getBlock
参数:
microip: monitor节点地址
microport: monitor节点端口
microchainaddress: 子链SubChain地址
blocknum: 块号
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/micro/v1.0/getBlock
BODY:microip=127.0.0.1µport=8546µchainaddress=0x***&blocknum=*****&token=***********
返回数据示例
{
"success": true,
"message": "",
"data": 子链区块信息
}
获得子链对应Hash的交易信息¶
方法:getTransactionByHash
参数:
microip: monitor节点地址
microport: monitor节点端口
microchainaddress: 子链SubChain地址
hash: 交易hash
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/micro/v1.0/getTransactionByHash
BODY:microip=127.0.0.1µport=8546µchainaddress=0x***&hash=0x**&token=***********
返回数据示例
{
"success": true,
"message": "",
"data": 子链交易信息
}
获得子链对应Hash的交易明细¶
方法:getTransactionReceiptByHash
参数:
microip: monitor节点地址
microport: monitor节点端口
microchainaddress: 子链SubChain地址
hash: 交易hash
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/micro/v1.0/getTransactionReceiptByHash
BODY:microip=127.0.0.1µport=8546µchainaddress=0x***&hash=0x**&token=***********
返回数据示例
{
"success": true,
"message": "",
"data": 子链交易明细,其中主要字段描述如下:
failed:交易是否成功 false表示成功
result:如执行合约方法,retrun的数据
transactionHash:子链hash
contractAddress:当部署合约时,返回合约地址
}
获取子链账户余额¶
方法:getBalance
参数:
microip: monitor节点地址
microport: monitor节点端口
microchainaddress: 子链SubChain地址
address: 账户地址
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/micro/v1.0/getBalance
BODY:vnodeip=&vnodeport=µip=127.0.0.1µport=8546µchainaddress=0x*****&address=0x*****&token=**************
返回数据示例
{
"success": true,
"message": "",
"data": 账户余额
}
子链原生币转账¶
方法:transferCoin
参数:
vnodeip: vnode节点地址
vnodeport: vnode节点端口
microip: monitor节点地址
microport: monitor节点端口
microchainaddress: 子链SubChain地址
via: 子链收益账号
from: 源账户地址
to: 目标账户地址
amount: 原生币数量
privatekey: 源账号私钥(传privatekey,可忽略参数pwd和encode,不传privatekey,则必须传pwd和encode认证)
pwd: 账户密码
encode:账户加密串
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/micro/v1.0/transferCoin
BODY:vnodeip=&vnodeport=µip=127.0.0.1µport=8546µchainaddress=0x**&via=0x**&from=0x**&to=0x**&amount=**&privatekey=0x***&token=*****
返回数据示例
{
"success": true,
"message": "",
"data": 交易hash
}
子链加签交易¶
方法:sendRawTransaction 调用dapp合约涉及修改数据的方法
参数:
vnodeip: vnode节点地址
vnodeport: vnode节点端口
microip: monitor节点地址
microport: monitor节点端口
from: 发送交易账户地址
microchainaddress: 子链SubChain地址
via: 子链收益账号
amount: payable对应金额
dappaddress: dapp合约地址
method: dapp合约方法 比如:buyMintToken(uint256)
paramtypes: dapp合约方法对应的参数类型 比如:["uint256"]
paramvalues: dapp合约方法对应的参数值 比如:[100000000]
privatekey: 源账号私钥(传privatekey,可忽略参数pwd和encode,不传privatekey,则必须传pwd和encode认证)
pwd: 账户密码
encode:账户加密串
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/micro/v1.0/sendRawTransaction
BODY:vnodeip=&vnodeport=µip=127.0.0.1µport=8546&from=0x**µchainaddress=0x***&via=0x**&amount=**&dappaddress=0x***&method=buyMintToken(uint256)¶mtypes=["uint256"]¶mvalues=[100000000]&privatekey=0x***&token=*****
返回数据示例
{
"success": true,
"message": "",
"data": 子链交易hash
}
子链合约调用¶
方法:callContract 针对public方法和变量,不涉及数据修改
参数:
microip: monitor节点地址
microport: monitor节点端口
microchainaddress: 子链SubChain地址
dappaddress: dapp合约地址
data: 字符串数组,如合约方法getTopicList(uint pageNum, uint pageSize),则传入["getTopicList", "0", "20"]
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/micro/v1.0/callContract
BODY:vnodeip=&vnodeport=µip=127.0.0.1µport=8546µchainaddress=0x*****&dappaddress=0x**&data=&token=********
返回数据示例
{
"success": true,
"message": "",
"data": 合约返回结果
}
子链ERC提币¶
方法:redeemErcMintToken 原生币转erc20
参数:
vnodeip: vnode节点地址
vnodeport: vnode节点端口
microipHmonitor节点地址
microport: monitor节点端口
microchainaddress: 子链SubChain地址
dappbaseaddress: dappbase合约地址
via: 子链收益账号
address: 提币账户地址
amount: 提取原生币数量
privatekey: 源账号私钥(传privatekey,可忽略参数pwd和encode,不传privatekey,则必须传pwd和encode认证)
pwd: 账户密码
encode:账户加密串
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/micro/v1.0/redeemErcMintToken
BODY:vnodeip=&vnodeport=µip=127.0.0.1µport=8546µchainaddress=0x**&dappbaseaddress=0x**&via=0x**&address=0x**&amount=**&data=****&privatekey=0x**&token=********
返回数据示例
{
"success": true,
"message": "",
"data": 交易hash
}
子链MOAC提币¶
方法:redeemMoacMintToken 原生币转moac
参数:
vnodeip: vnode节点地址
vnodeport: vnode节点端口
microipHmonitor节点地址
microport: monitor节点端口
microchainaddress: 子链SubChain地址
dappbaseaddress: dappbase合约地址
via: 子链收益账号
address: 提币账户地址
amount: 提取原生币数量
privatekey: 源账号私钥(传privatekey,可忽略参数pwd和encode,不传privatekey,则必须传pwd和encode认证)
pwd: 账户密码
encode:账户加密串
token: auth返回的授权token
调用示例:
POST: http://139.198.126.104:8080/api/micro/v1.0/redeemMoacMintToken
BODY:vnodeip=&vnodeport=µip=127.0.0.1µport=8546µchainaddress=0x**&dappbaseaddress=0x**&via=0x**&address=0x**&amount=**&data=****&privatekey=0x**&token=********
返回数据示例
{
"success": true,
"message": "",
"data": 交易hash
}
SDK¶
SDK 简介¶
为了方便用户接入,MOAC官方提供nodejs 版本的SDK,官方暂不考虑提供其他版本的SDK。
Node.JS SDK下载安装
npm install moac-api
Node.JS SDK异常处理说明:
应用方根据自己业务逻辑对sdk方法进行 try catch 异常处理
示例:
var VnodeChain = require("moac-api").vnodeChain;
try{
var vc = new VnodeChain("http://47.106.69.61:8989");
var blockNumber = vc.getBlockNumber();
console.log(blockNumber);
}catch (e){
console.log(e);
}
SDK 接口¶
钱包模块¶
注册¶
Node.JS Example
参数:
pwd:钱包账户密码
代码:
var account = require("moac-api").account;
var wallet = account.register(pwd);
返回:
wallet:
{ address: '钱包地址....',
privateKey: '私钥....',
keyStore: 'keyStore内容...'
}
登录¶
Node.JS Example
参数:
addr:钱包地址
pwd:钱包密码
keyStore:keyStore
代码:
var account = require("moac-api").account;
var status = account.login(addr, pwd, keyStore);
返回:
status:0 //登录失败
status:1 //登录成功
status:2 //密码错误
主链模块¶
实例化主链对象¶
Node.JS Example
参数:
vnodeAddress:主链访问地址 //http://47.106.69.61:8989
代码:
var VnodeChain = require("moac-api").vnodeChain;
var vc = new VnodeChain(vnodeAddress);
获取主链某一区块信息¶
Node.JS Example
参数:
hashOrNumber:区块hash或区块高度
代码:
var blockInfo = vc.getBlockInfo(hashOrNumber);
返回:
blockInfo:某一区块信息
获取主链交易详情¶
Node.JS Example
参数:
hash:交易hash
代码:
var tradeInfo = vc.getTransactionByHash(hash);
返回:
tradeInfo:交易详情
获取合约实例¶
Node.JS Example
参数:
microChainAddress:子链地址
versionKey:版本号(默认0.1版本)
代码:
var data = vc.getSubChainBaseInstance(microChainAddress, versionKey);
返回:
data:合约实例
获取主链账户余额¶
Node.JS Example
参数:
addr:钱包账户地址
代码:
var balance = vc.getBalance(addr);
返回:
balance:主链账户余额(单位为moac)
获取主链账户ERC代币余额¶
Node.JS Example
参数:
addr:钱包账户地址
contractAddress:合约地址
代码:
var balance = vc.getErcBalance(addr, contractAddress);
返回:
balance:账户ERC代币余额(erc20最小单位)
获取主链合约实例¶
Node.JS Example
参数:
abiObj:abi对象
contractAddress:合约地址
代码:
var object = vc.getContractInstance(abiObj, contractAddress);
返回:
object:主链合约实例对象
获取交易Data¶
参数:
method:方法 例 "issue(address,uint256)"
paramTypes:paramTypes 参数类型数组 例['address','uint256']
paramValues:paramValues 参数值数组 例['0x.....',10000](如需要传金额的入参为erc20最小单位)
代码:
var data = mc.getData(method,paramTypes,paramValues);
返回:
data:data字符串
主链加签交易¶
Node.JS Example
参数:
from:交易发送人
to:交易接受者(可以为个人地址,或者主链上的合约地址)
amount:交易金额
method:方法 例 "issue(address,uint256)"
paramTypes:paramTypes 参数类型数组 例['address','uint256']
paramValues:paramValues 参数值数组 例['0x.....',10000](如需要传金额的入参为erc20最小单位)
privateKey:交易发起人私钥字符串
gasPrice:gas费用(默认为0,如返回错误为gas过低,请在返回的gas基础上加上整数gas重新提交)
代码:
vc.sendRawTransaction(from, to, amount, method, paramTypes, paramValues, privateKey, gasPrice).then((hash) => {
console.log(hash);
});
返回:
hash:交易hash
主链MOAC转账¶
参数:
from:转账人地址
to:收款人地址
amount:交易金额(单位为moac)
privatekey:转账人私钥
代码:
vc.transferMoac(from, to, amount, privatekey).then((hash) => {
console.log(hash);
});
返回:
hash:交易hash
主链ERC代币转账¶
参数:
from:转账人地址
to:收款人地址
contractAddress:erc代币合约地址
amount:交易金额(单位为moac)
privateKey:转账人私钥
代码:
vc.transferErc(from, to, contractAddress, amount, privateKey).then((hash) => {
console.log(hash);
});
返回:
hash:交易hash
调用主链合约¶
参数:
method:方法 例 "issue(address,uint256)"
paramTypes:paramTypes 参数类型数组 例['address','uint256']
paramValues:paramValues 参数值数组 例['0x.....',10000](如需要传金额的入参为erc20最小单位)
contractAddress:合约地址
代码:
var callRes = vc.callContract(method, paramTypes, paramValues, contractAddress);
返回:
callRes:调用合约返回信息
ERC20充值¶
参数:
addr:钱包地址
privateKey:钱包私钥
microChainAddress:子链地址
method:方法 "issue(address,uint256)"
paramTypes:paramTypes 参数类型数组 ['address','uint256']
paramValues:paramValues 参数值数组 ['0x.....',10000](需要传金额的入参为erc20最小单位)
代码:
vc.buyErcMintToken(addr, privateKey, microChainAddress, method, paramTypes, paramValues).then((hash) => {
console.log(hash);
});
返回:
hash:交易hash
MOAC充值¶
参数:
addr:钱包地址
privateKey:钱包私钥
microChainAddress:子链地址
method:方法 "issue(address,uint256)"
paramTypes:paramTypes 参数类型数组 ['address','uint256']
paramValues:paramValues 参数值数组 ['0x.....',10000](金额单位为moac)
代码:
vc.buyMoacMintToken(addr, privateKey, microChainAddress, method, paramTypes, paramValues).then((hash) => {
console.log(hash);
});
返回:
hash:交易hash
子链模块¶
实例化子链对象¶
Node.JS Example
参数:
vnodeAddress:主链访问地址 //http://47.106.69.61:8989
monitorAddress:子链访问地址 //http://47.106.89.22:8546
microChainAddress:子链地址
via:子链via
代码:
var MicroChain = require("moac-api").microChain;
var mc = new MicroChain(vnodeAddress, monitorAddress, microChainAddress, via);
获取子链区块高度¶
Node.JS Example
代码:
mc.getBlockNumber().then((blockNumber) => {
console.log(blockNumber);
});
返回:
blockNumber:子链区块高度
获取某一区间内的多个区块信息¶
Node.JS Example
参数:
start:开始高度
end:结束高度
代码:
mc.getBlocks(start, end).then((blockListInfo) => {
console.log(blockListInfo);
});
返回:
blockListInfo:区块信息List
获取子链某一区块信息¶
Node.JS Example
参数:
blockNumber:区块高度
代码:
mc.getBlock(blockNumber).then((blockInfo) => {
console.log(blockInfo);
});
返回:
blockInfo:某一区块信息
获取子链交易详情¶
Node.JS Example
参数:
transactionHash:交易hash
代码:
mc.getTransactionByHash(transactionHash).then((transactionInfo) => {
console.log(transactionInfo);
});
返回:
transactionInfo:交易详情
获取子链账户余额¶
Node.JS Example
参数:
addr:钱包地址
代码:
mc.getBalance(addr).then((balance) => {
console.log(balance);
});
返回:
data:子链账户余额(erc20最小单位)
获取子链详细信息¶
Node.JS Example
代码:
mc.getMicroChainInfo().then((microChainInfo) => {
console.log(microChainInfo);
});;
返回:
microChainInfo:子链信息
获取子链DAPP状态¶
Node.JS Example
代码:
mc.getDappState().then((state) => {
console.log(state);
});;
返回:
state:1//正常
state:0//异常
获取Nonce¶
Node.JS Example
参数:
addr:账户钱包地址
代码:
mc.getNonce(addr).then((nonce) => {
console.log(nonce);
});;
返回:
nonce:得到的nonce
获取子链DAPP合约实例¶
参数:
dappContractAddress:dapp合约地址
dappAbi:dapp合约的Abi对象
代码:
var dapp = getDappInstance(dappContractAddress, dappAbi);
返回:
dapp:dapp实例
获取交易Data¶
参数:
method:方法 例 "issue(address,uint256)"
paramTypes:paramTypes 参数类型数组 例['address','uint256']
paramValues:paramValues 参数值数组 例['0x.....',10000](如需要传金额的入参为erc20最小单位)
代码:
var data = mc.getData(method,paramTypes,paramValues);
返回:
data:data字符串
子链加签交易¶
Node.JS Example
参数:
from:发送方的钱包地址
microChainAddress:子链地址
amount:交易金额
dappAddress:dapp地址
method:方法 例 "issue(address,uint256)"
paramTypes:paramTypes 参数类型数组 例['address','uint256']
paramValues:paramValues 参数值数组 例['0x.....',10000](如需要传金额的入参为erc20最小单位)
privateKey:发送方钱包私钥
代码:
mc.sendRawTransaction(from, microChainAddress, amount, dappAddress, method, paramTypes, paramValues, privateKey).then((hash) => {
console.log(hash);
});
返回:
hash:交易hash
子链转账¶
Node.JS Example
参数:
from:发送方的钱包地址
to:接收方的钱包地址
amount:交易金额(erc20最小单位)
privateKey:钱包私钥
代码:
mc.transferCoin(from, to, amount, privateKey).then((hash) => {
console.log(hash);
});
返回:
hash:交易hash
调用子链合约¶
参数:
contractAddress:dapp合约地址
param:例如合约中存在一个无参的方法getDechatInfo,则传入["getDechatInfo"];
存在一个有参的方法getTopicList(uint pageNum, uint pageSize), 则传入["getTopicList", 0, 20]
代码:
mc.callContract(contractAddress, param).then((data) => {
console.log(data);
});
返回:
data:调用合约返回信息
提币(MOAC)¶
参数:
addr:钱包地址
amount:金额(单位为moac)
privateKey:钱包私钥
代码:
mc.redeemMoacMintToken(addr, amount, privateKey).then((hash) => {
console.log(hash);
});
返回:
hash:交易hash
提币(ERC20)¶
参数:
addr:钱包地址
amount:金额(erc20最小单位)
privateKey:钱包私钥
代码:
mc.redeemErcMintToken(addr, amount,privateKey).then((hash) => {
console.log(hash);
});
返回:
hash:交易hash
DAPPs¶
去中心化应用(DAPPs)¶
墨客平台上的去中心化应用(DAPP)即可以部署在母链,也可以单独部署一条子链。
子链 DApps 应用¶
DApp runs on MicroChain means it has its own blockchain that supports transactions, data access, control flow in a layered structure. It creates the framework to allow users to execute Smart Contract in an efficient way. It also provides the architecture to spawn sub blockchains using underlying infrastructure quickly and easily. It is a Blockchain platform with necessary plumbing parts available to sub blockchains, providing solution for idea test, private chain deployment, complex task processing, decentralized applications etc.
部署和使用 ERC20 通证¶
Creating your own ERC20 Token on the MOAC blockchain¶
Before you read this page, you should:
- Understand the following general concepts: blockchain, smart contracts, ERC20 tokens;
- Be able to write a basic Ethereum smart contract in Solidity (see tutorial example);
After you read this page, you will be able to:
- Write your own ERC20 token contract;
- Compile and deploy it on the MOAC blockchain;
- Use the ERC20 token;
Write the ERC20 token smart contract¶
The ERC20 standard is developed by the Ethereum community.
contract ERC20Token {
string public name;
string public symbol;
uint public decimals;
uint256 public totalSupply;
function balanceOf(address _owner) public constant returns (uint256 balance);
function transfer(address _to, uint256 _value) public returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
function approve(address _spender, uint256 _value) public returns (bool success);
function allowance(address _owner, address _spender) public constant returns (uint256 remaining);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
User can develop its own ERC20 token. For that, we can either use a ready open source library to help with the task, or write the needed smart contracts directly from scratch. We will show both methods below so you can master your ERC20 token development skills.
Using a ready open source library¶
Let’s see how you can implement this interface by taking advantage of the OpenZeppelin Solidity library, for instance. We will write a TestCoin based on, for example, the PausableToken contract in OpenZeppelin:
pragma solidity ^0.4.18;
import "zeppelin-solidity/contracts/token/PausableToken.sol";
contract TestCoin is PausableToken {
string public name = "Test";
string public symbol = "TEST";
uint public decimals = 6;
uint public INITIAL_SUPPLY = 100000000 * (10 ** decimals);
function TestCoin() public {
totalSupply = INITIAL_SUPPLY;
balances[msg.sender] = INITIAL_SUPPLY;
}
}
To understand better all the steps that the inheritance from PausableToken has achieved in making our TestCoin a useful ERC20-compliant token (and why it can be helpful to start from an open source library like OpenZeppelin), you can follow closely the code of each of the library’s files that were imported after each inheritance and import is fully expanded.
For that, browsing the OpenZeppelin ERC20 token github repo will be very helpful: our TestCoin is inheriting from PausableToken, which itself inherits from StandardToken, which inherits from BasicToken and ERC20, and so on all the way to ERC20Basic and the SafeMath library import.
Developing your smart contract directly¶
Another way of doing this is to simply write the ERC20 interface and your contract implementing it directly from scratch. As you’ll see, this is actually a fairly straightforward task:
pragma solidity ^0.4.16;
contract ERC20Token {
uint256 public totalSupply;
function balanceOf(address _owner) public constant returns (uint256 balance);
function transfer(address _to, uint256 _value) public returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
function approve(address _spender, uint256 _value) public returns (bool success);
function allowance(address _owner, address _spender) public constant returns (uint256 remaining);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
contract TestToken is ERC20Token {
string public name = "Test Coin";
string public symbol = "TEST";
uint8 public decimals = 6;
uint256 public INITIAL_SUPPLY = 100000000 * (10 ** uint256(decimals));
mapping (address => uint256) balances;
mapping (address => mapping (address => uint256)) allowed;
function TestToken() {
totalSupply = INITIAL_SUPPLY;
balances[msg.sender] = INITIAL_SUPPLY;
}
function transfer(address _to, uint256 _value) public returns (bool success) {
require(balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]);
require(_to != 0x0);
balances[msg.sender] -= _value;
balances[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value);
balances[_to] += _value;
balances[_from] -= _value;
allowed[_from][msg.sender] -= _value;
emit Transfer(_from, _to, _value);
return true;
}
function balanceOf(address _owner) public constant returns (uint256 balance) {
return balances[_owner];
}
function approve(address _spender, uint256 _value) public returns (bool success) {
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender) public constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}
}
Make sure to save your TestToken contract to a file on your computer (e.g. TestToken.sol).
Compile and deploy ERC20 token smart contract¶
As a next step, you’ll need to generate the bytecode and ABI for your new smart contract. You can think of the bytecode as basically your contract’s compiled code. The ABI (Application Binary Interface) is a JavaScript Object that defines how to interact with your smart contract.
We will show three ways of achieving this as well - using MOAC wallet, Remix web IDE for Solidity development, or compiling using the solc compiler on your machine (i.e. the command line).
Using MOAC wallet¶
MOAC wallet is an online free, client-side interface for using MOAC wallets, make transactions and deploy contract. It was developed based on open-source software. To use the service, you need to run a local MOAC node with addition command line arguments:
--rpccorsdomain "http://wallet.moac.io"
This will allow the access of MOAC node using MOAC wallet.
Otherwise you will see the following error message:

ERC20_moacwallet01.png
Example command to start a MOAC node connecting with mainnet:
moac --rpccorsdomain "http://wallet.moac.io" --rpc --rpcport "8545" --rpcapi "chain3,mc,net,db"
A successful interface connecting to mainnet looks like this:

ERC20_moacwallet02.png
To compile the contract, click the “CONTRACTS” icon:

ERC20_moacwallet03.png
Then enter the contract deploy page:

ERC20_moacwallet04.png
Copy the source code and paste in the “SOLIDITY CONTRACT SOURCE CODE” section. After copying the source code, the compiling process will automatically started. If no errors are not found, the right side should show a “SELECT CONTRACT TO DEPLOY” menu.

ERC20_moacwallet05.png
Select the contract name “TokenERC20”:

ERC20_moacwallet06.png
Input the parameters values from the menu:

ERC20_moacwallet07.png
You need to have enough balance to deploy the contract. You can choose the amount of fee to use when deploying the contract. Click the DEPLOY button:

ERC20_moacwallet08.png
This is the contract ready to send from Account 1. The Provide gas is estimated by the compiler and we suggest you use it or put a larger number. If gas is not enough, the contract cannot be created. To continue, be sure to unlock the account to create the contract. You can use a console attached to the MOAC to do this:

ERC20_moacwallet09.png
After deploying, the interface is returned to the main menu and you can see the following transaction is creating.

ERC20_moacwallet10.png
After 12 confirmations, you can start using the contract by click the admin page link.

ERC20_moacwallet11.png
MOAC wallet is good for beginners that only need basic contract development needs. It cannot debug contracts. To advanced developers, you can use Remix to work with contracts.
Remix¶
Remix is an online tool developed by Ethereum community to work with smart contracts. MOAC also supports the deploy of smart contract through Remix.
Open Remix on your browser, create a new file called ‘TestToken.sol’ and copy paste the code of your smart contract. Make sure you are including all the other Solidity files that your code is referencing with imports, especially if you are using the open source library approach.
Select ‘TestToken’ in the Compile window then click “Start to Compile” and the Details button next to TestToken. Upon scrolling in the popup details window for TestToken, you should be able to see similar sections to this Remix screenshot for the bytecode and ABI of your smart contract:
If the contract is compiled successfully, remix will show the interface like this:

ERC20_moacwallet12.png
To deploy the contract, you need to connect REMIX to a local or remote MOAC node. In addition to other arguments, be sure to enable the access of REMIX to the MOAC node with
moac --rpccorsdomain "http://remix.ethereum.org" --rpc --rpcport "8545" --rpcapi "chain3,mc,net,db"
Click the Run Tab and you should see the following menu:

ERC20_moacwallet13.png
Choose the Environment menu: JavaScript VM is a simulated environment of Remix, it can be use to debugging the contract without actually deploying the contract to a real network. Injected Web3 is the default web3 connecting to Ethereum network. To deploy MOAC contract, you need to choose Web3 Provider.

ERC20_moacwallet14.png
After choose “Web3 Provider”, you can see a message like this:
Click “OK”,

ERC20_moacwallet15.png
You need to make sure the port is the same as the local running node.

ERC20_moacwallet12.png
You may see the error message like this:

ERC20_moacwallet17.png
If you see this error message, check the local node that include both
--rpccorsdomain "http://remix.ethereum.org"
and
--rpcport "8545"
If the connection is established, you should see your accounts from the Account List.

ERC20_moacwallet18.png
Before you deploy the contract, you need to unlock the account that send the contract. You can do the unlock with the MOAC console:

ERC20_moacwallet09.png
After successfully deployed the contract, you should see the contract address and other information showed in the menu:

ERC20_moacwallet19.png
Remix is good for developing and debugging smart contracts. It is not very convenient to deploy multiple contracts. If your requires to deploy multiple contracts, you can use the Node.Js packages.
Using the Node.Js packages¶
You need to install solc package to compile the smart contract, and chain3 package to deploy the contract.
To use the latest stable version of the Solidity compiler via Node.js you can install it via npm:
npm install solc
var solc = require('solc')
var input = 'contract x { function g() {} }'
// Setting 1 as second paramateractivates the optimiser
var output = solc.compile(input, 1)
for (var contractName in output.contracts) {
// code and ABI that are needed by web3
console.log(contractName + ': ' + output.contracts[contractName].bytecode)
console.log(contractName + '; ' + JSON.parse(output.contracts[contractName].interface))
}
To deploy the contracts, you need to install the Chain3 package:
npm install chain3
There is an example file in the package: example/contract_deploy.js
After successfully deploy, you should see the contract is displayed
Succeed!: 0x95d703ea48477f48335ae9c477ce6d986bc68453dfe3d6582714045456b93405
Using solc compiler to generate the ABI and bytecode Another way of generating these two files is to compile your smart contract using the solc compiler on your machine. If you haven’t used solc yet, you can follow these instructions for installing it on your machine.
Open a Terminal window and navigate to your working directory where you have saved your TestToken.sol file. Run the following command to export the ‘TestToken.abi’ and ‘TestToken.bin’ files to the bin directory:
solc --bin --abi -o bin TestToken.sol
As the file extensions suggest, ‘TestToken.abi’ contains your contract’s ABI, and ‘TestToken.bin’ contains its bytecode.
If you prefer accessing the solc compiler from within a program’s code to generate the ABI and bytecode files rather than using the command line, you can use the following code instead:
var fs = require ( ' fs ' );
var solc = requires ( 'solc' );
var cmds = process.argv;
if(cmds != null && cmds.length > 2){
var file = cmds[2];
var name = cmds[3];
var content = fs.readFileSync(file).toString();
was input = {
file: content
};
var output = solc.compile({sources: input}, 1);
console.log('contracts', Object.keys(output.contracts));
var ctt = output.contracts[name];
if(ctt == null){
return;
}
var bytecode = ctt.bytecode;
var abi = JSON.parse(ctt.interface);
console.log('bytecode', bytecode);
console.log('abi', ctt.interface);
}
Regardless of which method you followed, you should now have the ABI and bytecode files for your TestToken smart contract. Next, you will be able to deploy your token contract on the MOAC blockchain for others to interact with it.
部署和使用 ERC721 通证¶
Creating your own ERC721 Token on MOAC blockchain¶
Before you read this page, you should:
- Understand the following general concepts: blockchain, smart contracts, ERC721 tokens;
- Be able to write a basic Ethereum smart contract in Solidity (see tutorial example);
After you read this page, you will be able to:
- Write your own ERC721 token contract;
- Compile and deploy it on the MOAC blockchain;
- Use the ERC721 token;
Write the ERC721 token smart contract¶
The ERC721 standard is developed by the Ethereum community. It is a standard interface for non-fungible tokens(NFT), also known as deeds.
contract ERC721 {
function balanceOf(address _owner) external view returns (uint256);
function ownerOf(uint256 _tokenId) external view returns (address);
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
function approve(address _approved, uint256 _tokenId) external payable;
function setApprovalForAll(address _operator, bool _approved) external;
function getApproved(uint256 _tokenId) external view returns (address);
function isApprovedForAll(address _owner, address _operator) external view returns (bool);
function supportsInterface(bytes4 interfaceID) external view returns (bool);
event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
}
User can develop its own ERC721 token. For that, we can either use a ready open source library to help with the task, or write the needed smart contracts directly from scratch. We will show all three methods below so you can master your ERC721 token development skills.
Using a ready open source library¶
Let’s see how you can implement this interface by taking advantage of the OpenZeppelin Solidity library, for instance. We will write a TestCoin based on, for example, the PausableToken contract in OpenZeppelin:
pragma solidity ^0.4.18;
import "./ERC721Basic.sol";
import "./ERC721Receiver.sol";
import "../../math/SafeMath.sol";
import "../../AddressUtils.sol";
contract ERC721BasicToken is ERC721Basic {
using SafeMath for uint256;
using AddressUtils for address;
// Equals to `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`
// which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`
bytes4 constant ERC721_RECEIVED = 0xf0b9e5ba;
// Mapping from token ID to owner
mapping (uint256 => address) internal tokenOwner;
// Mapping from token ID to approved address
mapping (uint256 => address) internal tokenApprovals;
// Mapping from owner to number of owned token
mapping (address => uint256) internal ownedTokensCount;
// Mapping from owner to operator approvals
mapping (address => mapping (address => bool)) internal operatorApprovals;
modifier onlyOwnerOf(uint256 _tokenId) {
require(ownerOf(_tokenId) == msg.sender);
_;
}
modifier canTransfer(uint256 _tokenId) {
require(isApprovedOrOwner(msg.sender, _tokenId));
_;
}
function balanceOf(address _owner) public view returns (uint256) {
require(_owner != address(0));
return ownedTokensCount[_owner];
}
function ownerOf(uint256 _tokenId) public view returns (address) {
address owner = tokenOwner[_tokenId];
require(owner != address(0));
return owner;
}
function exists(uint256 _tokenId) public view returns (bool) {
address owner = tokenOwner[_tokenId];
return owner != address(0);
}
function approve(address _to, uint256 _tokenId) public {
address owner = ownerOf(_tokenId);
require(_to != owner);
require(msg.sender == owner || isApprovedForAll(owner, msg.sender));
if (getApproved(_tokenId) != address(0) || _to != address(0)) {
tokenApprovals[_tokenId] = _to;
emit Approval(owner, _to, _tokenId);
}
}
function getApproved(uint256 _tokenId) public view returns (address) {
return tokenApprovals[_tokenId];
}
function setApprovalForAll(address _to, bool _approved) public {
require(_to != msg.sender);
operatorApprovals[msg.sender][_to] = _approved;
emit ApprovalForAll(msg.sender, _to, _approved);
}
function isApprovedForAll(
address _owner,
address _operator
)
public
view
returns (bool)
{
return operatorApprovals[_owner][_operator];
}
function transferFrom(
address _from,
address _to,
uint256 _tokenId
)
public
canTransfer(_tokenId)
{
require(_from != address(0));
require(_to != address(0));
clearApproval(_from, _tokenId);
removeTokenFrom(_from, _tokenId);
addTokenTo(_to, _tokenId);
emit Transfer(_from, _to, _tokenId);
}
function safeTransferFrom(
address _from,
address _to,
uint256 _tokenId
)
public
canTransfer(_tokenId)
{
// solium-disable-next-line arg-overflow
safeTransferFrom(_from, _to, _tokenId, "");
}
function safeTransferFrom(
address _from,
address _to,
uint256 _tokenId,
bytes _data
)
public
canTransfer(_tokenId)
{
transferFrom(_from, _to, _tokenId);
// solium-disable-next-line arg-overflow
require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data));
}
function isApprovedOrOwner(
address _spender,
uint256 _tokenId
)
internal
view
returns (bool)
{
address owner = ownerOf(_tokenId);
// Disable solium check because of
// https://github.com/duaraghav8/Solium/issues/175
// solium-disable-next-line operator-whitespace
return (
_spender == owner ||
getApproved(_tokenId) == _spender ||
isApprovedForAll(owner, _spender)
);
}
function _mint(address _to, uint256 _tokenId) internal {
require(_to != address(0));
addTokenTo(_to, _tokenId);
emit Transfer(address(0), _to, _tokenId);
}
function _burn(address _owner, uint256 _tokenId) internal {
clearApproval(_owner, _tokenId);
removeTokenFrom(_owner, _tokenId);
emit Transfer(_owner, address(0), _tokenId);
}
function clearApproval(address _owner, uint256 _tokenId) internal {
require(ownerOf(_tokenId) == _owner);
if (tokenApprovals[_tokenId] != address(0)) {
tokenApprovals[_tokenId] = address(0);
emit Approval(_owner, address(0), _tokenId);
}
}
function addTokenTo(address _to, uint256 _tokenId) internal {
require(tokenOwner[_tokenId] == address(0));
tokenOwner[_tokenId] = _to;
ownedTokensCount[_to] = ownedTokensCount[_to].add(1);
}
function removeTokenFrom(address _from, uint256 _tokenId) internal {
require(ownerOf(_tokenId) == _from);
ownedTokensCount[_from] = ownedTokensCount[_from].sub(1);
tokenOwner[_tokenId] = address(0);
}
function checkAndCallSafeTransfer(
address _from,
address _to,
uint256 _tokenId,
bytes _data
)
internal
returns (bool)
{
if (!_to.isContract()) {
return true;
}
bytes4 retval = ERC721Receiver(_to).onERC721Received(
_from, _tokenId, _data);
return (retval == ERC721_RECEIVED);
}
}
To understand better all the steps that the inheritance from PausableToken has achieved in making our TestCoin a useful ERC721-compliant token (and why it can be helpful to start from an open source library like OpenZeppelin), you can follow closely the code of each of the library’s files that were imported after each inheritance and import is fully expanded.
For that, browsing the OpenZeppelin ERC721 token github repo will be very helpful: our TestCoin is inheriting from PausableToken, which itself inherits from StandardToken, which inherits from BasicToken and ERC721, and so on all the way to ERC721Basic and the SafeMath library import.
Developing your smart contract directly¶
Another way of doing this is to simply write the ERC721 interface and your contract implementing it directly from scratch. As you’ll see, this is actually a fairly straightforward task:
pragma solidity ^0.4.16;
contract ERC721Token {
uint256 public totalSupply;
function balanceOf(address _owner) public constant returns (uint256 balance);
function transfer(address _to, uint256 _value) public returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
function approve(address _spender, uint256 _value) public returns (bool success);
function allowance(address _owner, address _spender) public constant returns (uint256 remaining);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
contract TestToken is ERC721Token {
string public name = "Test Coin";
string public symbol = "TEST";
uint8 public decimals = 6;
uint256 public INITIAL_SUPPLY = 100000000 * (10 ** uint256(decimals));
mapping (address => uint256) balances;
mapping (address => mapping (address => uint256)) allowed;
function TestToken() {
totalSupply = INITIAL_SUPPLY;
balances[msg.sender] = INITIAL_SUPPLY;
}
function transfer(address _to, uint256 _value) public returns (bool success) {
require(balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]);
require(_to != 0x0);
balances[msg.sender] -= _value;
balances[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value);
balances[_to] += _value;
balances[_from] -= _value;
allowed[_from][msg.sender] -= _value;
emit Transfer(_from, _to, _value);
return true;
}
function balanceOf(address _owner) public constant returns (uint256 balance) {
return balances[_owner];
}
function approve(address _spender, uint256 _value) public returns (bool success) {
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender) public constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}
}
You can get this file directly from OpenZeppelin’s GitHub repo or copy paste the code above and edit it as needed. Make sure to save your contract to a local file on your computer (e.g. ERC721BasicToken.sol). However, the code is only for demonstration only.
Compile and deploy ERC721 token smart contract¶
As a next step, you’ll need to generate the bytecode and ABI for your new smart contract. You can think of the bytecode as basically your contract’s compiled code. The ABI (Application Binary Interface) is a JavaScript Object that defines how to interact with your smart contract.
We will show three ways of achieving this as well - using MOAC wallet, Remix web IDE for Solidity development, or compiling using the solc compiler on your machine (i.e. the command line).
Using MOAC wallet¶
MOAC wallet is an online free, client-side interface for using MOAC wallets, make transactions and deploy contract. It was developed based on open-source software. To use the service, you need to run a local MOAC node with addition command line arguments:
--rpccorsdomain "http://wallet.moac.io"
This will allow the access of MOAC node using MOAC wallet.
Otherwise you will see the following error message:

ERC20_moacwallet01.png
Example command to start a MOAC node connecting with mainnet:
moac --rpccorsdomain "http://wallet.moac.io" --rpc --rpcport "8545" --rpcapi "chain3,mc,net,db"
A successful interface connecting to mainnet looks like this:

ERC20_moacwallet02.png
To compile the contract, click the “CONTRACTS” icon:

ERC20_moacwallet03.png
Then enter the contract deploy page:

ERC20_moacwallet04.png
Copy the source code and paste in the “SOLIDITY CONTRACT SOURCE CODE” section. After copying the source code, the compiling process will automatically started. If no errors are not found, the right side should show a “SELECT CONTRACT TO DEPLOY” menu. |ERC20\_moacwallet05.png| Select the contract name “TokenERC721”: |ERC20\_moacwallet06.png| Input the parameters values from the menu: |ERC20\_moacwallet07.png| You need to have enough balance to deploy the contract. You can choose the amount of fee to use when deploying the contract. Click the DEPLOY button: |ERC20\_moacwallet08.png|
This is the contract ready to send from Account 1. The Provide gas is estimated by the compiler and we suggest you use it or put a larger number. If gas is not enough, the contract cannot be created. To continue, be sure to unlock the account to create the contract. You can use a console attached to the MOAC to do this:

ERC20_moacwallet09.png
After deploying, the interface is returned to the main menu and you can see the following transaction is creating.
|ERC20\_moacwallet10.png| After 12 confirmations, you can start using the contract by click the admin page link. |ERC20\_moacwallet11.png|
MOAC wallet is good for beginners that only need basic contract development needs. It cannot debug contracts. To advanced developers, you can use Remix to work with contracts.
Remix¶
Remix is an online tool developed by Ethereum community to work with smart contracts. MOAC also supports the deploy of smart contract through Remix.
Open Remix on your browser, create a new file called ‘TestToken.sol’ and copy paste the code of your smart contract. Make sure you are including all the other Solidity files that your code is referencing with imports, especially if you are using the open source library approach.
Select ‘TestToken’ in the Compile window then click “Start to Compile” and the Details button next to TestToken. Upon scrolling in the popup details window for TestToken, you should be able to see similar sections to this Remix screenshot for the bytecode and ABI of your smart contract:
If the contract is compiled successfully, remix will show the interface like this:
|ERC20\_moacwallet12.png| To deploy the contract, you need to connect REMIX to a local or remote MOAC node. In addition to other arguments, be sure to enable the access of REMIX to the MOAC node with
moac --rpccorsdomain "http://remix.ethereum.org" --rpc --rpcport "8545" --rpcapi "chain3,mc,net,db"
Click the Run Tab and you should see the following menu: |ERC20\_moacwallet13.png|
Choose the Environment menu: JavaScript VM is a simulated environment of Remix, it can be use to debugging the contract without actually deploying the contract to a real network. Injected Web3 is the default web3 connecting to Ethereum network. To deploy MOAC contract, you need to choose Web3 Provider.

ERC20_moacwallet14.png
After choose “Web3 Provider”, you can see a message like this:
Click “OK”,

ERC20_moacwallet15.png
You need to make sure the port is the same as the local running node.

ERC20_moacwallet12.png
You may see the error message like this:
|ERC20\_moacwallet17.png| If you see this error message, check the local node that include both
--rpccorsdomain "http://remix.ethereum.org"
and
--rpcport "8545"
If the connection is established, you should see your accounts from the Account List.

ERC20_moacwallet18.png
Before you deploy the contract, you need to unlock the account that send the contract. You can do the unlock with the MOAC console:

ERC20_moacwallet09.png
After successfully deployed the contract, you should see the contract address and other information showed in the menu:

ERC20_moacwallet19.png
Remix is good for developing and debugging smart contracts. It is not very convenient to deploy multiple contracts. If your requires to deploy multiple contracts, you can use the Node.Js packages.
Using the Node.Js packages¶
You need to install solc package to compile the smart contract, and chain3 package to deploy the contract.
To use the latest stable version of the Solidity compiler via Node.js you can install it via npm:
npm install solc
var solc = require('solc')
var input = 'contract x { function g() {} }'
// Setting 1 as second paramateractivates the optimiser
var output = solc.compile(input, 1)
for (var contractName in output.contracts) {
// code and ABI that are needed by web3
console.log(contractName + ': ' + output.contracts[contractName].bytecode)
console.log(contractName + '; ' + JSON.parse(output.contracts[contractName].interface))
}
To deploy the contracts, you need to install the Chain3 package:
npm install chain3
There is an example file in the package: example/contract_deploy.js
After successfully deploy, you should see the contract is displayed
Succeed!: 0x95d703ea48477f48335ae9c477ce6d986bc68453dfe3d6582714045456b93405
Using solc compiler to generate the ABI and bytecode Another way of generating these two files is to compile your smart contract using the solc compiler on your machine. If you haven’t used solc yet, you can follow the
FileStorm 使用指南¶
介绍¶
星际风暴是一个通过墨客子链将星际文件系统(IPFS)和区块链结合而产生的分布式存储平台。星际风暴构建在墨客子链之上,使得有存储需求的用户可以消耗通证来得到存储空间,而提供存储空间的节点提供者通过竞争来获得通证。这种激励方式可以鼓励大家把闲置的硬盘空间来共享,从而搭建一个可商用的全球化存储空间。更多信息可以访问项目网站(https://www.filestorm.net)。
FileStorm is a decentralized storage platform implemented with IPFS and MOAC. The files are stored on millions of data nodes provided by people around the world in IPFS format in exchange for MOAC. FileStorm is a project that involves three types of users.
- Storage Provider: Provides the hardware devices used for storage, such as computers with large volume of storage, or customized storage boxes. FileStorm program needs to be installed on these devices so they can connect to Moac FileStorm microchains as well as IPFS network. Storage providers can gain reward in MOAC by offering the storage service.
- Dapp Developers: The creator and owner of FileStorm microchains. They can create a dedicated microchain used for storage only for their own Dapp. Moac Foundation will also create a public FileStorm microchain. Dapp Developers will have to pay MOAC to deploy and maintain a FileStorm.
- Storage End Users: The users will use FileStorm through Dapps. The end users do not need any MOAC to use FileStorm, but they may have to pay to use the Dapps.
使用者¶
存储提供方¶
Storage providers are the people who run the FileStore MicroChain as the service.
FileStorm MicroChain needs to install the following packages:
- redis - Local database, used to save the map between public HASH and private HASH;
- IPFS Daemon - IPFS platform to save the data files;
- SCSServer - MOAC MicroChain server;
- stormcatcher - Program calls the IPFS program from MOAC MicroChain server;
These packages can be installed separately or through Docker.
Installation¶
redis:
Ubuntu
sudo apt update
sudo apt full-upgrade
sudo apt install build-essential tcl
curl -O http://download.redis.io/redis-stable.tar.gz
tar xzvf redis-stable.tar.gz
sudo apt install redis-server
CentOs
- ::
- sudo yum install epel-release sudo yum update sudo yum install redis
ipfs:
IPFS can be downloaded from IPFS
Ubuntu
wget https://dist.ipfs.io/go-ipfs/v0.4.17/go-ipfs_v0.4.17_linux-amd64.tar.gz
tar xvfz go-ipfs_v0.4.17_linux-amd64.tar.gz
sudo mv go-ipfs/ipfs /usr/local/bin/ipfs
- ::
- sudo yum install epel-release sudo yum update sudo yum install redis
scsserver:
The newest version can be download from release link.
scsserver stormcatcher userconfig.json run_filestorm_scs.sh stop_filestorm_scs.sh
Then you can execute filestorm_install.sh to install filestorm scs.
Configuration¶
Configuration file: userconfig.json
VnodeServiceCfg can be setup using the Vnode/Port information from Node info - Testnet Protocol Pool. Beneficiary is the public wallet address of SCS owner.
The VNODE server need to open the following ports for outside access: * 4001; * 5001; * 8080;
Running¶
IPFS file system needs to be initialized before the first usage:
ipfs init
Then the user can run FileStorm MicroChain using the start script:
cd scsserver
./run_filestorm_scs.sh
The start script calls the four components in the FileStorm:
#!/bin/bash
echo "Starting FileStorm SCS--"
nohup ipfs daemon > ipfs.out 2>&1 &
echo "IPFS Daemon started."
nohup redis-server > ipfs.out 2>&1 &
echo "Redis Server started. "
nohup ./ipfs_monkey > ipfs.out 2>&1 &
echo "IPFS Monkey started."
nohup ./scsserver > scs.out 2>&1 &
echo "SCS started."
To stop the service, call the following script:
./stop_filestorm_scs.sh
The closing script closed the four components:
#!/bin/bash
echo "Stoping FileStorm SCS--"
pkill ipfs_monkey
pkill redis-server
pkill ipfs
pkill scsserver
echo "FileStorm SCS Stopped."
To make the SCSs be able to work with MicroChain, 0.5 moac depsit needs to be added to each SCS’s address.
Monitring:
To check if the MOAC MicroChain running, check the log file:
tail -f scs.out
DAPP Developers¶
DAPP developers deploy the DAPP on the FileStorm MicroChain to let the Storage Users access the data through the DAPP.
To develop a DAPP on the FileStorm platform, you need to: 1. Run a vnode locally to connect to the MOAC mainnet(or testnet for testing). The newest released version is under:
- Start the vnode:
To connect with mainnet:
./moac --rpc --rpccorsdomain "http://wallet.moac.io" console
To connect with testnet:./moac --testnet --rpc --rpccorsdomain "http://wallet.moac.io" console
- Use MOAC walletto deploy the MicroChain;
- DeploySubChainBase.sol
- Find Node info - Testnet SubChainProtocolBase pool地址和 Vnodeproxy pool地址
- Use MOAC wallet to deploy the FileStormMicroChain.sol;
- Register the MicroChain;
- Check the status of MicroChain with MicroChain explorer.
数据存储方¶
Strage users access the data on the IPFS through DAPP deployed on the FileStorm.
Example:
The following procedures show how to access a data file on the FileStorm testnet.
- Setup a local VNODE server. The software can be downloaded from https://github.com/MOACChain/moac-core/releases;
- Running the VNODE:
./moac --testnet console
; - Setup IPFS download;
For ubuntu:
wget https://dist.ipfs.io/go-ipfs/v0.4.17/go-ipfs_v0.4.17_linux-amd64.tar.gz tar xvfz go-ipfs_v0.4.17_linux-amd64.tar.gz sudo mv go-ipfs/ipfs /usr/local/bin/ipfs
Generate a local text file for uploading:
vi newtestfile.txt
Add the generated file to the IPFS system:
ifps add newtestfile.txt
Convert the hash to HEX code, which can be done using this web tool:https://codebeautify.org/string-hex-converter. or using the NODEJS tool: `` npm install –save ethereumjs-abi ``
var abi = require(‘ethereumjs-abi’); var original = ‘QmQNe96LqV5TcRQyBz12iQXPZQjemBqkgnpHki3wmKjtd6’; var encoded = abi.simpleEncode(‘write(string)’, original);
console.log(‘original’, original);
- console.log(‘encoded’,
encoded.toString(‘hex’));
- The HEX code of the HASH should be a HEX code with length 46, total 92 digits. Since the storage of parameters in Solidity only has 32 digits, we used two parameters to store the HEX code of the HASH. The HEX code of the HASH is filled with 0s to make two HEX codes with 64 digits;
- Call the three functions to read, write and delete the data on the MicroChain:
- from: need to be an unlocked account;
- to: DAPP address provided by the DAPP developer or the Storage Provider;
- data: Add the HEX code from Step 7 after ‘2e’;
- After each successful call, the nonce need to increase by 1 for the next call.
- via needs to set as the same value of via in the vnodeproxy.json in the VNODE directory.
// write(fileHash) chain3.mc.sendTransaction( { from: chain3.mc.accounts[0], value:chain3.toSha(‘0’,’mc’), to: subchainbaseaddress, gas: “200000”, gasPrice: chain3.mc.gasPrice, shardingflag: 1, data: ‘0xba3835ba00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002e’ nonce: 1, via: chain3.mc.accounts[0] });
// read(fileHash) chain3.mc.sendTransaction( { from: mc.accounts[0], value:chain3.toSha(‘0’,’mc’), to: subchainbaseaddress, gas: “200000”, gasPrice: chain3.mc.gasPrice, shardingflag: 1, data: ‘0x616ffe830000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002e’ nonce: 2, via: mc.accounts[0] });
// remove(fileHash) chain3.mc.sendTransaction( { from: mc.accounts[0], value:chain3.toSha(‘0’,’mc’), to: subchainbaseaddress, gas: “200000”, gasPrice: chain3.mc.gasPrice, shardingflag: 1, data: ‘0x80599e4b0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002e’ nonce: 3, via: mc.accounts[0] }); ```
Results:
Write:a file was written to FileStorm MicroChain’s nodes with a HASH;
Read:A file will be read from FileStorm nodes; Remove:The data file will be removed from every FileStorm node;
移植到墨客平台¶
MOAC developed its VNODE client based on the Ethereum project. It also implements a *javascript runtime environment* (JSRE) that can be used in either interactive (console) or non-interactive (script) mode. It supports Dapp development through its own `chain3 <>`__ JavaScript API, just like web3.js on Ethereum.
If you want to develop Dapp on MOAC, you should use Solidity. MOAC supports the deployment of smart contracts through Remix, wallet.moac.io and For a Dapp that wants to move to MOAC from Ethereum, please follow these steps:
Deploy the smart contract:
- Remix, a browser compiler for Solidity.
- wallet.moac.io, a browser Dapp connect with local nodes to deploy contracts.
- Node.Js Solidity compiler, a JavaScript bindings for the Solidity compiler.
You can check the two examples in our wiki page:
Interact with the smart contract:
Example¶
Web3.js:
var Web3 = require('../index.js');
var web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));
var coinbase = web3.eth.coinbase;
console.log(coinbase);
var balance = web3.eth.getBalance(coinbase);
console.log(balance.toString(10));
Chain3:
var Chain3 = require('../index.js');
var chain3 = new Chain3();
chain3.setProvider(new chain3.providers.HttpProvider('http://localhost:8545'));
var coinbase = chain3.mc.accounts[0];
console.log(coinbase);
var balance = web3.eth.getBalance(coinbase);
console.log(balance.toString(10));