Skip to content

Commit

Permalink
Pure async RpcClient (#335)
Browse files Browse the repository at this point in the history
* compiling, some stuff stubbed out

* more tests working

* MakeTxContext

* mistake in GetBlock/GetBlockHeader

* rework TransactionManager to be closer to original

* more unit tests (2 still failing)

* remove assertEx

* Add ThrowsAsync comment

* ReturnsAsync

* fixed last remaining test issues

* minor TXManager cleanup

* formatting

* move tx contruction to MakeTransaction

* discards

* Async Suffixes (PR feedback)

* GetCommitteeAsync

* add custom magic support to tx manager

* fix format

* add magic param comment

* CR Feedback

* Clean enter

Co-authored-by: Harry <[email protected]>
Co-authored-by: Shargon <[email protected]>
  • Loading branch information
3 people authored Oct 15, 2020
1 parent 81e07af commit 65e8b9b
Show file tree
Hide file tree
Showing 15 changed files with 633 additions and 516 deletions.
27 changes: 17 additions & 10 deletions src/RpcClient/ContractClient.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System;
using System.Threading.Tasks;
using Neo.Network.P2P.Payloads;
using Neo.Network.RPC.Models;
using Neo.SmartContract;
Expand All @@ -13,14 +15,21 @@ namespace Neo.Network.RPC
public class ContractClient
{
protected readonly RpcClient rpcClient;
protected readonly uint? magic;


/// <summary>
/// ContractClient Constructor
/// </summary>
/// <param name="rpc">the RPC client to call NEO RPC methods</param>
public ContractClient(RpcClient rpc)
/// <param name="magic">
/// the network Magic value to use when signing transactions.
/// Defaults to ProtocolSettings.Default.Magic if not specified.
/// </param>
public ContractClient(RpcClient rpc, uint? magic = null)
{
rpcClient = rpc;
this.magic = magic;
}

/// <summary>
Expand All @@ -30,10 +39,10 @@ public ContractClient(RpcClient rpc)
/// <param name="operation">contract operation</param>
/// <param name="args">operation arguments</param>
/// <returns></returns>
public RpcInvokeResult TestInvoke(UInt160 scriptHash, string operation, params object[] args)
public Task<RpcInvokeResult> TestInvokeAsync(UInt160 scriptHash, string operation, params object[] args)
{
byte[] script = scriptHash.MakeScript(operation, args);
return rpcClient.InvokeScript(script);
return rpcClient.InvokeScriptAsync(script);
}

/// <summary>
Expand All @@ -43,7 +52,7 @@ public RpcInvokeResult TestInvoke(UInt160 scriptHash, string operation, params o
/// <param name="manifest">contract manifest</param>
/// <param name="key">sender KeyPair</param>
/// <returns></returns>
public Transaction CreateDeployContractTx(byte[] contractScript, ContractManifest manifest, KeyPair key)
public async Task<Transaction> CreateDeployContractTxAsync(byte[] contractScript, ContractManifest manifest, KeyPair key)
{
byte[] script;
using (ScriptBuilder sb = new ScriptBuilder())
Expand All @@ -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);
}
}
}
68 changes: 37 additions & 31 deletions src/RpcClient/Nep5API.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System;
using System.Linq;
using System.Numerics;
using System.Threading.Tasks;
using static Neo.Helper;

namespace Neo.Network.RPC
Expand All @@ -28,9 +29,10 @@ public Nep5API(RpcClient rpcClient) : base(rpcClient) { }
/// <param name="scriptHash">contract script hash</param>
/// <param name="account">account script hash</param>
/// <returns></returns>
public BigInteger BalanceOf(UInt160 scriptHash, UInt160 account)
public async Task<BigInteger> 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;
}

Expand All @@ -39,61 +41,67 @@ public BigInteger BalanceOf(UInt160 scriptHash, UInt160 account)
/// </summary>
/// <param name="scriptHash">contract script hash</param>
/// <returns></returns>
public string Name(UInt160 scriptHash)
public async Task<string> NameAsync(UInt160 scriptHash)
{
return TestInvoke(scriptHash, "name").Stack.Single().GetString();
var result = await TestInvokeAsync(scriptHash, "name").ConfigureAwait(false);
return result.Stack.Single().GetString();
}

