Skip to content

Commit

Permalink
* allow to filter circles_events.
Browse files Browse the repository at this point in the history
* add member/trusted count to V_CrcV2_Groups
* return crc, circles (v2) and static circles formatted as exacircles and attoCircles
  • Loading branch information
jaensen committed Sep 15, 2024
1 parent 69f0e0b commit 4536a1e
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 56 deletions.
69 changes: 44 additions & 25 deletions Circles.Index.CirclesViews/DatabaseSchema.cs
Original file line number Diff line number Diff line change
Expand Up @@ -559,35 +559,54 @@ UNION ALL
new("name", ValueTypes.String, true),
new("symbol", ValueTypes.String, true),
new("cidV0Digest", ValueTypes.Bytes, true),
new("memberCount", ValueTypes.Int, true),
new("trustedCount", ValueTypes.Int, true),
])
{
SqlMigrationItem = new SqlMigrationItem(@"
create or replace view public.""V_CrcV2_Groups""
(""blockNumber"", timestamp, ""transactionIndex"", ""logIndex"", ""transactionHash"", ""group"", mint, treasury, name,
symbol, ""cidV0Digest"")
symbol, ""cidV0Digest"", ""memberCount"", ""trustedCount"")
as
WITH latestmetadata AS (SELECT u.avatar,
u.""metadataDigest"",
u.""blockNumber"",
u.""transactionIndex"",
u.""logIndex"",
row_number()
OVER (PARTITION BY u.avatar ORDER BY u.""blockNumber"" DESC, u.""transactionIndex"" DESC, u.""logIndex"" DESC) AS rn
FROM ""CrcV2_UpdateMetadataDigest"" u)
SELECT g.""blockNumber"",
g.""timestamp"",
g.""transactionIndex"",
g.""logIndex"",
g.""transactionHash"",
g.""group"",
g.mint,
g.treasury,
g.name,
g.symbol,
lm.""metadataDigest"" AS ""cidV0Digest""
FROM ""CrcV2_RegisterGroup"" g
JOIN latestmetadata lm ON g.""group"" = lm.avatar
WHERE lm.rn = 1;
WITH latestmetadata AS (
SELECT u.avatar,
u.""metadataDigest"",
u.""blockNumber"",
u.""transactionIndex"",
u.""logIndex"",
row_number()
OVER (PARTITION BY u.avatar ORDER BY u.""blockNumber"" DESC, u.""transactionIndex"" DESC, u.""logIndex"" DESC) AS rn
FROM ""CrcV2_UpdateMetadataDigest"" u
)
SELECT g.""blockNumber"",
g.""timestamp"",
g.""transactionIndex"",
g.""logIndex"",
g.""transactionHash"",
g.""group"",
g.mint,
g.treasury,
g.name,
g.symbol,
lm.""metadataDigest"" AS ""cidV0Digest"",
count(""outTrust"".trustee) AS ""memberCount"",
count(""inTrust"".truster) AS ""trustedCount""
FROM ""CrcV2_RegisterGroup"" g
JOIN latestmetadata lm ON g.""group"" = lm.avatar
LEFT JOIN ""V_CrcV2_TrustRelations"" ""outTrust"" on ""outTrust"".truster = g.""group""
LEFT JOIN ""V_CrcV2_TrustRelations"" ""inTrust"" on ""inTrust"".trustee = g.""group""
WHERE lm.rn = 1
GROUP BY g.""blockNumber"",
g.""timestamp"",
g.""transactionIndex"",
g.""logIndex"",
g.""transactionHash"",
g.""group"",
g.mint,
g.treasury,
g.name,
g.symbol,
lm.""metadataDigest"";
")
};

Expand Down Expand Up @@ -705,7 +724,7 @@ union all
""erc20Wrapper"" as token,
""avatar"" as ""tokenOwner""
from ""CrcV2_ERC20WrapperDeployed""
where ""circlesType"" = 0
where ""circlesType"" = 1
union all
select ""blockNumber"",
""timestamp"",
Expand All @@ -717,7 +736,7 @@ union all
""erc20Wrapper"" as token,
""avatar"" as ""tokenOwner""
from ""CrcV2_ERC20WrapperDeployed""
where ""circlesType"" = 1;
where ""circlesType"" = 0;
")
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Text.RegularExpressions;
using Circles.Index.Common;
using Circles.Index.Query.Dto;
using NUnit.Framework.Legacy;

