> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oumla.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Tokenization Workflow

> Complete guide to creating collections, minting tokens, and managing NFTs

export const supportEmail = 'support@oumla.com';

This guide walks you through the complete tokenization workflow using the Oumla SDK, from creating collections to minting and burning tokens.

<Note>
  **Two Ways to Use Oumla**: This guide uses the TypeScript SDK. You can also accomplish the same tasks using direct REST API calls - see the [API Reference](/api-reference/introduction) for endpoint details.
</Note>

## Overview

The tokenization workflow involves several steps:

1. **Create Collection** - Deploy an NFT collection contract (ERC-721 or ERC-1155)
2. **Check Status** - Monitor the async deployment workflow
3. **Mint Tokens** - Mint NFTs to specific addresses
4. **View Tokens** - Query tokens in your collection
5. **Burn Tokens** - Remove tokens from circulation (optional)

<Tip>
  Collection creation and minting use **async workflows** for async processing. You'll need to check workflow status to know when operations complete.
</Tip>

## Prerequisites

Before starting, ensure you have:

* An initialized SDK client
* A profile created
* An address generated (for contract deployment)
* Your client share (for signing operations)

## Step 1: Create a Collection

Creating a collection deploys a new NFT contract. This is an **async operation** that returns a workflow ID.

```javascript theme={null}
import { OumlaSdkApiClient, OumlaSdkApiEnvironment } from '@oumla/sdk';

const client = new OumlaSdkApiClient({
  environment: OumlaSdkApiEnvironment.Sandbox,
  apiKey: 'your-api-key-here'
});

// Create an ERC-721 collection (NON_FUNGIBLE_TOKEN)
const collection = await client.tokenization.createCollection({
  addressId: 'your-address-id',
  type: 'NON_FUNGIBLE_TOKEN',
  clientShare: 'your-client-share',
  network: 'ETHEREUM',
  displayName: 'My NFT Collection',
  useGasless: false,
  fee: '0',
  feeLevel: 'standard',
  description: 'Optional collection description',
  createParams: {
    initializeParams: [
      { name: '_name', type: 'string', value: 'My Collection' },
      { name: '_symbol', type: 'string', value: 'MYC' },
      { name: 'defaultAdmin', type: 'address', value: '0x1111111111111111111111111111111111111111' },
      { name: 'minter', type: 'address', value: '0x2222222222222222222222222222222222222222' },
      { name: 'pauser', type: 'address', value: '0x3333333333333333333333333333333333333333' }
    ]
  }
});

console.log('Workflow ID:', collection.data.workflowResult.workflowId);
```

<Accordion title="ERC-1155 Collection Example">
  ```javascript theme={null}
  // Create an ERC-1155 collection (SEMI_FUNGIBLE_TOKEN)
  const collection = await client.tokenization.createCollection({
    addressId: 'your-address-id',
    type: 'SEMI_FUNGIBLE_TOKEN',
    clientShare: 'your-client-share',
    network: 'ETHEREUM',
    displayName: 'My Multi-Token Collection',
    createParams: {
      initializeParams: [
        { name: '_name', type: 'string', value: 'My Multi-Token Collection' },
        { name: '_symbol', type: 'string', value: 'MMTC' },
        { name: 'defaultAdmin', type: 'address', value: '0x1111111111111111111111111111111111111111' },
        { name: 'minter', type: 'address', value: '0x2222222222222222222222222222222222222222' },
        { name: 'pauser', type: 'address', value: '0x3333333333333333333333333333333333333333' }
      ]
    }
  });
  ```
</Accordion>

### Collection Types

* **NON\_FUNGIBLE\_TOKEN** (ERC-721): Non-fungible tokens (NFTs) - each token is unique
* **SEMI\_FUNGIBLE\_TOKEN** (ERC-1155): Multi-token standard - supports both fungible and non-fungible tokens

<Note>
  Use `NON_FUNGIBLE_TOKEN` for ERC-721 collections and `SEMI_FUNGIBLE_TOKEN` for ERC-1155 collections. These are the actual API values, not `ERC721` or `ERC1155`.
</Note>

## Step 2: Check Workflow Status

Collection creation is async. Check the workflow status to know when deployment completes:

```javascript theme={null}
// Check workflow status
const status = await client.workflows.getWorkflowStatus(collection.data.workflowResult.workflowId);

console.log('Status:', status.data.status); // COMPLETED, RUNNING, FAILED
console.log('Result:', status.data.result);

if (status.data.status === 'COMPLETED') {
  console.log('Collection deployed at:', status.data.result.contractAddress);
} else if (status.data.status === 'FAILED') {
  console.error('Deployment failed:', status.data.error);
}
```

