Learning-Bitcoin-from-the-C.../pt/18_3_Accessing_Bitcoind_with_NodeJS.md
2021-09-29 08:42:17 -03:00

9.8 KiB
Raw Blame History

18.3: Acessando o Bitcoind com NodeJS

NOTA: Esta seção foi adicionada recentemente ao curso e é um rascunho inicial que ainda pode estar aguardando revisão.

Esta seção explica como interagir com o bitcoind usando a linguagem de programação NodeJS e o pacote BCRPC.

Configurando o Node.js

O BCRPC é construído em node.js. Portanto, primeiro precisamos instalar os pacotes node.js e o npm (o gerenciador de pacotes do node) em nosso sistema.

Se estiver usando uma máquina Ubuntu, podemos executar os seguintes comandos para obter uma nova versão do node.js, ao invés da versão terrivelmente desatualizada no sistema de pacotes do Ubuntu.

$ curl -sL https://deb.nodesource.com/setup_14.x | sudo bash -
$ sudo apt-get install -y nodejs
$ sudo npm install mocha -g

Configurando o BCRPC

Agora podemos clonar o pacote BCRPC do GitHub e instalar as dependências.

$ git clone https://github.com/dgarage/bcrpc.git
$ cd bcrpc
$ npm install

Para testar o pacote BCRPC, devemos primeiro definir as variáveis de ambiente para o rpcuser e rpcpassword. Como de costume, elas vêm do ~/.bitcoin/bitcoin.conf. Também devemos definir a porta RPC como sendo 18332, que deve ser a correta para a configuração Testnet padrão descrita nos documentos.

$ export BITCOIND_USER=StandUp
$ export BITCOIND_PASS=d8340efbcd34e312044c8431c59c792c
$ export BITCOIND_PORT=18332

⚠️ AVISO: Obviamente, você nunca colocaria sua senha em uma variável de ambiente em um ambiente de produção.

🔗 MAINNET VS TESTNET: A porta seria 8332 para uma configuração na Mainnet.

Agora podemos verificar se tudo está funcionando corretamente:

$ npm test

> bcrpc@0.2.2 test /home/user1/bcrpc
> mocha tests.js

  BitcoinD
    ✓ is running

  bcrpc
    ✓ can get info

  2 passing (36ms)

Parabéns, agora temos um wrapper RPC pronto para ser usado no Bitcoin com o Node.js e que está funcionando com as nossas configurações do Bitcoin.

Criando um Projeto BCRPC

Agora podemos criar um novo projeto Node.js e instalar o BCRPC via npm.

$ cd ~
$ mkdir myproject
$ cd myproject
$ npm init
  [continue with default options]
$ npm install bcrpc

Construindo Nossa Conexão

Em nosso diretório myproject, criamos um arquivo .js onde nosso código JavaScript será executado.

Podemos iniciar uma conexão RPC criando um RpcAgent:

const RpcAgent = require('bcrpc');
agent = new RpcAgent({port: 18332, user: 'StandUp', pass: 'd8340efbcd34e312044c8431c59c792c'});

Obviamente, nosso user e pass devem coincidir novamente com o que está em nosso ~/.bitcoin/bitcoin.conf, e usamos a port 18332 se estivermos na Testnet.

Fazendo uma chamada RPC

Usando o BCRPC, podemos usar os mesmos comandos RPC que normalmente usaríamos via bitcoin-cli com nosso RpcAgent, exceto que eles precisam estar em camelCase. Por exemplo, getblockhash seria getBlockHash.

Para imprimir o número do bloco mais recente, basta chamar o getBlockCount através do nosso RpcAgent:

agent.getBlockCount(function (err, blockCount) {
  if (err)
    throw Error(JSON.stringify(err));
  console.log(blockCount.result);
});

Fazendo uma chamada RPC com argumentos

As funções BCRPC podem aceitar argumentos. Por exemplo, o getBlockHash recebe o blockCount.result como uma entrada.

  agent.getBlockHash(blockCount.result, function (err, hash) {
    if (err)
      throw Error(JSON.stringify(err));
    console.log(hash.result);
  })

O resultado das funções BCRPC é um objeto JSON contendo informações sobre quaisquer erros e o id da solicitação. Ao acessar nosso resultado, adicionamos o .result no final dele para especificar que estamos interessados no resultado real, não em informações sobre os erros.

Executando Nosso Código

Podemos encontrar o código getinfo no diretório src/.

$ node getinfo.js
1831094
00000000000002bf8b522a830180ad3a93b8eed33121f54b3842d8838580a53c

Isso é com o que a saída do exemplo acima se pareceria se substituíssemos o console.log(blockCount.result); e o console.log(hash.result); por console.log(blockCount); e console.log (hash);, respectivamente:

{ result: 1774686, error: null, id: null }
{
  result: '00000000000000d980c495a2b7addf09bb0a9c78b5b199c8e965ee54753fa5da',
  error: null,
  id: null
}

Pesquisando por Fundos

É útil, ao aceitar Bitcoin, verificar o Bitcoin recebido em um endereço específico em nossa carteira. Por exemplo, se administrássemos uma loja online que aceita Bitcoin, para cada pagamento de um cliente, geraríamos um novo endereço, mostraríamos esse endereço ao cliente e, em seguida, verificaríamos o saldo do endereço após algum tempo, para certificar-se de que o montante foi recebido:

agent.getReceivedByAddress('mpGpCMX6SuUimDZKiVViuhd7EGyVxkNnha', function (err, addressInfo) {
  if (err)
    throw Error(JSON.stringify(err));
  console.log(addressInfo.result);
});

