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
121 changes: 87 additions & 34 deletions cmd/rpc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2506,14 +2506,14 @@ $ curl -X POST localhost:50002/v1/query/tx-by-hash \

**Route:** `/v1/query/order`

**Description**: view a sell order by its unique idnetifier
**Description**: view a sell order by its unique identifier

**HTTP Method**: `POST`

**Request**:

- **height**: `uint64` – the block height to read data from (optional: use 0 to read from the latest block)
- **chainId**: `uint64` – the unique identifier of the committee
- **committee**: `uint64` – the unique identifier of the committee
- **orderId**: `hex-string` – the unique identifier of the order

**Response**:
Expand All @@ -2532,7 +2532,7 @@ $ curl -X POST localhost:50002/v1/query/tx-by-hash \
$ curl -X POST localhost:50002/v1/query/order \
-H "Content-Type: application/json" \
-d '{
"chainId": 1,
"committee": 1,
"orderId": "abb1f314f5f300d315a56581ccb0f10fe1665f90c8f09666f7c58abcabfbcedb",
"height": 1000
}'
Expand All @@ -2554,56 +2554,109 @@ $ curl -X POST localhost:50002/v1/query/order \

**Route:** `/v1/query/orders`

**Description**: view all sell orders for a counter-asset pair
**Description**: view all sell orders for a counter-asset pair with optional filters and pagination

**HTTP Method**: `POST`

**Request**:

- **height**: `uint64` – the block height to read data from (optional: use 0 to read from the latest block)
- **id**: `uint64` – the unique identifier of the committee (optional: use 0 to get all committees)
- **committee**: `uint64` – the unique identifier of the committee to filter by (optional: use 0 to get all committees)
- **sellersSendAddress**: `hex-string` – the seller address to filter orders by (optional: when provided, uses indexed lookup for efficient querying)
- **pageNumber**: `int` – the page number to retrieve (optional: starts at 1)
- **perPage**: `int` – the number of orders per page (optional: defaults to system default)

**Response**:
- **orders**: `object` - the swap order book from the 'root chain' for the 'nested chain'
- **chainId**: `uint64` - the unique identifier of the committee
- **orders**: `sell order array` - the actual list of sell orders
- **id**: `hex string` - the 20 byte identifier of the order
- **committee**: `uint64` - the id of the committee that is in-charge of escrow for the swap
- **data**: `hex-string` - a generic data field which can allow a committee to execute specific functionality for the swap
- **amountForSale**: `uint64` - amount of 'root-chain-asset' for sale
- **requestedAmount**: `uint64` - amount of 'counter-asset' the seller of the 'root-chain-asset' receives
- **sellerReceiveAddress**: `hex-string` - the external chain address to receive the 'counter-asset'
- **buyerSendAddress**: `hex-string` - if reserved (locked): the address the buyer will be transferring the funds from
- **buyerChainDeadline**: `hex-string` - the external chain height deadline to send the 'tokens' to SellerReceiveAddress
- **sellersSendAddress**: `hex-string` - the signing address of seller who is selling the CNPY


- **pageNumber**: `int` - the current page number
- **perPage**: `int` - the number of items per page
- **results**: `sell order array` - the paginated list of sell orders
- **id**: `hex string` - the 20 byte identifier of the order
- **committee**: `uint64` - the id of the committee that is in-charge of escrow for the swap
- **data**: `hex-string` - a generic data field which can allow a committee to execute specific functionality for the swap
- **amountForSale**: `uint64` - amount of 'root-chain-asset' for sale
- **requestedAmount**: `uint64` - amount of 'counter-asset' the seller of the 'root-chain-asset' receives
- **sellerReceiveAddress**: `hex-string` - the external chain address to receive the 'counter-asset'
- **buyerSendAddress**: `hex-string` - if reserved (locked): the address the buyer will be transferring the funds from
- **buyerChainDeadline**: `hex-string` - the external chain height deadline to send the 'tokens' to SellerReceiveAddress
- **sellersSendAddress**: `hex-string` - the signing address of seller who is selling the CNPY
- **type**: `string` - the type of paginated results ("orders")
- **count**: `int` - the number of items in this page
- **totalPages**: `int` - the total number of pages available
- **totalCount**: `int` - the total number of orders matching the filters

