AgentSkillsCN

Bridge Transfers

借助Bridge.xyz API实现资金流动与转账编排。支持法币与加密货币之间的入金/出金通道,满足钱包间转账需求,以及支付渠道的灵活转换(ACH、电汇、SEPA、各类区块链网络)。适用场景包括:创建转账任务、实时追踪转账状态、处理各类支付渠道,以及完成跨币种兑换。

SKILL.md
--- frontmatter
name: Bridge Transfers
description: Money movement and transfer orchestration with Bridge.xyz API. Onramp/offramp between fiat and crypto, wallet-to-wallet transfers, payment rail conversion (ACH, Wire, SEPA, blockchain networks). Use for: creating transfers, tracking status, handling payment rails, and cross-currency conversions.

Bridge Transfers Orchestration

Quick Reference

typescript
type PaymentRail = 
  | 'ach_push' | 'ach' | 'wire'           // Fiat US
  | 'sepa'                                    // Fiat EU  
  | 'spei'                                    // Fiat Mexico
  | 'ethereum' | 'solana' | 'polygon' | 'base' | 'arbitrum' | 'tron'  // Crypto
  | 'bridge_wallet';                          // Bridge wallets

type TransferState = 'awaiting_funds' | 'completed' | 'failed' | 'pending';
type Currency = 'usd' | 'eur' | 'mxn' | 'usdc' | 'usdb';

Create Transfer (Onramp - Fiat to Crypto)

typescript
interface CreateTransferRequest {
  amount: string;
  on_behalf_of: string;
  developer_fee?: string;
  developer_fee_percent?: string;
  source: {
    payment_rail: PaymentRail;
    currency: Currency;
    from_address?: string;           // For crypto sources
  };
  destination: {
    payment_rail: PaymentRail;
    currency: Currency;
    to_address: string;               // Required for crypto destinations
    external_account_id?: string;     // For fiat destinations
  };
  features?: {
    flexible_amount?: boolean;        // Allow any deposit amount
  };
}

interface Transfer {
  id: string;
  client_reference_id?: string;
  state: TransferState;
  on_behalf_of: string;
  amount: string;
  developer_fee: string;
  source: {
    payment_rail: PaymentRail;
    currency: Currency;
    from_address?: string;
  };
  destination: {
    payment_rail: PaymentRail;
    currency: Currency;
    to_address?: string;
    external_account_id?: string;
  };
  source_deposit_instructions?: {
    payment_rail: PaymentRail;
    currency: Currency;
    amount?: string;
    from_address?: string;
    to_address?: string;
    bank_account_number?: string;
    bank_routing_number?: string;
    bank_beneficiary_name?: string;
    deposit_message?: string;
    iban?: string;
    bic?: string;
  };
  receipt?: {
    initial_amount: string;
    developer_fee: string;
    exchange_fee: string;
    subtotal_amount: string;
    gas_fee: string;
    final_amount: string;
    destination_tx_hash?: string;
    url?: string;
  };
  created_at: string;
  updated_at: string;
}

