Skip to content

Commit

Permalink
Feature/mul pair (#228)
Browse files Browse the repository at this point in the history
* GetOpenOrders instead GetOrderForUsers. Deprecate fillOrders key

* ws tester script

* add symbol support to getOpenOrders and getOpenOrderIDs

* rename open_orders

* explicit test_symbol and test_order in tests

* support pair or symbol in query GET param

* modify girignore

* buf fix par-symbol early return

* remove symbol from open orders key and make it non mondatory in getOrders

* make e2e work with cancel per symbol

* remove comments
  • Loading branch information
uv-orbs authored Jul 1, 2024
1 parent c9fd836 commit 9b8f0a8
Show file tree
Hide file tree
Showing 25 changed files with 123 additions and 238 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ override.tf.json
*_override.tf.json
.terraformrc
terraform.rc
tfplan
tfplan
api_key.txt
8 changes: 5 additions & 3 deletions data/redisrepo/create_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ var orderId = uuid.MustParse("00000000-0000-0000-0000-000000000001")
var clientOId = uuid.MustParse("00000000-0000-0000-0000-000000000002")
var userId = uuid.MustParse("00000000-0000-0000-0000-000000000003")
var size, _ = decimal.NewFromString("10000324.123456789")
var symbol, _ = models.StrToSymbol("MATIC-USDC")

// for tests
var test_symbol, _ = models.StrToSymbol("MATIC-USDC")
var price = decimal.NewFromFloat(10.0)

var order = models.Order{
var test_order = models.Order{
Id: orderId,
Price: price,
Size: size,
Symbol: symbol,
Symbol: test_symbol,
Side: models.BUY,
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,16 @@ import (
"github.com/orbs-network/order-book/utils/logger/logctx"
)

// GetOrdersForUser returns all orders (open or filled) for a given user, sorted by creation time.
//
// `isFilledOrders` should be true if you want filled orders, false if you want open orders.
//
// GetOpenOrders returns all orders (open only) for a given user in Pair/symbol, sorted by creation time.

// This function is paginated, and returns the total number of orders for the user
func (r *redisRepository) GetOrdersForUser(ctx context.Context, userId uuid.UUID, isFilledOrders bool) (orders []models.Order, totalOrders int, err error) {
func (r *redisRepository) GetOpenOrders(ctx context.Context, userId uuid.UUID, symbol models.Symbol) (orders []models.Order, totalOrders int, err error) {
start, stop := utils.PaginationBounds(ctx)

var key string
if isFilledOrders {
logctx.Debug(ctx, "getting filled orders for user", logger.String("userId", userId.String()))
key = CreateUserFilledOrdersKey(userId)
} else {
logctx.Debug(ctx, "getting open orders for user", logger.String("userId", userId.String()))
key = CreateUserOpenOrdersKey(userId)
}

logctx.Debug(ctx, "getting open orders for user", logger.String("userId", userId.String()))
key = CreateUserOpenOrdersKey(userId)

count, err := r.client.ZCard(ctx, key).Result()

Expand Down Expand Up @@ -62,13 +56,22 @@ func (r *redisRepository) GetOrdersForUser(ctx context.Context, userId uuid.UUID
end = len(orderIds)
}

o, err := r.FindOrdersByIds(ctx, orderIds[i:end], false)
batch, err := r.FindOrdersByIds(ctx, orderIds[i:end], false)
if err != nil {
logctx.Error(ctx, "failed to find orders by IDs", logger.String("userId", userId.String()), logger.Error(err))
return []models.Order{}, 0, fmt.Errorf("failed to find orders by IDs: %v", err)
}

ordersSlice = append(ordersSlice, o...)
if symbol == "" {
ordersSlice = append(ordersSlice, batch...)
} else {
// apply symbol filter if needed
for _, o := range batch {
if o.Symbol == symbol {
ordersSlice = append(ordersSlice, o)
}
}
}
}

logctx.Debug(ctx, "got orders for user", logger.String("userId", userId.String()), logger.Int("count", len(orders)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ func TestRedisRepository_GetOrdersForUser(t *testing.T) {
Side: models.BUY,
}

symbol, err := models.StrToSymbol("MATIC-USDC")
assert.NoError(t, err)

t.Run("should get orders for user", func(t *testing.T) {

db, mock := redismock.NewClientMock()
Expand All @@ -37,7 +40,7 @@ func TestRedisRepository_GetOrdersForUser(t *testing.T) {
mock.ExpectZRange(key, int64(0), int64(10)).SetVal([]string{"00000000-0000-0000-0000-000000000001"})
mock.ExpectHGetAll(CreateOrderIDKey(order.Id)).SetVal(order.OrderToMap())

orders, totalOrders, err := repo.GetOrdersForUser(ctx, userId, false)
orders, totalOrders, err := repo.GetOpenOrders(ctx, userId, symbol)

assert.Equal(t, orders[0].Id, order.Id)
assert.Equal(t, orders[0].UserId, order.UserId)
Expand All @@ -60,7 +63,7 @@ func TestRedisRepository_GetOrdersForUser(t *testing.T) {

mock.ExpectZCard(key).SetErr(assert.AnError)

orders, totalOrders, err := repo.GetOrdersForUser(ctx, userId, false)
orders, totalOrders, err := repo.GetOpenOrders(ctx, userId, symbol)

assert.Equal(t, orders, []models.Order{})
assert.Equal(t, totalOrders, 0)
Expand All @@ -82,7 +85,7 @@ func TestRedisRepository_GetOrdersForUser(t *testing.T) {
mock.ExpectZCard(key).SetVal(1)
mock.ExpectZRange(key, int64(0), int64(10)).SetErr(assert.AnError)

orders, totalOrders, err := repo.GetOrdersForUser(ctx, userId, false)
orders, totalOrders, err := repo.GetOpenOrders(ctx, userId, symbol)

assert.Equal(t, orders, []models.Order{})
assert.Equal(t, totalOrders, 0)
Expand All @@ -104,7 +107,7 @@ func TestRedisRepository_GetOrdersForUser(t *testing.T) {
mock.ExpectZCard(key).SetVal(1)
mock.ExpectZRange(key, int64(0), int64(10)).SetVal([]string{"bad-uuid"})

orders, totalOrders, err := repo.GetOrdersForUser(ctx, userId, false)
orders, totalOrders, err := repo.GetOpenOrders(ctx, userId, symbol)

assert.Equal(t, orders, []models.Order{})
assert.Equal(t, totalOrders, 0)
Expand All @@ -127,7 +130,7 @@ func TestRedisRepository_GetOrdersForUser(t *testing.T) {
mock.ExpectZRange(key, int64(0), int64(10)).SetVal([]string{"00000000-0000-0000-0000-000000000001"})
mock.ExpectHGetAll(CreateOrderIDKey(order.Id)).SetErr(assert.AnError)

orders, totalOrders, err := repo.GetOrdersForUser(ctx, userId, false)
orders, totalOrders, err := repo.GetOpenOrders(ctx, userId, symbol)

assert.Equal(t, orders, []models.Order{})
assert.Equal(t, totalOrders, 0)
Expand Down
3 changes: 2 additions & 1 deletion data/redisrepo/get_orders.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import (
"github.com/orbs-network/order-book/utils/logger/logctx"
)

func (r *redisRepository) GetOpenOrderIds(ctx context.Context, userId uuid.UUID) ([]uuid.UUID, error) {
// returns all open IDs if symbol is empty
func (r *redisRepository) GetOpenOrderIds(ctx context.Context, userId uuid.UUID, symbol models.Symbol) ([]uuid.UUID, error) {
userOrdersKey := CreateUserOpenOrdersKey(userId)

// Fetch all order IDs for the user
Expand Down
10 changes: 5 additions & 5 deletions data/redisrepo/pub_sub_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/assert"
)

var orderJson, _ = order.ToJson()
var orderJson, _ = test_order.ToJson()

func TestRedisRepository_PublishEvent(t *testing.T) {

Expand All @@ -18,9 +18,9 @@ func TestRedisRepository_PublishEvent(t *testing.T) {
client: db,
}

mock.ExpectPublish(order.Id.String(), orderJson).SetVal(1)
mock.ExpectPublish(test_order.Id.String(), orderJson).SetVal(1)

err := repo.PublishEvent(ctx, order.Id.String(), orderJson)
err := repo.PublishEvent(ctx, test_order.Id.String(), orderJson)

assert.NoError(t, err)
})
Expand All @@ -32,9 +32,9 @@ func TestRedisRepository_PublishEvent(t *testing.T) {
client: db,
}

mock.ExpectPublish(order.Id.String(), orderJson).SetErr(assert.AnError)
mock.ExpectPublish(test_order.Id.String(), orderJson).SetErr(assert.AnError)

err := repo.PublishEvent(ctx, order.Id.String(), orderJson)
err := repo.PublishEvent(ctx, test_order.Id.String(), orderJson)

assert.ErrorContains(t, err, "failed to publish redis event")
})
Expand Down
11 changes: 1 addition & 10 deletions data/redisrepo/store_filled_orders.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,7 @@ func storeFilledOrderTx(ctx context.Context, transaction redis.Pipeliner, order
// 1. Remove the order from the user's open orders set
userOrdersKey := CreateUserOpenOrdersKey(order.UserId)
transaction.ZRem(ctx, userOrdersKey, order.Id.String())

// 2. Store the order in the filled orders set
userFilledOrdersKey := CreateUserFilledOrdersKey(order.UserId)
userFilledOrdersScore := float64(order.Timestamp.UTC().UnixNano())
transaction.ZAdd(ctx, userFilledOrdersKey, redis.Z{
Score: userFilledOrdersScore,
Member: order.Id.String(),
})

// 3. Remove the order from the buy/sell prices set for that pair
// 2. Remove the order from the buy/sell prices set for that pair
if order.Side == models.BUY {
buyPricesKey := CreateBuySidePricesKey(order.Symbol)
transaction.ZRem(ctx, buyPricesKey, order.Id.String())
Expand Down
13 changes: 2 additions & 11 deletions data/redisrepo/store_filled_orders_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (

"github.com/go-redis/redismock/v9"
"github.com/orbs-network/order-book/models"
"github.com/redis/go-redis/v9"
"github.com/shopspring/decimal"
"github.com/stretchr/testify/assert"
)
Expand All @@ -20,7 +19,7 @@ func TestRedisRepository_StoreFilledOrders(t *testing.T) {
ClientOId: clientOId,
Price: price,
Size: size,
Symbol: symbol,
Symbol: test_symbol,
Side: models.BUY,
Timestamp: timestamp,
SizePending: decimal.Zero,
Expand All @@ -36,10 +35,6 @@ func TestRedisRepository_StoreFilledOrders(t *testing.T) {

mock.ExpectTxPipeline()
mock.ExpectZRem(CreateUserOpenOrdersKey(buyOrder.UserId), buyOrder.Id.String()).SetVal(1)
mock.ExpectZAdd(CreateUserFilledOrdersKey(buyOrder.UserId), redis.Z{
Score: float64(timestamp.UnixNano()),
Member: buyOrder.Id.String(),
}).SetVal(1)
mock.ExpectZRem(CreateBuySidePricesKey(buyOrder.Symbol), buyOrder.Id.String()).SetVal(1)
mock.ExpectHSet(CreateOrderIDKey(buyOrder.Id), buyOrder.OrderToMap()).SetVal(1)
mock.ExpectTxPipelineExec()
Expand All @@ -55,7 +50,7 @@ func TestRedisRepository_StoreFilledOrders(t *testing.T) {
ClientOId: clientOId,
Price: price,
Size: size,
Symbol: symbol,
Symbol: test_symbol,
Side: models.SELL,
Timestamp: timestamp,
SizePending: decimal.Zero,
Expand All @@ -71,10 +66,6 @@ func TestRedisRepository_StoreFilledOrders(t *testing.T) {

mock.ExpectTxPipeline()
mock.ExpectZRem(CreateUserOpenOrdersKey(sellOrder.UserId), sellOrder.Id.String()).SetVal(1)
mock.ExpectZAdd(CreateUserFilledOrdersKey(sellOrder.UserId), redis.Z{
Score: float64(timestamp.UnixNano()),
Member: sellOrder.Id.String(),
}).SetVal(1)
mock.ExpectZRem(CreateSellSidePricesKey(sellOrder.Symbol), sellOrder.Id.String()).SetVal(1)
mock.ExpectHSet(CreateOrderIDKey(sellOrder.Id), sellOrder.OrderToMap()).SetVal(1)
mock.ExpectTxPipelineExec()
Expand Down
28 changes: 14 additions & 14 deletions data/redisrepo/store_open_order_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func TestRedisRepository_StoreOpenOrder(t *testing.T) {
ClientOId: clientOId,
Price: price,
Size: size,
Symbol: symbol,
Symbol: test_symbol,
Side: models.BUY,
Timestamp: timestamp,
}
Expand All @@ -42,7 +42,7 @@ func TestRedisRepository_StoreOpenOrder(t *testing.T) {
Score: float64(timestamp.UnixNano()),
Member: buyOrder.Id.String(),
}).SetVal(1)
mock.ExpectSetNX(Order2MakerTokenTrackKey(order), -1, 0).SetVal(true)
mock.ExpectSetNX(Order2MakerTokenTrackKey(buyOrder), -1, 0).SetVal(true)
mock.ExpectTxPipelineExec()

err := repo.StoreOpenOrder(ctx, buyOrder)
Expand All @@ -56,7 +56,7 @@ func TestRedisRepository_StoreOpenOrder(t *testing.T) {
ClientOId: clientOId,
Price: price,
Size: size,
Symbol: symbol,
Symbol: test_symbol,
Side: models.SELL,
Timestamp: timestamp,
}
Expand All @@ -79,7 +79,7 @@ func TestRedisRepository_StoreOpenOrder(t *testing.T) {
Score: float64(timestamp.UnixNano()),
Member: sellOrder.Id.String(),
}).SetVal(1)
mock.ExpectSetNX(Order2MakerTokenTrackKey(order), -1, 0).SetVal(true)
mock.ExpectSetNX(Order2MakerTokenTrackKey(sellOrder), -1, 0).SetVal(true)
mock.ExpectTxPipelineExec()

err := repo.StoreOpenOrder(ctx, sellOrder)
Expand All @@ -96,20 +96,20 @@ func TestRedisRepository_StoreOpenOrder(t *testing.T) {
}

mock.ExpectTxPipeline()
mock.ExpectHSet(CreateOrderIDKey(order.Id), order.OrderToMap()).SetErr(assert.AnError)
mock.ExpectSet(CreateClientOIDKey(order.ClientOId), order.Id.String(), 0).SetVal("OK")
mock.ExpectZAdd(CreateSellSidePricesKey(order.Symbol), redis.Z{
mock.ExpectHSet(CreateOrderIDKey(test_order.Id), test_order.OrderToMap()).SetErr(assert.AnError)
mock.ExpectSet(CreateClientOIDKey(test_order.ClientOId), test_order.Id.String(), 0).SetVal("OK")
mock.ExpectZAdd(CreateSellSidePricesKey(test_order.Symbol), redis.Z{
Score: 10.0016969392,
Member: order.Id.String(),
Member: test_order.Id.String(),
}).SetVal(1)
mock.ExpectZAdd(CreateUserOpenOrdersKey(order.UserId), redis.Z{
Score: float64(order.Timestamp.UnixNano()),
Member: order.Id.String(),
mock.ExpectZAdd(CreateUserOpenOrdersKey(test_order.UserId), redis.Z{
Score: float64(test_order.Timestamp.UnixNano()),
Member: test_order.Id.String(),
}).SetErr(assert.AnError)
mock.ExpectExists(Order2MakerTokenTrackKey(order)).SetVal(0)
mock.ExpectSetNX(Order2MakerTokenTrackKey(order), -1, 0).SetVal(true)
mock.ExpectExists(Order2MakerTokenTrackKey(test_order)).SetVal(0)
mock.ExpectSetNX(Order2MakerTokenTrackKey(test_order), -1, 0).SetVal(true)

err := repo.StoreOpenOrder(ctx, order)
err := repo.StoreOpenOrder(ctx, test_order)

assert.ErrorContains(t, err, "PerformTx txEnd commit failed", "should return error")
})
Expand Down
Loading

0 comments on commit 9b8f0a8

Please sign in to comment.