1) En los últimos 4-5 años he experimentado con un montón de arquitecturas de aplicaciones de Solana, y pensé que ya era hora de escribir mis hallazgos. Comenzando con lo menos complicado y añadiendo progresivamente más complejidad. Así que aquí va: Arquitectura de Aplicaciones de Solana, un hilo.
2) Comencemos con el modo fácil. Probablemente así es como se ve tu primera aplicación de Solana. Un frontend simple en react, establece una conexión a un RPC. No hay necesidad de un servidor API. El RPC es tu servidor. En los primeros días, estos estaban llenos de getAccountInfos, lógica de construcción de transacciones a medida, etc. Más tarde, cuando el rendimiento comienza a sufrir, añades capas de caché y agrupamiento. Entra getMultipleAccounts. Quizás también añadas suscripciones por websocket + polling para actualizar la interfaz de usuario en vivo. Esta arquitectura permite una prototipación extremadamente rápida. Prácticamente no hay devops. Costos de servidor insignificantes (solo despliega en vercel, etc). Sin embargo, tiene algunos defectos importantes.
3) El primer problema que enfrentas son las consultas complejas. En esta arquitectura, solo tienes el RPC de Solana en su versión básica. Eso significa que debes tratar a Solana como lo expone un RPC: como una base de datos NoSQL con un problema de actitud. Las consultas puntuales no son un problema. Incluso puedes ser muy creativo con los PDA para recorrer los datos de tu programa como si fuera una base de datos gráfica. Pero tan pronto como necesites hacer tu primer gPA, estarás en un gran aprieto. La interfaz no es ergonómica en absoluto. Si tienes algún tipo de datos de longitud dinámica, no se puede usar en absoluto. Dependiendo de tu proveedor de RPC, puede ser increíblemente lento. Incluso sin gPAs, este enfoque tiende a ser mucho más lento que tu típica aplicación web2 con renderizado del lado del servidor y una base de datos normal.
4) El segundo problema que enfrentas es la portabilidad de la lógica de construcción de transacciones. Con esta configuración, toda la lógica para construir transacciones está (a) en tu código frontend o (b) en bibliotecas que tu código importa. En el caso de (a), cualquiera que quiera construir transacciones fuera de tu frontend se enfrenta a un gran dolor (esto te incluye a ti, cuando inevitablemente necesites más aplicación). En el caso de (b), cualquier cambio en la lógica de construcción de transacciones requiere publicaciones de bibliotecas, que todos actualicen sus paquetes y luego actualizaciones de la interfaz de usuario. Apoyarse en herramientas de Anchor como la resolución de cuentas puede minimizar la cantidad de lógica que necesita ser trasladada, pero el problema persiste. Esto te roba agilidad y dificulta cambiar los puntos finales de los contratos inteligentes mientras aseguras que todas las versiones de tu lógica de construcción de TX sigan funcionando.
5) El tercer problema que encuentras es el hecho de que las interfaces de usuario suelen ser malas para enviar transacciones, especialmente con la lógica de reintento. Un usuario puede navegar fuera de la página, y la transacción deja de reintentar. Las grandes cantidades de transacciones tienden a tener dificultades para completarse. Es difícil depurar desde lejos por qué las cosas no están completándose.
6) El problema final aquí es que no eres el único con esta arquitectura. Un RPC es valioso, y básicamente tienes que exponer tu URL de RPC en tu frontend. Ahora, terminas en un juego del gato y el ratón para asegurarte de que nadie esté robando tu RPC y aumentando tus costos.
7) ¿Y ahora qué? Típicamente, incluso si no estás abordando la portabilidad de transacciones, terminas necesitando abordar las consultas de listas. gPA apesta, y todos lo sabemos. Así que puedes construir una arquitectura híbrida. En esta arquitectura, mantienes la capacidad de prototipar rápidamente, pero empujas las consultas difíciles y feas a una API. Un buen ejemplo concreto de esto es la gobernanza: tienes propuestas que se crean y que tienen un conjunto de etiquetas ("Económico", "Técnico", etc.). gPA no puede filtrar por etiqueta.
8) Esta arquitectura no ha resuelto la portabilidad de las transacciones, ni el problema de que la gente retire tu RPC. Pero a gran escala, al menos puedes resolver el problema de los gPAs lentos/imposibles. Introduce un nuevo problema: los indexadores. Más sobre esto más tarde.
9) Finalmente, tienes lo que yo llamaría la pila "enterprise" de Solana. Ya no estás tratando a Solana como una base de datos NoSQL. En su lugar, lo estás tratando como un bus de eventos. El frontend no sabe nada sobre el modelo de datos de Solana. El servidor construye transacciones y las pasa a la interfaz de usuario para su firma, luego las envía a Solana mismo. Trata esto como un evento y espera a que se propague de vuelta a los indexadores que cambiarán los datos subyacentes. Esta configuración tiene una gran portabilidad de transacciones: cualquiera puede acceder a tu API con parámetros limpios y recibir de vuelta transacciones/instrucciones. Esto hace que la interfaz de usuario sea extremadamente rápida: en lo que respecta a la interfaz de usuario, esto es básicamente web2. Puedes aprovechar al máximo el SSR. El RPC está abstraído: nadie puede robar tus créditos. Pero esta configuración tiene sus problemas.
10) El primer problema con el que te encontrarás es el dolor del indexador. Aunque esto se ha aliviado en los últimos años (gracias a los equipos de Triton, Helius y StreamingFast), todavía termino golpeando a nuestro indexador con una llave inglesa regularmente. Perderás mensajes. Cuando pierdes un mensaje, tu interfaz de usuario entra en un estado extraño (ejemplo: te envié un NFT, en la cadena lo recibiste, en mi base de datos dice que todavía lo poseo). Este tipo de problemas son desesperantes de depurar. ¿Es tu culpa? ¿Es culpa de tu proveedor de datos? ¡Quién sabe! Ahí se va tu tarde.
11) El siguiente problema con el que te encontrarás es el tiempo. Cuando utilizas directamente el RPC para todo, te permiten pasar compromisos y trabajar con los datos más recientes. Con un indexador, todo esto es manual. Esto significa que cuando estás construyendo transacciones, podrías estar construyéndolas basándote en datos desactualizados. Devuelves una transacción que está condenada al fracaso. Puedes resolver el problema de los datos desactualizados utilizando proveedores de datos que te ofrezcan datos extremadamente rápidos (por ejemplo, Helius laser stream). Pero entonces necesitas lidiar manualmente con los reorgs. Es decir, los datos que indexas necesitan ser desindexados si esa tx no terminó realmente procesándose. Esto es una pesadilla.
12) Puedes "hackear" los problemas de sincronización construyendo transacciones solo con datos del RPC, y utilizando tus datos indexados solo para alimentar la interfaz de usuario. Pero entonces, los usuarios seguirán teniendo problemas con posibles inconsistencias entre la interfaz de usuario y la cadena. Es decir, la interfaz dice que poseo este NFT y puedo transferirlo, luego el backend me grita y dice que no puedo.
13) El problema final con esta configuración es el costo, y si estamos siendo melodramáticos, "la muerte de la descentralización." El sueño de web3 no era tener que desplegar toneladas de servidores centralizados. Ahora has desplegado suficiente infraestructura para conseguir un trabajo como arquitecto principal en una empresa de web2. Cuesta dinero. Cuesta tiempo. Y todo es muy centralizado. ¿Qué tan descentralizado es tu protocolo si la mejor manera de interactuar con él es a través de una API de web2? Y hay como 72 desarrolladores en Solana que sabrían cómo interactuar con él sin esa API.
14) En última instancia, no voy a morir en ninguna colina en torno a la descentralización. Lo que es mejor para los usuarios tiende a ser la mejor opción. La configuración "empresarial" conduce a aplicaciones web rápidas y modernas y a una clara separación de preocupaciones. Por el lado negativo, añade costos de devops y te hace menos ágil. Recomiendo que la mayoría de las startups comiencen con el método directo a rpc a menos que estés construyendo algo que necesite explícitamente ser rápido o tener semánticas de consulta complejas. El tiempo de comercialización es clave. Siempre puedes contratar a un ingeniero de nivel medio más tarde y meterlo en la mazmorras de indexación.
15) Fin. Si alguno de ustedes ha encontrado una mejor configuración, háganmelo saber. Estas son todas las cosas que he probado. Estoy disfrutando bastante jugar con la configuración empresarial últimamente.
35,89K