> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pan.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Wallets

> Todo sobre wallets multi-chain en pan API

Las wallets son el componente fundamental de pan. Representan cuentas de usuario que funcionan en múltiples blockchains con una sola dirección.

## ¿Qué es una Wallet en pan?

Una wallet de pan es una cuenta no-custodial que:

* **Una dirección, múltiples chains**: La misma dirección 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 aplicación
* **Multi-token**: Soporta múltiples tokens por chain

| Chain    | Balances          |
| -------- | ----------------- |
| Ethereum | 200 USDC, 0.5 ETH |
| Arbitrum | 500 USDC, 0.1 ETH |
| Base     | 300 USDC          |

Todos accesibles con la misma dirección `0x742d35Cc...`

<Info>
  **Una dirección, múltiples chains**: La misma dirección `0x742d35Cc...` funciona en todas las redes EVM.
</Info>

## Crear una Wallet

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.pan.tech/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": "maria@ejemplo.com",
        "plan": "premium"
      }
    }'
  ```

  ```javascript JavaScript theme={null}
  const wallet = await pan.wallet.create({
    userId: 'usuario_maria_123',
    chainType: 'ethereum', // opcional, default: 'ethereum'
    metadata: {
      nombre: 'Maria Garcia',
      email: 'maria@ejemplo.com',
      plan: 'premium'
    }
  });
  ```

  ```python Python theme={null}
  wallet = requests.post(
      'https://api.pan.tech/v1/wallets',
      headers={'Authorization': f'Bearer {API_KEY}'},
      json={
          'userId': 'usuario_maria_123',
          'metadata': {
              'nombre': 'Maria Garcia',
              'email': 'maria@ejemplo.com'
          }
      }
  ).json()
  ```
</CodeGroup>

### Parámetros

| Parámetro   | Tipo   | Requerido | Descripción                                  |
| ----------- | ------ | --------- | -------------------------------------------- |
| `userId`    | string | Si        | ID único del usuario en tu aplicación        |
| `chainType` | string | No        | Tipo de chain: `ethereum` (default) o `tron` |
| `email`     | string | No        | Email del usuario (para notificaciones)      |
| `metadata`  | object | No        | Datos adicionales que quieras almacenar      |

### Respuesta

<ResponseExample>
  ```json theme={null}
  {
    "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": "maria@ejemplo.com",
      "plan": "premium"
    },
    "createdAt": "2024-01-15T10:30:00Z"
  }
  ```
</ResponseExample>

<Note>
  **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.
</Note>

## Obtener una Wallet

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.pan.tech/v1/wallets/usuario_maria_123" \
    -H "Authorization: Bearer $PAN_API_KEY"
  ```

  ```javascript JavaScript theme={null}
  const wallet = await pan.wallet.get('usuario_maria_123');
  ```
</CodeGroup>

<Tip>
  El endpoint usa `userId`, no `walletId`. Esto facilita mapear usuarios de tu aplicación a wallets de pan.
</Tip>

## Consultar Balances

Obtiene balances de todas las chains y tokens con una sola llamada:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.pan.tech/v1/balances/pan_wallet_a1b2c3d4e5f6" \
    -H "Authorization: Bearer $PAN_API_KEY"
  ```

  ```javascript JavaScript theme={null}
  const balances = await pan.wallet.getBalances('pan_wallet_a1b2c3d4e5f6');

  // Acceder a balances por chain
  const arbitrumChain = balances.chains.find(c => c.chain === 'arbitrum');
  console.log('Arbitrum:', arbitrumChain?.tokens);
  console.log('Total USD:', balances.totalValueUsd);
  ```
</CodeGroup>

<ResponseExample>
  ```json theme={null}
  {
    "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
  }
  ```
</ResponseExample>

### Estructura de Balance

Cada token en el balance incluye:

| Campo              | Descripción                                     |
| ------------------ | ----------------------------------------------- |
| `asset`            | Símbolo del token (USDC, ETH, etc.)             |
| `balance`          | Balance en unidades mínimas (wei/smallest unit) |
| `balanceFormatted` | Balance formateado con decimales                |
| `decimals`         | Numero de decimales del token                   |
| `valueUsd`         | Valor en USD del balance                        |

## Chains Soportadas

### Mainnet

| Chain        | Chain ID | Estado  |
| ------------ | -------- | ------- |
| Ethereum     | 1        | Próximo |
| Arbitrum One | 42161    | Próximo |
| Base         | 8453     | Próximo |

### Testnet (Disponible ahora)

| Chain            | Chain ID | Estado |
| ---------------- | -------- | ------ |
| Ethereum Sepolia | 11155111 | Activo |
| Arbitrum Sepolia | 421614   | Activo |
| Base Sepolia     | 84532    | Activo |

<Note>
  Actualmente pan opera en testnets. Mainnet estará disponible pronto.
</Note>

## Tokens Soportados

### USDC (Principal)

| Chain    | Dirección                                    |
| -------- | -------------------------------------------- |
| Ethereum | `0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48` |
| Arbitrum | `0xaf88d065e77c8cC2239327C5EDb3A432268e5831` |
| Base     | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` |

