diff --git a/x/liquidity/keeper/grpc_query.go b/x/liquidity/keeper/grpc_query.go index c2b50add..e3827979 100644 --- a/x/liquidity/keeper/grpc_query.go +++ b/x/liquidity/keeper/grpc_query.go @@ -580,7 +580,7 @@ func (k Querier) OrderBooks(c context.Context, req *types.QueryOrderBooksRequest } for _, tickPrec := range req.TickPrecisions { - obs = append(obs, types.MakeOrderBookResponse(ov, int(tickPrec), int(req.NumTicks))) + obs = append(obs, types.MakeOrderBookResponse(ov, lowestPrice, highestPrice, int(tickPrec), int(req.NumTicks))) } pairs = append(pairs, types.OrderBookPairResponse{ PairId: pairId, diff --git a/x/liquidity/keeper/swap_test.go b/x/liquidity/keeper/swap_test.go index 6cdbf127..64f62356 100644 --- a/x/liquidity/keeper/swap_test.go +++ b/x/liquidity/keeper/swap_test.go @@ -938,9 +938,11 @@ func (s *KeeperTestSuite) TestOrderBooks_edgecase1() { s.Require().Len(resp.Pairs, 1) s.Require().Len(resp.Pairs[0].OrderBooks, 1) - s.Require().Len(resp.Pairs[0].OrderBooks[0].Buys, 1) + s.Require().Len(resp.Pairs[0].OrderBooks[0].Buys, 2) s.Require().True(decEq(utils.ParseDec("0.6321"), resp.Pairs[0].OrderBooks[0].Buys[0].Price)) s.Require().True(intEq(sdk.NewInt(1178846737645), resp.Pairs[0].OrderBooks[0].Buys[0].UserOrderAmount)) + s.Require().True(decEq(utils.ParseDec("0.5187"), resp.Pairs[0].OrderBooks[0].Buys[1].Price)) + s.Require().True(intEq(sdk.NewInt(13340086), resp.Pairs[0].OrderBooks[0].Buys[1].UserOrderAmount)) s.Require().Len(resp.Pairs[0].OrderBooks[0].Sells, 0) } diff --git a/x/liquidity/types/example_orderbook_test.go b/x/liquidity/types/example_orderbook_test.go index 4f5371cc..26c76fc9 100644 --- a/x/liquidity/types/example_orderbook_test.go +++ b/x/liquidity/types/example_orderbook_test.go @@ -23,7 +23,9 @@ func ExampleMakeOrderBookResponse() { ov := ob.MakeView() ov.Match() tickPrec := 1 - resp := types.MakeOrderBookResponse(ov, tickPrec, 20) + lowestPrice := utils.ParseDec("0") + highestPrice := utils.ParseDec("20") + resp := types.MakeOrderBookResponse(ov, lowestPrice, highestPrice, tickPrec, 20) basePrice, found := types.OrderBookBasePrice(ov, tickPrec) if !found { panic("base price not found") @@ -64,7 +66,7 @@ func ExampleMakeOrderBookResponse_pool() { ov := ob.MakeView() ov.Match() tickPrec := 2 - resp := types.MakeOrderBookResponse(ov, tickPrec, 10) + resp := types.MakeOrderBookResponse(ov, lowestPrice, highestPrice, tickPrec, 10) basePrice, found := types.OrderBookBasePrice(ov, tickPrec) if !found { panic("base price not found") @@ -73,6 +75,11 @@ func ExampleMakeOrderBookResponse_pool() { // Output: // +------------------------------------------------------------------------+ + // | 2299835 | 1.011000000000000000 | | + // | 2342262 | 1.008000000000000000 | | + // | 2170367 | 1.005000000000000000 | | + // | 2059733 | 1.003000000000000000 | | + // | 1914496 | 1.000000000000000000 | | // | 1846587 | 0.998000000000000000 | | // | 1729430 | 0.995000000000000000 | | // | 1674921 | 0.993000000000000000 | | @@ -85,6 +92,12 @@ func ExampleMakeOrderBookResponse_pool() { // | | 0.985000000000000000 | 1520420 | // | | 0.982000000000000000 | 1671594 | // | | 0.979000000000000000 | 1672618 | + // | | 0.975000000000000000 | 1836801 | + // | | 0.972000000000000000 | 1839965 | + // | | 0.968000000000000000 | 2017741 | + // | | 0.965000000000000000 | 2023466 | + // | | 0.961000000000000000 | 2215515 | + // | | 0.957000000000000000 | 2224296 | // +------------------------------------------------------------------------+ } @@ -108,7 +121,7 @@ func ExampleMakeOrderBookResponse_userOrder() { ov := ob.MakeView() ov.Match() tickPrec := 3 - resp := types.MakeOrderBookResponse(ov, tickPrec, 10) + resp := types.MakeOrderBookResponse(ov, lowestPrice, highestPrice, tickPrec, 10) basePrice, found := types.OrderBookBasePrice(ov, tickPrec) if !found { panic("base price not found") @@ -154,7 +167,7 @@ func ExampleMakeOrderBookResponse_match() { ov := ob.MakeView() ov.Match() tickPrec := 3 - resp := types.MakeOrderBookResponse(ov, tickPrec, 10) + resp := types.MakeOrderBookResponse(ov, utils.ParseDec("0.9"), utils.ParseDec("1.1"), tickPrec, 10) basePrice, found := types.OrderBookBasePrice(ov, tickPrec) if !found { panic("base price not found") @@ -183,7 +196,7 @@ func ExampleMakeOrderBookResponse_zigzag() { ov.Match() basePrice, _ := types.OrderBookBasePrice(ov, 4) - resp := types.MakeOrderBookResponse(ov, 3, 20) + resp := types.MakeOrderBookResponse(ov, utils.ParseDec("0.9"), utils.ParseDec("1.1"), 3, 20) types.PrintOrderBookResponse(resp, basePrice) // Output: @@ -212,7 +225,7 @@ func ExampleMakeOrderBookResponse_edgecase1() { ov.Match() basePrice, _ := types.OrderBookBasePrice(ov, 4) - resp := types.MakeOrderBookResponse(ov, 3, 10) + resp := types.MakeOrderBookResponse(ov, lowestPrice, highestPrice, 3, 10) types.PrintOrderBookResponse(resp, basePrice) // Output: @@ -256,7 +269,7 @@ func ExampleMakeOrderBookResponse_edgecase2() { ov.Match() basePrice, _ := types.OrderBookBasePrice(ov, 4) - resp := types.MakeOrderBookResponse(ov, 3, 10) + resp := types.MakeOrderBookResponse(ov, utils.ParseDec("0.9"), utils.ParseDec("1.1"), 3, 10) types.PrintOrderBookResponse(resp, basePrice) // Output: @@ -280,7 +293,7 @@ func ExampleMakeOrderBookResponse_edgecase3() { ov.Match() basePrice, _ := types.OrderBookBasePrice(ov, 4) - resp := types.MakeOrderBookResponse(ov, 3, 10) + resp := types.MakeOrderBookResponse(ov, utils.ParseDec("0.9"), utils.ParseDec("1.1"), 3, 10) types.PrintOrderBookResponse(resp, basePrice) // Output: diff --git a/x/liquidity/types/orderbook.go b/x/liquidity/types/orderbook.go index b68ead98..417af867 100644 --- a/x/liquidity/types/orderbook.go +++ b/x/liquidity/types/orderbook.go @@ -24,7 +24,7 @@ func OrderBookBasePrice(ov amm.OrderView, tickPrec int) (sdk.Dec, bool) { } } -func MakeOrderBookResponse(ov amm.OrderView, tickPrec, numTicks int) OrderBookResponse { +func MakeOrderBookResponse(ov amm.OrderView, lowestPrice, highestPrice sdk.Dec, tickPrec, numTicks int) OrderBookResponse { ammTickPrec := amm.TickPrecision(tickPrec) resp := OrderBookResponse{TickPrecision: uint32(tickPrec)} @@ -45,7 +45,7 @@ func MakeOrderBookResponse(ov amm.OrderView, tickPrec, numTicks int) OrderBookRe startPrice := FitPriceToTickGap(highestBuyPrice, tickGap, true) currentPrice := startPrice accAmt := sdk.ZeroInt() - for i := 0; i < numTicks && !currentPrice.IsNegative(); i++ { + for i := 0; i < numTicks && currentPrice.GTE(lowestPrice) && !currentPrice.IsNegative(); { amt := ov.BuyAmountOver(currentPrice, true).Sub(accAmt) if amt.IsPositive() { resp.Buys = append(resp.Buys, OrderBookTickResponse{ @@ -54,6 +54,7 @@ func MakeOrderBookResponse(ov amm.OrderView, tickPrec, numTicks int) OrderBookRe PoolOrderAmount: sdk.ZeroInt(), }) accAmt = accAmt.Add(amt) + i++ } currentPrice = currentPrice.Sub(tickGap) } @@ -62,7 +63,7 @@ func MakeOrderBookResponse(ov amm.OrderView, tickPrec, numTicks int) OrderBookRe startPrice := FitPriceToTickGap(lowestSellPrice, tickGap, false) currentPrice := startPrice accAmt := sdk.ZeroInt() - for i := 0; i < numTicks; i++ { + for i := 0; i < numTicks && currentPrice.LTE(highestPrice); { amt := ov.SellAmountUnder(currentPrice, true).Sub(accAmt) if amt.IsPositive() { resp.Sells = append(resp.Sells, OrderBookTickResponse{ @@ -71,6 +72,7 @@ func MakeOrderBookResponse(ov amm.OrderView, tickPrec, numTicks int) OrderBookRe PoolOrderAmount: sdk.ZeroInt(), }) accAmt = accAmt.Add(amt) + i++ } currentPrice = currentPrice.Add(tickGap) } diff --git a/x/liquidity/types/orderbook_test.go b/x/liquidity/types/orderbook_test.go index 136a4784..50302501 100644 --- a/x/liquidity/types/orderbook_test.go +++ b/x/liquidity/types/orderbook_test.go @@ -16,9 +16,10 @@ func newOrder(dir amm.OrderDirection, price sdk.Dec, amt sdk.Int) amm.Order { } func TestMakeOrderBookResponse(t *testing.T) { - pool := amm.NewBasicPool(sdk.NewInt(862431695563), sdk.NewInt(37852851767), sdk.Int{}) - lowestPrice := pool.Price().Mul(sdk.NewDecWithPrec(9, 1)) - highestPrice := pool.Price().Mul(sdk.NewDecWithPrec(11, 1)) + pool := amm.NewBasicPool(sdk.NewInt(1000_000000), sdk.NewInt(1000_000000), sdk.Int{}) + lastPrice := utils.ParseDec("1") + lowestPrice := lastPrice.Mul(utils.ParseDec("0.9")) + highestPrice := lastPrice.Mul(utils.ParseDec("1.1")) ob := amm.NewOrderBook() ob.AddOrder(amm.PoolOrders(pool, amm.DefaultOrderer, lowestPrice, highestPrice, 4)...) @@ -29,13 +30,13 @@ func TestMakeOrderBookResponse(t *testing.T) { panic("base price not found") } - resp := types.MakeOrderBookResponse(ov, 3, 20) + resp := types.MakeOrderBookResponse(ov, lowestPrice, highestPrice, 4, 20) types.PrintOrderBookResponse(resp, basePrice) } func BenchmarkMakeOrderBookResponse(b *testing.B) { for i := 0; i < b.N; i++ { - makeOrderBookPairResponse(100, 10, 20, 4) + makeOrderBookPairResponse(100, 2, 20, 4) } } @@ -55,11 +56,12 @@ func makeOrderBookPairResponse(numOrders, numPools, numTicks, tickPrec int) *typ ob.AddOrder(newOrder(dir, price, amt)) } + lowestPrice, highestPrice := utils.ParseDec("0.9"), utils.ParseDec("1.1") for i := 0; i < numPools; i++ { rx := utils.RandomInt(r, sdk.NewInt(10000_000000), sdk.NewInt(11000_000000)) ry := utils.RandomInt(r, sdk.NewInt(10000_000000), sdk.NewInt(11000_000000)) pool := amm.NewBasicPool(rx, ry, sdk.Int{}) - ob.AddOrder(amm.PoolOrders(pool, amm.DefaultOrderer, utils.ParseDec("0.9"), utils.ParseDec("1.1"), tickPrec)...) + ob.AddOrder(amm.PoolOrders(pool, amm.DefaultOrderer, lowestPrice, highestPrice, tickPrec)...) } ov := ob.MakeView() @@ -74,8 +76,8 @@ func makeOrderBookPairResponse(numOrders, numPools, numTicks, tickPrec int) *typ PairId: 1, BasePrice: basePrice, } - for _, tickPrec := range []int{1, 2, 3, 4} { - resp.OrderBooks = append(resp.OrderBooks, types.MakeOrderBookResponse(ov, tickPrec, numTicks)) + for _, tickPrec := range []int{2, 3, 4} { + resp.OrderBooks = append(resp.OrderBooks, types.MakeOrderBookResponse(ov, lowestPrice, highestPrice, tickPrec, numTicks)) } return resp }