Contract Client Reference
Complete reference for apps/emprops-studio/clients/contract-client.ts - the core NFT contract interaction layer.
Overview
The contract client is a ~1,270 line TypeScript module that handles all blockchain interactions for NFT collections. It supports:
- Tezos (FA2) - Production
- Ethereum (ERC721) - Development
- Base (ERC721) - Development
Type Definitions
Blockchain Types
type Blockchain = "TEZOS" | "ETHEREUM" | "BASE"
type TezosCollectionKey = "projects" | "collections"Collection Configuration
interface CollectionContractConfig {
price: number // Native token units
editions: number // Max supply
status: "ON" | "OFF"
}Receiver (Revenue Split)
interface Receiver {
part_account: string // Wallet address
part_value: number // Basis points (10000 = 100%)
}Mint Modes
// Tezos V1 (Projects)
enum MintMode {
ALLOWLIST = 0,
FREELIST = 1,
ALL = 2
}
// Tezos V2 (Collections)
enum CollectionMintMode {
PUBLIC = 0,
ALLOW_LIST = 1,
FREE_LIST = 2
}
// Contract Status
enum Status {
OFF = 0,
ON = 1
}Collection Reading Functions
getTezCollection()
Fetches on-chain collection configuration from Tezos.
async function getTezCollection(
project: Project
): Promise<CollectionContractConfig | null>Parameters:
project- Project object withmintingContractAddressand ID
Returns:
{
status: "ON" | "OFF",
editions: number,
price: number // In XTZ (converted from mutez)
}Implementation Details:
- Creates read-only TezosToolkit via
getQuerierClientTez() - Loads contract at
project.mintingContractAddress - Detects version via
getTezCollectionKey() - V1: Queries
storage.projects.get(project.id) - V2: Queries
storage.collections.get(project.projectId) - Converts price from mutez to XTZ
getEthCollection()
Fetches on-chain collection configuration from Ethereum/Base.
async function getEthCollection(
project: Project
): Promise<CollectionContractConfig | null>Parameters:
project- Project object with blockchain info
Returns:
{
status: "ON" | "OFF",
editions: number,
price: number // In ETH
}Implementation Details:
- Selects RPC based on
project.blockchain - Creates Viem public client
- Reads contract state via
readContract() - Converts price from wei to ETH
Collection Update Functions
updateTezCollectionStatus()
Toggle minting on/off for Tezos collection.
async function updateTezCollectionStatus(
collection: Collection,
wallet: TezosToolkit,
newStatus: "ON" | "OFF"
): Promise<void>Contract Calls:
- V1:
contract.methodsObject.set_status(project_id, status) - V2:
contract.methodsObject.setStatus(collection_id, status)
updateTezCollectionPrice()
Update mint price for Tezos collection.
async function updateTezCollectionPrice(
collection: Collection,
wallet: TezosToolkit,
newPrice: number // In XTZ
): Promise<void>Contract Calls:
- V1:
contract.methodsObject.set_price(project_id, price_mutez) - V2:
contract.methodsObject.setPrice(collection_id, price_mutez)
Note: Price is converted to mutez: newPrice * 1_000_000
updateTezCollectionEditions()
Update max supply for Tezos collection.
async function updateTezCollectionEditions(
collection: Collection,
wallet: TezosToolkit,
newEditions: number
): Promise<void>Contract Calls:
- V1:
contract.methodsObject.set_total_editions(project_id, editions) - V2:
contract.methodsObject.setTotalEditions(collection_id, editions)
Fund Redemption Functions
getRedeemableTezFunds()
Calculate available funds for withdrawal.
async function getRedeemableTezFunds(
project: Project,
receiverAddress: string
): Promise<number> // Returns mutezCalculation:
- V1:
funds_collected * (creator_percentage / 10000) - V2:
(funds_collected * part_value / 10000) - funds_claimed
V2 Additional Logic:
- Queries
fundsClaimedBigMap for already withdrawn amounts - Subtracts claimed from total entitlement
getRedeemableEthFunds()
Calculate available funds for withdrawal from EVM chains.
async function getRedeemableEthFunds(
project: Project,
receiverAddress: string
): Promise<bigint> // Returns weiCollection Creation Functions
createTezosProjectVersion() (V1)
Create new collection on V1 Projects contract.
async function createTezosProjectVersion(
params: CollectionMetadataRequest,
collectionContractAddr: string,
tokenContractAddr: string,
wallet: TezosToolkit
): Promise<void>Parameters Built:
{
project: {
p_project_id: string,
p_project_name: string,
p_creator_address: string,
p_token_contract: string,
p_price: number, // mutez
p_editions: number,
p_mint_metadata: string, // IPFS URL
p_mode: MintMode,
p_status: Status,
p_free_minter: string,
p_description: string,
p_cover_uri: string,
p_publish_date: number, // Unix timestamp
p_generator_entrypoint: string,
p_width: number,
p_height: number
},
p_primary_sales_split: SplitConfig,
p_secondary_sales_split: SplitConfig,
p_allowlist: Spot[],
p_freelist: Spot[]
}createTezosCollectionVersion() (V2)
Create new collection on V2 Collections contract.
async function createTezosCollectionVersion(
params: CollectionMetadataRequest,
collectionContractAddr: string,
tokenContractAddr: string,
wallet: TezosToolkit
): Promise<void>Parameters Built:
{
collection: {
metadata: string,
tokenContractAddress: string,
freeMinter: string,
author: string,
mintMode: CollectionMintMode,
status: Status,
editions: number,
price: number // mutez
},
collectionConfig: {
enableBatchMint: boolean,
maxBatchMintAllowed: number,
startDate: number, // Unix timestamp
endDate: number | null
},
freelist: Spot[],
allowlist: Spot[],
royalties: Receiver[],
primarySalesReceivers: Receiver[]
}Minting Functions
handleContractsMintBatchs()
Execute batch mint operation.
async function handleContractsMintBatchs(
project: Project,
mintQuantity: number,
wallet: TezosToolkit | WalletClient,
owner?: string // Optional: mint to different address
): Promise<BatchOperation>V1 Minting (Projects):
// Creates individual calls per token
for (let i = 0; i < mintQuantity; i++) {
batch.withContractCall(
contract.methodsObject.mint_token({
p_id: project.id,
universal_id: uuidv4()
}),
{ amount: project.price, mutez: true }
)
}V2 Minting (Collections):
// Single call for all tokens
batch.withContractCall(
contract.methodsObject.mint({
quantityToMint: mintQuantity,
collectionId: Number(project.projectId),
owner: owner ?? userAddress
}),
{ amount: project.price * mintQuantity, mutez: true }
)Utility Functions
getTezCollectionKey()
Detect contract version by checking storage structure.
async function getTezCollectionKey(
contract: ContractAbstraction<Wallet>
): Promise<TezosCollectionKey | null>Returns:
"projects"- V1 contract"collections"- V2 contractnull- Unknown/invalid contract
getQuerierClientTez()
Create read-only Tezos client.
function getQuerierClientTez(): TezosToolkitUsage: For querying without wallet connection.
getRPCFromRegistry()
Get random RPC URL from configured registry.
function getRPCFromRegistry(chainId: ChainId): stringPurpose: Load balancing across RPC providers.
React Hooks
useCollectionContract()
Get writable contract instance.
function useCollectionContract(
blockchain: Blockchain,
contractAddress: string
): ContractAbstraction<Wallet> | ContractuseCollectionQuerierContract()
Get read-only contract instance.
function useCollectionQuerierContract(
blockchain: Blockchain,
contractAddress: string
): ContractAbstraction<ContractProvider> | ContractuseCollectionInfo()
Fetch collection metadata.
function useCollectionInfo(
project: Project
): SWRResponse<CollectionInfo>useCollectionConfig()
Fetch on-chain configuration.
function useCollectionConfig(
project: Project
): SWRResponse<CollectionContractConfig>useMintToken()
Mutation hook for minting.
function useMintToken(
project: Project
): {
trigger: (quantity: number) => Promise<void>,
isMutating: boolean
}usePublishCollection()
Mutation hook for collection creation.
function usePublishCollection(): {
trigger: (params: CreateProjectRequest) => Promise<void>,
isMutating: boolean
}Error Handling
Common Contract Errors
| Error Code | Description | Resolution |
|---|---|---|
NOT_ENOUGH_EDITIONS | Max supply reached | Collection is sold out |
NOT_ON_ALLOWLIST | Address not whitelisted | Check mint phase |
COLLECTION_PAUSED | Status is OFF | Wait for enablement |
WRONG_AMOUNT | Incorrect payment | Use exact price |
MAX_BATCH_EXCEEDED | Too many tokens | Reduce quantity |
MINT_NOT_STARTED | Before start date | Wait for start |
Transaction Failures
try {
const op = await contract.methodsObject.mint(params).send()
await op.confirmation(3)
} catch (error) {
if (error.message.includes('NOT_ENOUGH_EDITIONS')) {
// Handle sold out
}
// ... other error handling
}Environment Variables
# Tezos Contracts
NEXT_PUBLIC_PROJECT_CONTRACT_ADDRESS=KT1...
NEXT_PUBLIC_TOKEN_CONTRACT_ADDRESS=KT1...
# Ethereum Contracts
NEXT_PUBLIC_PROJECT_CONTRACT_ADDRESS_ETH=0x...
NEXT_PUBLIC_TOKEN_CONTRACT_ADDRESS_ETH=0x...
# Base Contracts
NEXT_PUBLIC_PROJECT_CONTRACT_ADDRESS_BASE=0x...
NEXT_PUBLIC_TOKEN_CONTRACT_ADDRESS_BASE=0x...
# Network
NEXT_PUBLIC_NETWORK=mainnet
NEXT_PUBLIC_NETWORKS_REGISTRY='{...}'Related Files
| File | Purpose |
|---|---|
clients/tezos-client.ts | Tezos domain resolution |
types/wallet.ts | Wallet types and chain IDs |
utils/mintStatus.ts | Mint eligibility checking |
utils/index.ts | Helper functions |
