Skip to main content
Las wallets son el componente fundamental de Pan. Representan cuentas de usuario que funcionan en multiples blockchains con una sola direccion.

¿Qué es una Wallet en Pan?

Una wallet de Pan es una cuenta no-custodial que:
  • Una direccion, multiples chains: La misma direccion funciona en Ethereum, Arbitrum, Base, etc.
  • No-custodial: Tu no tienes acceso a las llaves privadas (gestionadas por Privy)
  • Ligada a un usuario: Cada wallet pertenece a un userId de tu aplicacion
  • Multi-token: Soporta multiples tokens por chain
ChainBalances
Ethereum200 USDC, 0.5 ETH
Arbitrum500 USDC, 0.1 ETH
Base300 USDC
Todos accesibles con la misma direccion 0x742d35Cc...
Una direccion, multiples chains: La misma direccion 0x742d35Cc... funciona en todas las redes EVM.

Crear una Wallet

curl -X POST https://api.pan.dev/v1/wallets \
  -H "Authorization: Bearer $PAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "usuario_maria_123",
    "chainType": "ethereum",
    "metadata": {
      "nombre": "Maria Garcia",
      "email": "[email protected]",
      "plan": "premium"
    }
  }'

Parametros

ParametroTipoRequeridoDescripcion
userIdstringSiID unico del usuario en tu aplicacion
chainTypestringNoTipo de chain: ethereum (default) o tron
emailstringNoEmail del usuario (para notificaciones)
metadataobjectNoDatos adicionales que quieras almacenar

Respuesta

{
  "id": "pan_wallet_a1b2c3d4e5f6",
  "userId": "usuario_maria_123",
  "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "chainType": "ethereum",
  "chains": [
    "ethereum",
    "ethereum-sepolia",
    "arbitrum",
    "arbitrum-sepolia",
    "base",
    "base-sepolia"
  ],
  "metadata": {
    "nombre": "Maria Garcia",
    "email": "[email protected]",
    "plan": "premium"
  },
  "createdAt": "2024-01-15T10:30:00Z"
}
userId debe ser unico. Si intentas crear una wallet con un userId que ya existe, recibiras un error. Usa el endpoint GET para recuperar wallets existentes.

Obtener una Wallet

curl -X GET "https://api.pan.dev/v1/wallets/usuario_maria_123" \
  -H "Authorization: Bearer $PAN_API_KEY"
El endpoint usa userId, no walletId. Esto facilita mapear usuarios de tu aplicacion a wallets de Pan.

Consultar Balances

Obtiene balances de todas las chains y tokens con una sola llamada:
curl -X GET "https://api.pan.dev/v1/balances/pan_wallet_a1b2c3d4e5f6" \
  -H "Authorization: Bearer $PAN_API_KEY"
{
  "walletId": "pan_wallet_a1b2c3d4e5f6",
  "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "chains": [
    {
      "chain": "ethereum",
      "tokens": [
        {
          "asset": "USDC",
          "balance": "200000000",
          "balanceFormatted": "200.00",
          "decimals": 6,
          "valueUsd": 200.00
        },
        {
          "asset": "ETH",
          "balance": "500000000000000000",
          "balanceFormatted": "0.50",
          "decimals": 18,
          "valueUsd": 1250.00
        }
      ]
    },
    {
      "chain": "arbitrum",
      "tokens": [
        {
          "asset": "USDC",
          "balance": "500000000",
          "balanceFormatted": "500.00",
          "decimals": 6,
          "valueUsd": 500.00
        }
      ]
    },
    {
      "chain": "base",
      "tokens": [
        {
          "asset": "USDC",
          "balance": "300000000",
          "balanceFormatted": "300.00",
          "decimals": 6,
          "valueUsd": 300.00
        }
      ]
    }
  ],
  "totalValueUsd": 2250.00
}

Estructura de Balance

Cada token en el balance incluye:
CampoDescripcion
assetSimbolo del token (USDC, ETH, etc.)
balanceBalance en unidades minimas (wei/smallest unit)
balanceFormattedBalance formateado con decimales
decimalsNumero de decimales del token
valueUsdValor en USD del balance

Chains Soportadas

Mainnet

ChainChain IDEstado
Ethereum1Proximo
Arbitrum One42161Proximo
Base8453Proximo

Testnet (Disponible ahora)

ChainChain IDEstado
Ethereum Sepolia11155111Activo
Arbitrum Sepolia421614Activo
Base Sepolia84532Activo
Actualmente Pan opera en testnets. Mainnet estara disponible pronto.

Tokens Soportados

USDC (Principal)

ChainDireccion
Ethereum0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Arbitrum0xaf88d065e77c8cC2239327C5EDb3A432268e5831
Base0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913

Otros Tokens

TokenEthereumArbitrumBase
USDTSiSiNo
DAISiSiNo
WETHSiSiSi

Como Funcionan las Wallets Multi-chain

