Skip to content

Instantly share code, notes, and snippets.

@ryanio
Last active August 19, 2025 15:23
Show Gist options
  • Select an option

  • Save ryanio/0560c68b501cf03586b2965218efdd13 to your computer and use it in GitHub Desktop.

Select an option

Save ryanio/0560c68b501cf03586b2965218efdd13 to your computer and use it in GitHub Desktop.

How to Create an ERC-1155 Public Mint Order

Overview

To mint ERC-1155 tokens from a public drop, you need to create a Seaport advanced order that represents the mint transaction.

Required Information

  • Contract Address: The ERC-1155 drop contract
  • Token IDs: List of token IDs to mint
  • Quantities: Corresponding quantities for each token ID
  • Minter Address: Wallet address performing the mint
  • Drop Stage Info: Current price, fee basis points, start/end times
  • Payment Recipients: Fee recipient and creator payout addresses

Pre-Mint Validation

Input Validation

// Ensure quantities and token IDs match
if (quantities.length !== tokenIds.length) {
  throw new Error("Quantities and token IDs arrays must have same length");
}

// Ensure non-empty arrays
if (quantities.length === 0) {
  throw new Error("Must specify at least one token to mint");
}

Drop Stage Validation

// Check if drop stage is active
  const currentTime = Math.floor(Date.now() / 1000);
  if (currentTime < dropStage.startTime || currentTime > dropStage.endTime) {
    throw new Error("Drop stage is not currently active");
  }

Supply Validation

// For each token ID:
  // Check remaining supply
  const remainingSupply = dropStage.maxSupply - dropStage.totalMinted;
  if (quantity > remainingSupply) {
    throw new Error(`Insufficient supply remaining: ${remainingSupply} available`);
  }

Wallet Limits Validation

// Check per-wallet total limit
  const walletMinted = getCurrentWalletMintCount(minter, dropContract);
  const walletLimit = dropStage.maxTotalMintableByWallet;
  if (walletMinted + totalQuantity > walletLimit) {
    const remaining = walletLimit - walletMinted;
    throw new Error(`Wallet limit exceeded: ${remaining} remaining`);
  }

  // Check per-wallet per-token limit
  for (const [tokenId, quantity] of tokenQuantities) {
    const walletTokenMinted = getCurrentWalletTokenMintCount(minter, dropContract, tokenId);
    const tokenLimit = dropStage.maxTotalMintableByWalletPerToken;
    if (walletTokenMinted + quantity > tokenLimit) {
      const tokenRemaining = tokenLimit - walletTokenMinted;
      throw new Error(`Token ${tokenId} wallet limit exceeded: ${tokenRemaining} remaining`);
    }
  }

Balance Validation

const totalCost = calculateTotalCost(quantities, dropStage.price);
  const walletBalance = await getWalletBalance(minter);

  // Add minimum gas buffer for free mints
  const minBalance = totalCost === 0 ? parseEther("0.000006") : totalCost;

  if (walletBalance < minBalance) {
    throw new Error("Insufficient balance for mint transaction");
  }

Order Structure

