Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
9aa2418
Added FindSignerLeaf and GetSigners methods
BellringerQuinn Jun 12, 2025
4ae0790
Added ability to get weight of a topology or config - adding Weight c…
BellringerQuinn Jun 12, 2025
9980b2e
Added HashConfiguration method
BellringerQuinn Jun 12, 2025
27c302b
Added ability to make topology from leaves
BellringerQuinn Jun 13, 2025
a848768
Added Topology.Encode method
BellringerQuinn Jun 13, 2025
231716a
Merge branch 'V5-EcosystemWallet' into Feature/primitives-config
andygruening Jun 16, 2025
51c16c1
added config and dev tools tests, topology decoding
andygruening Jun 17, 2025
a187fdb
signing topologies
andygruening Jun 17, 2025
771780f
update testchain, and include wallet-contracts-v3 artifacts
pkieltyka Jun 17, 2025
15ca893
Merge remote-tracking branch 'origin/testchain-update' into Feature/p…
andygruening Jun 23, 2025
4b681d9
Merge branch 'V5-EcosystemWallet' into Feature/primitives-config
andygruening Jun 24, 2025
db0ec66
removed un-implemented code
andygruening Jun 24, 2025
498f570
encoding topology, leafs and signatures
andygruening Jun 27, 2025
ea86ac2
byte array encoding changes, padLeft does not throw exceptions when t…
andygruening Jun 27, 2025
6f5b540
concat and decode signatures
andygruening Jun 29, 2025
ad52d2c
latest changes
andygruening Jun 29, 2025
c2e59c4
unit test fr encoding and decoding config
andygruening Jun 29, 2025
0c52d6b
unit test for recovering random config
andygruening Jun 29, 2025
476ccec
parsing config adjustments
andygruening Jun 29, 2025
a57eaff
fix for sapient type
andygruening Jun 29, 2025
e9da413
fixed encoding of chained signatures
andygruening Jun 30, 2025
b464b0e
fixed sapient signatures
andygruening Jun 30, 2025
939488f
started adding sessions topology and leafs
andygruening Jun 30, 2025
4b16a49
started adding session tests
andygruening Jun 30, 2025
0fe11a1
parsing sessions topology to json
andygruening Jun 30, 2025
dfb7bec
parsing session permissions
andygruening Jun 30, 2025
95f506b
parsing permissions from json, test to add explicit session
andygruening Jun 30, 2025
cce53b7
adding blacklist address
andygruening Jun 30, 2025
bc68800
encoding session call signatures
andygruening Jul 1, 2025
8ead52d
flatting and minimising sessions topology
andygruening Jul 1, 2025
a5d2e00
fixed sessions branch encoding
andygruening Jul 1, 2025
d6ed318
fixed permissions and attestation parsing
andygruening Jul 1, 2025
498782c
fixed generic encoding
andygruening Jul 1, 2025
4ab48ce
removing explicit session
andygruening Jul 1, 2025
cecf48a
remove address from blacklist
andygruening Jul 1, 2025
0f85dbf
added AddressFactory
andygruening Jul 1, 2025
401d243
test to create sequence address
andygruening Jul 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -122,5 +122,4 @@ Assets/SequenceSDK/WaaS/Tests/Resources/
# Foundry

