# 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.

```javascript icon=logos:javascript
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);
  }
}

createNewAsset();
```

### Parameters

<x-field-group>
  <x-field data-name="moniker" data-type="string" data-required="true" data-desc="The name of the asset."></x-field>
  <x-field data-name="parent" data-type="string" data-default="''" data-required="false" data-desc="The address of a parent asset, if any."></x-field>
  <x-field data-name="data" data-type="object" data-required="true" data-desc="The data payload for the asset, which must include a typeUrl and value."></x-field>
  <x-field data-name="readonly" data-type="boolean" data-default="false" data-required="false" data-desc="If true, the asset cannot be updated after creation."></x-field>
  <x-field data-name="transferrable" data-type="boolean" data-default="true" data-required="false" data-desc="If true, the asset can be transferred to another account."></x-field>
  <x-field data-name="ttl" data-type="number" data-default="0" data-required="false" data-desc="Time-to-live in seconds after the asset's first consumption."></x-field>
  <x-field data-name="display" data-type="object" data-required="false" data-desc="Object containing display information for the asset."></x-field>
  <x-field data-name="endpoint" data-type="object" data-required="false" data-desc="Object containing endpoint details for the asset."></x-field>
  <x-field data-name="tags" data-type="string[]" data-default="[]" data-required="false" data-desc="An array of strings to categorize the asset."></x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="The wallet object of the asset's initial owner."></x-field>
  <x-field data-name="delegator" data-type="string" data-default="''" data-required="false" data-desc="The address of the account that authorized this transaction via delegation."></x-field>
</x-field-group>

### Returns

A `Promise` that resolves to an array containing the transaction hash and the new asset's on-chain address.

<x-field data-name="response" data-type="Promise<[string, string]>" data-desc="[transactionHash, assetAddress]"></x-field>

---


## 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.

```javascript icon=logos:javascript
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

<x-field-group>
  <x-field data-name="address" data-type="string" data-required="true" data-desc="The on-chain address of the asset to update."></x-field>
  <x-field data-name="moniker" data-type="string" data-required="true" data-desc="The new name for the asset."></x-field>
  <x-field data-name="data" data-type="object" data-required="true" data-desc="The updated data payload for the asset."></x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="The wallet object of the current asset owner."></x-field>
</x-field-group>

### Returns

A `Promise` that resolves to the transaction hash.

<x-field data-name="response" data-type="Promise<string>" data-desc="transactionHash"></x-field>

---


## 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.

```javascript icon=logos:javascript
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 {
    const [hash, factoryAddress] = await client.createAssetFactory({
      factory: factoryDefinition,
      wallet: wallet,
    });

    console.log(`Factory creation transaction sent: ${hash}`);
    console.log(`New factory address: ${factoryAddress}`);
  } catch (error) {
    console.error('Error creating asset factory:', error);
  }
}

createFactory();
```

### Parameters

<x-field-group>
  <x-field data-name="factory" data-type="object" data-required="true" data-desc="An object defining the factory's properties and minting logic.">
    <x-field data-name="name" data-type="string" data-required="true" data-desc="Name of the factory."></x-field>
    <x-field data-name="description" data-type="string" data-required="true" data-desc="Description of the factory's purpose."></x-field>
    <x-field data-name="limit" data-type="number" data-default="0" data-required="false" data-desc="The maximum number of assets that can be minted from this factory. 0 means unlimited."></x-field>
    <x-field data-name="trustedIssuers" data-type="string[]" data-required="false" data-desc="A list of account addresses authorized to mint from this factory."></x-field>
    <x-field data-name="input" data-type="object" data-required="true" data-desc="Defines the required input data for minting an asset."></x-field>
    <x-field data-name="output" data-type="object" data-required="true" data-desc="Defines the structure and properties of the asset that will be minted."></x-field>
    <x-field data-name="hooks" data-type="object[]" data-required="false" data-desc="A list of hooks to execute during the minting process."></x-field>
    <x-field data-name="data" data-type="object" data-required="false" data-desc="Additional arbitrary data to store with the factory."></x-field>
  </x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="The wallet object of the factory's owner."></x-field>
</x-field-group>

### Returns

A `Promise` that resolves to an array containing the transaction hash and the new factory's on-chain address.

<x-field data-name="response" data-type="Promise<[string, string]>" data-desc="[transactionHash, factoryAddress]"></x-field>

---


## 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.

```javascript icon=logos:javascript
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.

```javascript icon=logos:javascript
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`

<x-field-group>
  <x-field data-name="itx" data-type="object" data-required="true" data-desc="The inner transaction object returned from the `preMintAsset` method."></x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="The wallet of the user who is acquiring the asset."></x-field>
  <x-field data-name="delegator" data-type="string" data-default="''" data-required="false" data-desc="The address of the account that authorized this transaction via delegation."></x-field>
</x-field-group>

### Returns

A `Promise` that resolves to the transaction hash for the `acquireAsset` operation.

<x-field data-name="response" data-type="Promise<string>" data-desc="transactionHash"></x-field>

---


## 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.

```javascript icon=logos:javascript
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.

```javascript icon=logos:javascript
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`

<x-field-group>
  <x-field data-name="itx" data-type="object" data-required="true" data-desc="The inner transaction object returned from the `preMintAsset` method."></x-field>
  <x-field data-name="wallet" data-type="WalletObject" data-required="true" data-desc="The wallet of the issuer who is minting the asset."></x-field>
</x-field-group>

### Returns

A `Promise` that resolves to the transaction hash for the `mintAsset` operation.

<x-field data-name="response" data-type="Promise<string>" data-desc="transactionHash"></x-field>
