Manage Assets (NFTs)
This guide provides a comprehensive walkthrough of managing the entire lifecycle of Non-Fungible Tokens (NFTs), also known as assets, using the OCAP Client. You will learn how to create new assets from scratch, update their properties, establish an asset factory for standardized minting, and acquire new assets from that factory.
Create a New Asset#
You can create a unique, standalone asset on the blockchain using the createAsset method. Each asset is assigned a unique on-chain address derived from its initial properties.
const { wallet } = getWallet(); // User's wallet object
async function createNewAsset() {
try {
const [hash, address] = await client.createAsset({
moniker: 'My Unique Digital Artwork',
data: {
typeUrl: 'json',
value: {
description: 'A one-of-a-kind piece created by Artist X.',
imageUrl: 'https://example.com/path/to/image.png',
},
},
readonly: true,
transferrable: true,
wallet: wallet,
});
console.log(`Asset creation transaction sent: ${hash}`);
console.log(`New asset address: ${address}`);
return address;
} catch (error) {
console.error('Error creating asset:', error);
}
}See all 2 lines
Parameters#
Returns#
A Promise that resolves to an array containing the transaction hash and the new asset's on-chain address.
Update an Existing Asset#
If an asset was created with readonly: false, you can modify its moniker and data fields using the updateAsset method. The asset is identified by its unique address.
const { wallet } = getWallet(); // User's wallet object
const assetAddress = 'z362...'; // Address of the asset to update
async function updateExistingAsset() {
try {
const hash = await client.updateAsset({
address: assetAddress,
moniker: 'My Updated Digital Artwork',
data: {
typeUrl: 'json',
value: {
description: 'An updated description for my unique piece.',
imageUrl: 'https://example.com/path/to/new_image.png',
},
},
wallet: wallet,
});
console.log(`Asset update transaction sent: ${hash}`);
} catch (error) {
console.error('Error updating asset:', error);
}
}
updateExistingAsset();Parameters#
Returns#
A Promise that resolves to the transaction hash.
Create an Asset Factory#
An Asset Factory is a template for creating multiple, similar assets. It defines the structure, rules, and logic for minting new assets, which is more efficient than creating each one individually. This is ideal for use cases like issuing event tickets, certificates, or collectibles.
const { wallet } = getWallet(); // Factory owner's wallet
const factoryDefinition = {
name: 'Conference Ticket Factory',
description: 'Mints tickets for the 2024 Tech Conference.',
limit: 1000, // Max 1000 tickets can be minted
input: {
// Defines what data is required to mint an asset
type: 'object',
properties: {
attendeeName: { type: 'string' },
ticketType: { type: 'string', enum: ['General', 'VIP'] },
},
},
output: {
// Defines the structure of the minted asset
moniker: 'Ticket for {{attendeeName}}',
description: '{{ticketType}} admission for the 2024 Tech Conference.',
transferrable: false, // Tickets are non-transferrable
},
hooks: [],
};
async function createFactory() {
try {See all 13 lines
Parameters#
Returns#
A Promise that resolves to an array containing the transaction hash and the new factory's on-chain address.
Acquire an Asset from a Factory#
Acquiring an asset from a factory is a two-step process. First, you prepare the minting data, which allows you to preview the asset that will be created. Second, you submit the transaction to the blockchain to officially acquire the asset.
This separation is useful because it allows an application to show a user what they are about to receive before they sign and submit the final transaction.
Step 1: Prepare the Asset Data#
The preMintAsset method takes the factory address and user-provided inputs to generate the final asset data. This happens off-chain and does not require a transaction.
const factoryAddress = 'z2...'; // Address of the factory created previously
const { wallet: issuerWallet } = getIssuerWallet(); // The factory owner or a trusted issuer
const { wallet: userWallet } = getUserWallet(); // The user who will own the new asset
async function prepareAssetForMinting() {
try {
const mintingData = await client.preMintAsset({
factory: factoryAddress,
inputs: {
attendeeName: 'John Doe',
ticketType: 'VIP',
},
owner: userWallet.address,
wallet: issuerWallet,
});
console.log('Prepared asset data for minting:', mintingData);
return mintingData;
} catch (error) {
console.error('Error preparing asset:', error);
}
}Step 2: Send the Transaction#
Once the minting data is prepared, the user (the future asset owner) signs and sends the acquireAsset transaction. The itx object from preMintAsset is used as the payload.
async function acquireNewAsset() {
// First, get the minting data from Step 1
const itx = await prepareAssetForMinting();
if (!itx) return;
try {
const hash = await client.acquireAsset({
itx: itx,
wallet: userWallet, // The user's wallet signs the transaction
});
console.log(`Asset acquisition transaction sent: ${hash}`);
console.log(`New asset will be available at address: ${itx.address}`);
} catch (error) {
console.error('Error acquiring asset:', error);
}
}
acquireNewAsset();Parameters for acquireAsset#
Returns#
A Promise that resolves to the transaction hash for the acquireAsset operation.
Mint an Asset from a Factory#
In addition to the user-led acquireAsset flow, an authorized issuer (such as the factory owner or a trusted issuer) can mint an asset and send it directly to a user's account. This process also uses preMintAsset to prepare the data, but the final transaction is mintAsset, signed by the issuer.
This flow is useful for scenarios like airdrops, awarding certificates, or any case where the receiving user does not need to initiate the final transaction.
Step 1: Prepare the Asset Data#
This step is identical to the acquisition flow. The issuer calls preMintAsset to generate the transaction payload (itx) off-chain.
const factoryAddress = 'z2...'; // Address of the factory
const { wallet: issuerWallet } = getIssuerWallet(); // The factory owner or a trusted issuer
const userAddress = 'z1...'; // The address of the user who will receive the asset
async function prepareAssetForMinting() {
try {
const mintingData = await client.preMintAsset({
factory: factoryAddress,
inputs: {
attendeeName: 'Jane Smith',
ticketType: 'General',
},
owner: userAddress,
wallet: issuerWallet, // Issuer's wallet is used here
});
console.log('Prepared asset data for minting:', mintingData);
return mintingData;
} catch (error) {
console.error('Error preparing asset:', error);
}
}Step 2: Send the Mint Transaction#
The issuer uses the prepared itx object to call mintAsset. The transaction is signed with the issuer's wallet, and the newly created asset is assigned to the owner specified in the previous step.
async function mintNewAsset() {
// First, get the minting data from Step 1
const itx = await prepareAssetForMinting();
if (!itx) return;
try {
// The issuer's wallet signs the transaction
const hash = await client.mintAsset({
itx: itx,
wallet: issuerWallet,
});
console.log(`Asset minting transaction sent: ${hash}`);
console.log(`New asset for ${userAddress} will be available at address: ${itx.address}`);
} catch (error) {
console.error('Error minting asset:', error);
}
}
mintNewAsset();Parameters for mintAsset#
Returns#
A Promise that resolves to the transaction hash for the mintAsset operation.