Skip to content

Commit

Permalink
feat: Introduce BlockChainService methods for reward claim
Browse files Browse the repository at this point in the history
  • Loading branch information
OnedgeLee committed Dec 30, 2024
1 parent ddf6c58 commit 86e9883
Showing 1 changed file with 86 additions and 0 deletions.
86 changes: 86 additions & 0 deletions NineChronicles.Headless/BlockChainService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,14 @@
using MagicOnion.Server;
using Microsoft.Extensions.Caching.Memory;
using Nekoyume;
using Nekoyume.Delegation;
using Nekoyume.Model.Guild;
using Nekoyume.Model.State;
using Nekoyume.Module;
using Nekoyume.Shared.Services;
using NineChronicles.Headless.Utils;
using Serilog;
using static Humanizer.In;
using static NineChronicles.Headless.NCActionUtils;
using NodeExceptionType = Libplanet.Headless.NodeExceptionType;
using Transaction = Libplanet.Types.Tx.Transaction;
Expand Down Expand Up @@ -342,6 +346,54 @@ public UnaryResult<byte[]> GetBalanceByStateRootHash(
return new UnaryResult<byte[]>(encoded);
}

public UnaryResult<byte[]> GetUnbondClaimableHeightByBlockHash(
byte[] blockHashBytes, byte[] addressBytes)
{
var blockHash = new BlockHash(blockHashBytes);
var address = new Address(addressBytes);
var worldState = _blockChain.GetWorldState(blockHash);
var result = GetUnbondClaimableHeight(worldState, address);

byte[] encoded = _codec.Encode(result);
return new UnaryResult<byte[]>(encoded);
}

public UnaryResult<byte[]> GetUnbondClaimableHeightByStateRootHash(
byte[] stateRootHashBytes, byte[] addressBytes)
{
var stateRootHash = new HashDigest<SHA256>(stateRootHashBytes);
var address = new Address(addressBytes);
var worldState = _blockChain.GetWorldState(stateRootHash);
var result = GetUnbondClaimableHeight(worldState, address);

byte[] encoded = _codec.Encode(result);
return new UnaryResult<byte[]>(encoded);
}

public UnaryResult<byte[]> GetClaimableRewardsByBlockHash(
byte[] blockHashBytes, byte[] addressBytes)
{
var blockHash = new BlockHash(blockHashBytes);
var address = new Address(addressBytes);
var worldState = _blockChain.GetWorldState(blockHash);
var result = GetClaimableRewards(worldState, address);

byte[] encoded = _codec.Encode(result);
return new UnaryResult<byte[]>(encoded);
}

public UnaryResult<byte[]> GetClaimableRewardsByStateRootHash(
byte[] stateRootHashBytes, byte[] addressBytes)
{
var stateRootHash = new HashDigest<SHA256>(stateRootHashBytes);
var address = new Address(addressBytes);
var worldState = _blockChain.GetWorldState(stateRootHash);
var result = GetClaimableRewards(worldState, address);

byte[] encoded = _codec.Encode(result);
return new UnaryResult<byte[]>(encoded);
}

public UnaryResult<byte[]> GetTip()
{
Bencodex.Types.Dictionary headerDict = _blockChain.Tip.MarshalBlock();
Expand Down Expand Up @@ -430,6 +482,40 @@ public UnaryResult<bool> RemoveClient(byte[] addressBytes)
return new UnaryResult<bool>(true);
}

private static IValue GetUnbondClaimableHeight(IWorldState worldState, Address address)
{
var repository = new GuildRepository(new World(worldState), new HallowActionContext { });
var guildAddress = repository.GetGuildParticipant(address).GuildAddress;
var validatorAddress = repository.GetGuild(guildAddress).ValidatorAddress;
var guildDelegatee = repository.GetDelegatee(validatorAddress);
var unbondLockIn = repository.GetUnbondLockIn(guildDelegatee, address);
var unbondClaimableHeight = unbondLockIn.LowestExpireHeight;

return new Integer(unbondClaimableHeight);
}

private static IValue GetClaimableRewards(IWorldState worldState, Address address)
{
var repository = new GuildRepository(new World(worldState), new HallowActionContext { });
var guildAddress = repository.GetGuildParticipant(address).GuildAddress;
var validatorAddress = repository.GetGuild(guildAddress).ValidatorAddress;
var guildDelegatee = repository.GetDelegatee(validatorAddress);
var bond = repository.GetBond(guildDelegatee, address);
var share = bond.Share;

if (share.IsZero
|| bond.LastDistributeHeight is null
|| repository.GetCurrentRewardBase(guildDelegatee) is not RewardBase rewardBase)
{
return Null.Value;
}

var lastRewardBase = repository.GetRewardBase(guildDelegatee, bond.LastDistributeHeight.Value);
var rewards = guildDelegatee.CalculateRewards(share, rewardBase, lastRewardBase);

return new List(rewards.Select(r => r.Serialize()));
}

// Returning value is a list of [ Avatar, Inventory, QuestList, WorldInformation ]
private static IValue GetFullAvatarStateRaw(IWorldState worldState, Address address)
{
Expand Down

0 comments on commit 86e9883

Please sign in to comment.