Skip to content

Commit 5b4119b

Browse files
committed
feat(x/oracle): return latest prices first by default in prices query
Signed-off-by: Artur Troian <[email protected]>
1 parent e0933bc commit 5b4119b

File tree

3 files changed

+72
-3
lines changed

3 files changed

+72
-3
lines changed

upgrades/software/v2.1.0/upgrade.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ func (up *upgrade) UpgradeHandler() upgradetypes.UpgradeHandler {
106106
return toVM, fmt.Errorf("failed to set updated fee pool balance: %w", err)
107107
}
108108
}
109+
109110
return toVM, err
110111
}
111112
}

x/oracle/keeper/grpc_query.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ func (k Querier) Prices(ctx context.Context, req *types.QueryPricesRequest) (*ty
3131
*pageReq = *req.Pagination
3232
}
3333

34+
// Keys are stored in ascending chronological order.
35+
// Invert Reverse so the default returns latest prices first
36+
// and Reverse=true returns oldest first.
37+
pageReq.Reverse = !pageReq.Reverse
38+
3439
prices, pageRes, err := query.CollectionFilteredPaginate(
3540
ctx,
3641
keeper.prices,

x/oracle/keeper/grpc_query_test.go

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ func TestGRPCQueryPricesTimestamp(t *testing.T) {
121121
require.Len(t, res.Prices, 2)
122122
}
123123

124-
func TestGRPCQueryPricesPaginationReverse(t *testing.T) {
124+
func TestGRPCQueryPricesDefaultOrder(t *testing.T) {
125125
suite := setupTest(t)
126126

127127
source := testutil.AccAddress(t)
@@ -145,14 +145,15 @@ func TestGRPCQueryPricesPaginationReverse(t *testing.T) {
145145
ctx = addPriceEntry(t, ctx, suite.keeper, source, dataID, 11, ts2, sdkmath.LegacyMustNewDecFromStr("2.0"))
146146
ctx = addPriceEntry(t, ctx, suite.keeper, source, dataID, 12, ts3, sdkmath.LegacyMustNewDecFromStr("3.0"))
147147

148+
// Default order (no Reverse flag) should return latest prices first
148149
req := &oracletypes.QueryPricesRequest{
149150
Filters: oracletypes.PricesFilter{
150151
AssetDenom: sdkutil.DenomAkt,
151152
BaseDenom: sdkutil.DenomUSD,
152153
StartTime: baseTime,
153154
EndTime: baseTime.Add(time.Minute),
154155
},
155-
Pagination: &sdkquery.PageRequest{Limit: 2, Reverse: true},
156+
Pagination: &sdkquery.PageRequest{Limit: 2},
156157
}
157158

158159
res, err := suite.queryClient.Prices(ctx, req)
@@ -163,14 +164,15 @@ func TestGRPCQueryPricesPaginationReverse(t *testing.T) {
163164
require.True(t, res.Prices[0].ID.Timestamp.Equal(ts3))
164165
require.True(t, res.Prices[1].ID.Timestamp.Equal(ts2))
165166

167+
// Continue with cursor-based pagination
166168
req = &oracletypes.QueryPricesRequest{
167169
Filters: oracletypes.PricesFilter{
168170
AssetDenom: sdkutil.DenomAkt,
169171
BaseDenom: sdkutil.DenomUSD,
170172
StartTime: baseTime,
171173
EndTime: baseTime.Add(time.Minute),
172174
},
173-
Pagination: &sdkquery.PageRequest{Key: res.Pagination.NextKey, Limit: 2, Reverse: true},
175+
Pagination: &sdkquery.PageRequest{Key: res.Pagination.NextKey, Limit: 2},
174176
}
175177

176178
res, err = suite.queryClient.Prices(ctx, req)
@@ -179,3 +181,64 @@ func TestGRPCQueryPricesPaginationReverse(t *testing.T) {
179181
require.Len(t, res.Prices, 1)
180182
require.True(t, res.Prices[0].ID.Timestamp.Equal(ts1))
181183
}
184+
185+
func TestGRPCQueryPricesReverseOrder(t *testing.T) {
186+
suite := setupTest(t)
187+
188+
source := testutil.AccAddress(t)
189+
params := oracletypes.DefaultParams()
190+
params.Sources = []string{source.String()}
191+
params.MinPriceSources = 1
192+
params.MaxPriceStalenessPeriod = 1000
193+
params.TwapWindow = 10
194+
params.MaxPriceDeviationBps = 1000
195+
require.NoError(t, suite.keeper.SetParams(suite.ctx, params))
196+
197+
dataID := oracletypes.DataID{Denom: sdkutil.DenomAkt, BaseDenom: sdkutil.DenomUSD}
198+
baseTime := time.Now().UTC().Truncate(time.Nanosecond)
199+
200+
ts1 := baseTime.Add(10 * time.Second)
201+
ts2 := baseTime.Add(11 * time.Second)
202+
ts3 := baseTime.Add(12 * time.Second)
203+
204+
ctx := suite.ctx
205+
ctx = addPriceEntry(t, ctx, suite.keeper, source, dataID, 10, ts1, sdkmath.LegacyMustNewDecFromStr("1.0"))
206+
ctx = addPriceEntry(t, ctx, suite.keeper, source, dataID, 11, ts2, sdkmath.LegacyMustNewDecFromStr("2.0"))
207+
ctx = addPriceEntry(t, ctx, suite.keeper, source, dataID, 12, ts3, sdkmath.LegacyMustNewDecFromStr("3.0"))
208+
209+
// Reverse=true should return oldest prices first
210+
req := &oracletypes.QueryPricesRequest{
211+
Filters: oracletypes.PricesFilter{
212+
AssetDenom: sdkutil.DenomAkt,
213+
BaseDenom: sdkutil.DenomUSD,
214+
StartTime: baseTime,
215+
EndTime: baseTime.Add(time.Minute),
216+
},
217+
Pagination: &sdkquery.PageRequest{Limit: 2, Reverse: true},
218+
}
219+
220+
res, err := suite.queryClient.Prices(ctx, req)
221+
require.NoError(t, err)
222+
require.NotNil(t, res)
223+
require.Len(t, res.Prices, 2)
224+
require.NotEmpty(t, res.Pagination.NextKey)
225+
require.True(t, res.Prices[0].ID.Timestamp.Equal(ts1))
226+
require.True(t, res.Prices[1].ID.Timestamp.Equal(ts2))
227+
228+
// Continue with cursor-based pagination
229+
req = &oracletypes.QueryPricesRequest{
230+
Filters: oracletypes.PricesFilter{
231+
AssetDenom: sdkutil.DenomAkt,
232+
BaseDenom: sdkutil.DenomUSD,
233+
StartTime: baseTime,
234+
EndTime: baseTime.Add(time.Minute),
235+
},
236+
Pagination: &sdkquery.PageRequest{Key: res.Pagination.NextKey, Limit: 2, Reverse: true},
237+
}
238+
239+
res, err = suite.queryClient.Prices(ctx, req)
240+
require.NoError(t, err)
241+
require.NotNil(t, res)
242+
require.Len(t, res.Prices, 1)
243+
require.True(t, res.Prices[0].ID.Timestamp.Equal(ts3))
244+
}

0 commit comments

Comments
 (0)