diff --git a/src/RpcClient/Models/RpcApplicationLog.cs b/src/RpcClient/Models/RpcApplicationLog.cs index 205835e9c..cfdfbcc7e 100644 --- a/src/RpcClient/Models/RpcApplicationLog.cs +++ b/src/RpcClient/Models/RpcApplicationLog.cs @@ -11,6 +11,34 @@ public class RpcApplicationLog { public UInt256 TxId { get; set; } + public UInt256 BlockHash { get; set; } + + public List Executions { get; set; } + + public JObject ToJson() + { + JObject json = new JObject(); + if (TxId != null) + json["txid"] = TxId.ToString(); + if (BlockHash != null) + json["blockhash"] = BlockHash.ToString(); + json["executions"] = Executions.Select(p => p.ToJson()).ToArray(); + return json; + } + + public static RpcApplicationLog FromJson(JObject json) + { + return new RpcApplicationLog + { + TxId = json["txid"] is null ? null : UInt256.Parse(json["txid"].AsString()), + BlockHash = json["blockhash"] is null ? null : UInt256.Parse(json["blockhash"].AsString()), + Executions = ((JArray)json["executions"]).Select(p => Execution.FromJson(p)).ToList(), + }; + } + } + + public class Execution + { public TriggerType Trigger { get; set; } public VMState VMState { get; set; } @@ -24,7 +52,6 @@ public class RpcApplicationLog public JObject ToJson() { JObject json = new JObject(); - json["txid"] = TxId?.ToString(); json["trigger"] = Trigger; json["vmstate"] = VMState; json["gasconsumed"] = GasConsumed.ToString(); @@ -33,11 +60,10 @@ public JObject ToJson() return json; } - public static RpcApplicationLog FromJson(JObject json) + public static Execution FromJson(JObject json) { - return new RpcApplicationLog + return new Execution { - TxId = json["txid"] is null ? null : UInt256.Parse(json["txid"].AsString()), Trigger = json["trigger"].TryGetEnum(), VMState = json["vmstate"].TryGetEnum(), GasConsumed = long.Parse(json["gasconsumed"].AsString()), diff --git a/src/RpcClient/RpcClient.cs b/src/RpcClient/RpcClient.cs index deba207ef..b5d2cf430 100644 --- a/src/RpcClient/RpcClient.cs +++ b/src/RpcClient/RpcClient.cs @@ -3,6 +3,7 @@ using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.Network.RPC.Models; +using Neo.SmartContract; using Neo.SmartContract.Manifest; using System; using System.Collections.Generic; @@ -543,6 +544,16 @@ public async Task GetApplicationLogAsync(string txHash) return RpcApplicationLog.FromJson(result); } + /// + /// 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 async Task GetApplicationLogAsync(string txHash, TriggerType triggerType) + { + var result = await RpcSendAsync(GetRpcName(), txHash, triggerType).ConfigureAwait(false); + return RpcApplicationLog.FromJson(result); + } + /// /// Returns all the NEP-5 transaction information occurred in the specified address. /// This method is provided by the plugin RpcNep5Tracker. diff --git a/tests/Neo.Network.RPC.Tests/RpcTestCases.json b/tests/Neo.Network.RPC.Tests/RpcTestCases.json index ebe32c8a5..5de1433b6 100644 --- a/tests/Neo.Network.RPC.Tests/RpcTestCases.json +++ b/tests/Neo.Network.RPC.Tests/RpcTestCases.json @@ -666,7 +666,7 @@ "jsonrpc": "2.0", "id": 1, "result": { - "magic": 0, + "magic": 0, "tcpport": 20333, "wsport": 20334, "nonce": 592651621, @@ -1201,162 +1201,156 @@ "Request": { "jsonrpc": "2.0", "method": "getapplicationlog", - "params": [ "0x183cd84359cd9f8b956afcd02403ec07361c1dba55f0800241b4ef2b28e88bbb" ], + "params": [ "0x6ea186fe714b8168ede3b78461db8945c06d867da649852352dbe7cbf1ba3724" ], "id": 1 }, "Response": { "jsonrpc": "2.0", - "id": "1", + "id": 1, "result": { - "txid": "0xe36f62923deb64376e5e982e19b60afc65faca8d9e8eb71ac12f7298ce32ef7b", - "trigger": "Application", - "vmstate": "HALT", - "gasconsumed": "5814860", - "stack": [ + "blockhash": "0x6ea186fe714b8168ede3b78461db8945c06d867da649852352dbe7cbf1ba3724", + "executions": [ { - "type": "Array", - "value": [ - { - "type": "Any" - }, - { - "type": "Integer", - "value": "1" - }, - { - "type": "Integer", - "value": "1223" - }, - { - "type": "ByteString", - "value": "dGVzdHFxd2FzZGFz" - }, - { - "type": "Buffer", - "value": "CAwiNQw=" - }, + "trigger": "OnPersist", + "vmstate": "HALT", + "gasconsumed": "2031260", + "stack": [], + "notifications": [ { - "type": "Array", - "value": [ - { - "type": "ByteString", - "value": "YWE=" - }, - { - "type": "ByteString", - "value": "YmI=" - }, - { - "type": "ByteString", - "value": "Y2Mw" - } - ] + "contract": "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc", + "eventname": "Transfer", + "state": { + "type": "Array", + "value": [ + { + "type": "ByteString", + "value": "CqOHtT6Wt5iaYxQxoFbdH0CgQvY=" + }, + { + "type": "Any" + }, + { + "type": "Integer", + "value": "18083410" + } + ] + } }, { - "type": "Map", - "value": [ - { - "key": { - "type": "Integer", - "value": "2" + "contract": "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc", + "eventname": "Transfer", + "state": { + "type": "Array", + "value": [ + { + "type": "Any" }, - "value": { + { + "type": "ByteString", + "value": "z6LDQN4w1uEMToIZiPSxToNRPog=" + }, + { "type": "Integer", - "value": "12" + "value": "1252390" } - }, - { - "key": { - "type": "Integer", - "value": "0" + ] + } + } + ] + }, + { + "trigger": "PostPersist", + "vmstate": "HALT", + "gasconsumed": "2031260", + "stack": [], + "notifications": [ + { + "contract": "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc", + "eventname": "Transfer", + "state": { + "type": "Array", + "value": [ + { + "type": "Any" }, - "value": { + { + "type": "ByteString", + "value": "z6LDQN4w1uEMToIZiPSxToNRPog=" + }, + { "type": "Integer", - "value": "24" + "value": "50000000" } - } - ] + ] + } } ] } - ], - "notifications": [ + ] + } + } + }, + { + "Name": "getapplicationlogasync_triggertype", + "Request": { + "jsonrpc": "2.0", + "method": "getapplicationlog", + "params": [ "0x6ea186fe714b8168ede3b78461db8945c06d867da649852352dbe7cbf1ba3724", "OnPersist" ], + "id": 1 + }, + "Response": { + "jsonrpc": "2.0", + "id": 1, + "result": { + "blockhash": "0x6ea186fe714b8168ede3b78461db8945c06d867da649852352dbe7cbf1ba3724", + "executions": [ { - "contract": "0xbfe215933f29b29dacf0e8383722a62974ac8aa6", - "eventname": "event_name", - "state": { - "type": "Array", - "value": [ - { + "trigger": "OnPersist", + "vmstate": "HALT", + "gasconsumed": "2031260", + "stack": [], + "notifications": [ + { + "contract": "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc", + "eventname": "Transfer", + "state": { "type": "Array", "value": [ { - "type": "Array", - "value": [ - { - "type": "Integer", - "value": "1" - }, - { - "type": "Integer", - "value": "1223" - }, - { - "type": "ByteString", - "value": "dGVzdHFxd2FzZGFz" - }, - { - "type": "Buffer", - "value": "CAwiNQw=" - }, - { - "type": "Array", - "value": [ - { - "type": "ByteString", - "value": "YWE=" - }, - { - "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" - } - } - ] - } - ] + "type": "ByteString", + "value": "CqOHtT6Wt5iaYxQxoFbdH0CgQvY=" + }, + { + "type": "Any" + }, + { + "type": "Integer", + "value": "18083410" } ] } - ] - } + }, + { + "contract": "0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc", + "eventname": "Transfer", + "state": { + "type": "Array", + "value": [ + { + "type": "Any" + }, + { + "type": "ByteString", + "value": "z6LDQN4w1uEMToIZiPSxToNRPog=" + }, + { + "type": "Integer", + "value": "1252390" + } + ] + } + } + ] } ] } diff --git a/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs b/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs index 4f0b398ca..b558ef201 100644 --- a/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs +++ b/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs @@ -6,6 +6,7 @@ using Neo.IO.Json; using Neo.Network.P2P.Payloads; using Neo.Network.RPC.Models; +using Neo.SmartContract; using System; using System.Linq; using System.Net; @@ -421,6 +422,14 @@ public async Task GetApplicationLogTest() Assert.AreEqual(test.Response.Result.ToString(), result.ToJson().ToString()); } + [TestMethod()] + public async Task GetApplicationLogTest_TriggerType() + { + var test = TestUtils.RpcTestCases.Find(p => p.Name == (nameof(rpc.GetApplicationLogAsync) + "_triggertype").ToLower()); + var result = await rpc.GetApplicationLogAsync(test.Request.Params[0].AsString(), TriggerType.OnPersist); + Assert.AreEqual(test.Response.Result.ToString(), result.ToJson().ToString()); + } + [TestMethod()] public async Task GetNep5TransfersTest() {