# TOKEN Deposit & Spending SDK for E-commerce Merchants

This document serves as a comprehensive guide for e-commerce merchants' technical teams to integrate TOKEN functions on the Base chain. The protocol facilitates secure payment management and token minting using a pre-authorized merchant address and its private key.\
\
If you have not registered as a verified merchant, please [fill in this form](https://airtable.com/appJNhn3rLbOB3csU/paghZIGjBLuR5QlMX/form).

<div data-full-width="true"><figure><img src="/files/TcQwxjSCrJSW4y5nvCHg" alt=""><figcaption><p>Permit Ecosystem Overview</p></figcaption></figure></div>

### Prerequisites

Before integrating the SDK, ensure the following requirements are met:

1. **Private Key Management**:\
   Securely manage and store the merchant's private key. For security, handle the private key exclusively on the server side and avoid exposure in client-facing applications.
2. **Node.js Environment**:\
   Install Node.js to execute the JavaScript-based SDK. Verify compatibility with your system.
3. **Base Chain RPC Endpoint**:\
   Acquire a valid Base chain RPC URL. This can be sourced from a public node provider or a self-hosted node.

### Installation

To begin, install the required dependency — ethers.js --  to interact with the Base chain. Execute the following command in your project directory:

```bash
npm install ethers
```

### &#x20;

### SDK Implementation

The following JavaScript code represents the complete SDK for integration into merchant applications. It includes the core functionality of the [TOKEN smart contract](https://basescan.org/address/0xa1b68a58b1943ba90703645027a10f069770ed39).

```javascript
const { ethers } = require('ethers');

// Base chain RPC URL
const RPC_URL = 'https://mainnet.base.org';

// TOKEN's contract address
const CONTRACT_ADDRESS = '0xa1B68A58B1943Ba90703645027a10F069770ED39';

// Contract ABI
const ABI = [
  {
    "constant": false,
    "inputs": [
      {"name": "user", "type": "address"},
      {"name": "cashAmount", "type": "uint256"}
    ],
    "name": "mintToken",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {"name": "user", "type": "address"},
      {"name": "amount", "type": "uint256"}
    ],
    "name": "payMerchant",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  }
];



// Merchant's private key (replace with your actual key, ensure secure storage)
const PRIVATE_KEY = '0xYourPrivateKeyHere';

// Initialize provider and wallet
const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);

// Initialize contract instance
const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, wallet);



/**
 * Mint tokens for a user
 * @param {string} userAddress - The user's Base chain address
 * @param {string} cashAmount - The amount of tokens to mint (in token units)
 */
async function mintToken(userAddress, cashAmount) {
  try {
    const amount = ethers.utils.parseUnits(cashAmount.toString(), 18);
    const tx = await contract.mintToken(userAddress, amount);
    console.log('Minting transaction hash:', tx.hash);
    const receipt = await tx.wait();
    console.log('Minting transaction confirmed in block:', receipt.blockNumber);
    return receipt;
  } catch (error) {
    console.error('Error minting token:', error.message);
    throw error;
  }
}

/**
 * Process a payment from a user
 * @param {string} userAddress - The user's Base chain address
 * @param {string} amount - The amount of tokens to pay (in token units)
 */
async function payMerchant(userAddress, amount) {
  try {
    const paymentAmount = ethers.utils.parseUnits(amount.toString(), 18);
    const tx = await contract.payMerchant(userAddress, paymentAmount);
    console.log('Payment transaction hash:', tx.hash);
    const receipt = await tx.wait();
    console.log('Payment transaction confirmed in block:', receipt.blockNumber);
    return receipt;
  } catch (error) {
    console.error('Error processing payment:', error.message);
    throw error;
  }
}

/**
 * Get the TOKEN balance of a user
 * @param {string} userAddress - The user's Base chain address
 * @returns {string} The balance in TOKEN units
 */
async function getTokenBalance(userAddress) {
  try {
    const balance = await contract.balanceOf(userAddress);
    const formattedBalance = ethers.utils.parseUnits(balance.toString(), 18);
    console.log(`Balance of ${userAddress}: ${formattedBalance} TOKEN`);
    return formattedBalance;
  } catch (error) {
    console.error('Error getting token balance:', error.message);
    throw error;
  }
}



// Export functions for use in the merchant applications
module.exports = {
  mintToken,
  payMerchant,
  getTokenBalance
};
```

### Checking TOKEN Wallet Balance

The SDK now includes a getTokenBalance function that allows merchants to check the TOKEN balance of any user’s wallet. Since TOKEN is an ERC20 token, this function utilizes the standard balanceOf function from the ERC20 interface to query the balance of a specified address. The balance is returned in a human-readable format, adjusted for the token's decimals (dynamically retrieved using the decimals function).

* getTokenBalance(userAddress): Retrieves the TOKEN balance of the specified user address and returns it as a string in token units.

This function uses a contract instance initialized with a provider (no private key required for this read-only operation), making it efficient and secure for balance queries.

### Usage Instructions

To utilize the SDK, merchants can incorporate it into their applications as demonstrated below:

1. **Create an Application File** (e.g., app.js):

```javascript
const { mintToken, payMerchant, getTokenBalance } = require('./merchant-sdk.js');

// Mint tokens for a user
async function runMintToken(userAddress, TOKENAmount) {
  try {
    await mintToken(userAddress, TOKENAmount);
  } catch (error) {
    console.error('Minting failed:', error);
  }
}

// Process a payment from the user's address
async function runPayMerchant(userAddress, TOKENAmount) {
  try {
    await payMerchant(userAddress, TOKENAmount);
  } catch (error) {
    console.error('Payment failed:', error);
  }
}

// Check user balance from address
async function runGetTokenBalance(userAddress) {
  try {
    const balance = await getTokenBalance(userAddress);
    console.log(`User's TOKEN balance: ${balance}`);
  } catch (error) {
    console.error('Failed to check:', error);
  }
}

// Execute examples
runMintToken();
runPayMerchant();
runGetTokenBalance();
```

2. **Run the Application**:\
   Launch the application using the following terminal command:

```bash
node app.js
```

### &#x20;

### Key Considerations

* **Private Key Security**:\
  The PRIVATE\_KEY must remain confidential, and it should be utilized in a secure backend environment, never exposed client-side.
* **Token Units**:\
  Convert token amounts to the appropriate format (e.g., 18 decimal places) using ethers.utils.parseUnits.
* **Gas Fees**:\
  Ensure the merchant wallet contains sufficient Base chain native tokens (ETH on the Base chain) to cover the transaction gas costs of the "payMerchant" and "mintToken" operations.

### Support

Please check us on  [X](https://x.com/erc20permit) / [Telegram](https://t.me/permit_money) for assistance if you encounter any difficulties during integration or usage.


---

# Agent Instructions: 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:

```
GET https://permit-1.gitbook.io/permit-docs/token-deposit-and-spending-sdk-for-e-commerce-merchants.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
