Skip to content

Commit

Permalink
feat: Add state queries
Browse files Browse the repository at this point in the history
  • Loading branch information
s2quake committed Jan 13, 2025
1 parent 2866fd3 commit 420dfd8
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 7 deletions.
45 changes: 45 additions & 0 deletions NineChronicles.Headless.Tests/GraphTypes/DelegatorTypeTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Numerics;
using System.Threading.Tasks;
using GraphQL.Execution;
using Lib9c;
using Libplanet.Types.Tx;
using Nekoyume.ValidatorDelegation;
using NineChronicles.Headless.GraphTypes;
using Xunit;
using Xunit.Abstractions;

namespace NineChronicles.Headless.Tests.GraphTypes
{
public class DelegatorTypeTest
{
[Fact]
public async Task ExecuteQuery()
{
var lastDistributeHeight = 1L;
var share = new BigInteger(1000000000000000000) * 10;
var fav = Currencies.GuildGold * 10;

var result = await GraphQLTestUtils.ExecuteQueryAsync<DelegatorType>(
"{ lastDistributeHeight share fav { currency quantity } }",
source: new DelegatorType
{
LastDistributeHeight = lastDistributeHeight,
Share = share,
Fav = fav,
}
);

// Then
var data = (Dictionary<string, object>)((ExecutionNode)result.Data!).ToValue()!;

Assert.Equal(lastDistributeHeight, data["lastDistributeHeight"]);
Assert.Equal(share.ToString("N0"), data["share"]);

var favResult = (Dictionary<string, object>)data["fav"];
Assert.Equal(fav.Currency.Ticker, favResult["currency"]);
Assert.Equal(fav.GetQuantityString(minorUnit: true), favResult["quantity"]);
}
}
}
30 changes: 30 additions & 0 deletions NineChronicles.Headless/GraphTypes/DelegatorType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System.Numerics;
using GraphQL.Types;
using Libplanet.Types.Assets;

namespace NineChronicles.Headless.GraphTypes;

public class DelegatorType : ObjectGraphType<DelegatorType>
{
public long LastDistributeHeight { get; set; }

public BigInteger Share { get; set; }

public FungibleAssetValue Fav { get; set; }

public DelegatorType()
{
Field<NonNullGraphType<LongGraphType>>(
nameof(LastDistributeHeight),
description: "LastDistributeHeight of delegator",
resolve: context => context.Source.LastDistributeHeight);
Field<NonNullGraphType<StringGraphType>>(
nameof(Share),
description: "Share of delegator",
resolve: context => context.Source.Share.ToString("N0"));
Field<NonNullGraphType<FungibleAssetValueType>>(
nameof(Fav),
description: "Delegated FAV calculated based on Share value",
resolve: context => context.Source.Fav);
}
}
38 changes: 38 additions & 0 deletions NineChronicles.Headless/GraphTypes/GuildType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using GraphQL.Types;
using Libplanet.Crypto;
using Libplanet.Explorer.GraphTypes;
using Nekoyume.Model.Guild;

namespace NineChronicles.Headless.GraphTypes;

public class GuildType : ObjectGraphType<GuildType>
{
public Address Address { get; set; }

public Address ValidatorAddress { get; set; }

public Address GuildMasterAddress { get; set; }

public GuildType()
{
Field<NonNullGraphType<AddressType>>(
nameof(Address),
description: "Address of the guild",
resolve: context => context.Source.Address);
Field<NonNullGraphType<AddressType>>(
nameof(ValidatorAddress),
description: "Validator address of the guild",
resolve: context => context.Source.ValidatorAddress);
Field<NonNullGraphType<AddressType>>(
nameof(GuildMasterAddress),
description: "Guild master address of the guild",
resolve: context => context.Source.GuildMasterAddress);
}

public static GuildType FromDelegatee(Guild guild) => new GuildType
{
Address = guild.Address,
ValidatorAddress = guild.ValidatorAddress,
GuildMasterAddress = guild.GuildMasterAddress,
};
}
71 changes: 64 additions & 7 deletions NineChronicles.Headless/GraphTypes/StateQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
using Nekoyume.Module.Guild;
using Nekoyume.TypedAddress;
using Nekoyume.ValidatorDelegation;
using Nekoyume.Module.ValidatorDelegation;

namespace NineChronicles.Headless.GraphTypes
{
Expand Down Expand Up @@ -721,7 +722,7 @@ public StateQuery()
}
);

Field<AddressType>(
Field<GuildType>(
name: "guild",
description: "State for guild.",
arguments: new QueryArguments(
Expand All @@ -734,15 +735,14 @@ public StateQuery()
resolve: context =>
{
var agentAddress = new AgentAddress(context.GetArgument<Address>("agentAddress"));
if (!(context.Source.WorldState.GetAgentState(agentAddress) is { } agentState))
var repository = new GuildRepository(new World(context.Source.WorldState), new HallowActionContext { });
if (repository.GetJoinedGuild(agentAddress) is { } guildAddress)
{
return null;
var guild = repository.GetGuild(guildAddress);
return GuildType.FromDelegatee(guild);
}

var repository = new GuildRepository(new World(context.Source.WorldState), new HallowActionContext { });
var joinedGuild = (Address?)repository.GetJoinedGuild(agentAddress);

return joinedGuild;
return null;
}
);

Expand Down Expand Up @@ -791,6 +791,63 @@ public StateQuery()
return ValidatorType.FromDelegatee(delegatee);
}
);

Field<DelegatorType>(
name: "delegator",
description: "State for delegator.",
arguments: new QueryArguments(
new QueryArgument<NonNullGraphType<AddressType>>
{
Name = "address",
Description = "Agent or Validator address."
}
),
resolve: context =>
{
var address = context.GetArgument<Address>("address");
var agentAddress = new AgentAddress(address);
var guildRepository = new GuildRepository(
new World(context.Source.WorldState), new HallowActionContext { });
if (guildRepository.TryGetGuildParticipant(agentAddress, out var guildParticipant))
{
var guild = guildRepository.GetGuild(guildParticipant.GuildAddress);
var guildDelegatee = guildRepository.GetDelegatee(guild.ValidatorAddress);
var bond = guildRepository.GetBond(guildDelegatee, guildParticipant.Address);
var totalDelegated = guildDelegatee.Metadata.TotalDelegatedFAV;
var totalShare = guildDelegatee.Metadata.TotalShares;
var lastDistributeHeight = bond.LastDistributeHeight ?? -1;
var share = bond.Share;
var fav = (share * totalDelegated).DivRem(totalShare).Quotient;
return new DelegatorType
{
LastDistributeHeight = lastDistributeHeight,
Share = share,
Fav = fav,
};
}

var validatorAddress = address;
var validatorRepository = new ValidatorRepository(
new World(context.Source.WorldState), new HallowActionContext { });
if (validatorRepository.TryGetDelegatee(validatorAddress, out var validatorDelegatee))
{
var bond = validatorRepository.GetBond(validatorDelegatee, address);
var totalDelegated = validatorDelegatee.Metadata.TotalDelegatedFAV;
var totalShare = validatorDelegatee.Metadata.TotalShares;
var lastDistributeHeight = bond.LastDistributeHeight ?? -1;
var share = bond.Share;
var fav = (share * totalDelegated).DivRem(totalShare).Quotient;
return new DelegatorType
{
LastDistributeHeight = lastDistributeHeight,
Share = share,
Fav = fav,
};
}

return null;
}
);
}

public static List<RuneOptionSheet.Row.RuneOptionInfo> GetRuneOptions(
Expand Down

0 comments on commit 420dfd8

Please sign in to comment.