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

fix: SessionRequestEvents json error #193

Merged
merged 2 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
177 changes: 177 additions & 0 deletions Tests/WalletConnectSharp.Sign.Test/SignTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,62 @@ public class TestRequest2
public int y;
}

// represents array of strings requests, similar to personal_sign
[RpcMethod("complex_test_method")] [RpcRequestOptions(Clock.ONE_MINUTE, 99990)]
public class ComplexTestRequest : List<string>
{
public ComplexTestRequest()
{
}

public ComplexTestRequest(params string[] args) : base(args)
{
}

public int A
{
get
{
if (Count != 2 || !int.TryParse(this[0], out var a))
{
return 0;
}

return a;
}
}

public int B
{
get
{
if (Count != 2 || !int.TryParse(this[1], out var b))
{
return 0;
}

return b;
}
}
}

// represents array of objects requests, similar to eth_sendTransaction
[RpcMethod("complex_test_method_2")] [RpcRequestOptions(Clock.ONE_MINUTE, 99991)] [RpcResponseOptions(Clock.ONE_MINUTE, 99992)]
public class ComplexTestRequest2 : List<TestRequest2>
{
public ComplexTestRequest2()
{
}

public ComplexTestRequest2(params TestRequest2[] args) : base(args)
{
}

public string X => this.FirstOrDefault()?.x ?? string.Empty;

public int Y => this.FirstOrDefault()?.y ?? -1;
}

[RpcResponseOptions(Clock.ONE_MINUTE, 99999)]
public class TestResponse
{
Expand Down Expand Up @@ -387,6 +443,127 @@ public async Task TestTwoUniqueSessionRequestResponse()

Assert.True(responseReturned2);
}

[Fact] [Trait("Category", "integration")]
public async Task TestTwoUniqueComplexSessionRequestResponse()
{
await _cryptoFixture.WaitForClientsReady();

var testAddress = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045";
var testMethod = "complex_test_method";
var testMethod2 = "complex_test_method_2";

var dappConnectOptions = new ConnectOptions()
{
RequiredNamespaces = new RequiredNamespaces()
{
{
"eip155", new ProposedNamespace()
{
Methods = new[]
{
testMethod,
testMethod2
},
Chains = new[]
{
"eip155:1",
"eip155:10"
},
Events = new[]
{
"chainChanged",
"accountsChanged"
}
}
}
}
};

var dappClient = ClientA;
var connectData = await dappClient.Connect(dappConnectOptions);

var walletClient = ClientB;
var proposal = await walletClient.Pair(connectData.Uri);

var approveData = await walletClient.Approve(proposal, testAddress);

var sessionData = await connectData.Approval;
await approveData.Acknowledged();

var rnd = new Random();
var a = rnd.Next(100);
var b = rnd.Next(100);
var x = rnd.NextStrings(AllowedChars, (Math.Min(a, b), Math.Max(a, b)), 1).First();
var y = x.Length;

var testData = new ComplexTestRequest(a.ToString(), b.ToString());
var testData2 = new ComplexTestRequest2(new TestRequest2()
{
x = x, y = y
});

var pending = new TaskCompletionSource<int>();

// Step 1. Setup event listener for request

// The wallet client will listen for the request with the "test_method" rpc method
walletClient.Engine.SessionRequestEvents<ComplexTestRequest, TestResponse>()
.OnRequest += (requestData) =>
{
var request = requestData.Request;
var data = request.Params;

requestData.Response = new TestResponse()
{
result = data.A * data.B
};

return Task.CompletedTask;
};

// The wallet client will listen for the request with the "test_method" rpc method
walletClient.Engine.SessionRequestEvents<ComplexTestRequest2, bool>()
.OnRequest += (requestData) =>
{
var request = requestData.Request;
var data = request.Params;

requestData.Response = data.X.Length == data.Y;

return Task.CompletedTask;
};

// The dapp client will listen for the response
// Normally, we wouldn't do this and just rely on the return value
// from the dappClient.Engine.Request function call (the response Result or throws an Exception)
// We do it here for the sake of testing
dappClient.Engine.SessionRequestEvents<ComplexTestRequest, TestResponse>()
.FilterResponses((r) => r.Topic == sessionData.Topic)
.OnResponse += (responseData) =>
{
var response = responseData.Response;

var data = response.Result;

pending.TrySetResult(data.result);

return Task.CompletedTask;
};

// 2. Send the request from the dapp client
var responseReturned = await dappClient.Engine.Request<ComplexTestRequest, TestResponse>(sessionData.Topic, testData);
var responseReturned2 = await dappClient.Engine.Request<ComplexTestRequest2, bool>(sessionData.Topic, testData2);

// 3. Wait for the response from the event listener
var eventResult = await pending.Task.WithTimeout(TimeSpan.FromSeconds(5));

Assert.Equal(eventResult, a * b);
Assert.Equal(eventResult, testData.A * testData.B);
Assert.Equal(eventResult, responseReturned.result);

Assert.True(responseReturned2);
}

