diff --git a/debts/engine.go b/debts/engine.go index b934caba..15e45f09 100644 --- a/debts/engine.go +++ b/debts/engine.go @@ -400,7 +400,7 @@ func (eng *DebtEngine) CalculateSessionDebt(blockNum int64, session *schemas.Cre notMatched = true } // even if data compressor matching is disabled check the calc values with session data at block where last credit snapshot was taken - } else if sessionSnapshot.BlockNum == blockNum { + } else if sessionSnapshot.BlockNum == blockNum && sessionSnapshot.HealthFactor.Convert().Cmp(new(big.Int)) != 0 { // it is 0 when the issuccessful is false for redstone credit accounts if IsChangeMoreThanFraction(debt.CalTotalValueBI, sessionSnapshot.TotalValueBI, big.NewFloat(0.0001)) || // hf value calculated are on different side of 1 core.ValueDifferSideOf10000(debt.CalHealthFactor, sessionSnapshot.HealthFactor) || diff --git a/ds/repo.go b/ds/repo.go index a147ce7b..6ae6f30f 100644 --- a/ds/repo.go +++ b/ds/repo.go @@ -2,6 +2,7 @@ package ds import ( "math/big" + "time" "github.com/Gearbox-protocol/sdk-go/core" "github.com/Gearbox-protocol/sdk-go/core/schemas" @@ -134,4 +135,5 @@ type RepositoryI interface { AddTokenLTRamp(*schemas_v3.TokenLTRamp) AddQuotaDetails(*schemas_v3.QuotaDetails) GetAccountQuotaMgr() *AccountQuotaMgr + IsBlockRecent(block int64, dur time.Duration) bool } diff --git a/ds/repo_dummy.go b/ds/repo_dummy.go index ce794ae6..f0f2305f 100644 --- a/ds/repo_dummy.go +++ b/ds/repo_dummy.go @@ -2,6 +2,7 @@ package ds import ( "math/big" + "time" "github.com/Gearbox-protocol/sdk-go/core" "github.com/Gearbox-protocol/sdk-go/core/schemas" @@ -236,4 +237,5 @@ func (DummyRepo) GetTokenFromSdk(string) string { func (DummyRepo) AddTokenLTRamp(*schemas_v3.TokenLTRamp) {} func (DummyRepo) AddQuotaDetails(*schemas_v3.QuotaDetails) {} -func (DummyRepo) GetAccountQuotaMgr() *AccountQuotaMgr { return nil } +func (DummyRepo) GetAccountQuotaMgr() *AccountQuotaMgr { return nil } +func (DummyRepo) IsBlockRecent(block int64, dur time.Duration) bool { return false } diff --git a/go.mod b/go.mod index 7b7f2ac8..29697717 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/Gearbox-protocol/third-eye go 1.19 require ( - github.com/Gearbox-protocol/sdk-go v0.0.0-20240216014533-b42549c9dbfa + github.com/Gearbox-protocol/sdk-go v0.0.0-20240221203600-33735e3641f6 github.com/ethereum/go-ethereum v1.10.17 github.com/go-playground/validator/v10 v10.4.1 github.com/google/go-cmp v0.5.8 @@ -73,4 +73,4 @@ require ( replace github.com/btcsuite/btcd => github.com/btcsuite/btcd v0.22.1 -// replace github.com/Gearbox-protocol/sdk-go v0.0.0-20240216014533-b42549c9dbfa => ../sdk-go +replace github.com/Gearbox-protocol/sdk-go v0.0.0-20240216014533-b42549c9dbfa => ../sdk-go diff --git a/go.sum b/go.sum index 6daf3961..ba150c55 100644 --- a/go.sum +++ b/go.sum @@ -45,6 +45,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Gearbox-protocol/sdk-go v0.0.0-20240216014533-b42549c9dbfa h1:vxCl/4yH2wjUuLL+JljamikMIzH9NSgIm290q/eKJIk= github.com/Gearbox-protocol/sdk-go v0.0.0-20240216014533-b42549c9dbfa/go.mod h1:GniLx/DU7tCT+QSlKt9REqUaF748X8rbDNR4vAd1m+Y= +github.com/Gearbox-protocol/sdk-go v0.0.0-20240221203600-33735e3641f6 h1:sxfLq+AqMuknmG/ZiithtcskdzaEq6SiTbjKtiWq38I= +github.com/Gearbox-protocol/sdk-go v0.0.0-20240221203600-33735e3641f6/go.mod h1:GniLx/DU7tCT+QSlKt9REqUaF748X8rbDNR4vAd1m+Y= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= diff --git a/models/aggregated_block_feed/model.go b/models/aggregated_block_feed/model.go index 335846ec..f603e397 100644 --- a/models/aggregated_block_feed/model.go +++ b/models/aggregated_block_feed/model.go @@ -9,6 +9,7 @@ import ( "github.com/Gearbox-protocol/sdk-go/core" "github.com/Gearbox-protocol/sdk-go/core/schemas" "github.com/Gearbox-protocol/sdk-go/log" + "github.com/Gearbox-protocol/sdk-go/pkg" "github.com/Gearbox-protocol/sdk-go/utils" "github.com/Gearbox-protocol/third-eye/ds" "github.com/Gearbox-protocol/third-eye/models/aggregated_block_feed/query_price_feed" @@ -29,6 +30,7 @@ type AQFWrapper struct { queryFeedPrices []*schemas.PriceFeed // intervel from config Interval int64 + redStone pkg.RedStoneMgrI } // not present in db , manaully added in syncadapter repository handler @@ -55,6 +57,7 @@ func NewAQFWrapper(client core.ClientI, repo ds.RepositoryI, interval int64) *AQ mu: &sync.Mutex{}, QueryFeeds: map[string]*query_price_feed.QueryPriceFeed{}, queryPFdeps: NewQueryPFDepenencies(repo, client), + redStone: pkg.NewRedStoneMgr(client), } wrapper.queryPFdeps.aqf = wrapper return wrapper diff --git a/models/aggregated_block_feed/query.go b/models/aggregated_block_feed/query.go index 9714414d..04bdf96e 100644 --- a/models/aggregated_block_feed/query.go +++ b/models/aggregated_block_feed/query.go @@ -42,6 +42,7 @@ func (mdl *AQFWrapper) fetchAllPrices(toSinceTill int64) int64 { ch <- 1 wg.Add(1) go mdl.queryAsync(blockNum, ch, wg) + mdl.queryRedStone(blockNum) if rounds%100 == 0 { timeLeft := (time.Since(loopStartTime).Seconds() * float64(toSinceTill-blockNum)) / float64(blockNum-mdl.GetLastSync()) @@ -54,6 +55,37 @@ func (mdl *AQFWrapper) fetchAllPrices(toSinceTill int64) int64 { wg.Wait() return blockNum - mdl.Interval } +func (mdl *AQFWrapper) queryRedStone(blockNum int64) { + // for redstone + for _, adapter := range mdl.QueryFeeds { + // fetch from redstone + validTokens := adapter.TokensValidAtBlock(blockNum) + if adapter.GetPFType() == ds.RedStonePF && + len(validTokens) > 0 && mdl.redStone.IsRedStoneToken(validTokens[0].Token) && // if adapter has redstone token, then fetch from redstone + mdl.Repo.IsBlockRecent(blockNum, time.Minute*10) { + mdl.redStone.Update(blockNum, 20) + priceBI := mdl.redStone.GetPrice(validTokens[0].Token) + // + isPriceInUSD := adapter.GetVersion().IsPriceInUSD() // should be always true + + priceData := parsePriceForRedStone(priceBI, isPriceInUSD, adapter.GetAddress()) + log.Infof("RedStone price for %s at %d is %f", mdl.Repo.GetToken(validTokens[0].Token).Symbol, blockNum, priceData.Price) + // + priceFeeds := []*schemas.PriceFeed{} + for _, entry := range adapter.TokensValidAtBlock(blockNum) { + priceDataCopy := priceData.Clone() + // + priceDataCopy.BlockNumber = blockNum + priceDataCopy.Token = entry.Token + priceDataCopy.MergedPFVersion = entry.MergedPFVersion + priceDataCopy.Feed = adapter.GetAddress() + // + priceFeeds = append(priceFeeds, priceDataCopy) + } + mdl.updateQueryPrices(priceFeeds) + } + } +} // update all queryAdapter only if for the lastBlockNumber as we have fetched prices for that block. // not update for toSinceTill. if the interval is more than the syncCycle in engin/index.go, the queryAdpater lastsync will be updated but the prices will not be fetched @@ -145,7 +177,9 @@ var curvePFLatestRoundDataTimer = map[string]log.TimerFn{} func (mdl *AQFWrapper) processRoundData(blockNum int64, adapter *query_price_feed.QueryPriceFeed, entry multicall.Multicall2Result) []*schemas.PriceFeed { var priceData *schemas.PriceFeed - if entry.Success { + if adapter.GetPFType() == ds.RedStonePF && mdl.Repo.IsBlockRecent(blockNum, time.Minute*10) { // 20 blocks + return nil + } else if entry.Success { isPriceInUSD := adapter.GetVersion().IsPriceInUSD() priceData = parseRoundData(entry.ReturnData, isPriceInUSD, adapter.GetAddress()) } else if adapter.GetVersion().MoreThanEq(core.NewVersion(300)) { @@ -240,3 +274,15 @@ func parseRoundData(returnData []byte, isPriceInUSD bool, feed string) *schemas. Price: utils.GetFloat64Decimal(roundData.Answer, decimals), } } + +func parsePriceForRedStone(price *big.Int, isPriceInUSD bool, feed string) *schemas.PriceFeed { + var decimals int8 = 18 // for eth + if isPriceInUSD { + decimals = 8 // for usd + } + return &schemas.PriceFeed{ + RoundId: 0, + PriceBI: (*core.BigInt)(price), + Price: utils.GetFloat64Decimal(price, decimals), + } +} diff --git a/models/aggregated_block_feed/query_price_feed/yearn_price_feed.go b/models/aggregated_block_feed/query_price_feed/yearn_price_feed.go index 7eb6917b..a45516db 100644 --- a/models/aggregated_block_feed/query_price_feed/yearn_price_feed.go +++ b/models/aggregated_block_feed/query_price_feed/yearn_price_feed.go @@ -46,6 +46,10 @@ func NewQueryPriceFeed(token, oracle string, pfType string, discoveredAt int64, return mdl } +func (pf *QueryPriceFeed) GetPFType() string { + return pf.GetDetailsByKey("pfType") +} + func NewQueryPriceFeedFromAdapter(adapter *ds.SyncAdapter) *QueryPriceFeed { obj := &QueryPriceFeed{ SyncAdapter: adapter, diff --git a/repository/handlers/blocks.go b/repository/handlers/blocks.go index ac77708b..765ac1ff 100644 --- a/repository/handlers/blocks.go +++ b/repository/handlers/blocks.go @@ -151,17 +151,21 @@ func (repo *BlocksRepo) Load() { repo.prevStore.loadPrevPriceFeed(repo.db) } +func (repo *BlocksRepo) IsBlockRecent(block int64, dur time.Duration) bool { + ts := repo._setAndGetBlock(block).Timestamp + return time.Since(time.Unix(int64(ts), 0)) < dur +} func (repo *BlocksRepo) RecentMsgf(header log.RiskHeader, msg string, args ...interface{}) { - ts := repo._setAndGetBlock(header.BlockNumber).Timestamp - if time.Since(time.Unix(int64(ts), 0)) < time.Hour { - if header.EventCode == "AMQP" { - log.AMQPMsgf(msg, args...) - } else { - log.SendRiskAlert(log.RiskAlert{ - Msg: fmt.Sprintf(msg, args...), - RiskHeader: header, - }) - } + if !repo.IsBlockRecent(header.BlockNumber, time.Hour) { + return + } + if header.EventCode == "AMQP" { + log.AMQPMsgf(msg, args...) + } else { + log.SendRiskAlert(log.RiskAlert{ + Msg: fmt.Sprintf(msg, args...), + RiskHeader: header, + }) } } diff --git a/scripts/fix_execute_transfer_v3/main.go b/scripts/fix_execute_transfer_v3/main.go index f20ec521..173bacf4 100644 --- a/scripts/fix_execute_transfer_v3/main.go +++ b/scripts/fix_execute_transfer_v3/main.go @@ -46,8 +46,8 @@ func main() { for ind, execTransfer := range x { _ = execTransfer log.Info(ops[ind].ID) - // err = db.Exec(`update account_operations set main_action = ? where id=?`, execTransfer.Transfers, ops[ind].ID).Error - // log.CheckFatal(err) + err = db.Exec(`update account_operations set transfers = ? where id=?`, execTransfer.Transfers.String(), ops[ind].ID).Error + log.CheckFatal(err) } } //