Skip to main content

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.

Los Intents son el corazón de pan API. Representan objetivos financieros de alto nivel en lugar de transacciones especificas. En lugar de decirle a pan exactamente que transacciones ejecutar, expresas lo que quieres lograr y pan determina la mejor manera de hacerlo.

¿Qué es un Intent?

Un intent es una declaracion de un objetivo financiero. Cuando creas un intent, le dices a pan que quieres lograr, no como lograrlo.

Enfoque Tradicional

// Especificas COMO hacerlo
await bridge(500, 'arbitrum', 'base');
await approve(usdc, aavePool);
await aavePool.supply(usdc, 500);

Enfoque Intent

// Especificas QUE quieres
await pan.lend({
  walletId: 'wallet_123',
  amount: 500,
  asset: 'USDC'
});
El sistema de pan automaticamente:
  1. Analiza el estado actual del wallet
  2. Evalua protocolos DeFi y oportunidades disponibles
  3. Genera un plan de ejecución optimizado
  4. Ejecuta el plan de forma segura
1

Tu App envia request

POST /intents con action: lend, amount: 1000 USDC
2

Planificación

pan consulta balances (500 ARB, 500 Base) y APYs (Base 8.5%, ARB 7.2%)
3

Generación de plan

Plan optimo: bridge ARB a Base + deposit en Aave
4

Ejecución

pan ejecuta bridge y deposit, retornando txHashes
5

Resultado

Intent completado con resultados y costos de gas

Tipos de Intent

Lend (Prestar)

Deposita fondos en un protocolo de lending para ganar intereses:
const intent = await pan.lend({
  walletId: 'pan_wallet_abc123',
  amount: 1000,
  asset: 'USDC'
  // chain es opcional - pan encuentra el mejor APY
});
Que hace pan:
  • Consulta APYs en todas las chains soportadas
  • Identifica donde están los fondos del wallet
  • Si es necesario, hace bridge a la chain con mejor APY
  • Deposita en el protocolo (Aave) automaticamente

Withdraw (Retirar)

Retira fondos de un protocolo de lending:
const intent = await pan.withdraw({
  walletId: 'pan_wallet_abc123',
  amount: 500,
  asset: 'USDC',
  chain: 'base' // requerido para withdraw
});

Bridge

Mueve fondos entre chains:
const intent = await pan.bridge({
  walletId: 'pan_wallet_abc123',
  amount: 500,
  asset: 'USDC',
  fromChain: 'ethereum',
  toChain: 'arbitrum'
});

Parámetros de Intent

Comunes a todos los intents

ParámetroTipoRequeridoDescripción
walletIdstringSiID de la wallet pan
actionstringSilend, withdraw, o bridge
amountnumberSiCantidad en unidades del token
assetstringNoToken a usar (default: USDC)

Específicos por accion

Lend:
ParámetroTipoRequeridoDescripción
chainstringNoChain destino. Si no se especifica, pan elige la mejor
Withdraw:
ParámetroTipoRequeridoDescripción
chainstringSiChain de donde retirar
Bridge:
ParámetroTipoRequeridoDescripción
fromChainstringSiChain origen
toChainstringSiChain destino

Ciclo de Vida de un Intent

Los intents pasan por estados bien definidos:
EstadoDescripciónSiguiente
pendingIntent creado y validadoplanning
planningAnalizando balances, consultando yields, generando planexecuting o failed
executingEjecutando pasos: bridges, depositscompleted o failed
completedTodas las transacciones confirmadasFinal
failedError registrado, fondos segurosFinal
1

Pending

El intent ha sido creado y registrado en el sistema. Este estado es muy breve.
{ "status": "pending" }
2

Planning

pan está analizando el wallet, evaluando protocolos, y generando el plan de ejecución optimo.
{
  "status": "planning",
  "executionPlan": null  // Aun no disponible
}
Que ocurre internamente:
  • Consulta balances del wallet en todas las chains
  • Obtiene APYs actuales de protocolos
  • Calcula rutas de bridge optimas
  • Estima costos de gas
  • Genera plan de ejecución
3

Executing

pan está ejecutando las transacciones en blockchain.
{
  "status": "executing",
  "executionPlan": {
    "strategy": "single-bridge",
    "steps": [
      { "type": "bridge", "status": "completed" },
      { "type": "deposit", "status": "executing" }
    ]
  },
  "results": {
    "completedSteps": 1,
    "transactions": [
      { "type": "bridge", "txHash": "0x123..." }
    ]
  }
}
4

