Skip to main content
Immutable’s decentralised trading protocol. Orders created on any marketplace are visible and fillable across the entire ecosystem.

Why Orderbook?

Orders are visible across all Immutable marketplaces. Your players access the entire ecosystem’s liquidity, not just your marketplace.
Creating orders is free—sellers only sign a message. Gas is only paid when orders are filled.
Royalties are enforced at the protocol level. Creators always get paid on secondary sales.
Trades settle on-chain immediately. No waiting, no counterparty risk.

Core Concepts

Before diving into implementation, understand these universal orderbook concepts that apply across all platforms:

Order Types

Order TypeDescriptionWho CreatesExample
Listing (Sell Order)NFT owner offers to sell at fixed priceSeller”Selling Sword #123 for 1 IMX”
Bid (Buy Order)Buyer offers to buy specific NFTBuyer”Offering 0.5 IMX for Sword #123”
Collection BidBuyer offers to buy ANY NFT in collectionBuyer”Offering 0.3 IMX for any Sword”

Token Standards

Different NFT types behave differently in the orderbook:
  • Each token is unique (e.g., specific Sword #123)
  • Amount is always 1
  • Orders use FULL_RESTRICTED type
  • Cannot be partially filled
  • Most common for gaming items and collectibles
  • Learn more about ERC-721 contracts
  • ERC-20: Fungible tokens (e.g., USDC, project tokens)
  • NATIVE: Chain native currency (IMX on Immutable zkEVM)
  • Used as payment currency in orders
  • Amounts specified in smallest unit (wei)
  • Learn more about ERC-20 tokens

Maker vs Taker Model

The orderbook uses a maker/taker model to distinguish between liquidity providers and consumers: Maker 👷 Creates an order that goes on the orderbook (adds liquidity)
  • Listings: Sellers are makers
  • Bids: Buyers are makers
  • Typically pay lower fees to incentivize order creation
  • Maker fees set at order creation and cannot be changed
Taker 🛒 Fills an existing order (removes liquidity)
  • Filling listings: Buyers are takers
  • Filling bids: Sellers are takers
  • Typically pay higher fees as they consume liquidity
  • Taker fees set flexibly at fulfillment time

Order Lifecycle

Orders progress through these statuses:
StatusDescriptionTerminal?
PENDINGOrder submitted, awaiting balance/approval checksNo
ACTIVEOrder is live and can be filledNo
INACTIVETemporarily unfillable (insufficient balance, revoked approval)No
FILLEDOrder completely filledYes
CANCELLEDOrder cancelled by makerYes
EXPIREDOrder passed expiration timeYes
Optimistic UI: Status transitions happen asynchronously. Build your UI to handle PENDING → ACTIVE transitions gracefully.

Approval Pattern

The orderbook requires token approvals before certain operations: For Sellers (Creating Listings):
  • Before creating your first listing for an NFT collection, approve the Seaport contract to transfer your tokens
  • One-time per collection per user
  • Approval transaction costs gas
  • Subsequent listings of that collection don’t need approval
  • Smart contract wallets (Passport) may have pre-approved contracts via Hub configuration
For Buyers (Filling ERC-20 Orders):
  • Before buying with ERC-20 tokens, approve Seaport to spend those tokens
  • One-time per currency per user (or when allowance insufficient)
  • Native (IMX) orders never require buyer approval
For implementation details, see Creating Listings and Filling Orders

Getting Started

Prerequisites

Before using the Orderbook SDK, ensure you have:
  • User Authentication: Users authenticated with Passport or wallet connected (MetaMask, WalletConnect, etc.)
  • For Sellers:
  • For Buyers:
  • For Order Management:
    • Order IDs for querying or cancellation
    • Order ownership (for cancellation operations)

Installation

Install the orderbook package via npm:
npm install @imtbl/orderbook @imtbl/config

TypeScript SDK Overview

View all available packages and configuration options

Setup

import { Orderbook } from '@imtbl/orderbook';
import { Environment } from '@imtbl/config';

const orderbook = new Orderbook({
  baseConfig: {
    environment: Environment.SANDBOX,
    publishableKey: 'YOUR_PUBLISHABLE_KEY',
  },
});

Creating Listings

Listings let users sell NFTs at a fixed price. Creating a listing is gasless—only the buyer pays gas when filling.
Signed Zone v2 MigrationAs of May 2024, all new listings must use Signed Zone v2 contract. The legacy v1 zone contract is deprecated and will be sunset in May 2025.
  • SDK users: Contract address automatically updated
  • Direct API users: Update zone contract address manually (not recommended - see contract addresses)
  • Existing listings: v1 listings remain supported until May 2025 sunset date

List an ERC-721 NFT

import { Orderbook } from '@imtbl/orderbook';

// Get the user's wallet address
const address = await walletClient.getAddresses().then(a => a[0]);

// Prepare the listing
const { orderComponents, orderHash, typedData } = await orderbook.prepareListing({
  makerAddress: address,
  buy: {
    type: 'NATIVE',
    amount: '1000000000000000000', // 1 IMX in wei
  },
  sell: {
    type: 'ERC721',
    contractAddress: NFT_CONTRACT,
    tokenId: '123',
  },
});

// Sign the order (gasless)
const signature = await walletClient.signTypedData({
  account: address,
  ...typedData,
});

// Submit the listing
const { result } = await orderbook.createListing({
  orderComponents,
  orderHash,
  orderSignature: signature,
  makerFees: [],
});

console.log('Listing created:', result.id);

List an ERC-1155 NFT

For semi-fungible tokens, specify the quantity. Buy amount must be a multiple of sell amount.
const { orderComponents, orderHash, typedData } = await orderbook.prepareListing({
  makerAddress: address,
  buy: {
    type: 'NATIVE',
    amount: '500000000000000000', // 0.5 IMX per item (5 IMX total for 10 items)
  },
  sell: {
    type: 'ERC1155',
    contractAddress: NFT_CONTRACT,
    tokenId: '456',
    amount: '10', // Selling 10 copies
  },
});
// Buy amount (5 IMX) must be multiple of sell amount (10 items)
// This enables partial fills: buyer can purchase 1, 2, 5, or 10 items
Order Type Differences:
  • ERC-721 uses FULL_RESTRICTED order type (cannot be partially filled, amount always 1)
  • ERC-1155 uses PARTIAL_RESTRICTED order type (supports partial fills)
  • SDK automatically sets the correct order type based on token type

Filling Listings (Buying)

When a buyer fills a listing, the trade executes on-chain.
import { Orderbook } from '@imtbl/orderbook';

// Prepare the fill
const { actions } = await orderbook.fulfillOrder(
  `listingId`,
  address, // buyer address
  []       // taker fees (optional)
);

// Execute all required actions (approvals + fill)
for (const action of actions) {
  if (action.type === 'TRANSACTION') {
    const hash = await walletClient.sendTransaction({
      to: action.to,
      data: action.data,
      value: BigInt(action.value || '0'),
    });
    await publicClient.waitForTransactionReceipt({ hash });
  }
}

console.log('Purchase complete!');

Creating Bids

Bids let users make offers on specific NFTs.
import { Orderbook } from '@imtbl/orderbook';

// Prepare the bid
const { orderComponents, orderHash, typedData } = await orderbook.prepareBid({
  makerAddress: address,
  buy: {
    type: 'ERC721',
    contractAddress: NFT_CONTRACT,
    tokenId: '123',
  },
  sell: {
    type: 'NATIVE',
    amount: '500000000000000000', // Offering 0.5 IMX
  },
});

// Sign and submit (same pattern as listings)
const signature = await walletClient.signTypedData({
  account: address,
  ...typedData,
});

const { result } = await orderbook.createBid({
  orderComponents,
  orderHash,
  orderSignature: signature,
  makerFees: [],
});

console.log('Bid created:', result.id);

Order Expiration

Set when orders should expire:
const prepared = await orderbook.prepareListing({
  makerAddress: address,
  buy: { type: 'NATIVE', amount: '1000000000000000000' },
  sell: { type: 'ERC721', contractAddress: NFT_CONTRACT, tokenId: '123' },
  // Expire in 7 days
  expiration: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
});
ExpirationUse Case
1 hourFlash sales
24 hoursDaily auctions
7 daysStandard listings
30 daysLong-term listings

Next Steps