Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow traverse iterators #715

Merged
merged 13 commits into from
Jun 24, 2022
6 changes: 4 additions & 2 deletions src/RpcClient/Models/RpcInvokeResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public class RpcInvokeResult

public string Exception { get; set; }

public string Session { get; set; }

public JObject ToJson()
{
JObject json = new();
Expand Down Expand Up @@ -59,8 +61,8 @@ public static RpcInvokeResult FromJson(JObject json)
State = json["state"].TryGetEnum<VMState>(),
GasConsumed = long.Parse(json["gasconsumed"].AsString()),
};
if (json.ContainsProperty("exception"))
invokeScriptResult.Exception = json["exception"]?.AsString();
invokeScriptResult.Exception = json["exception"]?.AsString();
invokeScriptResult.Session = json["session"]?.AsString();
try
{
invokeScriptResult.Stack = ((JArray)json["stack"]).Select(p => Utility.StackItemFromJson(p)).ToArray();
Expand Down
59 changes: 48 additions & 11 deletions src/RpcClient/RpcClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using System.Net.Http;
using System.Net.Http.Headers;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
Expand Down Expand Up @@ -145,18 +146,8 @@ public virtual async Task<JObject> RpcSendAsync(string method, params JObject[]
return response.Result;
}

public static string GetRpcName()
public static string GetRpcName([CallerMemberName] string methodName = null)
{
var methodName = "";
for (int i = 1; i < 5; i++)
{
var method = new System.Diagnostics.StackTrace(true).GetFrame(i).GetMethod();
if (method.IsPublic && !method.IsGenericMethod)
{
methodName = method.Name;
break;
}
}
return new Regex("(.*?)(Hex|Both)?(Async)?").Replace(methodName, "$1").ToLowerInvariant();
}

Expand Down Expand Up @@ -460,6 +451,52 @@ public async Task<RpcUnclaimedGas> GetUnclaimedGasAsync(string address)
return RpcUnclaimedGas.FromJson(result);
}


public async IAsyncEnumerable<JObject> TraverseIteratorAsync(string sessionId, string id)
{
const int count = 100;
while (true)
{
var result = await RpcSendAsync(GetRpcName(), sessionId, id, count).ConfigureAwait(false);
var array = (JArray)result;
foreach (var jObject in array)
{
yield return jObject;
}
if (array.Count < count) break;
}
}

/// <summary>
/// Returns limit <paramref name="count"/> results from Iterator.
/// This RPC call does not affect the blockchain in any way.
/// </summary>
/// <param name="sessionId"></param>
/// <param name="id"></param>
/// <param name="count"></param>
/// <returns></returns>
public async IAsyncEnumerable<JObject> TraverseIteratorAsync(string sessionId, string id, int count)
{
var result = await RpcSendAsync(GetRpcName(), sessionId, id, count).ConfigureAwait(false);
if (result is JArray { Count: > 0 } array)
{
foreach (var jObject in array)
{
yield return jObject;
}
}
}

/// <summary>
/// Terminate specified Iterator session.
/// This RPC call does not affect the blockchain in any way.
/// </summary>
public async Task<bool> TerminateSessionAsync(string sessionId)
{
var result = await RpcSendAsync(GetRpcName(), sessionId).ConfigureAwait(false);
return result.GetBoolean();
}

#endregion SmartContract

#region Utilities
Expand Down
12 changes: 11 additions & 1 deletion src/RpcClient/Utility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,19 @@ public static StackItem StackItemFromJson(JObject json)
case StackItemType.Pointer:
return new Pointer(null, (int)json["value"].AsNumber());
case StackItemType.InteropInterface:
return new InteropInterface(new object());
return new InteropInterface(json);
}
return json["value"] is null ? StackItem.Null : json["value"].AsString();
}

public static string GetIteratorId(this StackItem item)
{
if (item is InteropInterface iop)
{
var json = iop.GetInterface<JObject>();
return json["id"]?.GetString();
}
return null;
}
}
}
Loading