Skip to main content
The b402 protocol enables users to make gasless payments in BEP-20 tokens such as USD1 and USDT on the BNB Chain. This guide shows how to send a payment to a seller using the b402 TypeScript SDK.

Overview

As a buyer, you can authorize payments using EIP-712 signatures without paying any gas fees. The b402 Facilitator covers the gas cost and settles the transaction on-chain via the b402 Relayer. Payments typically finalize in under 3 seconds.

Prerequisites

Before running the example, make sure you have:
  1. Node.js 18+
  2. A BNB Chain wallet with USD1 tokens
  3. A valid private key exported as an environment variable
.env
export PRIVATE_KEY=your_private_key_here

Installation

Install the required packages:
npm install ethers b402-sdk

Example

The following example demonstrates how to send a USD1 payment to a seller service that supports the b402 protocol. This walkthrough shows the complete flow from connecting your wallet to confirming the on-chain transaction.
  1. Initialize Provider & Wallet: Connect to BNB Chain and load your wallet.
  2. Check Balance: Ensure you have enough USD1.
  3. Approve Relayer: Allow the b402 relayer contract to spend tokens on your behalf.
  4. Send Payment: Use the b402.pay() method to send a gasless payment to a seller.
  5. Confirm Transaction: The SDK returns a transaction hash for verification on BscScan.

Step 1. Connect Wallet and Provider

// Import Packages and Define Constants
import { Wallet, Contract, JsonRpcProvider } from 'ethers';
import { B402 } from 'b402-sdk';

// USD1 stablecoin and b402 relayer contract on BNB Chain
const USD1 = '0x8d0d000ee44948fc98c9b98a4fa4921476f08b0d';
const RELAYER = '0xE1C2830d5DDd6B49E9c46EbE03a98Cb44CD8eA5a';
const RPC = 'https://bsc-dataseed1.binance.org';

async function main() {
  if (!process.env.PRIVATE_KEY) {
    console.error('❌ Set PRIVATE_KEY environment variable');
    process.exit(1);
  }

  // Connect to BNB Chain RPC
  const provider = new JsonRpcProvider(RPC);

  // Create wallet instance
  const wallet = new Wallet(process.env.PRIVATE_KEY, provider);
  console.log('Wallet address:', wallet.address);

Step 2. Load the Token Contract

  // Minimal BEP-20 ABI for balance, allowance, and approval
  const token = new Contract(
    USD1,
    [
      'function balanceOf(address) view returns (uint256)',
      'function allowance(address,address) view returns (uint256)',
      'function approve(address,uint256) returns (bool)',
    ],
    wallet
  );

  // Check user’s USD1 balance
  console.log('Checking balance...');
  const balance = await token.balanceOf(wallet.address);
  console.log('USD1 Balance:', Number(balance) / 1e18);

  if (balance === 0n) {
    console.error('❌ You need USD1 tokens to continue');
    process.exit(1);
  }

Step 3. Approve the Relayer (Once Per Token)

  console.log('Checking approval...');
  const allowance = await token.allowance(wallet.address, RELAYER);

  // If not approved yet, give the relayer unlimited allowance
  if (allowance === 0n) {
    console.log('Approving relayer...');
    const tx = await token.approve(
      RELAYER,
      '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
    );
    await tx.wait();
    console.log('✅ Relayer approved');
  }

Step 4. Send the Payment

  console.log('Sending payment...');

  // Initialize b402 SDK
  const b402 = new B402('mainnet');

  // Execute the payment
  const result = await b402.pay(wallet, {
    amount: '0.01', // payment amount in token units
    token: 'USD1',  // token symbol
    recipient: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', // seller’s address
  });

  // Display result
  if (result.success) {
    console.log('✅ Payment successful');
    console.log('Transaction Hash:', result.txHash);
    console.log(`View on BscScan: https://bscscan.com/tx/${result.txHash}`);
  } else {
    console.error('❌ Payment failed:', result.error);
  }
}

main();

Complete Example Code

// Import dependencies from ethers.js and the b402 SDK
import { Wallet, Contract, JsonRpcProvider } from 'ethers';
import { B402 } from 'b402-sdk';

// Define constants for the USD1 token, b402 Relayer contract, and BNB Chain RPC endpoint
const USD1 = '0x8d0d000ee44948fc98c9b98a4fa4921476f08b0d';
const RELAYER = '0xE1C2830d5DDd6B49E9c46EbE03a98Cb44CD8eA5a';
const RPC = 'https://bsc-dataseed1.binance.org';

async function main() {
  // Ensure the user has provided a private key for signing transactions
  if (!process.env.PRIVATE_KEY) {
    console.log('Set PRIVATE_KEY');
    process.exit(1);
  }

  // Connect to the BNB Chain and initialize the wallet
  const provider = new JsonRpcProvider(RPC);
  const wallet = new Wallet(process.env.PRIVATE_KEY, provider);
  console.log('Wallet:', wallet.address);

  // Create a contract instance for USD1 (BEP-20) with minimal ABI for balance, allowance, and approval
  const token = new Contract(
    USD1,
    [
      'function balanceOf(address) view returns (uint256)',
      'function allowance(address,address) view returns (uint256)',
      'function approve(address,uint256) returns (bool)',
    ],
    wallet
  );

  // Check the user's USD1 balance before sending payment
  console.log('Checking balance...');
  const balance = await token.balanceOf(wallet.address);
  console.log('USD1:', Number(balance) / 1e18);

  if (balance === 0n) {
    console.log('Need USD1 tokens');
    process.exit(1);
  }

  // Check if the b402 Relayer contract has approval to transfer tokens on behalf of the user
  console.log('Checking approval...');
  const allowance = await token.allowance(wallet.address, RELAYER);

  // If no approval exists, approve the Relayer with a large (max) allowance
  if (allowance === 0n) {
    console.log('Approving relayer...');
    const tx = await token.approve(
      RELAYER,
      '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
    );
    await tx.wait();
    console.log('Approved');
  }

  // Initialize the b402 SDK and send a gasless payment
  console.log('Sending payment...');
  const b402 = new B402('mainnet');

  // Define payment details: amount, token, and recipient (seller)
  const result = await b402.pay(wallet, {
    amount: '0.01', // Amount of USD1 to send
    token: 'USD1',  // Token symbol
    recipient: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', // Seller’s wallet
  });

  // Display the transaction result and link to BscScan
  if (result.success) {
    console.log('Payment successful');
    console.log('TX:', result.txHash);
    console.log(`View on BscScan: https://bscscan.com/tx/${result.txHash}`);
  } else {
    console.log('Payment failed:', result.error);
  }
}

// Execute the script
main();