Доп 5. Руководство по web3js

Этот учебник основан на сайте web3@1.0.0-beta.29 web3.js. Он предназначен в качестве введения в web3.js.

Библиотека web3.js JavaScript представляет собой набор модулей, содержащих специфическую функциональность для экосистемы Ethereum, а также совместимый с Ethereum JavaScript API, реализующий спецификацию Generic JSON RPC.

Вместо того чтобы запускать собственный локальный узел, вы можете использовать существующего поставщика инфраструктуры, который обслуживает узлы как облачные сервисы и выполняет запросы узлов для вас. Два популярных варианта включают Alchemy API и Infura.

web3.js Контрактное базовое взаимодействие в неблокируемой (асинхронной) моде

Убедитесь, что у вас есть действительная версия npm:

$ npm -v
5.6.0

Если вы этого не сделали, инициализируйте npm:

$ npm init

Установите основные зависимости:

$ npm i command-line-args
$ npm i web3
$ npm i node-rest-client-promise

Это обновит ваш файл конфигурации package.json с новыми зависимостями.

Выполнение сценариев Node.js

Базовое исполнение:

$ node code/web3js/web3js_demo/web3-contract-basic-interaction.js

Получите токен доступа от провайдера узла, например, Alchemy API или Infura, и сохраните api-ключ в локальном файле под названием alchemyFileToken или infuraFileToken):

$ node code/web3js/web3js_demo/web3-contract-basic-interaction.js \
  --alchemyFileToken /path/to/file/with/alchemy_token

или:

$ node code/web3js/web3js_demo/web3-contract-basic-interaction.js \
  --infuraFileToken /path/to/file/with/infura_token

Это позволит прочитать файл с вашим собственным маркером и передать его в качестве аргумента командной строки в фактическую команду.

Просмотр демонстрационного сценария

Далее рассмотрим наш демонстрационный скрипт web3-contract-basic-interaction.

Мы используем объект Web3 для получения базового провайдера web3:

var web3 = new Web3(node_host);

Затем мы можем взаимодействовать с web3 и попробовать некоторые базовые функции. Рассмотрим версию протокола:

web3.eth.getProtocolVersion().then(function(protocolVersion) {
      console.log(`Protocol Version: ${protocolVersion}`);
  })

Теперь давайте посмотрим на текущую цену на газ:

web3.eth.getGasPrice().then(function(gasPrice) {
      console.log(`Gas Price: ${gasPrice}`);
  })

Какой последний добытый блок в текущей цепи?

web3.eth.getBlockNumber().then(function(blockNumber) {
      console.log(`Block Number: ${blockNumber}`);
  })

Взаимодействие по контракту

Теперь давайте попробуем несколько базовых взаимодействий с контрактом. Для этих примеров мы будем использовать контракт WETH9_ в тестовой сети Kovan.

Во-первых, давайте инициализируем наш контрактный адрес:

var our_contract_address = "0xd0A1E359811322d97991E03f863a0C30C2cF029C";

Затем мы можем посмотреть на его баланс:

web3.eth.getBalance(our_contract_address).then(function(balance) {
      console.log(`Balance of ${our_contract_address}: ${balance}`);
})

и посмотреть его байткод:

web3.eth.getCode(our_contract_address).then(function(code) {
      console.log(code);
})

Далее мы подготовим нашу среду для взаимодействия с API проводника Etherscan.

Давайте инициализируем URL нашего контракта в API проводника Etherscan для цепочки Kovan:

var etherscan_url =
  "https://kovan.etherscan.io/api?module=contract&action=getabi&
  address=${our_contract_address}"

И давайте инициализируем REST-клиент для взаимодействия с API Etherscan:

var client = require('node-rest-client-promise').Client();

и получить обещание клиента:

client.getPromise(etherscan_url)

После того, как мы получили действительное обещание клиента, мы можем получить ABI нашего контракта из Etherscan API:

.then((client_promise) => {
  our_contract_abi = JSON.parse(client_promise.data.result);

И теперь мы можем создать наш объект контракта в виде обещания, чтобы использовать его позже:

  return new Promise((resolve, reject) => {
      var our_contract = new web3.eth.Contract(our_contract_abi,
                                               our_contract_address);
      try {
        // If all goes well
        resolve(our_contract);
      } catch (ex) {
        // If something goes wrong
        reject(ex);
      }
    });
})

Если наше обещание контракта возвращается успешно, мы можем начать взаимодействие с ним:

.then((our_contract) => {

Давайте посмотрим адрес нашего контракта:

console.log(`Our Contract address:${our_contract._address}`);

или альтернативно:

console.log(`Our Contract address in another way:
            ${our_contract.options.address}`);

Теперь давайте запросим наш контрактный ABI:

console.log("Our contract abi: " +
            JSON.stringify(our_contract.options.jsonInterface));

Мы можем увидеть общее количество поставок по нашему контракту с помощью обратного вызова:

our_contract.methods.totalSupply().call(function(err, totalSupply) {
    if (!err) {
        console.log(`Total Supply with a callback:  ${totalSupply}`);
    } else {
        console.log(err);
    }
});

Или мы можем использовать возвращаемое обещание вместо передачи обратного вызова:

our_contract.methods.totalSupply().call().then(function(totalSupply){
    console.log(`Total Supply with a promise:  ${totalSupply}`);
}).catch(function(err) {
    console.log(err);
});

Асинхронные операции с помощью Await

Теперь, когда вы ознакомились с базовым учебником, вы можете попробовать выполнить те же взаимодействия, используя асинхронную конструкцию await. Просмотрите сценарий web3-contract-basic-interaction-async-await.js в code/web3js и сравните его с этим руководством, чтобы увидеть, чем они отличаются. Async-await легче читать, так как в нем асинхронное взаимодействие больше похоже на последовательность блокирующих вызовов.