![npm](https://img.shields.io/npm/v/tonb-merchant-api-client) ![npm](https://img.shields.io/npm/dt/tonb-merchant-api-client)


# Merchant API client

Merchant API client is a library to interact with Merchant API.

## Usage

To make client work:

1. Create Provider that will handle all HTTP job.

    ```javascript
        const provider = new HttpProvider({
            apiKey: 'EXAMPLE-API-KEY',
            url: 'https://merchant-app-api2.tonb.io/',
            merchantId: 11,
        });
    ```

    The provider may accept one of the options:
    1. API key + Base URL + Merchant ID
    2. Axios Client with the data inside.

2. Pass the Provider to the InvoiceManager

   ```javascript
        const manager = new InvoiceManager(provider);
    ```

    InvoiceManager manages all work with invoices and is a part of a Merchant API client.

3. Create client

    ```javascript
        const client = new MerchantAPIClient(manager);
    ```

The invoice management may be performed through *client.invoiceManager.*

```javascript
    const stats = await client.invoiceManager.stats();
```

### InvoiceManager

InvoiceManager implements 4 methods to interact with BackEnd and 1 to handle webhooks:

```javascript
    // Creates new Invoice
    create(data: CreateInvoiceData): Promise<DataContainer<Invoice>>

    // Cancels existing Invoice
    cancel(invoiceId: InvoiceID): Promise<DataContainer<Invoice>>

    // Retrieves Invoice information
    info(invoiceId: InvoiceID): Promise<DataContainer<Invoice>>

    // Retrieves merchant statistics
    stats(): Promise<DataContainer<InvoiceStats>> 

    // Process WebHook data
    processUpdate(update: InvoiceUpdate): DataContainer<Omit<Invoice, 'id'>> 
```

The InvoiceManager returns all entities inside the container *DataContainer\<R\>*.

```javascript
    type DataContainer<R> = {
        data: R | null;
        isValid: boolean;
        error?: unknown;
    };
```

Before accessing the data, you should check whether the data is valid:

```javascript
    if (stats.isValid) {...}
```

Thereby, library does not throw errors.
In case of errors, ex.during HTTP interactions, the library handles all errors,
sets the *isValid* flag to *false*. Additionally, it may include Error inside DataContainer in the *error* field.

The Invoice contains the following data:

```javascript
    type Invoice = {
        domain?: string;
        id: InvoiceID;
        code?: string;
        webhook?: string;
        amount: bigint;
        order_id?: bigint;
        status?: InvoiceEnumStatus;
        transaction?: unknown; // any json object
        createdAt?: number; // UTC time
        updatedAt?: number; // UTC time
        user_from_id?: bigint;
        user_to_id?: bigint;
        wallet_from_id?: number;
        wallet_to_id?: number;
        user_from?: {
            first_name: string;
            last_name?: string;
            photo_url?: string;
        };
        wallet_from?: {
            address?: string;
        };
    };
```

### Methods

1. Create Invoice

    This method is used to create a new invoice.

    ```javascript
        async create(data: CreateInvoiceData): Promise<DataContainer<Invoice>>
    ```

    Example:

    ```javascript
        const invoiceData = {
            order_id: 12345,
            amount: 500,
        };

        const invoiceContainer = await invoiceManager.create(invoiceData);

        if (invoiceContainer.isValid) {
            const invoice = invoiceContainer.data;
            // Do something with the created invoice
            console.log('New Invoice ID:', invoice.id);
        } else {
            console.error('Error creating invoice:', invoiceContainer.error);
        }
    ```

2. Cancel Invoice

    This method is used to cancel an existing invoice.

    ```javascript
        async cancel(invoiceId: InvoiceID): Promise<DataContainer<Invoice>>
    ```

    Example:

    ```javascript
        const invoiceIdToCancel = 12345;

        const canceledInvoiceContainer = await invoiceManager.cancel(invoiceIdToCancel);

        if (canceledInvoiceContainer.isValid) {
            const canceledInvoice = canceledInvoiceContainer.data;
            // Handle the canceled invoice data
            console.log('Canceled Invoice ID:', canceledInvoice.id);
        } else {
            console.error('Error canceling invoice:', canceledInvoiceContainer.error);
        }
    ```

3. Get Invoice Information

    This method is used to retrieve information about a specific invoice.

    ```javascript
        async info(invoiceId: InvoiceID): Promise<DataContainer<Invoice>>
    ```

    Example:

    ```javascript
        const invoiceIdToRetrieve = 12345;

        const invoiceInfoContainer = await invoiceManager.info(invoiceIdToRetrieve);

        if (invoiceInfoContainer.isValid) {
            const invoiceInfo = invoiceInfoContainer.data;
            // Use the retrieved invoice information
            console.log('Invoice Status:', invoiceInfo.status);
        } else {
            console.error('Error getting invoice information:', invoiceInfoContainer.error);
        }
    ```

4. Get Merchant Statistics

    This method is used to get statistical data related to the merchant's invoices.

    ```javascript
        async stats(): Promise<DataContainer<InvoiceStats>>
    ```

    Example:

    ```javascript
        const merchantInvoiceStatsContainer = await invoiceManager.stats();

        if (merchantInvoiceStatsContainer.isValid) {
            const invoiceStats = merchantInvoiceStatsContainer.data;
            // Utilize the merchant's invoice statistics
            console.log('Total Invoice Count:', invoiceStats.count);
        } else {
            console.error('Error getting merchant invoice statistics:', merchantInvoiceStatsContainer.error);
        }
    ```

5. Process WebHook Data

    This method is used to process WebHook data related to an invoice update.

    ```javascript
        processUpdate(update: InvoiceUpdate): DataContainer<Omit<Invoice, 'id'>>
    ```

    Example:

    ```javascript
        const webhookData = {
            data: {
                status: 'created',
                code: '123456789',
                amount: 500,
                order_id: 12345,
                sign: 'signature',
            },
        };

        const processedData = invoiceManager.processUpdate(webhookData);

        if (processedData.isValid) {
            const processedInvoiceData = processedData.data;
            // Processed invoice data (without 'id' field)
            console.log('Processed Invoice Status:', processedInvoiceData.status);
        } else {
            console.error('Invalid data received in WebHook:', processedData.error);
        }
    ```

## Extending MerchantAPIClient

The MerchantAPIClient may be extended via adding new services, like InvoiceManager, inside it.
