From 633fa63b7e6c858ef1536503e52bb146b9798bbf Mon Sep 17 00:00:00 2001 From: Denis Subbotin Date: Thu, 31 Aug 2023 20:57:33 +0300 Subject: [PATCH] more fixes for staking APY --- pkg/api/staking_handlers.go | 11 +++-------- pkg/core/staking.go | 15 +++++++++++++++ pkg/litestorage/stacking.go | 3 +-- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/pkg/api/staking_handlers.go b/pkg/api/staking_handlers.go index 9f67f9fa..58504b44 100644 --- a/pkg/api/staking_handlers.go +++ b/pkg/api/staking_handlers.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "math" "net/http" "github.com/tonkeeper/opentonapi/internal/g" @@ -269,12 +270,7 @@ func (h Handler) GetStakingPoolHistory(ctx context.Context, params oas.GetStakin return nil, toError(http.StatusInternalServerError, err) } var result oas.GetStakingPoolHistoryOK - var prevTime uint32 - for i, l := range logs { - if i == 0 { - prevTime = l.CreatedAt - continue - } + for _, l := range logs { cells, err := boc.DeserializeBoc(l.Body) if err != nil { return nil, toError(http.StatusInternalServerError, err) @@ -292,10 +288,9 @@ func (h Handler) GetStakingPoolHistory(ctx context.Context, params oas.GetStakin return nil, toError(http.StatusInternalServerError, err) } result.Apy = append(result.Apy, oas.ApyHistory{ - Apy: float64(round.Profit) / float64(round.TotalBalance) / float64(l.CreatedAt-prevTime) * 3600 * 24 * 365 * 100, + Apy: (math.Pow(float64(round.Returned-round.Borrowed)/float64(round.TotalBalance)+1, 365*24*60*60/float64(65536)) - 1) * 100, Time: int(l.CreatedAt), }) - prevTime = l.CreatedAt } return &result, nil } diff --git a/pkg/core/staking.go b/pkg/core/staking.go index 8f1c19a1..8a4c7c09 100644 --- a/pkg/core/staking.go +++ b/pkg/core/staking.go @@ -2,6 +2,7 @@ package core import ( "github.com/tonkeeper/tongo" + "math" ) type Nominator struct { @@ -35,3 +36,17 @@ type LiquidPool struct { JettonMaster tongo.AccountID APY float64 } + +func CalculateAPY(roundExpected, roundBorrowed int64, governanceFee int32) float64 { + const secondsPerRound = 1 << 16 + const secondsPerYear = 3600 * 24 * 365 + roundsPerYear := float64(secondsPerYear) / float64(secondsPerRound) + effectiveRounds := roundsPerYear / 2 // Because each coin may participate only in odd/even rounds + profitPrevRound := float64(roundExpected-roundBorrowed) * (1 - float64(governanceFee)/float64(1<<24)) + percentPerPrevRound := profitPrevRound / float64(roundBorrowed) + apy := (math.Pow(1+percentPerPrevRound, effectiveRounds) - 1) * 100 + if math.IsNaN(apy) { + return 0 + } + return apy +} diff --git a/pkg/litestorage/stacking.go b/pkg/litestorage/stacking.go index 8cf15a83..d19b553e 100644 --- a/pkg/litestorage/stacking.go +++ b/pkg/litestorage/stacking.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "fmt" - "math" "math/big" "github.com/tonkeeper/tongo/tlb" @@ -202,7 +201,7 @@ func (s *LiteStorage) GetLiquidPool(ctx context.Context, pool tongo.AccountID) ( TotalAmount: p.TotalBalance, VerifiedSources: bytes.Equal(hash, references.TFLiquidPoolCodeHash[:]), JettonMaster: *jettonMaster, - APY: (math.Pow(1+float64(p.InterestRate)/float64(1<<24)*(1-float64(p.GovernanceFee)/float64(1<<24)), 3600*24*366/(1<<16)) - 1) * 100, + APY: core.CalculateAPY(p.PrevRoundBorrowers.Expected, p.PrevRoundBorrowers.Borrowed, p.InterestRate), }, err }