x0-react-sdk
Version:
React SDK for X0Pay Hyperlane token bridging with MetaMask and Safe wallet integration
497 lines (393 loc) • 15.8 kB
Markdown
# 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
```bash
npm install x0-react-sdk
```
## Usage
### Basic Usage
```tsx
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
```tsx
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:
```tsx
<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
```tsx
// 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
```typescript
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:
```tsx
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:
```tsx
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:
```tsx
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)
```tsx
<X0PayComponent
transactionParams={transactionParams}
onSuccess={onSuccess}
onError={onError}
/>
```
### Enable WalletConnect with Project ID
```tsx
<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
```tsx
<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:
```tsx
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:
```bash
cd X0-sdk
npm install
npm run dev
```
## Testing
The test app demonstrates the new fee calculation functionality:
```bash
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`