-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from CirclesUBI/table-schema-from-solidity
Table schema from solidity
- Loading branch information
Showing
98 changed files
with
3,143 additions
and
1,435,754 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
.container-state | ||
.state | ||
.container-state | ||
.spaceneth-state | ||
circles-contracts | ||
circles-contracts-v2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Nethermind.Numerics.Int256" Version="1.2.0" /> | ||
<PackageReference Include="Nethermind.ReferenceAssemblies" Version="1.25.4" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\Circles.Index.Common\Circles.Index.Common.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Reference Include="Npgsql"> | ||
<HintPath>..\..\..\..\.nuget\packages\npgsql\8.0.2\lib\net8.0\Npgsql.dll</HintPath> | ||
</Reference> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
using System.Numerics; | ||
using Circles.Index.Common; | ||
using Nethermind.Core.Crypto; | ||
|
||
namespace Circles.Index.CirclesV1; | ||
|
||
public class DatabaseSchema : IDatabaseSchema | ||
{ | ||
public ISchemaPropertyMap SchemaPropertyMap { get; } = new SchemaPropertyMap(); | ||
|
||
public IEventDtoTableMap EventDtoTableMap { get; } = new EventDtoTableMap(); | ||
|
||
public static readonly EventSchema HubTransfer = EventSchema.FromSolidity("CrcV1", | ||
"event HubTransfer(address indexed from, address indexed to, uint256 amount)"); | ||
|
||
public static readonly EventSchema Signup = EventSchema.FromSolidity("CrcV1", | ||
"event Signup(address indexed user, address indexed token)"); | ||
|
||
public static readonly EventSchema OrganizationSignup = EventSchema.FromSolidity("CrcV1", | ||
"event OrganizationSignup(address indexed organization)"); | ||
|
||
public static readonly EventSchema Trust = EventSchema.FromSolidity("CrcV1", | ||
"event Trust(address indexed canSendTo, address indexed user, uint256 limit)"); | ||
|
||
public static readonly EventSchema Transfer = new("CrcV1", "Transfer", | ||
Keccak.Compute("Transfer(address,address,uint256)"), | ||
[ | ||
new("blockNumber", ValueTypes.Int, true), | ||
new("timestamp", ValueTypes.Int, true), | ||
new("transactionIndex", ValueTypes.Int, true), | ||
new("logIndex", ValueTypes.Int, true), | ||
new("tokenAddress", ValueTypes.Address, true), | ||
new("from", ValueTypes.Address, true), | ||
new("to", ValueTypes.Address, true), | ||
new("amount", ValueTypes.BigInt, false) | ||
]); | ||
|
||
public IDictionary<(string Namespace, string Table), EventSchema> Tables { get; } = | ||
new Dictionary<(string Namespace, string Table), EventSchema> | ||
{ | ||
{ | ||
("CrcV1", "HubTransfer"), | ||
HubTransfer | ||
}, | ||
{ | ||
("CrcV1", "Signup"), | ||
Signup | ||
}, | ||
{ | ||
("CrcV1", "OrganizationSignup"), | ||
OrganizationSignup | ||
}, | ||
{ | ||
("CrcV1", "Trust"), | ||
Trust | ||
}, | ||
{ | ||
("CrcV1", "Transfer"), | ||
Transfer | ||
} | ||
}; | ||
|
||
public DatabaseSchema() | ||
{ | ||
EventDtoTableMap.Add<Signup>(("CrcV1", "Signup")); | ||
SchemaPropertyMap.Add(("CrcV1", "Signup"), | ||
new Dictionary<string, Func<Signup, object?>> | ||
{ | ||
{ "blockNumber", e => e.BlockNumber }, | ||
{ "timestamp", e => e.Timestamp }, | ||
{ "transactionIndex", e => e.TransactionIndex }, | ||
{ "logIndex", e => e.LogIndex }, | ||
{ "transactionHash", e => e.TransactionHash }, | ||
{ "user", e => e.User }, | ||
{ "token", e => e.Token } | ||
}); | ||
|
||
EventDtoTableMap.Add<OrganizationSignup>(("CrcV1", "OrganizationSignup")); | ||
SchemaPropertyMap.Add(("CrcV1", "OrganizationSignup"), | ||
new Dictionary<string, Func<OrganizationSignup, object?>> | ||
{ | ||
{ "blockNumber", e => e.BlockNumber }, | ||
{ "timestamp", e => e.Timestamp }, | ||
{ "transactionIndex", e => e.TransactionIndex }, | ||
{ "logIndex", e => e.LogIndex }, | ||
{ "transactionHash", e => e.TransactionHash }, | ||
{ "organization", e => e.Organization } | ||
}); | ||
|
||
EventDtoTableMap.Add<Trust>(("CrcV1", "Trust")); | ||
SchemaPropertyMap.Add(("CrcV1", "Trust"), | ||
new Dictionary<string, Func<Trust, object?>> | ||
{ | ||
{ "blockNumber", e => e.BlockNumber }, | ||
{ "timestamp", e => e.Timestamp }, | ||
{ "transactionIndex", e => e.TransactionIndex }, | ||
{ "logIndex", e => e.LogIndex }, | ||
{ "transactionHash", e => e.TransactionHash }, | ||
{ "canSendTo", e => e.CanSendTo }, | ||
{ "user", e => e.User }, | ||
{ "limit", e => e.Limit } | ||
}); | ||
|
||
EventDtoTableMap.Add<HubTransfer>(("CrcV1", "HubTransfer")); | ||
SchemaPropertyMap.Add(("CrcV1", "HubTransfer"), | ||
new Dictionary<string, Func<HubTransfer, object?>> | ||
{ | ||
{ "blockNumber", e => e.BlockNumber }, | ||
{ "timestamp", e => e.Timestamp }, | ||
{ "transactionIndex", e => e.TransactionIndex }, | ||
{ "logIndex", e => e.LogIndex }, | ||
{ "transactionHash", e => e.TransactionHash }, | ||
{ "from", e => e.From }, | ||
{ "to", e => e.To }, | ||
{ "amount", e => (BigInteger)e.Amount } | ||
}); | ||
|
||
EventDtoTableMap.Add<Transfer>(("CrcV1", "Transfer")); | ||
SchemaPropertyMap.Add(("CrcV1", "Transfer"), | ||
new Dictionary<string, Func<Transfer, object?>> | ||
{ | ||
{ "blockNumber", e => e.BlockNumber }, | ||
{ "timestamp", e => e.Timestamp }, | ||
{ "transactionIndex", e => e.TransactionIndex }, | ||
{ "logIndex", e => e.LogIndex }, | ||
{ "transactionHash", e => e.TransactionHash }, | ||
{ "tokenAddress", e => e.TokenAddress }, | ||
{ "from", e => e.From }, | ||
{ "to", e => e.To }, | ||
{ "amount", e => (BigInteger)e.Value } | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
using Circles.Index.Common; | ||
using Nethermind.Int256; | ||
|
||
namespace Circles.Index.CirclesV1; | ||
|
||
public record Signup( | ||
long BlockNumber, | ||
long Timestamp, | ||
int TransactionIndex, | ||
int LogIndex, | ||
string TransactionHash, | ||
string User, | ||
string Token) : IIndexEvent; | ||
|
||
public record OrganizationSignup( | ||
long BlockNumber, | ||
long Timestamp, | ||
int TransactionIndex, | ||
int LogIndex, | ||
string TransactionHash, | ||
string Organization) : IIndexEvent; | ||
|
||
public record Trust( | ||
long BlockNumber, | ||
long Timestamp, | ||
int TransactionIndex, | ||
int LogIndex, | ||
string TransactionHash, | ||
string User, | ||
string CanSendTo, | ||
int Limit) : IIndexEvent; | ||
|
||
public record HubTransfer( | ||
long BlockNumber, | ||
long Timestamp, | ||
int TransactionIndex, | ||
int LogIndex, | ||
string TransactionHash, | ||
string From, | ||
string To, | ||
UInt256 Amount) : IIndexEvent; | ||
|
||
public record Transfer( | ||
long BlockNumber, | ||
long Timestamp, | ||
int TransactionIndex, | ||
int LogIndex, | ||
string TransactionHash, | ||
string TokenAddress, | ||
string From, | ||
string To, | ||
UInt256 Value) : IIndexEvent; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
using System.Collections.Concurrent; | ||
using System.Globalization; | ||
using Circles.Index.Common; | ||
using Nethermind.Core; | ||
using Nethermind.Core.Extensions; | ||
using Nethermind.Int256; | ||
|
||
namespace Circles.Index.CirclesV1; | ||
|
||
public class LogParser(Address v1HubAddress) : ILogParser | ||
{ | ||
public static readonly ConcurrentDictionary<Address, object?> CirclesTokenAddresses = new(); | ||
|
||
public IEnumerable<IIndexEvent> ParseLog(Block block, TxReceipt receipt, LogEntry log, int logIndex) | ||
{ | ||
List<IIndexEvent> events = new(); | ||
if (log.Topics.Length == 0) | ||
{ | ||
return events; | ||
} | ||
|
||
var topic = log.Topics[0]; | ||
if (topic == DatabaseSchema.Transfer.Topic && | ||
CirclesTokenAddresses.ContainsKey(log.LoggersAddress)) | ||
{ | ||
events.Add(Erc20Transfer(block, receipt, log, logIndex)); | ||
} | ||
|
||
if (log.LoggersAddress == v1HubAddress) | ||
{ | ||
if (topic == DatabaseSchema.Signup.Topic) | ||
{ | ||
var signupEvents = CrcSignup(block, receipt, log, logIndex); | ||
foreach (var signupEvent in signupEvents) | ||
{ | ||
events.Add(signupEvent); | ||
} | ||
} | ||
|
||
if (topic == DatabaseSchema.OrganizationSignup.Topic) | ||
{ | ||
events.Add(CrcOrgSignup(block, receipt, log, logIndex)); | ||
} | ||
|
||
if (topic == DatabaseSchema.HubTransfer.Topic) | ||
{ | ||
events.Add(CrcHubTransfer(block, receipt, log, logIndex)); | ||
} | ||
|
||
if (topic == DatabaseSchema.Trust.Topic) | ||
{ | ||
events.Add(CrcTrust(block, receipt, log, logIndex)); | ||
} | ||
} | ||
|
||
return events; | ||
} | ||
|
||
private IIndexEvent Erc20Transfer(Block block, TxReceipt receipt, LogEntry log, int logIndex) | ||
{ | ||
string from = "0x" + log.Topics[1].ToString().Substring(Consts.AddressEmptyBytesPrefixLength); | ||
string to = "0x" + log.Topics[2].ToString().Substring(Consts.AddressEmptyBytesPrefixLength); | ||
UInt256 value = new(log.Data, true); | ||
|
||
return new Transfer( | ||
receipt.BlockNumber | ||
, (long)block.Timestamp | ||
, receipt.Index | ||
, logIndex | ||
, receipt.TxHash!.ToString() | ||
, log.LoggersAddress.ToString(true, false) | ||
, from | ||
, to | ||
, value); | ||
} | ||
|
||
private IIndexEvent CrcOrgSignup(Block block, TxReceipt receipt, LogEntry log, int logIndex) | ||
{ | ||
string org = "0x" + log.Topics[1].ToString().Substring(Consts.AddressEmptyBytesPrefixLength); | ||
|
||
return new OrganizationSignup( | ||
receipt.BlockNumber | ||
, (long)block.Timestamp | ||
, receipt.Index | ||
, logIndex | ||
, receipt.TxHash!.ToString() | ||
, org); | ||
} | ||
|
||
private IIndexEvent CrcTrust(Block block, TxReceipt receipt, LogEntry log, int logIndex) | ||
{ | ||
string user = "0x" + log.Topics[1].ToString().Substring(Consts.AddressEmptyBytesPrefixLength); | ||
string canSendTo = "0x" + log.Topics[2].ToString().Substring(Consts.AddressEmptyBytesPrefixLength); | ||
int limit = new UInt256(log.Data, true).ToInt32(CultureInfo.InvariantCulture); | ||
|
||
return new Trust( | ||
receipt.BlockNumber | ||
, (long)block.Timestamp | ||
, receipt.Index | ||
, logIndex | ||
, receipt.TxHash!.ToString() | ||
, user | ||
, canSendTo | ||
, limit); | ||
} | ||
|
||
private IIndexEvent CrcHubTransfer(Block block, TxReceipt receipt, LogEntry log, int logIndex) | ||
{ | ||
string from = "0x" + log.Topics[1].ToString().Substring(Consts.AddressEmptyBytesPrefixLength); | ||
string to = "0x" + log.Topics[2].ToString().Substring(Consts.AddressEmptyBytesPrefixLength); | ||
UInt256 amount = new(log.Data, true); | ||
|
||
return new HubTransfer( | ||
receipt.BlockNumber | ||
, (long)block.Timestamp | ||
, receipt.Index | ||
, logIndex | ||
, receipt.TxHash!.ToString() | ||
, from | ||
, to | ||
, amount); | ||
} | ||
|
||
private IEnumerable<IIndexEvent> CrcSignup(Block block, TxReceipt receipt, LogEntry log, int logIndex) | ||
{ | ||
string user = "0x" + log.Topics[1].ToString().Substring(Consts.AddressEmptyBytesPrefixLength); | ||
Address tokenAddress = new Address(log.Data.Slice(12)); | ||
|
||
IIndexEvent signupEvent = new Signup( | ||
receipt.BlockNumber | ||
, (long)block.Timestamp | ||
, receipt.Index | ||
, logIndex | ||
, receipt.TxHash!.ToString() | ||
, user | ||
, tokenAddress.ToString(true, false)); | ||
|
||
CirclesTokenAddresses.TryAdd(tokenAddress, null); | ||
|
||
IIndexEvent? signupBonusEvent = null; | ||
|
||
// Every signup comes together with an Erc20 transfer (the signup bonus). | ||
// Since the signup event is emitted after the transfer, the token wasn't known yet when we encountered the transfer. | ||
// Look for the transfer again and process it. | ||
for (int i = 0; i < receipt.Logs!.Length; i++) | ||
{ | ||
var repeatedLogEntry = receipt.Logs[i]; | ||
if (repeatedLogEntry.LoggersAddress != tokenAddress) | ||
{ | ||
continue; | ||
} | ||
|
||
if (repeatedLogEntry.Topics[0] == DatabaseSchema.Transfer.Topic) | ||
{ | ||
signupBonusEvent = Erc20Transfer(block, receipt, repeatedLogEntry, i); | ||
break; | ||
} | ||
} | ||
|
||
return signupBonusEvent == null | ||
? new[] { signupEvent } | ||
: new[] { signupEvent, signupBonusEvent }; | ||
} | ||
} |
Oops, something went wrong.