Offer Items (What You're Buying)

offer: [
    {
      itemType: ERC1155,
      token: "0x...", // Drop contract address
      identifierOrCriteria: "1", // Token ID
      startAmount: "5", // Quantity
      endAmount: "5"
    }
    // ... repeat for each token ID
  ]

Consideration Items (Payment)

consideration: [
    {
      itemType: NATIVE,
      token: "0x0000000000000000000000000000000000000000", // ETH = zero address
      identifierOrCriteria: "0",
      startAmount: "fee_amount",
      endAmount: "fee_amount",
      recipient: "0x..." // Fee recipient
    },
    {
      itemType: NATIVE,
      token: "0x0000000000000000000000000000000000000000",
      startAmount: "creator_amount",
      endAmount: "creator_amount",
      recipient: "0x..." // Creator address
    }
    // ... repeat for each creator payout
  ]

Order Parameters

{
    offerer: "0x...", // Drop contract address (not minter)
    zone: "0x0000000000000000000000000000000000000000",
    orderType: CONTRACT, // Special order type for mints
    startTime: 1640995200, // Drop stage start time
    endTime: 1672531200, // Drop stage end time
    zoneHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
    salt: "random_256_bit_number",
    conduitKey: "0x...", // Seaport conduit key
    counter: "0"
  }

Extra Data (SIP-6 Format)

The extraData field contains mint-specific information:

  0x + [version][mint_type][fee_recipient][minter][drop_index]
  - version: 00 (1 byte)
  - mint_type: 00 (1 byte)
  - fee_recipient: 20 bytes
  - minter: Minter wallet address (20 bytes)
  - drop_index: Drop stage index (1 byte)

Transaction Execution

  1. Validate all requirements above
  2. Create the advanced order with proper extraData
  3. Submit via Seaport's fulfillAvailableAdvancedOrders()
  4. Include total payment value in transaction
  5. For multi-token mints, batch multiple orders in single call

Payment Calculation

totalValue = tokenQuantities.sum() * stagePrice
  feeAmount = totalValue * feeBasisPoints / 10000
  creatorAmount = totalValue - feeAmount

  // Validate creator payouts exist for paid mints
  if (stagePrice > 0 && creatorPayouts.length === 0) {
    throw new Error("No creator payouts defined for paid mint");
  }

Error Handling

Common validation errors to handle:

  • INSUFFICIENT_SUPPLY: Not enough tokens remaining
  • WALLET_LIMIT_EXCEEDED: Minter has reached their limit
  • INSUFFICIENT_BALANCE: Not enough ETH for payment
  • STAGE_NOT_ACTIVE: Drop stage is not currently running

The order structure ensures proper payment distribution while the extraData provides the drop contract with necessary mint parameters.

Example Drop URI file (OpenSea will create on your behalf)

  {
    "stages": [
      {
        "uuid": "01926f83-4b8e-7000-8000-000000000001",
        "name": "Bronze Membership",
        "description": "Entry-level membership with basic benefits and community access",
        "isPublic": true,
        "maxTotalMintableByWallet": 3,
        "maxTokenSupplyForStage": 5000,
        "startTime": 1704067200,
        "endTime": 1735689600,
        "restrictFeeRecipients": true,
        "feeBps": 750,
        "paymentToken": "0x0000000000000000000000000000000000000000",
        "startPrice": "50000000000000000",
        "endPrice": "50000000000000000",
        "fromTokenId": 1,
        "toTokenId": 1,
        "maxTotalMintableByWalletPerToken": 3,
        "dropStageIndex": 0
      },
      {
        "uuid": "01926f83-4b8e-7000-8000-000000000002",
        "name": "Silver Membership",
        "description": "Mid-tier membership with enhanced benefits and priority access",
        "isPublic": true,
        "maxTotalMintableByWallet": 2,
        "maxTokenSupplyForStage": 3000,
        "startTime": 1704067200,
        "endTime": 1735689600,
        "restrictFeeRecipients": true,
        "feeBps": 750,
        "paymentToken": "0x0000000000000000000000000000000000000000",
        "startPrice": "150000000000000000",
        "endPrice": "150000000000000000",
        "fromTokenId": 2,
        "toTokenId": 2,
        "maxTotalMintableByWalletPerToken": 2,
        "dropStageIndex": 1
      },
      {
        "uuid": "01926f83-4b8e-7000-8000-000000000003",
        "name": "Gold Membership",
        "description": "Premium membership with exclusive benefits and VIP access",
        "isPublic": true,
        "maxTotalMintableByWallet": 1,
        "maxTokenSupplyForStage": 2000,
        "startTime": 1704067200,
        "endTime": 1735689600,
        "restrictFeeRecipients": true,
        "feeBps": 750,
        "paymentToken": "0x0000000000000000000000000000000000000000",
        "startPrice": "500000000000000000",
        "endPrice": "500000000000000000",
        "fromTokenId": 3,
        "toTokenId": 3,
        "maxTotalMintableByWalletPerToken": 1,
        "dropStageIndex": 2
      }
    ],
    "erc1155TokenMintDetails": [
      {
        "tokenId": "1",
        "groupName": "Membership Level",
        "groupValue": "Bronze",
        "imageUrl": "https://example.com/images/bronze-membership.png"
      },
      {
        "tokenId": "2",
        "groupName": "Membership Level",
        "groupValue": "Silver",
        "imageUrl": "https://example.com/images/silver-membership.png"
      },
      {
        "tokenId": "3",
        "groupName": "Membership Level",
        "groupValue": "Gold",
        "imageUrl": "https://example.com/images/gold-membership.png"
      }
    ]
  }

Key Fields Explained

Stage Fields
  • uuid: Unique identifier for each stage (ULID format)
  • isPublic: true for public stages (no allowlist required)
  • maxTotalMintableByWallet: Total limit across all tokens
  • maxTotalMintableByWalletPerToken: Per-token limit for each wallet
  • startPrice/endPrice: Same value for fixed pricing (Dutch auction if different)
  • fromTokenId/toTokenId: Token ID range this stage covers (single token = same value)
  • dropStageIndex: Index of the stage in the drop configuration
  • feeBps: Fee basis points (750 = 7.5%)
  • paymentToken: 0x0000... for ETH (native chain currency)
  • restrictFeeRecipients: true to only allow configured fee recipients
Token Details
  • tokenId: String representation of the token ID
  • groupName: Category for grouping tokens (e.g., "Membership Level")
  • groupValue: Specific value within the group (e.g., "Bronze")
  • imageUrl: Metadata image URL for the token
Pricing
  • Bronze: 0.05 ETH (50000000000000000 wei)
  • Silver: 0.15 ETH (150000000000000000 wei)
  • Gold: 0.5 ETH (500000000000000000 wei)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment