JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 11
  • Score
    100M100P100Q61776F
  • License MIT

React SDK for X0Pay Hyperlane token bridging with MetaMask and Safe wallet integration

Package Exports

  • x0-react-sdk

Readme

X0Pay React SDK

A React SDK for integrating X0Pay functionality into web applications. This SDK provides a complete solution for handling cross-chain token transfers with server-side fee management.

Features

  • Cross-chain transfers: Support for multiple blockchain networks
  • Server-side fee management: Automatic fee calculation based on transfer amount
  • Custom fee support: Override fees with validation against minimum requirements
  • Order ID validation: Real-time validation with X0-worker API
  • Multi-wallet support: MetaMask and WalletConnect integration
  • Safe wallet support: Gnosis Safe multisig wallet integration
  • Exchange rate handling: Automatic IDR to USD conversion
  • Progress tracking: Step-by-step transaction flow
  • Error handling: Comprehensive error management

Installation

npm install x0-react-sdk

Usage

Basic Usage

import React from 'react';
import { X0PayComponent } from 'x0-react-sdk';

function App() {
  const transactionParams = {
    orderId: 'ORDER123456', // Required: Order ID for validation
    transferAmount: 150000, // 150,000 IDR
    exchangeRate: 15000, // Optional: USD/IDR exchange rate
  };

  return (
    <X0PayComponent
      transactionParams={transactionParams}
      workerApiUrl="http://localhost:3000" // X0-worker API URL for fee calculation and order validation
      onSuccess={(txHash) => console.log('Success!', txHash)}
      onError={(err) => console.error('Error:', err.message)}
    />
  );
}

Order ID Validation

The SDK includes real-time order ID validation to prevent duplicate transactions. Order IDs are validated against the X0-worker API before allowing transactions to proceed.

Features

  • Real-time validation: Order IDs are validated as soon as they're entered
  • Duplicate prevention: Prevents transactions with existing order IDs
  • Visual feedback: Clear status indicators for order ID validation
  • Error handling: Comprehensive error messages for validation failures

Usage

const transactionParams = {
  orderId: 'ORDER123456', // Required: Unique order identifier
  transferAmount: 150000, // 150,000 IDR
  exchangeRate: 15000, // Optional: USD/IDR exchange rate
};

<X0PayComponent
  transactionParams={transactionParams}
  workerApiUrl="http://localhost:3000" // Required for order validation
  onSuccess={onSuccess}
  onError={onError}
/>

Validation States

  • Validating: Order ID is being checked
  • Available: Order ID is available for use (green indicator)
  • Exists: Order ID already exists (red indicator, transaction blocked)
  • Error: Validation failed (red indicator with error message)

Fee Management

The SDK supports both automatic server-side fee calculation and custom fee amounts with validation:

Automatic Fee Calculation (Default)

The SDK uses server-side fee calculation with automatic tiering based on transfer amount:

Fee Tiers

  • Tier 1: 10,000 - 4,999,999 IDR → 1% fee, minimum 2,000 IDR
  • Tier 2: 5,000,000 - 49,999,999 IDR → 0.75% fee, minimum 15,000 IDR
  • Tier 3: 50,000,000 - 200,000,000 IDR → 0.5% fee, minimum 50,000 IDR

Fee Calculation

  • Fees are always calculated as outer fees (added to transfer amount)
  • Total amount = Transfer Amount + Calculated Fee
  • Fee calculation is handled automatically by the X0-worker API

Example:

  • Transfer Amount: 150,000 IDR
  • Calculated Fee: 1,500 IDR (1% of 150,000 IDR)
  • Total Amount: 151,500 IDR

Custom Fee Amount (New Feature)

You can now provide a custom fee amount that will be validated against the API-calculated fee:

<X0PayComponent
  transactionParams={{
    orderId: 'ORDER123456',
    transferAmount: 150000, // 150,000 IDR
    exchangeRate: 15000,
    feeAmount: 2000 // Custom fee amount in IDR (must be >= API fee)
  }}
  workerApiUrl="http://localhost:3000"
  onSuccess={onSuccess}
  onError={onError}
