Diagrama de alto nivel
Diagram
flowchart TB
subgraph User["Usuario"]
W[Wallet EVM]
B[Navegador]
end
subgraph Frontend["FeatherScript Frontend (Next.js)"]
UI[Landing + dApp]
WM[wagmi / viem]
end
subgraph Chain["Robinhood Chain L2"]
SC[InscriptionRegistry]
ST[(Contract Storage)]
end
subgraph Index["Opcional — futuro"]
IDX[Event Indexer]
DB[(Base de datos)]
end
B --> UI
UI --> WM
W --> WM
WM -->|inscribe(bytes)| SC
WM -->|getInscription(id)| SC
SC --> ST
SC -->|event Inscribed| IDX
IDX --> DB
Flujo de inscripción
Diagram
sequenceDiagram
participant U as Usuario
participant F as Frontend
participant W as Wallet
participant C as InscriptionRegistry
participant L2 as Robinhood Chain
U->>F: Escribe texto o sube archivo
F->>F: Convierte contenido a bytes (hex)
U->>F: Clic "Inscribe On-Chain"
F->>W: writeContract(inscribe, data)
W->>U: Solicita firma
U->>W: Aprueba transacción
W->>L2: Envía tx
L2->>C: inscribe(data)
C->>C: inscriptionCount++
C->>C: Guarda Inscription en storage
C-->>L2: emit Inscribed(...)
L2-->>F: Transaction receipt
F->>F: Extrae inscriptionId del log
F->>U: Muestra confirmación + detalle
Estructura del repositorio
FeatherScript/
├── app/ # App Router de Next.js
│ ├── layout.tsx # Layout raíz, fuentes, providers
│ ├── page.tsx # Página principal (landing + dApp)
│ └── globals.css # Estilos globales + Tailwind
│
├── components/ # Componentes React
│ ├── Providers.tsx # WagmiProvider + React Query
│ ├── Header.tsx # Navbar + Connect Wallet
│ ├── Hero.tsx # Sección hero
│ ├── InscribeForm.tsx # Formulario de inscripción
│ ├── InscriptionHistory.tsx # Historial + modal de detalle
│ ├── ProtocolSection.tsx # Documentación visual del protocolo
│ └── Footer.tsx # Pie de página
│
├── lib/ # Lógica compartida
│ ├── chains.ts # Definición Robinhood mainnet/testnet
│ ├── wagmi.ts # Configuración wagmi
│ ├── contract.ts # ABI + dirección del contrato
│ └── utils.ts # Helpers (hex, formato, display)
│
├── contracts/ # Proyecto Foundry
│ ├── src/
│ │ └── InscriptionRegistry.sol
│ ├── test/
│ │ └── InscriptionRegistry.t.sol
│ ├── script/
│ │ └── Deploy.s.sol
│ └── foundry.toml
│
├── public/
│ └── featherscript-logo.png
│
├── docs/ # Esta documentación
├── package.json
├── .env.example
└── README.md
Capas del sistema
1. Capa de presentación (Frontend)
Responsabilidades:
- Conectar wallet del usuario
- Convertir texto/archivos a
bytes - Enviar transacciones al contrato
- Leer inscripciones existentes
- Mostrar historial y detalles
No almacena datos off-chain. Todo se lee directamente del contrato vía RPC.
2. Capa de protocolo (Smart Contract)
Responsabilidades:
- Recibir
bytesy persistirlos - Mantener contador global
- Exponer lectura por ID
- Emitir eventos para indexación
Es la única fuente de verdad on-chain.
3. Capa de red (Robinhood Chain)
- L2 compatible con EVM (Arbitrum Orbit)
- Gas pagado en ETH
- Confirmaciones rápidas (~sub-segundo)
- Chain ID mainnet:
4663
4. Capa de indexación (opcional, futuro)
No incluida en el MVP, pero recomendada para:
- Historial completo con
txHash - Búsqueda por creador
- Paginación eficiente
- APIs REST/GraphQL
Modelo de datos
Diagram
erDiagram
INSCRIPTION_REGISTRY ||--o{ INSCRIPTION : contains
INSCRIPTION_REGISTRY {
uint256 inscriptionCount
}
INSCRIPTION {
uint256 inscriptionId PK
address creator
uint256 timestamp
uint256 blockNumber
bytes data
}
El inscriptionId es la clave del mapping interno _inscriptions y va de 1 a inscriptionCount.
Decisiones de diseño
¿Por qué un solo contrato sin proxy?
- Máxima simplicidad y auditabilidad
- Sin riesgo de upgrades maliciosos
- Deploy una vez, permanente
¿Por qué bytes y no string?
byteses más flexible (archivos binarios, hex, UTF-8)- No impone encoding
- Gas ligeramente más predecible con
calldata
¿Por qué IDs incrementales y no hashes?
- Consulta directa por número (
getInscription(42)) - UX simple para usuarios ("Inscription #42")
- Los indexadores pueden mapear ID → txHash off-chain
¿Por qué límite de 24 KB en archivos (frontend)?
- El gas escala linealmente con el tamaño del calldata
- 24 KB es un balance razonable para inscripciones de texto/archivos pequeños
- Es una restricción de la UI, no del contrato