Completed

Todas las operaciones completaron exitosamente.
{
  "status": "completed",
  "results": {
    "completedSteps": 2,
    "totalGasUsed": "350000",
    "totalGasCostUsd": 2.30,
    "finalAmount": "998.50",
    "apy": 8.52
  },
  "completedAt": "2024-01-15T10:45:30Z"
}
5

Failed

Algo salio mal durante la ejecución.
{
  "status": "failed",
  "error": {
    "code": "INSUFFICIENT_FUNDS",
    "message": "Wallet does not have sufficient USDC",
    "details": {
      "required": "1000 USDC",
      "available": "750 USDC"
    }
  },
  "results": {
    "completedSteps": 1,
    "failedStep": 2
  }
}

Monitorear Intents

La ejecución de intents es asincrona. Debes hacer polling para seguir el progreso:
async function esperarIntent(intentId) {
  const maxIntentos = 60; // 5 minutos
  let intentos = 0;

  while (intentos < maxIntentos) {
    const intent = await pan.getIntent(intentId);

    console.log(`Estado: ${intent.status}`);

    // Mostrar progreso si está ejecutando
    if (intent.status === 'executing' && intent.executionPlan) {
      const pasos = intent.executionPlan.steps;
      const completados = intent.results?.completedSteps || 0;
      console.log(`  Progreso: ${completados}/${pasos.length}`);

      // Mostrar transacciones completadas
      intent.results?.transactions?.forEach(tx => {
        console.log(`  ${tx.type}: ${tx.txHash}`);
      });
    }

    // Verificar estados finales
    if (intent.status === 'completed') {
      console.log('Intent completado!');
      console.log(`Gas total: $${intent.results.totalGasCostUsd}`);
      return intent;
    }

    if (intent.status === 'failed') {
      console.error('Intent fallido:', intent.error.message);
      throw new Error(intent.error.message);
    }

    // Esperar 5 segundos
    await new Promise(r => setTimeout(r, 5000));
    intentos++;
  }

  throw new Error('Timeout esperando intent');
}
Intervalo de polling recomendado: 5-10 segundos. Mas frecuente desperdicia recursos, menos frecuente reduce responsividad.

Estrategias de Ejecución

pan determina automáticamente la mejor estrategia basandose en el estado del wallet:
SituaciónEstrategiaPasos
Fondos ya en mejor chainno-bridgeDeposito directo
Fondos en una chain diferentesingle-bridge1 bridge + deposit
Fondos en múltiples chainsmulti-bridgeN bridges + deposit
Sin fondos suficientesinsufficientError: fondos insuficientes

no-bridge

Los fondos ya están en la chain destino. Deposito directo.
{
  "strategy": "no-bridge",
  "steps": [
    { "type": "deposit", "chain": "base", "amount": "1000" }
  ]
}

single-bridge

Los fondos están en una sola chain diferente. Un bridge + deposito.
{
  "strategy": "single-bridge",
  "steps": [
    { "type": "bridge", "from": "arbitrum", "to": "base", "amount": "1000" },
    { "type": "deposit", "chain": "base", "amount": "1000" }
  ]
}

multi-bridge

Los fondos están distribuidos en múltiples chains. Varios bridges + deposito.
{
  "strategy": "multi-bridge",
  "steps": [
    { "type": "bridge", "from": "ethereum", "to": "base", "amount": "200" },
    { "type": "bridge", "from": "arbitrum", "to": "base", "amount": "500" },
    { "type": "deposit", "chain": "base", "amount": "1000" }
  ]
}

insufficient

No hay fondos suficientes. El intent falla en planning.
{
  "status": "failed",
  "error": {
    "code": "INSUFFICIENT_FUNDS",
    "message": "Not enough USDC across all chains",
    "details": {
      "required": "1000",
      "available": "750"
    }
  }
}

Manejo de Errores

Errores Comunes

CódigoDescripciónSolución
INSUFFICIENT_FUNDSNo hay fondos suficientesDepositar más fondos
WALLET_NOT_FOUNDWallet no existeVerificar walletId
INVALID_CHAINChain no soportadaUsar chain válida
BRIDGE_FAILEDFallo en bridgeReintentar intent
DEPOSIT_FAILEDFallo en depósitoVerificar protocolo

Estructura de Error

