diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 4b3679871..2d56584c7 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -15,7 +15,7 @@
-
+
diff --git a/src/RpcClient/Models/RpcContractState.cs b/src/RpcClient/Models/RpcContractState.cs
index e4e0f711d..797fa1a79 100644
--- a/src/RpcClient/Models/RpcContractState.cs
+++ b/src/RpcClient/Models/RpcContractState.cs
@@ -1,5 +1,7 @@
using Neo;
+using Neo.IO;
using Neo.IO.Json;
+using Neo.Network.RPC.Models;
using Neo.SmartContract;
using Neo.SmartContract.Manifest;
using System;
@@ -22,7 +24,7 @@ public static RpcContractState FromJson(JObject json)
Id = (int)json["id"].AsNumber(),
UpdateCounter = (ushort)json["updatecounter"].AsNumber(),
Hash = UInt160.Parse(json["hash"].AsString()),
- Script = Convert.FromBase64String(json["script"].AsString()),
+ Nef = RpcNefFile.FromJson(json["nef"]),
Manifest = ContractManifest.FromJson(json["manifest"])
}
};
diff --git a/src/RpcClient/Models/RpcMethodToken.cs b/src/RpcClient/Models/RpcMethodToken.cs
new file mode 100644
index 000000000..02bf31ead
--- /dev/null
+++ b/src/RpcClient/Models/RpcMethodToken.cs
@@ -0,0 +1,25 @@
+using Neo.IO.Json;
+using Neo.SmartContract;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Neo.Network.RPC.Models
+{
+ class RpcMethodToken
+ {
+ public static MethodToken FromJson(JObject json)
+ {
+ return new MethodToken
+ {
+ Hash = UInt160.Parse(json["hash"].AsString()),
+ Method = json["method"].AsString(),
+ ParametersCount = (ushort)json["paramcount"].AsNumber(),
+ HasReturnValue = json["hasreturnvalue"].AsBoolean(),
+ CallFlags = (CallFlags)Enum.Parse(typeof(CallFlags), json["callflags"].AsString())
+ };
+ }
+ }
+}
diff --git a/src/RpcClient/Models/RpcNefFile.cs b/src/RpcClient/Models/RpcNefFile.cs
new file mode 100644
index 000000000..d366d5294
--- /dev/null
+++ b/src/RpcClient/Models/RpcNefFile.cs
@@ -0,0 +1,25 @@
+using Neo.IO.Json;
+using Neo.SmartContract;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Neo.Network.RPC.Models
+{
+ class RpcNefFile
+ {
+ public static NefFile FromJson(JObject json)
+ {
+ return new NefFile
+ {
+ Compiler = json["compiler"].AsString(),
+ Version = json["version"].AsString(),
+ Tokens = ((JArray)json["tokens"]).Select(p => RpcMethodToken.FromJson(p)).ToArray(),
+ Script = Convert.FromBase64String(json["script"].AsString()),
+ CheckSum = (uint)json["checksum"].AsNumber()
+ };
+ }
+ }
+}
diff --git a/src/RpcClient/Nep17API.cs b/src/RpcClient/Nep17API.cs
index 14312e841..e3d7a8c53 100644
--- a/src/RpcClient/Nep17API.cs
+++ b/src/RpcClient/Nep17API.cs
@@ -76,14 +76,32 @@ public async Task TotalSupplyAsync(UInt160 scriptHash)
///
public async Task GetTokenInfoAsync(UInt160 scriptHash)
{
+ var contractState = await rpcClient.GetContractStateAsync(scriptHash.ToString()).ConfigureAwait(false);
byte[] script = Concat(
scriptHash.MakeScript("symbol", true),
scriptHash.MakeScript("decimals", true),
scriptHash.MakeScript("totalSupply", true));
-
- var contractState = await rpcClient.GetContractStateAsync(scriptHash.ToString()).ConfigureAwait(false);
var name = contractState.Manifest.Name;
+ var result = await rpcClient.InvokeScriptAsync(script).ConfigureAwait(false);
+ var stack = result.Stack;
+ return new RpcNep17TokenInfo
+ {
+ Name = name,
+ Symbol = stack[0].GetString(),
+ Decimals = (byte)stack[1].GetInteger(),
+ TotalSupply = stack[2].GetInteger()
+ };
+ }
+
+ public async Task GetTokenInfoAsync(string contractName)
+ {
+ var contractState = await rpcClient.GetContractStateAsync(contractName).ConfigureAwait(false);
+ byte[] script = Concat(
+ contractState.Hash.MakeScript("symbol", true),
+ contractState.Hash.MakeScript("decimals", true),
+ contractState.Hash.MakeScript("totalSupply", true));
+ var name = contractState.Manifest.Name;
var result = await rpcClient.InvokeScriptAsync(script).ConfigureAwait(false);
var stack = result.Stack;
@@ -109,7 +127,6 @@ public async Task CreateTransferTxAsync(UInt160 scriptHash, KeyPair
{
var sender = Contract.CreateSignatureRedeemScript(fromKey.PublicKey).ToScriptHash();
Signer[] signers = new[] { new Signer { Scopes = WitnessScope.CalledByEntry, Account = sender } };
-
byte[] script = scriptHash.MakeScript("transfer", true, sender, to, amount, data);
TransactionManagerFactory factory = new TransactionManagerFactory(rpcClient, magic);
@@ -136,7 +153,6 @@ public async Task CreateTransferTxAsync(UInt160 scriptHash, int m,
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", true, sender, to, amount, data);
TransactionManagerFactory factory = new TransactionManagerFactory(rpcClient, magic);
diff --git a/src/RpcClient/RpcClient.cs b/src/RpcClient/RpcClient.cs
index ca47d82a5..a02447e4a 100644
--- a/src/RpcClient/RpcClient.cs
+++ b/src/RpcClient/RpcClient.cs
@@ -203,7 +203,7 @@ public static ContractState ContractStateFromJson(JObject json)
Id = (int)json["id"].AsNumber(),
UpdateCounter = (ushort)json["updatecounter"].AsNumber(),
Hash = UInt160.Parse(json["hash"].AsString()),
- Script = Convert.FromBase64String(json["script"].AsString()),
+ Nef = RpcNefFile.FromJson(json["nef"]),
Manifest = ContractManifest.FromJson(json["manifest"])
};
}
diff --git a/tests/Neo.Network.RPC.Tests/RpcTestCases.json b/tests/Neo.Network.RPC.Tests/RpcTestCases.json
index 4ffadec7a..bcfe69d59 100644
--- a/tests/Neo.Network.RPC.Tests/RpcTestCases.json
+++ b/tests/Neo.Network.RPC.Tests/RpcTestCases.json
@@ -313,12 +313,28 @@
"result": "300000000"
}
},
+ {
+ "Name": "getcommitteeasync",
+ "Request": {
+ "jsonrpc": "2.0",
+ "method": "getcommittee",
+ "params": [],
+ "id": 1
+ },
+ "Response": {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": [
+ "02ced432397ddc44edba031c0bc3b933f28fdd9677792d7b20e6c036ddaaacf1e2"
+ ]
+ }
+ },
{
"Name": "getcontractstateasync",
"Request": {
"jsonrpc": "2.0",
"method": "getcontractstate",
- "params": [ "0xa6a6c15dcdc9b997dac448b6926522d22efeedfb" ],
+ "params": [ "gastoken" ],
"id": 1
},
"Response": {
@@ -327,8 +343,15 @@
"result": {
"id": -2,
"updatecounter": 0,
- "hash": "0xa6a6c15dcdc9b997dac448b6926522d22efeedfb",
- "script": "DAhHYXNUb2tlbkEa93tn",
+ "hash": "0x149a7f61eb3b4763b9655836ec7e75ddafdd1717",
+ "nef": {
+ "magic": 860243278,
+ "compiler": "ScriptBuilder",
+ "version": "3.0",
+ "tokens": [],
+ "script": "DAhHYXNUb2tlbkEa93tn",
+ "checksum": 4072842264
+ },
"manifest": {
"name": "GasToken",
"groups": [],
@@ -349,7 +372,7 @@
"parameters": [
{
"name": "account",
- "type": "ByteArray"
+ "type": "Hash160"
}
],
"offset": 0,
@@ -361,11 +384,132 @@
"parameters": [
{
"name": "from",
- "type": "ByteArray"
+ "type": "Hash160"
},
{
"name": "to",
- "type": "ByteArray"
+ "type": "Hash160"
+ },
+ {
+ "name": "amount",
+ "type": "Integer"
+ },
+ {
+ "name": "data",
+ "type": "Any"
+ }
+ ],
+ "offset": 0,
+ "returntype": "Boolean",
+ "safe": false
+ },
+ {
+ "name": "symbol",
+ "parameters": [],
+ "offset": 0,
+ "returntype": "String",
+ "safe": true
+ },
+ {
+ "name": "decimals",
+ "parameters": [],
+ "offset": 0,
+ "returntype": "Integer",
+ "safe": true
+ }
+ ],
+ "events": [
+ {
+ "name": "Transfer",
+ "parameters": [
+ {
+ "name": "from",
+ "type": "Hash160"
+ },
+ {
+ "name": "to",
+ "type": "Hash160"
+ },
+ {
+ "name": "amount",
+ "type": "Integer"
+ }
+ ]
+ }
+ ]
+ },
+ "permissions": [
+ {
+ "contract": "*",
+ "methods": "*"
+ }
+ ],
+ "trusts": [],
+ "extra": null
+ }
+ }
+ }
+ },
+ {
+ "Name": "getcontractstateasync",
+ "Request": {
+ "jsonrpc": "2.0",
+ "method": "getcontractstate",
+ "params": [ "0x149a7f61eb3b4763b9655836ec7e75ddafdd1717" ],
+ "id": 1
+ },
+ "Response": {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": {
+ "id": -2,
+ "updatecounter": 0,
+ "hash": "0x149a7f61eb3b4763b9655836ec7e75ddafdd1717",
+ "nef": {
+ "magic": 860243278,
+ "compiler": "ScriptBuilder",
+ "version": "3.0",
+ "tokens": [],
+ "script": "DAhHYXNUb2tlbkEa93tn",
+ "checksum": 4072842264
+ },
+ "manifest": {
+ "name": "GasToken",
+ "groups": [],
+ "supportedstandards": [
+ "NEP-17"
+ ],
+ "abi": {
+ "methods": [
+ {
+ "name": "totalSupply",
+ "parameters": [],
+ "offset": 0,
+ "returntype": "Integer",
+ "safe": true
+ },
+ {
+ "name": "balanceOf",
+ "parameters": [
+ {
+ "name": "account",
+ "type": "Hash160"
+ }
+ ],
+ "offset": 0,
+ "returntype": "Integer",
+ "safe": true
+ },
+ {
+ "name": "transfer",
+ "parameters": [
+ {
+ "name": "from",
+ "type": "Hash160"
+ },
+ {
+ "name": "to",
+ "type": "Hash160"
},
{
"name": "amount",
@@ -433,7 +577,7 @@
"jsonrpc": "2.0",
"id": 1,
"method": "getcontractstate",
- "params": [ "0x0a46e2e37c9987f570b4af253fb77e7eef0f72b6" ]
+ "params": [ "neotoken" ]
},
"Response": {
"jsonrpc": "2.0",
@@ -441,8 +585,15 @@
"result": {
"id": -1,
"updatecounter": 0,
- "hash": "0x0a46e2e37c9987f570b4af253fb77e7eef0f72b6",
- "script": "DAhOZW9Ub2tlbkEa93tn",
+ "hash": "0x0e1b9bfaa44e60311f6f3c96cfcd6d12c2fc3add",
+ "nef": {
+ "magic": 860243278,
+ "compiler": "ScriptBuilder",
+ "version": "3.0",
+ "tokens": [],
+ "script": "DAhOZW9Ub2tlbkEa93tn",
+ "checksum": 1698415525
+ },
"manifest": {
"name": "NeoToken",
"groups": [],
@@ -482,7 +633,7 @@
"parameters": [
{
"name": "account",
- "type": "ByteArray"
+ "type": "Hash160"
},
{
"name": "end",
@@ -522,7 +673,7 @@
"parameters": [
{
"name": "account",
- "type": "ByteArray"
+ "type": "Hash160"
},
{
"name": "voteTo",
@@ -559,7 +710,7 @@
"parameters": [
{
"name": "account",
- "type": "ByteArray"
+ "type": "Hash160"
}
],
"offset": 0,
@@ -571,11 +722,228 @@
"parameters": [
{
"name": "from",
- "type": "ByteArray"
+ "type": "Hash160"
+ },
+ {
+ "name": "to",
+ "type": "Hash160"
+ },
+ {
+ "name": "amount",
+ "type": "Integer"
+ },
+ {
+ "name": "data",
+ "type": "Any"
+ }
+ ],
+ "offset": 0,
+ "returntype": "Boolean",
+ "safe": false
+ },
+ {
+ "name": "symbol",
+ "parameters": [],
+ "offset": 0,
+ "returntype": "String",
+ "safe": true
+ },
+ {
+ "name": "decimals",
+ "parameters": [],
+ "offset": 0,
+ "returntype": "Integer",
+ "safe": true
+ }
+ ],
+ "events": [
+ {
+ "name": "Transfer",
+ "parameters": [
+ {
+ "name": "from",
+ "type": "Hash160"
},
{
"name": "to",
+ "type": "Hash160"
+ },
+ {
+ "name": "amount",
+ "type": "Integer"
+ }
+ ]
+ }
+ ]
+ },
+ "permissions": [
+ {
+ "contract": "*",
+ "methods": "*"
+ }
+ ],
+ "trusts": [],
+ "extra": null
+ }
+ }
+ }
+ },
+ {
+ "Name": "getcontractstateasync",
+ "Request": {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "getcontractstate",
+ "params": [ "0x0e1b9bfaa44e60311f6f3c96cfcd6d12c2fc3add" ]
+ },
+ "Response": {
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": {
+ "id": -1,
+ "updatecounter": 0,
+ "hash": "0x0e1b9bfaa44e60311f6f3c96cfcd6d12c2fc3add",
+ "nef": {
+ "magic": 860243278,
+ "compiler": "ScriptBuilder",
+ "version": "3.0",
+ "tokens": [],
+ "script": "DAhOZW9Ub2tlbkEa93tn",
+ "checksum": 1698415525
+ },
+ "manifest": {
+ "name": "NeoToken",
+ "groups": [],
+ "supportedstandards": [
+ "NEP-17"
+ ],
+ "abi": {
+ "methods": [
+ {
+ "name": "totalSupply",
+ "parameters": [],
+ "offset": 0,
+ "returntype": "Integer",
+ "safe": true
+ },
+ {
+ "name": "setGasPerBlock",
+ "parameters": [
+ {
+ "name": "gasPerBlock",
+ "type": "Integer"
+ }
+ ],
+ "offset": 0,
+ "returntype": "Boolean",
+ "safe": false
+ },
+ {
+ "name": "getGasPerBlock",
+ "parameters": [],
+ "offset": 0,
+ "returntype": "Integer",
+ "safe": true
+ },
+ {
+ "name": "unclaimedGas",
+ "parameters": [
+ {
+ "name": "account",
+ "type": "Hash160"
+ },
+ {
+ "name": "end",
+ "type": "Integer"
+ }
+ ],
+ "offset": 0,
+ "returntype": "Integer",
+ "safe": true
+ },
+ {
+ "name": "registerCandidate",
+ "parameters": [
+ {
+ "name": "pubkey",
+ "type": "ByteArray"
+ }
+ ],
+ "offset": 0,
+ "returntype": "Boolean",
+ "safe": false
+ },
+ {
+ "name": "unregisterCandidate",
+ "parameters": [
+ {
+ "name": "pubkey",
"type": "ByteArray"
+ }
+ ],
+ "offset": 0,
+ "returntype": "Boolean",
+ "safe": false
+ },
+ {
+ "name": "vote",
+ "parameters": [
+ {
+ "name": "account",
+ "type": "Hash160"
+ },
+ {
+ "name": "voteTo",
+ "type": "ByteArray"
+ }
+ ],
+ "offset": 0,
+ "returntype": "Boolean",
+ "safe": false
+ },
+ {
+ "name": "getCandidates",
+ "parameters": [],
+ "offset": 0,
+ "returntype": "Array",
+ "safe": true
+ },
+ {
+ "name": "getCommittee",
+ "parameters": [],
+ "offset": 0,
+ "returntype": "Array",
+ "safe": true
+ },
+ {
+ "name": "getNextBlockValidators",
+ "parameters": [],
+ "offset": 0,
+ "returntype": "Array",
+ "safe": true
+ },
+ {
+ "name": "balanceOf",
+ "parameters": [
+ {
+ "name": "account",
+ "type": "Hash160"
+ }
+ ],
+ "offset": 0,
+ "returntype": "Integer",
+ "safe": true
+ },
+ {
+ "name": "transfer",
+ "parameters": [
+ {
+ "name": "from",
+ "type": "Hash160"
+ },
+ {
+ "name": "to",
+ "type": "Hash160"
},
{
"name": "amount",
diff --git a/tests/Neo.Network.RPC.Tests/UT_Nep17API.cs b/tests/Neo.Network.RPC.Tests/UT_Nep17API.cs
index 4d4582f11..a3d7bb63e 100644
--- a/tests/Neo.Network.RPC.Tests/UT_Nep17API.cs
+++ b/tests/Neo.Network.RPC.Tests/UT_Nep17API.cs
@@ -97,18 +97,33 @@ public async Task TestGetTokenInfo()
rpcClientMock.Setup(p => p.RpcSendAsync("getcontractstate", It.Is(u => true)))
.ReturnsAsync(test.Response.Result)
.Verifiable();
-
- if (test.Request.Params[0].AsString() == "0xa6a6c15dcdc9b997dac448b6926522d22efeedfb")
+ var gasToken = "0x149a7f61eb3b4763b9655836ec7e75ddafdd1717";
+ Assert.AreEqual(NativeContract.GAS.Hash.ToString(), gasToken);
+ var neoToken = "0x0e1b9bfaa44e60311f6f3c96cfcd6d12c2fc3add";
+ Assert.AreEqual(NativeContract.NEO.Hash.ToString(), neoToken);
+ if (test.Request.Params[0].AsString() == gasToken || test.Request.Params[0].AsString().Equals(NativeContract.GAS.Name, System.StringComparison.OrdinalIgnoreCase))
{
- var result = await nep17API.GetTokenInfoAsync(NativeContract.GAS.Hash);
+ var result = await nep17API.GetTokenInfoAsync(NativeContract.GAS.Name.ToLower());
+ Assert.AreEqual(NativeContract.GAS.Symbol, result.Symbol);
+ Assert.AreEqual(8, (int)result.Decimals);
+ Assert.AreEqual(1_00000000, (int)result.TotalSupply);
+ Assert.AreEqual("GasToken", result.Name);
+
+ result = await nep17API.GetTokenInfoAsync(NativeContract.GAS.Hash);
Assert.AreEqual(NativeContract.GAS.Symbol, result.Symbol);
Assert.AreEqual(8, (int)result.Decimals);
Assert.AreEqual(1_00000000, (int)result.TotalSupply);
Assert.AreEqual("GasToken", result.Name);
}
- else if (test.Request.Params[0].AsString() == "0x0a46e2e37c9987f570b4af253fb77e7eef0f72b6")
+ else if (test.Request.Params[0].AsString() == neoToken || test.Request.Params[0].AsString().Equals(NativeContract.NEO.Name, System.StringComparison.OrdinalIgnoreCase))
{
- var result = await nep17API.GetTokenInfoAsync(NativeContract.NEO.Hash);
+ var result = await nep17API.GetTokenInfoAsync(NativeContract.NEO.Name.ToLower());
+ Assert.AreEqual(NativeContract.NEO.Symbol, result.Symbol);
+ Assert.AreEqual(0, (int)result.Decimals);
+ Assert.AreEqual(1_00000000, (int)result.TotalSupply);
+ Assert.AreEqual("NeoToken", result.Name);
+
+ result = await nep17API.GetTokenInfoAsync(NativeContract.NEO.Hash);
Assert.AreEqual(NativeContract.NEO.Symbol, result.Symbol);
Assert.AreEqual(0, (int)result.Decimals);
Assert.AreEqual(1_00000000, (int)result.TotalSupply);
diff --git a/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs b/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs
index f4f2f5c12..9add97bec 100644
--- a/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs
+++ b/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs
@@ -155,6 +155,17 @@ public async Task TestGetBlockHeader()
}
}
+ [TestMethod]
+ public async Task TestGetCommittee()
+ {
+ var tests = TestUtils.RpcTestCases.Where(p => p.Name == nameof(rpc.GetCommitteeAsync).ToLower());
+ foreach (var test in tests)
+ {
+ var result = await rpc.GetCommitteeAsync();
+ Assert.AreEqual(test.Response.Result.ToString(), ((JArray)result.Select(p => (JObject)p).ToArray()).ToString());
+ }
+ }
+
[TestMethod]
public async Task TestGetContractState()
{
diff --git a/tests/Neo.Network.RPC.Tests/UT_RpcModels.cs b/tests/Neo.Network.RPC.Tests/UT_RpcModels.cs
index 18b55c603..bb557da6a 100644
--- a/tests/Neo.Network.RPC.Tests/UT_RpcModels.cs
+++ b/tests/Neo.Network.RPC.Tests/UT_RpcModels.cs
@@ -46,6 +46,9 @@ public void TestGetContractState()
JObject json = TestUtils.RpcTestCases.Find(p => p.Name == nameof(RpcClient.GetContractStateAsync).ToLower()).Response.Result;
var item = RpcContractState.FromJson(json);
Assert.AreEqual(json.ToString(), item.ToJson().ToString());
+
+ var nef = RpcNefFile.FromJson(json["nef"]);
+ Assert.AreEqual(json["nef"].ToString(), nef.ToJson().ToString());
}
[TestMethod()]
@@ -56,6 +59,12 @@ public void TestRpcInvokeResult()
Assert.AreEqual(json.ToString(), item.ToJson().ToString());
}
+ [TestMethod()]
+ public void TestRpcMethodToken()
+ {
+ RpcMethodToken.FromJson(JObject.Parse("{\"hash\": \"0x0e1b9bfaa44e60311f6f3c96cfcd6d12c2fc3add\", \"method\":\"test\",\"paramcount\":\"1\",\"hasreturnvalue\":\"true\",\"callflags\":\"All\"}"));
+ }
+
[TestMethod()]
public void TestRpcNep17Balances()
{