Querying Orders
Get a Single Order
import { Orderbook } from '@imtbl/orderbook';
const { result: order } = await orderbook.getListing(orderId);
console.log({
id: order.id,
status: order.status,
price: order.buy.amount,
seller: order.accountAddress,
tokenId: order.sell.tokenId,
});
Use OrdersApi.GetListingAsync() from the zkEVM API package:using Immutable.Api.ZkEvm.Api;
var ordersApi = new OrdersApi();
var listing = await ordersApi.GetListingAsync("imtbl-zkevm-testnet", listingId);
Debug.Log($"Status: {listing.Result.Status}");
Query orders using the Immutable REST API. The Unreal SDK provides HTTP utilities for making API calls. Order data is returned as JSON that you can parse into your game’s data structures.
List Orders for a Collection
import { Orderbook, OrderStatusName } from '@imtbl/orderbook';
const { result } = await orderbook.listListings({
sellItemContractAddress: NFT_CONTRACT,
status: OrderStatusName.ACTIVE,
pageSize: 50,
});
for (const listing of result) {
console.log(`Token #${listing.sell.tokenId}: ${listing.buy.amount} IMX`);
}
Use OrdersApi.ListListingsAsync() from the zkEVM API package:var listings = await ordersApi.ListListingsAsync(
chainName: "imtbl-zkevm-testnet",
sellItemContractAddress: nftContractAddress,
status: OrderStatusName.ACTIVE,
pageSize: 50
);
Query the Immutable REST API for listings. Use the page_cursor query parameter for pagination.
let cursor: string | undefined;
do {
const { result, page } = await orderbook.listListings({
sellItemContractAddress: NFT_CONTRACT,
status: OrderStatusName.ACTIVE,
pageSize: 100,
pageCursor: cursor,
});
for (const listing of result) {
console.log(listing.id);
}
cursor = page.nextCursor;
} while (cursor);
Use the pageCursor parameter for pagination. The response includes Page.NextCursor for fetching the next page.
Order Status
Orders progress through these statuses:
| Status | Description |
|---|
ACTIVE | Order is open and can be filled |
FILLED | Order has been completely filled |
CANCELLED | Order was cancelled by the maker |
EXPIRED | Order passed its expiration time |
INACTIVE | Order is temporarily unfillable |
PENDING | Order is being processed |
Fill Status
Track how much of an order has been filled (relevant for ERC-1155 partial fills):
| Fill Status | Description |
|---|
UNFILLED | No fills yet |
PARTIAL | Some quantity filled |
FILLED | Completely filled |
const { result: order } = await orderbook.getListing(orderId);
console.log({
fillStatus: order.fillStatus.name,
numerator: order.fillStatus.numerator, // Amount filled
denominator: order.fillStatus.denominator, // Total amount
});
// For ERC-1155: Check remaining quantity
const remaining =
BigInt(order.fillStatus.denominator) - BigInt(order.fillStatus.numerator);
console.log(`${remaining} items still available`);
Fill status is included in the listing response from OrdersApi.GetListingAsync(). Check the FillStatus property for numerator/denominator values.
Cancelling Orders
Soft Cancel (Gasless)
Soft cancels are free and instant—the order is marked as cancelled off-chain:
import { Orderbook } from '@imtbl/orderbook';
const { result } = await orderbook.cancelOrders([orderId], address);
console.log('Order cancelled:', result);
Use OrdersApi.CancelOrdersAsync() from the zkEVM API package for soft cancellation.
Soft cancellation is done via the Immutable REST API. No on-chain transaction required.
Soft cancels are immediate but rely on marketplaces respecting the cancellation. The signature remains technically valid on-chain until expiration.
Hard Cancel (On-Chain)
Hard cancels invalidate the order on-chain. This costs gas but guarantees the order cannot be filled:
import { Orderbook } from '@imtbl/orderbook';
// Prepare the cancellation
const { signableAction } = await orderbook.prepareOrderCancellations([orderId]);
// Execute on-chain
const hash = await walletClient.sendTransaction({
to: signableAction.to,
data: signableAction.data,
});
await publicClient.waitForTransactionReceipt({ hash });
console.log('Order cancelled on-chain');
Use OrderbookApi.PrepareOrderCancellationsAsync() to get the transaction data, then execute with Passport:using Immutable.Orderbook.Api;
using Immutable.Orderbook.Model;
var orderbookApi = new OrderbookApi();
// Prepare on-chain cancellation
var request = new PrepareOrderCancellationsRequest(
orderIds: new List<string> { orderId }
);
var response = await orderbookApi.PrepareOrderCancellationsAsync(request);
// Execute on-chain
await passport.ZkEvmSendTransactionWithConfirmation(new TransactionRequest
{
to = response.SignableAction.PopulatedTransactions.To,
data = response.SignableAction.PopulatedTransactions.Data
});
For hard (on-chain) cancellation, send the transaction using ZkEvmSendTransactionWithConfirmation:// After getting cancellation transaction data from the API
FImtblTransactionRequest Request;
Request.To = CancellationTo;
Request.Data = CancellationData;
Passport->ZkEvmSendTransactionWithConfirmation(Request,
FImtblPassportResponseDelegate::CreateLambda([](FImmutablePassportResult Result) {
if (Result.Success) {
UE_LOG(LogTemp, Log, TEXT("Order cancelled on-chain"));
}
}));
When to Use Each
| Scenario | Recommended |
|---|
| User wants to cancel quickly | Soft cancel |
| High-value order | Hard cancel |
| Suspicious activity | Hard cancel |
| Order about to expire | Soft cancel |
Webhooks
Get real-time notifications for order events. Configure in Hub.
| Event | Trigger |
|---|
imtbl_order_updated | Order status changed |
imtbl_activity_sale | Trade completed |
Webhook Payload Example
{
"event_name": "imtbl_order_updated",
"data": {
"id": "order-123",
"status": "FILLED",
"sell": {
"type": "ERC721",
"contract_address": "0x...",
"token_id": "456"
},
"buy": {
"type": "NATIVE",
"amount": "1000000000000000000"
}
}
}
Next Steps