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


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.heyhal.xyz/api-documentation/token-minted.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
