From d882f9cfb1c57f639ecc0047fc27d99fdecdbe59 Mon Sep 17 00:00:00 2001 From: Quinn Purdy <49766546+BellringerQuinn@users.noreply.github.com> Date: Tue, 17 Dec 2024 13:55:44 -0500 Subject: [PATCH] Apply a timeshift from the server when initializing IntentSender to better resolve time out of sync error (#219) --- .../WaaS/Tests/IntentSenderTests.cs | 15 ++++++++++++ .../DataTypes/ParameterTypes/IntentPayload.cs | 10 ++++---- .../SequenceSDK/EmbeddedWallet/HttpClient.cs | 24 +++++++++++++++++++ .../SequenceSDK/EmbeddedWallet/IHttpClient.cs | 3 +++ .../EmbeddedWallet/IntentSender.cs | 24 ++++++++++++++++--- 5 files changed, 68 insertions(+), 8 deletions(-) diff --git a/Assets/SequenceSDK/WaaS/Tests/IntentSenderTests.cs b/Assets/SequenceSDK/WaaS/Tests/IntentSenderTests.cs index ecb58cc9f..010fec625 100644 --- a/Assets/SequenceSDK/WaaS/Tests/IntentSenderTests.cs +++ b/Assets/SequenceSDK/WaaS/Tests/IntentSenderTests.cs @@ -164,6 +164,11 @@ public async Task SendRequest(string path, T args, Dictionary(responseJson); } + + public async Task GetTimeShift() + { + return TimeSpan.Zero; + } } private class MockHttpClientReturnsUnknownCode : IHttpClient @@ -177,6 +182,11 @@ public async Task SendRequest(string path, T args, Dictionary(responseJson); } + + public async Task GetTimeShift() + { + return TimeSpan.Zero; + } } private class MockHttpClientReturnsSuccessfulTransaction : IHttpClient @@ -190,6 +200,11 @@ public async Task SendRequest(string path, T args, Dictionary(responseJson); } + + public async Task GetTimeShift() + { + return TimeSpan.Zero; + } } [Serializable] diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/DataTypes/ParameterTypes/IntentPayload.cs b/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/DataTypes/ParameterTypes/IntentPayload.cs index ffc04857d..2e2dcd23e 100644 --- a/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/DataTypes/ParameterTypes/IntentPayload.cs +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/DataTypes/ParameterTypes/IntentPayload.cs @@ -11,15 +11,15 @@ namespace Sequence.EmbeddedWallet public class IntentPayload { public JObject data; - public uint expiresAt; - public uint issuedAt; + public ulong expiresAt; + public ulong issuedAt; public string name; public Signature[] signatures; public string version; [Preserve] [JsonConstructor] - public IntentPayload(string version, string name, uint expiresAt, uint issuedAt, JObject data, Signature[] signatures) + public IntentPayload(string version, string name, ulong expiresAt, ulong issuedAt, JObject data, Signature[] signatures) { this.version = version; this.name = name; @@ -29,7 +29,7 @@ public IntentPayload(string version, string name, uint expiresAt, uint issuedAt, this.signatures = signatures; } - public IntentPayload(string version, IntentType name, uint expiresAt, uint issuedAt, JObject data, Signature[] signatures) + public IntentPayload(string version, IntentType name, ulong expiresAt, ulong issuedAt, JObject data, Signature[] signatures) { this.version = version; this.name = IntentNames[name]; @@ -39,7 +39,7 @@ public IntentPayload(string version, IntentType name, uint expiresAt, uint issue this.signatures = signatures; } - public IntentPayload(string version, IntentType type, JObject data, Signature[] signatures, uint timeBeforeExpiryInSeconds = 30, uint currentTime = 0) + public IntentPayload(string version, IntentType type, JObject data, Signature[] signatures, uint timeBeforeExpiryInSeconds = 30, ulong currentTime = 0) { this.version = version; this.name = IntentNames[type]; diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/HttpClient.cs b/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/HttpClient.cs index 3a73b03a5..93445b3c6 100644 --- a/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/HttpClient.cs +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/HttpClient.cs @@ -238,6 +238,30 @@ public async Task SendRequest(string path, T args, [CanBeNull] Dictio } } + public async Task GetTimeShift() + { + UnityWebRequest request = UnityWebRequest.Get(_waasUrl.AppendTrailingSlashIfNeeded() + "status"); + request.method = UnityWebRequest.kHttpVerbGET; + + try + { + await request.SendWebRequest(); + DateTime serverTime = DateTime.Parse(request.GetResponseHeader("date")).ToUniversalTime(); + DateTime localTime = DateTime.UtcNow; + TimeSpan timeShift = serverTime - localTime; + return timeShift; + } + catch (Exception e) + { + Debug.LogError("Error getting time shift: " + e.Message); + return TimeSpan.Zero; + } + finally + { + request.Dispose(); + } + } + private string GetRequestErrorIfAvailable(UnityWebRequest request) { if (request.downloadHandler != null && request.downloadHandler.data != null) diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/IHttpClient.cs b/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/IHttpClient.cs index bca7225e9..06782aa61 100644 --- a/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/IHttpClient.cs +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/IHttpClient.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Threading.Tasks; using JetBrains.Annotations; @@ -8,5 +9,7 @@ public interface IHttpClient { public Task SendRequest(string path, T args, [CanBeNull] Dictionary headers = null, string overrideUrl = null); + + public Task GetTimeShift(); } } \ No newline at end of file diff --git a/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/IntentSender.cs b/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/IntentSender.cs index 59d921782..00762ea62 100644 --- a/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/IntentSender.cs +++ b/Packages/Sequence-Unity/Sequence/SequenceSDK/EmbeddedWallet/IntentSender.cs @@ -19,6 +19,8 @@ public class IntentSender : IIntentSender private int _waasProjectId; private string _waasVersion; private string _sessionId; + private TimeSpan _timeshift; + private bool _ready = false; private JsonSerializerSettings serializerSettings = new JsonSerializerSettings { @@ -33,6 +35,13 @@ public IntentSender(IHttpClient httpClient, Sequence.Wallet.IWallet sessionWalle _waasProjectId = waasProjectId; _waasVersion = waasVersion; _sessionId = IntentDataOpenSession.CreateSessionId(_sessionWallet.GetAddress()); + GetTimeShift().ConfigureAwait(false); + } + + private async Task GetTimeShift() + { + _timeshift = await _httpClient.GetTimeShift(); + _ready = true; } public async Task SendIntent(T2 args, IntentType type, uint timeBeforeExpiryInSeconds = 30, uint currentTime = 0) @@ -68,11 +77,11 @@ public async Task SendIntent(T2 args, IntentType type, uint timeBefore long currentTimeAccordingToIntent = 0; if (intentPayload is IntentPayload intent) { - currentTimeAccordingToIntent = intent.issuedAt; + currentTimeAccordingToIntent = (long)intent.issuedAt; } else if (intentPayload is RegisterSessionIntent registerSessionIntent) { - currentTimeAccordingToIntent = registerSessionIntent.intent.issuedAt; + currentTimeAccordingToIntent = (long)registerSessionIntent.intent.issuedAt; } else { @@ -116,8 +125,17 @@ private string AssemblePayloadJson(T args) return JsonConvert.SerializeObject(args, serializerSettings); } - private async Task AssembleIntentPayload(string payload, IntentType type, uint timeToLiveInSeconds, uint currentTime) + private async Task AssembleIntentPayload(string payload, IntentType type, uint timeToLiveInSeconds, ulong currentTime) { + while (!_ready) + { + await Task.Yield(); + } + + if (currentTime == 0) + { + currentTime = (ulong)DateTimeOffset.UtcNow.Add(_timeshift).ToUnixTimeSeconds(); + } JObject packet = JsonConvert.DeserializeObject(payload); IntentPayload toSign = new IntentPayload(_waasVersion, type, packet, null, timeToLiveInSeconds, currentTime); string toSignJson = JsonConvert.SerializeObject(toSign, serializerSettings);