Локальное окружение для изучения Web3.js и Ethereum
Отправка ethereum транзакции через консоль
В данной статье я расскажу как настроить окружение для изучения библиотеки web3.js Статья рассчитана на тех, кто интересуется blockchain и хочет научиться взаимодействовать с сетью Ethereum, она же EVM (Ethereum Virtual Machine), через библиотеку web3.js
После настройки окружения, мы отправим нашу первую транзакцию — перевод криптовалюты с одного аккаунта на другой посредством библиотеки web3, а так же изучим некоторые другие команды. После данного руководства не составит труда поэкспериментировать и с остальными методами библиотеки, ознакомившись с документацией web3 API.
Что нам понадобится?
Что такое web3.js?
Согласно официальной документации, web3.js это Ethereum JavaScript API, содержащий коллекцию библиотек, позволяющих взаимодействовать с локальными или удалёнными ethereum нодами, посредством HTTP, IPC или WebSocket. В нашем случае мы будем взаимодействовать только с локальной нодой, а все наши транзакции будут происходить внутри нашего компьютера.
Что такое Ganache?
Ganache — это локальная Ethereum блокчейн сеть, состоящая всего из одной ноды. По сравнению с боевыми нодами реальных блокчейн сетей, Ganache занимает очень мало места, так как при старте она не содержит никаких данных, кроме самого первого Genesis блока и 10 тестовых акаунтов, имеющих на своём балансе по 100 ETH. Ganache прекрасно подходит для тестирования Dapp приложений, смарт-контрактов и изучения блокчейн сети Ethereum.
Что такое truffle?
Это библиотека, позволяющая взаимодействовать с EVM — Ethereum Virtual Machine, разрабатывать смарт-контракты, компилировать и деплоить их в EVM, отлаживать их, а так же взаимодействовать с ними через консоль. Библиотека включает в себя библиотеку web3.js.
Итак, приступим.
Установка Ganache
Скачиваем дистрибутив, устанавливаем, запускаем приложение и нажимаем Quickstart
Экран после первого запуска Ganache
После инициализации нашего локального ethereum блокчейна, видим 10 тестовых аккаунтов. Каждый аккаунт имеет баланс по 100 ETH
Рабочее пространство Ganache с 10-ю аккаунтами
Всё, ethereum блокчейн установлен, теперь настроим консоль при помощи которой мы будем отправлять сообщения нашему блокчейну.
Устанавливаем библиотеку truffle через npm
Для этого нам понадобится установленная Node.js v14 — v18. Скачать nodejs можно тут. Затем устанавливаем truffle:
$ npm install -g truffle
Проверяем, что всё установилось корректно:
$ truffle version
Вывод:
Truffle v5.8.1 (core: 5.8.1)
Ganache v7.7.7
Solidity - 0.8.19 (solc-js)
Node v18.12.1
Web3.js v1.8.2
Если возникли проблемы, то можно посмотреть официальное руководство по установке.
Заходим в truffle console
Теперь пробуем зайти в консоль:
$ truffle console
Мы видим следующее сообщение:
Could not find suitable configuration file.
Truffle v5.8.1 (core: 5.8.1)
Node v18.12.1
Так произошло, потому что truffle не нашёл файла конфигурации. Но к счастью ничего настраивать нам не нужно, а достаточно создать пустой файл truffle-config.js
и truffle применит настройки по-умолчанию.
Создадим произвольную папку, в ней создадим наш пустой файл настроек и запустим truffle консоль:
$ mkdir web3-demo
$ cd web3-demo
$ touch truffle-config.js
$ truffle console
У нас должна появиться строка консоли:
$ truffle(ganache)>
Примечание: вместо создания вручную пустого файла truffle-config.js
мы могли бы использовать команду
$ truffle init
и тогда truffle создал бы для нас пустой проект с файлом конфигурации и пустыми каталогами:
Окружение после выполнения команды $ truffle init
Данная структура проекта предназначена для разработки smart-контрактов и деплоя их в тестовую сеть Ganache, что не является темой данного топика, поэтому я использовал минимально необходимые настройки.
Тестируем доступ к блокчейн сети через консоль
Набираем в открытой ранее truffle консоли:
web3.eth.getAccounts()
Если мы видим вывод представленный ниже, то всё отлично, мы подключились к нашей тестовой локальной блокчейн EVM. В данном случае мы запросили сеть выдать нам все аккаунты, и они идентичны тем, что мы видели в нашем GUI Ganache. Сами аккаунты могут отличаться, так как Ganache при каждом запуске генерирует новые аккаунты.
[
'0x4DfcE7Fb36c1C95Fd72dE02DB865EfC5c4E72dE8',
'0x968a34AC105aca298209c2dce23A8De721fB3C19',
'0x9a978DaeecA6cdD141c9aDEc7A0AE5F86e48F10d',
'0x2FcF93F05067445886afF6d832d68b8b4E31b0A3',
'0x777C7A81C70B3978a2D2574E2D4939D882f0AA13',
'0xc1a204D8E7e5550C6Cd1c9d2f142F7C3306b0774',
'0x432D3e48DA7FdeAf41933E85C04a401b96bAeefe',
'0x4a47F93Dfe15bA9165C8E6735ffD8D142d238F5c',
'0xA1B19BA4fcC38A86927f4C76e5cEC5Bd027940aC',
'0x47fc50170A8E68D7C6d2855c2d9F1F0412CB5B77'
]
Теперь попробуем отправить криптовалюту с одного аккаунта на другой.
Отправка криптовалюты с одного аккаунта на другой
Для отправки мы воспользуемся следующей командой:
web3.eth.sendTransaction({
from: "0x4DfcE7Fb36c1C95Fd72dE02DB865EfC5c4E72dE8",
to: "0x968a34AC105aca298209c2dce23A8De721fB3C19",
value: web3.utils.toWei("0.01", "ether")
})
Данная команда подписывает приватным ключом отправителя транзакцию, и отправляет её в сеть Ethereum. Сама транзакция представлена в виде javascript объекта.
Значения для полей from
и to
я взял из предыдущего вызова getAccounts()
, это соответствует первому и второму адресу в массиве. Вы можете использовать любые другие адреса.
В поле value мы помещаем сумму, которую хотим отправить. В данном случае я поместил вызов функции, которая сконвертирует значение, выраженное в Ether в значение, выраженное в Wei. Дело в том, что EVM оперирует только значениями выраженными в Wei — это минимальная единица измерения криптовалюты Ethereum. 1 Ether = 10^18 Wei.
Можно прямо сейчас проверить в консоли, какое число бы нам пришлось писать в value, без этой функции:
web3.utils.toWei("0.01", "ether")
Вывод:
'10000000000000000'
Как видим, можно легко запутаться в нулях. Здесь представлены все единицы измерения криптовалюты в Ethereum.
Перед запуском транзакции, проверим состояние балансов наших аккаунтов:
Первый аккаунт:
web3.eth.getBalance("0x4DfcE7Fb36c1C95Fd72dE02DB865EfC5c4E72dE8")
Вывод:
'100000000000000000000'
Второй аккаунт:
web3.eth.getBalance("0x968a34AC105aca298209c2dce23A8De721fB3C19")
Вывод:
'100000000000000000000'
Напомню, что здесь мы видим значение баланса, выраженного в Wei. Можно так же заглянуть в GUI Ganache и убедиться, что всё верно. В GUI баланс отражён в Ether.
Ganache отображает баланс в ETH
Итак, у нас всё готово для запуска транзакции. Запускаем саму транзакцию:
web3.eth.sendTransaction({from: "0x4DfcE7Fb36c1C95Fd72dE02DB865EfC5c4E72dE8", to: "0x968a34AC105aca298209c2dce23A8De721fB3C19", value: web3.utils.toWei("0.01", "ether")})
Если всё прошло успешно, то на выходе получаем js-объект. Это так называемый Receipt
, или квитанция о совершённой транзакции. В ней содержится такая информация, как хэш транзакции (по нему мы можем найти транзакцию в блокчейне), номер блока в который была записана наша транзакция, хэш блока и другая полезная информация.
{
transactionHash: '0x0bf4bd25ab2de3b44e6a60ae7187748f85349eb88f7df1d90a6ce1041ebc827d',
transactionIndex: 0,
blockNumber: 1,
blockHash: '0xa54a964d5db58d84b21d9d29ee1972ffd74501d67fd4432c7cbce0dddc01fe83',
from: '0x4dfce7fb36c1c95fd72de02db865efc5c4e72de8',
to: '0x968a34ac105aca298209c2dce23a8de721fb3c19',
cumulativeGasUsed: 21000,
gasUsed: 21000,
contractAddress: null,
logs: [],
logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
status: true,
effectiveGasPrice: 3375000000,
type: '0x2'
}
Итак, транзакция прошла успешно. Теперь проверим балансы наших аккаунтов.
Аккаунт-отправитель:
web3.eth.getBalance("0x4DfcE7Fb36c1C95Fd72dE02DB865EfC5c4E72dE8")
Вывод:
'99989929125000000000'
Аккаунт-получатель:
web3.eth.getBalance("0x968a34AC105aca298209c2dce23A8De721fB3C19")
Вывод:
'100010000000000000000'
Как видим, балансы изменились: у получателя прибавилось 0.01 Ether, а у отправителя списалась сумма, чуть большая, чем 0.01 Ether. Дело в том, что с отправителя списалась ещё и комиссия за транзакцию, которая выражается в Gas. Gas это топливо сети Ethereum, или оплата за пользование вычислительными ресурсами.
Данная комиссия вычисляется путём умножения текущей стоимости 1 единицы Gas на то количество единиц Gas, которое потребуется для выполнения нашей транзакции. В реальной сети Ethereum стоимость 1 единицы Gas постоянно меняется. Здесь можно провести параллель с ценами на бензин на АЗС, и стоимостью поездки из пункта А в пункт Б на личном автомобиле. Общая стоимость проезда в данном случае будет складываться из цены за литр бензина и объёма израсходованного топлива.
Проверяем баланс в GUI Ganache:
Изменения балансов после проведения транзакции
Напоследок можно зайти на вкладку Transactions в Ganache, и там увидеть нашу транзакцию.
Вкладка транзакций. Транзакции кликабельны
Зайдём внутрь транзакции, кликнув на неё:
Информация по конкретной транзакции
Так же можно зайти на вкладку Blocks и увидеть два блока: нулевой был записан при запуске самой сети Ethereum, это так называемый Genesis Block, следующий блок — это и есть тот блок, куда попала наша транзакция:
Вкладка блоков. Каждый блок кликабельный
Зайдём внутрь первого блока, куда попала наша транзакция:
Информация о первом блоке с нашей транзакцией
Если сравнить квитанцию, которая была получена в консоли, с тем что отражено в GUI, то можно убедиться что информация идентична.
На этом всё. Мы настроили окружение и научились отправлять транзакцию через консоль. Для дальнейшего изучения Ethereum, можно воспользоваться официальной документацией к Web3 API.
Например описание получение баланса находится тут. Получить текущую цену на Gas можно этой командой:
web3.eth.getGasPrice()
Вывод:
'20000000000'
При дальнейшем изучении, в данной среде можно деплоить и тестировать smart-контракты.
Спасибо за внимание, всем успехов в освоении web3:)