In this guide, we’ll walk through the process of minting USDT on Arbitrum using the Aarc SDK. The complete implementation can be found in our example repository.

Prerequisites

  • Node.js and npm installed
  • An Ethereum wallet with private key
  • API key from Aarc
  • Basic understanding of TypeScript and Ethereum

Setup

1

Install SDK

Install the Aarc SDK and required dependencies:

npm install @aarc-xyz/core-viem ethers dotenv
2

Configure Environment

Create a .env file with your credentials:

API_KEY=your_aarc_api_key
PRIVATE_KEY=your_wallet_private_key
RPC_URL=your_arbitrum_rpc_url
3

Initialize SDK

Set up the SDK and wallet configuration:

import { AarcCore } from "@aarc-xyz/core-viem";
import { ethers } from "ethers";

const API_KEY = process.env.API_KEY!;
const PRIVATE_KEY = process.env.PRIVATE_KEY!;
const RPC_URL = process.env.RPC_URL!;

export const aarcCoreSDK = new AarcCore(API_KEY);
export const walletProvider = ethers.getDefaultProvider(RPC_URL);
export const wallet = new ethers.Wallet(PRIVATE_KEY, walletProvider);

Implementation

1

Define Constants

Set up the USDT token details and destination parameters:

const USDT_ADDRESS = "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9";
const DESTINATION_TOKEN = {
  decimals: 6, // USDT decimals
  chainId: 42161, // Arbitrum chain ID
  address: USDT_ADDRESS,
};
2

Create Mint Call Data Generator

Implement the function to generate the minting call data:

function generateStablecoinCallData(
  toAddress: string,
  amount: string
): string {
  // Create the contract interface with mint function
  const usdtInterface = new ethers.Interface([
    "function mint(address _destination, uint256 _amount) external",
  ]);

  // Generate the contract payload for minting USDT
  return usdtInterface.encodeFunctionData("mint", [
    toAddress, // destination: user's address
    amount, // amount: amount to mint
  ]);
}
3

Check Token Balance

Verify USDT balance before proceeding:

const balance = await getMultichainBalance(wallet.address, {
  tokenAddress: DESTINATION_TOKEN.address,
  tokenChainId: DESTINATION_TOKEN.chainId,
  tokenAmount: amount,
});

const fromToken = balance[DESTINATION_TOKEN.chainId.toString()]?.balances?.find(
  (b) => b.symbol === "USDT"
);

if (!fromToken) {
  throw new Error("No USDT balance available");
}
4

Get Deposit Address

Fetch the deposit address from Aarc:

const depositData = await getDepositAddress({
  contractPayload: callData,
  fromToken: {
    decimals: fromToken.decimals,
    chainId: DESTINATION_TOKEN.chainId,
    address: fromToken.token_address,
  },
  fromTokenAmount: amount,
  destinationToken: DESTINATION_TOKEN,
  destinationWalletAddress: USDT_ADDRESS,
  requestedAmount: amount,
});
5

Execute Transaction

Send the transaction and handle the response:

const trxHash = await executeTransaction(depositData);
console.log("Transaction completed with hash:", trxHash);

Usage Example

async function main() {
  try {
    // Amount in smallest unit (6 decimals for USDT)
    const amount = "1000000"; // 1 USDT
    await mintStablecoin(amount);
  } catch (error) {
    console.error("Error in main execution:", error);
  }
}

Understanding the Flow

  1. Balance Check: Verifies if you have sufficient USDT on Arbitrum
  2. Call Data Generation: Creates the encoded function call for USDT minting
  3. Deposit Address: Gets a unique deposit address from Aarc
  4. Transaction Execution: Sends the transaction and notifies Aarc of completion

The minting process involves several steps to ensure security and proper token allocation:

  • First, we check the current balance to ensure sufficient funds
  • Then, we generate the specific call data needed for the minting operation
  • Next, we obtain a secure deposit address from Aarc
  • Finally, we execute the transaction to mint the tokens

For the complete implementation with error handling and utility functions, check out our example repository.