Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 3 additions & 8 deletions proto/umee/oracle/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package umee.oracle.v1;
import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "umee/oracle/v1/oracle.proto";
import "umee/oracle/v1/genesis.proto";
import "cosmos/base/v1beta1/coin.proto";

option go_package = "github.com/umee-network/umee/v4/x/oracle/types";
Expand Down Expand Up @@ -261,10 +262,7 @@ message QueryMedians {
// Query/Medians RPC method.
message QueryMediansResponse {
// medians defines a list of the medians for all stamped denoms.
repeated cosmos.base.v1beta1.DecCoin medians = 1 [
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.DecCoins",
(gogoproto.nullable) = false
];
repeated Price medians = 1 [(gogoproto.nullable) = false];
}

// QueryMedianDeviations is the request type for the Query/MedianDeviations RPC Response.
Expand All @@ -279,8 +277,5 @@ message QueryMedianDeviations {
// Query/MedianDeviations RPC method.
message QueryMedianDeviationsResponse {
// medians defines a list of the median deviations for all stamped denoms.
repeated cosmos.base.v1beta1.DecCoin medianDeviations = 1 [
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.DecCoins",
(gogoproto.nullable) = false
];
repeated Price medianDeviations = 1 [(gogoproto.nullable) = false];
}
109 changes: 69 additions & 40 deletions swagger/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1093,19 +1093,20 @@ paths:
items:
type: object
properties:
denom:
type: string
amount:
exchange_rate_tuple:
type: object
properties:
denom:
type: string
exchange_rate:
type: string
title: >-
ExchangeRateTuple - struct to store interpreted exchange
rates data to store
block_num:
type: string
description: >-
DecCoin defines a token with a denomination and a decimal
amount.


NOTE: The amount field is an Dec which implements the custom
method

signatures required by gogoproto.
format: uint64
title: Price is an instance of a price "stamp"
description: >-
medians defines a list of the median deviations for all
stamped denoms.
Expand Down Expand Up @@ -1159,19 +1160,20 @@ paths:
items:
type: object
properties:
denom:
type: string
amount:
exchange_rate_tuple:
type: object
properties:
denom:
type: string
exchange_rate:
type: string
title: >-
ExchangeRateTuple - struct to store interpreted exchange
rates data to store
block_num:
type: string
description: >-
DecCoin defines a token with a denomination and a decimal
amount.


NOTE: The amount field is an Dec which implements the custom
method

signatures required by gogoproto.
format: uint64
title: Price is an instance of a price "stamp"
description: medians defines a list of the medians for all stamped denoms.
description: |-
QueryMediansResponse is response type for the
Expand Down Expand Up @@ -2970,6 +2972,23 @@ definitions:
Maximum Median Stamps represents the maximum amount of medians the
oracle module will store before pruning via FIFO.
description: Params defines the parameters for the oracle module.
umee.oracle.v1.Price:
type: object
properties:
exchange_rate_tuple:
type: object
properties:
denom:
type: string
exchange_rate:
type: string
title: >-
ExchangeRateTuple - struct to store interpreted exchange rates data to
store
block_num:
type: string
format: uint64
title: Price is an instance of a price "stamp"
umee.oracle.v1.QueryActiveExchangeRatesResponse:
type: object
properties:
Expand Down Expand Up @@ -3150,15 +3169,20 @@ definitions:
items:
type: object
properties:
denom:
type: string
amount:
exchange_rate_tuple:
type: object
properties:
denom:
type: string
exchange_rate:
type: string
title: >-
ExchangeRateTuple - struct to store interpreted exchange rates
data to store
block_num:
type: string
description: |-
DecCoin defines a token with a denomination and a decimal amount.

NOTE: The amount field is an Dec which implements the custom method
signatures required by gogoproto.
format: uint64
title: Price is an instance of a price "stamp"
description: >-
medians defines a list of the median deviations for all stamped
denoms.
Expand All @@ -3173,15 +3197,20 @@ definitions:
items:
type: object
properties:
denom:
type: string
amount:
exchange_rate_tuple:
type: object
properties:
denom:
type: string
exchange_rate:
type: string
title: >-
ExchangeRateTuple - struct to store interpreted exchange rates
data to store
block_num:
type: string
description: |-
DecCoin defines a token with a denomination and a decimal amount.

NOTE: The amount field is an Dec which implements the custom method
signatures required by gogoproto.
format: uint64
title: Price is an instance of a price "stamp"
description: medians defines a list of the medians for all stamped denoms.
description: |-
QueryMediansResponse is response type for the
Expand Down
4 changes: 2 additions & 2 deletions tests/grpc/client/query/oracle.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func (c *Client) QueryExchangeRates() ([]sdk.DecCoin, error) {
return queryResponse.ExchangeRates, nil
}

func (c *Client) QueryMedians() ([]sdk.DecCoin, error) {
func (c *Client) QueryMedians() (oracletypes.Prices, error) {
ctx, cancel := context.WithTimeout(context.Background(), queryTimeout)
defer cancel()

Expand All @@ -44,7 +44,7 @@ func (c *Client) QueryMedians() ([]sdk.DecCoin, error) {
return queryResponse.Medians, nil
}

func (c *Client) QueryMedianDeviations() ([]sdk.DecCoin, error) {
func (c *Client) QueryMedianDeviations() (oracletypes.Prices, error) {
ctx, cancel := context.WithTimeout(context.Background(), queryTimeout)
defer cancel()

Expand Down
4 changes: 2 additions & 2 deletions tests/grpc/price_listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func listenForPrices(
}
// Saves the last median for each denom
for _, median := range medians {
priceStore.medians[median.Denom] = median.Amount
priceStore.medians[median.ExchangeRateTuple.Denom] = median.ExchangeRateTuple.ExchangeRate
}

medianDeviations, err := umeeClient.QueryClient.QueryMedianDeviations()
Expand All @@ -52,7 +52,7 @@ func listenForPrices(
}
// Saves the last median deviation for each denom
for _, medianDeviation := range medianDeviations {
priceStore.medianDeviations[medianDeviation.Denom] = medianDeviation.Amount
priceStore.medianDeviations[medianDeviation.ExchangeRateTuple.Denom] = medianDeviation.ExchangeRateTuple.ExchangeRate
}

return priceStore, nil
Expand Down
5 changes: 3 additions & 2 deletions x/oracle/abci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,12 @@ func (s *IntegrationTestSuite) TestEndblockerHistoracle() {
// query for past 6 medians (should only get 4 back since max median stamps is set to 4)
medians := app.OracleKeeper.HistoricMedians(ctx, denom.SymbolDenom, 6)
s.Require().Equal(4, len(medians))
s.Require().Equal(tc.expectedHistoricMedians, medians)

s.Require().Equal(tc.expectedHistoricMedians, medians.Decs())

medianHistoricDeviation, err := app.OracleKeeper.HistoricMedianDeviation(ctx, denom.SymbolDenom)
s.Require().NoError(err)
s.Require().Equal(tc.expectedHistoricMedianDeviation, medianHistoricDeviation)
s.Require().Equal(tc.expectedHistoricMedianDeviation, medianHistoricDeviation.ExchangeRateTuple.ExchangeRate)

withinHistoricMedianDeviation, err := app.OracleKeeper.WithinHistoricMedianDeviation(ctx, denom.SymbolDenom)
s.Require().NoError(err)
Expand Down
27 changes: 7 additions & 20 deletions x/oracle/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ func (q querier) Medians(

ctx := sdk.UnwrapSDKContext(goCtx)

medians := make([]sdk.DecCoin, 0)
medians := make([]types.Price, 0)

if len(req.Denom) > 0 {
if req.NumStamps == 0 {
Expand All @@ -273,18 +273,10 @@ func (q querier) Medians(
req.NumStamps = uint32(q.MaximumMedianStamps(ctx))
}

medians = make(sdk.DecCoins, req.NumStamps)
medianList := q.HistoricMedians(ctx, req.Denom, uint64(req.NumStamps))

for i, median := range medianList {
medians[i] = sdk.NewDecCoinFromDec(req.Denom, median)
}
medians = q.HistoricMedians(ctx, req.Denom, uint64(req.NumStamps))
} else {
q.IterateAllMedianPrices(ctx, func(median types.Price) (stop bool) {
medians = append(
medians,
sdk.NewDecCoinFromDec(median.ExchangeRateTuple.Denom, median.ExchangeRateTuple.ExchangeRate),
)
medians = append(medians, median)
return false
})
}
Expand All @@ -304,23 +296,18 @@ func (q querier) MedianDeviations(

ctx := sdk.UnwrapSDKContext(goCtx)

medianDeviations := make([]sdk.DecCoin, 0)
medianDeviations := types.Prices{}

if len(req.Denom) > 0 {
exchangeRate, err := q.HistoricMedianDeviation(ctx, req.Denom)
price, err := q.HistoricMedianDeviation(ctx, req.Denom)
if err != nil {
return nil, err
}

medianDeviations = append(medianDeviations, sdk.NewDecCoinFromDec(req.Denom, exchangeRate))
medianDeviations = append(medianDeviations, *price)
} else {
q.IterateAllMedianDeviationPrices(ctx, func(medianDeviation types.Price) (stop bool) {
medianDeviations = append(
medianDeviations,
sdk.NewDecCoinFromDec(
medianDeviation.ExchangeRateTuple.Denom,
medianDeviation.ExchangeRateTuple.ExchangeRate,
))
medianDeviations = append(medianDeviations, medianDeviation)
return false
})
}
Expand Down
57 changes: 45 additions & 12 deletions x/oracle/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,27 +210,50 @@ func (s *IntegrationTestSuite) TestQuerier_Medians() {
atomMedian1 := sdk.DecCoin{Denom: "atom", Amount: sdk.MustNewDecFromStr("51.09")}
umeeMedian1 := sdk.DecCoin{Denom: "umee", Amount: sdk.MustNewDecFromStr("6540.23")}

app.OracleKeeper.SetHistoricMedian(ctx, atomMedian0.Denom, uint64(ctx.BlockHeight()-4), atomMedian0.Amount)
app.OracleKeeper.SetHistoricMedian(ctx, umeeMedian0.Denom, uint64(ctx.BlockHeight()-4), umeeMedian0.Amount)
blockHeight0 := uint64(ctx.BlockHeight() - 4)
app.OracleKeeper.SetHistoricMedian(ctx, atomMedian0.Denom, blockHeight0, atomMedian0.Amount)
app.OracleKeeper.SetHistoricMedian(ctx, umeeMedian0.Denom, blockHeight0, umeeMedian0.Amount)

res, err := s.queryClient.Medians(ctx.Context(), &types.QueryMedians{})
s.Require().NoError(err)
s.Require().Equal(res.Medians, sdk.NewDecCoins(atomMedian0, umeeMedian0))

expected := []types.Price{
*types.NewPrice(atomMedian0.Amount, "atom", blockHeight0),
*types.NewPrice(umeeMedian0.Amount, "umee", blockHeight0),
}
s.Require().Equal(res.Medians, expected)

res, err = s.queryClient.Medians(ctx.Context(), &types.QueryMedians{Denom: atomMedian0.Denom, NumStamps: 1})
s.Require().NoError(err)
s.Require().Equal(res.Medians, sdk.NewDecCoins(atomMedian0))

app.OracleKeeper.SetHistoricMedian(ctx, atomMedian1.Denom, uint64(ctx.BlockHeight()-2), atomMedian1.Amount)
app.OracleKeeper.SetHistoricMedian(ctx, umeeMedian1.Denom, uint64(ctx.BlockHeight()-2), umeeMedian1.Amount)
expected = []types.Price{
*types.NewPrice(atomMedian0.Amount, "atom", blockHeight0),
}
s.Require().Equal(res.Medians, expected)

blockHeight1 := uint64(ctx.BlockHeight() - 2)
app.OracleKeeper.SetHistoricMedian(ctx, atomMedian1.Denom, blockHeight1, atomMedian1.Amount)
app.OracleKeeper.SetHistoricMedian(ctx, umeeMedian1.Denom, blockHeight1, umeeMedian1.Amount)

res, err = s.queryClient.Medians(ctx.Context(), &types.QueryMedians{})
s.Require().NoError(err)
s.Require().Equal(res.Medians, sdk.DecCoins{atomMedian0, atomMedian1, umeeMedian0, umeeMedian1})

expected = []types.Price{
*types.NewPrice(atomMedian0.Amount, "atom", blockHeight0),
*types.NewPrice(atomMedian1.Amount, "atom", blockHeight1),
*types.NewPrice(umeeMedian0.Amount, "umee", blockHeight0),
*types.NewPrice(umeeMedian1.Amount, "umee", blockHeight1),
}
s.Require().Equal(res.Medians, expected)

res, err = s.queryClient.Medians(ctx.Context(), &types.QueryMedians{Denom: atomMedian1.Denom, NumStamps: 2})
s.Require().NoError(err)
s.Require().Equal(res.Medians, sdk.DecCoins{atomMedian1, atomMedian0})

expected = []types.Price{
*types.NewPrice(atomMedian1.Amount, "atom", blockHeight1),
*types.NewPrice(atomMedian0.Amount, "atom", blockHeight0),
}
s.Require().Equal(res.Medians, expected)

res, err = s.queryClient.Medians(ctx.Context(), &types.QueryMedians{Denom: atomMedian1.Denom, NumStamps: 0})
s.Require().ErrorContains(err, "parameter NumStamps must be greater than 0")
Expand All @@ -244,16 +267,26 @@ func (s *IntegrationTestSuite) TestQuerier_MedianDeviations() {
umeeMedianDeviation := sdk.DecCoin{Denom: "umee", Amount: sdk.MustNewDecFromStr("9541.48")}

app.OracleKeeper.SetMedianStampPeriod(ctx, 1)
app.OracleKeeper.SetHistoricMedianDeviation(ctx, atomMedianDeviation.Denom, uint64(ctx.BlockHeight()-1), atomMedianDeviation.Amount)
app.OracleKeeper.SetHistoricMedianDeviation(ctx, umeeMedianDeviation.Denom, uint64(ctx.BlockHeight()-1), umeeMedianDeviation.Amount)
blockHeight := uint64(ctx.BlockHeight() - 1)
app.OracleKeeper.SetHistoricMedianDeviation(ctx, atomMedianDeviation.Denom, blockHeight, atomMedianDeviation.Amount)
app.OracleKeeper.SetHistoricMedianDeviation(ctx, umeeMedianDeviation.Denom, blockHeight, umeeMedianDeviation.Amount)

res, err := s.queryClient.MedianDeviations(ctx.Context(), &types.QueryMedianDeviations{})
s.Require().NoError(err)
s.Require().Equal(res.MedianDeviations, sdk.NewDecCoins(atomMedianDeviation, umeeMedianDeviation))

expected := []types.Price{
*types.NewPrice(atomMedianDeviation.Amount, "atom", blockHeight),
*types.NewPrice(umeeMedianDeviation.Amount, "umee", blockHeight),
}
s.Require().Equal(res.MedianDeviations, expected)

res, err = s.queryClient.MedianDeviations(ctx.Context(), &types.QueryMedianDeviations{Denom: atomMedianDeviation.Denom})
s.Require().NoError(err)
s.Require().Equal(res.MedianDeviations, sdk.NewDecCoins(atomMedianDeviation))

expected = []types.Price{
*types.NewPrice(atomMedianDeviation.Amount, "atom", blockHeight),
}
s.Require().Equal(res.MedianDeviations, expected)
}

func (s *IntegrationTestSuite) TestEmptyRequest() {
Expand Down
Loading