Sign In / Up

Non-fungible tokens on Stacks

Creating non-fungible tokens on Stacks

Non-fungible tokens or NFTs are digital assets registered on a blockchain with unique identifiers and properties that distinguish them from each other.

This contract example implements a basic NFT collection that conforms to the SIP-009 NFT standard

Key Components

Trait Implementation

(impl-trait 'SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait.nft-trait)

The contract implements the SIP-009 NFT trait, which is a standardized interface ensuring your NFTs will be compatible with wallets, marketplaces, and other applications in the Stacks ecosystem.

NFT Definition

(define-non-fungible-token Your-NFT-Name uint)

This creates your NFT collection with Your-NFT-Name as the identifier. Each token will have a unique integer ID.


State Variables

(define-data-var last-token-id uint u0)
(define-data-var base-uri (string-ascii 80) "https://your.api.com/path/to/collection/{id}")
  • last-token-id: Tracks the most recently minted token ID (starts at 0)
  • base-uri: Stores the URL where metadata for each token can be found

Constants

(define-constant CONTRACT_OWNER tx-sender)
(define-constant COLLECTION_LIMIT u1000)
(define-constant ERR_OWNER_ONLY (err u100))
(define-constant ERR_NOT_TOKEN_OWNER (err u101))
(define-constant ERR_SOLD_OUT (err u300))

These define important values used throughout the contract:

  • CONTRACT_OWNER: The deployer of the contract
  • COLLECTION_LIMIT: Maximum number of NFTs that can be minted (1000)
  • Error codes for various failure cases

SIP-009 Required Functions

1. Get Last Token ID

(define-read-only (get-last-token-id)
 (ok (var-get last-token-id))
)

Returns the ID of the most recently minted NFT.

2. Get Token URI

(define-read-only (get-token-uri (token-id uint))
 (ok (some (var-get base-uri)))
)

Returns the metadata URI for a given token. This implementation returns the same URI for all tokens, but you could modify it to return token-specific URIs.

3. Get Owner

(define-read-only (get-owner (token-id uint))
 (ok (nft-get-owner? Your-NFT-Name token-id))
)

Returns the current owner of a specified token using Clarity's built-in nft-get-owner? function.

4. Transfer Function

(define-public (transfer (token-id uint) (sender principal) (recipient principal))
 (begin
  (asserts! (is-eq tx-sender sender) ERR_NOT_TOKEN_OWNER)
  (nft-transfer? Your-NFT-Name token-id sender recipient)
 )
)

Allows an owner to transfer their NFT to another account:

  • Verifies the sender is the current transaction sender
  • Uses Clarity's built-in nft-transfer? function to execute the transfer

Minting Function

(define-public (mint (recipient principal))
 (let ((token-id (+ (var-get last-token-id) u1)))
  (asserts! (< (var-get last-token-id) COLLECTION_LIMIT) ERR_SOLD_OUT)
  (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_OWNER_ONLY)
  (try! (nft-mint? Your-NFT-Name token-id recipient))
  (var-set last-token-id token-id)
  (ok token-id)
 )
)

This function creates a new NFT and assigns it to the specified recipient:

  • Calculates the next token ID
  • Ensures the collection limit hasn't been reached
  • Restricts minting to the contract owner
  • Mints the token using Clarity's built-in nft-mint? function
  • Updates the last token ID
  • Returns the new token ID


Lesson discussion

Swap insights and ask questions about “Build On Stacks”.

Be the first to start the discussion

Ask a question or share your thoughts about this lesson.