From 2ac9d274d955a779c603e844862ff5653591e3da Mon Sep 17 00:00:00 2001 From: Jiri Malek Date: Sat, 2 May 2020 10:58:36 +0200 Subject: [PATCH] Add total and available delegation limits info to staker. --- internal/graphql/schema/bundle.go | 18 +++++++-- .../schema/definition/types/staker.graphql | 14 ++++++- internal/repository/rpc/sfc.go | 39 ++++++++++++++++++- internal/types/staker.go | 4 ++ 4 files changed, 69 insertions(+), 6 deletions(-) diff --git a/internal/graphql/schema/bundle.go b/internal/graphql/schema/bundle.go index c654e60d..307f38ad 100644 --- a/internal/graphql/schema/bundle.go +++ b/internal/graphql/schema/bundle.go @@ -1,6 +1,6 @@ package gqlschema -// Auto generated GraphQL schema bundle; created 2020-05-01 00:34 +// Auto generated GraphQL schema bundle; created 2020-05-02 10:50 const schema = ` # StakerInfo represents extended staker information from smart contract. type StakerInfo { @@ -118,7 +118,7 @@ type EstimatedRewards { currentRewardRateYearly: Int! """ - Total amount of staked FTM tokens used for the calculation. + Total amount of staked FTM tokens used for the calculation in WEI units. The estimation uses total staked amount, not the effective amount provided by the last epoch. The effective amount does include current undelegations and also skips offline self-stakings and flagged stakings. @@ -314,6 +314,18 @@ type Staker { "Amount of tokens delegated to the staker." delegatedMe: BigInt + """ + Maximum total amount of tokens allowed to be delegated to the staker. + This value depends on the amount of self staked tokens. + """ + totalDelegatedLimit: BigInt! + + """ + Maximum amount of tokens allowed to be delegated to the staker on a new delegation. + This value depends on the amount of self staked tokens. + """ + delegatedLimit: BigInt! + "Is this a validator record." isValidator: Boolean! @@ -520,7 +532,7 @@ type Query { price(to:String!):Price! """ - Get calculated staking rewards for an account or given staking amount. + Get calculated staking rewards for an account or given staking amount in FTM tokens. At least one of the address and amount parameters must be provided. If you provide both, the address takes precedence and the amount is ignored. """ diff --git a/internal/graphql/schema/definition/types/staker.graphql b/internal/graphql/schema/definition/types/staker.graphql index f12dfa65..2789a97d 100644 --- a/internal/graphql/schema/definition/types/staker.graphql +++ b/internal/graphql/schema/definition/types/staker.graphql @@ -12,9 +12,21 @@ type Staker { "Amount of own staked tokens in WEI." stake: BigInt - "Amount of tokens delegated to the staker." + "Amount of tokens delegated to the staker in WEI." delegatedMe: BigInt + """ + Maximum total amount of tokens allowed to be delegated to the staker in WEI. + This value depends on the amount of self staked tokens. + """ + totalDelegatedLimit: BigInt! + + """ + Maximum amount of tokens allowed to be delegated to the staker on a new delegation in WEI. + This value depends on the amount of self staked tokens. + """ + delegatedLimit: BigInt! + "Is this a validator record." isValidator: Boolean! diff --git a/internal/repository/rpc/sfc.go b/internal/repository/rpc/sfc.go index 5b454e57..00a7b733 100644 --- a/internal/repository/rpc/sfc.go +++ b/internal/repository/rpc/sfc.go @@ -131,8 +131,17 @@ func (ftm *FtmBridge) stakerUpdateFromSfc(staker *types.Staker) error { staker.Stake = (*hexutil.Big)(si.StakeAmount) staker.Status = hexutil.Uint64(si.Status.Uint64()) - // recalculate the total stake - staker.TotalStake = (*hexutil.Big)(big.NewInt(0).Add(si.DelegatedMe, si.StakeAmount)) + if staker.Stake != nil && staker.DelegatedMe != nil { + // recalculate the total stake + staker.TotalStake = (*hexutil.Big)(big.NewInt(0).Add(si.DelegatedMe, si.StakeAmount)) + + // calculate delegation limit + staker.TotalDelegatedLimit = ftm.maxDelegatedLimit(staker.Stake, contract) + + // calculate available limit for staking + val := new(big.Int).Sub((*big.Int)(&staker.TotalDelegatedLimit), (*big.Int)(staker.DelegatedMe)) + staker.DelegatedLimit = (hexutil.Big)(*val) + } } else { // log issue ftm.log.Debug("staker info update from SFC failed, no data received") @@ -142,6 +151,32 @@ func (ftm *FtmBridge) stakerUpdateFromSfc(staker *types.Staker) error { return nil } +// maxDelegatedLimit calculate maximum amount of tokens allowed to be delegated to a staker. +func (ftm *FtmBridge) maxDelegatedLimit(staked *hexutil.Big, contract *SfcContract) hexutil.Big { + // if we don't know the staked amount, return zero + if staked == nil { + return (hexutil.Big)(*hexutil.MustDecodeBig("0x0")) + } + + // ratio unit is used to calculate the value (1.000.000) + // please note this formula is taken from SFC contract and can change + ratioUnit := hexutil.MustDecodeBig("0xF4240") + + // get delegation ration + ratio, err := contract.MaxDelegatedRatio(nil) + if err != nil { + ftm.log.Errorf("can not get the delegation ratio; %s", err.Error()) + return (hexutil.Big)(*hexutil.MustDecodeBig("0x0")) + } + + // calculate the delegation limit temp value + temp := new(big.Int).Mul((*big.Int)(staked), ratio) + + // adjust to percent + value := new(big.Int).Div(temp, ratioUnit) + return (hexutil.Big)(*value) +} + // Staker extract a staker information by numeric id. func (ftm *FtmBridge) Staker(id hexutil.Uint64) (*types.Staker, error) { // keep track of the operation diff --git a/internal/types/staker.go b/internal/types/staker.go index 9c2ee85e..15c53966 100644 --- a/internal/types/staker.go +++ b/internal/types/staker.go @@ -32,6 +32,10 @@ type Staker struct { ClaimedRewards *hexutil.Big `json:"claimedRewards"` DelegationClaimedRewards *hexutil.Big `json:"delegatorsClaimedRewards"` Status hexutil.Uint64 `json:"status"` + + /* delegation limits */ + TotalDelegatedLimit hexutil.Big + DelegatedLimit hexutil.Big } // StakerInfo holds extended staker information.