### Workflow Status Values

* **RUNNING**: Operation in progress
* **COMPLETED**: Operation successful
* **FAILED**: Operation failed (check error details)
* **CANCELLED**: Operation was cancelled

<Tip>
  Poll the workflow status endpoint every few seconds until status is COMPLETED or FAILED. Consider implementing exponential backoff for production applications.
</Tip>

## Step 3: Get Collection Details

Once deployment completes, retrieve collection details:

```javascript theme={null}
const collectionDetails = await client.tokenization.getCollectionById(
  collection.data.workflowResult.operationId
);

console.log('Collection:', collectionDetails.data);
console.log('Contract Address:', collectionDetails.data.contractAddress);
console.log('Network:', collectionDetails.data.network);
```

## Step 4: Mint Tokens

Mint tokens to specific addresses. For ERC-721, mint unique tokens. For ERC-1155, specify token ID and amount.

### Minting ERC-721 Tokens

```javascript theme={null}
const mintResult = await client.tokenization.mintToken(collection.data.workflowResult.operationId, {
  addressId: 'your-address-id',
  clientShare: 'your-client-share',
  to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', // Recipient address
  tokenId: '0', // Sequential token ID (start from 0)
  metadata: {
    name: 'My First NFT',
    description: 'This is my first NFT',
    image: 'https://example.com/image.png',
    attributes: [
      {
        trait_type: 'Color',
        value: 'Blue'
      }
    ]
  }
});

console.log('Mint Workflow ID:', mintResult.data.workflowResult.workflowId);
```

### Minting ERC-1155 Tokens

```javascript theme={null}
const mintResult = await client.tokenization.mintToken(collection.data.workflowResult.operationId, {
  addressId: 'your-address-id',
  clientShare: 'your-client-share',
  to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
  tokenId: '1', // Token type ID
  amount: '100', // Amount to mint (for ERC-1155)
  metadataURI: 'https://api.example.com/metadata/1'
});

console.log('Mint Workflow ID:', mintResult.data.workflowResult.workflowId);
```

<Warning>
  **Token ID Sequencing**: For ERC-721 collections, token IDs must be sequential starting from 0. The system validates this to prevent conflicts.
</Warning>

## Step 5: Check Mint Status

Minting is also async. Check the workflow status:

```javascript theme={null}
const mintStatus = await client.workflows.getWorkflowStatus(mintResult.data.workflowResult.workflowId);

if (mintStatus.data.status === 'COMPLETED') {
  console.log('Token minted successfully!');
  console.log('Transaction Hash:', mintStatus.data.result.transactionHash);
}
```

## Step 6: View Collection Tokens

List all tokens in your collection:

```javascript theme={null}
const tokens = await client.tokenization.getCollectionTokens({
  id: collection.data.workflowResult.operationId,
  skip: 0,
  take: 25
});

console.log('Total tokens:', tokens.data.tokens.length);
tokens.data.tokens.forEach(token => {
  console.log(`Token ${token.tokenId}:`, token);
});
```

## Step 7: Get Token Details

Get details for a specific token:

```javascript theme={null}
const tokenDetails = await client.tokenization.getCollectionTokenDetails(
  collection.data.workflowResult.operationId,
  '0'
);

console.log('Token Details:', tokenDetails.data);
console.log('Owner:', tokenDetails.data.owner);
console.log('Metadata:', tokenDetails.data.metadata);
```

## Step 8: Burn Tokens (Optional)

Burn tokens to remove them from circulation:

```javascript theme={null}
const burnResult = await client.tokenization.burnToken('collection-id', {
  addressId: 'your-address-id',
  clientShare: 'your-client-share',
  tokenId: '0' // Token ID to burn
});

console.log('Burn Workflow ID:', burnResult.data.workflowResult.workflowId);

// Check burn status
const burnStatus = await client.workflows.getWorkflowStatus(burnResult.data.workflowResult.workflowId);
```

## Complete Example

Here's a complete example that ties everything together:

