Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Embed Stablecoin Payments

Embed onchain stablecoin payments directly into your telecom, neobank, or fintech application. No wallet UI, no seed phrases - just passkey authentication and instant USDC transfers.

Why Stablecoin Payments?

Traditional cross-border payments are slow and expensive. When you send $1,000 to a contractor in Brazil using traditional rails, the costs add up quickly: payment processor fees ($10–$40), intermediary bank cuts (0.1%–4.0% FX spread), and 3-5 days of settlement time. By the time the payment clears, the recipient has lost $80 to fees.

Stablecoins change this entirely:
Traditional RailsStablecoin Rails
3-5 business daysSeconds
$40-80 in fees per $1,000~$0.01-0.10
Bank hours only24/7/365
Currency volatility riskDollar-denominated stability
Opaque reconciliationOn-chain transparency

With JAW, you can embed these benefits directly into your application. Users authenticate with passkeys (no seed phrases), pay gas fees in USDC (no ETH needed), and send payments that settle in seconds.

Prerequisites

Install the core SDK:

npm
npm install @jaw.id/core

Get your API key at dashboard.jaw.id.

Configuration

Set up your account configuration with the ERC-20 paymaster for USDC gas payments:

import { Account, JAW_PAYMASTER_URL } from '@jaw.id/core';
 
const USDC_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'; // USDC on Base
 
const config = {
  chainId: 8453, // Base
  apiKey: 'YOUR_API_KEY',
};
 
const paymasterUrl = `${JAW_PAYMASTER_URL}?chainId=8453&api-key=YOUR_API_KEY`;

Account Management

Since you're using the Account class directly (headless mode), no JAW UI is rendered. The only prompt users see is the native browser/OS passkey dialog.

Create Account
// New user: create account with passkey
const account = await Account.create(config, {
  username: 'user@yourapp.com' // Your app's user identifier
});
 
// Store the credentialId for future sign-ins
const { credentialId } = account.getMetadata();
// Save credentialId in your own backend/database (not an SDK function)
await storeCredentialId('user@yourapp.com', credentialId);

Send a USDC Payment

Send USDC with gas fees paid in USDC - users don't need ETH:

import { encodeFunctionData, erc20Abi, parseUnits } from 'viem';
 
// Send 10 USDC to a recipient
const { id, chainId } = await account.sendCalls(
  [{
    to: USDC_ADDRESS,
    data: encodeFunctionData({
      abi: erc20Abi,
      functionName: 'transfer',
      args: [
        '0xRecipientAddress...', // Recipient address
        parseUnits('10', 6)      // 10 USDC (6 decimals)
      ]
    })
  }],
  undefined,              // options
  paymasterUrl,           // ERC-20 paymaster
  { token: USDC_ADDRESS } // Pay gas in USDC
);
 
console.log('Transaction submitted:', id);

The SDK automatically handles the USDC approval for gas payment - no extra step required.

Check Transaction Status

Poll for transaction confirmation:

const status = account.getCallStatus(id);
 
if (status) {
  switch (status.status) {
    case 100:
      console.log('Pending...');
      break;
    case 200:
      console.log('Completed!', status.receipts?.[0]?.transactionHash);
      break;
    case 400:
      console.log('Failed (off-chain)');
      break;
    case 500:
      console.log('Reverted (on-chain)');
      break;
  }
}

Batch Payments

Send multiple payments in a single transaction for payroll or mass payouts:

const recipients = [
  { address: '0xAlice...', amount: '500' },
  { address: '0xBob...', amount: '750' },
  { address: '0xCharlie...', amount: '300' },
];
 
const calls = recipients.map(({ address, amount }) => ({
  to: USDC_ADDRESS,
  data: encodeFunctionData({
    abi: erc20Abi,
    functionName: 'transfer',
    args: [address, parseUnits(amount, 6)]
  })
}));
 
const { id } = await account.sendCalls(
  calls,
  undefined,
  paymasterUrl,
  { token: USDC_ADDRESS }
);

All transfers execute atomically - either all succeed or all fail together.

Supported Networks

See Supported Networks for the full list.

Related