DApps — Desarrolla una cartera web en Stellar con React

Ernesto Garcia N
Blockchain Academy Mexico
10 min readMar 10, 2020

Anteriormente escribí un tutorial introductorio al SDK de Stellar, y esta es una continuación de aquel tutorial, por lo que, si no lo has checado, puedes ir aquí para ver la parte 1, ya que nos basaremos mucho en dicho contenido.

Disclaimer: Este tutorial requiere conocimientos generales de Javascript y algo de React. Aunque no es totalmente necesario, habrá varias cosas que no explique tan a detalle.

DApps para mortales

Blockchain ha evolucionado de ser una tecnología con propósitos meramente monetarios, a convertirse en todo un abanico de posibilidades, que permiten desde el desarrollo de ICO’s hasta la creación de protocolos para certificaciones de documentos, y, esto es en gran medida a la capacidad de los desarrolladores de crear capas de abstracción para el acceso a la tecnología.

Desde el punto de vista de usabilidad, existen problemas de adopción que son generados por el lenguaje que utiliza Blockchain: Llaves privadas, criptografía asimétrica, curvas elípticas, máquinas virtuales, etc., lo que, además de ser meramente técnico, son datos que no le interesan a nuestros usuarios, y requieren ser escondidos de alguna manera.

Lo cierto es que el trabajo de un Blockchain Developer es principalmente crear estas capas de abstracción generando interfaces y aplicaciones que acerquen la tecnología a las masas. No obstante, para esto se necesita un grado de conocimiento técnico alto, además de práctica y experiencia para desarrollar productos robustos y profesionales.

Ante esta situación, creo que es momento de poner el ejemplo y crear una aplicación descentralizada en un ambiente lo más real posible, y para ello, utilizaremos el contenido del tutorial pasado, donde creamos una cartera en Stellar utilizando Node.js y nuestra terminal Unix.

¿Qué vamos a construir?

Para este tutorial, vamos a crear una fantabulosa wallet de Stellar, que nos permitirá crear nuestra cuenta, enviar transacciones, y checar balances de terceros.

La aplicación la desarrollaremos reciclando el código de la primera parte de este tutorial, y además, utilizando React JS, una de las librerías para desarrollar interfaces de mayor popularidad en el mercado, y desarrollada por Facebook.

Prerequisitos

  • Haber seguido el tutorial introductorio a Stellar
  • Conocimiento básico de Node, Javascript y React
  • Tener listo tu editor de código
  • Comandos básicos de terminal Unix
  • Conocimiento de git

Primeros pasos

Antes de iniciar, vamos a necesitar descargar el repositorio anterior, con el cuál vamos a empezar.

git clone https://github.com/ernestognw/stellar-tutorial.git

Y, dado que subí la versión terminada de este proyecto a la rama principal, será necesario movernos a la rama tutorial-1, que es el punto de partida

git checkout tutorial-1

Una vez aquí, vamos a instalar los paquetes que necesitaremos, ya que ahora trabajaremos con una interfaz gráfica, así que hay que tomar algunas consideraciones:

  • react: La librería principal con la que desarrollaremos nuestra UI
  • react-dom: Acompañante de react, es el responsable de renderizar correctamente nuestra aplicación dentro de un documento HTML
  • react-scripts: Para evitarnos un setup muy complicado, utilizaremos los scripts de create-react-app para facilitarnos la vida
  • chakra-ui: Este es un paquete de componentes de interfaz bastante fácil de usar, y que nos evitará hacer decisiones de diseño. Además, hay que incluir algunas dependencias de emotion para hacerlo funcionar correctamente

Las añadiremos utilizando el siguiente comando

npm install react react-dom react-scripts @chakra-ui/core @emotion/core @emotion/styled emotion-theming

Además, tendremos que remover dotenv y node-fetch, que son dependencias de nuestro proyecto pasado, con las que manejabamos las llaves de Stellar y peticiones http. No obstante, en un ambiente de navegador, podemos utilizar algunas ventajas que nos provee, así que ya no son necesarias:

npm uninstall dotenv node-fetch

Setup

En este punto, ya tenemos lo necesario para hacer el setup del proyecto, y para eso, será necesario crear dos carpetas nuevas en nuestro directorio:

  • src: Aquí irá la aplicación de React
  • public: Aquí estará el index.html donde renderizaremos la aplicación

Dentro de public, colocaremos el siguiente index.html:

Y en src, crearemos los siguientes archivos:

index.js toma la aplicación y la inyecta en el html de public
App.js será el layout inicial para nuestro wallet

Dentro de App.js se añaden algunos componentes extra que sugiere la documentación de Chakra UI, que coloca el setup de CSS inicial para que la librería funcione bien.

Ahora, notarás que tenemos un componente llamado Wallet. Este lo crearemos dentro de una carpeta components, donde desarrollaremos toda la DApp, por lo que es necesario crearla.

Dentro de components, crearemos una carpeta de nombre wallet, y colocaremos un dummy component solo para inicializar la app:

A continuación, la carpeta utils, donde teníamos todos los scripts pasados, la moveremos dentro de src, para que podamos importar las funciones y que podamos usarlas dentro de React.

El setup final quedaría de esta forma:

Finalmente, modificaremos el package.json, ya que ahora utilizaremos scripts diferentes, eliminando los pasados y añadiendo los de react. Para ello, reemplaza el campo scripts con el siguiente objeto en JSON:

“scripts”: {  “start”: “react-scripts start”,  “build”: “react-scripts build”}

A partir de aquí, puedes empezar la aplicación de react para visualizar que todo ha salido bien con:

npm start

Y con suerte, tu app por ahora se verá así:

¡Bienvenido!

Modificando los scripts de Stellar

Para uso general, vamos a tener que hacer un arreglo de los scripts que tenemos en utils, ya que ahora se comportarán ligeramente diferente a la versión anterior, puesto que ahora queremos que los resultados no se impriman en consola, si no que sean regresados a la interfaz en React para que podamos utilizarlos como verdaderos utils.

Para ello, vamos a realizar las siguientes acciones, que primero te describiré, y a continuación te adjunto los scripts modificados:

  1. Remover el check-recipient-balance.js, ya que ahora checaremos balances solicitándole la dirección al usuario
  2. Renombraremos check-balance por load-account.js
  3. Modificaremos create-pair.js, y separaremos en dos partes la lógica, una para crear las llaves, y otra para fondearlas a través de la testnet de Stellar
  4. Modificaremos send-transaction.js, para pasarle manualmente la cuenta destino.

Además, pasaremos la sintaxis de todos a EcmaScript16, ya que react nos añade soporte nativo para esa sintaxis, así que removeremos todos los require y los reemplazaremos por import.

load-account.js

Previamente, este archivo cargaba la cuenta y mostraba los balances en consola, ahora la usaremos sólo para retornar una cuenta cargada, y nos servirá para mostrar tanto el balance del usuario, como cualquier otro balance.

En el archivo de create-pair.js, separaremos en partes la lógica, ya que ahora lo haremos en dos pasos desde la aplicación.

Anteriormente, teníamos aquí hardcodeada la dirección del destinatario, e importábamos el secret desde un archivo secreto, ahora, añadimos control del destinatario, el secret lo tomaremos como parámetro, y la cantidad la decidirá el usuario.

Una vez rediseñada la lógica, vamos a comenzar con el desarrollo de la interfaz.

Creando la interfaz

Nuestra interfaz pasará por 3 fases cuando accede un usuario nuevo, y será el flujo con el cuál creará su wallet:

  1. Pantalla de inicio: Aquí el usuario verá un botón para crear su cuenta, o, adicionalmente, podrá importar otra cuenta utilizando su llave secreta.
  2. Pantalla de copy: Normalmente las wallets te muestran sólo una vez tu llave secreta, y te piden que la copies antes de poder avanzar, aquí haremos lo mismo
  3. Pantalla principal: Aquí se concentrará la lógica principal de la aplicación.

Para crear este flujo, tomaremos el dummy component que hicimos en el directorio wallet, y lo reemplazaremos con la lógica correspondiente, utilizando localStorage para guardar las llaves del usuario, y manteniendo su sesión abierta.

En el nuevo archivo, podemos observar que dependiendo de las variables que estén guardadas en nuestro navegador, mostraremos una vista u otra, ya que en caso de no haber llaves, crearemos el par utilizando la vista de Start, y cuando las generemos, le pediremos que las copie en CopyKey. Este último dato lo verificaremos con la variable isKeyCopied, y, finalmente, si el proceso ya se hizo previamente, mandaremos a la vista principal de Main.

Además, hay valores que necesitamos pasar por props a los siguientes componentes, para que puedan acceder a los setters y otra información.

En este punto, tu aplicación no abrirá correctamente, ya que necesitamos añadir una carpeta components internamente en wallet, para importar las vistas desde ahí. Te sugiero agregar el mismo dummy component que hicimos al inicio en wallet.

La estructura actual se ve así:

Ahora, crearemos la vista de inicio, en src/components/wallet/components/start:

Lo que hicimos fue añadir un titulo lindo a la app, además de las dos opciones de las que hablamos anteriormente:

  1. Crear una nueva cuenta: Esta opción ejecuta la función createAccount con la cual generamos las llaves utilizando los scrips que modificamos anteriormente, y las guardamos en localStorage para mantener la información de la sesión. Después, actualizamos la vista para ir a la vista de Copy
  2. Importar una cuenta: Normalmente, puedes entrar a una wallet utilizando tus llaves privadas, o, en este caso el secret, para ello, validamos que sea de formato correcto, y generamos la llave publica con el SDK de Stellar, actualizamos la información de sesión y lo mandamos a la vista principal.

Justo ahora, si añadiste los dummy components en las otras carpetas, tu aplicación se verá así:

El siguiente paso es añadir la vista de Copy, la cuál añadiremos en src/components/wallet/copy-key.js

Aquí sólo mostraremos el secret, con un botón para copiarlo, y, la posibilidad de confirmar que se copió, o de regresar a la pantalla inicial.

El funcionamiento es sencillo, aquí recomiendo que añadas un poco más de funcionalidad, ya que, como sabes, el manejo del secret es algo delicado, así que como reto, podrías intentar añadir más validaciones para dejarlo avanzar.

En este punto, si inicias la aplicación y te vas directo a crear una cuenta, lo que verás será lo siguiente:

Ahora, crearemos la parte principal de la aplicación. No obstante, es necesario dividir la lógica en bloques un poco más pequeños para separar correctamente las responsabilidades:

  1. Crearemos un componente que se hará cargo de mostrar los datos de la cuenta, que es la llave pública y el balance
  2. También añadiremos otro componente con la lógica para realizar el envío de la transacción
  3. Finalmente, un componente para manejar el chequeo de balances para otras cuentas

Toda esta lógica la agregaremos en src/components/wallet/components/main:

Notarás que he creado otra carpeta components interna, aquí irán los componentes que te mencioné, por lo que puedes llenarlos con dummy data por ahora, más adelante te compartiré su contenido.

Al añadir la carpeta y los dummy components, la estructura de archivos nos quedará así:

Enseguida, procederemos a añadir la lógica correspondiente a cada uno de los subcomponentes, donde se realizarán las funciones principales, así que primero añadiremos el contenido de account-data:

Aquí, tomaremos la llave pública cargada directamente desde el componente padre, y la cuenta cargada, con la que mostraremos los balances.

En caso de que tu cuenta sea nueva, el único tipo de balance que se mostrará será native, pero recuerda que puedes tener diferentes tipos de balance en distintas currencies.

El siguiente componente que agregaremos, será el de send-transaction:

En este componente estamos tomando toda la lógica de nuestro script que utilizábamos anteriormente para mandar la transacción, ahora, simplemente lo estamos conectando con la interfaz, y mostrando los errores correspondientes en caso de haber.

Finalmente, añadimos el bloque para checar el balance de otra cuenta, con la cuál podemos verificar que nuestra transacción funcionó correctamente. Esta lógica irá en el archivo de balance-checker:

¡Y listo! Si todo ha salido bien hasta este punto, tendrás tu aplicación funcionando correctamente.

Usando nuestra DApp

Aplicación funcionando

Para probarla, puedes enviar algo de XLM a la siguiente dirección, la cuál es una cuenta prueba que agregué para efectos del tutorial:

GDC75JQ6SOC3EJU5FL2IO6JL5Y2HUEPZQBVAM2TESCLG5NMYPSX6JJRP

Sólo colócala en el input de destinatario, y coloca un número válido de XLM, luego haz click en enviar:

Dicha transacción la puedes comprobar en Horizon con el siguiente link:

https://horizon-testnet.stellar.org/transactions/{hash}

Un ejemplo de los datos de una transacción, los puedes verificar aquí.

En seguida, puedes comprobar el balance de la cuenta destino, para verificar si existe un cambio en su balance, y por lo tanto, que tu transacción llegó perfectamente bien:

Por último, verás que hay un botón para salir de la cuenta, el cuál remueve absolutamente todos los datos del navegador, por lo que si el usuario no guardó su llave secreta, básicamente significa que la habremos perdido para siempre.

Como reto, te dejo de tarea que añadas una validación extra antes de salir, para evitar accidentes en un hipotético caso de uso real.

Si quieres probarlo, puedes hacer click, y regresar a la pestaña principal, verás que ya no puedes acceder de ninguna forma a los datos de esa cuenta.

Como siempre, ya sabes que puedes revisar el contenido final del proyecto en el repositorio original, que es el que descargaste al inicio, tan sólo moviéndote a la rama principal:

git checkout master

Conclusión

Algo que mencioné en el artículo pasado, es que Stellar tiene una gran Developer Experience, por lo que es muy sencillo utilizar sus herramientas y familiarizarse con los conceptos. No obstante, esto es algo que no siempre pasa, y que aveces puede ser complicado de entender. Sin embargo, es necesario que existan desarrolladores dispuestos a crear herramientas que ayuden a la adopción de las tecnologías blockchain.

Particularmente, con este tutorial, podrás ver un primer caso de uso con un SDK, integrado a una aplicación web con estándares similares a los de producción. Está en ti ahora aprovechar este conocimiento para construir una aplicación más robusta.

De la misma forma que en el tutorial pasado, te sugiero que tomes algunas de las ideas de la lista pública que tiene Stellar para desarrollar, y así, utilizar la arquitectura de proyecto de este nuevo tutorial para poner en práctica tus habilidades.

--

--

Ernesto Garcia N
Blockchain Academy Mexico

Ethereum Developer @OpenZeppelin | Intern twice @Google | Blockchain Development Teacher @blockdemy and @platzi