npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

cliente-blockchain-bo

v1.1.3

Published

Biblioteca interacción blockchain hyperledger

Downloads

42

Readme

Biblioteca de interacción con cadena de bloques hyperledger fabric

Colección de funciones para interactuar con la cadena de bloques. Usa las librerías fabric-client o fabric-network (a elección).

Instalación

npm install --save cliente-blockchain-bo

Requerimientos

Se conecta a una cadena de bloques mediante un contrato inteligente instalado en la blockchain, el nombre del contrato inteligente (chaincode) y las credenciales para la interacción se encuentran en archivos de configuración y llaves.

  • El chaincode se especifica en el archivo config.yaml. La ubicación de este archivo se especifica al inicializar esta biblioteca (ver ejemplos de inicialización).
  • Las credenciales de conexión se encuentran en los directorios crypto-config. La ubicación de estos directorios se especifica en el archivo config.yaml.
  • Para conectarse se requieren credenciales de usuarios enrolados que se guardan en carpetas.
    • En caso de usar fabric-network (recomendado) en una carpeta wallet
    • En caso de usar fabric-client (experimental) en una carpeta hfc-key-store

Inicialización

let blockchainClienteBo = require("cliente-blockchain-bo");

// Inicializar
const bcCliente = await blockchainClienteBo.iniciar("<ruta absoluta del archivo de configuracion config.yaml>");
if (bcCliente.iniciado === false) {
  // caso erroneo
  // console.log(boCliente.errors);
}

// ejemplo suponiendo que el archivo de configuracion config.yaml esta en el directorio actual
bcCliente = await blockchainClienteBo.iniciar(process.cwd() + '/config.yaml');

Uso

Fabric Network

Usando la biblioteca de inserción/consulta recomendada.

Introducir datos

 
 try {
    let respuesta = await boClient.escribirRegistroFabricNetwork({
      fcn: 'funcion_fcn',
      chaincode: 'nombre_del_chaincode'
    },
                                                        // argumentos (todos deben ser string)
                                                        'argumento 1',
                                                        'argumento 2',
                                                        // ...
                                                        'argumento n'
                                                       );
	console.log('Respuesta en bruto:', respuesta);
    console.log('Respuesta toString:', respuesta.toString());
  } catch (e) {
    console.log(' --- error al escribir datos\n', e);
  }

Consultar datos

  try {
    resp = await boClient.consultarRegistroFabricNetwork({
      chaincode: 'nombre del chaincode',         // opcional
      fcn: 'funcion fcn',                        // opcional
	  timeout: 20000,                            // opcional
    }, 'identificador es obligatorio');
    
	console.log('respuesta en bruto::', resp);
	console.log('respuesta toString()', resp.toString());
  } catch (e) {
    console.log('error al consultar:', e);
  }

Fabric Client

Para escribir, la biblioteca selecciona al azar el peer al que envía la petición para escritura.

// escribir
let resultado;
try { 
  // se indican parametros
  res = await boClient.escribirRegistro({
      identificador: 'identificador unico', 
      datos: datos,                         // array de datos que se van a introducir (de acuerdo al chaincode)
      timeout: 12000,                       // maximo tiempo de espera en este caso 12s. (opcional)
	  autogenerarIdentificador: false,      // Para obviar el identificador y usar el transaction_id como identificador unico (opcional)
      maximoIntentos: 3,                    // Indica maximo numero de intentos (opcional)
	  chaincode: 'nombre',                  // nombre de chaincode especifico (opcional)
	  fcn: 'funcionChaincode',              // funcion del chaincode a usar (opcional)
	  nArgIdentificador: <number>           // Para mandar el identificador como numero de argumento indicado (opcional)
    });
  if (resultado.finalizado !== true) {
    // error
  }
} catch(e) {
 // Error general
}

// consultar
let consulta;
try {
  consulta = await bcCliente.consultarRegistro('<identificador>');
  // otras formas de consultar
  // La siguiente especifica un timeout de 5000 ms, 5 intentos como maximo, usa el chaincode 'n1' y la funcion 'fcn1' de ese chaincode
  // consulta = await bcCliente.consultarRegistro('<identificador>', 5000, 5, 'n1', 'fcn1'); 

  if (consulta.finalizado !== true) {
    // caso erroneo
  }
  // mostrar datos
  console.log(consulta.resultado); 
  /* NOTA: consulta.resultado es la respuesta del chaincode y el tipo de respuesta esta definida por este. Si la respuesta fuese un buffer si es conveniente se puede convertir a cadena con:
  consulta.resultado.toString(); */
  } catch(e) {
    // .. caso erroeno..
  }
  
  
  // consultar detalles de una transaccion
  let detalles;
  try {
    detalles = await bcCliente.consultarDetallesTransaccion(<transaction_id>)
  } catch (e) {
    // caso erroneo
  }

  // Tambien existen los metodos que usan fabric-network: consultarRegistroFabricNetwork, escribirRegistroFabricNetwork, que hacen tareas similares *experimentales*.

