Saltar al contenido principal

Desarrollar plantillas de interfaz de usuario para la inicialización de contratos

Esta guía retoma donde Construir un frontend de Dapp lo dejó, echando un vistazo más profundo al --frontend-template utilizado allí. A partir de ahí, vamos a:

  1. Buscar en GitHub otras plantillas de Soroban
  2. Crear nuestra propia plantilla simple

Crear nuestra propia plantilla será una excelente manera de aprender cómo funcionan. ¡No son tan complicadas!

Buscar en GitHub otras plantillas de Soroban

La plantilla oficial mantenida por Stellar Development Foundation (SDF), como se usó en Construir un frontend de Dapp, está en GitHub en stellar/soroban-template-astro. Usa el marco web Astro. Aunque Astro funciona con React, Vue, Svelte y cualquier otra biblioteca de interfaz de usuario, la plantilla opta por no usarlas, prefiriendo el propio lenguaje de plantillas de Astro, que usa JavaScript puro sin biblioteca de interfaz de usuario.

(Puede que te preguntes por qué toma esta elección poco popular. ¡Una pregunta justa! El equipo quería equilibrar la utilidad real con un enfoque amplio. ¡No todos los que aprenden Stellar y Soroban están familiarizados con React, ni con ninguna otra biblioteca de interfaz de usuario. También demuestra que las bibliotecas centrales de Soroban funcionan con cualquier proyecto de JavaScript.)

Pero ten en cuenta que el comando contract init del CLI fue diseñado para funcionar con cualquier plantilla de interfaz de usuario. ¡No necesita incluso vivir en GitHub! Simplemente pasa otra URL de git válida al comando, y clonará eso en lugar del repositorio oficial:

# the following is NOT a valid git repository, and will not work 😄
stellar contract init my-new-project --frontend-template https://whatever.cool/project/you/want

¿Entonces cómo puedes encontrar otras plantillas de interfaz de usuario válidas?

En algún momento podríamos establecer un DAO u otro sistema de votación para curar una lista de plantillas de alta calidad, pero por ahora... ¡busca en GitHub! Y en GitLab. Y en cualquier otro sitio de código fuente que conozcas.

En GitHub, en la barra de búsqueda principal, busca por "soroban-template-". Con las comillas. Aquí tienes un enlace directo a los resultados de búsqueda: github.com/search?q=%22soroban-template-%22

Puedes copiar este enfoque para cualquier otro sitio web de código fuente, como GitLab.

¿Cómo sabes si alguno de estos es bueno? Prueba ellos. Mira su código fuente. ¿Cuántas estrellas tienen? ¿Cuán activos son sus mantenedores? Ninguna de estas es una métrica perfecta, que es por qué un registro curado podría ser agradable en el futuro.

Si ninguno de ellos se ajusta, entonces podría ser tiempo de...

Crear tu propia plantilla

Esto será más fácil de lo que podrías imaginar. Hay algunas complicaciones, pero en general estas plantillas son proyectos de Node bastante estándar.

Pero primero, ¿cómo están organizados estos proyectos?

Cuando ejecutas stellar contract init, siempre incluye un proyecto de Rust/Cargo, con un Cargo.toml que define un espacio de trabajo, y miembros del espacio de trabajo ubicados en una carpeta contracts. Como mínimo, hay un contrato, contracts/hello_world, pero puedes obtener más usando --with-example.

Por separado, puedes incluir un --frontend-template. Hasta ahora, todas las plantillas de interfaz de usuario han sido proyectos de Node, que tienen un package.json en la raíz. En el proyecto compuesto final, el proyecto de Node y el proyecto de Rust viven uno al lado del otro, y la plantilla de interfaz de usuario espera que el proyecto de Rust esté allí. Espera una carpeta contracts con una o más subcarpetas, y espera un directorio target con todos los artefactos de construcción de Rust.

Así que ten eso en mente. Estamos creando un proyecto de Node bastante simple, y contándole sobre nuestro material de Soroban, como la carpeta contracts.

1. Inicializar un proyecto NPM

Así que, ¡hagamos un proyecto de Node simple! En lugar de inicializar un proyecto Astro, como la plantilla de interfaz de usuario oficial, intentemos algo nuevo. La Encuesta del Estado de JS me dice que algo llamado "Solid" es bastante nuevo y querido. ¿Qué dice que hay que hacer?

npx degit solidjs/templates/ts soroban-template-solid
cd soroban-template-solid
npm install
npm run dev

¡Ok, tenemos una plantilla de Solid en funcionamiento! ¡Ahora vamos a convertirlo en una plantilla de Soroban!

