diff --git a/src/RpcClient/Models/RpcInvokeResult.cs b/src/RpcClient/Models/RpcInvokeResult.cs index eeae4518c..67fb81e9a 100644 --- a/src/RpcClient/Models/RpcInvokeResult.cs +++ b/src/RpcClient/Models/RpcInvokeResult.cs @@ -1,5 +1,6 @@ using Neo.IO.Json; -using Neo.SmartContract; +using Neo.VM; +using Neo.VM.Types; using System; using System.Linq; @@ -13,7 +14,7 @@ public class RpcInvokeResult public string GasConsumed { get; set; } - public ContractParameter[] Stack { get; set; } + public StackItem[] Stack { get; set; } public string Tx { get; set; } @@ -44,7 +45,7 @@ public static RpcInvokeResult FromJson(JObject json) invokeScriptResult.GasConsumed = json["gasconsumed"].AsString(); try { - invokeScriptResult.Stack = ((JArray)json["stack"]).Select(p => ContractParameter.FromJson(p)).ToArray(); + invokeScriptResult.Stack = ((JArray)json["stack"]).Select(p => Utility.StackItemFromJson(p)).ToArray(); } catch { } invokeScriptResult.Tx = json["tx"]?.AsString(); diff --git a/src/RpcClient/Nep5API.cs b/src/RpcClient/Nep5API.cs index fc1616126..c700d5c68 100644 --- a/src/RpcClient/Nep5API.cs +++ b/src/RpcClient/Nep5API.cs @@ -30,7 +30,7 @@ public Nep5API(RpcClient rpcClient) : base(rpcClient) { } /// public BigInteger BalanceOf(UInt160 scriptHash, UInt160 account) { - BigInteger balance = TestInvoke(scriptHash, "balanceOf", account).Stack.Single().ToStackItem().GetInteger(); + BigInteger balance = TestInvoke(scriptHash, "balanceOf", account).Stack.Single().GetInteger(); return balance; } @@ -41,7 +41,7 @@ public BigInteger BalanceOf(UInt160 scriptHash, UInt160 account) /// public string Name(UInt160 scriptHash) { - return TestInvoke(scriptHash, "name").Stack.Single().ToStackItem().GetString(); + return TestInvoke(scriptHash, "name").Stack.Single().GetString(); } /// @@ -51,7 +51,7 @@ public string Name(UInt160 scriptHash) /// public string Symbol(UInt160 scriptHash) { - return TestInvoke(scriptHash, "symbol").Stack.Single().ToStackItem().GetString(); + return TestInvoke(scriptHash, "symbol").Stack.Single().GetString(); } /// @@ -61,7 +61,7 @@ public string Symbol(UInt160 scriptHash) /// public byte Decimals(UInt160 scriptHash) { - return (byte)TestInvoke(scriptHash, "decimals").Stack.Single().ToStackItem().GetInteger(); + return (byte)TestInvoke(scriptHash, "decimals").Stack.Single().GetInteger(); } /// @@ -71,7 +71,7 @@ public byte Decimals(UInt160 scriptHash) /// public BigInteger TotalSupply(UInt160 scriptHash) { - return TestInvoke(scriptHash, "totalSupply").Stack.Single().ToStackItem().GetInteger(); + return TestInvoke(scriptHash, "totalSupply").Stack.Single().GetInteger(); } /// @@ -90,10 +90,10 @@ public RpcNep5TokenInfo GetTokenInfo(UInt160 scriptHash) return new RpcNep5TokenInfo { - Name = result[0].ToStackItem().GetString(), - Symbol = result[1].ToStackItem().GetString(), - Decimals = (byte)result[2].ToStackItem().GetInteger(), - TotalSupply = result[3].ToStackItem().GetInteger() + Name = result[0].GetString(), + Symbol = result[1].GetString(), + Decimals = (byte)result[2].GetInteger(), + TotalSupply = result[3].GetInteger() }; } diff --git a/src/RpcClient/PolicyAPI.cs b/src/RpcClient/PolicyAPI.cs index de078a8e3..073b105b3 100644 --- a/src/RpcClient/PolicyAPI.cs +++ b/src/RpcClient/PolicyAPI.cs @@ -23,7 +23,7 @@ public PolicyAPI(RpcClient rpcClient) : base(rpcClient) { } /// public uint GetMaxTransactionsPerBlock() { - return (uint)TestInvoke(scriptHash, "getMaxTransactionsPerBlock").Stack.Single().ToStackItem().GetInteger(); + return (uint)TestInvoke(scriptHash, "getMaxTransactionsPerBlock").Stack.Single().GetInteger(); } /// @@ -32,7 +32,7 @@ public uint GetMaxTransactionsPerBlock() /// public uint GetMaxBlockSize() { - return (uint)TestInvoke(scriptHash, "getMaxBlockSize").Stack.Single().ToStackItem().GetInteger(); + return (uint)TestInvoke(scriptHash, "getMaxBlockSize").Stack.Single().GetInteger(); } /// @@ -41,7 +41,7 @@ public uint GetMaxBlockSize() /// public long GetFeePerByte() { - return (long)TestInvoke(scriptHash, "getFeePerByte").Stack.Single().ToStackItem().GetInteger(); + return (long)TestInvoke(scriptHash, "getFeePerByte").Stack.Single().GetInteger(); } /// @@ -50,7 +50,7 @@ public long GetFeePerByte() /// public UInt160[] GetBlockedAccounts() { - var result = (VM.Types.Array)TestInvoke(scriptHash, "getBlockedAccounts").Stack.Single().ToStackItem(); + var result = (VM.Types.Array)TestInvoke(scriptHash, "getBlockedAccounts").Stack.Single(); return result.Select(p => new UInt160(p.GetSpan().ToArray())).ToArray(); } } diff --git a/src/RpcClient/Utility.cs b/src/RpcClient/Utility.cs index cff72fd78..6bca96b12 100644 --- a/src/RpcClient/Utility.cs +++ b/src/RpcClient/Utility.cs @@ -2,11 +2,15 @@ using Neo.IO.Json; using Neo.Network.P2P.Payloads; using Neo.SmartContract; +using Neo.VM.Types; using Neo.Wallets; using System; using System.Globalization; using System.Linq; using System.Numerics; +using Array = Neo.VM.Types.Array; +using Boolean = Neo.VM.Types.Boolean; +using Buffer = Neo.VM.Types.Buffer; namespace Neo.Network.RPC { @@ -173,5 +177,44 @@ public static Witness WitnessFromJson(JObject json) witness.VerificationScript = Convert.FromBase64String(json["verification"].AsString()); return witness; } + + public static StackItem StackItemFromJson(JObject json) + { + StackItemType type = json["type"].TryGetEnum(); + switch (type) + { + case StackItemType.Boolean: + return new Boolean(json["value"].AsBoolean()); + case StackItemType.Buffer: + return new Buffer(Convert.FromBase64String(json["value"].AsString())); + case StackItemType.ByteString: + return new ByteString(Convert.FromBase64String(json["value"].AsString())); + case StackItemType.Integer: + return new Integer(new BigInteger(json["value"].AsNumber())); + case StackItemType.Array: + Array array = new Array(); + foreach (var item in (JArray)json["value"]) + array.Add(StackItemFromJson(item)); + return array; + case StackItemType.Struct: + Struct @struct = new Struct(); + foreach (var item in (JArray)json["value"]) + @struct.Add(StackItemFromJson(item)); + return @struct; + case StackItemType.Map: + Map map = new Map(); + foreach (var item in (JArray)json["value"]) + { + PrimitiveType key = (PrimitiveType)StackItemFromJson(item["key"]); + map[key] = StackItemFromJson(item["value"]); + } + return map; + case StackItemType.Pointer: + return new Pointer(null, (int)json["value"].AsNumber()); + case StackItemType.InteropInterface: + return new InteropInterface(new object()); // See https://github.com/neo-project/neo/blob/master/src/neo/VM/Helper.cs#L194 + } + return null; + } } } diff --git a/src/RpcClient/WalletAPI.cs b/src/RpcClient/WalletAPI.cs index 3d9edaa83..014aba6ec 100644 --- a/src/RpcClient/WalletAPI.cs +++ b/src/RpcClient/WalletAPI.cs @@ -52,7 +52,7 @@ public decimal GetUnclaimedGas(UInt160 account) { UInt160 scriptHash = NativeContract.NEO.Hash; BigInteger balance = nep5API.TestInvoke(scriptHash, "unclaimedGas", account, rpcClient.GetBlockCount() - 1) - .Stack.Single().ToStackItem().GetInteger(); + .Stack.Single().GetInteger(); return ((decimal)balance) / (long)NativeContract.GAS.Factor; } diff --git a/tests/Neo.Network.RPC.Tests/RpcTestCases.json b/tests/Neo.Network.RPC.Tests/RpcTestCases.json index d364a71d3..33ee866d1 100644 --- a/tests/Neo.Network.RPC.Tests/RpcTestCases.json +++ b/tests/Neo.Network.RPC.Tests/RpcTestCases.json @@ -758,20 +758,62 @@ "gasconsumed": "5061560", "stack": [ { - "type": "ByteArray", - "value": "R0FT" - }, - { - "type": "ByteArray", - "value": "Z2Fz" - }, - { - "type": "Integer", - "value": "8" - }, - { - "type": "Integer", - "value": "3001101329992600" + "type": "Array", + "value": [ + { + "type": "ByteString", + "value": "dGVzdA==" + }, + { + "type": "InteropInterface" + }, + { + "type": "Integer", + "value": "1" + }, + { + "type": "Buffer", + "value": "CAwiNQw=" + }, + { + "type": "Array", + "value": [ + { + "type": "ByteString", + "value": "YmI=" + }, + { + "type": "ByteString", + "value": "Y2Mw" + } + ] + }, + { + "type": "Map", + "value": [ + { + "key": { + "type": "Integer", + "value": "2" + }, + "value": { + "type": "Integer", + "value": "12" + } + }, + { + "key": { + "type": "Integer", + "value": "0" + }, + "value": { + "type": "Integer", + "value": "24" + } + } + ] + } + ] } ], "tx": "00769d16556925aa554712439a9c613ba114efa3fac23ddbca00e1f505000000009e021400000000005620200000009910c30c046e616d650c143b7d3711c6f0ccf9b1dca903d1bfa1d896f1238c41627d5b5210c30c0673796d626f6c0c143b7d3711c6f0ccf9b1dca903d1bfa1d896f1238c41627d5b5210c30c08646563696d616c730c143b7d3711c6f0ccf9b1dca903d1bfa1d896f1238c41627d5b5210c30c0b746f74616c537570706c790c143b7d3711c6f0ccf9b1dca903d1bfa1d896f1238c41627d5b5201420c40c848d0fcbf5e6a820508242ea8b7ccbeed3caefeed5db570537279c2154f7cfd8b0d8f477f37f4e6ca912935b732684d57c455dff7aa525ad4ab000931f22208290c2103aa052fbcb8e5b33a4eefd662536f8684641f04109f1d5e69cdda6f084890286a0b410a906ad4" diff --git a/tests/Neo.Network.RPC.Tests/UT_ContractClient.cs b/tests/Neo.Network.RPC.Tests/UT_ContractClient.cs index 0e84afa3d..dfdbf9990 100644 --- a/tests/Neo.Network.RPC.Tests/UT_ContractClient.cs +++ b/tests/Neo.Network.RPC.Tests/UT_ContractClient.cs @@ -32,7 +32,7 @@ public void TestInvoke() ContractClient contractClient = new ContractClient(rpcClientMock.Object); var result = contractClient.TestInvoke(NativeContract.GAS.Hash, "balanceOf", UInt160.Zero); - Assert.AreEqual(30000000000000L, (long)result.Stack[0].ToStackItem().GetInteger()); + Assert.AreEqual(30000000000000L, (long)result.Stack[0].GetInteger()); } [TestMethod] diff --git a/tests/Neo.Network.RPC.Tests/UT_TransactionManager.cs b/tests/Neo.Network.RPC.Tests/UT_TransactionManager.cs index 1f4da3250..b1546a9c7 100644 --- a/tests/Neo.Network.RPC.Tests/UT_TransactionManager.cs +++ b/tests/Neo.Network.RPC.Tests/UT_TransactionManager.cs @@ -95,7 +95,7 @@ public static void MockInvokeScript(Mock mockClient, byte[] script, p { var result = new RpcInvokeResult() { - Stack = parameters, + Stack = parameters.Select(p => p.ToStackItem()).ToArray(), GasConsumed = "100", Script = script.ToHexString(), State = VMState.HALT