**Example 1: Basic pagination**
```
$ curl -X POST localhost:50002/v1/query/orders \
-H "Content-Type: application/json" \
-d '{
"chainId": 1,
"height": 1000
"pageNumber": 1,
"perPage": 10
}'

> {
"chainID": 1,
"orders": [
"pageNumber": 1,
"perPage": 10,
"results": [
{
"id": "abb1f314f5f300d315a56581ccb0f10fe1665f90c8f09666f7c58abcabfbcedb",
"committee": "1",
"data": "",
"amountForSale": 1000000000000,
"requestedAmount": 2000000000000,
"sellersReceiveAddress": "502c0b3d6ccd1c6f164aa5536b2ba2cb9e80c711",
"buyerSendAddress": "aaac0b3d64c12c6f164545545b2ba2ab4d80deff",
"buyerChainDeadline": 17585,
"sellersSendAddress": "bb43c46244cef15f2451a446cea011fc1a2eddfe"
}
]
"id": "abb1f314f5f300d315a56581ccb0f10fe1665f90c8f09666f7c58abcabfbcedb",
"committee": 1,
"amountForSale": 1000000000000,
"requestedAmount": 2000000000000,
"sellerReceiveAddress": "502c0b3d6ccd1c6f164aa5536b2ba2cb9e80c711",
"sellersSendAddress": "bb43c46244cef15f2451a446cea011fc1a2eddfe"
},
{
"id": "ccd2f425f6f411e426b67692ddc1f21gf2776ga1d9g1a777g8d69bcdbacddfec",
"committee": 1,
"amountForSale": 500000000000,
"requestedAmount": 1000000000000,
"sellerReceiveAddress": "613d1c4e7dde2d7g275bb6647c3cb3dc0f91d822",
"buyerSendAddress": "aaac0b3d64c12c6f164545545b2ba2ab4d80deff",
"buyerChainDeadline": 17585,
"sellersSendAddress": "cc54d57355dfg26g3562b557dfb122gd2b3feegh"
}
],
"type": "orders",
"count": 2,
"totalPages": 1,
"totalCount": 2
}
```

**Example 2: Filter by committee with pagination**
```
$ curl -X POST localhost:50002/v1/query/orders \
-H "Content-Type: application/json" \
-d '{
"committee": 1,
"pageNumber": 1,
"perPage": 20
}'
```

**Example 3: Filter by sellersSendAddress with pagination (uses indexed lookup)**
```
$ curl -X POST localhost:50002/v1/query/orders \
-H "Content-Type: application/json" \
-d '{
"sellersSendAddress": "bb43c46244cef15f2451a446cea011fc1a2eddfe",
"pageNumber": 1,
"perPage": 10
}'
```

**Example 4: Filter by both committee and sellersSendAddress with pagination (most efficient)**
```
$ curl -X POST localhost:50002/v1/query/orders \
-H "Content-Type: application/json" \
-d '{
"committee": 1,
"sellersSendAddress": "bb43c46244cef15f2451a446cea011fc1a2eddfe",
"pageNumber": 1,
"perPage": 10
}'
```

## Dex Batch
**Route:** `/v1/query/dex-batch`
**Description**: view the locked dex batch for a committee or all dex batches
Expand Down
6 changes: 3 additions & 3 deletions cmd/rpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -1018,10 +1018,10 @@ func (c *Client) heightRequest(routeName string, height uint64, ptr any) (err li
return
}