2. git init

¡Haz commit temprano, haz commit a menudo! Puedes detener el servidor de desarrollo (el que comenzaste con npm run dev arriba; deténlo con ctrlc, incluso en un Mac) si quieres, o abre una nueva terminal y:

git init
git add .
git commit -m "init from solid ts template"

3. Copia el script initialize.js

La plantilla soroban-template-astro mantenida por la SDF tiene un script initialize.js en su raíz del proyecto. Cópialo en tu proyecto.

Si estás familiarizado con la scripting en Node, deberías poder averiguar lo que está haciendo. Si no, ¡es una gran manera de aprender! Consejo: comienza desde el final, donde hace el generateAccount(); buildAll(); deployAll();.

Ese material al final debería darte una pista sobre lo que hace este script. Hace cosas que una aplicación Soroban necesita. Las aplicaciones Soroban hacen llamadas a Soroban.

Así que este script:

  1. genera una cuenta Soroban/Stellar
  2. construye todos los contratos
  3. despliega todos los contratos (a una red Soroban que se ejecuta localmente; recapitularé esto pronto)
  4. binds contracts — that is, it creates NPM projects for each deployed contract by running stellar contract bindings typescript
  5. importa los contratos para un uso directo en el resto de tu proyecto

Recuerda que necesita hacer todo esto de manera independiente del contrato. Es decir, la elección de --frontend-template es independiente de la elección de --with-example. ¡La plantilla de interfaz de usuario no sabe qué contratos podría encontrar! Pero necesita construir, desplegar, vincular e importar lo que haya.

Así que este script hace eso.

Pero necesita algunas otras cosas.

A. devDependencies

El script utiliza un par de paquetes NPM. Instálalos:

npm install --save-dev dotenv glob

B. .env

El paquete dotenv instalado anteriormente analiza variables de entorno desde un archivo .env. La plantilla oficial incluye un .env.example. Ve y cópialo en tu propio proyecto. Para prepararte para probarlo, también puedes copiarlo a un .env local.

cp .env.example .env

C. .gitignore

Querrás ignorar el archivo .env que creaste anteriormente, así como algunos otros artefactos de construcción creados por el script initialize.js. Pega la parte inferior de el .gitignore de la plantilla oficial en el .gitignore de tu plantilla:

# environment variables
.env
.env.production