/// <summary>
/// Get symbol of NEP5 token
/// </summary>
/// <param name="scriptHash">contract script hash</param>
/// <returns></returns>
public string Symbol(UInt160 scriptHash)
public async Task<string> SymbolAsync(UInt160 scriptHash)
{
return TestInvoke(scriptHash, "symbol").Stack.Single().GetString();
var result = await TestInvokeAsync(scriptHash, "symbol").ConfigureAwait(false);
return result.Stack.Single().GetString();
}

/// <summary>
/// Get decimals of NEP5 token
/// </summary>
/// <param name="scriptHash">contract script hash</param>
/// <returns></returns>
public byte Decimals(UInt160 scriptHash)
public async Task<byte> 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();
}

/// <summary>
/// Get total supply of NEP5 token
/// </summary>
/// <param name="scriptHash">contract script hash</param>
/// <returns></returns>
public BigInteger TotalSupply(UInt160 scriptHash)
public async Task<BigInteger> TotalSupplyAsync(UInt160 scriptHash)
{
return TestInvoke(scriptHash, "totalSupply").Stack.Single().GetInteger();
var result = await TestInvokeAsync(scriptHash, "totalSupply").ConfigureAwait(false);
return result.Stack.Single().GetInteger();
}

/// <summary>
/// Get token information in one rpc call
/// </summary>
/// <param name="scriptHash">contract script hash</param>
/// <returns></returns>
public RpcNep5TokenInfo GetTokenInfo(UInt160 scriptHash)
public async Task<RpcNep5TokenInfo> 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()
};
}

Expand All @@ -105,19 +113,18 @@ public RpcNep5TokenInfo GetTokenInfo(UInt160 scriptHash)
/// <param name="to">to account script hash</param>
/// <param name="amount">transfer amount</param>
/// <returns></returns>
public Transaction CreateTransferTx(UInt160 scriptHash, KeyPair fromKey, UInt160 to, BigInteger amount)
public async Task<Transaction> 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);
}

/// <summary>
Expand All @@ -130,21 +137,20 @@ public Transaction CreateTransferTx(UInt160 scriptHash, KeyPair fromKey, UInt160
/// <param name="to">to account</param>
/// <param name="amount">transfer amount</param>
/// <returns></returns>
public Transaction CreateTransferTx(UInt160 scriptHash, int m, ECPoint[] pubKeys, KeyPair[] fromKeys, UInt160 to, BigInteger amount)
public async Task<Transaction> 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!");
var sender = Contract.CreateMultiSigContract(m, pubKeys).ScriptHash;
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);
}
}
}
23 changes: 14 additions & 9 deletions src/RpcClient/PolicyAPI.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Neo.SmartContract.Native;
using Neo.VM;
using System.Linq;
using System.Threading.Tasks;

namespace Neo.Network.RPC
{
Expand All @@ -21,37 +22,41 @@ public PolicyAPI(RpcClient rpcClient) : base(rpcClient) { }
/// Get Max Transactions Count Per Block
/// </summary>
/// <returns></returns>
public uint GetMaxTransactionsPerBlock()
public async Task<uint> GetMaxTransactionsPerBlockAsync()
{
return (uint)TestInvoke(scriptHash, "getMaxTransactionsPerBlock").Stack.Single().GetInteger();
var result = await TestInvokeAsync(scriptHash, "getMaxTransactionsPerBlock").ConfigureAwait(false);
return (uint)result.Stack.Single().GetInteger();
}

/// <summary>
/// Get Max Block Size
/// </summary>
/// <returns></returns>
public uint GetMaxBlockSize()
public async Task<uint> GetMaxBlockSizeAsync()
{
return (uint)TestInvoke(scriptHash, "getMaxBlockSize").Stack.Single().GetInteger();
var result = await TestInvokeAsync(scriptHash, "getMaxBlockSize").ConfigureAwait(false);
return (uint)result.Stack.Single().GetInteger();
}

/// <summary>
/// Get Network Fee Per Byte
/// </summary>
/// <returns></returns>
public long GetFeePerByte()
public async Task<long> GetFeePerByteAsync()
{
return (long)TestInvoke(scriptHash, "getFeePerByte").Stack.Single().GetInteger();
var result = await TestInvokeAsync(scriptHash, "getFeePerByte").ConfigureAwait(false);
return (long)result.Stack.Single().GetInteger();
}

/// <summary>
/// Get Ploicy Blocked Accounts
/// </summary>
/// <returns></returns>
public UInt160[] GetBlockedAccounts()
public async Task<UInt160[]> 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();
}
}
}
Loading

0 comments on commit 65e8b9b

Please sign in to comment.