Las tecnologías Blockchain son, sin duda, unas de las más disruptivas de los últimos años que cambiarán a corto-medio plazo muchos factores sociales tal y como los conocemos.

Yendo a un nivel más específico, dentro de Blockchain, ya hicimos en el blog una breve introducción a la tecnología DLT de IOTA y Tangle. Hoy damos un paso más y veremos unos ejemplos sencillos de cómo generar seeds, address, realizar transacciones entre monederos además de cómo leer las transacciones de una cola MQ.

Esto nos servirá como base para poder dar pasos orientados a diversos casos de uso de IOTA como, por ejemplo, aplicaciones IoT. ¡Empezamos!

Contexto

Ahora ya que hemos visto las propiedades básicas de IOTA, junto con la definición de términos, podemos arrancar nuestros ejemplos de software. Lo que vamos a desarrollar se puede resumir en las siguientes acciones:

Implementando transacciones

Para estos ejemplos vamos a utilizar NodeJS, por lo que debemos tener instalado el entorno de desarrollo. A partir de aquí, instalar IOTA es sencillo:

Dentro de nuestra carpeta de trabajo donde guardaremos los programas Node, ejecutamos:

npm install @iota/core

Esto nos instalará la librería de IOTA con sus dependencias. La información de la librería la podemos encontrar en esta web. Creamos el fichero address.js que con el siguiente contenido:

///////////////////////////////////
// Generación de carteras(address)
///////////////////////////////////
const Iota = require('@iota/core');

const iota = Iota.composeAPI({
    provider: 'https://nodes.devnet.thetangle.org:443'
});

const seed =
'SENDER99999TROLL9SEED9TROLL9SEED9TROLL9SEED9TROLL9SEED9TROLL9SEED9TROLL9SEED9TROL';

iota.getNewAddress(seed, {index: 0, security: 2}).then(address => console.log(address));

Al ejecutarlo con node address.js este nos devuelve las tres primeras address en base a la seed:

DOXUKFZZHNZDKGICPMYMOWNOIPCB9CDKZAJJPRESBQXPLAAAWYNRDWNR9EHMDFCEXQSKZMEDJFHOXSRLC

Es importante indicar que este proceso es offline, de manera que todo se genera en nuestra máquina local.

La seed del ejemplo anterior está generada manualmente cumpliendo con el patrón de 81 caracteres compuesto de A a Z y puede contener el caracter 9, también podemos generar una seed automáticamente con esta sentencia desde la consola de linux:

cat /dev/urandom |tr -dc A-Z9|head -c${1:-81}

Nos devolverá la siguiente cadena:

‘STKGY9PTOTVOGGQENVQMARJQIDKDSZVHIGZTBOT9BHQHWCZXESAAXA99GZRYGESQLQLSJVGEFPIJFZEYY’

Que asignaremos a la variable MySeed.

El código que hay a continuación muestra cómo realizar dos transacciones de forma simultánea en la misma invocación.

Es importante señalar que no hay un límite de envío de transacciones en la misma invocación, pero sí que hay que realizar la prueba de trabajo por cada una de ellas.

Instalamos la dependencia:

npm install @iota/core

Creamos el fichero txValue0.js que con el siguiente contenido:

///////////////////////////////////////////////
// Envío de transacciones con valor 0 y mensaje
///////////////////////////////////////////////
const IOTA = require('@iota/core')
const { asciiToTrytes } = require('@iota/converter')

var NodeURL = "https://nodes.devnet.thetangle.org:443";
const iota = IOTA.composeAPI({
  'provider': NodeURL
});
var MySeed = "SENDER99999TROLL9SEED9TROLL9SEED9TROLL9SEED9TROLL9SEED9TROLL9SEED9TROLL9SEED9TROL";
var TargetAddress1 = "QQS9DSNXQE9FK9JSRNWPPOWYAYTUV9NIIEDTTHSJCNIHHWSUBISAJJYXGITIZRGHBPKSPTIETCOFYORLZ";
var TargetAddress2 = "JWFDXHFMEVPVYKEBPWBHDKU9ADBPSU9HBIGEZ9ZYWPKDZFXSYCPAZINHUNGRY9VGKJDW9NTHFYSNBYGICHCVGJZMAX";
var NowIs = new Date()

