Desarrollo local
Cadenas EVM locales que emulan las testnets públicas, datos de demo a través del pipeline real y las dos suites de aceptación.
Última actualización 27 oct 2026
Necesitás Docker (Postgres + Redis), Bun y Foundry para anvil (brew install foundry, o curl -L https://foundry.paradigm.xyz | bash && foundryup).
Cadenas locales: bun run chain:dev
apps/server/scripts/chain/dev.ts levanta un anvil por red de test con el chainId real (Polygon Amoy 80002 en :18002, BSC Testnet 97 en :18097, Base Sepolia 84532 en :18532) y planta una stablecoin mock en cada dirección de token canónica con anvil_setCode. El servidor corre el mismo registry y los mismos caminos de código que usa en las testnets públicas; solo cambia la URL del RPC.
- Las cuentas por defecto de anvil #1–#3 son los compradores: cada una tiene 1,000,000 de cada token en cada cadena.
- La hot wallet (índice 0 de
CRYPTO_MASTER_MNEMONIC) se fondea con gas nativo. - Flags:
--block-time 2(por defecto, minado por intervalo),--block-time 0(un bloque por transacción; los tests minan conanvil_mine),--mainnets(agrega los chainIds 137 / 56 / 8453 en:18137/:18056/:18453para demos locales en modo live),--fresh(borra el estado persistido enscripts/chain/.state/).
Apuntá el servidor a ellas en apps/server/.env:
CRYPTO_MASTER_MNEMONIC="depend mechanic screen brush dust raven sure found body super chronic parrot" # public dev mnemonic
CRYPTO_RPC_POLYGON_AMOY=http://127.0.0.1:18002
CRYPTO_RPC_BSC_TESTNET=http://127.0.0.1:18097
CRYPTO_RPC_BASE_SEPOLIA=http://127.0.0.1:18532y, opcionalmente, dale al botón de wallet del checkout los mismos RPCs (apps/client/.env.local: NEXT_PUBLIC_CRYPTO_RPC_POLYGON_AMOY=http://127.0.0.1:18002, …), para que una wallet del navegador pueda agregar la cadena local.
Después corré la API (bun run dev) y el worker (bun run --cwd apps/server worker): sin el worker no se escanea, no se barre ni se envía nada.
Datos de demo: bun run crypto:demo
apps/server/scripts/crypto-demo.ts llena un stack en ejecución con la historia de Glyphyard a través del pipeline real (API de merchant, API del checkout público y transferencias ERC-20 reales desde las wallets de los compradores): los sellers Halden Type, Kiso Foundry, Pampa Type, Ribbon & Rule, Osaro Studio, el partner Kerning Weekly, dos payment links e invoices en todos los estados (pagadas en distintas redes, sobrepagada con un refund reclamable, pagada de menos, pendiente, vencida, reembolsada, una todavía confirmándose) más un payout completado. Es idempotente y tarda unos 2.5 minutos. Corre sobre la org acme del seed (entrá como [email protected] / password123).
Sus valores por defecto son --api http://localhost:3405 --checkout http://localhost:3404; con los puertos por defecto pasá --api http://localhost:3005 --checkout http://localhost:3004. --webhook-url <url> además registra un webhook endpoint.
Aceptación: bun run --cwd apps/server crypto:e2e
La definición de terminado de la fase 1, a nivel API, unos 1:35. Levanta su propio stack aislado (un schema de Postgres descartable, Redis DB 9, tres cadenas anvil en los puertos +100 con un bloque por transacción, la API en :3105 y el worker) y verifica cada resultado on chain y en el ledger: creación idempotente de invoices, vista pública, pago, DETECTED → PAID, las líneas de ledger 90 / 10 / 2 / 0.50, un webhook firmado, una transferencia con token equivocado puesta en escrow y reembolsada en su propio token, el sweep, un payout, y underpaid → expired → refund reclamado (dirección de contrato rechazada). Imprime ALL PASSED y sale con 0 solo si pasaron todos los pasos.
Suite de navegador: bun run e2e:crypto
Cinco specs de Playwright (tests/e2e/crypto-*.spec.ts) manejan la UI real contra cadenas locales:
| Spec | Cubre |
|---|---|
crypto-checkout | elegir un par → Pay with wallet (un provider EIP-1193 inyectado respaldado por anvil; arranca en otra cadena, así que corre el cambio) → DETECTED → recibo PAID con la barra de split → invoice imprimible; el monto exacto salió del comprador on chain |
crypto-refund | underpaid → expired → refund retenido en la página pública (sin link) → link de reclamo desde la API de merchant → el portal rechaza un contrato, paga a una EOA on chain |
crypto-dashboard | overview en modo Test → detalle de la invoice: resumen, ledger balanceado, pestaña Technical con claim_url oculto |
crypto-payout | activar 2FA en Settings → New payout con un código TOTP → COMPLETED, monto neto en el destino on chain |
crypto-payment-link | crear un link en el dashboard → /l/:slug → checkout → PAID, contador de ventas en 1 |
tests/scripts/run-e2e.ts con E2E_CRYPTO=1 crea y migra un schema aislado, lo seedea, levanta las cadenas (puertos +200, un bloque por transacción) y el worker sobre Redis DB 10, y corre la API en :3205 y el cliente en :3204, así puede correr al lado de bun run dev y chain:dev. Los specs minan las confirmaciones ellos mismos. Si ya hay otro next dev corriendo en apps/client (Next.js permite uno por directorio), usá E2E_CLIENT_MODE=start para servir un next build nuevo (E2E_SKIP_CLIENT_BUILD=1 reutiliza el último). Playwright corre sobre Node, no sobre Bun: poné un Node real primero en el PATH.
Testnets públicas
Seteá CRYPTO_RPC_<NETWORK> con RPCs públicos (ver apps/server/.env.example) para correr el camino de lectura contra Amoy, BSC Testnet y Base Sepolia. Amoy no tiene un USDT canónico (el contrato USDT de Amoy existe solo en las cadenas locales), así que ahí pagá las invoices de Amoy en USDC. Los valores por defecto del scanner (rangos de 200 bloques, partidos a la mitad ante los límites del provider) están dimensionados para esos providers; la evidencia está en docs/superpowers/specs/2026-10-27-public-testnet-smoke.md.