/>

Custom Fee Features

  • Validation: Custom fee must be greater than or equal to the API-calculated fee
  • Flexibility: Allows for higher fees when needed (e.g., priority transactions)
  • Safety: Prevents underpayment by validating against minimum required fee
  • Transparency: Shows both custom fee and API fee for comparison

Fee Validation Process

  1. API Fee Calculation: SDK fetches the minimum required fee from X0-worker API
  2. Custom Fee Validation: Compares your custom fee with the API fee
  3. Transaction Blocking: If custom fee is too low, transaction buttons are disabled
  4. Clear Feedback: Shows validation status with detailed error messages

Example with Custom Fee

// This will work if API fee is 1,500 IDR or less
<X0PayComponent
  transactionParams={{
    orderId: 'ORDER123456',
    transferAmount: 150000,
    exchangeRate: 15000,
    feeAmount: 2000 // 2,000 IDR custom fee
  }}
  workerApiUrl="http://localhost:3000"
  onSuccess={onSuccess}
  onError={onError}
/>

// This will be blocked if API fee is higher than 1,000 IDR
<X0PayComponent
  transactionParams={{
    orderId: 'ORDER123456',
    transferAmount: 150000,
    exchangeRate: 15000,
    feeAmount: 1000 // 1,000 IDR custom fee (may be too low)
  }}
  workerApiUrl="http://localhost:3000"
  onSuccess={onSuccess}
  onError={onError}
/>

Fee Display

When using custom fees, the UI shows:

  • Custom Fee: Your custom fee amount in IDR and USD
  • API Fee: The minimum required fee from the API
  • Validation Status: ✓ Passed or ⚠️ Failed with error message
  • Total Amount: Transfer amount + your custom fee

Transaction Parameters

interface X0PayTransactionParams {
  orderId: string; // Order identifier (required) - used for validation and tracking
  transferAmount: number; // Amount in IDR
  exchangeRate?: number; // Optional exchange rate (USD/IDR)
  feeAmount?: number; // Optional fee amount in IDR, API fee will be used for validation
}

interface X0PayComponentProps {
  config?: X0PayConfig; // Optional - if not provided, uses built-in chain/token configurations
  clientConfig?: X0PayClientConfig; // Optional - client-provided chain and token configurations
  transactionParams: X0PayTransactionParams;
  onSuccess?: (txHash: string) => void;
  onError?: (error: Error) => void;
  className?: string;
  style?: React.CSSProperties;
  walletConnectProjectId?: string; // WalletConnect project ID for mobile support
  enableWalletConnect?: boolean; // Enable WalletConnect mobile support
  enableSafe?: boolean; // Enable Safe wallet support
  workerApiUrl?: string; // X0-worker API URL for fee calculation
}

Order ID Requirements

  • Required: Every transaction must have a unique order ID
  • Validation: Order IDs are validated against the X0-worker API
  • Uniqueness: Order IDs must not have been used in previous transactions
  • Format: Order IDs can be any string format (alphanumeric, UUID, etc.)

Configuration

The SDK supports both default configurations and client-provided configurations. Client configurations can override or extend the default configurations.

Default Configuration

The SDK comes with pre-configured chains and tokens. If no custom configuration is provided, the SDK will use these defaults.

Client Configuration

You can provide custom chain and token configurations that override or extend the defaults:

import { X0PayComponent, X0PayClientConfig } from 'x0-react-sdk';