var msg1 = asciiToTrytes("Esta es una prueba de tx sin valor, con fecha, " + NowIs)
var msg2 = asciiToTrytes("Esta es otra prueba de tx sin valor con fecha, " + NowIs)


var pt = {
  'address': TargetAddress1,
  'value': 0,
  'message': msg1,
  'tag': 'TESTING99IOTA99TUTORIAL9'
}
var pt2 = {
  'address': TargetAddress2,
  'value': 0,
  'message': msg2,
  'tag': 'TESTING99IOTA99TUTORIAL9'
}
const transfers = [pt, pt2]
iota.prepareTransfers(MySeed, transfers)
.then(trytes => iota.sendTrytes(trytes, (depth = 3), (mwm = 9)))
.then(bundle => {
  console.log(bundle)
})
.catch(err => {
  console.error(err)
})

Ejecutamos con node txValue0.js y nos devuelve por consola:

Al ejecutar el código del ejemplo ‘Envío de transacciones con valor 0 y mensaje’ del fichero txValue0.js, muestra por consola un json con los valores de la transacción, a destacar el campo signatureMessageFragment que contiene el texto del mensaje enviado en formato ternario. La longitud máxima de este campo es de 2187 caracteres.

Las transacciones que realicemos podemos verlas en un explorador de transacciones. En nuestro caso, acudiremos a la web thetangle.org para la red principal o a devnet.thetangle.org para la red de pruebas.

El explorador nos permitirá examinar el estado de la transacción: en particular si está o no finalizada, y otras de sus propiedades como por ejemplo la fecha y hora en la que se realizó o a quien se envió.

Sobre el ejemplo anterior, aclarar que el cálculo del PoW se realiza de forma individual de las dos transacciones previas, es decir si el envío de nuestra transacción se realiza a 10 usuarios diferentes, significa que hay que validar el PoW de 20 usuarios previos.

También añadir que el PoW se puede delegar, de forma que en lugar de realizarlo en el cliente se puede asignar a un nodo servidor de confianza con más recursos de computación.

Por ejemplo, en la web contamos con una API que nos ofrece usar como servicio un módulo FPGA diseñado para contener la implementación del core de IOTA.

El resultado es el siguiente: en el caso de que se realice en el cliente el cálculo del PoW, el tiempo medio es de 15 segundos por transacción, si se delega a este módulo FPGA el tiempo baja a menos de un segundo por transacción.

Por lo que acabamos de comentar, es importante tener en cuenta el número de transacciones que se van a realizar en el momento de diseñar la aplicación.

Por ejemplo, si es una aplicación que va a ejecutarse desde nuestro dispositivo móvil, como comprar nuestro libro preferido en la librería de barrio o, por lo contrario, si somos una entidad financiera que genera miles de transacciones al día desde un centro de datos.

Hecha la aclaración de cómo gestiona múltiples transacciones en una ejecución de nuestro ejemplo, continuamos con la programación de una transacción con valor económico.

En esta parte necesitaremos tokens de IOTA y usaremos la red de desarrollo para almacenar las transacciones.

Primero necesitaremos dos seed, una para generar un address donde almacenar y desde donde enviar los primeros tokens y la segunda para generar un address donde recibir los tokens, en nuestro ejemplo también somos la parte receptora.

Ahora vamos a solicitar tokens de prueba para la red de desarrollo, entrando en esta url. Esta web nos solicita un address que podamos gestionar donde recibir los token.

Una vez solicitados los token, podemos consultar su estado en este explorador. Creamos el fichero sendTokens.js que con el siguiente contenido:

///////////////////////////////
// Enviando IOTA Tokens
///////////////////////////////
const IOTA = require('@iota/core')
const { asciiToTrytes } = require('@iota/converter')

var NodeURL = "https://nodes.devnet.thetangle.org:443";
const iota = IOTA.composeAPI({
  'provider': NodeURL
});

const seed =
'SENDER99999TROLL9SEED9TROLL9SEED9TROLL9SEED9TROLL9SEED9TROLL9SEED9TROLL9SEED9TROL'


