Skip to main content


Bundle NFTs and Tokens together in Packs that users can open and receive randomly selected tokens from those that were bundled!

To create a new project using this template, use the thirdweb CLI:

npx thirdweb create --template packs

Using this template

In this example, we use packs to create loot boxes that can contain any amount of:

  • ERC-721 NFTs
  • ERC-1155 NFTs
  • ERC-20 tokens

We can open these loot boxes to reveal the tokens inside!


  • Pack contract: To create openable loot boxes that contain NFTs from our Edition and Token contracts.
  • Edition contract: To create NFTs with multiple copies and bundle them into the packs.
  • Token contract: To create our own token that we can bundle into the packs.
  • React SDK: to enable users to connect their wallets with the useMetamask hook, and access hooks such as usePack to interact with the Pack contract.
  • TypeScript SDK: To write scripts that create and deploy our pack contract, and bundle the tokens into the packs.

Using This Repo

To create your own version of this template, you can use the following steps:

1. Get a copy of this repo

Use our CLI to create a copy of this repo on your local machine:

npx thirdweb create --template packs

2. Deploy some contracts!

This example project uses a Token, Edition, and Pack contract.

You can deploy all of these contracts via the thirdweb dashboard

This project also includes a deployPack script that you can use to deploy the pack contract and a bundleTokens script that you can use to bundle the tokens (from your NFT/Token contracts) into the packs.

3. Plug in your NFT Drop contract address

Replace the example contract addresses with your contract addresses in the pages, scripts, and components of this project.

You can use find and replace to change these contract addresses. Our example contract addresses are:

  • Pack: 0x0Aee160411473f63be2DfF2865E81A1D59636C97
  • Token: 0x270d0f9DA22332F33159337E3DE244113a1C863C
  • Edition: 0xb4A48c837aB7D0e5C85eA2b0D9Aa11537340Fa17


Below, you'll find the core features of this example explained!

Creating a Pack Contract

You can use the thirdweb dashboard to deploy a pack contract.

In this example project, we have written a script to deploy the pack contract via the SDK in deployPack.ts.

const packAddress = await sdk.deployer.deployPack({
name: "Treasure Chests",
primary_sale_recipient: "0xb371d1C5629C70ACd726B20a045D197c256E1054",

Bundling Tokens

Inside the bundleTokens script, we can bundle NFTs and Tokens into the packs.

We bundle 500 units worth of tokens to create 100 packs with 5 rewards each.

const packNfts = await pack.create({
// ... our tokens and NFTs here
// ...
rewardsPerPack: 5,

Connecting to User Wallets

We wrap our application in the ThirdwebProvider in the _app.tsx so that we can use all of the React SDK's hooks:

<ThirdwebProvider desiredChainId={activeChainId}>
<Component {...pageProps} />

Now in the index.tsx file, we can use the useMetamask hook to connect to the user's wallet:

const address = useAddress();
const connectWithMetamask = useMetamask();
const disconnectWallet = useDisconnect();

Connecting to our Pack Contract

We use the usePack hook to connect to the pack contract using it's contract address:

const pack = usePack("0x0Aee160411473f63be2DfF2865E81A1D59636C97");

Viewing Packs Owned by the Connected Wallet

Since each pack is an ERC-1155 NFT itself, we can use the useOwnedNFTs hook to view the packs (and quantity) that the user owns:

const { data: nfts, isLoading } = useOwnedNFTs(pack, address);

We use the nfts array to display the packs that the user owns on the UI.

Opening Packs

To open a pack, we simply pass the tokenId of the pack and the quantity to open to the open function:

const openedRewards = await pack?.open(0, 1); // 0 = tokenId, 1 = quantity

Displaying Rewards

We then use the values returned in this openedRewards object to display the tokens that the user opened.

Since the openedRewards object returns the contractAddress and tokenId, we use the useNFT or the useMetadata hook (for ERC-20 tokens) to get the metadata of the tokens that were opened:

// For ERC-1155 / ERC-721 tokens:
const edition = useEdition(reward.contractAddress);
const { data } = useNFT(edition, reward.tokenId);

// For ERC-20 tokens:
const token = useToken(reward.contractAddress);
const { data } = useMetadata(token);

Then we again map over the rewards arrays contained in the openedRewards object and display the rewards that the user opened on the UI.

Join our Discord!

For any questions, suggestions, join our discord at