{
  "error": {
    "code": "ERROR_CODE",
    "message": "Mensaje legible para humanos",
    "details": {
      "campo1": "valor1",
      "campo2": "valor2"
    }
  }
}

Reintentar Intents Fallidos

async function ejecutarConReintento(params, maxReintentos = 3) {
  let ultimoError;

  for (let i = 0; i < maxReintentos; i++) {
    try {
      const intent = await pan.lend(params);
      return await esperarIntent(intent.id);
    } catch (error) {
      ultimoError = error;

      // Solo reintentar errores transitorios
      const reintentables = ['BRIDGE_FAILED', 'NETWORK_ERROR', 'TIMEOUT'];
      if (!reintentables.includes(error.code)) {
        throw error;
      }

      console.log(`Reintento ${i + 1}/${maxReintentos}...`);
      await new Promise(r => setTimeout(r, 5000 * (i + 1))); // Backoff
    }
  }

  throw ultimoError;
}

Ejemplos Avanzados

Lending con Verificacion de APY

async function lendSiApy(walletId, amount, minApy) {
  // Obtener yields actuales
  const { rates, best } = await pan.yields.getAll();

  // Verificar APY minimo
  if (best.apy < minApy) {
    console.log(`APY actual (${best.apy}%) menor a mínimo (${minApy}%)`);
    return null;
  }

  // Crear intent
  const intent = await pan.lend({
    walletId,
    amount,
    asset: 'USDC'
  });

  console.log(`Lending a ${best.chain} con ${best.apy}% APY`);
  return intent;
}

// Uso: solo prestar si APY > 7%
await lendSiApy('wallet_123', 1000, 7.0);

Rebalanceo Automatico

async function rebalancearAMejorYield(walletId) {
  // 1. Obtener balances actuales
  const balancesResponse = await pan.wallet.getBalances(walletId);

  // 2. Calcular total disponible
  let totalUsdc = 0;
  for (const chainData of balancesResponse.chains) {
    const usdc = chainData.tokens.find(t => t.asset === 'USDC');
    if (usdc) totalUsdc += parseFloat(usdc.balanceFormatted);
  }

  if (totalUsdc === 0) {
    console.log('No hay USDC disponible');
    return;
  }

  // 3. Obtener mejor yield
  const { best } = await pan.yields.getAll();
  console.log(`Mejor yield: ${best.apy}% en ${best.chain}`);

  // 4. Crear intent de lending
  // pan automáticamente consolidara fondos de todas las chains
  const intent = await pan.lend({
    walletId,
    amount: totalUsdc,
    asset: 'USDC'
  });

  return intent;
}

Notificaciones de Progreso

async function ejecutarConNotificaciones(walletId, amount, onProgress) {
  const intent = await pan.lend({ walletId, amount, asset: 'USDC' });

  let ultimoEstado = null;
  let ultimosPasos = 0;

  while (true) {
    const actual = await pan.getIntent(intent.id);

    // Notificar cambio de estado
    if (actual.status !== ultimoEstado) {
      onProgress({
        type: 'status',
        status: actual.status,
        message: getStatusMessage(actual.status)
      });
      ultimoEstado = actual.status;
    }

    // Notificar pasos completados
    const pasosCompletados = actual.results?.completedSteps || 0;
    if (pasosCompletados > ultimosPasos) {
      const paso = actual.executionPlan.steps[pasosCompletados - 1];
      onProgress({
        type: 'step',
        step: paso,
        completed: pasosCompletados,
        total: actual.executionPlan.steps.length
      });
      ultimosPasos = pasosCompletados;
    }

    // Estado final
    if (actual.status === 'completed' || actual.status === 'failed') {
      return actual;
    }

    await new Promise(r => setTimeout(r, 5000));
  }
}

function getStatusMessage(status) {
  return {
    pending: 'Iniciando...',
    planning: 'Calculando mejor estrategia...',
    executing: 'Ejecutando transacciones...',
    completed: 'Completado!',
    failed: 'Error en ejecución'
  }[status];
}

// Uso
await ejecutarConNotificaciones('wallet_123', 1000, (progress) => {
  console.log(progress);
  // Enviar a UI, webhook, etc.
});

Próximos Pasos

Planes de Ejecución

Profundiza en como pan optimiza estrategias

Ejecutar Intents

Guía práctica paso a paso

Monitorear Estado

Mejores prácticas de monitoreo

Manejo de Errores

Como manejar errores correctamente