# generated contract clients
packages/*
# if you have other workspace packages, add them here
!packages/.gitkeep

# generated contract client imports
src/contracts/*
!src/contracts/util.ts

C. package.json

Asegúrate de que los usuarios de tu plantilla no olviden ejecutar el script initialize.js. Modifica la sección scripts de la siguiente manera:

-    "start": "vite",
- "dev": "vite",
- "build": "vite build",
- "serve": "vite preview"
+ "init": "node initialize.js",
+ "start": "npm run init && vite",
+ "dev": "npm run init && vite",
+ "build": "npm run init && vite build",
+ "serve": "npm run init && vite preview"

Alternativamente, en lugar de agregar las repetitivas declaraciones npm run init, podrías optar por añadir un script postinstall donde ejecutes npm run init, o simplemente node initialize.js allí.

También necesitas decirle a NPM que trate esto como un espacio de trabajo. ¡Sí, este proyecto es un espacio de trabajo de Cargo y un espacio de trabajo de NPM! El paso bindAll de initialize.js coloca los paquetes de NPM generados en packages/*. En la parte inferior de package.json, añade:

   "dependencies": {
"solid-js": "^1.8.11"
- }
+ },
+ "workspaces": [
+ "packages/*"
+ ]
}

También asegúrate de que este proyecto esté configurado para permitir las declaraciones import en el script initialize.js. Añade esto a nivel superior:

   "description": "",
+ "type": "module",
"scripts": {

Mientras estás aquí, también puedes actualizar el name (quizás "soroban-template-solid") y description.

E. src/contracts/util.ts

En el .gitignore anterior, es posible que hayas notado que este archivo está explícitamente incluido. Cópialo desde la plantilla oficial. Necesitarás crear la carpeta src/contracts.

Como puedes ver, simplemente facilita import { rpcUrl, networkPassphrase } from 'util' en los archivos generados en el paso de importAll.

F. README

Quizás quieras comenzar copiando el README de la plantilla oficial para explicar cómo hacer cp .env.example .env. From there, this might also be a good time to explain anything else that makes your template unique! ¿Por qué la gente querría usarla?

4. git commit

¡Haz commit de los cambios!

git add .
git commit -m "add initialize.js script and supporting changes"

5. ¡Prueba esto!

¡Eso es todo! You have an NPM project with an initialize.js script (and its supporting cast). ¡Eso es todo lo que realmente necesitas!

Para probarlo, pronto ejecutaremos stellar contract init . en este proyecto para añadir el material de Cargo y una carpeta contracts. ¡Pero ten cuidado! ¡No quieres hacer commit de estos cambios! Puedes usar git restore . al final de tus pruebas para deshacerte de los nuevos archivos.

Vamos a probarlo. Primero, asegúrate de que estás ejecutando una red Stellar local. Inicia Docker Desktop o cualquier alternativa que prefieras, entonces:

stellar network container start local

Ahora podemos ejecutar contract init. Vamos a incluir un contrato extra. Luego ejecutaremos el script dev (que, recuerda, ejecutará primero el script initialize.js):

stellar contract init . --with-example increment
npm run dev

Después de hacer esto, es posible que notes muchos cambios nuevos en el proyecto. ¡Todo ese material de Rust, Cargo y Soroban!

$ git status --short

?? .soroban/
?? Cargo.lock
?? Cargo.toml
?? contracts/
?? target/

Q: Should you commit this stuff?
A: NO!

Q: Should you gitignore this stuff?
A: NO!

Las carpetas .soroban y target están gitignoreadas por la plantilla principal de Rust/Cargo. En los proyectos que especifiquen el tuyo como su --frontend-template, ese .gitignore se fusionará con el tuyo. No es necesario incluir esas líneas dos veces.

Y los proyectos que utilizan el tuyo querrán hacer commit de los archivos Cargo.* y contracts, pero tu plantilla no debería incluirlos. Eso puede causar problemas con la inicialización del proyecto más adelante. Nor should it gitignore them, because your .gitignore will be part of projects started with your template! ¡Causaría problemas y confusión, si la gente no se diera cuenta de que algunos de sus archivos más importantes estaban gitignoreados!

Está bien. Ve y abre la aplicación en tu navegador. Solid ejecuta su servidor de desarrollo en http://localhost:3000. ¿Se carga? ¡Debería! ¡En realidad no utilizamos el nuevo material src/contracts/* en la aplicación misma!

6. Espera. ¿Debería la plantilla realmente usar los contratos?

¡Buena pregunta!

Sabes que el contrato hello_world siempre estará allí. Así que podrías demostrar a tus usuarios cómo importarlo y usarlo en un archivo de aplicación (como src/App.tsx, en la plantilla de Solid). Pero recuerda: ¡ningún otro contrato tiene garantizado estar allí! So don't commit any changes that import and use something like increment!

Aquí tienes una forma de demostrar cómo importar y usar el contrato hello_world en el App.tsx de la plantilla de Solid:

+import greeter from "./contracts/hello_world";

const App: Component = () => {
return (
<div class={styles.App}>
<header class={styles.header}>
+ <form
+ onSubmit={async (e) => {
+ e.preventDefault();
+ const { result } = await greeter.hello({
+ to: e.currentTarget.toWhom.value,
+ });
+ alert(result);
+ }}
+ >
+ <label>
+ Who you gonna call? &amp;nbsp;
+ <input name="toWhom" value="World" /> &amp;nbsp;
+ </label>
+ <button type="submit">Say Hello</button>
+ </form>

7. ¡Hazlo tan complejo como quieras!

Esta es tu plantilla. Ve y añade dependencias útiles y archivos de utilidad que siempre quieras, como gestión de billeteras o lo que sea. Si quieres añadir un montón de componentes de interfaz de usuario, estilos y bibliotecas de gestión de estado, ¡adelante!

La plantilla oficial se esfuerza por la simplicidad. Incluso por superficialidad. Está destinado a ser una herramienta de enseñanza, para personas con diferentes niveles de experiencia en JS y Soroban. ¡La tuya no tiene tales restricciones! Debería ser útil para ti.

¡Y las plantillas son baratas de hacer! Si quieres tener una soroban-template-framework-x-basic para un público más amplio, y otra soroban-template-framework-x-opinionated para tus propios proyectos, ¡puedes hacerlo!

Conclusión

Algunas cosas que hicimos en esta sección:

  • Buscamos en GitHub nuevas plantillas de interfaz de usuario
  • Aprendimos que algunas plantillas podrían no estar en GitHub
  • Vimos cómo funcionan las plantillas de interfaz de usuario e interactúan con la plantilla "backend" que siempre viene con stellar contract init
  • Desarrollada nuestra propia plantilla al agregar un script initialize.js a una plantilla básica de NPM

Después de que termines de construir tu propia plantilla de frontend, ¿qué sigue? ¡Tú eliges! Puedes: