Skip to content

Commit

Permalink
Savepoint
Browse files Browse the repository at this point in the history
  • Loading branch information
skibitsky committed Sep 28, 2024
1 parent f5c054d commit eecc8f0
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 46 deletions.
49 changes: 4 additions & 45 deletions .idea/.idea.Reown/.idea/workspace.xml

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

50 changes: 49 additions & 1 deletion src/Reown.Sign/Runtime/Models/Cacao/CacaoObject.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;
Expand Down Expand Up @@ -49,7 +50,11 @@ public string FormatMessage()
? $"Resources:\n{string.Join('\n', Payload.Resources.Select((resource) => $"- {resource}"))}"
: null;

//TODO decode recaps and add to the statement
if (ReCapUtils.TryGetRecapFromResources(Payload.Resources, out var recapStr))
{
var decoded = ReCapUtils.DecodeRecap(recapStr);
statement = FormatStatementFromRecap(decoded, statement);
}

var message = string.Join('\n', new[]
{
Expand All @@ -68,5 +73,48 @@ public string FormatMessage()

return message;
}

public string FormatStatementFromRecap(ReCap recap, string statement = "")
{
ReCapUtils.ValidateRecap(recap);

const string statementBase = "I further authorize the stated URI to perform the following actions on my behalf: ";

if (statement.Contains(statementBase))
return statement;

var statementForRecap = new List<string>();
var currentCounter = 0;
foreach (var resource in recap.Att.Keys)
{
var actions = (recap.Att[resource] as Dictionary<string, object>)!.Keys.Select(ability => new
{
Ability = ability.Split("/")[0],
Action = ability.Split("/")[1]
});

actions = actions.OrderBy(action => action.Action);
var uniqueAbilities = new Dictionary<string, List<string>>();
foreach (var action in actions)
{
if (!uniqueAbilities.ContainsKey(action.Ability))
uniqueAbilities[action.Ability] = new List<string>();

uniqueAbilities[action.Ability].Add(action.Action);
}

var abilities = uniqueAbilities.Keys.Select(ability =>
{
currentCounter++;
return $"({currentCounter}) '{ability}': '{string.Join("', '", uniqueAbilities[ability])}' for '{resource}'.";
});

statementForRecap.Add(string.Join(", ", abilities).Replace(".,", "."));
}

var recapStatement = string.Join(" ", statementForRecap);
recapStatement = $"{statementBase}{recapStatement}";
return $"{statement} {recapStatement}";
}
}
}
3 changes: 3 additions & 0 deletions src/Reown.Sign/Runtime/Utils/SignatureUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ public static async Task<bool> VerifySignature(
string chainId,
string projectId)
{
if (string.IsNullOrWhiteSpace(cacaoSignature.S))
throw new ArgumentException("VerifySignature Failed: CacaoSignature S is null or empty");

return cacaoSignature.T switch
{
CacaoSignatureType.Eip191 => IsValidEip191Signature(address, reconstructedMessage, cacaoSignature.S),
Expand Down
86 changes: 86 additions & 0 deletions test/Reown.Sign.Test/SignatureTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using Reown.Sign.Models.Cacao;
using Reown.Sign.Utils;
using Reown.TestUtils;
using Xunit;

namespace Reown.Sign.Test;

public class SignatureTests
{
public const string ChainId = "eip155:1";
public const string Address = "0x2faf83c542b68f1b4cdc0e770e8cb9f567b08f71";

private readonly string _projectId = TestValues.TestProjectId;

private readonly string _reconstructedMessage = """
localhost wants you to sign in with your Ethereum account:
0x2faf83c542b68f1b4cdc0e770e8cb9f567b08f71
URI: http://localhost:3000/
Version: 1
Chain ID: 1
Nonce: 1665443015700
Issued At: 2022-10-10T23:03:35.700Z
Expiration Time: 2022-10-11T23:03:35.700Z
""".Replace("\r", "");

[Fact] [Trait("Category", "integration")]
public async Task VerifySignature_WithValidEip1271Signature_ReturnsTrue()
{
var signature = new CacaoSignature(CacaoSignatureType.Eip1271,
"0xc1505719b2504095116db01baaf276361efd3a73c28cf8cc28dabefa945b8d536011289ac0a3b048600c1e692ff173ca944246cf7ceb319ac2262d27b395c82b1c");

var isValid =
await SignatureUtils.VerifySignature(Address, _reconstructedMessage, signature, ChainId, _projectId);

Assert.True(isValid);
}

[Fact] [Trait("Category", "integration")]
public async Task VerifySignature_WithInvalidEip1271Signature_ReturnsFalse()
{
var signature = new CacaoSignature(CacaoSignatureType.Eip1271,
"0xdead5719b2504095116db01baaf276361efd3a73c28cf8cc28dabefa945b8d536011289ac0a3b048600c1e692ff173ca944246cf7ceb319ac2262d27b395c82b1c");

var isValid =
await SignatureUtils.VerifySignature(Address, _reconstructedMessage, signature, ChainId, _projectId);

Assert.False(isValid);
}

[Theory]
[Trait("Category", "integration")]
[InlineData(CacaoSignatureType.Eip191)]
[InlineData(CacaoSignatureType.Eip1271)]
public async Task VerifySignature_WithEmptySignature_ThrowsArgumentException(CacaoSignatureType signatureType)
{
var signature = new CacaoSignature(signatureType, "");

await Assert.ThrowsAsync<ArgumentException>(async () =>
await SignatureUtils.VerifySignature(Address, _reconstructedMessage, signature, ChainId, _projectId));
}

[Fact] [Trait("Category", "integration")]
public async Task VerifySignature_WithInvalidEip191Signature_ReturnsFalse()
{
var signature = new CacaoSignature(CacaoSignatureType.Eip191,
"0xdead5719b2504095116db01baaf276361efd3a73c28cf8cc28dabefa945b8d536011289ac0a3b048600c1e692ff173ca944246cf7ceb319ac2262d27b395c82b1c");

var isValid =
await SignatureUtils.VerifySignature(Address, _reconstructedMessage, signature, ChainId, _projectId);

Assert.False(isValid);
}

[Theory]
[Trait("Category", "integration")]
[InlineData(CacaoSignatureType.Eip191)]
[InlineData(CacaoSignatureType.Eip1271)]
public async Task VerifySignature_WithNullSignature_ThrowsArgumentException(CacaoSignatureType signatureType)
{
var signature = new CacaoSignature(signatureType, null);

await Assert.ThrowsAsync<ArgumentException>(async () =>
await SignatureUtils.VerifySignature(Address, _reconstructedMessage, signature, ChainId, _projectId));
}
}

0 comments on commit eecc8f0

Please sign in to comment.