const clientConfig: X0PayClientConfig = {
  chains: [
    // Override existing chain
    {
      chainId: '0x89', // Polygon
      name: 'Polygon (Custom RPC)',
      rpcUrls: ['https://polygon-rpc.com/', 'https://rpc-mainnet.maticvigil.com/'],
      nativeCurrency: { name: 'Matic', symbol: 'MATIC', decimals: 18 },
      blockExplorerUrls: ['https://polygonscan.com/'],
    },
    // Add new chain
    {
      chainId: '0x1', // Ethereum mainnet
      name: 'Ethereum',
      rpcUrls: ['https://mainnet.infura.io/v3/YOUR-PROJECT-ID'],
      nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
      blockExplorerUrls: ['https://etherscan.io/'],
    },
  ],
  chainTokenConfigs: [
    {
      chainId: '0x89', // Polygon
      chainName: 'Polygon (Custom RPC)',
      tokens: [
        {
          symbol: 'USDT',
          name: 'Tether USD (Custom)',
          address: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',
          decimals: 6,
          hypColAddress: '0x6316043b1EE191538A3903d95723506229B1e985',
        },
        // Add new token
        {
          symbol: 'USDC',
          name: 'USD Coin',
          address: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
          decimals: 6,
          hypColAddress: '0x1234567890123456789012345678901234567890',
        },
      ],
              hookAddress: '0x9B31d0eb6D852939Fe5A2BB8a66F3b5E6679A3a5',
        destinationDomain: 137,
    },
  ],
};

<X0PayComponent
  clientConfig={clientConfig}
  transactionParams={transactionParams}
  onSuccess={onSuccess}
  onError={onError}
/>

Legacy Configuration (Still Supported)

You can still provide custom configuration for specific transactions:

const config = {
  erc20TokenAddress: '0x...',
  hypColAddress: '0x...',
  recipient: '0x...',
  hookAddress: '0x...',
};

<X0PayComponent
  config={config}
  transactionParams={transactionParams}
  onSuccess={onSuccess}
  onError={onError}
/>

Configuration Manager

For advanced usage, you can use the configuration manager directly:

import { globalConfigManager, X0ConfigManager } from 'x0-react-sdk';

// Update global configuration
globalConfigManager.updateClientConfigs(clientChains, clientChainTokenConfigs);

// Or create a new instance
const configManager = new X0ConfigManager(clientChains, clientChainTokenConfigs);
const chains = configManager.getChains();
const configs = configManager.getChainTokenConfigs();

Recipient Address

The recipient address is automatically retrieved from the hook contract's vaultAddress() function and converted to bytes32 format for Hyperlane message compatibility. This ensures that the recipient is always up-to-date and matches the vault address configured in the hook contract.

  • Automatic Retrieval: The SDK automatically calls the hook contract to get the current vault address
  • Bytes Conversion: The address is automatically converted to bytes32 format using ethers.utils.hexZeroPad()
  • No Hardcoding: No need to hardcode recipient addresses in configurations
  • Dynamic Updates: If the vault address changes in the hook contract, the SDK will automatically use the new address

The recipient retrieval happens when:

  1. A wallet is connected
  2. The hook address is available in the configuration
  3. The provider is ready to make contract calls

Note: The recipient is stored in bytes32 format (e.g., 0x00000000000000000000000076ad6ab8e9d4b10b27d949a414e9aa18c665ef9f) to ensure compatibility with Hyperlane message format.

Wallet Options

The SDK supports multiple wallet types with an intuitive UI for wallet selection.

Basic Usage (Auto-detect)

<X0PayComponent
  transactionParams={transactionParams}
  onSuccess={onSuccess}
  onError={onError}
/>

Enable WalletConnect with Project ID

<X0PayComponent
  transactionParams={transactionParams}
  onSuccess={onSuccess}
  onError={onError}
  walletConnectProjectId="YOUR_PROJECT_ID"
  enableWalletConnect={true}
/>

Wallet Selection Features

When enableWalletConnect is true, users can choose from:

  • Auto: Automatically selects the best wallet for the platform
  • MetaMask Web Extension: For desktop MetaMask users
  • Mobile Wallet (WalletConnect): For mobile wallet users

