Skip to content

Commit c9d7eec

Browse files
authored
Preprocess Typed Data JSON w/ >uint32 fields (#100)
1 parent 957b895 commit c9d7eec

File tree

3 files changed

+157
-2
lines changed

3 files changed

+157
-2
lines changed

Thirdweb.Tests/Thirdweb.Utils/Thirdweb.Utils.Tests.cs

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Numerics;
2+
using Newtonsoft.Json.Linq;
23

34
namespace Thirdweb.Tests.Utilities;
45

@@ -506,7 +507,7 @@ public async void ToJsonExternalWalletFriendly_ReturnsCorrectValue4()
506507
var verifyingContract = await pkWallet.GetAddress(); // doesn't matter here
507508
var typedDataRaw = EIP712.GetTypedDefinition_SmartAccount_AccountMessage("Account", "1", 137, verifyingContract);
508509
var json = Utils.ToJsonExternalWalletFriendly(typedDataRaw, msg);
509-
var jsonObject = Newtonsoft.Json.Linq.JObject.Parse(json);
510+
var jsonObject = JObject.Parse(json);
510511
var internalMsg = jsonObject.SelectToken("$.message.message");
511512
Assert.NotNull(internalMsg);
512513
Assert.Equal("0x01020304", internalMsg);
@@ -763,4 +764,106 @@ public async Task FetchGasFees_Celo()
763764
Assert.True(maxPrio > 0);
764765
Assert.Equal(maxFee, maxPrio);
765766
}
767+
768+
[Fact]
769+
public void PreprocessTypedDataJson_FormatsBigIntegers()
770+
{
771+
// Arrange
772+
var inputJson =
773+
/*lang=json,strict*/
774+
@"
775+
{
776+
""from"": 973250616940336452028326648501327235277017847475,
777+
""data"": ""0x"",
778+
""nested"": {
779+
""value"": 4294967295
780+
},
781+
""array"": [
782+
123,
783+
973250616940336452028326648501327235277017847475
784+
]
785+
}";
786+
787+
var expectedJson =
788+
/*lang=json,strict*/
789+
@"
790+
{
791+
""from"": ""973250616940336452028326648501327235277017847475"",
792+
""data"": ""0x"",
793+
""nested"": {
794+
""value"": 4294967295
795+
},
796+
""array"": [
797+
123,
798+
""973250616940336452028326648501327235277017847475""
799+
]
800+
}";
801+
802+
// Act
803+
var processedJson = Utils.PreprocessTypedDataJson(inputJson);
804+
805+
// Assert
806+
var expectedJObject = JObject.Parse(expectedJson);
807+
var processedJObject = JObject.Parse(processedJson);
808+
809+
Assert.Equal(expectedJObject, processedJObject);
810+
}
811+
812+
[Fact]
813+
public void PreprocessTypedDataJson_NoLargeNumbers_NoChange()
814+
{
815+
// Arrange
816+
var inputJson =
817+
/*lang=json,strict*/
818+
@"
819+
{
820+
""value"": 123,
821+
""nested"": {
822+
""value"": 456
823+
},
824+
""array"": [1, 2, 3]
825+
}";
826+
827+
// Act
828+
var processedJson = Utils.PreprocessTypedDataJson(inputJson);
829+
var expectedJObject = JObject.Parse(inputJson);
830+
var processedJObject = JObject.Parse(processedJson);
831+
832+
// Assert
833+
Assert.Equal(expectedJObject, processedJObject);
834+
}
835+
836+
[Fact]
837+
public void PreprocessTypedDataJson_NestedLargeNumbers()
838+
{
839+
// Arrange
840+
var inputJson =
841+
/*lang=json,strict*/
842+
@"
843+
{
844+
""nested"": {
845+
""value"": 973250616940336452028326648501327235277017847475
846+
},
847+
""array"": [123, 973250616940336452028326648501327235277017847475]
848+
}";
849+
850+
var expectedJson =
851+
/*lang=json,strict*/
852+
@"
853+
{
854+
""nested"": {
855+
""value"": ""973250616940336452028326648501327235277017847475""
856+
},
857+
""array"": [123, ""973250616940336452028326648501327235277017847475""]
858+
}";
859+
860+
// Act
861+
var processedJson = Utils.PreprocessTypedDataJson(inputJson);
862+
863+
// Assert
864+
var expectedJObject = JObject.Parse(expectedJson);
865+
var processedJObject = JObject.Parse(processedJson);
866+
867+
Assert.Equal(expectedJObject, processedJObject);
868+
}
766869
}

Thirdweb/Thirdweb.Utils/Utils.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -953,4 +953,54 @@ public static async Task<SocialProfiles> GetSocialProfiles(ThirdwebClient client
953953

954954
return new SocialProfiles(deserializedResponse.Data);
955955
}
956+
957+
/// <summary>
958+
/// Preprocesses the typed data JSON to stringify large numbers.
959+
/// </summary>
960+
/// <param name="json">The typed data JSON.</param>
961+
/// <returns>The preprocessed typed data JSON.</returns>
962+
public static string PreprocessTypedDataJson(string json)
963+
{
964+
var jObject = JObject.Parse(json);
965+
966+
static void StringifyLargeNumbers(JToken token)
967+
{
968+
if (token is JObject obj)
969+
{
970+
foreach (var property in obj.Properties().ToList())
971+
{
972+
StringifyLargeNumbers(property.Value);
973+
}
974+
}
975+
else if (token is JArray array)
976+
{
977+
foreach (var item in array.ToList())
978+
{
979+
StringifyLargeNumbers(item);
980+
}
981+
}
982+
else if (token is JValue value)
983+
{
984+
if (value.Type == JTokenType.Integer)
985+
{
986+
try
987+
{
988+
var bigInt = BigInteger.Parse(value.ToString());
989+
if (bigInt > new BigInteger(uint.MaxValue) || bigInt < BigInteger.Zero)
990+
{
991+
value.Replace(bigInt.ToString());
992+
}
993+
}
994+
catch (FormatException)
995+
{
996+
// Skip if the value isn't properly formatted as an integer
997+
}
998+
}
999+
}
1000+
}
1001+
1002+
StringifyLargeNumbers(jObject);
1003+
1004+
return jObject.ToString();
1005+
}
9561006
}

Thirdweb/Thirdweb.Wallets/InAppWallet/EcosystemWallet/EcosystemWallet.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,9 +776,11 @@ public async Task<string> SignTypedDataV4(string json)
776776
throw new ArgumentNullException(nameof(json), "Json to sign cannot be null.");
777777
}
778778

779+
var processedJson = Utils.PreprocessTypedDataJson(json);
780+
779781
var url = $"{ENCLAVE_PATH}/sign-typed-data";
780782

781-
var requestContent = new StringContent(json, Encoding.UTF8, "application/json");
783+
var requestContent = new StringContent(processedJson, Encoding.UTF8, "application/json");
782784

783785
var response = await this.HttpClient.PostAsync(url, requestContent).ConfigureAwait(false);
784786
_ = response.EnsureSuccessStatusCode();

0 commit comments

Comments
 (0)