> ## Documentation Index
> Fetch the complete documentation index at: https://docs.immutable.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Trait bids

Place bids on NFTs in a collection whose metadata matches filters you define (for example, `Background` is `Blue` or `Red`). Trait bids are a stricter form of [collection bids](https://docs.immutable.com/docs/products/orderbook/collection-bids.md).
The seller must still choose a concrete token when filling, but that token’s **indexed attributes** must satisfy all of your trait criteria.

> [!NOTE]
>
> See [Getting Started](https://docs.immutable.com/docs/products/orderbook/overview.md#getting-started) for prerequisites and installation.

## What is a trait bid?

* You offer **ERC-20**  tokens to buy **one or more** NFTs from a collection,
  identified by an **ERC-721 collection** or **ERC-1155 collection** buy item.
* You attach **`traitCriteria`**: an array of filters. Each filter has a
  **trait type** (metadata attribute name) and a list of **allowed values**.
* **Matching semantics:** every trait type you specify must be matched by the NFT’s metadata. For a given type, the token matches if its attribute value is **one** of the values you listed.
  Matching is **case-insensitive** for values and numerical values are converted to their string equivalent.
* Orders appear as **`TRAIT_BID`** in API responses alongside listings, bids, and collection bids. Use the order `type` field when branching in your app or webhooks.

## Prerequisites

* Same setup as other orderbook flows ([Passport](https://docs.immutable.com/docs/products/passport/authentication.md) or wallet, [fees](https://docs.immutable.com/docs/products/orderbook/fees.md), etc.).
* **Metadata for fulfillment:** when a seller fills your bid with a specific `tokenId`, Immutable validates that token’s **attributes** against your criteria.
  That requires the NFT’s metadata to be available through Immutable’s [indexer](docs/products/indexer/overview). If metadata is missing or out of date, fulfillment can fail even
  if the token exists on-chain.

## Creating a trait bid

The flow mirrors [collection bids](https://docs.immutable.com/docs/products/orderbook/collection-bids.md): **prepare** (builds `orderComponents`, `orderHash`, and `actions`) → run any **approval** transactions → **sign** the EIP-712 order from the `SIGNABLE` action → **create**.

```typescript theme={null}
import { Orderbook, ActionType } from '@imtbl/orderbook';

const prepared = await orderbook.prepareTraitBid({
  makerAddress: address,
  buy: {
    type: 'ERC721_COLLECTION',
    contractAddress: NFT_CONTRACT,
    amount: '1',
  },
  sell: {
    type: 'ERC20',
    contractAddress: PAYMENT_TOKEN,
    amount: '1000000000000000000', // wei
  },
});

// 1) Submit approval txs from prepared.actions (if any)
for (const action of prepared.actions) {
  if (action.type === ActionType.TRANSACTION) {
    const tx = await action.buildTransaction();
    await walletClient.sendTransaction(tx);
  }
}

// 2) Sign the CREATE_ORDER payload from the SIGNABLE action (EIP-712; same shape as collection bids)
const signable = prepared.actions.find((a) => a.type === ActionType.SIGNABLE);
if (!signable) throw new Error('Missing signable order action');

const orderSignature = await walletClient.signTypedData({
  account: address,
  domain: signable.message.domain,
  types: signable.message.types,
  primaryType: 'OrderComponents',
  message: signable.message.value,
});

// 3) Create the trait bid on Immutable
const { result } = await orderbook.createTraitBid({
  orderComponents: prepared.orderComponents,
  orderHash: prepared.orderHash,
  orderSignature,
  makerFees: [],
  // The NFT used for fulfillment must have:
  //   - A `Background` trait, with a value of eitehr `Blue` or `Red`
  //   - A `Rarity` trait, with a value of `Legendary`
  traitCriteria: [
    { traitType: 'Background', values: ['Blue', 'Red'] },
    { traitType: 'Rarity', values: ['Legendary'] },
  ],
});

console.log('Trait bid created:', result.id);
```

## Filling a trait bid (seller)

Sellers call **`fulfillOrder`** with the **trait bid order id** and the **token ID** they are selling. The fifth argument is `tokenId` (criteria fulfillment); pass **`undefined`** for `amountToFill` when you are not doing a partial ERC-1155 quantity fill.

```typescript theme={null}
import { Orderbook } from '@imtbl/orderbook';

const { actions } = await orderbook.fulfillOrder(
  traitBidId,
  sellerAddress,
  [], // taker fees
  undefined, // amountToFill — unused for standard ERC-721 trait fill
  '123', // tokenId — required: which NFT the seller is selling into the bid
);

// Execute actions (approvals + fulfill) in order — same as filling listings
for (const action of actions) {
  if (action.type === 'TRANSACTION') {
    const unsignedTx = await action.buildTransaction();
    const hash = await walletClient.sendTransaction(unsignedTx);
    await publicClient.waitForTransactionReceipt({ hash });
  }
}
```

> [!WARNING]
>
> If the token’s **indexed metadata** does not satisfy **every** trait filter on the bid, the orderbook will **not** return valid fulfillment data for that token.

For more context on actions, fees, and expiry, see [Fill orders](https://docs.immutable.com/docs/products/orderbook/fill-orders.md).

## Querying trait bids

### List trait bids

Filter by collection contract, status, maker, and pagination — same ergonomics as `listCollectionBids`.

```typescript theme={null}
import { Orderbook, OrderStatusName } from '@imtbl/orderbook';

const { result, page } = await orderbook.listTraitBids({
  buyItemContractAddress: NFT_CONTRACT,
  status: OrderStatusName.ACTIVE,
  pageSize: 50,
});

for (const bid of result) {
  console.log(bid.id, bid.traitCriteria, bid.sell.amount);
}
```

### Get one trait bid

```typescript theme={null}
const { result: bid } = await orderbook.getTraitBid(traitBidId);

console.log({
  id: bid.id,
  status: bid.status,
  traitCriteria: bid.traitCriteria,
  sell: bid.sell,
  buy: bid.buy,
});
```

## Comparison: token bid vs collection bid vs trait bid vs metadata bid

| Aspect | Token bid | Collection bid | Trait bid | Metadata bid |
| - | - | - | - | - |
| **Buy target** | One specific `tokenId` | Any token in the collection | Any token whose attributes match `traitCriteria` | Any token matching `metadataId` **or** `metadataCriteria` (top-level fields and/or attributes) |
| **Fulfillment** | Seller sells that token | Seller passes **`tokenId`** | Seller passes **`tokenId`** + attributes must match | Seller passes **`tokenId`** + token must match the bid's `metadataId` or `metadataCriteria` |
| **Typical use** | Target a rare ID | Floor sweep / any item | Offers on **filtered** attribute sets (e.g. legendary + blue background) | Offers on tokens from a specific template (id mode), or human-readable metadata conditions spanning top-level fields and attributes (criteria mode) |

## Fees and cancellation

* **Fees:** same maker/taker concepts as other orders — see [Fees](https://docs.immutable.com/docs/products/orderbook/fees.md).
* **Cancel:** use the bid’s order id with [Cancel orders](https://docs.immutable.com/docs/products/orderbook/cancel-orders.md) (soft or hard cancel patterns apply to open orders).

## Next steps

> [card] [Collection bids](https://docs.immutable.com/docs/products/orderbook/collection-bids.md)
>
> Bids on any NFT in a collection without trait filters

> [card] [Metadata bids](https://docs.immutable.com/docs/products/orderbook/metadata-bids.md)
>
> Bids matched by metadata ID or field-level metadata criteria

> [card] [Fill orders](https://docs.immutable.com/docs/products/orderbook/fill-orders.md)
>
> Fulfillment, actions, and approvals

> [card] [Order management](https://docs.immutable.com/docs/products/orderbook/order-management.md)
>
> Status, pagination, and webhooks

> [card] [Cancel orders](https://docs.immutable.com/docs/products/orderbook/cancel-orders.md)
>
> Cancel trait bids you created


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.