NonFungibleToken API
This module provides the full NonFungibleToken module API.
For an overview of the module, read the NonFungibleToken guide.
import "./node_modules/@openzeppelin/compact-contracts/token/NonFungibleToken";Ledger
_name: Opaque<"string">
sealed ledger
#The immutable token name.
_symbol: Opaque<"string">
sealed ledger
#The immutable token symbol.
_owners: Map<Uint<128>, Either<Bytes<32>, ContractAddress>>
ledger
#Mapping from token IDs to their owner addresses.
_balances: Map<Either<Bytes<32>, ContractAddress>, Uint<128>>
ledger
#Mapping from account addresses to their token balances.
_tokenApprovals: Map<Uint<128>, Either<Bytes<32>, ContractAddress>>
ledger
#Mapping from token IDs to approved addresses.
_operatorApprovals: Map<Either<Bytes<32>, ContractAddress>, Map<Either<Bytes<32>, ContractAddress>, Boolean>>
ledger
#Mapping from owner addresses to operator approvals.
_tokenURIs: Map<Uint<128>, Opaque<"string">>
ledger
#Mapping from token IDs to their metadata URIs.
Witnesses
wit_NonFungibleTokenSK() → Bytes<32>
witness
#Returns the caller's secret key used in deriving the account identifier.
The same key produces the same account identifier across all contracts. Users who desire cross-contract unlinkability should use different keys per contract.
Circuits
ZERO() → Either<Bytes<32>, ContractAddress>
pure
#Returns a canonical zero Either value (left variant with zero Bytes<32>).
Used as the zero value for mint/burn operations and cleared approvals.
initialize(name_: Opaque<"string">, symbol_: Opaque<"string">) → []
circuit
#Initializes the contract by setting the name and symbol.
This MUST be called in the implementing contract's constructor. Failure to do so can lead to an irreparable contract.
Requirements:
- Contract is not initialized.
balanceOf(owner: Either<Bytes<32>, ContractAddress>) → Uint<128>
circuit
#Returns the number of tokens in owner's account.
Requirements:
- Contract is initialized.
ownerOf(tokenId: Uint<128>) → Either<Bytes<32>, ContractAddress>
circuit
#Returns the owner of the tokenId token.
Requirements:
- The contract is initialized.
- The
tokenIdmust exist.
name() → Opaque<"string">
circuit
#Returns the token name.
Requirements:
- Contract is initialized.
symbol() → Opaque<"string">
circuit
#Returns the symbol of the token.
Requirements:
- Contract is initialized.
tokenURI(tokenId: Uint<128>) → Opaque<"string">
circuit
#Returns the token URI for the given tokenId.
Returns an empty string if a tokenURI does not exist.
Requirements:
- The contract is initialized.
- The
tokenIdmust exist.
Native strings and string operations aren't supported within the Compact language, e.g. concatenating a base URI + token ID is not possible like in other NFT implementations. Therefore, we propose the URI storage approach; whereby, NFTs may or may not have unique "base" URIs. It's up to the implementation to decide on how to handle this.
_setTokenURI(tokenId: Uint<128>, tokenURI: Opaque<"string">) → []
circuit
#Sets the URI as tokenURI for the given tokenId.
Requirements:
- The contract is initialized.
- The
tokenIdmust exist.
approve(to: Either<Bytes<32>, ContractAddress>, tokenId: Uint<128>) → []
circuit
#Gives permission to to to transfer tokenId token to another account.
The approval is cleared when the token is transferred.
The caller's identity is derived from the wit_NonFungibleTokenSK witness as persistentHash(secretKey).
Only a single account can be approved at a time, so approving the zero value clears previous approvals.
Requirements:
- The contract is initialized.
- The caller must either own the token or be an approved operator.
tokenIdmust exist.
getApproved(tokenId: Uint<128>) → Either<Bytes<32>, ContractAddress>
circuit
#Returns the account approved for tokenId token.
Requirements:
- The contract is initialized.
tokenIdmust exist.
setApprovalForAll(
operator: Either<Bytes<32>, ContractAddress>,
approved: Boolean
) → []circuit
#Approve or remove operator as an operator for the caller.
Operators can call transferFrom for any token owned by the caller.
The caller's identity is derived from the wit_NonFungibleTokenSK witness as persistentHash(secretKey).
Requirements:
- The contract is initialized.
- The
operatorcannot be zero.
isApprovedForAll(
owner: Either<Bytes<32>, ContractAddress>,
operator: Either<Bytes<32>, ContractAddress>
) → Booleancircuit
#Returns if the operator is allowed to manage all of the assets of owner.
Requirements:
- The contract is initialized.
transferFrom(
fromAddress: Either<Bytes<32>, ContractAddress>,
to: Either<Bytes<32>, ContractAddress>,
tokenId: Uint<128>
) → []circuit
#Transfers tokenId token from fromAddress to to.
The caller's identity is derived from the wit_NonFungibleTokenSK witness as persistentHash(secretKey).
Transfers to contract addresses are currently disallowed until contract-to-contract interactions are supported in Compact. This restriction prevents assets from being inadvertently locked in contracts that cannot currently handle token receipt.
Requirements:
- The contract is initialized.
fromAddressis not zero.tois not zero.tois not a ContractAddress.tokenIdtoken must be owned byfromAddress.- If the caller is not
fromAddress, it must be approved to move this token by either approve or setApprovalForAll.
_unsafeTransferFrom(
fromAddress: Either<Bytes<32>, ContractAddress>,
to: Either<Bytes<32>, ContractAddress>,
tokenId: Uint<128>
) → []circuit
#Unsafe variant of transferFrom which allows transfers to contract addresses.
The caller's identity is derived from the wit_NonFungibleTokenSK witness as persistentHash(secretKey).
Transfers to contract addresses are considered unsafe because contract-to-contract calls are not currently supported. Tokens sent to a contract address may become irretrievable. Once contract-to-contract calls are supported, this circuit may be deprecated.
Requirements:
- The contract is initialized.
fromAddressis not zero.tois not zero.tokenIdtoken must be owned byfromAddress.- If the caller is not
fromAddress, it must be approved to move this token by either approve or setApprovalForAll.
_ownerOf(tokenId: Uint<128>) → Either<Bytes<32>, ContractAddress>
circuit
#Returns the owner of the tokenId. Does NOT revert if token doesn't exist.
Requirements:
- The contract is initialized.
_getApproved(tokenId: Uint<128>) → Either<Bytes<32>, ContractAddress>
circuit
#Returns the approved address for tokenId.
Returns the zero value if tokenId is not minted.
Requirements:
- The contract is initialized.
_isAuthorized(
owner: Either<Bytes<32>, ContractAddress>,
spender: Either<Bytes<32>, ContractAddress>,
tokenId: Uint<128>
) → Booleancircuit
#Returns whether spender is allowed to manage owner's tokens,
or tokenId in particular (ignoring whether it is owned by owner).
Requirements:
- The contract is initialized.
This function assumes that owner is the actual owner of tokenId and does not verify this assumption.
_checkAuthorized(
owner: Either<Bytes<32>, ContractAddress>,
spender: Either<Bytes<32>, ContractAddress>,
tokenId: Uint<128>
) → []circuit
#Checks if spender can operate on tokenId, assuming the provided owner is the actual owner.
Requirements:
- The contract is initialized.
spenderhas approval fromownerfortokenIdORspenderhas approval to manage all ofowner's assets.
This function assumes that owner is the actual owner of tokenId and does not verify this assumption.
_update(
to: Either<Bytes<32>, ContractAddress>,
tokenId: Uint<128>,
auth: Either<Bytes<32>, ContractAddress>
) → Either<Bytes<32>, ContractAddress>internal
#Transfers tokenId from its current owner to to,
or alternatively mints (or burns) if the current owner (or to) is the zero address.
Returns the owner of the tokenId before the update.
Requirements:
- The contract is initialized.
- If
authis non 0, then this function will check thatauthis either the owner of the token, or approved to operate on the token (by the owner).
_mint(to: Either<Bytes<32>, ContractAddress>, tokenId: Uint<128>) → []
circuit
#Mints tokenId and transfers it to to.
Transfers to contract addresses are currently disallowed until contract-to-contract interactions are supported in Compact. This restriction prevents assets from being inadvertently locked in contracts that cannot currently handle token receipt.
Requirements:
- The contract is initialized.
tokenIdmust not exist.tois not zero.tois not a ContractAddress.
_unsafeMint(to: Either<Bytes<32>, ContractAddress>, tokenId: Uint<128>) → []
circuit
#Unsafe variant of _mint which allows transfers to contract addresses.
Transfers to contract addresses are considered unsafe because contract-to-contract calls are not currently supported. Tokens sent to a contract address may become irretrievable. Once contract-to-contract calls are supported, this circuit may be deprecated.
Requirements:
- Contract is initialized.
tokenIdmust not exist.tois not zero.
_burn(tokenId: Uint<128>) → []
circuit
#Destroys tokenId.
The approval is cleared when the token is burned.
This circuit does not check if the sender is authorized to operate on the token.
Requirements:
- The contract is initialized.
tokenIdmust exist.
_transfer(
fromAddress: Either<Bytes<32>, ContractAddress>,
to: Either<Bytes<32>, ContractAddress>,
tokenId: Uint<128>
) → []circuit
#Transfers tokenId from fromAddress to to. As opposed to transferFrom,
this imposes no restrictions on the caller's identity.
Transfers to contract addresses are currently disallowed until contract-to-contract interactions are supported in Compact. This restriction prevents assets from being inadvertently locked in contracts that cannot currently handle token receipt.
Requirements:
- The contract is initialized.
tois not zero.tois not a ContractAddress.tokenIdtoken must be owned byfromAddress.
_unsafeTransfer(
fromAddress: Either<Bytes<32>, ContractAddress>,
to: Either<Bytes<32>, ContractAddress>,
tokenId: Uint<128>
) → []circuit
#Unsafe variant of _transfer which allows transfers to contract addresses.
Transfers tokenId from fromAddress to to. As opposed to _unsafeTransferFrom, this imposes no restrictions on the caller's identity. It does NOT check if the recipient is a ContractAddress.
Transfers to contract addresses are considered unsafe because contract-to-contract calls are not currently supported. Tokens sent to a contract address may become irretrievable. Once contract-to-contract calls are supported, this circuit may be deprecated.
Requirements:
- Contract is initialized.
tois not zero.tokenIdtoken must be owned byfromAddress.
_approve(
to: Either<Bytes<32>, ContractAddress>,
tokenId: Uint<128>,
auth: Either<Bytes<32>, ContractAddress>
) → []circuit
#Approve to to operate on tokenId.
Requirements:
- The contract is initialized.
- If
authis non 0, then this function will check thatauthis either the owner of the token, or approved to operate on the token (by the owner).
_setApprovalForAll(
owner: Either<Bytes<32>, ContractAddress>,
operator: Either<Bytes<32>, ContractAddress>,
approved: Boolean
) → []circuit
#Approve operator to operate on all of owner tokens.
Requirements:
- The contract is initialized.
owneris not zero.operatoris not zero.
_requireOwned(tokenId: Uint<128>) → Either<Bytes<32>, ContractAddress>
circuit
#Reverts if the tokenId doesn't have a current owner (it hasn't been minted, or it has been burned).
Returns the owner.
Requirements:
- The contract is initialized.
tokenIdmust exist.
_computeAccountId() → Bytes<32>
internal
#Computes the caller's account identifier from the wit_NonFungibleTokenSK witness.
ID Derivation: accountId = persistentHash(secretKey)
The result is a 32-byte commitment that uniquely identifies the caller.
computeAccountId(secretKey: Bytes<32>) → Bytes<32>
pure
#Computes an account identifier without on-chain state, allowing a user to derive
their identity commitment before submitting it in a token operation.
This is the off-chain counterpart to the internal _computeAccountId and produces an identical result
given the same inputs.
ID Derivation: accountId = persistentHash(secretKey)
The secretKey parameter is a sensitive secret. Mishandling it can permanently compromise the security of this system.
Never log or persist the key in plaintext. Use cryptographically secure randomness to generate keys.
Treat key loss as identity loss — a lost key cannot be recovered.
_isTargetZero(target: Either<Bytes<32>, ContractAddress>) → Boolean
internal
#Returns true if target's active branch (as indicated by is_left) holds the zero value.