Pan utiliza Privy para generar wallets. La magia de “una direccion, multiples chains” funciona porque:
  1. Derivacion Deterministica: La misma llave privada genera la misma direccion en todas las chains EVM
  2. Privy como Custodio Tecnico: Privy maneja las llaves de forma segura
  3. Tu Aplicacion No Tiene Acceso: Las llaves nunca salen de la infraestructura de Privy
1

Tu app llama a Pan

wallet.create({ userId: '123' })
2

Pan solicita wallet a Privy

Privy genera llave privada, deriva direccion, y la almacena encriptada
3

Pan guarda el mapeo

Se registra la relacion userId → walletId en la base de datos
4

Pan retorna la wallet

Tu app recibe { id, address, chains[] }
La llave privada nunca sale de Privy. Tu aplicacion solo recibe la direccion publica.

Arquitectura de Seguridad

CapaComponentesResponsabilidad
Tu AplicacionPan SDKEnvia requests con API Key
Pan APIWallet Service, Intent ServiceOrquesta operaciones
Privy (Custodio)Key Generation, Encrypted Storage, SignerGenera, almacena y firma
BlockchainsEthereum, Arbitrum, BaseReciben transacciones firmadas

Limites de Wallets

Los limites de wallets dependen de tu plan:
PlanWallets Maximas
Free100
Pro10,000
EnterpriseIlimitadas

Verificar Uso

// El limite se verifica automaticamente al crear
try {
  const wallet = await pan.wallet.create({ userId: 'nuevo_user' });
} catch (error) {
  if (error.code === 'WALLET_LIMIT_EXCEEDED') {
    console.log('Necesitas actualizar tu plan');
  }
}

Metadata

El campo metadata te permite almacenar datos adicionales con cada wallet:
const wallet = await pan.wallet.create({
  userId: 'usuario_123',
  metadata: {
    // Datos de tu aplicacion
    nombre: 'Juan Perez',
    email: '[email protected]',
    plan: 'premium',
    kyc_status: 'verified',
    referral_code: 'ABC123',

    // Cualquier dato serializable a JSON
    preferences: {
      currency: 'USD',
      language: 'es'
    }
  }
});
No almacenes datos sensibles (contrasenas, tokens de sesion, etc.) en metadata. Aunque estan almacenados de forma segura, es mejor practica mantenerlos separados.

Patrones Comunes

Crear Wallet al Registrarse

async function onUserSignup(user) {
  // Crear wallet de Pan junto con el registro
  const wallet = await pan.wallet.create({
    userId: user.id,
    metadata: {
      email: user.email,
      name: user.name,
      signupDate: new Date().toISOString()
    }
  });

  // Guardar walletId en tu base de datos
  await db.users.update(user.id, {
    panWalletId: wallet.id,
    panWalletAddress: wallet.address
  });

  return wallet;
}

Obtener o Crear Wallet

async function getOrCreateWallet(userId) {
  try {
    // Intentar obtener wallet existente
    return await pan.wallet.get(userId);
  } catch (error) {
    if (error.code === 'WALLET_NOT_FOUND') {
      // Crear si no existe
      return await pan.wallet.create({ userId });
    }
    throw error;
  }
}

Mostrar Balances al Usuario

async function getFormattedBalances(walletId) {
  const response = await pan.wallet.getBalances(walletId);

  const formatted = [];

  for (const chainData of response.chains) {
    for (const token of chainData.tokens) {
      if (parseFloat(token.balanceFormatted) > 0) {
        formatted.push({
          chain: formatChainName(chainData.chain),
          token: token.asset,
          amount: token.balanceFormatted,
          usd: `$${token.valueUsd.toFixed(2)}`
        });
      }
    }
  }

  return {
    items: formatted,
    total: `$${response.totalValueUsd.toFixed(2)}`
  };
}

function formatChainName(chain) {
  const names = {
    'ethereum': 'Ethereum',
    'ethereum-sepolia': 'Ethereum (Testnet)',
    'arbitrum': 'Arbitrum',
    'arbitrum-sepolia': 'Arbitrum (Testnet)',
    'base': 'Base',
    'base-sepolia': 'Base (Testnet)'
  };
  return names[chain] || chain;
}

Fondear Wallets

En Testnet (Demo)

Pan ofrece un endpoint para fondear wallets de prueba:
await fetch('https://api.pan.dev/v1/demo/fund', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    walletId: 'pan_wallet_abc123',
    chain: 'arbitrum-sepolia',
    amount: 1000 // USDC
  })
});

En Produccion

En produccion, los usuarios depositan fondos directamente a su direccion de wallet:
// Mostrar direccion para deposito
const wallet = await pan.wallet.get(userId);

return {
  message: 'Deposita fondos a esta direccion:',
  address: wallet.address,
  supportedChains: ['Ethereum', 'Arbitrum', 'Base'],
  supportedTokens: ['USDC', 'USDT', 'ETH']
};

Proximos Pasos