The SDK intelligently:

  • Shows only available wallet options
  • Handles chain switching for MetaMask
  • Provides QR codes for mobile wallets
  • Automatically detects the best wallet for the platform

Safe Wallet Support

The SDK includes comprehensive support for Gnosis Safe multisig wallets:

Enable Safe Support

<X0PayComponent
  transactionParams={transactionParams}
  enableSafe={true}
  workerApiUrl="http://localhost:3000"
  onSuccess={onSuccess}
  onError={onError}
/>

Safe Flow Features

When Safe support is enabled, users can choose between:

  • EOA (Externally Owned Account): Standard MetaMask/WalletConnect flow
  • Safe (Gnosis Safe): Multisig wallet flow

Safe Transaction Flow

  1. Connect Wallet: Connect to Safe using MetaMask or WalletConnect
  2. Create/Join Proposal:
    • Create: Create a new transaction proposal and sign it
    • Join: Join an existing proposal by signing it
  3. Execute Transaction: Execute the transaction once enough signatures are collected

Safe Proposal Management

  • Proposal Creation: Create transaction proposals with all necessary parameters
  • Signature Collection: Collect signatures from multiple Safe owners
  • Threshold Validation: Ensure minimum required signatures are collected
  • Proposal Sharing: Share proposal JSON with other Safe owners
  • Transaction Execution: Execute the transaction when threshold is met

Safe UI Features

  • Account Type Selection: Choose between EOA and Safe flows
  • Safe Address Input: Enter the Safe address for proposal creation
  • Proposal JSON: Paste and validate existing proposals
  • Signature Status: Track collected signatures vs. required threshold
  • Proposal Details: Display human-readable transaction details
  • Copy to Clipboard: Easy sharing of proposal JSON

Supported Networks

The SDK supports multiple blockchain networks including:

  • Polygon
  • Mumbai (Polygon Testnet)
  • Arbitrum
  • Optimism
  • Base
  • And more...

Exchange Rate

The SDK automatically fetches the current USD/IDR exchange rate from a reliable API. You can also provide a custom exchange rate in the transaction parameters.

Error Handling

The SDK provides comprehensive error handling for:

  • Network connection issues
  • Insufficient balance
  • Transaction failures
  • Exchange rate errors
  • Fee calculation errors
  • Wallet connection problems

Wallet Utilities

The SDK provides utility functions for wallet management:

import { 
  getAvailableWalletTypes, 
  createDefaultWalletConnectConfig,
  getRecommendedWalletType 
} from 'x0-react-sdk';

// Get available wallet types
const availableWallets = getAvailableWalletTypes(); // ['metamask', 'walletconnect']

// Get recommended wallet type for current platform
const recommendedWallet = getRecommendedWalletType(); // 'metamask' or 'walletconnect'

// Create default WalletConnect configuration
const walletConnectConfig = createDefaultWalletConnectConfig('YOUR_PROJECT_ID');

Styling

The SDK includes default styling that can be customized using CSS classes:

  • .x0pay-container
  • .x0pay-button
  • .x0pay-error
  • .x0pay-transaction-details

Development

To run the SDK in development mode:

cd X0-sdk
npm install
npm run dev

Testing

The test app demonstrates the new fee calculation functionality:

cd test-app
npm install
npm start

License

MIT License

Supported Token Addresses

Arbitrum One

  • USDC: 0xaf88d065e77c8cC2239327C5EDb3A432268e5831
    • Hyperlane Collateral: 0x922D6956C99E12DFeB3224DEA977D0939758A1Fe
  • USDT: 0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9
    • Hyperlane Collateral: 0x1234567890123456789012345678901234567890

Polygon

  • USDC: 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174
    • Hyperlane Collateral: 0x922D6956C99E12DFeB3224DEA977D0939758A1Fe
  • USDT: 0xc2132D05D31c914a87C6611C10748AEb04B58e8F
    • Hyperlane Collateral: 0xabcdef1234567890abcdef1234567890abcdef12