
Cómo convertir tu idea en un programa de Solana (contrato inteligente)
Tabla de contenido
- Ejemplo de programa de Solana: creación de un mercado de predicciones
- Arquitectura del mercado de predicciones
- 1. Diseñar nuestra aplicación como cuentas de Solana
- 2. Representar las relaciones entre los datos
- 3. Almacenar tokens
- 4. Reducir el esfuerzo de lectura
- 5. Reducir la contención de escritura
- Conclusión
- Recursos adicionales
Diseñemos un programa de Solana. El ecosistema de Solana ofrece numerosos artículos para entender el modelo de programación de Solana y crear pequeños programas de demostración, una excelente forma de que los principiantes aprendan Solana y Anchor. Sin embargo, los programas reales presentan consideraciones más complejas.
En este artículo, analizaremos un programa real que queremos crear y veremos cómo:
- Definir nuestros datos como cuentas de Solana
- Crear relaciones entre nuestros datos
- Almacenar tokens dentro de nuestro programa
- Usar índices para acelerar las lecturas
- Usar sharding para acelerar las escrituras
El objetivo de este ejemplo es ayudarte a tomar tus propias ideas y entender cómo modelarlas como programas y cuentas de Solana.
Nota: Este artículo supone que conoces los fundamentos de Anchor.
Ejemplo de programa de Solana: creación de un mercado de predicciones
El programa que diseñaremos hoy es un mercado de predicciones similar a Polymarket, Hedgehog o Drift BET. Si no conoces los mercados de predicciones, estos permiten apostar por distintos resultados de un evento. Podría tratarse de qué equipo gana el Superbowl, quién obtiene el Óscar a mejor director, si el gobierno hará un anuncio antes de una hora determinada o cualquier otro evento del mundo real con un resultado específico. Si alguien apuesta por el resultado ganador, recibe ganancias del fondo de apuestas.
Arquitectura del mercado de predicciones
Esta es la arquitectura principal de un mercado de predicciones y la relación entre cada elemento:
- Hay varios eventos.
- Cada evento tiene varios resultados. Con el tiempo, uno de ellos se determinará como el resultado ganador.
- Los usuarios hacen varias apuestas por cada resultado. Cuando un usuario hace una apuesta, sus fondos se añaden al fondo de premios de ese evento.
Cuando el evento se «resuelve» (es decir, cuando conocemos el resultado ganador):
- Los usuarios que apostaron por el resultado ganador podrán reclamar sus ganancias
- Los ganadores recibirán una parte del fondo de premios (menos una comisión de la casa)
- La parte del fondo de premios que reciba cada ganador dependerá de su proporción de las apuestas por el resultado ganador.
1. Diseñar nuestra aplicación como cuentas de Solana
Si diseñáramos este programa para usar una base de datos relacional, pensaríamos en lo siguiente:
- Los elementos de datos similares se almacenan como filas de una tabla
- Se usan claves primarias para identificar de forma única cada elemento de datos
- Las columnas de la tabla definen los atributos esperados de cada elemento de datos y sus tipos
En Solana, estos conceptos corresponden aproximadamente a lo siguiente:
- Los elementos de datos similares se almacenan con el mismo tipo de cuenta
- Se usan direcciones para identificar de forma única cada elemento de datos
- La struct (claves y tipos de datos) define los atributos de cada elemento
Estos son los mismos datos, representados tanto en una tabla de base de datos tradicional como en cuentas de Solana:
2. Representar las relaciones entre los datos
Las relaciones entre elementos de datos funcionan de forma muy distinta en Solana. Las bases de datos tradicionales usan relaciones (es decir, la conexión lógica entre tablas). Solana gestiona las relaciones de uno a muchos como un vector de direcciones, donde cada dirección contiene una cuenta con el elemento.
Por ejemplo, los eventos tienen «resultados» que forman un vector de direcciones de resultados. Anchor lo representa como Vec<Pubkey>, aunque las direcciones PDA (como la de nuestro resultado) no son realmente claves públicas.
3. Almacenar tokens
A diferencia de las bases de datos tradicionales, los programas de Solana también pueden almacenar fondos dentro de una cuenta, no solo cifras de saldo.
En nuestro ejemplo, el evento necesita una cuenta de tokens para su fondo de premios. La PDA del evento será propietaria de la cuenta del fondo de premios. Cuando los usuarios hagan apuestas, enviarán tokens a esta cuenta. Pero, aún más importante, cuando reclamen sus ganancias, nuestro programa firmará la transacción como la cuenta del evento para retirar tokens del fondo de premios.
4. Reducir el esfuerzo de lectura
Nuestro programa debe responder con la mayor rapidez posible para los usuarios. Como desarrolladores, queremos evitar pagar innecesariamente por lecturas de cuentas que no necesitamos. Podemos hacer que nuestro programa responda mejor y sea más eficiente mediante totales acumulados e índices.
Calcular totales acumulados
Cuando los usuarios reclamen sus ganancias, necesitaremos saber exactamente cuánto se apostó por cada resultado. Los mercados de predicciones determinan el pago de un usuario ganador con la fórmula fondo de premios × importe de la apuesta ÷ total de apuestas por el resultado ganador.
Ahora mismo, solo almacenamos el importe de cada apuesta en la cuenta de esa apuesta. Para obtener el total apostado por un resultado específico, tendríamos que leer todas las cuentas de apuestas y sumar los importes.
En su lugar, añadamos un campo a cada resultado, total_amount, y aumentémoslo cuando los usuarios hagan apuestas. Así, cuando ganen, podremos determinar fácilmente el importe del pago sin tener que leer todas las apuestas de ese resultado.
Usar índices
También necesitaremos encontrar todas las apuestas de una cuenta de usuario específica. Podríamos obtener todas las cuentas de apuestas con getProgramAccounts() y filtrar aquellas cuyo apostador corresponda a la dirección de ese usuario. Aunque el rápido getProgramAccounts() de Helius permite hacerlo mucho más rápido que otros proveedores de RPC, los índices son una alternativa habitual.
Así que creemos un índice para almacenar las apuestas de cada usuario. Cuando un usuario haga una nueva apuesta, crearemos este elemento si no existe y añadiremos la apuesta a su lista de apuestas:
También añadiremos etiquetas a cada evento para encontrar fácilmente todos los eventos con las etiquetas «sports», «politics», «europe», «usa», «politics», etc. Crearemos otro índice para ello:
Ahora podemos recuperar fácilmente todos los eventos de interés consultando la cuenta de etiquetas de eventos.
5. Reducir la contención de escritura
¿Recuerdas que cada evento tiene una única cuenta de tokens donde se almacenan las apuestas de ese evento? Cada vez que un usuario añada una nueva apuesta, se moverán tokens a esta cuenta. En otras palabras, se escribirá en la cuenta.
Solana es rápida porque paraleliza las operaciones. Sin embargo, el saldo de una única cuenta no puede actualizarse en paralelo. Debe hacerse de forma secuencial, porque cada cuenta debe tener un único saldo en todo momento.
Si se anuncia un nuevo evento y recibe muchas apuestas, se producirán numerosas escrituras simultáneas en la cuenta de tokens del evento y las transacciones de nuestro programa podrían parecer lentas. Esto se denomina contención de escritura: varias transacciones compiten por acceder a la cuenta.
Una forma de permitir el paralelismo en estos casos es mediante sharding. Un recurso se divide en varias partes, llamadas shards, a las que se puede acceder en paralelo.
Cómo funciona el sharding
Los pagos entrantes se envían a shards de win_pool separados según el valor del último byte de la clave pública del apostador mediante la macro shard_num(). Esto garantiza que los pagos entrantes sean rápidos.
Más adelante, un manejador de instrucciones de administración puede consolidarlos en una única cuenta de fondo de premios. Así tendremos liquidez en la misma cuenta para pagar a los ganadores.
También debemos considerar la contención de escritura si se finaliza un evento popular y todos los ganadores reclaman sus ganancias al mismo tiempo. Además, tendremos que mover los fondos del fondo de premios tan rápido como sea posible.
La mejor opción en este caso es evitar un proceso de reclamación. Si enviamos los fondos de forma secuencial en cuanto finalice el evento, los usuarios no tendrán que lidiar con reclamaciones lentas: sus ganancias ya estarán depositadas en sus cuentas.
Sin embargo, necesitas tener usuarios antes de preocuparte por multitudes que apuesten o reclamen sus ganancias. Si estás planificando tu programa de Solana y aún no lo has lanzado, no necesitas optimizaciones para gestionar grandes volúmenes de tráfico de usuarios que todavía no tienes. Si no las necesitas para el lanzamiento, debes considerar la complejidad adicional de optimizaciones mayores como esta. Ten en cuenta que quizá debas implementarlas cuando tu programa se vuelva más popular.
Conclusión
En este artículo, analizamos a fondo cómo crear una aplicación real en Solana. Ahora tienes conocimientos prácticos para definir cuentas de Solana, establecer relaciones entre datos, almacenar tokens y optimizar el rendimiento mediante índices y sharding.
Si tienes más preguntas, puedes comunicarte con @helius en X o unirte al Discord de Helius. Ampliaremos este ejemplo de mercado de predicciones en el futuro, así que asegúrate de seguir esas cuentas para recibir novedades.
Con estas nuevas habilidades, es hora de convertir tus ideas en programas de Solana y darles vida dentro del ecosistema de Solana. ¡Feliz programación! Gracias a Ichigo por revisar este artículo y a r0bre por señalar la técnica de sharding de cuentas utilizada.
Recursos adicionales
Artículos relacionados
Suscríbete a Helius
Mantente al día con las novedades del desarrollo en Solana y recibe actualizaciones cuando publiquemos