Archivo de configuración

El <archivo de configuracion> debe tener la estructura que se proporciona en el archivo config.sample.yaml.

Estructura del archivo de configuración:

---
name: nombre-de-la-red
version: 1.0.0
user: Nombre de usuario enrolado
channel: Nombre del canal
# se recomiendan rutas absolutas
walletPath: "<ruta del directorio wallet>" # si se usa fabric-network
hfcKeyStorePath: "<ruta del directorio hfc-keysotre>" # si se usa fabric-client
chaincode:
  name: Nombre del chaincode
  fcns:
    introducir: createDoc
    consultar: queryDoc
	fcn1: nombreOtraFuncion1
    fcn2: nombreOtraFuncion2
client:
  organization: Nombre de la Organizacion
  connection:
    timeout:
      peer:
        endorser: '300'
organizations:
  Dominio:
    mspid: OrganizacionMSP
    peers:
    - peer0.dominio.gob.bo
    - peer1.dominio.gob.bo
    - peer2.dominio.gob.bo
    certificateAuthorities:
    - ca.gob.bo
peers:
  peer0.dominio.gob.bo:
    url: grpcs://<ip-peer0>:<puerto>
    tlsCACerts:
	  # recomendado usar rutas absolutas
      path: "/home/alguien/crypto-config/peerOrganizations/dominio.gob.bo/tlsca/tlsca.dominio.gob.bo-cert.pem"
    grpcOptions:
      ssl-target-name-override: peer0.dominio.gob.bo
  peer1.dominio.gob.bo:
    url: grpcs://<ip-peer1>:<puerto>
    tlsCACerts:
	  # recomendado usar rutas absolutas
      path: "/home/alguien/crypto-config/peerOrganizations/dominio.gob.bo/tlsca/tlsca.dominio.gob.bo-cert.pem"
    grpcOptions:
      ssl-target-name-override: peer1.dominio.gob.bo
  peer2.dominio.gob.bo:
    url: grpcs://<ip-peer2>:<puerto>
    tlsCACerts:
	  # recomendado usar rutas absolutas
      path: "/home/alguien/crypto-config/peerOrganizations/dominio.gob.bo/tlsca/tlsca.dominio.gob.bo-cert.pem"
    grpcOptions:
      ssl-target-name-override: peer2.dominio.gob.bo
certificateAuthorities:
  ca.gob.bo:
    url: https://<ip-ca>:<puerto>
    caName: ca.gob.bo
    tlsCACerts:
	  # recomendado usar rutas absolutas
      path: "/home/alguien/crypto-config/peerOrganizations/dominio.gob.bo/tlsca/tlsca.dominio.gob.bo-cert.pem"
    httpOptions:
      verify: false

Nota sobre resolución de dominios

En algunos casos es necesario hacer que el sistema resuelva la dirección IP de los peers por ejemplo si peer0.dominio.gob.bo apunta a la ip: 192.168.1.100, en Debian se puede asociar ips y dominios agregando en /etc/hosts, por ejemplo:

192.168.1.100 peer0.dominio.gob.bo
192.168.1.102 peer1.dominio.gob.bo
192.168.1.104 peer2.dominio.gob.bo
192.168.1.103 ca.gob.bo

Ejemplos de uso básico

Primero se require instalar todas las dependencias y ajustar el archivo config.yaml.

Fabric network (recomendado)

Script test-fabric-network.js, se ejecuta con node test-fabric-network.js.

const blockchainClienteBo = require('cliente-blockchain-bo');