const main = async () => {
const receivingAddress = 'VRTZCRMHOPYWRAODZVFRJCUVPSUTFYKTIFMFAUOMNGWSSCINVVTJ9ZEHLIMUUXQCHSOAIY9XBJAJWS9VZ'
var NowIs = new Date()
var msg1 = asciiToTrytes("HOLA te envio 500i, " + NowIs)

const transfers = [{
   value: 500,
   address: receivingAddress,
   tag: 'MYMAGIC',
   signatureMessageFragment: msg1
 }]
console.log('Enviando 500i a ' + receivingAddress)
try {
 const trytes = await iota.prepareTransfers(seed, transfers)
 const response = await iota.sendTrytes(trytes, 3, 9)
 console.log('Completed TXs')
 response.map(tx => console.log(tx))
} catch (e) {
 console.log(e)
}
}
main()

Al ejecutarlo con node sendTokens.js realiza la transferencia por valor de 500i.

En el ejemplo anterior, donde se realiza una transacción sin valor económico podíamos ver que el campo value es igual a cero, en cambio en esta última ejecución podemos ver en la traza que campo value tiene un valor económico de 500i.

También podemos ver en el explorador la transacción que acabamos de realizar a través de este enlace.

Programáticamente hemos realizado el envío de transacciones. Ahora, veamos cómo leer esas transacciones.

En este ejemplo pedimos expresamente que busque todas las transacciones que están contenidas en una cartera.Creamos el fichero fetchTx.js que con el siguiente contenido:

///////////////////////////////
// Leyendo tx message 
///////////////////////////////
const iotaLibrary = require('@iota/core')
const Converter = require('@iota/converter')
const iota = iotaLibrary.composeAPI({
 provider: 'https://nodes.thetangle.org:443'
})
const address = 'QQS9DSNXQE9FK9JSRNWPPOWYAYTUV9NIIEDTTHSJCNIHHWSUBISAJJYXGITIZRGHBPKSPTIETCOFYORLZ'
iota
 .findTransactionObjects({ addresses: [address] })
 .then(response => {
   console.log('Encoded message:')
   console.log(response[0].signatureMessageFragment)
   const trytes = response[0].signatureMessageFragment.slice(0, -1)
   const data = Converter.trytesToAscii(trytes)
   console.log('Decoded message:')
   console.log(data)
 }).catch(err => {
   console.error(err)
 })

Al ejecutar el programa con node fetchTx.js y podemos ver en la consola el mensaje que hemos mandado previamente, en Trytes y ascii.

Por último en este ejemplo vamos a escuchar por una cola Mq las transacciones que van pasando por el Tangle, tenemos la posibilidad de solo escuchar las que nos interesa, por ejemplo nuestra cartera.

Para esto necesitamos instalar la dependencia de ZMQ para NodeJS, ejecutaremos en consola:

npm i zeromq

Creamos el fichero listenTx.js con el siguiente contenido:

///////////////////////////////
// Leyendo Tx con MQ
///////////////////////////////

let zmq = require('zeromq')
let sock = zmq.socket('sub')
sock.connect('tcp://db.iota.partners:5556')
if (!process.argv[2]) {
 console.log('Escuchando todas las transacciones del nodo')
 console.log('---------------------')
 console.log('Nota: Si quieres escuchar transacciones de tu address:')
 console.log('node listen.js ‘address’ ')

 sock.subscribe('tx')
} else {
 console.log('Escuchando transacciones de la address: ' + process.argv[2])
 sock.subscribe(process.argv[2])
}

sock.on('message', msg => {
 const data = msg.toString().split(' ') 
 switch (
   data[0] 
 ) {
   case 'tx': 
     console.log(“Cualquier TX!”, data)
     break
   case process.argv[2]:
     console.log(“Mi TX! “, data)
     break
 }
})

Finalmente cuando la transacción es aprobada, se muestra en consola la información de la cola.

Conclusiones

Después de ver cómo se han ejecutado los ejemplos por lo que los saldos no pueden variar, os animamos a generar seeds, address, realizar pruebas de envío y lectura de transacciones y comprobar que la generación de transacciones no es complicada.

Además, si nos basamos en NodeJS solo es necesario importar la librerías y con poco código podremos interactuamos con la red de IOTA de una forma sencilla.

Happy coding!

Cuéntanos qué te parece.

Enviar.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.