diff --git a/src/RpcClient/ContractClient.cs b/src/RpcClient/ContractClient.cs
index 0aa3aff3b..a6ffb8f28 100644
--- a/src/RpcClient/ContractClient.cs
+++ b/src/RpcClient/ContractClient.cs
@@ -1,3 +1,5 @@
+using System;
+using System.Threading.Tasks;
using Neo.Network.P2P.Payloads;
using Neo.Network.RPC.Models;
using Neo.SmartContract;
@@ -13,14 +15,21 @@ namespace Neo.Network.RPC
public class ContractClient
{
protected readonly RpcClient rpcClient;
+ protected readonly uint? magic;
+
///
/// ContractClient Constructor
///
/// the RPC client to call NEO RPC methods
- public ContractClient(RpcClient rpc)
+ ///
+ /// the network Magic value to use when signing transactions.
+ /// Defaults to ProtocolSettings.Default.Magic if not specified.
+ ///
+ public ContractClient(RpcClient rpc, uint? magic = null)
{
rpcClient = rpc;
+ this.magic = magic;
}
///
@@ -30,10 +39,10 @@ public ContractClient(RpcClient rpc)
/// contract operation
/// operation arguments
///
- public RpcInvokeResult TestInvoke(UInt160 scriptHash, string operation, params object[] args)
+ public Task TestInvokeAsync(UInt160 scriptHash, string operation, params object[] args)
{
byte[] script = scriptHash.MakeScript(operation, args);
- return rpcClient.InvokeScript(script);
+ return rpcClient.InvokeScriptAsync(script);
}
///
@@ -43,7 +52,7 @@ public RpcInvokeResult TestInvoke(UInt160 scriptHash, string operation, params o
/// contract manifest
/// sender KeyPair
///
- public Transaction CreateDeployContractTx(byte[] contractScript, ContractManifest manifest, KeyPair key)
+ public async Task CreateDeployContractTxAsync(byte[] contractScript, ContractManifest manifest, KeyPair key)
{
byte[] script;
using (ScriptBuilder sb = new ScriptBuilder())
@@ -54,13 +63,11 @@ public Transaction CreateDeployContractTx(byte[] contractScript, ContractManifes
UInt160 sender = Contract.CreateSignatureRedeemScript(key.PublicKey).ToScriptHash();
Signer[] signers = new[] { new Signer { Scopes = WitnessScope.CalledByEntry, Account = sender } };
- Transaction tx = new TransactionManager(rpcClient)
- .MakeTransaction(script, signers)
+ TransactionManagerFactory factory = new TransactionManagerFactory(rpcClient, magic);
+ TransactionManager manager = await factory.MakeTransactionAsync(script, signers).ConfigureAwait(false);
+ return await manager
.AddSignature(key)
- .Sign()
- .Tx;
-
- return tx;
+ .SignAsync().ConfigureAwait(false);
}
}
}
diff --git a/src/RpcClient/Models/RpcVersion.cs b/src/RpcClient/Models/RpcVersion.cs
index c66015218..34ca163dd 100644
--- a/src/RpcClient/Models/RpcVersion.cs
+++ b/src/RpcClient/Models/RpcVersion.cs
@@ -4,6 +4,8 @@ namespace Neo.Network.RPC.Models
{
public class RpcVersion
{
+ public uint Magic { get; set; }
+
public int TcpPort { get; set; }
public int WsPort { get; set; }
@@ -12,9 +14,11 @@ public class RpcVersion
public string UserAgent { get; set; }
+
public JObject ToJson()
{
JObject json = new JObject();
+ json["magic"] = Magic;
json["tcpport"] = TcpPort;
json["wsport"] = WsPort;
json["nonce"] = Nonce;
@@ -25,6 +29,7 @@ public JObject ToJson()
public static RpcVersion FromJson(JObject json)
{
RpcVersion version = new RpcVersion();
+ version.Magic = (uint)json["magic"].AsNumber();
version.TcpPort = (int)json["tcpport"].AsNumber();
version.WsPort = (int)json["wsport"].AsNumber();
version.Nonce = (uint)json["nonce"].AsNumber();
diff --git a/src/RpcClient/Nep5API.cs b/src/RpcClient/Nep5API.cs
index c700d5c68..59cadd67e 100644
--- a/src/RpcClient/Nep5API.cs
+++ b/src/RpcClient/Nep5API.cs
@@ -7,6 +7,7 @@
using System;
using System.Linq;
using System.Numerics;
+using System.Threading.Tasks;
using static Neo.Helper;
namespace Neo.Network.RPC
@@ -28,9 +29,10 @@ public Nep5API(RpcClient rpcClient) : base(rpcClient) { }
/// contract script hash
/// account script hash
///
- public BigInteger BalanceOf(UInt160 scriptHash, UInt160 account)
+ public async Task BalanceOfAsync(UInt160 scriptHash, UInt160 account)
{
- BigInteger balance = TestInvoke(scriptHash, "balanceOf", account).Stack.Single().GetInteger();
+ var result = await TestInvokeAsync(scriptHash, "balanceOf", account).ConfigureAwait(false);
+ BigInteger balance = result.Stack.Single().GetInteger();
return balance;
}
@@ -39,9 +41,10 @@ public BigInteger BalanceOf(UInt160 scriptHash, UInt160 account)
///
/// contract script hash
///
- public string Name(UInt160 scriptHash)
+ public async Task NameAsync(UInt160 scriptHash)
{
- return TestInvoke(scriptHash, "name").Stack.Single().GetString();
+ var result = await TestInvokeAsync(scriptHash, "name").ConfigureAwait(false);
+ return result.Stack.Single().GetString();
}
///
@@ -49,9 +52,10 @@ public string Name(UInt160 scriptHash)
///
/// contract script hash
///
- public string Symbol(UInt160 scriptHash)
+ public async Task SymbolAsync(UInt160 scriptHash)
{
- return TestInvoke(scriptHash, "symbol").Stack.Single().GetString();
+ var result = await TestInvokeAsync(scriptHash, "symbol").ConfigureAwait(false);
+ return result.Stack.Single().GetString();
}
///
@@ -59,9 +63,10 @@ public string Symbol(UInt160 scriptHash)
///
/// contract script hash
///
- public byte Decimals(UInt160 scriptHash)
+ public async Task DecimalsAsync(UInt160 scriptHash)
{
- return (byte)TestInvoke(scriptHash, "decimals").Stack.Single().GetInteger();
+ var result = await TestInvokeAsync(scriptHash, "decimals").ConfigureAwait(false);
+ return (byte)result.Stack.Single().GetInteger();
}
///
@@ -69,9 +74,10 @@ public byte Decimals(UInt160 scriptHash)
///
/// contract script hash
///
- public BigInteger TotalSupply(UInt160 scriptHash)
+ public async Task TotalSupplyAsync(UInt160 scriptHash)
{
- return TestInvoke(scriptHash, "totalSupply").Stack.Single().GetInteger();
+ var result = await TestInvokeAsync(scriptHash, "totalSupply").ConfigureAwait(false);
+ return result.Stack.Single().GetInteger();
}
///
@@ -79,21 +85,23 @@ public BigInteger TotalSupply(UInt160 scriptHash)
///
/// contract script hash
///
- public RpcNep5TokenInfo GetTokenInfo(UInt160 scriptHash)
+ public async Task GetTokenInfoAsync(UInt160 scriptHash)
{
- byte[] script = Concat(scriptHash.MakeScript("name"),
+ byte[] script = Concat(
+ scriptHash.MakeScript("name"),
scriptHash.MakeScript("symbol"),
scriptHash.MakeScript("decimals"),
scriptHash.MakeScript("totalSupply"));
- var result = rpcClient.InvokeScript(script).Stack;
+ var result = await rpcClient.InvokeScriptAsync(script).ConfigureAwait(false);
+ var stack = result.Stack;
return new RpcNep5TokenInfo
{
- Name = result[0].GetString(),
- Symbol = result[1].GetString(),
- Decimals = (byte)result[2].GetInteger(),
- TotalSupply = result[3].GetInteger()
+ Name = stack[0].GetString(),
+ Symbol = stack[1].GetString(),
+ Decimals = (byte)stack[2].GetInteger(),
+ TotalSupply = stack[3].GetInteger()
};
}
@@ -105,19 +113,18 @@ public RpcNep5TokenInfo GetTokenInfo(UInt160 scriptHash)
/// to account script hash
/// transfer amount
///
- public Transaction CreateTransferTx(UInt160 scriptHash, KeyPair fromKey, UInt160 to, BigInteger amount)
+ public async Task CreateTransferTxAsync(UInt160 scriptHash, KeyPair fromKey, UInt160 to, BigInteger amount)
{
var sender = Contract.CreateSignatureRedeemScript(fromKey.PublicKey).ToScriptHash();
Signer[] signers = new[] { new Signer { Scopes = WitnessScope.CalledByEntry, Account = sender } };
byte[] script = scriptHash.MakeScript("transfer", sender, to, amount);
- Transaction tx = new TransactionManager(rpcClient)
- .MakeTransaction(script, signers)
- .AddSignature(fromKey)
- .Sign()
- .Tx;
- return tx;
+ TransactionManagerFactory factory = new TransactionManagerFactory(rpcClient, magic);
+ TransactionManager manager = await factory.MakeTransactionAsync(script, signers).ConfigureAwait(false);
+ return await manager
+ .AddSignature(fromKey)
+ .SignAsync().ConfigureAwait(false);
}
///
@@ -130,7 +137,7 @@ public Transaction CreateTransferTx(UInt160 scriptHash, KeyPair fromKey, UInt160
/// to account
/// transfer amount
///
- public Transaction CreateTransferTx(UInt160 scriptHash, int m, ECPoint[] pubKeys, KeyPair[] fromKeys, UInt160 to, BigInteger amount)
+ public async Task CreateTransferTxAsync(UInt160 scriptHash, int m, ECPoint[] pubKeys, KeyPair[] fromKeys, UInt160 to, BigInteger amount)
{
if (m > fromKeys.Length)
throw new ArgumentException($"Need at least {m} KeyPairs for signing!");
@@ -138,13 +145,12 @@ public Transaction CreateTransferTx(UInt160 scriptHash, int m, ECPoint[] pubKeys
Signer[] signers = new[] { new Signer { Scopes = WitnessScope.CalledByEntry, Account = sender } };
byte[] script = scriptHash.MakeScript("transfer", sender, to, amount);
- Transaction tx = new TransactionManager(rpcClient)
- .MakeTransaction(script, signers)
- .AddMultiSig(fromKeys, m, pubKeys)
- .Sign()
- .Tx;
- return tx;
+ TransactionManagerFactory factory = new TransactionManagerFactory(rpcClient, magic);
+ TransactionManager manager = await factory.MakeTransactionAsync(script, signers).ConfigureAwait(false);
+ return await manager
+ .AddMultiSig(fromKeys, m, pubKeys)
+ .SignAsync().ConfigureAwait(false);
}
}
}
diff --git a/src/RpcClient/PolicyAPI.cs b/src/RpcClient/PolicyAPI.cs
index 073b105b3..540f945da 100644
--- a/src/RpcClient/PolicyAPI.cs
+++ b/src/RpcClient/PolicyAPI.cs
@@ -1,6 +1,7 @@
using Neo.SmartContract.Native;
using Neo.VM;
using System.Linq;
+using System.Threading.Tasks;
namespace Neo.Network.RPC
{
@@ -21,37 +22,41 @@ public PolicyAPI(RpcClient rpcClient) : base(rpcClient) { }
/// Get Max Transactions Count Per Block
///
///
- public uint GetMaxTransactionsPerBlock()
+ public async Task GetMaxTransactionsPerBlockAsync()
{
- return (uint)TestInvoke(scriptHash, "getMaxTransactionsPerBlock").Stack.Single().GetInteger();
+ var result = await TestInvokeAsync(scriptHash, "getMaxTransactionsPerBlock").ConfigureAwait(false);
+ return (uint)result.Stack.Single().GetInteger();
}
///
/// Get Max Block Size
///
///
- public uint GetMaxBlockSize()
+ public async Task GetMaxBlockSizeAsync()
{
- return (uint)TestInvoke(scriptHash, "getMaxBlockSize").Stack.Single().GetInteger();
+ var result = await TestInvokeAsync(scriptHash, "getMaxBlockSize").ConfigureAwait(false);
+ return (uint)result.Stack.Single().GetInteger();
}
///
/// Get Network Fee Per Byte
///
///
- public long GetFeePerByte()
+ public async Task GetFeePerByteAsync()
{
- return (long)TestInvoke(scriptHash, "getFeePerByte").Stack.Single().GetInteger();
+ var result = await TestInvokeAsync(scriptHash, "getFeePerByte").ConfigureAwait(false);
+ return (long)result.Stack.Single().GetInteger();
}
///
/// Get Ploicy Blocked Accounts
///
///
- public UInt160[] GetBlockedAccounts()
+ public async Task GetBlockedAccountsAsync()
{
- var result = (VM.Types.Array)TestInvoke(scriptHash, "getBlockedAccounts").Stack.Single();
- return result.Select(p => new UInt160(p.GetSpan().ToArray())).ToArray();
+ var result = await TestInvokeAsync(scriptHash, "getBlockedAccounts").ConfigureAwait(false);
+ var array = (VM.Types.Array)result.Stack.Single();
+ return array.Select(p => new UInt160(p.GetSpan().ToArray())).ToArray();
}
}
}
diff --git a/src/RpcClient/RpcClient.cs b/src/RpcClient/RpcClient.cs
index d6f3411c7..6d81f9b86 100644
--- a/src/RpcClient/RpcClient.cs
+++ b/src/RpcClient/RpcClient.cs
@@ -20,11 +20,13 @@ namespace Neo.Network.RPC
///
public class RpcClient : IDisposable
{
- private HttpClient httpClient;
+ private readonly HttpClient httpClient;
+ private readonly string baseAddress;
public RpcClient(string url, string rpcUser = default, string rpcPass = default)
{
- httpClient = new HttpClient() { BaseAddress = new Uri(url) };
+ httpClient = new HttpClient();
+ baseAddress = url;
if (!string.IsNullOrEmpty(rpcUser) && !string.IsNullOrEmpty(rpcPass))
{
string token = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{rpcUser}:{rpcPass}"));
@@ -32,9 +34,10 @@ public RpcClient(string url, string rpcUser = default, string rpcPass = default)
}
}
- public RpcClient(HttpClient client)
+ public RpcClient(HttpClient client, string url)
{
httpClient = client;
+ baseAddress = url;
}
#region IDisposable Support
@@ -46,10 +49,9 @@ protected virtual void Dispose(bool disposing)
{
if (disposing)
{
- httpClient?.Dispose();
+ httpClient.Dispose();
}
- httpClient = null;
disposedValue = true;
}
}
@@ -62,8 +64,10 @@ public void Dispose()
public async Task SendAsync(RpcRequest request)
{
+ if (disposedValue) throw new ObjectDisposedException(nameof(RpcClient));
+
var requestJson = request.ToJson().ToString();
- using var result = await httpClient.PostAsync(httpClient.BaseAddress, new StringContent(requestJson, Encoding.UTF8));
+ using var result = await httpClient.PostAsync(baseAddress, new StringContent(requestJson, Encoding.UTF8)).ConfigureAwait(false);
var content = await result.Content.ReadAsStringAsync();
var response = RpcResponse.FromJson(JObject.Parse(content));
response.RawResponse = content;
@@ -76,19 +80,7 @@ public async Task SendAsync(RpcRequest request)
return response;
}
- public RpcResponse Send(RpcRequest request)
- {
- try
- {
- return SendAsync(request).Result;
- }
- catch (AggregateException ex)
- {
- throw ex.GetBaseException();
- }
- }
-
- public virtual JObject RpcSend(string method, params JObject[] paraArgs)
+ public virtual async Task RpcSendAsync(string method, params JObject[] paraArgs)
{
var request = new RpcRequest
{
@@ -97,7 +89,9 @@ public virtual JObject RpcSend(string method, params JObject[] paraArgs)
Method = method,
Params = paraArgs
};
- return Send(request).Result;
+
+ var response = await SendAsync(request).ConfigureAwait(false);
+ return response.Result;
}
#region Blockchain
@@ -105,82 +99,84 @@ public virtual JObject RpcSend(string method, params JObject[] paraArgs)
///
/// Returns the hash of the tallest block in the main chain.
///
- public string GetBestBlockHash()
+ public async Task GetBestBlockHashAsync()
{
- return RpcSend("getbestblockhash").AsString();
+ var result = await RpcSendAsync("getbestblockhash").ConfigureAwait(false);
+ return result.AsString();
}
///
/// Returns the hash of the tallest block in the main chain.
/// The serialized information of the block is returned, represented by a hexadecimal string.
///
- public string GetBlockHex(string hashOrIndex)
+ public async Task GetBlockHexAsync(string hashOrIndex)
{
- if (int.TryParse(hashOrIndex, out int index))
- {
- return RpcSend("getblock", index).AsString();
- }
- return RpcSend("getblock", hashOrIndex).AsString();
+ var result = int.TryParse(hashOrIndex, out int index)
+ ? await RpcSendAsync("getblock", index).ConfigureAwait(false)
+ : await RpcSendAsync("getblock", hashOrIndex).ConfigureAwait(false);
+ return result.AsString();
}
///
/// Returns the hash of the tallest block in the main chain.
///
- public RpcBlock GetBlock(string hashOrIndex)
+ public async Task GetBlockAsync(string hashOrIndex)
{
- if (int.TryParse(hashOrIndex, out int index))
- {
- return RpcBlock.FromJson(RpcSend("getblock", index, true));
- }
- return RpcBlock.FromJson(RpcSend("getblock", hashOrIndex, true));
+ var result = int.TryParse(hashOrIndex, out int index)
+ ? await RpcSendAsync("getblock", index, true).ConfigureAwait(false)
+ : await RpcSendAsync("getblock", hashOrIndex, true).ConfigureAwait(false);
+
+ return RpcBlock.FromJson(result);
}
///
/// Gets the number of blocks in the main chain.
///
- public uint GetBlockCount()
+ public async Task GetBlockCountAsync()
{
- return (uint)RpcSend("getblockcount").AsNumber();
+ var result = await RpcSendAsync("getblockcount").ConfigureAwait(false);
+ return (uint)result.AsNumber();
}
///
/// Returns the hash value of the corresponding block, based on the specified index.
///
- public string GetBlockHash(int index)
+ public async Task GetBlockHashAsync(int index)
{
- return RpcSend("getblockhash", index).AsString();
+ var result = await RpcSendAsync("getblockhash", index).ConfigureAwait(false);
+ return result.AsString();
}
///
/// Returns the corresponding block header information according to the specified script hash.
///
- public string GetBlockHeaderHex(string hashOrIndex)
+ public async Task GetBlockHeaderHexAsync(string hashOrIndex)
{
- if (int.TryParse(hashOrIndex, out int index))
- {
- return RpcSend("getblockheader", index).AsString();
- }
- return RpcSend("getblockheader", hashOrIndex).AsString();
+ var result = int.TryParse(hashOrIndex, out int index)
+ ? await RpcSendAsync("getblockheader", index).ConfigureAwait(false)
+ : await RpcSendAsync("getblockheader", hashOrIndex).ConfigureAwait(false);
+ return result.AsString();
}
///
/// Returns the corresponding block header information according to the specified script hash.
///
- public RpcBlockHeader GetBlockHeader(string hashOrIndex)
+ public async Task GetBlockHeaderAsync(string hashOrIndex)
{
- if (int.TryParse(hashOrIndex, out int index))
- {
- return RpcBlockHeader.FromJson(RpcSend("getblockheader", index, true));
- }
- return RpcBlockHeader.FromJson(RpcSend("getblockheader", hashOrIndex, true));
+ var result = int.TryParse(hashOrIndex, out int index)
+ ? await RpcSendAsync("getblockheader", index, true).ConfigureAwait(false)
+ : await RpcSendAsync("getblockheader", hashOrIndex, true).ConfigureAwait(false);
+
+ return RpcBlockHeader.FromJson(result);
}
///
/// Queries contract information, according to the contract script hash.
///
- public ContractState GetContractState(string hash)
+ public async Task GetContractStateAsync(string hash)
{
- return ContractStateFromJson(RpcSend("getcontractstate", hash));
+ var result = await RpcSendAsync("getcontractstate", hash).ConfigureAwait(false);
+ return ContractStateFromJson(result);
}
public static ContractState ContractStateFromJson(JObject json)
@@ -196,35 +192,39 @@ public static ContractState ContractStateFromJson(JObject json)
///
/// Obtains the list of unconfirmed transactions in memory.
///
- public string[] GetRawMempool()
+ public async Task GetRawMempoolAsync()
{
- return ((JArray)RpcSend("getrawmempool")).Select(p => p.AsString()).ToArray();
+ var result = await RpcSendAsync("getrawmempool").ConfigureAwait(false);
+ return ((JArray)result).Select(p => p.AsString()).ToArray();
}
///
/// Obtains the list of unconfirmed transactions in memory.
/// shouldGetUnverified = true
///
- public RpcRawMemPool GetRawMempoolBoth()
+ public async Task GetRawMempoolBothAsync()
{
- return RpcRawMemPool.FromJson(RpcSend("getrawmempool", true));
+ var result = await RpcSendAsync("getrawmempool", true).ConfigureAwait(false);
+ return RpcRawMemPool.FromJson(result);
}
///
/// Returns the corresponding transaction information, based on the specified hash value.
///
- public string GetRawTransactionHex(string txHash)
+ public async Task GetRawTransactionHexAsync(string txHash)
{
- return RpcSend("getrawtransaction", txHash).AsString();
+ var result = await RpcSendAsync("getrawtransaction", txHash).ConfigureAwait(false);
+ return result.AsString();
}
///
/// Returns the corresponding transaction information, based on the specified hash value.
/// verbose = true
///
- public RpcTransaction GetRawTransaction(string txHash)
+ public async Task GetRawTransactionAsync(string txHash)
{
- return RpcTransaction.FromJson(RpcSend("getrawtransaction", txHash, true));
+ var result = await RpcSendAsync("getrawtransaction", txHash, true).ConfigureAwait(false);
+ return RpcTransaction.FromJson(result);
}
///
@@ -232,47 +232,49 @@ public RpcTransaction GetRawTransaction(string txHash)
///
/// Transaction
/// NetworkFee
- public long CalculateNetworkFee(Transaction tx)
+ public async Task CalculateNetworkFeeAsync(Transaction tx)
{
- var json = RpcSend("calculatenetworkfee", Convert.ToBase64String(tx.ToArray()));
+ var json = await RpcSendAsync("calculatenetworkfee", Convert.ToBase64String(tx.ToArray()))
+ .ConfigureAwait(false);
return (long)json["networkfee"].AsNumber();
}
///
/// Returns the stored value, according to the contract script hash (or Id) and the stored key.
///
- public string GetStorage(string scriptHashOrId, string key)
+ public async Task GetStorageAsync(string scriptHashOrId, string key)
{
- if (int.TryParse(scriptHashOrId, out int id))
- {
- return RpcSend("getstorage", id, key).AsString();
- }
-
- return RpcSend("getstorage", scriptHashOrId, key).AsString();
+ var result = int.TryParse(scriptHashOrId, out int id)
+ ? await RpcSendAsync("getstorage", id, key).ConfigureAwait(false)
+ : await RpcSendAsync("getstorage", scriptHashOrId, key).ConfigureAwait(false);
+ return result.AsString();
}
///
/// Returns the block index in which the transaction is found.
///
- public uint GetTransactionHeight(string txHash)
+ public async Task GetTransactionHeightAsync(string txHash)
{
- return uint.Parse(RpcSend("gettransactionheight", txHash).AsString());
+ var result = await RpcSendAsync("gettransactionheight", txHash).ConfigureAwait(false);
+ return uint.Parse(result.AsString());
}
///
/// Returns the next NEO consensus nodes information and voting status.
///
- public RpcValidator[] GetNextBlockValidators()
+ public async Task GetNextBlockValidatorsAsync()
{
- return ((JArray)RpcSend("getnextblockvalidators")).Select(p => RpcValidator.FromJson(p)).ToArray();
+ var result = await RpcSendAsync("getnextblockvalidators").ConfigureAwait(false);
+ return ((JArray)result).Select(p => RpcValidator.FromJson(p)).ToArray();
}
///
/// Returns the current NEO committee members.
///
- public string[] GetCommittee()
+ public async Task GetCommitteeAsync()
{
- return ((JArray)RpcSend("getcommittee")).Select(p => p.AsString()).ToArray();
+ var result = await RpcSendAsync("getcommittee").ConfigureAwait(false);
+ return ((JArray)result).Select(p => p.AsString()).ToArray();
}
#endregion Blockchain
@@ -282,49 +284,54 @@ public string[] GetCommittee()
///
/// Gets the current number of connections for the node.
///
- public int GetConnectionCount()
+ public async Task GetConnectionCountAsync()
{
- return (int)RpcSend("getconnectioncount").AsNumber();
+ var result = await RpcSendAsync("getconnectioncount").ConfigureAwait(false);
+ return (int)result.AsNumber();
}
///
/// Gets the list of nodes that the node is currently connected/disconnected from.
///
- public RpcPeers GetPeers()
+ public async Task GetPeersAsync()
{
- return RpcPeers.FromJson(RpcSend("getpeers"));
+ var result = await RpcSendAsync("getpeers").ConfigureAwait(false);
+ return RpcPeers.FromJson(result);
}
///
/// Returns the version information about the queried node.
///
- public RpcVersion GetVersion()
+ public async Task GetVersionAsync()
{
- return RpcVersion.FromJson(RpcSend("getversion"));
+ var result = await RpcSendAsync("getversion").ConfigureAwait(false);
+ return RpcVersion.FromJson(result);
}
///
/// Broadcasts a serialized transaction over the NEO network.
///
- public UInt256 SendRawTransaction(byte[] rawTransaction)
+ public async Task SendRawTransactionAsync(byte[] rawTransaction)
{
- return UInt256.Parse(RpcSend("sendrawtransaction", rawTransaction.ToHexString())["hash"].AsString());
+ var result = await RpcSendAsync("sendrawtransaction", rawTransaction.ToHexString()).ConfigureAwait(false);
+ return UInt256.Parse(result["hash"].AsString());
}
///
/// Broadcasts a transaction over the NEO network.
///
- public UInt256 SendRawTransaction(Transaction transaction)
+ public Task SendRawTransactionAsync(Transaction transaction)
{
- return SendRawTransaction(transaction.ToArray());
+ return SendRawTransactionAsync(transaction.ToArray());
}
///
/// Broadcasts a serialized block over the NEO network.
///
- public UInt256 SubmitBlock(byte[] block)
+ public async Task SubmitBlockAsync(byte[] block)
{
- return UInt256.Parse(RpcSend("submitblock", block.ToHexString())["hash"].AsString());
+ var result = await RpcSendAsync("submitblock", block.ToHexString()).ConfigureAwait(false);
+ return UInt256.Parse(result["hash"].AsString());
}
#endregion Node
@@ -335,33 +342,36 @@ public UInt256 SubmitBlock(byte[] block)
/// Returns the result after calling a smart contract at scripthash with the given operation and parameters.
/// This RPC call does not affect the blockchain in any way.
///
- public RpcInvokeResult InvokeFunction(string scriptHash, string operation, RpcStack[] stacks, params Signer[] signer)
+ public async Task InvokeFunctionAsync(string scriptHash, string operation, RpcStack[] stacks, params Signer[] signer)
{
List parameters = new List { scriptHash.AsScriptHash(), operation, stacks.Select(p => p.ToJson()).ToArray() };
if (signer.Length > 0)
{
parameters.Add(signer.Select(p => (JObject)p.ToJson()).ToArray());
}
- return RpcInvokeResult.FromJson(RpcSend("invokefunction", parameters.ToArray()));
+ var result = await RpcSendAsync("invokefunction", parameters.ToArray()).ConfigureAwait(false);
+ return RpcInvokeResult.FromJson(result);
}
///
/// Returns the result after passing a script through the VM.
/// This RPC call does not affect the blockchain in any way.
///
- public RpcInvokeResult InvokeScript(byte[] script, params Signer[] signers)
+ public async Task InvokeScriptAsync(byte[] script, params Signer[] signers)
{
List parameters = new List { script.ToHexString() };
if (signers.Length > 0)
{
parameters.Add(signers.Select(p => p.ToJson()).ToArray());
}
- return RpcInvokeResult.FromJson(RpcSend("invokescript", parameters.ToArray()));
+ var result = await RpcSendAsync("invokescript", parameters.ToArray()).ConfigureAwait(false);
+ return RpcInvokeResult.FromJson(result);
}
- public RpcUnclaimedGas GetUnclaimedGas(string address)
+ public async Task GetUnclaimedGasAsync(string address)
{
- return RpcUnclaimedGas.FromJson(RpcSend("getunclaimedgas", address.AsScriptHash()));
+ var result = await RpcSendAsync("getunclaimedgas", address.AsScriptHash()).ConfigureAwait(false);
+ return RpcUnclaimedGas.FromJson(result);
}
#endregion SmartContract
@@ -371,17 +381,19 @@ public RpcUnclaimedGas GetUnclaimedGas(string address)
///
/// Returns a list of plugins loaded by the node.
///
- public RpcPlugin[] ListPlugins()
+ public async Task ListPluginsAsync()
{
- return ((JArray)RpcSend("listplugins")).Select(p => RpcPlugin.FromJson(p)).ToArray();
+ var result = await RpcSendAsync("listplugins").ConfigureAwait(false);
+ return ((JArray)result).Select(p => RpcPlugin.FromJson(p)).ToArray();
}
///
/// Verifies that the address is a correct NEO address.
///
- public RpcValidateAddressResult ValidateAddress(string address)
+ public async Task ValidateAddressAsync(string address)
{
- return RpcValidateAddressResult.FromJson(RpcSend("validateaddress", address));
+ var result = await RpcSendAsync("validateaddress", address).ConfigureAwait(false);
+ return RpcValidateAddressResult.FromJson(result);
}
#endregion Utilities
@@ -391,25 +403,28 @@ public RpcValidateAddressResult ValidateAddress(string address)
///
/// Close the wallet opened by RPC.
///
- public bool CloseWallet()
+ public async Task CloseWalletAsync()
{
- return RpcSend("closewallet").AsBoolean();
+ var result = await RpcSendAsync("closewallet").ConfigureAwait(false);
+ return result.AsBoolean();
}
///
/// Exports the private key of the specified address.
///
- public string DumpPrivKey(string address)
+ public async Task DumpPrivKeyAsync(string address)
{
- return RpcSend("dumpprivkey", address).AsString();
+ var result = await RpcSendAsync("dumpprivkey", address).ConfigureAwait(false);
+ return result.AsString();
}
///
/// Creates a new account in the wallet opened by RPC.
///
- public string GetNewAddress()
+ public async Task GetNewAddressAsync()
{
- return RpcSend("getnewaddress").AsString();
+ var result = await RpcSendAsync("getnewaddress").ConfigureAwait(false);
+ return result.AsString();
}
///
@@ -417,60 +432,66 @@ public string GetNewAddress()
/// This method applies to assets that conform to NEP-5 standards.
///
/// new address as string
- public BigDecimal GetWalletBalance(string assetId)
+ public async Task GetWalletBalanceAsync(string assetId)
{
- byte decimals = new Nep5API(this).Decimals(UInt160.Parse(assetId.AsScriptHash()));
- BigInteger balance = BigInteger.Parse(RpcSend("getwalletbalance", assetId)["balance"].AsString());
+ byte decimals = await new Nep5API(this).DecimalsAsync(UInt160.Parse(assetId.AsScriptHash())).ConfigureAwait(false);
+ var result = await RpcSendAsync("getwalletbalance", assetId).ConfigureAwait(false);
+ BigInteger balance = BigInteger.Parse(result["balance"].AsString());
return new BigDecimal(balance, decimals);
}
///
/// Gets the amount of unclaimed GAS in the wallet.
///
- public BigInteger GetWalletUnclaimedGas()
+ public async Task GetWalletUnclaimedGasAsync()
{
- return BigInteger.Parse(RpcSend("getwalletunclaimedgas").AsString());
+ var result = await RpcSendAsync("getwalletunclaimedgas").ConfigureAwait(false);
+ return BigInteger.Parse(result.AsString());
}
///
/// Imports the private key to the wallet.
///
- public RpcAccount ImportPrivKey(string wif)
+ public async Task ImportPrivKeyAsync(string wif)
{
- return RpcAccount.FromJson(RpcSend("importprivkey", wif));
+ var result = await RpcSendAsync("importprivkey", wif).ConfigureAwait(false);
+ return RpcAccount.FromJson(result);
}
///
/// Lists all the accounts in the current wallet.
///
- public List ListAddress()
+ public async Task> ListAddressAsync()
{
- return ((JArray)RpcSend("listaddress")).Select(p => RpcAccount.FromJson(p)).ToList();
+ var result = await RpcSendAsync("listaddress").ConfigureAwait(false);
+ return ((JArray)result).Select(p => RpcAccount.FromJson(p)).ToList();
}
///
/// Open wallet file in the provider's machine.
/// By default, this method is disabled by RpcServer config.json.
///
- public bool OpenWallet(string path, string password)
+ public async Task OpenWalletAsync(string path, string password)
{
- return RpcSend("openwallet", path, password).AsBoolean();
+ var result = await RpcSendAsync("openwallet", path, password).ConfigureAwait(false);
+ return result.AsBoolean();
}
///
/// Transfer from the specified address to the destination address.
///
/// This function returns Signed Transaction JSON if successful, ContractParametersContext JSON if signing failed.
- public JObject SendFrom(string assetId, string fromAddress, string toAddress, string amount)
+ public async Task SendFromAsync(string assetId, string fromAddress, string toAddress, string amount)
{
- return RpcSend("sendfrom", assetId.AsScriptHash(), fromAddress.AsScriptHash(), toAddress.AsScriptHash(), amount);
+ return await RpcSendAsync("sendfrom", assetId.AsScriptHash(), fromAddress.AsScriptHash(),
+ toAddress.AsScriptHash(), amount).ConfigureAwait(false);
}
///
/// Bulk transfer order, and you can specify a sender address.
///
/// This function returns Signed Transaction JSON if successful, ContractParametersContext JSON if signing failed.
- public JObject SendMany(string fromAddress, IEnumerable outputs)
+ public async Task SendManyAsync(string fromAddress, IEnumerable outputs)
{
var parameters = new List();
if (!string.IsNullOrEmpty(fromAddress))
@@ -479,16 +500,17 @@ public JObject SendMany(string fromAddress, IEnumerable outputs)
}
parameters.Add(outputs.Select(p => p.ToJson()).ToArray());
- return RpcSend("sendmany", paraArgs: parameters.ToArray());
+ return await RpcSendAsync("sendmany", paraArgs: parameters.ToArray()).ConfigureAwait(false);
}
///
/// Transfer asset from the wallet to the destination address.
///
/// This function returns Signed Transaction JSON if successful, ContractParametersContext JSON if signing failed.
- public JObject SendToAddress(string assetId, string address, string amount)
+ public async Task SendToAddressAsync(string assetId, string address, string amount)
{
- return RpcSend("sendtoaddress", assetId.AsScriptHash(), address.AsScriptHash(), amount);
+ return await RpcSendAsync("sendtoaddress", assetId.AsScriptHash(), address.AsScriptHash(), amount)
+ .ConfigureAwait(false);
}
#endregion Wallet
@@ -499,9 +521,10 @@ public JObject SendToAddress(string assetId, string address, string amount)
/// Returns the contract log based on the specified txHash. The complete contract logs are stored under the ApplicationLogs directory.
/// This method is provided by the plugin ApplicationLogs.
///
- public RpcApplicationLog GetApplicationLog(string txHash)
+ public async Task GetApplicationLogAsync(string txHash)
{
- return RpcApplicationLog.FromJson(RpcSend("getapplicationlog", txHash));
+ var result = await RpcSendAsync("getapplicationlog", txHash).ConfigureAwait(false);
+ return RpcApplicationLog.FromJson(result);
}
///
@@ -511,20 +534,24 @@ public RpcApplicationLog GetApplicationLog(string txHash)
/// The address to query the transaction information.
/// The start block Timestamp, default to seven days before UtcNow
/// The end block Timestamp, default to UtcNow
- public RpcNep5Transfers GetNep5Transfers(string address, ulong? startTimestamp = default, ulong? endTimestamp = default)
+ public async Task GetNep5TransfersAsync(string address, ulong? startTimestamp = default, ulong? endTimestamp = default)
{
startTimestamp ??= 0;
endTimestamp ??= DateTime.UtcNow.ToTimestampMS();
- return RpcNep5Transfers.FromJson(RpcSend("getnep5transfers", address.AsScriptHash(), startTimestamp, endTimestamp));
+ var result = await RpcSendAsync("getnep5transfers", address.AsScriptHash(), startTimestamp, endTimestamp)
+ .ConfigureAwait(false);
+ return RpcNep5Transfers.FromJson(result);
}
///
/// Returns the balance of all NEP-5 assets in the specified address.
/// This method is provided by the plugin RpcNep5Tracker.
///
- public RpcNep5Balances GetNep5Balances(string address)
+ public async Task GetNep5BalancesAsync(string address)
{
- return RpcNep5Balances.FromJson(RpcSend("getnep5balances", address.AsScriptHash()));
+ var result = await RpcSendAsync("getnep5balances", address.AsScriptHash())
+ .ConfigureAwait(false);
+ return RpcNep5Balances.FromJson(result);
}
#endregion Plugins
diff --git a/src/RpcClient/TransactionManager.cs b/src/RpcClient/TransactionManager.cs
index ac38818de..7e35e25f0 100644
--- a/src/RpcClient/TransactionManager.cs
+++ b/src/RpcClient/TransactionManager.cs
@@ -1,12 +1,13 @@
using Neo.Cryptography.ECC;
+using Neo.IO;
using Neo.Network.P2P.Payloads;
-using Neo.Network.RPC.Models;
using Neo.SmartContract;
using Neo.SmartContract.Native;
using Neo.Wallets;
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Threading.Tasks;
namespace Neo.Network.RPC
{
@@ -15,65 +16,56 @@ namespace Neo.Network.RPC
///
public class TransactionManager
{
+ private class SignItem { public Contract Contract; public HashSet KeyPairs; }
+
private readonly RpcClient rpcClient;
- private readonly PolicyAPI policyAPI;
- private readonly Nep5API nep5API;
- private class SignItem { public Contract Contract; public HashSet KeyPairs; }
+ ///
+ /// protocol settings Magic value to use for hashing transactions.
+ ///
+ private readonly uint magic;
///
/// The Transaction context to manage the witnesses
///
- private ContractParametersContext context;
+ private readonly ContractParametersContext context;
///
/// This container stores the keys for sign the transaction
///
- private List signStore;
+ private readonly List signStore = new List();
///
- /// The Transaction managed by this class
+ /// The Transaction managed by this instance
///
- public Transaction Tx { get; private set; }
+ private readonly Transaction tx;
+
+ public Transaction Tx => tx;
///
/// TransactionManager Constructor
///
- /// the RPC client to call NEO RPC API
- /// the account script hash of sender
- public TransactionManager(RpcClient rpc)
+ /// the transaction to manage. Typically buildt
+ /// the RPC client to call NEO RPC API
+ ///
+ /// the network Magic value to use when signing transactions.
+ /// Defaults to ProtocolSettings.Default.Magic if not specified.
+ ///
+ public TransactionManager(Transaction tx, RpcClient rpcClient, uint magic)
{
- rpcClient = rpc;
- policyAPI = new PolicyAPI(rpc);
- nep5API = new Nep5API(rpc);
+ this.tx = tx;
+ this.context = new ContractParametersContext(tx);
+ this.rpcClient = rpcClient;
+ this.magic = magic;
}
///
- /// Create an unsigned Transaction object with given parameters.
+ /// Helper function for one-off TransactionManager creation
///
- /// Transaction Script
- /// Transaction Attributes
- ///
- public TransactionManager MakeTransaction(byte[] script, Signer[] signers = null, TransactionAttribute[] attributes = null)
+ public static Task MakeTransactionAsync(RpcClient rpcClient, byte[] script, Signer[] signers = null, TransactionAttribute[] attributes = null, uint? magic = null)
{
- var random = new Random();
- uint height = rpcClient.GetBlockCount() - 1;
- Tx = new Transaction
- {
- Version = 0,
- Nonce = (uint)random.Next(),
- Script = script,
- Signers = signers,
- ValidUntilBlock = height + Transaction.MaxValidUntilBlockIncrement,
- Attributes = attributes ?? Array.Empty(),
- };
-
- RpcInvokeResult result = rpcClient.InvokeScript(script, signers);
- Tx.SystemFee = long.Parse(result.GasConsumed);
- context = new ContractParametersContext(Tx);
- signStore = new List();
-
- return this;
+ var factory = new TransactionManagerFactory(rpcClient, magic);
+ return factory.MakeTransactionAsync(script, signers, attributes);
}
///
@@ -109,9 +101,10 @@ public TransactionManager AddMultiSig(KeyPair key, int m, params ECPoint[] publi
/// The Public Keys construct the multiple signature contract
public TransactionManager AddMultiSig(KeyPair[] keys, int m, params ECPoint[] publicKeys)
{
- foreach (var key in keys)
+ Contract contract = Contract.CreateMultiSigContract(m, publicKeys);
+ for (int i = 0; i < keys.Length; i++)
{
- AddMultiSig(key, m, publicKeys);
+ AddSignItem(contract, keys[i]);
}
return this;
}
@@ -162,7 +155,7 @@ public TransactionManager AddWitness(UInt160 scriptHash, params object[] paramet
///
/// Verify Witness count and add witnesses
///
- public TransactionManager Sign()
+ public async Task SignAsync()
{
// Calculate NetworkFee
Tx.Witnesses = Tx.GetScriptHashesForVerifying(null).Select(u => new Witness()
@@ -170,23 +163,25 @@ public TransactionManager Sign()
InvocationScript = Array.Empty(),
VerificationScript = GetVerificationScript(u)
}).ToArray();
- Tx.NetworkFee = rpcClient.CalculateNetworkFee(Tx);
+ Tx.NetworkFee = await rpcClient.CalculateNetworkFeeAsync(Tx).ConfigureAwait(false);
Tx.Witnesses = null;
- var gasBalance = nep5API.BalanceOf(NativeContract.GAS.Hash, Tx.Sender);
+ var gasBalance = await new Nep5API(rpcClient).BalanceOfAsync(NativeContract.GAS.Hash, Tx.Sender).ConfigureAwait(false);
if (gasBalance < Tx.SystemFee + Tx.NetworkFee)
throw new InvalidOperationException($"Insufficient GAS in address: {Tx.Sender.ToAddress()}");
// Sign with signStore
- foreach (var item in signStore)
- foreach (var key in item.KeyPairs)
+ for (int i = 0; i < signStore.Count; i++)
+ {
+ foreach (var key in signStore[i].KeyPairs)
{
- byte[] signature = Tx.Sign(key);
- if (!context.AddSignature(item.Contract, key.PublicKey, signature))
+ byte[] signature = Tx.Sign(key, magic);
+ if (!context.AddSignature(signStore[i].Contract, key.PublicKey, signature))
{
throw new Exception("AddSignature failed!");
}
}
+ }
// Verify witness count
if (!context.Completed)
@@ -194,7 +189,7 @@ public TransactionManager Sign()
throw new Exception($"Please add signature or witness first!");
}
Tx.Witnesses = context.GetWitnesses();
- return this;
+ return Tx;
}
private byte[] GetVerificationScript(UInt160 hash)
diff --git a/src/RpcClient/TransactionManagerFactory.cs b/src/RpcClient/TransactionManagerFactory.cs
new file mode 100644
index 000000000..0f7277a2c
--- /dev/null
+++ b/src/RpcClient/TransactionManagerFactory.cs
@@ -0,0 +1,57 @@
+using Neo.Network.P2P.Payloads;
+using Neo.Network.RPC.Models;
+using System;
+using System.Threading.Tasks;
+
+namespace Neo.Network.RPC
+{
+ public class TransactionManagerFactory
+ {
+ private readonly RpcClient rpcClient;
+
+ ///
+ /// protocol settings Magic value to use for hashing transactions.
+ /// defaults to ProtocolSettings.Default.Magic if unspecified
+ ///
+ private readonly uint magic;
+
+ ///
+ /// TransactionManagerFactory Constructor
+ ///
+ /// the RPC client to call NEO RPC API
+ ///
+ /// the network Magic value to use when signing transactions.
+ /// Defaults to ProtocolSettings.Default.Magic if not specified.
+ ///
+ public TransactionManagerFactory(RpcClient rpcClient, uint? magic = null)
+ {
+ this.rpcClient = rpcClient;
+ this.magic = magic ?? ProtocolSettings.Default.Magic;
+ }
+
+ ///
+ /// Create an unsigned Transaction object with given parameters.
+ ///
+ /// Transaction Script
+ /// Transaction Attributes
+ ///
+ public async Task MakeTransactionAsync(byte[] script, Signer[] signers = null, TransactionAttribute[] attributes = null)
+ {
+ uint blockCount = await rpcClient.GetBlockCountAsync().ConfigureAwait(false) - 1;
+ RpcInvokeResult invokeResult = await rpcClient.InvokeScriptAsync(script, signers).ConfigureAwait(false);
+
+ var tx = new Transaction
+ {
+ Version = 0,
+ Nonce = (uint)new Random().Next(),
+ Script = script,
+ Signers = signers ?? Array.Empty(),
+ ValidUntilBlock = blockCount - 1 + Transaction.MaxValidUntilBlockIncrement,
+ SystemFee = long.Parse(invokeResult.GasConsumed),
+ Attributes = attributes ?? Array.Empty(),
+ };
+
+ return new TransactionManager(tx, rpcClient, magic);
+ }
+ }
+}
diff --git a/src/RpcClient/WalletAPI.cs b/src/RpcClient/WalletAPI.cs
index 014aba6ec..b4cef3c55 100644
--- a/src/RpcClient/WalletAPI.cs
+++ b/src/RpcClient/WalletAPI.cs
@@ -37,10 +37,10 @@ public WalletAPI(RpcClient rpc)
/// address, scripthash or public key string
/// Example: address ("Ncm9TEzrp8SSer6Wa3UCSLTRnqzwVhCfuE"), scripthash ("0xb0a31817c80ad5f87b6ed390ecb3f9d312f7ceb8"), public key ("02f9ec1fd0a98796cf75b586772a4ddd41a0af07a1dbdf86a7238f74fb72503575")
///
- public decimal GetUnclaimedGas(string account)
+ public Task GetUnclaimedGasAsync(string account)
{
UInt160 accountHash = Utility.GetScriptHash(account);
- return GetUnclaimedGas(accountHash);
+ return GetUnclaimedGasAsync(accountHash);
}
///
@@ -48,11 +48,12 @@ public decimal GetUnclaimedGas(string account)
///
/// account scripthash
///
- public decimal GetUnclaimedGas(UInt160 account)
+ public async Task GetUnclaimedGasAsync(UInt160 account)
{
UInt160 scriptHash = NativeContract.NEO.Hash;
- BigInteger balance = nep5API.TestInvoke(scriptHash, "unclaimedGas", account, rpcClient.GetBlockCount() - 1)
- .Stack.Single().GetInteger();
+ var blockCount = await rpcClient.GetBlockCountAsync().ConfigureAwait(false);
+ var result = await nep5API.TestInvokeAsync(scriptHash, "unclaimedGas", account, blockCount - 1).ConfigureAwait(false);
+ BigInteger balance = result.Stack.Single().GetInteger();
return ((decimal)balance) / (long)NativeContract.GAS.Factor;
}
@@ -62,9 +63,9 @@ public decimal GetUnclaimedGas(UInt160 account)
/// address, scripthash or public key string
/// Example: address ("Ncm9TEzrp8SSer6Wa3UCSLTRnqzwVhCfuE"), scripthash ("0xb0a31817c80ad5f87b6ed390ecb3f9d312f7ceb8"), public key ("02f9ec1fd0a98796cf75b586772a4ddd41a0af07a1dbdf86a7238f74fb72503575")
///
- public uint GetNeoBalance(string account)
+ public async Task GetNeoBalanceAsync(string account)
{
- BigInteger balance = GetTokenBalance(NativeContract.NEO.Hash.ToString(), account);
+ BigInteger balance = await GetTokenBalanceAsync(NativeContract.NEO.Hash.ToString(), account).ConfigureAwait(false);
return (uint)balance;
}
@@ -74,9 +75,9 @@ public uint GetNeoBalance(string account)
/// address, scripthash or public key string
/// Example: address ("Ncm9TEzrp8SSer6Wa3UCSLTRnqzwVhCfuE"), scripthash ("0xb0a31817c80ad5f87b6ed390ecb3f9d312f7ceb8"), public key ("02f9ec1fd0a98796cf75b586772a4ddd41a0af07a1dbdf86a7238f74fb72503575")
///
- public decimal GetGasBalance(string account)
+ public async Task GetGasBalanceAsync(string account)
{
- BigInteger balance = GetTokenBalance(NativeContract.GAS.Hash.ToString(), account);
+ BigInteger balance = await GetTokenBalanceAsync(NativeContract.GAS.Hash.ToString(), account).ConfigureAwait(false);
return ((decimal)balance) / (long)NativeContract.GAS.Factor;
}
@@ -87,11 +88,11 @@ public decimal GetGasBalance(string account)
/// address, scripthash or public key string
/// Example: address ("Ncm9TEzrp8SSer6Wa3UCSLTRnqzwVhCfuE"), scripthash ("0xb0a31817c80ad5f87b6ed390ecb3f9d312f7ceb8"), public key ("02f9ec1fd0a98796cf75b586772a4ddd41a0af07a1dbdf86a7238f74fb72503575")
///
- public BigInteger GetTokenBalance(string tokenHash, string account)
+ public Task GetTokenBalanceAsync(string tokenHash, string account)
{
UInt160 scriptHash = Utility.GetScriptHash(tokenHash);
UInt160 accountHash = Utility.GetScriptHash(account);
- return nep5API.BalanceOf(scriptHash, accountHash);
+ return nep5API.BalanceOfAsync(scriptHash, accountHash);
}
///
@@ -101,10 +102,10 @@ public BigInteger GetTokenBalance(string tokenHash, string account)
/// wif or private key
/// Example: WIF ("KyXwTh1hB76RRMquSvnxZrJzQx7h9nQP2PCRL38v6VDb5ip3nf1p"), PrivateKey ("450d6c2a04b5b470339a745427bae6828400cf048400837d73c415063835e005")
/// The transaction sended
- public Transaction ClaimGas(string key)
+ public Task ClaimGasAsync(string key)
{
KeyPair keyPair = Utility.GetKeyPair(key);
- return ClaimGas(keyPair);
+ return ClaimGasAsync(keyPair);
}
///
@@ -113,12 +114,12 @@ public Transaction ClaimGas(string key)
///
/// keyPair
/// The transaction sended
- public Transaction ClaimGas(KeyPair keyPair)
+ public async Task ClaimGasAsync(KeyPair keyPair)
{
UInt160 toHash = Contract.CreateSignatureRedeemScript(keyPair.PublicKey).ToScriptHash();
- BigInteger balance = nep5API.BalanceOf(NativeContract.NEO.Hash, toHash);
- Transaction transaction = nep5API.CreateTransferTx(NativeContract.NEO.Hash, keyPair, toHash, balance);
- rpcClient.SendRawTransaction(transaction);
+ BigInteger balance = await nep5API.BalanceOfAsync(NativeContract.NEO.Hash, toHash).ConfigureAwait(false);
+ Transaction transaction = await nep5API.CreateTransferTxAsync(NativeContract.NEO.Hash, keyPair, toHash, balance).ConfigureAwait(false);
+ await rpcClient.SendRawTransactionAsync(transaction).ConfigureAwait(false);
return transaction;
}
@@ -131,15 +132,15 @@ public Transaction ClaimGas(KeyPair keyPair)
/// address or account script hash
/// token amount
///
- public Transaction Transfer(string tokenHash, string fromKey, string toAddress, decimal amount)
+ public async Task TransferAsync(string tokenHash, string fromKey, string toAddress, decimal amount)
{
UInt160 scriptHash = Utility.GetScriptHash(tokenHash);
- var decimals = nep5API.Decimals(scriptHash);
+ var decimals = await nep5API.DecimalsAsync(scriptHash).ConfigureAwait(false);
KeyPair from = Utility.GetKeyPair(fromKey);
UInt160 to = Utility.GetScriptHash(toAddress);
BigInteger amountInteger = amount.ToBigInteger(decimals);
- return Transfer(scriptHash, from, to, amountInteger);
+ return await TransferAsync(scriptHash, from, to, amountInteger).ConfigureAwait(false);
}
///
@@ -150,10 +151,10 @@ public Transaction Transfer(string tokenHash, string fromKey, string toAddress,
/// to account script hash
/// transfer amount
///
- public Transaction Transfer(UInt160 scriptHash, KeyPair from, UInt160 to, BigInteger amountInteger)
+ public async Task TransferAsync(UInt160 scriptHash, KeyPair from, UInt160 to, BigInteger amountInteger)
{
- Transaction transaction = nep5API.CreateTransferTx(scriptHash, from, to, amountInteger);
- rpcClient.SendRawTransaction(transaction);
+ Transaction transaction = await nep5API.CreateTransferTxAsync(scriptHash, from, to, amountInteger).ConfigureAwait(false);
+ await rpcClient.SendRawTransactionAsync(transaction).ConfigureAwait(false);
return transaction;
}
@@ -167,10 +168,10 @@ public Transaction Transfer(UInt160 scriptHash, KeyPair from, UInt160 to, BigInt
/// to account
/// transfer amount
///
- public Transaction Transfer(UInt160 scriptHash, int m, ECPoint[] pubKeys, KeyPair[] keys, UInt160 to, BigInteger amountInteger)
+ public async Task TransferAsync(UInt160 scriptHash, int m, ECPoint[] pubKeys, KeyPair[] keys, UInt160 to, BigInteger amountInteger)
{
- Transaction transaction = nep5API.CreateTransferTx(scriptHash, m, pubKeys, keys, to, amountInteger);
- rpcClient.SendRawTransaction(transaction);
+ Transaction transaction = await nep5API.CreateTransferTxAsync(scriptHash, m, pubKeys, keys, to, amountInteger).ConfigureAwait(false);
+ await rpcClient.SendRawTransactionAsync(transaction).ConfigureAwait(false);
return transaction;
}
@@ -180,7 +181,7 @@ public Transaction Transfer(UInt160 scriptHash, int m, ECPoint[] pubKeys, KeyPai
/// the transaction to observe
/// TimeoutException throws after "timeout" seconds
/// the Transaction state, including vmState and blockhash
- public async Task WaitTransaction(Transaction transaction, int timeout = 60)
+ public async Task WaitTransactionAsync(Transaction transaction, int timeout = 60)
{
DateTime deadline = DateTime.UtcNow.AddSeconds(timeout);
RpcTransaction rpcTx = null;
@@ -193,7 +194,7 @@ public async Task WaitTransaction(Transaction transaction, int t
try
{
- rpcTx = rpcClient.GetRawTransaction(transaction.Hash.ToString());
+ rpcTx = await rpcClient.GetRawTransactionAsync(transaction.Hash.ToString()).ConfigureAwait(false);
if (rpcTx == null || rpcTx.Confirmations == null)
{
await Task.Delay((int)Blockchain.MillisecondsPerBlock / 2);
diff --git a/src/RpcServer/RpcServer.Blockchain.cs b/src/RpcServer/RpcServer.Blockchain.cs
index 25ae58acc..3adde1ac7 100644
--- a/src/RpcServer/RpcServer.Blockchain.cs
+++ b/src/RpcServer/RpcServer.Blockchain.cs
@@ -6,9 +6,7 @@
using Neo.Ledger;
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
-using Neo.SmartContract;
using Neo.SmartContract.Native;
-using Neo.VM;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -18,13 +16,13 @@ namespace Neo.Plugins
partial class RpcServer
{
[RpcMethod]
- private JObject GetBestBlockHash(JArray _params)
+ protected virtual JObject GetBestBlockHash(JArray _params)
{
return Blockchain.Singleton.CurrentBlockHash.ToString();
}
[RpcMethod]
- private JObject GetBlock(JArray _params)
+ protected virtual JObject GetBlock(JArray _params)
{
JObject key = _params[0];
bool verbose = _params.Count >= 2 && _params[1].AsBoolean();
@@ -54,13 +52,13 @@ private JObject GetBlock(JArray _params)
}
[RpcMethod]
- private JObject GetBlockCount(JArray _params)
+ protected virtual JObject GetBlockCount(JArray _params)
{
return Blockchain.Singleton.Height + 1;
}
[RpcMethod]
- private JObject GetBlockHash(JArray _params)
+ protected virtual JObject GetBlockHash(JArray _params)
{
uint height = uint.Parse(_params[0].AsString());
if (height <= Blockchain.Singleton.Height)
@@ -71,7 +69,7 @@ private JObject GetBlockHash(JArray _params)
}
[RpcMethod]
- private JObject GetBlockHeader(JArray _params)
+ protected virtual JObject GetBlockHeader(JArray _params)
{
JObject key = _params[0];
bool verbose = _params.Count >= 2 && _params[1].AsBoolean();
@@ -103,7 +101,7 @@ private JObject GetBlockHeader(JArray _params)
}
[RpcMethod]
- private JObject GetContractState(JArray _params)
+ protected virtual JObject GetContractState(JArray _params)
{
UInt160 script_hash = UInt160.Parse(_params[0].AsString());
ContractState contract = Blockchain.Singleton.View.Contracts.TryGet(script_hash);
@@ -111,7 +109,7 @@ private JObject GetContractState(JArray _params)
}
[RpcMethod]
- private JObject GetRawMemPool(JArray _params)
+ protected virtual JObject GetRawMemPool(JArray _params)
{
bool shouldGetUnverified = _params.Count >= 1 && _params[0].AsBoolean();
if (!shouldGetUnverified)
@@ -128,7 +126,7 @@ private JObject GetRawMemPool(JArray _params)
}
[RpcMethod]
- private JObject GetRawTransaction(JArray _params)
+ protected virtual JObject GetRawTransaction(JArray _params)
{
UInt256 hash = UInt256.Parse(_params[0].AsString());
bool verbose = _params.Count >= 2 && _params[1].AsBoolean();
@@ -153,7 +151,7 @@ private JObject GetRawTransaction(JArray _params)
}
[RpcMethod]
- private JObject GetStorage(JArray _params)
+ protected virtual JObject GetStorage(JArray _params)
{
if (!int.TryParse(_params[0].AsString(), out int id))
{
@@ -172,7 +170,7 @@ private JObject GetStorage(JArray _params)
}
[RpcMethod]
- private JObject GetTransactionHeight(JArray _params)
+ protected virtual JObject GetTransactionHeight(JArray _params)
{
UInt256 hash = UInt256.Parse(_params[0].AsString());
uint? height = Blockchain.Singleton.View.Transactions.TryGet(hash)?.BlockIndex;
@@ -181,7 +179,7 @@ private JObject GetTransactionHeight(JArray _params)
}
[RpcMethod]
- private JObject GetNextBlockValidators(JArray _params)
+ protected virtual JObject GetNextBlockValidators(JArray _params)
{
using SnapshotView snapshot = Blockchain.Singleton.GetSnapshot();
var validators = NativeContract.NEO.GetNextBlockValidators(snapshot);
@@ -196,7 +194,7 @@ private JObject GetNextBlockValidators(JArray _params)
}
[RpcMethod]
- private JObject GetCommittee(JArray _params)
+ protected virtual JObject GetCommittee(JArray _params)
{
using SnapshotView snapshot = Blockchain.Singleton.GetSnapshot();
return new JArray(NativeContract.NEO.GetCommittee(snapshot).Select(p => (JObject)p.ToString()));
diff --git a/src/RpcServer/RpcServer.Node.cs b/src/RpcServer/RpcServer.Node.cs
index 0696ab7f3..ccf06ee28 100644
--- a/src/RpcServer/RpcServer.Node.cs
+++ b/src/RpcServer/RpcServer.Node.cs
@@ -15,13 +15,13 @@ namespace Neo.Plugins
partial class RpcServer
{
[RpcMethod]
- private JObject GetConnectionCount(JArray _params)
+ protected virtual JObject GetConnectionCount(JArray _params)
{
return LocalNode.Singleton.ConnectedCount;
}
[RpcMethod]
- private JObject GetPeers(JArray _params)
+ protected virtual JObject GetPeers(JArray _params)
{
JObject json = new JObject();
json["unconnected"] = new JArray(LocalNode.Singleton.GetUnconnectedPeers().Select(p =>
@@ -57,18 +57,19 @@ private static JObject GetRelayResult(VerifyResult reason, UInt256 hash)
}
[RpcMethod]
- private JObject GetVersion(JArray _params)
+ protected virtual JObject GetVersion(JArray _params)
{
JObject json = new JObject();
json["tcpport"] = LocalNode.Singleton.ListenerTcpPort;
json["wsport"] = LocalNode.Singleton.ListenerWsPort;
json["nonce"] = LocalNode.Nonce;
json["useragent"] = LocalNode.UserAgent;
+ json["magic"] = ProtocolSettings.Default.Magic;
return json;
}
[RpcMethod]
- private JObject SendRawTransaction(JArray _params)
+ protected virtual JObject SendRawTransaction(JArray _params)
{
Transaction tx = _params[0].AsString().HexToBytes().AsSerializable();
RelayResult reason = system.Blockchain.Ask(tx).Result;
@@ -76,7 +77,7 @@ private JObject SendRawTransaction(JArray _params)
}
[RpcMethod]
- private JObject SubmitBlock(JArray _params)
+ protected virtual JObject SubmitBlock(JArray _params)
{
Block block = _params[0].AsString().HexToBytes().AsSerializable();
RelayResult reason = system.Blockchain.Ask(block).Result;
diff --git a/src/RpcServer/RpcServer.SmartContract.cs b/src/RpcServer/RpcServer.SmartContract.cs
index 31b956ff5..2acec7012 100644
--- a/src/RpcServer/RpcServer.SmartContract.cs
+++ b/src/RpcServer/RpcServer.SmartContract.cs
@@ -98,7 +98,7 @@ private static Signers SignersFromJson(JArray _params)
}
[RpcMethod]
- private JObject InvokeFunction(JArray _params)
+ protected virtual JObject InvokeFunction(JArray _params)
{
UInt160 script_hash = UInt160.Parse(_params[0].AsString());
string operation = _params[1].AsString();
@@ -114,7 +114,7 @@ private JObject InvokeFunction(JArray _params)
}
[RpcMethod]
- private JObject InvokeScript(JArray _params)
+ protected virtual JObject InvokeScript(JArray _params)
{
byte[] script = _params[0].AsString().HexToBytes();
UInt160 sender = _params.Count >= 2 ? AddressToScriptHash(_params[1].AsString()) : null;
@@ -123,7 +123,7 @@ private JObject InvokeScript(JArray _params)
}
[RpcMethod]
- private JObject GetUnclaimedGas(JArray _params)
+ protected virtual JObject GetUnclaimedGas(JArray _params)
{
string address = _params[0].AsString();
JObject json = new JObject();
diff --git a/src/RpcServer/RpcServer.Utilities.cs b/src/RpcServer/RpcServer.Utilities.cs
index 7e4bf45db..52cf665e3 100644
--- a/src/RpcServer/RpcServer.Utilities.cs
+++ b/src/RpcServer/RpcServer.Utilities.cs
@@ -2,7 +2,6 @@
#pragma warning disable IDE0060
using Neo.IO.Json;
-using Neo.Wallets;
using System.Linq;
namespace Neo.Plugins
@@ -10,7 +9,7 @@ namespace Neo.Plugins
partial class RpcServer
{
[RpcMethod]
- private JObject ListPlugins(JArray _params)
+ protected virtual JObject ListPlugins(JArray _params)
{
return new JArray(Plugin.Plugins
.OrderBy(u => u.Name)
@@ -26,14 +25,14 @@ private JObject ListPlugins(JArray _params)
}
[RpcMethod]
- private JObject ValidateAddress(JArray _params)
+ protected virtual JObject ValidateAddress(JArray _params)
{
string address = _params[0].AsString();
JObject json = new JObject();
UInt160 scriptHash;
try
{
- scriptHash = AddressToScriptHash(address);
+ scriptHash = address.ToScriptHash();
}
catch
{
diff --git a/src/RpcServer/RpcServer.Wallet.cs b/src/RpcServer/RpcServer.Wallet.cs
index 5bcff2b39..021893d5a 100644
--- a/src/RpcServer/RpcServer.Wallet.cs
+++ b/src/RpcServer/RpcServer.Wallet.cs
@@ -40,7 +40,7 @@ public DummyWallet() : base("") { }
public override bool VerifyPassword(string password) => false;
}
- private Wallet wallet;
+ protected Wallet wallet;
private void CheckWallet()
{
@@ -49,14 +49,14 @@ private void CheckWallet()
}
[RpcMethod]
- private JObject CloseWallet(JArray _params)
+ protected virtual JObject CloseWallet(JArray _params)
{
wallet = null;
return true;
}
[RpcMethod]
- private JObject DumpPrivKey(JArray _params)
+ protected virtual JObject DumpPrivKey(JArray _params)
{
CheckWallet();
UInt160 scriptHash = AddressToScriptHash(_params[0].AsString());
@@ -65,7 +65,7 @@ private JObject DumpPrivKey(JArray _params)
}
[RpcMethod]
- private JObject GetNewAddress(JArray _params)
+ protected virtual JObject GetNewAddress(JArray _params)
{
CheckWallet();
WalletAccount account = wallet.CreateAccount();
@@ -75,7 +75,7 @@ private JObject GetNewAddress(JArray _params)
}
[RpcMethod]
- private JObject GetWalletBalance(JArray _params)
+ protected virtual JObject GetWalletBalance(JArray _params)
{
CheckWallet();
UInt160 asset_id = UInt160.Parse(_params[0].AsString());
@@ -85,7 +85,7 @@ private JObject GetWalletBalance(JArray _params)
}
[RpcMethod]
- private JObject GetWalletUnclaimedGas(JArray _params)
+ protected virtual JObject GetWalletUnclaimedGas(JArray _params)
{
CheckWallet();
BigInteger gas = BigInteger.Zero;
@@ -98,7 +98,7 @@ private JObject GetWalletUnclaimedGas(JArray _params)
}
[RpcMethod]
- private JObject ImportPrivKey(JArray _params)
+ protected virtual JObject ImportPrivKey(JArray _params)
{
CheckWallet();
string privkey = _params[0].AsString();
@@ -115,7 +115,7 @@ private JObject ImportPrivKey(JArray _params)
}
[RpcMethod]
- private JObject CalculateNetworkFee(JArray _params)
+ protected virtual JObject CalculateNetworkFee(JArray _params)
{
byte[] tx = Convert.FromBase64String(_params[0].AsString());
@@ -125,7 +125,7 @@ private JObject CalculateNetworkFee(JArray _params)
}
[RpcMethod]
- private JObject ListAddress(JArray _params)
+ protected virtual JObject ListAddress(JArray _params)
{
CheckWallet();
return wallet.GetAccounts().Select(p =>
@@ -140,7 +140,7 @@ private JObject ListAddress(JArray _params)
}
[RpcMethod]
- private JObject OpenWallet(JArray _params)
+ protected virtual JObject OpenWallet(JArray _params)
{
string path = _params[0].AsString();
string password = _params[1].AsString();
@@ -195,7 +195,7 @@ private void ProcessInvokeWithWallet(JObject result, UInt160 sender = null, Sign
}
[RpcMethod]
- private JObject SendFrom(JArray _params)
+ protected virtual JObject SendFrom(JArray _params)
{
CheckWallet();
UInt160 assetId = UInt160.Parse(_params[0].AsString());
@@ -236,7 +236,7 @@ private JObject SendFrom(JArray _params)
}
[RpcMethod]
- private JObject SendMany(JArray _params)
+ protected virtual JObject SendMany(JArray _params)
{
CheckWallet();
int to_start = 0;
@@ -286,7 +286,7 @@ private JObject SendMany(JArray _params)
}
[RpcMethod]
- private JObject SendToAddress(JArray _params)
+ protected virtual JObject SendToAddress(JArray _params)
{
CheckWallet();
UInt160 assetId = UInt160.Parse(_params[0].AsString());
diff --git a/src/RpcServer/RpcServer.cs b/src/RpcServer/RpcServer.cs
index e21755b5a..a17d51d22 100644
--- a/src/RpcServer/RpcServer.cs
+++ b/src/RpcServer/RpcServer.cs
@@ -19,7 +19,7 @@
namespace Neo.Plugins
{
- public sealed partial class RpcServer : IDisposable
+ public partial class RpcServer : IDisposable
{
private readonly Dictionary> methods = new Dictionary>();
diff --git a/src/RpcServer/RpcServerPlugin.cs b/src/RpcServer/RpcServerPlugin.cs
index 2d662432f..bc30cba3a 100644
--- a/src/RpcServer/RpcServerPlugin.cs
+++ b/src/RpcServer/RpcServerPlugin.cs
@@ -2,7 +2,7 @@
namespace Neo.Plugins
{
- public sealed class RpcServerPlugin : Plugin
+ public class RpcServerPlugin : Plugin
{
static List