Resumen
El frontend es una landing page + dApp construida con Next.js 15 (App Router). Permite conectar wallet, inscribir datos y consultar el historial on-chain. Todo el texto de la UI está en inglés; la documentación del proyecto está en español.
Tecnologías
| Paquete | Versión | Uso |
|---|---|---|
next | 15.x | Framework React con SSR |
react | 19.x | UI |
typescript | 5.7.x | Tipado estático |
tailwindcss | 4.x | Estilos utility-first |
wagmi | 2.x | Hooks de wallet y contrato |
viem | 2.x | Cliente Ethereum tipado |
@tanstack/react-query | 5.x | Cache de queries wagmi |
framer-motion | 11.x | Animaciones suaves |
Estructura de páginas
app/layout.tsx
- Fuentes: Geist Sans + Geist Mono
- Metadata SEO y Open Graph
- Wrapper
<Providers>con Wagmi + React Query - Tema oscuro (
#0a0f14)
app/page.tsx
Página única que compone todas las secciones:
Header → Hero → InscribeForm → InscriptionHistory → ProtocolSection → Footer
↓
InscriptionDetail (modal)
Estado local:
refreshKey— fuerza recarga del historial tras inscribirselectedId— ID de inscripción seleccionadalastTxHash— hash de la última transacción del usuario
Componentes
Header.tsx
| Función | Detalle |
|---|---|
| Logo + nombre | Link a / con featherscript-logo.png |
| Navegación | Anchors: Inscribe, History, Protocol |
| Connect Wallet | Botón wagmi useConnect con connector injected |
| Switch Network | Aparece si la wallet no está en Chain ID 4663 |
Hero.tsx
Sección principal con:
- Badge "Open Inscription Protocol · Robinhood Chain L2"
- Título: "One Transaction. One Permanent Inscription."
- CTAs: "Start Inscribing" y "Read the Protocol"
- Stats:
1 = 1,ETH,4663
Animaciones de entrada con Framer Motion.
InscribeForm.tsx
Formulario principal de inscripción.
Flujo:
- Usuario escribe texto o sube archivo (mutuamente excluyentes)
- Archivos limitados a 24 KB (validación frontend)
- Contenido convertido a hex con
textOrFileToHex() writeContract({ functionName: 'inscribe', args: [data] })useWaitForTransactionReceiptespera confirmación- Parsea
inscriptionIddeltopics[1]del evento en el receipt - Llama
onInscribed(id, txHash)al padre
Estados de UI:
Signing...— wallet pendienteConfirming...— esperando bloque- Mensaje de éxito con tx hash truncado
- Modo demo si
NEXT_PUBLIC_REGISTRY_ADDRESSno está configurado
InscriptionHistory.tsx
Dos exportaciones:
InscriptionHistory
- Lee
inscriptionCount()del contrato - Carga las últimas 10 inscripciones
- Grid de tarjetas clicables
- Muestra: ID, tamaño, preview de datos, creator, fecha
InscriptionDetail
- Modal full-screen con animación spring
- Campos: Creator, Timestamp, Block, Size, Tx Hash (si disponible)
- Raw data en
<pre>con scroll - Link al Blockscout explorer
ProtocolSection.tsx
Documentación visual integrada en la landing:
- 4 feature cards (One Transaction, Raw Bytes, Fully On-Chain, Zero Permissions)
- Snippet del contrato
- Lista de exclusiones intencionales
- Nota sobre limitación del tx hash
Footer.tsx
Links a Blockscout y Robinhood Chain Docs.
Providers.tsx
<WagmiProvider config={wagmiConfig}>
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
</WagmiProvider>
Librerías (lib/)
chains.ts
Define dos cadenas con viem.defineChain:
| Chain | ID | RPC |
|---|---|---|
robinhoodChain | 4663 | rpc.mainnet.chain.robinhood.com |
robinhoodTestnet | 46630 | rpc.testnet.chain.robinhood.com |
wagmi.ts
createConfig({
chains: [robinhoodChain, robinhoodTestnet],
connectors: [injected()],
transports: { ... },
ssr: true,
})
Solo usa el connector injected (MetaMask, Rabby, Robinhood Wallet, etc.) para minimizar dependencias.
contract.ts
INSCRIPTION_REGISTRY_ABI— ABI tipadaas constINSCRIPTION_REGISTRY_ADDRESS— desdeNEXT_PUBLIC_REGISTRY_ADDRESSEXPLORER_URL— Blockscout mainnet
utils.ts
| Función | Descripción |
|---|---|
bytesToDisplayText | Intenta decodificar hex a UTF-8; si no es imprimible, muestra hex |
textOrFileToHex | Convierte string o ArrayBuffer a 0x... |
formatAddress | 0x1234...abcd |
formatTimestamp | Fecha local legible |
formatBytesSize | B / KB / MB |
Diseño visual
Paleta
| Color | Uso |
|---|---|
#0a0f14 | Fondo principal |
#0d1219 | Superficies elevadas |
emerald-500 | Acento primario |
cyan-500 | Acento secundario / gradientes |
zinc-400/500 | Texto secundario |
Principios UI
- Dark mode nativo
- Bordes sutiles (
border-white/10) - Glassmorphism ligero (
backdrop-blur) - Gradientes en CTAs principales
- Animaciones de entrada al scroll (
whileInView) - Tipografía mono para datos on-chain
Variables de entorno
| Variable | Requerida | Descripción |
|---|---|---|
NEXT_PUBLIC_REGISTRY_ADDRESS | Para inscribir | Dirección del contrato desplegado |
Sin esta variable, la app funciona en modo demo: muestra la UI pero no permite transacciones reales.
Scripts npm
npm run dev # Desarrollo en localhost:3000
npm run build # Build de producción
npm run start # Servidor de producción
npm run lint # Linter Next.js
Flujo de usuario completo
- Usuario abre la landing
- Conecta wallet (MetaMask, Robinhood Wallet, etc.)
- Si no está en Robinhood Chain → botón "Switch Network"
- Escribe mensaje o sube archivo pequeño
- Clic "Inscribe On-Chain"
- Firma transacción en wallet
- Espera confirmación (~segundos en L2)
- Modal de detalle se abre automáticamente
- Historial se actualiza con la nueva inscripción