Взаимодействие со смарт-контрактами с использованием Web3.js (часть I)
Платформа Web3.JS позволяет разработчикам взаимодействовать с Ethereum смарт-контрактами, используя Javascript Node.js. Фреймворк состоит из модулей с определенными функциями:
web3-eth
предназначен для блокчейна и смарт-контрактов.web3-shh
предназначен для протокола шепота, для связи p2p и широковещательной передачи.web3-bzz
- это протокол роя, децентрализованное хранилище файлов.web3-utils
содержит полезные вспомогательные функции для разработчиков DApp (децентрализованных приложений).
Это предоставляет разработчикам стандартный способ использования вызовов API и интеграции функций с интерфейсным приложением Node.js. Это позволяет пользователям получить доступ к функциям блокчейна, таким как отправка транзакций, проверка остатков на счетах и подписание сообщений.
Начиная
Ниже приведены требования для начала разработки приложений, которые могут взаимодействовать со смарт-контрактами.
- Node.js - его необходимо установить для конкретной используемой операционной системы. Настоятельно рекомендуется использовать версию LTS (доступны версии для Linux, macOS и Windows).
- Web3.js. Установите Web3.js с помощью npm или yarn из папки проекта консоли терминала.
- Подключение к узлу Ethereum - для этого требуется либо локальный узел (например, Ganache), либо подключение к действующему узлу в сети (например, Infura). Тем, кто хочет протестировать в сети, рекомендую использовать шлюз Infura.
Объект Web3
Объект web3 - это главный класс фреймворка. Для вызова любой функции необходимо использовать объект web3.
web3.<name of function or call>
Сначала необходимо создать новый экземпляр объекта. В приглашении узла на консоли терминала:
> const Web3 = require('web3')
Теперь, когда мы создали экземпляр объекта, мы должны создать поставщика, который создает экземпляр объекта Web3, который подключается к сети Ethereum. Есть несколько типов сетей.
(Обратите внимание, что это заглавная буква "W" для провайдера Web3)
- Основная сеть Ethereum или основная сеть (активный блокчейн, используемый для ETH)
- Тестовые сети (например, Кован, Ринкеби, Ропстен, Гёрли)
- Провайдеры Web3 (например, с использованием порта 7545 на локальном хосте или удаленном сервере)
- Внедренный Web3 (например, Infura Gateway)
В этом примере будет использоваться конечная точка Infura. Это URL-адрес, предоставляемый Infura при создании проекта. Это должно быть создано до того, как будет выдан URL-адрес.
Примечание. Указанный URL-адрес является лишь примером и не должен использоваться в реальной производственной или тестовой среде.
> const web3 = new Web3('https://ropsten.infura.io/v3/76162cfy074u522fa49be7ca11cc9a33')
Когда вы вызываете объект Web3, он возвращает функциональные возможности объекта. Вот фрагмент возвращенных результатов (см. Снимок экрана):
> Web3
Если вы прокрутите вниз дальше, вы увидите следующее:
Это показывает содержимое модулей библиотеки. В блокчейне Ethereum используются функции и поддерживаемые единицы (например, wei). Это то, чему должны следовать разработчики, чтобы взаимодействовать с блокчейном. Вы не можете отправлять транзакции, если эти соглашения не соблюдаются должным образом, поэтому они похожи на правила, касающиеся транзакций для смарт-контрактов. Разработчики могут ссылаться на них при написании заявлений.
Работа с аккаунтами Ethereum
Одно из основных применений Web3.js - работа с учетными записями. Допустим, мы хотим создать новую учетную запись в блокчейне Ethereum. Мы можем сделать это, выполнив команду, и возвращенный результат будет полностью функциональной учетной записью, которую может использовать пользователь, с публичным адресом и закрытым ключом.
Примечание. Эта учетная запись используется только в качестве примера. Не используйте в производственных или тестовых целях.
> web3.eth.accounts.create(); { address: "0xb8CE9ab6943e1eCED004cDe8e3bBed6568c2Fv01", privateKey: "0x348ce564d427a3311b6546bbcff9390d69395b06ed6c486954e971d860fe8709", signTransaction: function(tx){...}, sign: function(data){...}, encrypt: function(password){...} }
Вы создаете учетную запись с адресом Ethereum:
0xb8CE9ab6943e1eCED004cDe8e3bBed6568c2Fv01
Эту учетную запись можно использовать в сети, указанной вами в качестве провайдера. Его нельзя использовать в другой сети, кроме той, в которой он был создан.
У учетной записи также есть закрытый ключ. Это очень важно, потому что закрытый ключ - это то, что обеспечивает авторизацию пользователя для учетной записи.
0x348ce564d427a3311b6546bbcff9390d69395b06ed6c486954e971d860fe8709
Если он потерян, любые остатки на счете больше не могут быть восстановлены, если нет резервной копии закрытого ключа. Любой, кто украл закрытый ключ, также может использовать его для доступа к учетной записи. Храните закрытый ключ в безопасности и никогда не раскрывайте его другим.
Точно так же вы можете получить адрес из закрытого ключа с помощью функции privateKeyToAccount ().
> web3.eth.accounts.privateKeyToAccount('0x348ce564d427a3311b6546bbcff9390d69395b06ed6c486954e971d860fe8709'); { address: '0xb8CE9ab6943e1eCED004cDe8e3bBed6568c2Fv01', privateKey: '0x348ce564d427a3311b6546bbcff9390d69395b06ed6c486954e971d860fe8709', signTransaction: function(tx){...}, sign: function(data){...}, encrypt: function(password){...} }
Другие функции, доступные для разработчиков, включают шифрование и подписание сообщений с использованием учетной записи Ethereum.
Запрос блокчейна
Разработчики могут использовать пакет web3-eth для запроса информации из цепочки блоков. Это не потребует каких-либо затрат на использование газа, потому что эти вызовы не изменяют состояние. Они просто считывают данные, а не записывают данные в цепочку блоков.
Чтобы получить баланс со счета, используйте функцию getBalance () с адресом в качестве параметра.
> web3.eth.getBalance('0x6e35A20a740bC7288bdec5d4E138a253D4A72660') .then(console.log) Promise { <pending> } > 5984521207000000000
Баланс счета возвращается в wei, что является наименьшим номиналом эфира. Есть еще один способ получить баланс в ETH или эфире, но для этого требуется вызов функции web.utils. Ниже приводится пример:
> web3.eth.getBalance('0x6e35A20a740bC7288bdec5d4E138a253D4A72660', (call, wei) => { balance = web3.utils.fromWei(wei, 'ether')}) Promise { <pending> } > balance '5.984521207'
Как видите, для этого требуется использование оператора с вызовом функции, которая переводит результат getBalance в переменный баланс с преобразованием из wei в эфир. Результат - 5,98, выраженный в эфире.
Выполнение транзакции
Это более глубокое погружение в Web3.js, на этот раз с использованием транзакций. Это потребует затрат на газ, поскольку транзакция вносит изменения в состояние. Это изменяет данные в цепочке блоков, что требует консенсуса посредством майнинга, прежде чем транзакция может быть зафиксирована в блоке.
Используемые функции будут взяты из библиотеки EthereumJS. Прежде чем продолжить, убедитесь, что ethereumjs-tx установлен.
Сначала создайте файл с именем app.js (любое имя можно использовать с расширением js). Это будет веб-приложение, которое будет взаимодействовать с блокчейном Ethereum, используя функции из установленных нами библиотек.
Вот следующий код для app.js:
Примечание. Это только пример. Закрытые ключи не раскрываются в демонстрационных целях.
const Tx = require('ethereumjs-tx').Transaction const Web3 = require('web3') const web3 = new Web3('<endpoint>') const account1 = '<address 1>' const account2 = '<address 2>' const privateKey1 = Buffer.from('<private key 1>', 'hex') const privateKey2 = Buffer.from('<private key 2>', 'hex') web3.eth.getTransactionCount(account1, (err, txCount) => { // Build a transaction const txObject = { nonce: web3.utils.toHex(txCount), to: account2, value: web3.utils.toHex(web3.utils.toWei('1', 'ether')), gasLimit: web3.utils.toHex(21000), gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')) } // Sign the transaction const tx = new Tx(txObject, { chain: 'ropsten' }) tx.sign(privateKey1) const serializedTransaction = tx.serialize() const raw = '0x' + serializedTransaction.toString('hex') // Broadcast the transaction web3.eth.sendSignedTransaction(raw, (err, txHash) => { console.log('txHash: ', txHash) console.log(err) }) })
Приложение будет переводить сумму в 1 эфир (1 ETH) с учетной записи пользователя 1 на учетную запись 2. В сделке учитывается стоимость газа в 10 gwei и лимит 21000 wei. Одноразовый номер указывает значение счетчика транзакций. Эти значения необходимо преобразовать в шестнадцатеричные, поэтому мы используем функцию web3.utils.toHex ().
На самом деле создание транзакции состоит из 3 частей.
Сначала мы строим транзакцию, используя следующую структуру данных:
nonce: web3.utils.toHex(txCount), to: account2, value: web3.utils.toHex(web3.utils.toWei('1', 'ether')), gasLimit: web3.utils.toHex(21000), gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei'))
Это наш объект транзакции, который будет отправлен в блокчейн Ethereum.
Затем транзакция должна быть подписана отправляющим ее пользователем account1.
tx.sign(privateKey1)
В функцию tx.sign () передается значение закрытого ключа пользователя. Это авторизует транзакцию с момента ее подписания.
Наконец, транзакция транслируется в сеть. Майнеры заберут его и упакуют в блок, где его нужно будет добыть и проверить.
В конце был добавлен консольный журнал, чтобы мы могли видеть возвращаемый результат, что важно (будет объяснено позже).
Чтобы отправить нашу транзакцию, введите следующее в командной строке терминала (не внутри среды узла, а из папки).
$ node app.js txHash: 0x92c0c7d98b0a13f157ed6e4d6aaf28c4525c55c354a3792e097b91c2fafc8e80
Здесь важен результат, потому что он покажет, была ли транзакция обработана успешно. Если вы получили значение txHash, значит, это успех. В противном случае в коде есть ошибки, которые необходимо исправить.
Чтобы проверить транзакцию, откройте обозреватель цепочки блоков для сети провайдера, которую вы использовали (например, Ethereum). Посмотрите на хеш-значение транзакции, и он вернет детали транзакции.
Синопсис
Web3.js предоставляет разработчикам приложений возможность создавать DApps и интерфейсы. Это способ обеспечить функциональность внешнего интерфейса в сети, которая может взаимодействовать со смарт-контрактами и блокчейном Ethereum.
Продолжение следует… (см. Часть II)