RPC 调用方法
RpcClient
封装了所有 RpcServer
提供的接口,可以通过该模块中提供的标准方法在代码中发送 RPC 请求,只需要传入相应的参数,SDK 就会根据参数构造相应的 JSON-RPC 请求,进而获得节点返回的数据。
#
初始化发送 RPC 请求需要先初始化 RpcClient
类型,可以根据自己的需要选择一个 Neo 节点的 RPC Server 端口,这里举例说明:
测试网节点:
// TestNet NodeRpcClient client = new RpcClient(new Uri("http://seed1.neo.org:20332"), null, null, ProtocolSettings.Load("config.json"));
本地节点(本地节点是本地维护的 Neo-CLI,可以根据配置连接主网,测试网或者私链):
// Local NodeRpcClient client = new RpcClient(new Uri("http://localhost:20332"), null, null, ProtocolSettings.Load("config.json"));
note
一个应用程序中一般只需要初始化一个 RpcClient
实例,而不需要在每个方法中初始化。
#
区块链数据#
获取最新区块哈希获取区块链中高度最大的区块的哈希:
string hexString = await client.GetBestBlockHashAsync().ConfigureAwait(false);byte[] hashBytes = hexString.HexToBytes();UInt256 hash256 = UInt256.Parse(hexString);
#
获取区块完整信息可以通过区块散列值或者区块索引获取具体的区块信息:
RpcBlock rpcBlock = await client.GetBlockAsync("773dd2dae4a9c9275290f89b56e67d7363ea4826dfd4fc13cc01cf73a44b0d0e").ConfigureAwait(false);Block block = rpcBlock.Block;
或者
RpcBlock rpcBlock = await client.GetBlockAsync("1024").ConfigureAwait(false);Block block = rpcBlock.Block;
也可以通过区块散列值或者区块索引获取序列化后的区块信息:
string serializedBlock = await client.GetBlockHexAsync("773dd2dae4a9c9275290f89b56e67d7363ea4826dfd4fc13cc01cf73a44b0d0e").ConfigureAwait(false);
#
获取当前区块数量区块索引(Index) = 区块高度(Height) = 区块数量(Count) - 1
uint blockCount = await client.GetBlockCountAsync().ConfigureAwait(false);
#
根据区块索引获取区块的散列:string hexString = await client.GetBlockHashAsync(10000).ConfigureAwait(false);byte[] hashBytes = hexString.HexToBytes();UInt256 hash256 = UInt256.Parse(hexString);
#
获取区块头信息可以通过区块散列值或者区块索引获取具体的区块头信息:
RpcBlockHeader blockHeader = await client.GetBlockHeaderAsync("a5508c9b6ed0fc09a531a62bc0b3efcb6b8a9250abaf72ab8e9591294c1f6957").ConfigureAwait(false);Header header = blockHeader.Header;
或者
RpcBlockHeader blockHeader = await client.GetBlockHeaderAsync("10000").ConfigureAwait(false);Header header = blockHeader.Header;
也可以通过区块散列值或者区块索引获取序列化后的区块头信息:
string serializedBlockHeader = await client.GetBlockHeaderHexAsync("a5508c9b6ed0fc09a531a62bc0b3efcb6b8a9250abaf72ab8e9591294c1f6957").ConfigureAwait(false);
或者
string serializedBlockHeader = await client.GetBlockHeaderHexAsync("10000").ConfigureAwait(false);
#
获取合约信息通过合约哈希获取合约信息:
ContractState contractState = await client.GetContractStateAsync("dc675afc61a7c0f7b3d2682bf6e1d8ed865a0e5f").ConfigureAwait(false);
#
获取内存中的交易列表只获取内存中已确认的交易散列列表:
string[] verifiedTransactions = await client.GetRawMempoolAsync().ConfigureAwait(false);
同时获取内存中已确认和未确认的交易散列列表:
RpcRawMemPool memPool = await client.GetRawMempoolBothAsync().ConfigureAwait(false);string[] verifiedTransactions = memPool.Verified;string[] unverifiedTransactions = memPool.UnVerified;
#
获取交易信息通过交易哈希来获取对应的交易信息:
RpcTransaction rpcTransaction = await client.GetRawTransactionAsync("f4250dab094c38d8265acc15c366dc508d2e14bf5699e12d9df26577ed74d657").ConfigureAwait(false);Transaction transaction = rpcTransaction.Transaction;
也可以通过交易哈希来获取对应的序列化后的交易:
string serializedTransaction = await client.GetRawTransactionHexAsync("f4250dab094c38d8265acc15c366dc508d2e14bf5699e12d9df26577ed74d657").ConfigureAwait(false);
#
计算交易网络费计算指定交易的网络费用
long networkFee = await rpcClient.CalculateNetworkFeeAsync(transaction).ConfigureAwait(false);
#
获取合约存储区的值通过合约脚本散列和存储的键
(需要转化为 hex string)获取对应存储的值:
string value = await client.GetStorageAsync("03febccf81ac85e3d795bc5cbd4e84e907812aa3", "5065746572").ConfigureAwait(false);
#
获取指定交易的高度通过交易哈希获取指定交易所在的区块高度:
uint height = await client.GetTransactionHeightAsync("f4250dab094c38d8265acc15c366dc508d2e14bf5699e12d9df26577ed74d657").ConfigureAwait(false);
#
获取下一轮共识节点的信息获取网络中下一轮共识节点的信息及投票情况:
RpcValidator[] rpcValidators = await client.GetNextBlockValidatorsAsync().ConfigureAwait(false);foreach (var validator in rpcValidators){ string publicKey = validator.PublicKey; BigInteger voteCount = validator.Votes; bool isActive = validator.Active;}
#
获取当前委员会成员获取网络中当前委员会成员公钥列表
string[] committees = await client.GetCommitteeAsync().ConfigureAwait(false);
#
节点#
获取节点连接数获取连接到该节点的节点数量:
int connectionCount = await client.GetConnectionCountAsync().ConfigureAwait(false);
#
获取已连接/未连接的节点获得该节点当前已连接/未连接的节点列表,包括 IP 地址和端口:
RpcPeers rpcPeers = await client.GetPeersAsync().ConfigureAwait(false);;RpcPeer[] connected = rpcPeers.Connected;RpcPeer[] unconnected = rpcPeers.Unconnected;if (connected.Length > 0){ RpcPeer peer = connected[1]; string address = peer.Address; int port = peer.Port;}
#
获取节点的版本信息获取接收 RPC 请求的节点的版本信息:
RpcVersion rpcVersion = await client.GetVersionAsync().ConfigureAwait(false);string version = rpcVersion.UserAgent;
#
广播交易发送并广播序列化后的交易:
UInt256 txHash = await client.SendRawTransactionAsync("80000001195876cb34364dc38b730077156c6bc3a7fc570044a66fbfeeea56f71327e8ab0000029b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc500c65eaf440000000f9a23e06f74cf86b8827a9108ec2e0f89ad956c9b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc50092e14b5e00000030aab52ad93f6ce17ca07fa88fc191828c58cb71014140915467ecd359684b2dc358024ca750609591aa731a0b309c7fb3cab5cd0836ad3992aa0a24da431f43b68883ea5651d548feb6bd3c8e16376e6e426f91f84c58232103322f35c7819267e721335948d385fae5be66e7ba8c748ac15467dcca0693692dac".HexToBytes()).ConfigureAwait(false);
或者将交易对象tx在网络中进行广播:
UInt256 txHash = await client.SendRawTransactionAsync(transaction).ConfigureAwait(false);
#
广播区块发送并广播序列化后的区块:
UInt256 blockHash = await client.SubmitBlockAsync("000000000000000000000000000000000000000000000000000000000000000000000000845c34e7c1aed302b1718e914da0c42bf47c476ac4d89671f278d8ab6d27aa3d65fc8857000000001dac2b7c00000000be48d3a3f5d10013ab9ffee489706078714f1ea2010001510400001dac2b7c00000000400000455b7b226c616e67223a227a682d434e222c226e616d65223a22e5b08fe89a81e882a1227d2c7b226c616e67223a22656e222c226e616d65223a22416e745368617265227d5d0000c16ff28623000000da1745e9b549bd0bfa1a569971c77eba30cd5a4b00000000400001445b7b226c616e67223a227a682d434e222c226e616d65223a22e5b08fe89a81e5b881227d2c7b226c616e67223a22656e222c226e616d65223a22416e74436f696e227d5d0000c16ff286230008009f7fd096d37ed2c0e3f7f0cfc924beef4ffceb680000000001000000019b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc50000c16ff2862300be48d3a3f5d10013ab9ffee489706078714f1ea201000151".HexToBytes()).ConfigureAwait(false);
#
智能合约#
调用智能合约的特定方法通过指定的智能合约脚本散列、方法名和参数在虚拟机中运行后返回结果:
string contractHash = "0xd2a4cff31913016155e38e474a2c06d08be276cf";string method = "transfer";RpcStack from = new RpcStack(){ Type = "Hash160", Value = "0x262678399f390ee9f0cfd9ac8c65df8c149b4e9c"};RpcStack to = new RpcStack(){ Type = "Hash160", Value = "0x753b9b069ef88dea7323a0f1ba6cb24486584f05"};RpcStack amount = new RpcStack(){ Type = "Integer", Value = "120000000"};RpcStack data = new RpcStack(){ Type = "String", Value = "my data"};
Signer signer0 = new Signer(){ Account = UInt160.Parse("0x262678399f390ee9f0cfd9ac8c65df8c149b4e9c")};
RpcInvokeResult rpcInvokeResult = await _rpcClient.InvokeFunctionAsync(contractHash, method, new RpcStack[] { from, to, amount, data }, signer0).ConfigureAwait(false);
string script = rpcInvokeResult.Script;var engineState = rpcInvokeResult.State;long gasConsumed = rpcInvokeResult.GasConsumed;
#
调用指定脚本通过在虚拟机中运行指定脚本后返回结果:
byte[] script = "00046e616d656724058e5e1b6008847cd662728549088a9ee82191".HexToBytes();RpcInvokeResult rpcInvokeResult = await client.InvokeScriptAsync(script).ConfigureAwait(false);
#
获取未领取的Gas获取指定地址未领取的Gas数量:
RpcUnclaimedGas unclaimedGas = await client.GetUnclaimedGasAsync("NXsG3zwpwcfvBiA3bNMx6mWZGEro9ZqTqM").ConfigureAwait(false);BigInteger unclaimed = unclaimedGas.Unclaimed;string address = unclaimedGas.Address;
#
工具#
获取插件信息显示节点已加载的插件列表:
RpcPlugin[] rpcPlugins = await client.ListPluginsAsync().ConfigureAwait(false);foreach (var item in rpcPlugins){ string name = item.Name; string version = item.Version;}
#
验证地址验证指定地址是否是正确的 Neo 地址:
RpcValidateAddressResult result = await client.ValidateAddressAsync("AQVh2pG732YvtNaxEGkQUei3YA4cvo7d2i").ConfigureAwait(false);string address = result.Address;bool isValid = result.IsValid;
#
节点本地钱包节点本地钱包接口包含可以访问节点本地钱包文件的功能,使用该部分的方法之前需要先通过 openwallet
方法打开钱包。
节点的配置文件默认禁用此方法,因为有很高的安全风险。
#
打开钱包打开节点所在机器中的钱包文件:
string path = "D:/temp/123.json";string password = "Password***";bool result = await client.OpenWalletAsync(path, password).ConfigureAwait(false);
#
关闭钱包关闭钱包将清除内存中的钱包信息:
bool result = await client.CloseWalletAsync().ConfigureAwait(false);
#
导出私钥导出指定地址的私钥:
string wif = await client.DumpPrivKeyAsync("NVVwFw6XyhtRCFQ8SpUTMdPyYt4Vd9A1XQ").ConfigureAwait(false);
#
余额查询根据指定的资产哈希,返回钱包中对应资产的余额信息。该方法适用于原生合约资产及符合 NEP-17 标准的合约资产:
BigDecimal balance = await client.GetWalletBalanceAsync(NativeContract.NEO.Hash.ToString()).ConfigureAwait(false);
#
创建账号在打开的钱包文件中创建一个新的账号,并返回该账号的地址:
string address = await client.GetNewAddressAsync().ConfigureAwait(false);
#
获取可提取的 GAS 数量显示钱包中可提取的 GAS 数量:
BigInteger amount = await client.GetWalletUnclaimedGasAsync().ConfigureAwait(false);
#
导入私钥导入私钥到钱包:
string wif = "KyoYyZpoccbR6KZ25eLzhMTUxREwCpJzDsnuodGTKXSG8fDW9t7x";RpcAccount account = await client.ImportPrivKeyAsync(wif).ConfigureAwait(false);
#
列出钱包账号列出当前钱包内的所有地址:
List<RpcAccount> acoounts = await client.ListAddressAsync().ConfigureAwait(false);
#
从指定地址转账从指定地址,向指定地址转账:
string assetId = NativeContract.NEO.Hash.ToString();string fromAddress = "NVVwFw6XyhtRCFQ8SpUTMdPyYt4Vd9A1XQ";string toAddress= "NZs2zXSPuuv9ZF6TDGSWT1RBmE8rfGj7UW";string amount = "100";JObject result = await client.SendFromAsync(assetId, fromAddress, toAddress, amount).ConfigureAwait(false);
返回JSON交易详情说明交易发送成功,否则交易发送失败。 如果签名不完整会返回待签名的交易。 如果余额不足会返回错误信息。
#
批量转账批量转账命令,并且可以指定发送地址:
List<RpcTransferOut> outs = new List<RpcTransferOut>();outs.Add(new RpcTransferOut{ Asset = NativeContract.NEO.Hash, ScriptHash = Utility.GetScriptHash("NVVwFw6XyhtRCFQ8SpUTMdPyYt4Vd9A1XQ"), Value = "100"});outs.Add(new RpcTransferOut{ Asset = NativeContract.GAS.Hash, ScriptHash = Utility.GetScriptHash("NZs2zXSPuuv9ZF6TDGSWT1RBmE8rfGj7UW"), Value = "100.12345678"});JObject result = await client.SendManyAsync("", outs).ConfigureAwait(false);
返回JSON交易详情说明交易发送成功,否则交易发送失败。 如果签名不完整会返回待签名的交易。 如果余额不足会返回错误信息。
#
向指定地址转账向指定地址转账:
string assetId = NativeContract.NEO.Hash.ToString();string toAddress = "NZs2zXSPuuv9ZF6TDGSWT1RBmE8rfGj7UW";string amount = "100";JObject result = await client.SendToAddressAsync(assetId, toAddress, amount).ConfigureAwait(false);
返回JSON交易详情说明交易发送成功,否则交易发送失败。 如果签名不完整会返回待签名的交易。 如果余额不足会返回错误信息。
#
插件#
查询交易日志根据指定的交易 ID 获取合约日志: 需要节点安装 ApplicationLogs 插件才可以调用。
string txHash = "0x23bf33766d00b4bb3314185f1ff0c2c85182d4d5e4e96f7c2df7506e7f99098b";RpcApplicationLog log = await client.GetApplicationLogAsync(txHash).ConfigureAwait(false);
或者根据指定的交易ID和触发器类型获取合约日志:
string txHash = "0x23bf33766d00b4bb3314185f1ff0c2c85182d4d5e4e96f7c2df7506e7f99098b";RpcApplicationLog log = await client.GetApplicationLogAsync(txHash, TriggerType.Application).ConfigureAwait(false);
#
查询 NEP-17 资产余额返回指定地址内的所有 NEP-17 资产余额: 需要节点安装 TokensTracker 插件才可以调用。
string address = "NVVwFw6XyhtRCFQ8SpUTMdPyYt4Vd9A1XQ";RpcNep17Balances balances = await client.GetNep17BalancesAsync(address).ConfigureAwait(false);
#
查询交易记录返回指定地址内的所有 NEP-17 交易记录: 需要节点安装 TokensTracker 插件才可以调用。 如果设置起始和结束时间戳,则返回时间戳范围内的交易信息。 如果不设置此参数,则返回近七天内的交易信息。
string address = "NVVwFw6XyhtRCFQ8SpUTMdPyYt4Vd9A1XQ";RpcNep17Transfers transfers = await client.GetNep17TransfersAsync(address, 0).ConfigureAwait(false);