async function main() {
  const boClient = await blockchainClienteBo.iniciar(process.cwd() + '/config.yaml');
  console.log('boCLiente Object Inicializacion:::', boClient);

  let resp;
  // // escribir enviando un identificador
  const chaincodeName = 'chaincodeprueba';

  let n = Math.random()*99999999999;
  let hashDatos = '702996976c';
  let ci = '900900900';
  let nombres = 'Lucaz Monsar';
  let primer_apellido = 'Tritón';
  let segundo_apellido = 'Montes';
  let descripcion = 'Registro-de-pruebas';
  let extra = 'Algoritmo Hash Usado: sha256';

  let tx_id;
  
  // // escribir datos
  console.log(`Escribir por chaincode ${chaincodeName}:`);
  console.log('-----------------------------------------------------------------------------');
  try {
    resp = await boClient.escribirRegistroFabricNetwork({
      autogenerarIdentificador: true,
      timeout: 12000, 
      fcn: 'initDoc',
      chaincode: chaincodeName
    },
                                                        // argumentos
                                                        hashDatos,
                                                        ci,
                                                        nombres,
                                                        primer_apellido,
                                                        segundo_apellido,
                                                        descripcion,
                                                        extra                                                       
                                                       );
    console.log('------------ detalles respuesta');
    console.log(resp);
    console.log('--- to String');
    console.log(resp);
    let respuesta = JSON.parse(resp.toString());
    tx_id = respuesta.TxId; // transaction_id
    console.log('--- JSON.parse .... to String');
    console.log(JSON.parse(resp.toString()));
    console.log(respuesta.Timestamp);
    console.log(respuesta.TxID);
    console.log('--- respuesta.Value');
    console.log(respuesta.Value);
  } catch (e) {
    console.log(' --- error al escribir datos\n', e);
  }
  console.log('------ end escribir ---');
  setTimeout(async () => {
    // consultar datos
    console.log(`\nConsultar por CI (historico) ${ci}`);
    console.log('-----------------------------------------------------------------------------');
    try {
      resp = await boClient.consultarRegistroFabricNetwork(
        {
          chaincode: chaincodeName,
          fcn: 'queryDocsByCI'
        },
        ci // identificador para la consulta
      );
      console.log('---- resultado (completo)');
      console.log(resp);
      console.log('---- res.resultado.toString()');
      console.log(resp.toString(), '\n\n');
      let parsed = JSON.parse(resp.toString());
      console.log(parsed);
      console.log('ci:', parsed[0].Record.ci);
      console.log('hashdatos:', parsed[0].Record.hashdatos);
      console.log('transactionid:', parsed[0].Record.transactionid);
      console.log('nombres:', parsed[0].Record.nombres);
      
    } catch (e) {
      console.log('Error consulta:', e);
    }

    
    console.log(`\nConsultar por hash (historico) ${hashDatos}`);
    console.log('-----------------------------------------------------------------------------');
    try {
      resp = await boClient.consultarRegistroFabricNetwork({
        chaincode: chaincodeName,
        fcn: 'getHistoryForDoc'
      }, hashDatos);
      console.log('---- resultado (completo)');
      console.log(resp);
      console.log('---- res.resultado.toString()');
      console.log(resp.toString(), '\n\n');
      console.log(JSON.parse(resp.toString()));
    } catch (e) {
      console.log('Error consulta:', e);
    }

    process.exit(0);
  }, 3550);
}

main();

Fabric client

Script test-fabric-client.js, se ejecuta con node test-fabric-client-js.

const blockchainClienteBo = require('cliente-blockchain-bo');

async function main() {
  const boClient = await blockchainClienteBo.iniciar(process.cwd() + '/config.yaml');

  let res;
  // escribir enviando un identificador
  console.log('\n---------- escribir con identificador dado ------------------');
  let identificador = Math.random()*1000000; // numero al azar
  // siempre un array, en este caso un array de un elemento.
  let datos = [JSON.stringify({
    'argumento1',                   // arg1
    45121.1141,                     // arg2
    razon: `Pruebas con id ${identificador}` // arg3
  })];
  let tx_id;
  try {
    res = await boClient.escribirRegistro({
      identificador: 'test' + identificador,
      datos: datos,
      timeout: 12000,
	  chaincode: 'c1',
	  fcn: 'createDoc'
    });
    console.log('Escribir resultado::::::::::', res);
    tx_id = res.resultado.tx_id; // transaction_id
  } catch (e) {
    console.log('escribir error::::::', e);
  }

  console.log('consultar:::::::::::::');
  try {
    res = await boClient.consultarRegistro('test' + identificador);
    console.log('resultado.toString():::::', res.resultado.toString());
  } catch (e) {
    console.log('consultar error xxxxx', e);
  }

  // escribir usando el transaction_id como identificador
  try {
    console.log('\n escribir usando transaction_id como identificador ------------------------');
    datos = [JSON.stringify({
      razon: `Introduciendo datos con transaction_id como identificador`,
      adicional: `test ${Math.random()*1000000}`
    })];
    res = await boClient.escribirRegistro({
      datos: datos,
      timeout: 12000,
      autogenerarIdentificador: true
    });
    console.log('Escribir resultado:::::::::::::::::', res);
    tx_id = res.resultado.tx_id;
  } catch (e) {
    console.log('escribir error::::::', e);
  }

  console.log('consultar por transaction_id:::::::::::::');
  try {
    res = await boClient.consultarRegistro(tx_id);
    console.log('resultado.toString() ::::::', res.resultado.toString());
  } catch (e) {
    console.log('consultar error xxxxx', e);
  }
  
  console.log('consultar detalles de una trasaccion::::::::::::::::::');
  try {
    const util = require('util');
    res = await boClient.consultarDetallesTransaccion(tx_id);
    console.log('res.resultado\n:', util.inspect(res.resultado, {showHidden: false, depth: null}));
  } catch (e) {
    console.log('Error:', e);
  }

  process.exit(0);
}

main();