// send-guard.mts: call APEX's send guard before every USDC or token send on Arc. Node 20+. Official x402 client.
// npm install @x402/fetch@2.28.0 @x402/evm@2.28.0 viem      run: PAYER_KEY=0x... node send-guard.mts
// $0.001 per check, paid in USDC on Arc (no gas needed). Docs: https://apexfaucet.xyz/llms.txt   Fixtures for CI mocks:
// https://apexfaucet.xyz/arc/send-guard-fixtures.json
import { x402Client, wrapFetchWithPayment } from '@x402/fetch'
import { registerExactEvmScheme } from '@x402/evm/exact/client'
import { privateKeyToAccount } from 'viem/accounts'

const client = new x402Client()
registerExactEvmScheme(client, { signer: privateKeyToAccount(process.env.PAYER_KEY as `0x${string}`), networks: ['eip155:5042'] })
const payFetch = wrapFetchWithPayment(fetch, client)

// Reason keys: lookalike, poison-bait, token-contract, burn, sanctioned, usdc-blacklisted, impostor-token, not-a-token (stop);
// contract, fresh, self, history-unread, sanctions-unread, token-unread (check); known (info). Each reason: { level, key, message }.
export async function sendGuard({ from, to, token }: { from: string; to: string; token?: string }) {
  const q = new URLSearchParams({ from, to, ...(token ? { token } : {}) })
  const res = await payFetch('https://apexfaucet.xyz/api/x402/arc-send-guard?' + q)
  const body = await res.json().catch(() => null)
  const g = body && (body.data ?? body)
  // Fail closed: a guard that could not be paid or read is not an "ok".
  if (!res.ok || !g || !g.verdict) {
    const pr = res.headers.get('payment-required')   // on a payment refusal the reason is here, e.g. insufficient_funds
    const why = pr ? JSON.parse(Buffer.from(pr, 'base64').toString()).error : (body && body.error) || res.status
    throw new Error('send guard unavailable (' + why + '): do not send until it answers')
  }
  return { verdict: g.verdict as 'stop' | 'check' | 'ok', reasons: g.reasons as { level: string; key: string; message: string }[] }
}

// Example: today's real poisoning attack on Arc (9 Oct 2026). A wallet about to "send to" the lookalike planted in its history.
const { verdict, reasons } = await sendGuard({ from: '0x6cf1329447dbfeae5ff2b922b693eb9518c3c9a0', to: '0x024b820fe19d85a4558ac38cac83ac231070700c' })
if (verdict === 'stop') console.log('DO NOT SEND:', reasons.filter((r) => r.level === 'stop').map((r) => r.key + ': ' + r.message))
else console.log(verdict, reasons)