func (c *Client) orderRequest(routeName string, height uint64, orderId string, chainId uint64, ptr any) (err lib.ErrorI) {
func (c *Client) orderRequest(routeName string, height uint64, orderId string, committee uint64, ptr any) (err lib.ErrorI) {
bz, err := lib.MarshalJSON(orderRequest{
ChainId: chainId,
OrderId: orderId,
Committee: committee,
OrderId: orderId,
heightRequest: heightRequest{
Height: height,
},
Expand Down
42 changes: 31 additions & 11 deletions cmd/rpc/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,30 +269,33 @@ func (s *Server) EcoParameters(w http.ResponseWriter, r *http.Request, _ httprou
})
}

// Order gets an order for the specified chain
// Order gets an order for the specified committee
func (s *Server) Order(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
// Invoke helper with the HTTP request, response writer and an inline callback
s.orderParams(w, r, func(s *fsm.StateMachine, p *orderRequest) (any, lib.ErrorI) {
orderId, err := lib.StringToBytes(p.OrderId)
if err != nil {
return nil, err
}
return s.GetOrder(orderId, p.ChainId)
return s.GetOrder(orderId, p.Committee)
})
}

// Orders retrieves the order book for a committee
// Orders retrieves the order book for a committee with optional filters and pagination
func (s *Server) Orders(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
// Invoke helper with the HTTP request, response writer and an inline callback
s.heightAndIdParams(w, r, func(s *fsm.StateMachine, id uint64) (any, lib.ErrorI) {
if id == 0 {
return s.GetOrderBooks()
}
b, err := s.GetOrderBook(id)
if err != nil {
return nil, err
s.ordersParams(w, r, func(s *fsm.StateMachine, req *ordersRequest) (any, lib.ErrorI) {
// convert seller address if provided
var sellerAddr []byte
if req.SellersSendAddress != "" {
var err lib.ErrorI
sellerAddr, err = lib.StringToBytes(req.SellersSendAddress)
if err != nil {
return nil, err
}
}
return &lib.OrderBooks{OrderBooks: []*lib.OrderBook{b}}, nil
// use paginated query
return s.GetOrdersPaginated(sellerAddr, req.Committee, req.PageParams)
})
}

Expand Down Expand Up @@ -664,8 +667,25 @@ func (s *Server) IndexerBlobsCached(height uint64, delta bool) (*fsm.IndexerBlob

// orderParams is a helper function to abstract common workflows around a callback requiring a state machine and order request
func (s *Server) orderParams(w http.ResponseWriter, r *http.Request, callback func(s *fsm.StateMachine, request *orderRequest) (any, lib.ErrorI)) {
// initialize a new orderRequest object
req := new(orderRequest)
// execute the callback with the state machine and request
s.readOnlyStateFromHeightParams(w, r, req, func(state *fsm.StateMachine) (err lib.ErrorI) {
p, err := callback(state, req)
if err != nil {
write(w, err, http.StatusBadRequest)
return
}
write(w, p, http.StatusOK)
return
})
}

// ordersParams is a helper function to abstract common workflows around a callback requiring a state machine and orders request
func (s *Server) ordersParams(w http.ResponseWriter, r *http.Request, callback func(s *fsm.StateMachine, request *ordersRequest) (any, lib.ErrorI)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function is the exact same one as the one above orderParams but with a different struct, there are multiple implementations like this on this file (likely AI generated) but is unmaintainable long term as it is requiring a different function for every different struct, this is a perfect example to use generics or use any/type-casting to minimize this issue, no further actions based on this, just documenting for future refactors

// initialize a new ordersRequest object
req := new(ordersRequest)
// execute the callback with the state machine and request
s.readOnlyStateFromHeightParams(w, r, req, func(state *fsm.StateMachine) (err lib.ErrorI) {
p, err := callback(state, req)
if err != nil {
Expand Down
11 changes: 9 additions & 2 deletions cmd/rpc/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,18 @@ type chainRequest struct {
}

type orderRequest struct {
ChainId uint64 `json:"chainId"`
OrderId string `json:"orderId"`
Committee uint64 `json:"committee"`
OrderId string `json:"orderId"`
heightRequest
}

type ordersRequest struct {
Committee uint64 `json:"committee"`
SellersSendAddress string `json:"sellersSendAddress"`
heightRequest
lib.PageParams
}

type heightsRequest struct {
heightRequest
StartHeight uint64 `json:"startHeight"`
Expand Down
11 changes: 11 additions & 0 deletions fsm/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ var (
orderBookPrefix = []byte{13} // store key prefix for 'sell orders' before they are bid on
retiredCommitteePrefix = []byte{14} // store key prefix for 'retired' (dead) committees
dexPrefix = []byte{15} // store key prefix for 'dex' functionality
orderBySellerPrefix = []byte{16} // store key prefix for 'sell orders' indexed by seller address

lockedBatchSegment = []byte{1}
nextBatchSement = []byte{2}
Expand Down Expand Up @@ -78,6 +79,16 @@ func OrderBookPrefix(cId uint64) []byte { return lib.JoinLenPrefix(orderBookPref
func KeyForOrder(chainId uint64, orderId []byte) []byte {
return append(OrderBookPrefix(chainId), lib.JoinLenPrefix(orderId)...)
}

func OrderBySellerPrefix(seller []byte) []byte {
return lib.JoinLenPrefix(orderBySellerPrefix, seller)
}
func OrderBySellerAndChainPrefix(seller []byte, chainId uint64) []byte {
return append(OrderBySellerPrefix(seller), lib.JoinLenPrefix(formatUint64(chainId))...)
}
func KeyForOrderBySeller(seller []byte, chainId uint64, orderId []byte) []byte {
return append(OrderBySellerAndChainPrefix(seller, chainId), lib.JoinLenPrefix(orderId)...)
}
func KeyForUnstaking(height uint64, address crypto.AddressI) []byte {
return append(UnstakingPrefix(height), lib.JoinLenPrefix(address.Bytes())...)
}
Expand Down
Loading
Loading