# NFTs and Collectibles

An NFT collection is `validTokenIds` set to a range and a mint approval. Every question a marketplace contract usually answers (can it trade, can it burn, who takes a royalty, what is listed at what price) is an approval on the collection or on a holder's own account. Listings and bids are outgoing and incoming approvals with a coin transfer attached, so the orderbook lives in the same place as the tokens.

Editions are the same collection with an amount above 1 per token ID. Soulbound is the same collection with no post-mint approval.

## What Makes It Work

| Requirement | Token-standard primitive |
| --- | --- |
| 100 unique tokens | `validTokenIds: [{ "start": "1", "end": "100" }]` and amount `1` per transfer. See [Collections](https://docs.bitbadges.io/token-standard/concepts/collections) |
| Per-token metadata | `tokenMetadata` URI with an `{id}` placeholder |
| Tradable | A post-mint approval `fromListId: "!Mint"`, `toListId: "All"`, plus the `NFTMarketplace` and `NFTPricingDenom:ubadge` standards. See [Set Transferability](https://docs.bitbadges.io/guides/set-transferability) |
| Listed at a price | The seller's outgoing approval with `coinTransfers` to the seller. `bb build listing` writes it |
| Bid on a token or the whole collection | The bidder's incoming approval with `coinTransfers` from the bidder. `bb build bid` writes it |
| Royalty on every sale | `userApprovalSettings` on the collection approval. See [User Approval Settings](https://docs.bitbadges.io/token-standard/approval-criteria/user-approval-settings) |
| Supply capped forever | `invariants.maxSupplyPerId` and `canUpdateValidTokenIds` locked. See [Minting and Supply](https://docs.bitbadges.io/token-standard/concepts/minting-and-supply) |

## The Fields That Matter

```json
{
  "standards": ["NFTs", "NFTMarketplace", "NFTPricingDenom:ubadge"],
  "validTokenIds": [{ "start": "1", "end": "100" }],
  "tokenMetadata": [{ "tokenIds": [{ "start": "1", "end": "100" }], "uri": "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi/{id}.json" }],
  "collectionApprovals": [
    {
      "approvalId": "creator-mint",
      "fromListId": "Mint",
      "toListId": "All",
      "initiatedByListId": "bb1p0rrel3365scadq5k9pv0x0zp9j22js6dnw70d",
      "approvalCriteria": { "overridesFromOutgoingApprovals": true }
    },
    {
      "approvalId": "transferable-approval",
      "fromListId": "!Mint",
      "toListId": "All",
      "initiatedByListId": "All",
      "approvalCriteria": {}
    }
  ]
}
```

Delete `transferable-approval` and the collection is soulbound. Replace `toListId: "All"` with the burn address and it is burnable but not tradable.

```bash
bb build listing --address bb1p0rrel3365scadq5k9pv0x0zp9j22js6dnw70d --collection-id 1 --token-ids 4 --price 40 --denom USDC --expiration 30d
bb build bid --address bb1py4mfpg6uf59qkyzg0nmau322c5873eeysp5ue --collection-id 1 --price 35 --denom USDC --expiration 7d
```

The first emits a MsgSetOutgoingApproval that sells token 4 for 40 USDC to whoever executes it. The second emits a MsgSetIncomingApproval that buys any token in the collection for 35 USDC. When a transfer matches both, the token and the coins move in one transaction.

## Variations

- Editions: mint amount `50` of token ID 1 instead of amount `1` of IDs 1 to 50.
- Allowlist mint: `merkleChallenges` on the mint approval, or a [claim](https://docs.bitbadges.io/guides/distribute-with-claims) with plugins that emit the proof.
- Paid mint: `coinTransfers` on the mint approval with the price.
- Admin revocation: a manager-only approval with both override flags, for a ticket that must be voidable.
- One-item sale with a bidding window: an [auction](https://docs.bitbadges.io/use-cases/crowdfunding-and-auctions), where the token is minted straight to the winner.

## Build It

- Skill: [NFT Collection](https://docs.bitbadges.io/agents/skills/nft-collection), [Tradable](https://docs.bitbadges.io/agents/skills/tradable), [Burnable](https://docs.bitbadges.io/agents/skills/burnable)
- Guide: [Create a Collection](https://docs.bitbadges.io/guides/create-a-collection), [Set Transferability](https://docs.bitbadges.io/guides/set-transferability)
- CLI: [`bb build listing`](https://docs.bitbadges.io/cli/build#listing), [`bb build bid`](https://docs.bitbadges.io/cli/build#bid), `bb nfts` from [Standards](https://docs.bitbadges.io/cli/standards#nfts)

```text
Load the nft-collection and tradable skills. Create a 500-piece collection called Demo Relics with metadata at ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi/{id}.json, where only I can mint, holders can trade, and supply is locked. Validate, review, simulate, then give me the review link.
```