async function createTransfer(request: CreateTransferRequest): Promise<Transfer> {
  const response = await fetch(`${BRIDGE_API_URL}/transfers`, {
    method: 'POST',
    headers: {
      'Api-Key': API_KEY,
      'Idempotency-Key': crypto.randomUUID(),
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(request),
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Transfer creation failed: ${error.message}`);
  }

  return response.json();
}

USD ACH to USDC (Ethereum)

typescript
async function onrampUSDToCrypto(
  customerId: string,
  amount: string,
  cryptoAddress: string
): Promise<Transfer> {
  return createTransfer({
    amount,
    on_behalf_of: customerId,
    source: {
      payment_rail: 'ach_push',
      currency: 'usd',
    },
    destination: {
      payment_rail: 'ethereum',
      currency: 'usdc',
      to_address: cryptoAddress,
    },
  });
}

// Usage
const transfer = await onrampUSDToCrypto(
  'cust_alice',
  '1000.00',
  '0xdeadbeef'
);

console.log('Transfer ID:', transfer.id);
console.log('Status:', transfer.state);
console.log('Deposit Instructions:', transfer.source_deposit_instructions);

EUR SEPA to USDC (Solana)

typescript
async function onrampEURToCrypto(
  customerId: string,
  amount: string,
  solanaAddress: string
): Promise<Transfer> {
  return createTransfer({
    amount,
    on_behalf_of: customerId,
    source: {
      payment_rail: 'sepa',
      currency: 'eur',
    },
    destination: {
      payment_rail: 'solana',
      currency: 'usdc',
      to_address: solanaAddress,
    },
  });
}

Flexible Amount Onramp

typescript
async function flexibleOnramp(
  customerId: string,
  cryptoAddress: string,
  feePercent: string = '1.0'
): Promise<Transfer> {
  return createTransfer({
    on_behalf_of: customerId,
    source: {
      payment_rail: 'ach_push',
      currency: 'usd',
    },
    destination: {
      payment_rail: 'ethereum',
      currency: 'usdc',
      to_address: cryptoAddress,
    },
    developer_fee_percent: feePercent,
    features: {
      flexible_amount: true,  // Customer can send any amount
    },
  });
}

Offramp (Crypto to Fiat)

typescript
async function offrampCryptoToUSD(
  customerId: string,
  amount: string,
  externalAccountId: string,
  cryptoAddress: string
): Promise<Transfer> {
  return createTransfer({
    amount,
    on_behalf_of: customerId,
    source: {
      payment_rail: 'ethereum',
      currency: 'usdc',
      from_address: cryptoAddress,
    },
    destination: {
      payment_rail: 'ach',
      currency: 'usd',
      external_account_id: externalAccountId,
    },
  });
}

// Offrump with Tron USDT
async function offrampUSDTFromTron(
  customerId: string,
  amount: string,
  externalAccountId: string,
  tronAddress: string,
  blockchainMemo?: string
): Promise<Transfer> {
  return createTransfer({
    amount,
    on_behalf_of: customerId,
    source: {
      payment_rail: 'tron',
      currency: 'usdt',
      from_address: tronAddress,
    },
    destination: {
      payment_rail: 'ach',
      currency: 'usd',
      external_account_id: externalAccountId,
    },
  });
}

Wallet-to-Wallet Transfer

typescript
async function walletToWalletTransfer(
  customerId: string,
  amount: string,
  fromWalletId: string,
  toWalletId: string,
  chain: PaymentRail = 'solana'
): Promise<Transfer> {
  return createTransfer({
    amount,
    on_behalf_of: customerId,
    source: {
      payment_rail: 'bridge_wallet',
      currency: 'usdc',
      from_address: fromWalletId,  // Actually bridge_wallet_id
    },
    destination: {
      payment_rail: chain,
      currency: 'usdc',
      to_address: toWalletId,
    },
  });
}

// Multi-recipient payroll
async function processPayroll(
  employerCustomerId: string,
  employerWalletId: string,
  payments: { walletId: string; chain: PaymentRail; amount: string }[]
): Promise<Transfer[]> {
  const results: Transfer[] = [];

  for (const payment of payments) {
    const transfer = await walletToWalletTransfer(
      employerCustomerId,
      payment.amount,
      employerWalletId,
      payment.walletId,
      payment.chain
    );
    results.push(transfer);
  }

  return results;
}

List Transfers

typescript
interface ListTransfersParams {
  limit?: number;
  offset?: number;
  starting_after?: string;
  ending_before?: string;
  transfer_state?: TransferState;
  tx_hash?: string;
  updated_after_ms?: number;
  updated_before_ms?: number;
  template_id?: string;
}

async function listTransfers(
  customerId: string,
  params: ListTransfersParams = {}
): Promise<{ count: number; data: Transfer[] }> {
  const query = new URLSearchParams();
  
  if (params.limit) query.set('limit', params.limit.toString());
  if (params.offset) query.set('offset', params.offset.toString());
  if (params.transfer_state) query.set('transfer_state', params.transfer_state);
  if (params.starting_after) query.set('starting_after', params.starting_after);
  if (params.ending_before) query.set('ending_before', params.ending_before);

  const response = await fetch(
    `${BRIDGE_API_URL}/transfers?${query}`,
    {
      headers: { 'Api-Key': API_KEY },
    }
  );

  if (!response.ok) {
    throw new Error('Failed to list transfers');
  }

  return response.json();
}

// Usage
const transfers = await listTransfers('cust_alice', { limit: 10 });
console.log(`Found ${transfers.count} transfers`);
transfers.data.forEach(t => {
  console.log(`${t.id}: ${t.state} - ${t.amount} ${t.source.currency}`);
});

Transfer Tracking

typescript
class TransferTracker {
  async getTransfer(transferId: string): Promise<Transfer> {
    const response = await fetch(`${BRIDGE_API_URL}/transfers/${transferId}`, {
      headers: { 'Api-Key': API_KEY },
    });

    if (!response.ok) {
      throw new Error(`Transfer not found: ${transferId}`);
    }

    return response.json();
  }

  async waitForCompletion(transferId: string, maxAttempts: number = 30): Promise<Transfer> {
    for (let i = 0; i < maxAttempts; i++) {
      const transfer = await this.getTransfer(transferId);
      
      if (transfer.state === 'completed') {
        return transfer;
      }
      
      if (transfer.state === 'failed') {
        throw new Error(`Transfer failed: ${transferId}`);
      }

      await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds
    }

    throw new Error('Transfer pending - timeout');
  }

  generateReceipt(transfer: Transfer): string {
    if (!transfer.receipt) {
      return 'Receipt not available';
    }

    return `
Transfer Receipt
=================
ID: ${transfer.id}
Status: ${transfer.state}
Date: ${transfer.created_at}

Amount: ${transfer.amount} ${transfer.source.currency}
Developer Fee: ${transfer.receipt.developer_fee}
Exchange Fee: ${transfer.receipt.exchange_fee}
Gas Fee: ${transfer.receipt.gas_fee}

Final Amount: ${transfer.receipt.final_amount} ${transfer.destination.currency}
${transfer.receipt.destination_tx_hash ? `Tx Hash: ${transfer.receipt.destination_tx_hash}` : ''}

View Full Receipt: ${transfer.receipt.url}
    `.trim();
  }
}

Cross-Border Payment Flow

typescript
interface CrossBorderPayment {
  senderCustomerId: string;
  senderCurrency: 'usd' | 'eur' | 'mxn';
  recipientCryptoAddress: string;
  amount: string;
}

async function processCrossBorderPayment(payment: CrossBorderPayment): Promise<Transfer> {
  const paymentRail = payment.senderCurrency === 'eur' ? 'sepa' : 
                      payment.senderCurrency === 'mxn' ? 'spei' : 'ach_push';

  return createTransfer({
    amount: payment.amount,
    on_behalf_of: payment.senderCustomerId,
    source: {
      payment_rail: paymentRail,
      currency: payment.senderCurrency,
    },
    destination: {
      payment_rail: 'ethereum',
      currency: 'usdc',
      to_address: payment.recipientCryptoAddress,
    },
  });
}

// Complete remittance service
class RemittanceService {
  async sendFromUSA(senderId: string, amount: string, recipientEth: string) {
    return createTransfer({
      amount,
      on_behalf_of: senderId,
      source: { payment_rail: 'ach_push', currency: 'usd' },
      destination: { payment_rail: 'ethereum', currency: 'usdc', to_address: recipientEth },
    });
  }

  async sendFromEurope(senderId: string, amount: string, recipientEth: string) {
    return createTransfer({
      amount,
      on_behalf_of: senderId,
      source: { payment_rail: 'sepa', currency: 'eur' },
      destination: { payment_rail: 'ethereum', currency: 'usdc', to_address: recipientEth },
    });
  }

  async sendFromMexico(senderId: string, amount: string, recipientEth: string) {
    return createTransfer({
      amount,
      on_behalf_of: senderId,
      source: { payment_rail: 'spei', currency: 'mxn' },
      destination: { payment_rail: 'ethereum', currency: 'usdc', to_address: recipientEth },
    });
  }
}

Transfer Templates

typescript
interface TransferTemplate {
  id: string;
  state: TransferState;
  on_behalf_of: string;
  source: { payment_rail: PaymentRail; currency: Currency };
  destination: { payment_rail: PaymentRail; currency: Currency; to_address?: string };
  features: { static_template: boolean; flexible_amount?: boolean };
}

async function listTemplates(customerId: string): Promise<TransferTemplate[]> {
  const response = await fetch(`${BRIDGE_API_URL}/transfer_templates?on_behalf_of=${customerId}`, {
    headers: { 'Api-Key': API_KEY },
  });

  if (!response.ok) {
    throw new Error('Failed to list templates');
  }

  const data = await response.json();
  return data.transfer_templates || [];
}

Error Handling

typescript
class TransferError extends Error {
  constructor(
    message: string,
    public transferId?: string,
    public state?: TransferState,
    public code?: string
  ) {
    super(message);
    this.name = 'TransferError';
  }
}

async function handleTransferError(error: unknown): Promise<TransferError> {
  if (error instanceof TransferError) {
    return error;
  }

  const bridgeError = error as { message?: string; code?: string };
  
  return new TransferError(
    bridgeError.message || 'Unknown transfer error',
    undefined,
    undefined,
    bridgeError.code
  );
}

// Retry logic
async function retryTransfer<T>(
  operation: () => Promise<T>,
  maxRetries: number = 3,
  delayMs: number = 1000
): Promise<T> {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await operation();
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      
      const transferError = error as { code?: string };
      
      // Don't retry client errors
      if (transferError.code === 'invalid_request') {
        throw error;
      }

      await new Promise(resolve => setTimeout(resolve, delayMs * (i + 1)));
    }
  }
  
  throw new Error('Unexpected retry state');
}

Webhook Events

  • transfer.created - Transfer initiated
  • transfer.state_updated - Transfer state changed
  • transfer.completed - Transfer finished successfully
  • transfer.failed - Transfer failed

Best Practices

  1. Always use Idempotency-Key - Prevents duplicate transfers
  2. Store transfer IDs - Essential for tracking and support
  3. Implement webhooks - More reliable than polling
  4. Validate addresses - Check crypto addresses before sending
  5. Handle fees - Account for developer fees in calculations
  6. Support multiple rails - Different regions need different payment methods