/testchain/lib
/testchain/artifacts/*

53 changes: 53 additions & 0 deletions Assets/SequenceSDK/EcosystemWallet/IntegrationTests/ConfigTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System.Collections.Generic;
using System.Numerics;
using System.Threading.Tasks;
using Sequence.EcosystemWallet.Primitives;
using Sequence.Utils;

namespace Sequence.EcosystemWallet.IntegrationTests
{
public class ConfigTests
{
public Task<string> ConfigNew(Dictionary<string, object> parameters)
{
var threshold = (string)parameters["threshold"];
var checkpoint = (string)parameters["checkpoint"];
var content = (string)parameters["content"];

var checkpointer = parameters.TryGetValue("checkpointer", out var checkpointerValue) &&
checkpointerValue != null ? new Address(checkpointerValue as string) : null;

var config = new Primitives.Config
{
threshold = BigInteger.Parse(threshold),
checkpoint = BigInteger.Parse(checkpoint),
topology = Topology.FromLeaves(Topology.ParseContentToLeafs(content)),
checkpointer = checkpointer
};

return Task.FromResult(config.ToJson());
}

public Task<string> ConfigEncode(Dictionary<string, object> parameters)
{
var input = parameters["input"].ToString();
var config = Primitives.Config.FromJson(input);
var signature = new RawSignature
{
checkpointerData = null,
configuration = config,
};

var encoded = signature.Encode().ByteArrayToHexStringWithPrefix();
return Task.FromResult(encoded);
}

public Task<string> ConfigImageHash(Dictionary<string, object> parameters)
{
var input = parameters["input"].ToString();
var config = Primitives.Config.FromJson(input);
var imageHash = config.HashConfiguration().ByteArrayToHexStringWithPrefix();
return Task.FromResult(imageHash);
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Sequence.EcosystemWallet.IntegrationTests
{
public class DevToolsTest
{
public Task<string> DevToolsRandomConfig(Dictionary<string, object> parameters)
{
var maxDepth = int.Parse(parameters["maxDepth"].ToString());
var seed = (string)parameters["seed"];
var minThresholdOnNested = int.Parse(parameters["minThresholdOnNested"].ToString());
var checkpointer = parameters.TryGetValue("checkpointer", out var checkpointerObj) ? checkpointerObj.ToString() : "no";
var skewed = parameters.TryGetValue("skewed", out var skewedObj) ? skewedObj.ToString() : "none";

var options = new DevTools.RandomOptions
{
seededRandom = string.IsNullOrEmpty(seed) ? null : DevTools.CreateSeededRandom(seed),
checkpointer = checkpointer,
minThresholdOnNested = minThresholdOnNested,
skewed = skewed
};

return Task.FromResult(DevTools.CreateRandomConfig(maxDepth, options).ToJson());
}

public Task<string> DevToolsRandomSessionTopology(Dictionary<string, object> parameters)
{
throw new System.NotImplementedException("DevToolsTest.DevToolsRandomSessionTopology");
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,31 @@ internal class Server
public static readonly Dictionary<string, Func<Dictionary<string, object>, Task<object>>> Methods =
new Dictionary<string, Func<Dictionary<string, object>, Task<object>>>
{
// PAYLOAD
["payload_toAbi"] = async (parameters) => await new PayloadTests().PayloadToAbi(parameters),
["payload_toPacked"] = async (parameters) => await new PayloadTests().PayloadToPacked(parameters),
["payload_toJson"] = async (parameters) => await new PayloadTests().PayloadToJson(parameters),
["payload_hashFor"] = async (parameters) => await new PayloadTests().PayloadHashFor(parameters),
// CONFIG
["config_new"] = async (parameters) => await new ConfigTests().ConfigNew(parameters),
["config_encode"] = async (parameters) => await new ConfigTests().ConfigEncode(parameters),
["config_imageHash"] = async (parameters) => await new ConfigTests().ConfigImageHash(parameters),
// DEV TOOLS
["devTools_randomConfig"] = async (parameters) => await new DevToolsTest().DevToolsRandomConfig(parameters),
["devTools_randomSessionTopology"] = async (parameters) => await new DevToolsTest().DevToolsRandomSessionTopology(parameters),
// SIGNATURE
["signature_encode"] = async (parameters) => await new SignatureTests().SignatureEncode(parameters),
["signature_concat"] = async (parameters) => await new SignatureTests().SignatureConcat(parameters),
["signature_decode"] = async (parameters) => await new SignatureTests().SignatureDecode(parameters),
// SESSIONS
["session_empty"] = async (parameters) => await new SessionsTest().SessionEmpty(parameters),
["session_encodeTopology"] = async (parameters) => await new SessionsTest().SessionEncodeTopology(parameters),
["session_encodeCallSignatures"] = async (parameters) => await new SessionsTest().SessionEncodeCallSignatures(parameters),
["session_imageHash"] = async (parameters) => await new SessionsTest().SessionImageHash(parameters),
["session_explicit_add"] = async (parameters) => await new SessionsTest().SessionExplicitAdd(parameters),
["session_explicit_remove"] = async (parameters) => await new SessionsTest().SessionExplicitRemove(parameters),
["session_implicit_addBlacklistAddress"] = async (parameters) => await new SessionsTest().SessionImplicitAddBlacklistAddress(parameters),
["session_implicit_removeBlacklistAddress"] = async (parameters) => await new SessionsTest().SessionImplicitRemoveBlacklistAddress(parameters),
};

public async Task<JsonRpcResponse> HandleSingleRequest(
Expand All @@ -33,12 +54,7 @@ public async Task<JsonRpcResponse> HandleSingleRequest(

if (!silent)
{
Debug.Log($"[{DateTime.UtcNow:O}] Processing request: method={method} id={id}");
}

if (debug && !silent)
{
Debug.Log("Request details: " + JsonConvert.SerializeObject(rpcRequest, Formatting.Indented));
Debug.Log($"Processing request: method={method} id={id} payload={JsonConvert.SerializeObject(rpcRequest, Formatting.Indented)}");
}

if (jsonrpc != "2.0")
Expand All @@ -47,7 +63,7 @@ public async Task<JsonRpcResponse> HandleSingleRequest(
new JsonRpcErrorResponse(new JsonRpcErrorResponse.Error(-32600, "Invalid JSON-RPC version"), id);
if (!silent)
{
Debug.LogError($"[{DateTime.UtcNow:O}] Error response: {(debug ? JsonConvert.SerializeObject(error) : error.error.message)}");
Debug.LogError($"Error response: {(debug ? JsonConvert.SerializeObject(error) : error.error.message)}");
}

return error;
Expand All @@ -58,21 +74,14 @@ public async Task<JsonRpcResponse> HandleSingleRequest(
JsonRpcErrorResponse error = new JsonRpcErrorResponse(new JsonRpcErrorResponse.Error(-32601, $"Method not found: {method}"), id);
if (!silent)
{
Debug.LogError($"[{DateTime.UtcNow:O}] Error response: {(debug ? JsonConvert.SerializeObject(error) : error.error.message)}");
Debug.LogError($"Error response: {(debug ? JsonConvert.SerializeObject(error) : error.error.message)}");
}
return error;
}

try
{
Dictionary<string, object> methodParams;

if (debug && !silent)
{
Debug.Log($"[{DateTime.UtcNow:O}] Raw params: {JsonConvert.SerializeObject(@params)}");
}

// Convert params to JObject for more flexible parsing if needed
Newtonsoft.Json.Linq.JObject paramsJObject = null;
if (@params is Dictionary<string, object> paramsDict)
{
Expand All @@ -90,20 +99,11 @@ public async Task<JsonRpcResponse> HandleSingleRequest(
Debug.LogWarning("No method params");
}

if (debug && !silent)
{
Debug.Log($"[{DateTime.UtcNow:O}] Final methodParams: {JsonConvert.SerializeObject(methodParams)}");
}

var result = await Methods[method](methodParams);
JsonRpcSuccessResponse response = new JsonRpcSuccessResponse(result, id);
if (!silent)
{
Debug.Log($"[{DateTime.UtcNow:O}] Success Response for Method={method} id={id}");
if (debug)
{
Debug.Log("Response details: " + JsonConvert.SerializeObject(response, Formatting.Indented));
}
Debug.Log($"Response details for Method={method}: " + JsonConvert.SerializeObject(response, Formatting.Indented) + $", Params used = {JsonConvert.SerializeObject(methodParams)}");
}
return response;
}
Expand All @@ -112,7 +112,7 @@ public async Task<JsonRpcResponse> HandleSingleRequest(
JsonRpcErrorResponse error = new JsonRpcErrorResponse(new JsonRpcErrorResponse.Error(-32000, $"Unknown error: {ex.Message}"), id);
if (!silent)
{
Debug.LogError($"[{DateTime.UtcNow:O}] Error response: {(debug ? JsonConvert.SerializeObject(error) : error.error.message)}");
Debug.LogError($"Error response: {(debug ? JsonConvert.SerializeObject(error) : error.error.message)} {ex.StackTrace}");
}
return error;
}
Expand Down
105 changes: 105 additions & 0 deletions Assets/SequenceSDK/EcosystemWallet/IntegrationTests/SessionsTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Sequence.EcosystemWallet.Primitives;
using Sequence.EcosystemWallet.UnitTests;
using Sequence.Utils;

namespace Sequence.EcosystemWallet.IntegrationTests
{
public class SessionsTest
{
public Task<string> SessionEmpty(Dictionary<string, object> parameters)
{
var identitySigner = parameters["identitySigner"].ToString();
var topology = SessionsUtils.CreateSessionsTopologyWithSingleIdentity(identitySigner);

return Task.FromResult(topology.JsonSerialize());
}

public Task<string> SessionEncodeTopology(Dictionary<string, object> parameters)
{
var topologyJson = parameters["sessionTopology"].ToString();
var topology = SessionsTopology.FromJson(topologyJson);
var encoded = topology.Encode().ByteArrayToHexStringWithPrefix();

return Task.FromResult(encoded);
}

public Task<string> SessionEncodeCallSignatures(Dictionary<string, object> parameters)
{
var sessionTopologyJson = parameters["sessionTopology"].ToString();

var signatures = JsonConvert.DeserializeObject<object[]>(parameters["callSignatures"]
.ToString()).Select(s => SessionCallSignature.FromJson(s.ToString())).ToArray();

var explicitSigners = JsonConvert.DeserializeObject<string[]>(parameters["explicitSigners"]
.ToString()).Select(v => new Address(v)).ToArray();

var implicitSigners = JsonConvert.DeserializeObject<string[]>(parameters["implicitSigners"]
.ToString()).Select(v => new Address(v)).ToArray();

var sessionsTopology = SessionsTopology.FromJson(sessionTopologyJson);
var encodedSignatures = SessionCallSignature.EncodeSignatures(signatures, sessionsTopology, explicitSigners, implicitSigners);

return Task.FromResult(encodedSignatures.ByteArrayToHexStringWithPrefix());
}

public Task<string> SessionImageHash(Dictionary<string, object> parameters)
{
var sessionTopologyJson = parameters["sessionTopology"].ToString();
var topology = SessionsTopology.FromJson(sessionTopologyJson);

return Task.FromResult(topology.ImageHash());
}

public Task<string> SessionExplicitAdd(Dictionary<string, object> parameters)
{
var explicitSessionJson = parameters["explicitSession"].ToString();
var sessionTopologyJson = parameters["sessionTopology"].ToString();

var explicitSession = SessionPermissions.FromJson(explicitSessionJson);
var sessionTopology = SessionsTopology.FromJson(sessionTopologyJson);

var existingPermission = sessionTopology.FindLeaf<PermissionLeaf>(leaf =>
leaf.permissions.signer.Equals(explicitSession.signer));

if (existingPermission != null)
throw new Exception("Session already exists.");

var newTopology = sessionTopology.AddExplicitSession(explicitSession);
return Task.FromResult(newTopology.JsonSerialize());
}

public Task<string> SessionExplicitRemove(Dictionary<string, object> parameters)
{
var explicitSessionAddress = new Address((string)parameters["explicitSession"]);
var sessionTopology = SessionsTopology.FromJson(parameters["sessionTopology"].ToString());
var newTopology = sessionTopology.RemoveExplicitSession(explicitSessionAddress);

return Task.FromResult(newTopology.JsonSerialize());
}

public Task<string> SessionImplicitAddBlacklistAddress(Dictionary<string, object> parameters)
{
var blacklistAddress = new Address((string)parameters["blacklistAddress"]);
var sessionTopologyJson = parameters["sessionTopology"].ToString();

var sessionsTopology = SessionsTopology.FromJson(sessionTopologyJson);
sessionsTopology.AddToImplicitBlacklist(blacklistAddress);

return Task.FromResult(sessionsTopology.JsonSerialize());
}

public Task<string> SessionImplicitRemoveBlacklistAddress(Dictionary<string, object> parameters)
{
var address = new Address((string)parameters["address"]);
var sessionTopology = SessionsTopology.FromJson(parameters["sessionTopology"].ToString());
sessionTopology.RemoveFromImplicitBlacklist(address);

return Task.FromResult(sessionTopology.JsonSerialize());
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Sequence.EcosystemWallet.Primitives;
using Sequence.EcosystemWallet.Utils;
using Sequence.Utils;
using UnityEngine;

namespace Sequence.EcosystemWallet.IntegrationTests
{
public class SignatureTests
{
public Task<string> SignatureEncode(Dictionary<string, object> parameters)
{
var input = parameters["input"].ToString();
var signatures = parameters["signatures"].ToString();
var noChainId = !parameters.TryGetValue("chainId", out var chainIdValue) || !(bool)chainIdValue;
var checkpointerData = parameters.TryGetValue("checkpointerData", out var checkpointerDataValue) ?
checkpointerDataValue.ToString().HexStringToByteArray() : null;

return Task.FromResult(SignatureUtils.EncodeSignatureFromInput(input, signatures, noChainId, checkpointerData));
}

public Task<string> SignatureDecode(Dictionary<string, object> parameters)
{
var encodedSignature = parameters["signature"].ToString().HexStringToByteArray();
var signature = RawSignature.Decode(encodedSignature);

return Task.FromResult(signature.ToJson());
}

public Task<string> SignatureConcat(Dictionary<string, object> parameters)
{
var signatures = parameters.GetArray<string>("signatures");
var decoded = signatures.Select(signature =>
RawSignature.Decode(signature.HexStringToByteArray())).ToArray();

var parentSignature = decoded[0];
parentSignature.suffix = decoded.Slice(1);
var encoded = parentSignature.Encode();

return Task.FromResult(encoded.ByteArrayToHexStringWithPrefix());
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading