AgentSkillsCN

Bridge Cards

通过Bridge.xyz API进行卡片的开通与管理。您可以创建与加密钱包绑定的虚拟卡和实体Visa卡,在全球范围内支持稳定币支付。适用场景包括:开通卡片、管理卡片账户、自定义卡片设计,以及实现加密货币与法币之间的便捷支付。

SKILL.md
--- frontmatter
name: Bridge Cards
description: Card provisioning and management with Bridge.xyz API. Create virtual and physical Visa cards linked to crypto wallets, enable stablecoin spending globally. Use for: provisioning cards, managing card accounts, card design customization, and crypto-to-fiat spending.

Bridge Cards Management

Quick Reference

typescript
type CardChain = 'solana' | 'ethereum' | 'polygon' | 'base' | 'arbitrum';
type CardCurrency = 'usdc' | 'usdb';
type CardStatus = 'active' | 'pending' | 'inactive' | 'frozen';
type CardDesign = string;

Provision Card Account

typescript
interface CreateCardRequest {
  client_reference_id?: string;
  currency: CardCurrency;
  chain: CardChain;
  crypto_account: {
    type: 'bridge_wallet' | 'standard';
    address: string;
  };
  card_design_shortname?: CardDesign;
}

interface CardAccount {
  id: string;
  client_reference_id?: string;
  customer_id: string;
  cardholder_name: {
    first_name: string;
    middle_name?: string;
    last_name: string;
  };
  card_image_url: string;
  status: CardStatus;
  status_reason?: string;
  card_details: {
    last_4: string;
    expiry: string;  // MM/YY
    bin: string;
    pin_status: 'not_set' | 'set';
  };
  balances: {
    available: { amount: string; currency: CardCurrency };
    hold: { amount: string; currency: CardCurrency };
  };
  freezes: {
    card_account_id: string;
    reason: 'lost_or_stolen' | 'fraud' | 'other';
    reason_detail?: string;
    starting_at?: string;
    ending_at?: string;
    created_at?: string;
  }[];
  crypto_account: {
    type: string;
    address: string;
  };
  funding_instructions: {
    currency: CardCurrency;
    chain: CardChain;
    address: string;
    memo?: string;
  };
  additional_funding_instructions?: {
    currency: CardCurrency;
    chain: CardChain;
    address: string;
    memo?: string;
  }[];
}

async function provisionCard(
  customerId: string,
  request: CreateCardRequest
): Promise<CardAccount> {
  const response = await fetch(`${BRIDGE_API_URL}/customers/${customerId}/card_accounts`, {
    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(`Card provisioning failed: ${error.message}`);
  }

  return response.json();
}

Basic Card Provisioning

typescript
async function createBasicCard(
  customerId: string,
  walletAddress: string,
  chain: CardChain = 'solana'
): Promise<CardAccount> {
  return provisionCard(customerId, {
    currency: 'usdc',
    chain,
    crypto_account: {
      type: 'bridge_wallet',
      address: walletAddress,
    },
  });
}

// Usage
const card = await createBasicCard(
  'cust_alice',
  '7bHbB8RwQgyNgxXZx8Q2kNzjEkmyv9Kb1DKZa63K3CtB',
  'solana'
);

console.log('Card ID:', card.id);
console.log('Last 4:', card.card_details.last_4);
console.log('Expiry:', card.card_details.expiry);
console.log('Status:', card.status);
console.log('Available Balance:', card.balances.available);

Card with Custom Design

typescript
async function createCustomDesignCard(
  customerId: string,
  walletAddress: string,
  designShortname: string
): Promise<CardAccount> {
  return provisionCard(customerId, {
    currency: 'usdc',
    chain: 'solana',
    crypto_account: {
      type: 'bridge_wallet',
      address: walletAddress,
    },
    card_design_shortname: designShortname,
  });
}

// Available designs would be fetched from Bridge
const designs = ['default', 'metallic', 'minimal', 'premium'];

Fund Card Account

typescript
interface FundCardRequest {
  amount: string;
  on_behalf_of: string;
  source: {
    payment_rail: 'ach_push' | 'wire' | 'sepa';
    currency: 'usd' | 'eur';
  };
  destination: {
    payment_rail: 'card';  // Special rail for cards
    currency: CardCurrency;
    card_account_id: string;
  };
}

async function fundCard(request: FundCardRequest): 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(`Card funding failed: ${error.message}`);
  }

  return response.json();
}

// Fund card from USD bank account
async function addFundsToCard(
  customerId: string,
  cardId: string,
  amount: string,
  walletAddress: string
): Promise<Transfer> {
  return fundCard({
    amount,
    on_behalf_of: customerId,
    source: {
      payment_rail: 'ach_push',
      currency: 'usd',
    },
    destination: {
      payment_rail: 'card',
      currency: 'usdc',
      card_account_id: cardId,
    },
  });
}

Card Management

typescript
class CardManager {
  async freezeCard(cardId: string, reason: 'lost_or_stolen' | 'fraud' = 'lost_or_stolen'): Promise<CardAccount> {
    const response = await fetch(`${BRIDGE_API_URL}/card_accounts/${cardId}/freezes`, {
      method: 'POST',
      headers: {
        'Api-Key': API_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        reason,
        starting_at: new Date().toISOString(),
      }),
    });

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

    return response.json();
  }

  async unfreezeCard(cardId: string, freezeId: string): Promise<CardAccount> {
    const response = await fetch(
      `${BRIDGE_API_URL}/card_accounts/${cardId}/freezes/${freezeId}`,
      {
        method: 'DELETE',
        headers: { 'Api-Key': API_KEY },
      }
    );

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

    return response.json();
  }

  async getCard(cardId: string): Promise<CardAccount> {
    const response = await fetch(`${BRIDGE_API_URL}/card_accounts/${cardId}`, {
      headers: { 'Api-Key': API_KEY },
    });

    if (!response.ok) {
      throw new Error('Card not found');
    }

    return response.json();
  }

  async listCustomerCards(customerId: string): Promise<CardAccount[]> {
    const response = await fetch(`${BRIDGE_API_URL}/customers/${customerId}/card_accounts`, {
      headers: { 'Api-Key': API_KEY },
    });

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

    return response.json();
  }
}

Complete Card Service

typescript
interface CreateCardRequest {
  customerId: string;
  walletAddress: string;
  chain?: CardChain;
  currency?: CardCurrency;
  design?: string;
  initialFunding?: {
    amount: string;
    bankAccountId: string;
  };
}

class CardService {
  async createAndFundCard(request: CreateCardRequest): Promise<{
    card: CardAccount;
    fundingTransfer?: Transfer;
  }> {
    // 1. Create the card
    const card = await provisionCard(request.customerId, {
      currency: request.currency || 'usdc',
      chain: request.chain || 'solana',
      crypto_account: {
        type: 'bridge_wallet',
        address: request.walletAddress,
      },
      card_design_shortname: request.design,
    });

    // 2. Fund if requested
    let fundingTransfer: Transfer | undefined;
    if (request.initialFunding) {
      fundingTransfer = await fundCard({
        amount: request.initialFunding.amount,
        on_behalf_of: request.customerId,
        source: {
          payment_rail: 'ach_push',
          currency: 'usd',
          external_account_id: request.initialFunding.bankAccountId,
        },
        destination: {
          payment_rail: 'card',
          currency: request.currency || 'usdc',
          card_account_id: card.id,
        },
      });
    }

    return { card, fundingTransfer };
  }

  async replaceLostCard(customerId: string, oldCardId: string): Promise<CardAccount> {
    const oldCard = await this.getCard(oldCardId);
    
    // Freeze old card
    await this.freezeCard(oldCardId, 'lost_or_stolen');

    // Create new card with same wallet
    return provisionCard(customerId, {
      currency: oldCard.balances.available.currency,
      chain: oldCard.crypto_account.address.startsWith('0x') ? 'ethereum' : 'solana',
      crypto_account: {
        type: oldCard.crypto_account.type,
        address: oldCard.crypto_account.address,
      },
    });
  }
}

Multi-Card Strategy

typescript
class MultiCardStrategy {
  // Create different cards for different spending purposes
  async setupExpenseCards(
    customerId: string,
    walletAddress: string
  ): Promise<{ dining: CardAccount; travel: CardAccount; daily: CardAccount }> {
    const [dining, travel, daily] = await Promise.all([
      provisionCard(customerId, {
        currency: 'usdc',
        chain: 'solana',
        crypto_account: { type: 'bridge_wallet', address: walletAddress },
        card_design_shortname: 'dining',
      }),
      provisionCard(customerId, {
        currency: 'usdc',
        chain: 'solana',
        crypto_account: { type: 'bridge_wallet', address: walletAddress },
        card_design_shortname: 'travel',
      }),
      provisionCard(customerId, {
        currency: 'usdc',
        chain: 'solana',
        crypto_account: { type: 'bridge_wallet', address: walletAddress },
        card_design_shortname: 'daily',
      }),
    ]);

    return { dining, travel, daily };
  }

  // Allocate budget to cards
  async allocateBudget(
    customerId: string,
    cardId: string,
    monthlyBudget: string
  ): Promise<void> {
    // Store budget allocation in your system
    // Monitor spending via webhooks
  }
}

Card Dashboard

typescript
interface CardDashboard {
  totalCards: number;
  totalAvailableBalance: string;
  cards: {
    id: string;
    last4: string;
    status: CardStatus;
    balance: string;
    chain: CardChain;
  }[];
}

async function getCardDashboard(customerId: string): Promise<CardDashboard> {
  const cards = await new CardManager().listCustomerCards(customerId);

  return {
    totalCards: cards.length,
    totalAvailableBalance: cards
      .reduce((sum, c) => sum + parseFloat(c.balances.available.amount), 0)
      .toFixed(2),
    cards: cards.map(c => ({
      id: c.id,
      last4: c.card_details.last_4,
      status: c.status,
      balance: c.balances.available.amount,
      chain: c.crypto_account.address.startsWith('0x') ? 'ethereum' : 'solana',
    })),
  };
}

Webhook Events

  • card_account.created - New card provisioned
  • card_account.status_updated - Card status changed
  • card_account.freeze_created - Card was frozen
  • card_account.freeze_removed - Card was unfrozen
  • card_transaction.completed - Purchase completed

Best Practices

  1. One currency per card - Cannot change after creation
  2. One chain per card - Cannot change after creation
  3. Freeze immediately - If card is lost
  4. Multiple funding sources - Support various chains
  5. Webhook monitoring - Track transactions in real-time
  6. Balance alerts - Notify when balance is low