> For the complete documentation index, see [llms.txt](https://docs.heyhal.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.heyhal.xyz/api-documentation/token-minted.md).

# Token Minted

**Endpoint:** <mark style="color:yellow;">`POST /api/v1/coin/minted`</mark>

### Description

This endpoint updates the token's status after successful minting and broadcasts the status change through WebSocket. It's typically called after a mint transaction has been confirmed on the blockchain.

### Authentication

Required: Yes

Type: Bearer Token (JWT)

### Request

#### Headers

#### Content-Type: application/json

#### Authorization: Bearer \<your\_jwt\_token>

#### Body Parameters

| Parameter | Type   | Required | Description                    |
| --------- | ------ | -------- | ------------------------------ |
| token     | string | Yes      | The mint address of the token  |
| tx        | string | Yes      | The transaction signature/hash |

Example Request:

{

&#x20; "token": "TokenMintAddress123...",

&#x20; "tx": "TransactionSignature456..."

}

### Response

#### Success Response

Status Code: 200 OK

Content-Type: application/json

{

&#x20; "success": true

}

#### Error Response

Status Code: 500 Internal Server Error

{

&#x20; "error": "An internal error occurred. Please try again later."

}

### Example Usage

### // Basic implementation

### async function confirmTokenMinting(

### &#x20; tokenMintAddress: string,&#x20;

### &#x20; transactionSignature: string

### ) {

### &#x20; try {

### &#x20;   const response = await fetch('<https://api.heyhal.xyz/api/v1/coin/minted>', {

### &#x20;     method: 'POST',

### &#x20;     headers: {

### &#x20;       'Content-Type': 'application/json',

### &#x20;       'Authorization': \`Bearer ${localStorage.getItem('auth\_token')}\`

### &#x20;     },

### &#x20;     body: JSON.stringify({

### &#x20;       token: tokenMintAddress,

### &#x20;       tx: transactionSignature

### &#x20;     })

### &#x20;   });

### &#x20;   if (!response.ok) {

### &#x20;     throw new Error(\`HTTP error! status: ${response.status}\`);

### &#x20;   }

### &#x20;   const result = await response.json();

### &#x20;   return result.success;

### &#x20; } catch (error) {

### &#x20;   console.error('Error confirming token minting:', error);

### &#x20;   throw error;

### &#x20; }

### }

### // Complete minting flow manager

### class TokenMintingManager {

### &#x20; private wsConnection: WebSocket | null = null;

### &#x20;&#x20;

### &#x20; constructor(private readonly wsUrl: string) {

### &#x20;   this.initializeWebSocket();

### &#x20; }

### &#x20;&#x20;

### &#x20; private initializeWebSocket() {

### &#x20;   this.wsConnection = new WebSocket(this.wsUrl);

### &#x20;   this.wsConnection.onmessage = (event) => {

### &#x20;     const data = JSON.parse(event.data);

### &#x20;     if (data.type === 'TOKEN\_MINTED') {

### &#x20;       this.handleMintingComplete(data.token, data.status);

### &#x20;     }

### &#x20;   };

### &#x20; }

### &#x20;&#x20;

### &#x20; async confirmMinting(

### &#x20;   tokenMintAddress: string,&#x20;

### &#x20;   transactionSignature: string

### &#x20; ) {

### &#x20;   try {

### &#x20;     await confirmTokenMinting(tokenMintAddress, transactionSignature);

### &#x20;    &#x20;

### &#x20;     // Subscribe to WebSocket updates for this token

### &#x20;     this.wsConnection?.send(JSON.stringify({

### &#x20;       type: 'SUBSCRIBE\_TOKEN',

### &#x20;       token: tokenMintAddress

### &#x20;     }));

### &#x20;    &#x20;

### &#x20;   } catch (error) {

### &#x20;     console.error('Minting confirmation failed:', error);

### &#x20;     throw error;

### &#x20;   }

### &#x20; }

### &#x20;&#x20;

### &#x20; private handleMintingComplete(token: string, status: string) {

### &#x20;   // Implement your success handling logic here

### &#x20;   console.log(\`Token ${token} minting completed with status: ${status}\`);

### &#x20; }

### &#x20;&#x20;

### &#x20; cleanup() {

### &#x20;   this.wsConnection?.close();

### &#x20; }

### }

### Implementation Notes

Status Updates

// Example of status tracking

class TokenStatusTracker {

&#x20; private statusListeners: Map\<string, ((status: string) => void)\[]> = new Map();

&#x20;&#x20;

&#x20; addStatusListener(

&#x20;   tokenMintAddress: string,&#x20;

&#x20;   listener: (status: string) => void

&#x20; ) {

&#x20;   const listeners = this.statusListeners.get(tokenMintAddress) || \[];

&#x20;   listeners.push(listener);

&#x20;   this.statusListeners.set(tokenMintAddress, listeners);

&#x20; }

&#x20;&#x20;

&#x20; removeStatusListener(

&#x20;   tokenMintAddress: string,&#x20;

&#x20;   listener: (status: string) => void

&#x20; ) {

&#x20;   const listeners = this.statusListeners.get(tokenMintAddress) || \[];

&#x20;   const index = listeners.indexOf(listener);

&#x20;   if (index > -1) {

&#x20;     listeners.splice(index, 1);

&#x20;     this.statusListeners.set(tokenMintAddress, listeners);

&#x20;   }

&#x20; }

&#x20;&#x20;

&#x20; notifyStatusChange(tokenMintAddress: string, status: string) {

&#x20;   const listeners = this.statusListeners.get(tokenMintAddress) || \[];

&#x20;   listeners.forEach(listener => listener(status));

&#x20; }

}

WebSocket Integration

// WebSocket event handler

class TokenMintedWebSocket {

&#x20; private ws: WebSocket;

&#x20; private reconnectAttempts = 0;

&#x20; private readonly MAX\_RECONNECT\_ATTEMPTS = 5;

&#x20;&#x20;

&#x20; constructor(private readonly url: string) {

&#x20;   this.ws = this.connect();

&#x20; }

&#x20;&#x20;

&#x20; private connect(): WebSocket {

&#x20;   const ws = new WebSocket(this.url);

&#x20;  &#x20;

&#x20;   ws.onopen = () => {

&#x20;     console.log('WebSocket connected');

&#x20;     this.reconnectAttempts = 0;

&#x20;   };

&#x20;  &#x20;

&#x20;   ws.onclose = () => {

&#x20;     if (this.reconnectAttempts < this.MAX\_RECONNECT\_ATTEMPTS) {

&#x20;       this.reconnectAttempts++;

&#x20;       setTimeout(() => {

&#x20;         this.ws = this.connect();

&#x20;       }, 1000 \* this.reconnectAttempts);

&#x20;     }

&#x20;   };

&#x20;  &#x20;

&#x20;   ws.onerror = (error) => {

&#x20;     console.error('WebSocket error:', error);

&#x20;   };

&#x20;  &#x20;

&#x20;   return ws;

&#x20; }

&#x20;&#x20;

&#x20; subscribeToToken(tokenMintAddress: string) {

&#x20;   if (this.ws.readyState === WebSocket.OPEN) {

&#x20;     this.ws.send(JSON.stringify({

&#x20;       type: 'SUBSCRIBE\_TOKEN',

&#x20;       token: tokenMintAddress

&#x20;     }));

&#x20;   }

&#x20; }

&#x20;&#x20;

&#x20; close() {

&#x20;   this.ws.close();

&#x20; }

}

Transaction Verification

// Verify transaction before confirming

async function verifyMintTransaction(

&#x20; connection: Connection,

&#x20; signature: string

): Promise\<boolean> {

&#x20; try {

&#x20;   const status = await connection.getSignatureStatus(signature);

&#x20;  &#x20;

&#x20;   if (!status.value) {

&#x20;     throw new Error('Transaction not found');

&#x20;   }

&#x20;  &#x20;

&#x20;   if (status.value.err) {

&#x20;     throw new Error('Transaction failed');

&#x20;   }

&#x20;  &#x20;

&#x20;   return status.value.confirmationStatus === 'finalized';

&#x20; } catch (error) {

&#x20;   console.error('Transaction verification failed:', error);

&#x20;   return false;

&#x20; }

}

### Best Practices

1\. Error Recovery

async function confirmMintingWithRetry(

&#x20; tokenMintAddress: string,

&#x20; transactionSignature: string,

&#x20; maxRetries = 3

): Promise\<boolean> {

&#x20; for (let attempt = 1; attempt <= maxRetries; attempt++) {

&#x20;   try {

&#x20;     const result = await confirmTokenMinting(

&#x20;       tokenMintAddress,

&#x20;       transactionSignature

&#x20;     );

&#x20;     return result;

&#x20;   } catch (error) {

&#x20;     if (attempt === maxRetries) throw error;

&#x20;     await new Promise(resolve =>&#x20;

&#x20;       setTimeout(resolve, 1000 \* attempt)

&#x20;     );

&#x20;   }

&#x20; }

&#x20; return false;

}

Event Handling

interface MintingEvent {

&#x20; type: 'TOKEN\_MINTED';

&#x20; token: string;

&#x20; status: string;

&#x20; timestamp: number;

}

class MintingEventEmitter {

&#x20; private listeners: ((event: MintingEvent) => void)\[] = \[];

&#x20;&#x20;

&#x20; addEventListener(listener: (event: MintingEvent) => void) {

&#x20;   this.listeners.push(listener);

&#x20; }

&#x20;&#x20;

&#x20; removeEventListener(listener: (event: MintingEvent) => void) {

&#x20;   const index = this.listeners.indexOf(listener);

&#x20;   if (index > -1) {

&#x20;     this.listeners.splice(index, 1);

&#x20;   }

&#x20; }

&#x20;&#x20;

&#x20; emit(event: MintingEvent) {

&#x20;   this.listeners.forEach(listener => listener(event));

&#x20; }

}

<br>