NOTA: Obviamente, precisaremos inserir um endereço reconhecido por nossa máquina.

Por padrão, esta função verifica as transações que foram confirmadas uma vez, no entanto, podemos aumentar para um número maior, como 6:

agent.getReceivedByAddress('mpGpCMX6SuUimDZKiVViuhd7EGyVxkNnha', 6, function (err, addressInfo) {
  if (err)
    throw Error(JSON.stringify(err));
  console.log(addressInfo.result);
});

Pesquisando Informações da Carteira

Também podemos procurar informações adicionais sobre nossa carteira e visualizar nosso saldo, contagem de transações etc.

agent.getWalletInfo(function (err, walletInfo) {
  if (err)
    throw Error(JSON.stringify(err));
  console.log(walletInfo.result);
});

O código está disponível como walletinfo.js.

$ node walletinfo.js
0.008498
{
  walletname: '',
  walletversion: 169900,
  balance: 0.010438,
  unconfirmed_balance: 0,
  immature_balance: 0,
  txcount: 4,
  keypoololdest: 1596567843,
  keypoolsize: 999,
  hdseedid: 'da5a1b058deb9e51ecffef1b0ddc069a5dfb2c5f',
  keypoolsize_hd_internal: 1000,
  paytxfee: 0,
  private_keys_enabled: true,
  avoid_reuse: false,
  scanning: false
}

Ao invés de imprimirmos todos os detalhes associados à nossa carteira, podemos imprimir informações específicas, como nosso saldo. Como um objeto JSON está sendo acessado, podemos fazer isso alterando a linha console.log(walletInfo.result); para console.log(walletInfo.result.balance);:

Criando um Endereço

Também podemos passar argumentos adicionais para os comandos RPC. Por exemplo, o seguinte gera um novo endereço legado, com o sinalizador -addresstype.

agent.getNewAddress('-addresstype', 'legacy', function (err, newAddress) {
  if (err)
    throw Error(JSON.stringify(err));
  console.log(newAddress.result);
});

Isso é o mesmo que executar o seguinte na linha de comando:

$ bitcoin-cli getnewaddress -addresstype legacy
mtGPcBvRPZFEHo2YX8un9qqPBydhG82uuZ

No BCRPC, geralmente podemos usar os mesmos sinalizadores que no bitcoin-cli no BCRPC. Embora usamos o camelCase (getNewAddress) para os métodos, os sinalizadores, que normalmente são separados por espaços na linha de comando, são colocados em strings e separados por vírgulas.

Enviando uma Transação

Podemos enviar saldos para um endereço muito facilmente, usando a função sendToAddress:

agent.sendToAddress(newAddress.result, 0.00001, function(err, txid) {
  if (err)
    throw Error(JSON.stringify(err));
  console.log(txid.result);
});

Isso deve retornar o txid da transação:

1679bee019c61608340b79810377be2798efd4d2ec3ace0f00a1967af70666b9

Pesquisando uma Transação

Agora podemos desejar visualizar uma transação, como a que acabamos de enviar.

agent.getTransaction(txid.result, function (err, transaction) {
  if (err)
    throw Error(JSON.stringify(err));
  console.log(transaction.result);
});

Devemos obter uma saída semelhante a esta:

{
  amount: 0.001,
  confirmations: 4776,
  blockhash: '000000006628870b0a8a66abea9cf0d4e815c491f079e3fa9e658a87b5dc863a',
  blockindex: 117,
  blocktime: 1591857418,
  txid: '1661ce322c128e053b8ea8fcc22d17df680d2052983980e2281d692b9b4ab7df',
  walletconflicts: [],
  time: 1591857343,
  timereceived: 1591857343,
  'bip125-replaceable': 'no',
  details: [
    {
      address: 'mpGpCMX6SuUimDZKiVViuhd7EGyVxkNnha',
      category: 'receive',
      amount: 0.001,
      label: '',
      vout: 0
    }
  ],
  hex: '02000000000101e9e8c3bd057d54e73baadc60c166860163b0e7aa60cab33a03e89fb44321f8d5010000001716001435c2aa3fc09ea53c3e23925c5b2e93b9119b2568feffffff02a0860100000000001976a914600c8c6a4abb0a502ea4de01681fe4fa1ca7800688ac65ec1c000000000017a91425b920efb2fde1a0277d3df11d0fd7249e17cf8587024730440220403a863d312946aae3f3ef0a57206197bc67f71536fb5f4b9ca71a7e226b6dc50220329646cf786cfef79d60de3ef54f702ab1073694022f0618731902d926918c3e012103e6feac9d7a8ad1ac6b36fb4c91c1c9f7fff1e7f63f0340e5253a0e4478b7b13f41fd1a00'
}

O código completo está disponível no sendtx.js.

Resumo: Acessando o Bitcoind com NodeJS

Com o BCRPC podemos acessar todos os comandos RPC disponíveis através do bitcoin-cli, usando o JavaScript. O BCRPC README tem alguns exemplos que usam promises (os exemplos neste livro usam callbacks). O JavaScript por trás dele é curto e bem legível.

Com base nesses exemplos, devemos ser capazes de incorporar Bitcoin em um projeto Node.js e fazer coisas como enviar e receber fundos.

O Que Vem Depois?

Vamos aprender mais sobre "Conversando com o Bitcoind com Outras Linguagens" na seção §18.4: Acessando o Bitcoind com Python.