namespace Circles.Index.Query.Tests;

Expand Down
69 changes: 49 additions & 20 deletions Circles.Index.Rpc/CirclesRpcModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,26 +77,51 @@ private async Task<List<CirclesTokenBalance>> GetTokenBalancesForAccount(Address
{
var rawBalance = balanceTasks[token.TokenAddress].Result;

UInt256 demurragedBalanceAttoCircles;
decimal demurragedBalanceCircles;
UInt256 inflationaryBalanceAttoCircles;
decimal inflationaryBalanceCircles;
UInt256 attoCircles;
decimal cirlces;

if (token.IsInflationary)
UInt256 attoCrc;
decimal crc;

UInt256 staticAttoCircles;
decimal staticCircles;

if (token.TokenType == "CrcV1_Signup")
{
inflationaryBalanceAttoCircles = rawBalance;
inflationaryBalanceCircles = ConversionUtils.AttoCirclesToCircles(rawBalance);
// OG CRC
attoCrc = rawBalance;
crc = ConversionUtils.AttoCirclesToCircles(rawBalance);

demurragedBalanceCircles = ConversionUtils.CrcToTc(DateTime.Now, inflationaryBalanceCircles);
demurragedBalanceAttoCircles = ConversionUtils.CirclesToAttoCircles(demurragedBalanceCircles);
cirlces = ConversionUtils.CrcToCircles(crc);
attoCircles = ConversionUtils.CirclesToAttoCircles(cirlces);

staticCircles = ConversionUtils.CirclesToStaticCircles(cirlces);
staticAttoCircles = ConversionUtils.CirclesToAttoCircles(staticCircles);
}
else
{
demurragedBalanceAttoCircles = rawBalance;
demurragedBalanceCircles = ConversionUtils.AttoCirclesToCircles(rawBalance);

inflationaryBalanceCircles = ConversionUtils.TcToCrc(DateTime.Now, demurragedBalanceCircles);
inflationaryBalanceAttoCircles = ConversionUtils.CirclesToAttoCircles(inflationaryBalanceCircles);
if (token.IsInflationary)
{
staticAttoCircles = rawBalance;
staticCircles = ConversionUtils.AttoCirclesToCircles(rawBalance);

cirlces = ConversionUtils.StaticCirclesToCircles(staticCircles);
attoCircles = ConversionUtils.CirclesToAttoCircles(cirlces);

crc = ConversionUtils.CirclesToCrc(cirlces);
attoCrc = ConversionUtils.CirclesToAttoCircles(crc);
}
else
{
attoCircles = rawBalance;
cirlces = ConversionUtils.AttoCirclesToCircles(rawBalance);

crc = ConversionUtils.CirclesToCrc(cirlces);
attoCrc = ConversionUtils.CirclesToAttoCircles(crc);

staticCircles = ConversionUtils.CirclesToStaticCircles(cirlces);
staticAttoCircles = ConversionUtils.CirclesToAttoCircles(staticCircles);
}
}

var tokenAddress = token.TokenAddress;
Expand All @@ -110,10 +135,12 @@ private async Task<List<CirclesTokenBalance>> GetTokenBalancesForAccount(Address
token.TokenOwner.ToString(true, false),
token.TokenType,
token.Version,
demurragedBalanceAttoCircles.ToString(CultureInfo.InvariantCulture),
demurragedBalanceCircles,
inflationaryBalanceAttoCircles.ToString(CultureInfo.InvariantCulture),
inflationaryBalanceCircles,
attoCircles.ToString(CultureInfo.InvariantCulture),
cirlces,
staticAttoCircles.ToString(CultureInfo.InvariantCulture),
staticCircles,
attoCrc.ToString(CultureInfo.InvariantCulture),
crc,
token.IsErc20,
token.IsErc1155,
token.IsWrapped,
Expand Down Expand Up @@ -308,10 +335,12 @@ public ResultWrapper<DatabaseQueryResult> circles_query(SelectDto query)
return ResultWrapper<DatabaseQueryResult>.Success(result);
}

public ResultWrapper<CirclesEvent[]> circles_events(Address? address, long? fromBlock, long? toBlock = null, FilterPredicateDto[]? filterPredicates = null, bool? sortAscending = false)
public ResultWrapper<CirclesEvent[]> circles_events(Address? address, long? fromBlock, long? toBlock = null,
FilterPredicateDto[]? filterPredicates = null, bool? sortAscending = false)
{
var queryEvents = new QueryEvents(_indexerContext);
return ResultWrapper<CirclesEvent[]>.Success(queryEvents.CirclesEvents(address, fromBlock, toBlock, filterPredicates, sortAscending));
return ResultWrapper<CirclesEvent[]>.Success(queryEvents.CirclesEvents(address, fromBlock, toBlock,
filterPredicates, sortAscending));
}

private string[] GetTokenExposureIds(Address address)
Expand Down
2 changes: 2 additions & 0 deletions Circles.Index.Rpc/ICirclesRpcModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public record CirclesTokenBalance(
decimal Circles,
string StaticAttoCircles,
decimal StaticCircles,
string AttoCrc,
decimal Crc,
bool IsErc20,
bool IsErc1155,
bool IsWrapped,
Expand Down
118 changes: 111 additions & 7 deletions Circles.Index.Utils/ConversionUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,80 @@

namespace Circles.Index.Utils;

using System;

public static class DemurrageConverter
{
const decimal Gamma = 0.99980133200859895743m; // Daily demurrage factor
const decimal Beta = 1.0001987074682146291562714890133039617432343970799554367508m;

const long DemurrageWindow = 86400; // 1 day in seconds
const long InflationDayZero = 1602720000L; // 15th October 2020

// Method to compute the power of Γ^i (Gamma^i)
public static decimal GammaPower(long i)
{
return (decimal)Math.Pow((double)Gamma, i);
}

public static decimal BetaPower(long i)
{
return (decimal)Math.Pow((double)Beta, i);
}

public static long Day(long timestamp)
{
// calculate which day the timestamp is in, rounding down
// note: max uint64 is 2^64 - 1, so we can safely cast the result
return (timestamp - InflationDayZero) / DemurrageWindow;
}

/// <summary>
/// Converts an inflationary balance to a demurraged balance.
/// </summary>
/// <param name="demurragedBalance">The demurraged balance to convert.</param>
/// <returns></returns>
public static decimal ConvertDemurragedToInflationary(decimal demurragedBalance)
{
decimal CalculateInflationaryBalance()
{
/* Solidity code:
* // calculate the inflationary balance by dividing the balance by GAMMA^days
// note: GAMMA < 1, so dividing by a power of it, returns a bigger number,
// so the numerical imprecision is in the least significant bits.
int128 i = Math64x64.pow(BETA_64x64, _dayUpdated);
return Math64x64.mulu(i, _balance);
*/
var timestamp = DateTimeOffset.UnixEpoch.ToUnixTimeMilliseconds();
return demurragedBalance * BetaPower(Day(timestamp));
}

decimal inflationaryAmount = CalculateInflationaryBalance();
return inflationaryAmount;
}

public static decimal ConvertInflationaryToDemurraged(decimal inflationaryBalance)
{
/** From solidity:
* // calculate the demurrage value by multiplying the value by GAMMA^days
// note: GAMMA < 1, so multiplying by a power of it, returns a smaller number,
// so we lose the least significant bits, but our ground truth is the demurrage value,
// and the inflationary value is a numerical approximation (where the least significant digits
// are not reliable).
int128 r = Math64x64.pow(GAMMA_64x64, uint256(_day));
return Math64x64.mulu(r, _inflationaryValue);
*/
decimal CalculateDemurragedBalance()
{
var timestamp = DateTimeOffset.UnixEpoch.ToUnixTimeMilliseconds();
return inflationaryBalance * GammaPower(Day(timestamp));
}

decimal demurragedAmount = CalculateDemurragedBalance();
return demurragedAmount;
}
}

public abstract class ConversionUtils
{
private static readonly long CirclesInceptionTimestamp =
Expand Down Expand Up @@ -45,26 +119,56 @@ public static decimal GetCrcPayoutAt(long timestamp)
return result;
}

public static decimal CrcToTc(DateTime timestamp, decimal amount)
/// <summary>
/// Converts a v1 inflationary CRC balance to a v2 personal Circles balance (demurraged).
/// </summary>
/// <param name="crcBalance"></param>
/// <returns></returns>
public static decimal CrcToCircles(decimal crcBalance)
{
long ts = ConvertToUnixTimestamp(timestamp);
long ts = ConvertToUnixTimestamp(DateTime.Now);

decimal payoutAtTimestamp = GetCrcPayoutAt(ts);
decimal result = amount / payoutAtTimestamp * 24m;
decimal result = crcBalance / payoutAtTimestamp * 24m;

return result;
}

public static decimal TcToCrc(DateTime timestamp, decimal amount)
/// <summary>
/// Converts a regular v2 personal Circles balance (demurraged) to a v1 compatible CRC balance (inflationary).
/// </summary>
/// <param name="circlesBalance"></param>
/// <returns></returns>
public static decimal CirclesToCrc(decimal circlesBalance)
{
long ts = ConvertToUnixTimestamp(timestamp);
long ts = ConvertToUnixTimestamp(DateTime.Now);

decimal payoutAtTimestamp = GetCrcPayoutAt(ts);
decimal result = amount / 24m * payoutAtTimestamp;
decimal result = circlesBalance / 24m * payoutAtTimestamp;

return result;
}

/// <summary>
/// Converts a regular v2 personal Circles balance (demurraged) to a static Circles balance (inflationary).
/// </summary>
/// <param name="circlesBalance"></param>
/// <returns></returns>
public static decimal CirclesToStaticCircles(decimal circlesBalance)
{
return CirclesToCrc(circlesBalance) * 3;
}

/// <summary>
/// Converts a static Circles balance (inflationary) to a regular v2 personal Circles balance (demurraged).
/// </summary>
/// <param name="staticCirclesBalance"></param>
/// <returns></returns>
public static decimal StaticCirclesToCircles(decimal staticCirclesBalance)
{
return CrcToCircles(staticCirclesBalance / 3);
}

public static decimal AttoCirclesToCircles(UInt256 weiBalance)
{
// Convert to Ether by dividing by 10^18 (Ether has 18 decimal places)
Expand All @@ -90,7 +194,7 @@ public static UInt256 AddressToUInt256(Address address)
{
return new(address.Bytes, true);
}

public static Address UInt256ToAddress(UInt256 uint256)
{
return new Address(uint256.ToBigEndian()[12..].ToHexString());
Expand Down
4 changes: 2 additions & 2 deletions Circles.Index/Circles.Index.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
<Authors>Daniel Janz (Gnosis Service GmbH)</Authors>
<Copyright>Gnosis Service GmbH</Copyright>
<Product>Circles</Product>
<AssemblyVersion>1.8.0</AssemblyVersion>
<FileVersion>1.8.0</FileVersion>
<AssemblyVersion>1.8.1</AssemblyVersion>
<FileVersion>1.8.1</FileVersion>
</PropertyGroup>


Expand Down
2 changes: 1 addition & 1 deletion docker-compose.gnosis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ services:
- V2_STANDARD_TREASURY_ADDRESS=0xbb76CF35ec106c5c7a447246257dcfCB7244cA04
- V2_ERC20_LIFT_ADDRESS=0xB6B79BeEfd58cf33b298A456934554cf440354aD
- POSTGRES_CONNECTION_STRING=Server=postgres-gnosis;Port=5432;Database=postgres;User Id=${POSTGRES_USER};Password=${POSTGRES_PASSWORD};
- START_BLOCK=35700000
- START_BLOCK=12000000

postgres-gnosis:
image: postgres:16
Expand Down

0 comments on commit 4536a1e

Please sign in to comment.