### Otros Tokens

| Token | Ethereum | Arbitrum | Base |
| ----- | -------- | -------- | ---- |
| USDT  | Si       | Si       | No   |
| DAI   | Si       | Si       | No   |
| WETH  | Si       | Si       | Si   |

## Como Funciónan las Wallets Multi-chain

pan utiliza Privy para generar wallets. La magia de "una dirección, múltiples chains" funciona porque:

1. **Derivación Determinística**: La misma llave privada genera la misma dirección 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

<Steps>
  <Step title="Tu app llama a pan">
    `wallet.create({ userId: '123' })`
  </Step>

  <Step title="pan solicita wallet a Privy">
    Privy genera llave privada, deriva dirección, y la almacena encriptada
  </Step>

  <Step title="pan guarda el mapeo">
    Se registra la relacion userId → walletId en la base de datos
  </Step>

  <Step title="pan retorna la wallet">
    Tu app recibe `{ id, address, chains[] }`
  </Step>
</Steps>

<Warning>
  La llave privada **nunca** sale de Privy. Tu aplicación solo recibe la dirección publica.
</Warning>

### Arquitectura de Seguridad

| Capa                 | Componentes                               | Responsabilidad                |
| -------------------- | ----------------------------------------- | ------------------------------ |
| **Tu Aplicacion**    | pan SDK                                   | Envia requests con API Key     |
| **pan API**          | Wallet Service, Intent Service            | Orquesta operaciones           |
| **Privy (Custodio)** | Key Generation, Encrypted Storage, Signer | Genera, almacena y firma       |
| **Blockchains**      | Ethereum, Arbitrum, Base                  | Reciben transacciones firmadas |

## Limites de Wallets

Los límites de wallets dependen de tu plan:

| Plan       | Wallets Maximas |
| ---------- | --------------- |
| Free       | 100             |
| Pro        | 10,000          |
| Enterprise | Ilimitadas      |

### Verificar Uso

```javascript theme={null}
// El límite se verifica automáticamente 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:

```javascript theme={null}
const wallet = await pan.wallet.create({
  userId: 'usuario_123',
  metadata: {
    // Datos de tu aplicación
    nombre: 'Juan Perez',
    email: 'juan@ejemplo.com',
    plan: 'premium',
    kyc_status: 'verified',
    referral_code: 'ABC123',

    // Cualquier dato serializable a JSON
    preferences: {
      currency: 'USD',
      language: 'es'
    }
  }
});
```

<Warning>
  No almacenes datos sensibles (contrasenas, tokens de sesion, etc.) en metadata. Aunque están almacenados de forma segura, es mejor práctica mantenerlos separados.
</Warning>

## Patrones Comunes

### Crear Wallet al Registrarse

```javascript theme={null}
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

```javascript theme={null}
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

```javascript theme={null}
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:

```javascript theme={null}
await fetch('https://api.pan.tech/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 dirección de wallet:

```javascript theme={null}
// Mostrar dirección para deposito
const wallet = await pan.wallet.get(userId);

return {
  message: 'Deposita fondos a está dirección:',
  address: wallet.address,
  supportedChains: ['Ethereum', 'Arbitrum', 'Base'],
  supportedTokens: ['USDC', 'USDT', 'ETH']
};
```

## Próximos Pasos

<CardGroup cols={2}>
  <Card title="Consultar Balances" icon="wallet" href="/guias/consultar-balances">
    Guía detallada sobre consulta de balances
  </Card>

  <Card title="Intents" icon="target" href="/guias/conceptos/intents">
    Aprende sobre operaciones basadas en intents
  </Card>

  <Card title="Crear Wallets API" icon="terminal" href="/api/wallets/crear-wallet">
    Referencia completa del endpoint
  </Card>

  <Card title="Seguridad" icon="shield" href="/guias/mejores-practicas/seguridad">
    Mejores prácticas de seguridad
  </Card>
</CardGroup>