```javascript theme={null}
import { OumlaSdkApiClient, OumlaSdkApiEnvironment } from '@oumla/sdk';

const client = new OumlaSdkApiClient({
  environment: OumlaSdkApiEnvironment.Sandbox,
  apiKey: process.env.OUMLA_API_KEY
});

async function tokenizationWorkflow() {
  try {
    // Step 1: Create collection
    const collection = await client.tokenization.createCollection({
      addressId: process.env.ADDRESS_ID,
      type: 'NON_FUNGIBLE_TOKEN', // Use 'NON_FUNGIBLE_TOKEN' for ERC-721, 'SEMI_FUNGIBLE_TOKEN' for ERC-1155
      clientShare: process.env.CLIENT_SHARE,
      network: 'ETHEREUM',
      displayName: 'My NFT Collection',
      createParams: {
        initializeParams: [
          { name: '_name', type: 'string', value: 'My Collection' },
          { name: '_symbol', type: 'string', value: 'MYC' },
          { name: 'defaultAdmin', type: 'address', value: process.env.ADMIN_ADDRESS },
          { name: 'minter', type: 'address', value: process.env.MINTER_ADDRESS },
          { name: 'pauser', type: 'address', value: process.env.PAUSER_ADDRESS }
        ]
      }
    });

    console.log('Collection creation started. Workflow ID:', collection.data.workflowResult.workflowId);

    // Step 2: Wait for collection deployment
    let collectionStatus;
    do {
      await new Promise(resolve => setTimeout(resolve, 3000)); // Wait 3 seconds
      collectionStatus = await client.workflows.getWorkflowStatus(collection.data.workflowResult.workflowId);
      console.log('Collection status:', collectionStatus.data.status);
    } while (collectionStatus.data.status === 'RUNNING');

    if (collectionStatus.data.status === 'FAILED') {
      throw new Error('Collection deployment failed: ' + collectionStatus.data.error);
    }

    const contractAddress = collectionStatus.data.result.contractAddress;
    console.log('Collection deployed at:', contractAddress);

    // Step 3: Get collection ID (operationId from the createCollection workflow)
    const collectionId = collection.data.workflowResult.operationId;
    
    // Step 4: Mint a token
    const mintResult = await client.tokenization.mintToken(collectionId, {
      addressId: process.env.ADDRESS_ID,
      clientShare: process.env.CLIENT_SHARE,
      to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
      metadata: {
        name: 'My First NFT',
        description: 'This is my first NFT',
        image: 'https://example.com/image.png'
      }
    });

    console.log('Minting started. Workflow ID:', mintResult.data.workflowResult.workflowId);

    // Step 5: Wait for mint to complete
    let mintStatus;
    do {
      await new Promise(resolve => setTimeout(resolve, 3000));
      mintStatus = await client.workflows.getWorkflowStatus(mintResult.data.workflowResult.workflowId);
      console.log('Mint status:', mintStatus.data.status);
    } while (mintStatus.data.status === 'RUNNING');

    if (mintStatus.data.status === 'COMPLETED') {
      console.log('Token minted successfully!');
      console.log('Transaction Hash:', mintStatus.data.result.transactionHash);
    }

    // Step 6: View tokens
    const tokens = await client.tokenization.getCollectionTokens({
      id: collectionId,
      skip: 0,
      take: 10
    });

    console.log('Collection tokens:', tokens.data.tokens);

  } catch (error) {
    console.error('Error:', error);
  }
}

tokenizationWorkflow();
```

## Workflow Status Values

When checking workflow status, you'll receive one of these values:

* **RUNNING**: Operation is in progress
* **COMPLETED**: Operation completed successfully
* **FAILED**: Operation failed (check `error` field for details)
* **CANCELLED**: Operation was cancelled

## Common Issues

### Collection Deployment Fails

**Causes:**

* Insufficient gas balance
* Invalid constructor parameters
* Network connectivity issues

**Solutions:**

* Ensure address has sufficient ETH for gas
* Verify constructor parameters match contract requirements
* Check network status and retry

### Minting Fails

**Causes:**

* Invalid token ID (not sequential for ERC-721)
* Collection not deployed yet
* Insufficient gas balance

**Solutions:**

* Ensure token IDs are sequential starting from 0
* Wait for collection deployment to complete
* Verify sufficient gas balance

### Workflow Status Stuck

**Causes:**

* Network congestion
* Transaction pending in mempool

**Solutions:**

* Wait longer (some operations take time)
* Check blockchain explorer for transaction status
* Contact support if stuck for extended period

## Best Practices

1. **Always check workflow status** before proceeding to next steps
2. **Handle errors gracefully** - workflows can fail
3. **Use sequential token IDs** for ERC-721 collections
4. **Store workflow IDs** for tracking and debugging
5. **Implement retry logic** for transient failures
6. **Monitor gas prices** for cost optimization
7. **Validate addresses** before minting tokens

## Next Steps

* Learn about [Contract Deployment Workflow](/guides/workflows/contract-deployment)
* Explore [Withdrawal Workflow](/guides/workflows/withdrawal)
* Review [Error Reference](/guides/error-reference) for troubleshooting
