Skip to main content

Por que o controle de orçamento é importante

Um agente de IA chamando APIs pagas em loop pode acumular custos rapidamente. O controle de orçamento permite:
  • Limitar o gasto total por sessão
  • Definir limites por domínio (ex.: máx. 100 sats/sessão em api.weather.com)
  • Receber um callback antes de cada pagamento
  • Obter um relatório completo de gastos a qualquer momento

Orçamento global

import { L402Client, BlinkWallet } from "l402-kit";

const client = new L402Client({
  wallet: new BlinkWallet(process.env.BLINK_API_KEY!, process.env.BLINK_WALLET_ID!),
  budgetSats: 500, // max 500 sats total this session
});
Quando uma resposta 402 inclui um campo priceSats e ele excederia o orçamento restante, o cliente lança BudgetExceededError antes de pagar — nenhum satoshi é gasto.

Orçamento por domínio

const client = new L402Client({
  wallet,
  budgetSats: 2000,
  budgetPerDomain: {
    "api.weather.com": 100,
    "api.finance.com": 500,
  },
});
Os limites por domínio são verificados de forma independente do limite global — ambos devem ser aprovados para que o pagamento prossiga.

Callbacks

const client = new L402Client({
  wallet,
  budgetSats: 1000,
  onSpend: (sats, url) => {
    console.log(`✓ Paid ${sats} sats → ${url}`);
    // log to your telemetry, update a dashboard, etc.
  },
  onBudgetExceeded: (url, sats) => {
    console.warn(`✗ Blocked: ${sats} sats requested by ${url} — budget exhausted`);
    // alert, notify Slack, etc.
  },
});
onBudgetExceeded / on_budget_exceeded é chamado imediatamente antes de BudgetExceededError ser lançado — útil para logs ou alertas.

Relatório de gastos

const report = client.spendingReport();

if (report) {
  console.log(`Total spent: ${report.total} sats`);
  console.log(`Remaining:   ${report.remaining} sats`);
  console.log("By domain:", report.byDomain);
  // { "api.weather.com": 42, "api.finance.com": 105 }

  for (const tx of report.transactions) {
    console.log(`  ${tx.ts}  ${tx.sats} sats  ${tx.url}`);
  }
}
spendingReport() retorna null / None quando nenhum orçamento está configurado.

Tratando BudgetExceededError

import { BudgetExceededError } from "l402-kit";

try {
  const res = await client.fetch("https://api.example.com/premium");
} catch (err) {
  if (err instanceof BudgetExceededError) {
    console.log(`Need ${err.required} sats, only ${err.remaining} remaining`);
    // gracefully degrade — return cached data, skip this step, etc.
  }
}

Notas sobre concorrência

Não compartilhe uma única instância de L402Client entre chamadas Promise.all concorrentes quando os limites de orçamento forem importantes.BudgetTracker.check() e record() são separados por um await (o pagamento Lightning). Duas chamadas client.fetch() concorrentes para endpoints diferentes podem ambas passar pela verificação de orçamento antes que qualquer uma registre o gasto — o que significa que o custo combinado pode exceder temporariamente seu limite de orçamento em um pagamento.Padrão seguro — chamadas sequenciais:
for (const url of urls) {
  const res = await client.fetch(url); // awaited one at a time
}
Padrão arriscado — chamadas paralelas:
// Both may pass budget.check() before either calls budget.record()
const results = await Promise.all(urls.map(url => client.fetch(url)));
Mitigação para cargas de trabalho paralelas: defina seu budgetSats de forma conservadora (ex.: 80% do seu limite real) para absorver o gasto excedente de um pagamento concorrente. Para aplicação estrita, processe as chamadas sequencialmente.

Referência completa de opções

OpçãoTypeScriptPythonPadrãoDescrição
Orçamento globalbudgetSatsbudget_satsilimitadoMáximo de sats para a sessão
Por domíniobudgetPerDomainbudget_per_domain{}Mapa de domínio → máx. sats
Hook de gastoonSpendon_spendChamado após cada pagamento
Hook de limite excedidoonBudgetExceededon_budget_exceededChamado antes de lançar exceção