¿Dónde están mis Bitcoins? Cómo consultar un wallet con NodeJs

 

bitcoin_wall.jpg

En este post explicaremos cómo con JavaScript es posible consultar un wallet y comprobar que una cierta cantidad de Bitcoins ha llegado a él.

El enfoque que utilizaremos será el de conectarnos a un “wallet local” que tendremos instalado previamente en nuestro PC en modo “autopilot”.

Bitcoin Core

Para ello usaremos Bitcoin Coreel monedero “Full Client” oficial para PC creado inicialmente por Satoshi Nakamoto, que convirtie tu ordenador en un nodo más de la red Bitcoin. Bitcoin Core lleva incluida la librería Bitcoind con una interfaz gráfica, pudiéndose ejecutar desde una línea de comandos o a través de un escritorio. Además puede ser controlado de forma remota usando el protocolo JSON-RPC. 

Para que el programa que vamos a realizar funcione, necesitaremos recibir dinero en una dirección de Bitcoin de nuestro wallet.

Pasos a seguir:

  • Instalando node-bitcoin, una biblioteca JavaScript que se conecta a Bitcoin Core

Para instalarla:

npm install bitcoin

  • Arrancar Bitcoin Core

Descargar “Bitcoin Core” de https://bitcoin.org/en/download

Arrancar “Bitcoin Core” en modo servidor. Este programa abrirá un socket el cual utilizaremos para conectarnos desde nuestro programa JavaScript.

En una consola de comandos situarnos en el directorio C:\Program Files (x86)\Bitcoin

Y ejecutamos: bitcoin-qt.exe –server

La primera vez que arranca “Bitcoin Core”  en modo servidor  te preguntará si quieres crear el fichero:  “bitcoin.conf”, en el cual podremos añadir un usuario y contraseña.

  • Creamos el fichero “holaDinero.js”
var bitcoin = require("bitcoin");
var client = new bitcoin.Client({
host: 'localhost',
port: 8332,
user: 'myUsername',
pass: 'myPassword'
});
var previousBalance = 0;
function mainLoop() {
client.getBalance('*', 0, function (err, balance) {
if (err) {
console.log(err);
} else if (balance > previousBalance) {
console.log("Hello Money! New balance: " + balance);
previousBalance = balance;
} else {
console.log("Nothing's changed.");
}
});
}
setInterval(mainLoop(), 5000);


Explicación del código

En la primera línea indicamos que estamos usando la librería “node-bitcoin”:

var bitcoin = require("bitcoin");

A continuación establecemos una conexión al monedero de “Bitcoin Core”.

Si estamos ejecutando nuestra aplicación en el mismo pc que “Bitcoin Core” nuestro host sería “localhost” (por defecto el nodo de Bitcoin correrá en el puerto 8332).

Utilizaremos el mismo usuario y contraseña que establecimos en el fichero “bitcoin.conf”. (C:\Users\<username>\AppData\Roaming\Bitcoin\bitcoin.conf.

var client = new bitcoin.Client({
host: 'localhost',
port: 8332,
user: 'myUsername',
pass: 'myPassword'
});

Definimos variable para guardar el importe previo de nuestro balance (var previousBalance).

var previousBalance = 0;

Ahora definimos un bucle que va a chequear el balance en nuestro monedero y nos informará cuando dicho balance haya sido modificado.

    • Con “getBalance”, preguntamos a “Bitcoin Core” por el estado actual del balance de nuestro monedero. Creamos una función callback, que llamará a function(err,balance) {}, cuando recibamos el resultado del balance.
    • Cuando el balance esté disponible, chequeamos si existe algún error y en tal caso lo visualizamos con “console.log(err)”
    • Seguidamente verificamos si el balance es superior al anterior, si es así mostramos un mensaje y actualizamos el anterior balance.
function mainLoop() {
client.getBalance('*', 0, function (err, balance) {
if (err) {
console.log(err);
} else if (balance > previousBalance) {
console.log("Hello Money! New balance: " + balance);
previousBalance = balance;
} else {
console.log("Nothing's changed.");
}
});
}
  • Por último creamos un “timer” que ejecuta la función “mainLoop” cada 5000 milisegundos.
setInterval(mainLoop(), 5000);

Para probar nuestro programa, ejecutamos el comando siguiente en una consola situandonos en el directorio que contiene holaDinero.js:

res1.png

 

Lo siguiente es enviar una cantidad de bitcoins a nuestro monedero administrado por “Bitcoin Core” desde otro monedero. Para ello, debes utilizar una dirección de bitcoin que puedes encontrar haciendo clic en el botón "Recibir" en Bitcoin Core.

De la forma en la que hemos escrito la aplicación, ésta contará el dinero que ha llegado a tu cartera solo si ha recibido una confirmación en la cadena de bloques. Dado que las confirmaciones suelen tardar unos 10-20 minutos, necesitarás
esperar un poco antes de ver lo siguiente:
 
res2.png

 

JSON-RPC API

La función “mainLoop” manda mensajes a “Bitcoin Core”. JSON-RPC permite enviar mensajes entre dos programas de una forma fácil.

El único comando que comunica con “Bitcoin Core” es “client.getBalance”, pero existen muchos más que permiten manipular direcciones de Bitcoin, modificar monederos, analizar transacciones y otras operaciones que queramos hacer en Bitcoin wallet. 

Limitaciones de escribir programas usando JSON-RPC

El principal inconveniente de realizar un programa que utilice un wallet de Bitcoin para controlar dicho monedero, es que a veces suele ser ineficiente.  Usando JSON-RPC podemos escribir un programa en JavaScript rápidamente, pero pueden existir problemas utilizando esta API.

Polling Vs Pushing

Un problema es que este programa usa “polling” para detectar cuando el dinero llega. “Polling” constantemente chequea el estado de “Bitcoin Core” preguntando a este software cada 5 segundos. Si necesitamos hacer una aplicación con alto rendimiento sería mejor usar “pushing”. “Pushing” implica que nuestra aplicación estaría esperando y sería notificada cuando el dinero llegue. Sin embargo, habilitar “pushing” es bastante difícil en “Bitcoin Core”.

Forks

Otro problema con nuestro programa es que la cadena de bloques de Bitcoin ya que a veces puede tener una bifurcación (forks), y pueden existir transacciones que dejen de estar confirmadas y, por lo tanto, obtendremos un balance erróneo. Este escenario es raro que ocurra, pero si estamos creando una aplicación que maneja cantidades elevadas de dinero este tipo de comportamientos hay que tenerlos en cuenta.

La solución sería usar client.listTransactions (en vez de client.getBalance), revisando todas las transacciones para determinar si implican envío de dinero a nuestro monedero en los últimos 5 segundos. 

Capacidad de cómputo

Por último, “Bitcoin Core” necesita para funcionar la cadena de bloques entera y gran capacidad de cómputo, y nuestro programa no necesitaría esta alta capacidad de procesamiento.

Para evitar todo esto la solución es escribir programas que se ejecuten directamente sobre la red de Bitcoin. Avanzaremos más en estos problemas en próximos posts.