From 861208d7244adf13b43b68fdf42cdfeb0f09e4ec Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Mon, 18 Sep 2023 18:49:36 +0200 Subject: [PATCH] feat(oracle): include timestamp into save exchange rates (#2249) * feat(oracle): include timestamp into save exchange rates * update implementations * tests * add comment * linter * leverage test * Update tests and String * keys_tests * cosmetic * ExchangeRate stringer * cli test * abci test --- proto/umee/oracle/v1/genesis.proto | 1 + proto/umee/oracle/v1/oracle.proto | 16 +- x/leverage/keeper/oracle.go | 11 +- x/leverage/keeper/oracle_test.go | 7 +- x/leverage/types/expected_types.go | 4 +- x/oracle/abci.go | 2 +- x/oracle/abci_test.go | 16 +- x/oracle/keeper/grpc_query.go | 4 +- x/oracle/keeper/keeper.go | 40 ++-- x/oracle/keeper/keeper_test.go | 24 +- x/oracle/types/genesis.pb.go | 5 +- x/oracle/types/keys.go | 3 +- x/oracle/types/keys_test.go | 31 +-- x/oracle/types/msgs_test.go | 4 +- x/oracle/types/oracle.pb.go | 346 +++++++++++++++++++++++------ x/oracle/types/vote.go | 23 +- x/oracle/types/vote_test.go | 24 +- 17 files changed, 397 insertions(+), 164 deletions(-) diff --git a/proto/umee/oracle/v1/genesis.proto b/proto/umee/oracle/v1/genesis.proto index 9b0ae78851..57e1c76f55 100644 --- a/proto/umee/oracle/v1/genesis.proto +++ b/proto/umee/oracle/v1/genesis.proto @@ -13,6 +13,7 @@ message GenesisState { Params params = 1 [(gogoproto.nullable) = false]; repeated FeederDelegation feeder_delegations = 2 [(gogoproto.nullable) = false]; + // TODO: need to update this to save data with timestamp repeated ExchangeRateTuple exchange_rates = 3 [ (gogoproto.castrepeated) = "ExchangeRateTuples", (gogoproto.nullable) = false diff --git a/proto/umee/oracle/v1/oracle.proto b/proto/umee/oracle/v1/oracle.proto index 46a9f2dfcb..8cecd4a33b 100644 --- a/proto/umee/oracle/v1/oracle.proto +++ b/proto/umee/oracle/v1/oracle.proto @@ -79,7 +79,6 @@ message AvgCounterParams { // Denom - the object to hold configurations of each denom message Denom { option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_stringer) = false; string base_denom = 1 [(gogoproto.moretags) = "yaml:\"base_denom\""]; @@ -94,7 +93,6 @@ message Denom { // rate}{denom},...,{exchange rate}{denom}:{voter}") message AggregateExchangeRatePrevote { option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_stringer) = false; string hash = 1 [(gogoproto.moretags) = "yaml:\"hash\""]; @@ -106,7 +104,6 @@ message AggregateExchangeRatePrevote { // the exchange rates of USD denominated in various assets. message AggregateExchangeRateVote { option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_stringer) = false; repeated ExchangeRateTuple exchange_rate_tuples = 1 [ @@ -121,7 +118,6 @@ message AggregateExchangeRateVote { // ExchangeRateTuple - struct to store interpreted exchange rates data to store message ExchangeRateTuple { option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_stringer) = false; string denom = 1 [(gogoproto.moretags) = "yaml:\"denom\""]; @@ -148,3 +144,15 @@ message AvgCounter { // Unix timestamp when the first price was aggregated in the counter google.protobuf.Timestamp start = 3 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; } + +// ExchangeRate stores exchange rate with timestamp +message ExchangeRate { + option (gogoproto.equal) = false; + option (gogoproto.goproto_stringer) = false; + + string rate = 1 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; + google.protobuf.Timestamp timestamp = 3 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; +} diff --git a/x/leverage/keeper/oracle.go b/x/leverage/keeper/oracle.go index 871972b38d..7173c5cc43 100644 --- a/x/leverage/keeper/oracle.go +++ b/x/leverage/keeper/oracle.go @@ -31,7 +31,8 @@ func (k Keeper) TokenPrice(ctx sdk.Context, baseDenom string, mode types.PriceMo mode = types.PriceModeSpot } - var price, spotPrice, historicPrice sdk.Dec + var price, historicPrice sdk.Dec + var spotPrice oracletypes.ExchangeRate if mode != types.PriceModeHistoric { // spot price is required for modes other than historic spotPrice, err = k.oracleKeeper.GetExchangeRate(ctx, t.SymbolDenom) @@ -56,15 +57,17 @@ func (k Keeper) TokenPrice(ctx sdk.Context, baseDenom string, mode types.PriceMo } } + // TODO: need to use spotPrice.Timestamp to make a decision about the price + switch mode { case types.PriceModeSpot: - price = spotPrice + price = spotPrice.Rate case types.PriceModeHistoric: price = historicPrice case types.PriceModeHigh: - price = sdk.MaxDec(spotPrice, historicPrice) + price = sdk.MaxDec(spotPrice.Rate, historicPrice) case types.PriceModeLow: - price = sdk.MinDec(spotPrice, historicPrice) + price = sdk.MinDec(spotPrice.Rate, historicPrice) default: return sdk.ZeroDec(), t.Exponent, types.ErrInvalidPriceMode.Wrapf("%d", mode) } diff --git a/x/leverage/keeper/oracle_test.go b/x/leverage/keeper/oracle_test.go index d2e67013df..3cdcdd225b 100644 --- a/x/leverage/keeper/oracle_test.go +++ b/x/leverage/keeper/oracle_test.go @@ -43,14 +43,15 @@ func (m *mockOracleKeeper) MedianOfHistoricMedians(ctx sdk.Context, denom string return p, uint32(numStamps), nil } -func (m *mockOracleKeeper) GetExchangeRate(_ sdk.Context, denom string) (sdk.Dec, error) { +func (m *mockOracleKeeper) GetExchangeRate(_ sdk.Context, denom string) (oracletypes.ExchangeRate, error) { p, ok := m.symbolExchangeRates[denom] if !ok { // This error matches oracle behavior on missing asset price - return sdk.ZeroDec(), oracletypes.ErrUnknownDenom.Wrap(denom) + return oracletypes.ExchangeRate{}, oracletypes.ErrUnknownDenom.Wrap(denom) } - return p, nil + // TODO: add timestamp + return oracletypes.ExchangeRate{Rate: p}, nil } // Clear clears a denom from the mock oracle, simulating an outage. diff --git a/x/leverage/types/expected_types.go b/x/leverage/types/expected_types.go index 947383f288..5a1e276f97 100644 --- a/x/leverage/types/expected_types.go +++ b/x/leverage/types/expected_types.go @@ -3,6 +3,8 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + oracle "github.com/umee-network/umee/v6/x/oracle/types" ) // AccountKeeper defines the expected account keeper used for leverage simulations (noalias) @@ -31,6 +33,6 @@ type BankKeeper interface { // OracleKeeper defines the expected x/oracle keeper interface. type OracleKeeper interface { - GetExchangeRate(ctx sdk.Context, denom string) (sdk.Dec, error) + GetExchangeRate(ctx sdk.Context, denom string) (oracle.ExchangeRate, error) MedianOfHistoricMedians(ctx sdk.Context, denom string, numStamps uint64) (sdk.Dec, uint32, error) } diff --git a/x/oracle/abci.go b/x/oracle/abci.go index 891aa8078a..28f9d73461 100644 --- a/x/oracle/abci.go +++ b/x/oracle/abci.go @@ -77,8 +77,8 @@ func CalcPrices(ctx sdk.Context, params types.Params, k keeper.Keeper) error { if err != nil { return err } - k.SetExchangeRateWithEvent(ctx, denom, exchangeRate) + if k.IsPeriodLastBlock(ctx, params.HistoricStampPeriod) { k.AddHistoricPrice(ctx, denom, exchangeRate) } diff --git a/x/oracle/abci_test.go b/x/oracle/abci_test.go index 6bb4e8581b..6b57cb318c 100644 --- a/x/oracle/abci_test.go +++ b/x/oracle/abci_test.go @@ -6,7 +6,6 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" "github.com/cosmos/cosmos-sdk/x/staking" "github.com/cosmos/cosmos-sdk/x/staking/teststaking" @@ -157,7 +156,8 @@ func (s *IntegrationTestSuite) TestEndBlockerVoteThreshold() { for _, denom := range app.OracleKeeper.AcceptList(ctx) { rate, err := app.OracleKeeper.GetExchangeRate(ctx, denom.SymbolDenom) s.Require().NoError(err) - s.Require().Equal(sdk.MustNewDecFromStr("1.0"), rate) + s.Require().Equal(types.ExchangeRate{Rate: sdk.OneDec(), Timestamp: ctx.BlockTime()}, + rate) } // Test: only val2 votes (has 39% vote power). @@ -176,8 +176,8 @@ func (s *IntegrationTestSuite) TestEndBlockerVoteThreshold() { for _, denom := range app.OracleKeeper.AcceptList(ctx) { rate, err := app.OracleKeeper.GetExchangeRate(ctx, denom.SymbolDenom) - s.Require().ErrorIs(err, sdkerrors.Wrap(types.ErrUnknownDenom, denom.SymbolDenom)) - s.Require().Equal(sdk.ZeroDec(), rate) + s.Require().ErrorIs(err, types.ErrUnknownDenom.Wrap(denom.SymbolDenom)) + s.Require().Equal(types.ExchangeRate{}, rate) } // Test: val2 and val3 votes. @@ -199,7 +199,7 @@ func (s *IntegrationTestSuite) TestEndBlockerVoteThreshold() { for _, denom := range app.OracleKeeper.AcceptList(ctx) { rate, err := app.OracleKeeper.GetExchangeRate(ctx, denom.SymbolDenom) s.Require().NoError(err) - s.Require().Equal(sdk.MustNewDecFromStr("0.5"), rate) + s.Require().Equal(types.ExchangeRate{Rate: sdk.NewDecWithPrec(5, 1), Timestamp: ctx.BlockTime()}, rate) } // TODO: check reward distribution @@ -236,10 +236,10 @@ func (s *IntegrationTestSuite) TestEndBlockerVoteThreshold() { rate, err := app.OracleKeeper.GetExchangeRate(ctx, "umee") s.Require().NoError(err) - s.Require().Equal(sdk.MustNewDecFromStr("1.0"), rate) + s.Require().Equal(types.ExchangeRate{Rate: sdk.OneDec(), Timestamp: ctx.BlockTime()}, rate) rate, err = app.OracleKeeper.GetExchangeRate(ctx, "atom") - s.Require().ErrorIs(err, sdkerrors.Wrap(types.ErrUnknownDenom, "atom")) - s.Require().Equal(sdk.ZeroDec(), rate) + s.Require().ErrorIs(err, types.ErrUnknownDenom.Wrap("atom")) + s.Require().Equal(types.ExchangeRate{}, rate) } var exchangeRates = map[string][]sdk.Dec{ diff --git a/x/oracle/keeper/grpc_query.go b/x/oracle/keeper/grpc_query.go index 795942eadf..7d297ae7c7 100644 --- a/x/oracle/keeper/grpc_query.go +++ b/x/oracle/keeper/grpc_query.go @@ -52,6 +52,8 @@ func (q querier) ExchangeRates( ctx := sdk.UnwrapSDKContext(goCtx) + // TODO: need to decide if we want to return DecCoins here or list of ExchangeRates with denoms (we + // need the latter for genesis anyway) var exchangeRates sdk.DecCoins if len(req.Denom) > 0 { @@ -60,7 +62,7 @@ func (q querier) ExchangeRates( return nil, err } - exchangeRates = exchangeRates.Add(sdk.NewDecCoinFromDec(req.Denom, exchangeRate)) + exchangeRates = exchangeRates.Add(sdk.NewDecCoinFromDec(req.Denom, exchangeRate.Rate)) } else { q.IterateExchangeRates(ctx, func(denom string, rate sdk.Dec) (stop bool) { exchangeRates = exchangeRates.Add(sdk.NewDecCoinFromDec(denom, rate)) diff --git a/x/oracle/keeper/keeper.go b/x/oracle/keeper/keeper.go index e1bf4c2f35..35ccd7e1eb 100644 --- a/x/oracle/keeper/keeper.go +++ b/x/oracle/keeper/keeper.go @@ -2,7 +2,6 @@ package keeper import ( "fmt" - "strings" "github.com/cosmos/cosmos-sdk/codec" storetypes "github.com/cosmos/cosmos-sdk/store/types" @@ -12,7 +11,9 @@ import ( gogotypes "github.com/gogo/protobuf/types" "github.com/tendermint/tendermint/libs/log" + "github.com/umee-network/umee/v6/util" "github.com/umee-network/umee/v6/util/sdkutil" + "github.com/umee-network/umee/v6/util/store" "github.com/umee-network/umee/v6/x/oracle/types" ) @@ -72,22 +73,18 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { // GetExchangeRate gets the consensus exchange rate of USD denominated in the // denom asset from the store. -func (k Keeper) GetExchangeRate(ctx sdk.Context, symbol string) (sdk.Dec, error) { - store := ctx.KVStore(k.storeKey) - symbol = strings.ToUpper(symbol) - b := store.Get(types.KeyExchangeRate(symbol)) - if b == nil { - return sdk.ZeroDec(), types.ErrUnknownDenom.Wrap(symbol) +func (k Keeper) GetExchangeRate(ctx sdk.Context, symbol string) (types.ExchangeRate, error) { + v := store.GetValue[*types.ExchangeRate](ctx.KVStore(k.storeKey), types.KeyExchangeRate(symbol), + "exchange_rate") + if v == nil { + return types.ExchangeRate{}, types.ErrUnknownDenom.Wrap(symbol) } - - decProto := sdk.DecProto{} - k.cdc.MustUnmarshal(b, &decProto) - - return decProto.Dec, nil + return *v, nil } // GetExchangeRateBase gets the consensus exchange rate of an asset // in the base denom (e.g. ATOM -> uatom) +// TODO: needs to return timestamp as well func (k Keeper) GetExchangeRateBase(ctx sdk.Context, denom string) (sdk.Dec, error) { var symbol string var exponent uint64 @@ -110,16 +107,16 @@ func (k Keeper) GetExchangeRateBase(ctx sdk.Context, denom string) (sdk.Dec, err } powerReduction := ten.Power(exponent) - return exchangeRate.Quo(powerReduction), nil + return exchangeRate.Rate.Quo(powerReduction), nil } // SetExchangeRate sets the consensus exchange rate of USD denominated in the // denom asset to the store. -func (k Keeper) SetExchangeRate(ctx sdk.Context, denom string, exchangeRate sdk.Dec) { - store := ctx.KVStore(k.storeKey) - bz := k.cdc.MustMarshal(&sdk.DecProto{Dec: exchangeRate}) - denom = strings.ToUpper(denom) - store.Set(types.KeyExchangeRate(denom), bz) +func (k Keeper) SetExchangeRate(ctx sdk.Context, denom string, rate sdk.Dec) { + key := types.KeyExchangeRate(denom) + val := types.ExchangeRate{Rate: rate, Timestamp: ctx.BlockTime()} + err := store.SetValue(ctx.KVStore(k.storeKey), key, &val, "exchange_rate") + util.Panic(err) } // SetExchangeRateWithEvent sets an consensus @@ -132,6 +129,7 @@ func (k Keeper) SetExchangeRateWithEvent(ctx sdk.Context, denom string, exchange } // IterateExchangeRates iterates over all USD rates in the store. +// TODO: handler should use ExchangeRate type rather than Dec func (k Keeper) IterateExchangeRates(ctx sdk.Context, handler func(string, sdk.Dec) bool) { store := ctx.KVStore(k.storeKey) iter := sdk.KVStorePrefixIterator(store, types.KeyPrefixExchangeRate) @@ -141,10 +139,10 @@ func (k Keeper) IterateExchangeRates(ctx sdk.Context, handler func(string, sdk.D for ; iter.Valid(); iter.Next() { key := iter.Key() denom := string(key[prefixLen : len(key)-1]) // -1 to remove the null suffix - dp := sdk.DecProto{} - k.cdc.MustUnmarshal(iter.Value(), &dp) + var er types.ExchangeRate + k.cdc.MustUnmarshal(iter.Value(), &er) - if handler(denom, dp.Dec) { + if handler(denom, er.Rate) { break } } diff --git a/x/oracle/keeper/keeper_test.go b/x/oracle/keeper/keeper_test.go index a8d4dc043e..2d2d8d56d9 100644 --- a/x/oracle/keeper/keeper_test.go +++ b/x/oracle/keeper/keeper_test.go @@ -205,11 +205,11 @@ func (s *IntegrationTestSuite) TestAggregateExchangeRateVoteError() { } func (s *IntegrationTestSuite) TestSetExchangeRateWithEvent() { - app, ctx := s.app, s.ctx - app.OracleKeeper.SetExchangeRateWithEvent(ctx, displayDenom, sdk.OneDec()) - rate, err := app.OracleKeeper.GetExchangeRate(ctx, displayDenom) + v := sdk.OneDec() + s.app.OracleKeeper.SetExchangeRateWithEvent(s.ctx, displayDenom, v) + rate, err := s.app.OracleKeeper.GetExchangeRate(s.ctx, displayDenom) s.Require().NoError(err) - s.Require().Equal(rate, sdk.OneDec()) + s.Require().Equal(rate, types.ExchangeRate{Rate: v, Timestamp: s.ctx.BlockTime()}) } func (s *IntegrationTestSuite) TestGetExchangeRate_InvalidDenom() { @@ -227,17 +227,17 @@ func (s *IntegrationTestSuite) TestGetExchangeRate_NotSet() { } func (s *IntegrationTestSuite) TestGetExchangeRate_Valid() { - app, ctx := s.app, s.ctx - - app.OracleKeeper.SetExchangeRate(ctx, displayDenom, sdk.OneDec()) - rate, err := app.OracleKeeper.GetExchangeRate(ctx, displayDenom) + v := sdk.OneDec() + expected := types.ExchangeRate{Rate: v, Timestamp: s.ctx.BlockTime()} + s.app.OracleKeeper.SetExchangeRate(s.ctx, displayDenom, v) + rate, err := s.app.OracleKeeper.GetExchangeRate(s.ctx, displayDenom) s.Require().NoError(err) - s.Require().Equal(rate, sdk.OneDec()) + s.Require().Equal(rate, expected) - app.OracleKeeper.SetExchangeRate(ctx, strings.ToLower(displayDenom), sdk.OneDec()) - rate, err = app.OracleKeeper.GetExchangeRate(ctx, displayDenom) + s.app.OracleKeeper.SetExchangeRate(s.ctx, strings.ToLower(displayDenom), sdk.OneDec()) + rate, err = s.app.OracleKeeper.GetExchangeRate(s.ctx, displayDenom) s.Require().NoError(err) - s.Require().Equal(rate, sdk.OneDec()) + s.Require().Equal(rate, expected) } func (s *IntegrationTestSuite) TestGetExchangeRateBase() { diff --git a/x/oracle/types/genesis.pb.go b/x/oracle/types/genesis.pb.go index e8b352eddb..b4862a32bf 100644 --- a/x/oracle/types/genesis.pb.go +++ b/x/oracle/types/genesis.pb.go @@ -25,8 +25,9 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // GenesisState defines the oracle module's genesis state. type GenesisState struct { - Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` - FeederDelegations []FeederDelegation `protobuf:"bytes,2,rep,name=feeder_delegations,json=feederDelegations,proto3" json:"feeder_delegations"` + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` + FeederDelegations []FeederDelegation `protobuf:"bytes,2,rep,name=feeder_delegations,json=feederDelegations,proto3" json:"feeder_delegations"` + // TODO: need to update this to save data with timestamp ExchangeRates ExchangeRateTuples `protobuf:"bytes,3,rep,name=exchange_rates,json=exchangeRates,proto3,castrepeated=ExchangeRateTuples" json:"exchange_rates"` MissCounters []MissCounter `protobuf:"bytes,4,rep,name=miss_counters,json=missCounters,proto3" json:"miss_counters"` AggregateExchangeRatePrevotes []AggregateExchangeRatePrevote `protobuf:"bytes,5,rep,name=aggregate_exchange_rate_prevotes,json=aggregateExchangeRatePrevotes,proto3" json:"aggregate_exchange_rate_prevotes"` diff --git a/x/oracle/types/keys.go b/x/oracle/types/keys.go index 5dae6ef9ef..53359f0f36 100644 --- a/x/oracle/types/keys.go +++ b/x/oracle/types/keys.go @@ -2,6 +2,7 @@ package types import ( "encoding/binary" + "strings" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/address" @@ -33,7 +34,7 @@ var ( // KeyExchangeRate - stored by *denom* func KeyExchangeRate(denom string) []byte { // append 0 for null-termination - return util.ConcatBytes(1, KeyPrefixExchangeRate, []byte(denom)) + return util.ConcatBytes(1, KeyPrefixExchangeRate, []byte(strings.ToUpper(denom))) } // KeyFeederDelegation - stored by *Validator* address diff --git a/x/oracle/types/keys_test.go b/x/oracle/types/keys_test.go index 1475365376..e2f0c527c6 100644 --- a/x/oracle/types/keys_test.go +++ b/x/oracle/types/keys_test.go @@ -1,11 +1,10 @@ package types import ( - "fmt" "testing" sdk "github.com/cosmos/cosmos-sdk/types" - "gotest.tools/v3/assert" + "github.com/stretchr/testify/assert" appparams "github.com/umee-network/umee/v6/app/params" ) @@ -17,24 +16,24 @@ func TestKeyExchangeRate(t *testing.T) { expectedKey []byte }{ { + // converts uumee to UUMEE denom: appparams.BondDenom, - expectedKey: []byte{0x1, 0x75, 0x75, 0x6d, 0x65, 0x65, 0x0}, + expectedKey: []byte{0x1, 0x55, 0x55, 0x4d, 0x45, 0x45, 0x0}, }, { + // converts "Ibc" to "IBC" denom: IbcDenomLuna, - expectedKey: []byte{0x1, 0x69, 0x62, 0x63, 0x2f, 0x30, 0x45, 0x46, 0x31, 0x35, 0x44, 0x46, 0x32, 0x46, 0x30, 0x32, 0x34, 0x38, 0x30, 0x41, 0x44, 0x45, 0x30, 0x42, 0x42, 0x36, 0x45, 0x38, 0x35, 0x44, 0x39, 0x45, 0x42, 0x42, 0x35, 0x44, 0x41, 0x45, 0x41, 0x32, 0x38, 0x33, 0x36, 0x44, 0x33, 0x38, 0x36, 0x30, 0x45, 0x39, 0x46, 0x39, 0x37, 0x46, 0x39, 0x41, 0x41, 0x44, 0x45, 0x34, 0x46, 0x35, 0x37, 0x41, 0x33, 0x31, 0x41, 0x41, 0x30, 0x0}, + expectedKey: []byte{0x1, 0x49, 0x42, 0x43, 0x2f, 0x30, 0x45, 0x46, 0x31, 0x35, 0x44, 0x46, 0x32, 0x46, 0x30, 0x32, 0x34, 0x38, 0x30, 0x41, 0x44, 0x45, 0x30, 0x42, 0x42, 0x36, 0x45, 0x38, 0x35, 0x44, 0x39, 0x45, 0x42, 0x42, 0x35, 0x44, 0x41, 0x45, 0x41, 0x32, 0x38, 0x33, 0x36, 0x44, 0x33, 0x38, 0x36, 0x30, 0x45, 0x39, 0x46, 0x39, 0x37, 0x46, 0x39, 0x41, 0x41, 0x44, 0x45, 0x34, 0x46, 0x35, 0x37, 0x41, 0x33, 0x31, 0x41, 0x41, 0x30, 0x0}, }, { denom: IbcDenomAtom, - expectedKey: []byte{0x1, 0x69, 0x62, 0x63, 0x2f, 0x32, 0x37, 0x33, 0x39, 0x34, 0x46, 0x42, 0x30, 0x39, 0x32, 0x44, 0x32, 0x45, 0x43, 0x43, 0x44, 0x35, 0x36, 0x31, 0x32, 0x33, 0x43, 0x37, 0x34, 0x46, 0x33, 0x36, 0x45, 0x34, 0x43, 0x31, 0x46, 0x39, 0x32, 0x36, 0x30, 0x30, 0x31, 0x43, 0x45, 0x41, 0x44, 0x41, 0x39, 0x43, 0x41, 0x39, 0x37, 0x45, 0x41, 0x36, 0x32, 0x32, 0x42, 0x32, 0x35, 0x46, 0x34, 0x31, 0x45, 0x35, 0x45, 0x42, 0x32, 0x0}, + expectedKey: []byte{0x1, 0x49, 0x42, 0x43, 0x2f, 0x32, 0x37, 0x33, 0x39, 0x34, 0x46, 0x42, 0x30, 0x39, 0x32, 0x44, 0x32, 0x45, 0x43, 0x43, 0x44, 0x35, 0x36, 0x31, 0x32, 0x33, 0x43, 0x37, 0x34, 0x46, 0x33, 0x36, 0x45, 0x34, 0x43, 0x31, 0x46, 0x39, 0x32, 0x36, 0x30, 0x30, 0x31, 0x43, 0x45, 0x41, 0x44, 0x41, 0x39, 0x43, 0x41, 0x39, 0x37, 0x45, 0x41, 0x36, 0x32, 0x32, 0x42, 0x32, 0x35, 0x46, 0x34, 0x31, 0x45, 0x35, 0x45, 0x42, 0x32, 0x0}, }, } for i, testCase := range testCases { actualKey := KeyExchangeRate(testCase.denom) - t.Run(fmt.Sprintf("test %d - expected key: %s should be the same as actual key: %s", i, testCase.expectedKey, actualKey), func(t *testing.T) { - assert.DeepEqual(t, testCase.expectedKey, actualKey) - }) + assert.Equal(t, testCase.expectedKey, actualKey, "test: %v", i) } } @@ -52,9 +51,7 @@ func TestKeyFeederDelegation(t *testing.T) { for i, testCase := range testCases { actualKey := KeyFeederDelegation(testCase.val) - t.Run(fmt.Sprintf("test %d - expected key: %s should be the same as actual key: %s", i, testCase.expectedKey, actualKey), func(t *testing.T) { - assert.DeepEqual(t, testCase.expectedKey, actualKey) - }) + assert.Equal(t, testCase.expectedKey, actualKey, "test: %v", i) } } @@ -72,9 +69,7 @@ func TestKeyMissCounter(t *testing.T) { for i, testCase := range testCases { actualKey := KeyMissCounter(testCase.val) - t.Run(fmt.Sprintf("test %d - expected key: %s should be the same as actual key: %s", i, testCase.expectedKey, actualKey), func(t *testing.T) { - assert.DeepEqual(t, testCase.expectedKey, actualKey) - }) + assert.Equal(t, testCase.expectedKey, actualKey, "test: %v", i) } } @@ -92,9 +87,7 @@ func TestKeyAggregateExchangeRatePrevote(t *testing.T) { for i, testCase := range testCases { actualKey := KeyAggregateExchangeRatePrevote(testCase.val) - t.Run(fmt.Sprintf("test %d - expected key: %s should be the same as actual key: %s", i, testCase.expectedKey, actualKey), func(t *testing.T) { - assert.DeepEqual(t, testCase.expectedKey, actualKey) - }) + assert.Equal(t, testCase.expectedKey, actualKey, "test: %v", i) } } @@ -112,9 +105,7 @@ func TestKeyAggregateExchangeRateVote(t *testing.T) { for i, testCase := range testCases { actualKey := KeyAggregateExchangeRateVote(testCase.val) - t.Run(fmt.Sprintf("test %d - expected key: %s should be the same as actual key: %s", i, testCase.expectedKey, actualKey), func(t *testing.T) { - assert.DeepEqual(t, testCase.expectedKey, actualKey) - }) + assert.Equal(t, testCase.expectedKey, actualKey, "test: %v", i) } } diff --git a/x/oracle/types/msgs_test.go b/x/oracle/types/msgs_test.go index e8051eff39..dbc7ab7c7a 100644 --- a/x/oracle/types/msgs_test.go +++ b/x/oracle/types/msgs_test.go @@ -122,9 +122,9 @@ func TestMsgAggregateExchangeRateVote(t *testing.T) { for i, tc := range tests { msg := NewMsgAggregateExchangeRateVote(tc.salt, tc.exchangeRates, tc.feeder, sdk.ValAddress(tc.validator)) if tc.expectPass { - assert.NilError(t, msg.ValidateBasic(), "test: %v", i) + assert.NilError(t, msg.ValidateBasic(), "test: %d", i) } else { - assert.ErrorContains(t, msg.ValidateBasic(), tc.expectedErrorMsg) + assert.ErrorContains(t, msg.ValidateBasic(), "", "test", i, "expected_err", tc.expectedErrorMsg) } } } diff --git a/x/oracle/types/oracle.pb.go b/x/oracle/types/oracle.pb.go index 25abff1771..4d51ad8e5b 100644 --- a/x/oracle/types/oracle.pb.go +++ b/x/oracle/types/oracle.pb.go @@ -330,6 +330,44 @@ func (m *AvgCounter) XXX_DiscardUnknown() { var xxx_messageInfo_AvgCounter proto.InternalMessageInfo +// ExchangeRate stores exchange rate with timestamp +type ExchangeRate struct { + Rate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,1,opt,name=rate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"rate"` + Timestamp time.Time `protobuf:"bytes,3,opt,name=timestamp,proto3,stdtime" json:"timestamp"` +} + +func (m *ExchangeRate) Reset() { *m = ExchangeRate{} } +func (*ExchangeRate) ProtoMessage() {} +func (*ExchangeRate) Descriptor() ([]byte, []int) { + return fileDescriptor_8893c9e0e94ceb54, []int{7} +} +func (m *ExchangeRate) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ExchangeRate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ExchangeRate.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ExchangeRate) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExchangeRate.Merge(m, src) +} +func (m *ExchangeRate) XXX_Size() int { + return m.Size() +} +func (m *ExchangeRate) XXX_DiscardUnknown() { + xxx_messageInfo_ExchangeRate.DiscardUnknown(m) +} + +var xxx_messageInfo_ExchangeRate proto.InternalMessageInfo + func init() { proto.RegisterType((*Params)(nil), "umee.oracle.v1.Params") proto.RegisterType((*AvgCounterParams)(nil), "umee.oracle.v1.AvgCounterParams") @@ -338,78 +376,81 @@ func init() { proto.RegisterType((*AggregateExchangeRateVote)(nil), "umee.oracle.v1.AggregateExchangeRateVote") proto.RegisterType((*ExchangeRateTuple)(nil), "umee.oracle.v1.ExchangeRateTuple") proto.RegisterType((*AvgCounter)(nil), "umee.oracle.v1.AvgCounter") + proto.RegisterType((*ExchangeRate)(nil), "umee.oracle.v1.ExchangeRate") } func init() { proto.RegisterFile("umee/oracle/v1/oracle.proto", fileDescriptor_8893c9e0e94ceb54) } var fileDescriptor_8893c9e0e94ceb54 = []byte{ - // 1052 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xcf, 0x6f, 0xdc, 0x44, - 0x14, 0x5e, 0x93, 0x26, 0xdd, 0x9d, 0x4d, 0xda, 0xc4, 0xd9, 0x80, 0x9b, 0xa0, 0x75, 0x6a, 0x44, - 0xc9, 0x81, 0xda, 0x34, 0xe5, 0x87, 0xd8, 0x13, 0x35, 0xa1, 0x5c, 0x5a, 0x29, 0x72, 0xa3, 0x22, - 0x71, 0xb1, 0x66, 0xed, 0x89, 0x77, 0x14, 0xdb, 0xb3, 0x9a, 0x19, 0x6f, 0x92, 0x0b, 0xe7, 0x9e, - 0x50, 0x8f, 0x3d, 0xe6, 0xc4, 0x81, 0x3b, 0x88, 0x3f, 0x21, 0xc7, 0x1e, 0x11, 0x07, 0x17, 0x92, - 0x0b, 0xe2, 0x84, 0xf6, 0x2f, 0x40, 0xf3, 0xc3, 0x59, 0x6f, 0x36, 0x42, 0x44, 0x9c, 0xd6, 0x6f, - 0xbe, 0xf7, 0xde, 0xf7, 0xbd, 0x37, 0x6f, 0x9e, 0x16, 0x6c, 0x14, 0x19, 0x42, 0x1e, 0xa1, 0x30, - 0x4a, 0x91, 0x37, 0x7a, 0xa0, 0xbf, 0xdc, 0x21, 0x25, 0x9c, 0x98, 0xb7, 0x04, 0xe8, 0xea, 0xa3, - 0xd1, 0x83, 0xf5, 0x4e, 0x42, 0x12, 0x22, 0x21, 0x4f, 0x7c, 0x29, 0xaf, 0x75, 0x3b, 0x21, 0x24, - 0x49, 0x91, 0x27, 0xad, 0x7e, 0xb1, 0xef, 0x71, 0x9c, 0x21, 0xc6, 0x61, 0x36, 0xd4, 0x0e, 0xdd, - 0xcb, 0x0e, 0x71, 0x41, 0x21, 0xc7, 0x24, 0x57, 0xb8, 0x53, 0xde, 0x04, 0x0b, 0xbb, 0x90, 0xc2, - 0x8c, 0x99, 0x9f, 0x81, 0xf6, 0x88, 0x70, 0x14, 0x0e, 0x11, 0xc5, 0x24, 0xb6, 0x8c, 0x4d, 0x63, - 0xeb, 0x86, 0xff, 0xf6, 0xb8, 0xb4, 0xcd, 0x63, 0x98, 0xa5, 0x3d, 0xa7, 0x06, 0x3a, 0x01, 0x10, - 0xd6, 0xae, 0x34, 0xcc, 0x1c, 0xdc, 0x92, 0x18, 0x1f, 0x50, 0xc4, 0x06, 0x24, 0x8d, 0xad, 0xb7, - 0x36, 0x8d, 0xad, 0x96, 0xff, 0xf5, 0x69, 0x69, 0x37, 0x7e, 0x2b, 0xed, 0x7b, 0x09, 0xe6, 0x83, - 0xa2, 0xef, 0x46, 0x24, 0xf3, 0x22, 0xc2, 0x32, 0xc2, 0xf4, 0xcf, 0x7d, 0x16, 0x1f, 0x78, 0xfc, - 0x78, 0x88, 0x98, 0xbb, 0x83, 0xa2, 0x71, 0x69, 0xaf, 0xd5, 0x98, 0x2e, 0xb2, 0x39, 0xc1, 0x92, - 0x38, 0xd8, 0xab, 0x6c, 0x13, 0x81, 0x36, 0x45, 0x87, 0x90, 0xc6, 0x61, 0x1f, 0xe6, 0xb1, 0x35, - 0x27, 0xc9, 0x76, 0xae, 0x4d, 0xa6, 0xcb, 0xaa, 0xa5, 0x72, 0x02, 0xa0, 0x2c, 0x1f, 0xe6, 0xb1, - 0x19, 0x81, 0x75, 0x8d, 0xc5, 0x98, 0x71, 0x8a, 0xfb, 0x85, 0xe8, 0x5b, 0x78, 0x88, 0xf3, 0x98, - 0x1c, 0x5a, 0x37, 0x64, 0x7b, 0xde, 0x1f, 0x97, 0xf6, 0xdd, 0xa9, 0x3c, 0x57, 0xf8, 0x3a, 0x81, - 0xa5, 0xc0, 0x9d, 0x1a, 0xf6, 0x8d, 0x84, 0xcc, 0x10, 0xb4, 0x61, 0x14, 0xa1, 0x21, 0x0f, 0x53, - 0xcc, 0xb8, 0x35, 0xbf, 0x39, 0xb7, 0xd5, 0xde, 0x5e, 0x73, 0xa7, 0x2f, 0xdf, 0xdd, 0x41, 0x39, - 0xc9, 0xfc, 0x0f, 0x44, 0x89, 0x13, 0xe1, 0xb5, 0x38, 0xe7, 0xc7, 0x37, 0x76, 0x4b, 0x3a, 0x3d, - 0xc1, 0x8c, 0x07, 0x40, 0x41, 0xe2, 0x5b, 0x5c, 0x0e, 0x4b, 0x21, 0x1b, 0x84, 0xfb, 0x14, 0x46, - 0x82, 0xd8, 0x5a, 0xf8, 0x7f, 0x97, 0x33, 0x9d, 0xcd, 0x09, 0x96, 0xe4, 0xc1, 0x63, 0x6d, 0x9b, - 0x3d, 0xb0, 0xa8, 0x3c, 0x74, 0x9f, 0x6e, 0xca, 0x3e, 0xbd, 0x33, 0x2e, 0xed, 0xd5, 0x7a, 0x7c, - 0xd5, 0x99, 0xb6, 0x34, 0x75, 0x33, 0xbe, 0x03, 0x9d, 0x0c, 0xe7, 0xe1, 0x08, 0xa6, 0x38, 0x16, - 0x93, 0x56, 0xe5, 0x68, 0x4a, 0xc5, 0x4f, 0xaf, 0xad, 0x78, 0x43, 0x31, 0x5e, 0x95, 0xd3, 0x09, - 0x56, 0x32, 0x9c, 0x3f, 0x17, 0xa7, 0xbb, 0x88, 0x6a, 0xfe, 0x6d, 0xb0, 0x36, 0xc0, 0x8c, 0x13, - 0x8a, 0xa3, 0x50, 0x3e, 0xa2, 0xea, 0x2d, 0xb4, 0x44, 0x11, 0xc1, 0x6a, 0x05, 0x3e, 0x13, 0x98, - 0x1e, 0x7e, 0x17, 0xac, 0x66, 0x28, 0xc6, 0x30, 0x9f, 0x8e, 0x00, 0x32, 0x62, 0x45, 0x41, 0x75, - 0xff, 0x8f, 0x40, 0x27, 0x83, 0x47, 0x38, 0x2b, 0xb2, 0x70, 0x48, 0x71, 0x84, 0x54, 0x18, 0xb3, - 0xda, 0x32, 0xc0, 0xd4, 0xd8, 0xae, 0x80, 0x64, 0x18, 0x13, 0xaa, 0xaa, 0x88, 0x3a, 0x13, 0xb3, - 0x16, 0x95, 0x2a, 0x0d, 0x3e, 0x9d, 0x50, 0xb1, 0x5e, 0xf3, 0xd5, 0x89, 0xdd, 0xf8, 0xf3, 0xc4, - 0x36, 0x9c, 0xbf, 0x0d, 0xb0, 0xfc, 0x68, 0x94, 0x7c, 0x49, 0x8a, 0x9c, 0x23, 0xaa, 0x9f, 0x3a, - 0x01, 0x00, 0x8e, 0x92, 0xfa, 0x4b, 0x6f, 0x6f, 0xdf, 0x71, 0xd5, 0xaa, 0x70, 0xab, 0x55, 0xe1, - 0xee, 0xe8, 0x55, 0xe1, 0x7f, 0x22, 0x3a, 0xff, 0x57, 0x69, 0x77, 0x26, 0x41, 0x1f, 0x92, 0x0c, - 0x73, 0x94, 0x0d, 0xf9, 0xf1, 0xb8, 0xb4, 0x57, 0xf4, 0x40, 0x5e, 0xa0, 0xce, 0xab, 0x37, 0xb6, - 0x11, 0xb4, 0xe0, 0x28, 0xd1, 0x55, 0x1f, 0x00, 0x61, 0x84, 0x6c, 0x80, 0xf7, 0xb9, 0xdc, 0x0e, - 0xff, 0xca, 0xf7, 0x50, 0xf3, 0xad, 0x5e, 0xc4, 0x4c, 0xd1, 0x2d, 0x4f, 0xe8, 0x24, 0xa8, 0xd8, - 0x9a, 0x70, 0x94, 0x3c, 0x93, 0xe6, 0x2f, 0x06, 0x98, 0x97, 0x8f, 0xc1, 0xfc, 0x18, 0x80, 0x3e, - 0x64, 0x28, 0x8c, 0x85, 0x25, 0xeb, 0x6c, 0xf9, 0x6b, 0x13, 0xc1, 0x13, 0xcc, 0x09, 0x5a, 0xc2, - 0x50, 0x51, 0x62, 0x84, 0x8f, 0xb3, 0x3e, 0x49, 0x75, 0x9c, 0xda, 0x66, 0xf5, 0x11, 0xae, 0xa1, - 0x62, 0x84, 0xa5, 0xa9, 0x62, 0x3d, 0xd0, 0x44, 0x47, 0x43, 0x92, 0xa3, 0x9c, 0xcb, 0xc5, 0xb4, - 0xe4, 0xaf, 0x8e, 0x4b, 0xfb, 0xb6, 0x8a, 0xab, 0x10, 0x27, 0xb8, 0x70, 0xea, 0x2d, 0xbe, 0x38, - 0xb1, 0x1b, 0xfa, 0xb6, 0x1a, 0xce, 0x4f, 0x06, 0x78, 0xf7, 0x51, 0x92, 0x50, 0x94, 0x40, 0x8e, - 0xbe, 0x3a, 0x8a, 0x06, 0x30, 0x4f, 0x50, 0x00, 0x39, 0xda, 0xa5, 0x48, 0x2c, 0x41, 0xf3, 0x3d, - 0x70, 0x63, 0x00, 0xd9, 0x40, 0xd7, 0x72, 0x7b, 0x5c, 0xda, 0x6d, 0x95, 0x5b, 0x9c, 0x3a, 0x81, - 0x04, 0xcd, 0x7b, 0x60, 0x5e, 0x38, 0x53, 0xad, 0x7c, 0x79, 0x5c, 0xda, 0x8b, 0x93, 0xcd, 0x4a, - 0x9d, 0x40, 0xc1, 0xb2, 0xd0, 0xa2, 0x9f, 0x61, 0x1e, 0xf6, 0x53, 0x12, 0x1d, 0x48, 0xc1, 0xd3, - 0x6f, 0xb5, 0x86, 0x8a, 0x42, 0xa5, 0xe9, 0x0b, 0xeb, 0x92, 0xee, 0x33, 0x03, 0xdc, 0xb9, 0x52, - 0xf7, 0x73, 0x21, 0xfa, 0x7b, 0x03, 0x74, 0x90, 0x3e, 0x0c, 0x29, 0x14, 0xcb, 0xbd, 0x18, 0xa6, - 0x88, 0x59, 0x86, 0x5c, 0x77, 0x77, 0x2f, 0xaf, 0xbb, 0x7a, 0x82, 0x3d, 0xe1, 0xe9, 0x7f, 0xae, - 0x57, 0xdf, 0x46, 0xd5, 0xc8, 0xd9, 0x64, 0x62, 0x07, 0x9a, 0x33, 0x91, 0x2c, 0x30, 0xd1, 0xcc, - 0xd9, 0x7f, 0x6d, 0xd0, 0xa5, 0x22, 0x7f, 0x36, 0xc0, 0xca, 0x0c, 0x81, 0xc8, 0x55, 0x1f, 0xaf, - 0x5a, 0x2e, 0x3d, 0x1f, 0x0a, 0x36, 0x0f, 0xc0, 0xd2, 0x94, 0x6c, 0xcd, 0xfd, 0xf8, 0xda, 0x5b, - 0xad, 0x73, 0x45, 0x0f, 0x9c, 0x60, 0xb1, 0x5e, 0xe6, 0x25, 0xe1, 0x3f, 0x18, 0x00, 0x4c, 0x76, - 0x80, 0xf9, 0x05, 0x98, 0x63, 0x45, 0xa5, 0xd7, 0xbd, 0x1e, 0x7f, 0x20, 0x42, 0xcd, 0x65, 0x30, - 0x97, 0x17, 0xea, 0x61, 0x2c, 0x05, 0xe2, 0xd3, 0xec, 0x81, 0x79, 0xc6, 0x21, 0x55, 0x43, 0xdf, - 0xde, 0x5e, 0x9f, 0x79, 0xdc, 0x7b, 0xd5, 0x1f, 0x13, 0xbf, 0x29, 0x18, 0x5f, 0x8a, 0x27, 0xab, - 0x42, 0x7a, 0xcd, 0x17, 0x5a, 0xa8, 0xff, 0xe4, 0xf4, 0x8f, 0x6e, 0xe3, 0xf4, 0xac, 0x6b, 0xbc, - 0x3e, 0xeb, 0x1a, 0xbf, 0x9f, 0x75, 0x8d, 0x97, 0xe7, 0xdd, 0xc6, 0xeb, 0xf3, 0x6e, 0xe3, 0xd7, - 0xf3, 0x6e, 0xe3, 0x5b, 0xb7, 0x26, 0x51, 0x4c, 0xcc, 0xfd, 0x1c, 0xf1, 0x43, 0x42, 0x0f, 0xa4, - 0xe1, 0x8d, 0x3e, 0xf5, 0x8e, 0xaa, 0x3f, 0x53, 0x52, 0x6e, 0x7f, 0x41, 0x92, 0x3f, 0xfc, 0x27, - 0x00, 0x00, 0xff, 0xff, 0x78, 0xba, 0x04, 0x76, 0x68, 0x09, 0x00, 0x00, + // 1074 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xcd, 0x6f, 0x1b, 0x45, + 0x14, 0xf7, 0x92, 0x8f, 0xda, 0xe3, 0xa4, 0x4d, 0x36, 0x0e, 0xb8, 0x09, 0xf2, 0xa6, 0x8b, 0x28, + 0x39, 0xd0, 0x35, 0x4d, 0xf9, 0x10, 0x39, 0xd1, 0x25, 0x94, 0x4b, 0x2b, 0x45, 0xdb, 0xa8, 0x48, + 0x5c, 0x56, 0xe3, 0xdd, 0xc9, 0x7a, 0x14, 0xef, 0x8e, 0x35, 0x33, 0xeb, 0x24, 0x17, 0xce, 0x9c, + 0x50, 0x8f, 0x3d, 0xe6, 0xc4, 0x81, 0x1b, 0x88, 0x3f, 0x22, 0xc7, 0x1e, 0x11, 0x87, 0x2d, 0x24, + 0x17, 0xc4, 0x09, 0xf9, 0x2f, 0x40, 0xf3, 0xb1, 0xde, 0x71, 0x13, 0x21, 0x0c, 0x27, 0xef, 0x9b, + 0xdf, 0xfc, 0xde, 0xfb, 0xbd, 0x37, 0xef, 0x3d, 0x19, 0x6c, 0xe6, 0x29, 0x42, 0x5d, 0x42, 0x61, + 0x34, 0x40, 0xdd, 0xd1, 0x7d, 0xfd, 0xe5, 0x0d, 0x29, 0xe1, 0xc4, 0xbe, 0x29, 0x40, 0x4f, 0x1f, + 0x8d, 0xee, 0x6f, 0xb4, 0x12, 0x92, 0x10, 0x09, 0x75, 0xc5, 0x97, 0xba, 0xb5, 0xe1, 0x24, 0x84, + 0x24, 0x03, 0xd4, 0x95, 0x56, 0x2f, 0x3f, 0xec, 0x72, 0x9c, 0x22, 0xc6, 0x61, 0x3a, 0xd4, 0x17, + 0x3a, 0xaf, 0x5f, 0x88, 0x73, 0x0a, 0x39, 0x26, 0x99, 0xc2, 0xdd, 0xe2, 0x06, 0x58, 0xdc, 0x87, + 0x14, 0xa6, 0xcc, 0xfe, 0x04, 0x34, 0x47, 0x84, 0xa3, 0x70, 0x88, 0x28, 0x26, 0x71, 0xdb, 0xda, + 0xb2, 0xb6, 0xe7, 0xfd, 0x37, 0xc7, 0x85, 0x63, 0x9f, 0xc2, 0x74, 0xb0, 0xeb, 0x1a, 0xa0, 0x1b, + 0x00, 0x61, 0xed, 0x4b, 0xc3, 0xce, 0xc0, 0x4d, 0x89, 0xf1, 0x3e, 0x45, 0xac, 0x4f, 0x06, 0x71, + 0xfb, 0x8d, 0x2d, 0x6b, 0xbb, 0xe1, 0x7f, 0x79, 0x5e, 0x38, 0xb5, 0x5f, 0x0b, 0xe7, 0x6e, 0x82, + 0x79, 0x3f, 0xef, 0x79, 0x11, 0x49, 0xbb, 0x11, 0x61, 0x29, 0x61, 0xfa, 0xe7, 0x1e, 0x8b, 0x8f, + 0xba, 0xfc, 0x74, 0x88, 0x98, 0xb7, 0x87, 0xa2, 0x71, 0xe1, 0xac, 0x1b, 0x91, 0x26, 0xde, 0xdc, + 0x60, 0x59, 0x1c, 0x1c, 0x94, 0xb6, 0x8d, 0x40, 0x93, 0xa2, 0x63, 0x48, 0xe3, 0xb0, 0x07, 0xb3, + 0xb8, 0x3d, 0x27, 0x83, 0xed, 0xcd, 0x1c, 0x4c, 0xa7, 0x65, 0xb8, 0x72, 0x03, 0xa0, 0x2c, 0x1f, + 0x66, 0xb1, 0x1d, 0x81, 0x0d, 0x8d, 0xc5, 0x98, 0x71, 0x8a, 0x7b, 0xb9, 0xa8, 0x5b, 0x78, 0x8c, + 0xb3, 0x98, 0x1c, 0xb7, 0xe7, 0x65, 0x79, 0xde, 0x1d, 0x17, 0xce, 0x9d, 0x29, 0x3f, 0xd7, 0xdc, + 0x75, 0x83, 0xb6, 0x02, 0xf7, 0x0c, 0xec, 0x2b, 0x09, 0xd9, 0x21, 0x68, 0xc2, 0x28, 0x42, 0x43, + 0x1e, 0x0e, 0x30, 0xe3, 0xed, 0x85, 0xad, 0xb9, 0xed, 0xe6, 0xce, 0xba, 0x37, 0xfd, 0xf8, 0xde, + 0x1e, 0xca, 0x48, 0xea, 0xbf, 0x27, 0x52, 0xac, 0x84, 0x1b, 0x3c, 0xf7, 0x87, 0x57, 0x4e, 0x43, + 0x5e, 0x7a, 0x8c, 0x19, 0x0f, 0x80, 0x82, 0xc4, 0xb7, 0x78, 0x1c, 0x36, 0x80, 0xac, 0x1f, 0x1e, + 0x52, 0x18, 0x89, 0xc0, 0xed, 0xc5, 0xff, 0xf7, 0x38, 0xd3, 0xde, 0xdc, 0x60, 0x59, 0x1e, 0x3c, + 0xd2, 0xb6, 0xbd, 0x0b, 0x96, 0xd4, 0x0d, 0x5d, 0xa7, 0x1b, 0xb2, 0x4e, 0x6f, 0x8d, 0x0b, 0x67, + 0xcd, 0xe4, 0x97, 0x95, 0x69, 0x4a, 0x53, 0x17, 0xe3, 0x1b, 0xd0, 0x4a, 0x71, 0x16, 0x8e, 0xe0, + 0x00, 0xc7, 0xa2, 0xd3, 0x4a, 0x1f, 0x75, 0xa9, 0xf8, 0xc9, 0xcc, 0x8a, 0x37, 0x55, 0xc4, 0xeb, + 0x7c, 0xba, 0xc1, 0x6a, 0x8a, 0xb3, 0x67, 0xe2, 0x74, 0x1f, 0x51, 0x1d, 0x7f, 0x07, 0xac, 0xf7, + 0x31, 0xe3, 0x84, 0xe2, 0x28, 0x94, 0x43, 0x54, 0xce, 0x42, 0x43, 0x24, 0x11, 0xac, 0x95, 0xe0, + 0x53, 0x81, 0xe9, 0xe6, 0xf7, 0xc0, 0x5a, 0x8a, 0x62, 0x0c, 0xb3, 0x69, 0x06, 0x90, 0x8c, 0x55, + 0x05, 0x99, 0xf7, 0x3f, 0x00, 0xad, 0x14, 0x9e, 0xe0, 0x34, 0x4f, 0xc3, 0x21, 0xc5, 0x11, 0x52, + 0x34, 0xd6, 0x6e, 0x4a, 0x82, 0xad, 0xb1, 0x7d, 0x01, 0x49, 0x1a, 0x13, 0xaa, 0x4a, 0x86, 0x19, + 0x89, 0xb5, 0x97, 0x94, 0x2a, 0x0d, 0x3e, 0xa9, 0x42, 0xb1, 0xdd, 0xfa, 0x8b, 0x33, 0xa7, 0xf6, + 0xc7, 0x99, 0x63, 0xb9, 0x7f, 0x59, 0x60, 0xe5, 0xe1, 0x28, 0xf9, 0x9c, 0xe4, 0x19, 0x47, 0x54, + 0x8f, 0x3a, 0x01, 0x00, 0x8e, 0x12, 0x73, 0xd2, 0x9b, 0x3b, 0xb7, 0x3d, 0xb5, 0x2a, 0xbc, 0x72, + 0x55, 0x78, 0x7b, 0x7a, 0x55, 0xf8, 0x1f, 0x89, 0xca, 0xff, 0x59, 0x38, 0xad, 0x8a, 0xf4, 0x3e, + 0x49, 0x31, 0x47, 0xe9, 0x90, 0x9f, 0x8e, 0x0b, 0x67, 0x55, 0x37, 0xe4, 0x04, 0x75, 0x5f, 0xbc, + 0x72, 0xac, 0xa0, 0x01, 0x47, 0x89, 0xce, 0xfa, 0x08, 0x08, 0x23, 0x64, 0x7d, 0x7c, 0xc8, 0xe5, + 0x76, 0xf8, 0xc7, 0x78, 0x0f, 0x74, 0xbc, 0xb5, 0x09, 0x67, 0x2a, 0xdc, 0x4a, 0x15, 0x4e, 0x82, + 0x2a, 0x5a, 0x1d, 0x8e, 0x92, 0xa7, 0xd2, 0xfc, 0xd9, 0x02, 0x0b, 0x72, 0x18, 0xec, 0x0f, 0x01, + 0xe8, 0x41, 0x86, 0xc2, 0x58, 0x58, 0x32, 0xcf, 0x86, 0xbf, 0x5e, 0x09, 0xae, 0x30, 0x37, 0x68, + 0x08, 0x43, 0xb1, 0x44, 0x0b, 0x9f, 0xa6, 0x3d, 0x32, 0xd0, 0x3c, 0xb5, 0xcd, 0xcc, 0x16, 0x36, + 0x50, 0xd1, 0xc2, 0xd2, 0x54, 0xdc, 0x2e, 0xa8, 0xa3, 0x93, 0x21, 0xc9, 0x50, 0xc6, 0xe5, 0x62, + 0x5a, 0xf6, 0xd7, 0xc6, 0x85, 0x73, 0x4b, 0xf1, 0x4a, 0xc4, 0x0d, 0x26, 0x97, 0x26, 0x2f, 0x55, + 0x73, 0x7f, 0xb4, 0xc0, 0xdb, 0x0f, 0x93, 0x84, 0xa2, 0x04, 0x72, 0xf4, 0xc5, 0x49, 0xd4, 0x87, + 0x59, 0x82, 0x02, 0xc8, 0xd1, 0x3e, 0x45, 0x62, 0x01, 0xda, 0xef, 0x80, 0xf9, 0x3e, 0x64, 0x7d, + 0x9d, 0xc7, 0xad, 0x71, 0xe1, 0x34, 0x95, 0x5f, 0x71, 0xea, 0x06, 0x12, 0xb4, 0xef, 0x82, 0x05, + 0x71, 0x99, 0x6a, 0xd5, 0x2b, 0xe3, 0xc2, 0x59, 0xaa, 0xb6, 0x2a, 0x75, 0x03, 0x05, 0xcb, 0x24, + 0xf3, 0x5e, 0x8a, 0x79, 0xd8, 0x1b, 0x90, 0xe8, 0x48, 0x8a, 0x9d, 0x9e, 0x53, 0x03, 0x15, 0x49, + 0x4a, 0xd3, 0x17, 0x96, 0xa1, 0xb9, 0xb0, 0xc0, 0xed, 0x6b, 0x35, 0x3f, 0x13, 0x82, 0xbf, 0xb3, + 0x40, 0x0b, 0xe9, 0xc3, 0x90, 0x42, 0xb1, 0xd4, 0xf3, 0xe1, 0x00, 0xb1, 0xb6, 0x25, 0xd7, 0xdc, + 0x9d, 0xd7, 0xd7, 0x9c, 0xe9, 0xe0, 0x40, 0xdc, 0xf4, 0x3f, 0xd5, 0x2b, 0x6f, 0xb3, 0x2c, 0xe0, + 0x55, 0x67, 0x62, 0xf7, 0xd9, 0x57, 0x98, 0x2c, 0xb0, 0xd1, 0x95, 0xb3, 0x7f, 0x5b, 0x1c, 0x23, + 0xc1, 0x9f, 0x2c, 0xb0, 0x7a, 0xc5, 0xb9, 0xf0, 0x63, 0xb6, 0x94, 0xe1, 0x47, 0xf7, 0x84, 0x82, + 0xed, 0x23, 0xb0, 0x3c, 0x25, 0x59, 0xc7, 0x7d, 0x34, 0xf3, 0x26, 0x6b, 0x5d, 0x93, 0xbf, 0x1b, + 0x2c, 0x99, 0x29, 0x1a, 0xa2, 0xbf, 0xb7, 0x00, 0xa8, 0x66, 0xde, 0xfe, 0x0c, 0xcc, 0xb1, 0xbc, + 0xd4, 0xea, 0xcd, 0x16, 0x3b, 0x10, 0x54, 0x7b, 0x05, 0xcc, 0x65, 0xb9, 0x1a, 0x84, 0xe5, 0x40, + 0x7c, 0xda, 0xbb, 0x60, 0x81, 0x71, 0x48, 0x55, 0x93, 0x37, 0x77, 0x36, 0xae, 0x0c, 0xf3, 0x41, + 0xf9, 0x47, 0xc4, 0xaf, 0x8b, 0x88, 0xcf, 0xc5, 0x88, 0x2a, 0xca, 0x6e, 0xfd, 0xdb, 0x52, 0xe8, + 0x99, 0x05, 0x96, 0xcc, 0xea, 0xda, 0x3e, 0x98, 0x97, 0x75, 0xfa, 0x6f, 0x5a, 0x25, 0xd7, 0xf6, + 0x41, 0x63, 0xf2, 0x2f, 0x68, 0x26, 0x79, 0x15, 0xad, 0xaa, 0xa5, 0xff, 0xf8, 0xfc, 0xf7, 0x4e, + 0xed, 0xfc, 0xa2, 0x63, 0xbd, 0xbc, 0xe8, 0x58, 0xbf, 0x5d, 0x74, 0xac, 0xe7, 0x97, 0x9d, 0xda, + 0xcb, 0xcb, 0x4e, 0xed, 0x97, 0xcb, 0x4e, 0xed, 0x6b, 0xcf, 0x50, 0x26, 0x9a, 0xf9, 0x5e, 0x86, + 0xf8, 0x31, 0xa1, 0x47, 0xd2, 0xe8, 0x8e, 0x3e, 0xee, 0x9e, 0x94, 0xff, 0xef, 0xa4, 0xca, 0xde, + 0xa2, 0x14, 0xf0, 0xe0, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0xed, 0xc7, 0x26, 0x38, 0xfb, 0x09, + 0x00, 0x00, } func (this *Params) Equal(that interface{}) bool { @@ -839,6 +880,47 @@ func (m *AvgCounter) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *ExchangeRate) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ExchangeRate) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExchangeRate) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n4, err4 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp):]) + if err4 != nil { + return 0, err4 + } + i -= n4 + i = encodeVarintOracle(dAtA, i, uint64(n4)) + i-- + dAtA[i] = 0x1a + { + size := m.Rate.Size() + i -= size + if _, err := m.Rate.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintOracle(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func encodeVarintOracle(dAtA []byte, offset int, v uint64) int { offset -= sovOracle(v) base := offset @@ -997,6 +1079,19 @@ func (m *AvgCounter) Size() (n int) { return n } +func (m *ExchangeRate) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Rate.Size() + n += 1 + l + sovOracle(uint64(l)) + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp) + n += 1 + l + sovOracle(uint64(l)) + return n +} + func sovOracle(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -2106,6 +2201,123 @@ func (m *AvgCounter) Unmarshal(dAtA []byte) error { } return nil } +func (m *ExchangeRate) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ExchangeRate: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExchangeRate: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Rate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Rate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipOracle(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthOracle + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipOracle(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/oracle/types/vote.go b/x/oracle/types/vote.go index 69d1a62dba..98991c1d56 100644 --- a/x/oracle/types/vote.go +++ b/x/oracle/types/vote.go @@ -1,14 +1,14 @@ package types import ( + "encoding/json" "fmt" "strings" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/umee-network/umee/v6/util/sdkutil" "gopkg.in/yaml.v3" - - "github.com/umee-network/umee/v6/x/leverage/types" ) func NewAggregateExchangeRatePrevote( @@ -53,10 +53,12 @@ func NewExchangeRateTuple(denom string, exchangeRate sdk.Dec) ExchangeRateTuple } } -// String implement stringify func (v ExchangeRateTuple) String() string { - out, _ := yaml.Marshal(v) - return string(out) + return fmt.Sprintf("{\"denom\":%q, \"exchange_rate\":%q}", v.Denom, sdkutil.FormatDec(v.ExchangeRate)) +} + +func (v ExchangeRateTuple) MarshalJSON() ([]byte, error) { + return []byte(v.String()), nil } // ExchangeRateTuples - array of ExchangeRateTuple @@ -64,8 +66,8 @@ type ExchangeRateTuples []ExchangeRateTuple // String implements fmt.Stringer interface func (tuples ExchangeRateTuples) String() string { - out, _ := yaml.Marshal(tuples) - return string(out) + bz, _ := json.Marshal(tuples) + return string(bz) // fmt.Sprint([]ExchangeRateTuple(tuples)) } // ParseExchangeRateTuples ExchangeRateTuple parser @@ -89,7 +91,7 @@ func ParseExchangeRateTuples(tuplesStr string) (ExchangeRateTuples, error) { return nil, err } if !decCoin.IsPositive() { - return nil, types.ErrInvalidOraclePrice + return nil, fmt.Errorf("exchange rate can't be negative: %s", tupleStr) } denom := strings.ToUpper(denomAmountStr[0]) @@ -106,3 +108,8 @@ func ParseExchangeRateTuples(tuplesStr string) (ExchangeRateTuples, error) { return tuples, nil } + +func (v ExchangeRate) String() string { + bz, _ := json.Marshal(v) + return string(bz) +} diff --git a/x/oracle/types/vote_test.go b/x/oracle/types/vote_test.go index eac080b934..97b968b572 100644 --- a/x/oracle/types/vote_test.go +++ b/x/oracle/types/vote_test.go @@ -2,9 +2,10 @@ package types import ( "testing" + "time" sdk "github.com/cosmos/cosmos-sdk/types" - "gotest.tools/v3/assert" + "github.com/stretchr/testify/assert" ) func TestAggregateExchangeRatePrevoteString(t *testing.T) { @@ -31,22 +32,21 @@ func TestAggregateExchangeRateVoteString(t *testing.T) { } func TestExchangeRateTuplesString(t *testing.T) { + t.Parallel() exchangeRateTuple := NewExchangeRateTuple(UmeeDenom, sdk.OneDec()) - assert.Equal(t, exchangeRateTuple.String(), "denom: uumee\nexchange_rate: \"1.000000000000000000\"\n") + assert.Equal(t, exchangeRateTuple.String(), `{"denom":"uumee", "exchange_rate":"1"}`) exchangeRateTuples := ExchangeRateTuples{ exchangeRateTuple, NewExchangeRateTuple(IbcDenomAtom, sdk.SmallestDec()), } - assert.Equal(t, "- denom: uumee\n exchange_rate: \"1.000000000000000000\"\n- denom: ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2\n exchange_rate: \"0.000000000000000001\"\n", exchangeRateTuples.String()) + assert.Equal(t, `[{"denom":"uumee","exchange_rate":"1"},{"denom":"ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2","exchange_rate":"0.000000000000000001"}]`, exchangeRateTuples.String()) } func TestParseExchangeRateTuples(t *testing.T) { - errMsg := "invalid oracle price" - valid := "uumee:123.0,uatom:123.123" _, err := ParseExchangeRateTuples(valid) - assert.NilError(t, err) + assert.NoError(t, err) duplicatedDenom := "uumee:100.0,uatom:123.123,uatom:121233.123" _, err = ParseExchangeRateTuples(duplicatedDenom) @@ -62,16 +62,22 @@ func TestParseExchangeRateTuples(t *testing.T) { zeroCoinsWithValid := "uumee:0.0,uatom:123.1" _, err = ParseExchangeRateTuples(zeroCoinsWithValid) - assert.ErrorContains(t, err, errMsg) + assert.ErrorContains(t, err, "can't be negative") negativeCoinsWithValid := "uumee:-1234.5,uatom:123.1" _, err = ParseExchangeRateTuples(negativeCoinsWithValid) - assert.ErrorContains(t, err, errMsg) + assert.ErrorContains(t, err, "can't be negative") multiplePricesPerRate := "uumee:123: uumee:456,uusdc:789" _, err = ParseExchangeRateTuples(multiplePricesPerRate) assert.ErrorContains(t, err, "invalid exchange rate") _, err = ParseExchangeRateTuples("") - assert.NilError(t, err) + assert.NoError(t, err) +} + +func TestExchangeRateString(t *testing.T) { + t1 := time.Date(2022, 9, 18, 15, 55, 01, 0, time.UTC) + er := ExchangeRate{Rate: sdk.MustNewDecFromStr("1.5"), Timestamp: t1} + assert.Equal(t, `{"rate":"1.500000000000000000","timestamp":"2022-09-18T15:55:01Z"}`, er.String()) }