[Fact, Trait("Category", "integration")]
public async Task TestTwoUniqueSessionRequestResponseUsingAddressProviderDefaults()
Expand Down
31 changes: 20 additions & 11 deletions WalletConnectSharp.Core/Controllers/TypedMessageHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,23 +98,32 @@ public async Task<DisposeHandlerToken> HandleMessageType<T, TR>(Func<string, Jso

async void RequestCallback(object sender, MessageEvent e)
{
if (requestCallback == null || Disposed)
try
{
return;
}
if (requestCallback == null || Disposed)
{
return;
}

var topic = e.Topic;
var message = e.Message;
var topic = e.Topic;
var message = e.Message;

var options = DecodeOptionForTopic(topic);

if (options == null && !await this.Core.Crypto.HasKeys(topic)) return;
var options = DecodeOptionForTopic(topic);

if (options == null && !await Core.Crypto.HasKeys(topic))
{
return;
}

var payload = await this.Core.Crypto.Decode<JsonRpcRequest<T>>(topic, message, options);
var payload = await Core.Crypto.Decode<JsonRpcRequest<T>>(topic, message, options);

(await this.Core.History.JsonRpcHistoryOfType<T, TR>()).Set(topic, payload, null);
(await Core.History.JsonRpcHistoryOfType<T, TR>()).Set(topic, payload, null);

await requestCallback(topic, payload);
await requestCallback(topic, payload);
}
catch (JsonException)
{
}
}

async void ResponseCallback(object sender, MessageEvent e)
Expand Down
31 changes: 17 additions & 14 deletions WalletConnectSharp.Core/Models/Verify/Verifier.cs
Original file line number Diff line number Diff line change
@@ -1,35 +1,38 @@
using System.Net;
using Newtonsoft.Json;
using WalletConnectSharp.Common.Utils;
using Newtonsoft.Json;
using WalletConnectSharp.Common.Logging;

namespace WalletConnectSharp.Core.Models.Verify;

public class Verifier
public sealed class Verifier : IDisposable
{
public const string VerifyServer = "https://verify.walletconnect.com";

public CancellationTokenSource CancellationTokenSource { get; }
private const string VerifyServer = "https://verify.walletconnect.com";

public Verifier()
private readonly HttpClient _client = new()
{
this.CancellationTokenSource = new CancellationTokenSource(Clock.AsTimeSpan(Clock.FIVE_SECONDS));
}
Timeout = TimeSpan.FromSeconds(5)
};

public async Task<string> Resolve(string attestationId)
{
try
{
using HttpClient client = new HttpClient();
var url = $"{VerifyServer}/attestation/{attestationId}";
var results = await client.GetStringAsync(url);
WCLogger.Log($"[Verifier] Resolving attestation {attestationId} from {url}");
var results = await _client.GetStringAsync(url);
WCLogger.Log($"[Verifier] Resolved attestation. Results: {results}");

var verifiedContext = JsonConvert.DeserializeObject<VerifiedContext>(results);

return verifiedContext != null ? verifiedContext.Origin : "";
return verifiedContext != null ? verifiedContext.Origin : string.Empty;
}
catch
{
return "";
return string.Empty;
}
}

public void Dispose()
{
_client?.Dispose();
}
}
1 change: 1 addition & 0 deletions WalletConnectSharp.Core/WalletConnectCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ protected virtual void Dispose(bool disposing)
MessageHandler?.Dispose();
Expirer?.Dispose();
Pairing?.Dispose();
Verify?.Dispose();
}

Disposed = true;
Expand Down
Loading