> ## 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](/docs/products/orderbook/collection-bids).
The seller must still choose a concrete token when filling, but that token’s **indexed attributes** must satisfy all of your trait criteria.

<Info>
  See [Getting Started](/docs/products/orderbook/overview#getting-started) for prerequisites and installation.
</Info>

## 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](/docs/products/passport/authentication) or wallet, [fees](/docs/products/orderbook/fees), 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](/docs/products/orderbook/collection-bids): **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.
</Warning>

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

## 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 metadata matches `traitCriteria`               | Any token whose `metadata_id` matches `metadataId`     |
| **Fulfillment** | Seller sells that token | Seller passes **`tokenId`** | Seller passes **`tokenId`** + metadata must match              | Seller passes **`tokenId`** + `metadata_id` must match |
| **Typical use** | Target a rare ID        | Floor sweep / any item      | Offers on **filtered** sets (e.g. legendary + blue background) | Offers on tokens from a specific template or blueprint |

## Fees and cancellation

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

## Next steps

<CardGroup cols={2}>
  <Card title="Collection bids" icon="gavel" href="/docs/products/orderbook/collection-bids">
    Bids on any NFT in a collection without trait filters
  </Card>

  <Card title="Metadata bids" icon="fingerprint" href="/docs/products/orderbook/metadata-bids">
    Bids on tokens sharing a specific metadata ID
  </Card>

  <Card title="Fill orders" icon="cart-shopping" href="/docs/products/orderbook/fill-orders">
    Fulfillment, actions, and approvals
  </Card>

  <Card title="Order management" icon="list-check" href="/docs/products/orderbook/order-management">
    Status, pagination, and webhooks
  </Card>

  <Card title="Cancel orders" icon="xmark" href="/docs/products/orderbook/cancel-orders">
    Cancel trait bids you created
  </Card>
</CardGroup>
