Отправка транзакций с использованием viem
Это руководство для начинающих по отправке транзакций Эфириума с использованием библиотеки viem (открывается в новой вкладке). Для отправки транзакции в блокчейн Эфириума необходимо выполнить три основных шага: создание, подписание и трансляция. Мы рассмотрим все три и надеемся ответить на любые ваши вопросы! В этом руководстве мы будем использовать Alchemy (открывается в новой вкладке) для отправки наших транзакций в цепь Эфириума. Вы можете создать бесплатный аккаунт Alchemy здесь (открывается в новой вкладке).
ПРИМЕЧАНИЕ: Это руководство предназначено для подписания ваших транзакций на бэкенде вашего приложения. Если вы хотите интегрировать подписание транзакций на фронтенде, ознакомьтесь с API провайдера МетаМаск (открывается в новой вкладке).
Основы
Как и большинство разработчиков блокчейна в самом начале своего пути, вы, возможно, искали информацию о том, как отправить транзакцию (что должно быть довольно просто), и столкнулись с множеством руководств, каждое из которых говорит о разном, оставляя вас в замешательстве. Если вы оказались в такой ситуации, не волнуйтесь; мы все через это проходили! Поэтому, прежде чем мы начнем, давайте проясним несколько моментов:
1. Alchemy не хранит ваши приватные ключи
- Это означает, что Alchemy не может подписывать и отправлять транзакции от вашего имени. Причина этого кроется в безопасности. Alchemy никогда не попросит вас поделиться своим приватным ключом, и вы никогда не должны делиться своим приватным ключом с размещенным узлом (или с кем-либо еще).
- Вы можете читать данные из блокчейна, используя основной API Alchemy, но для записи в него вам понадобится использовать что-то еще для подписания ваших транзакций перед их отправкой через Alchemy (это справедливо и для любого другого сервиса узлов).
2. Что такое «подписант» (signer)?
- Подписанты будут подписывать транзакции для вас, используя ваш приватный ключ. В этом руководстве мы будем использовать viem (открывается в новой вкладке) для подписания нашей транзакции, но вы также можете использовать любую другую библиотеку Web3.
- На фронтенде хорошим примером подписанта является МетаМаск (открывается в новой вкладке), который будет подписывать и отправлять транзакции от вашего имени.
3. Зачем мне нужно подписывать свои транзакции?
- Каждый пользователь, который хочет отправить транзакцию в сети Эфириум, должен подписать транзакцию (используя свой приватный ключ), чтобы подтвердить, что отправитель транзакции является тем, за кого себя выдает.
- Крайне важно защищать этот приватный ключ, поскольку доступ к нему предоставляет полный контроль над вашим аккаунтом Эфириума, позволяя вам (или любому, у кого есть доступ) выполнять транзакции от вашего имени.
4. Как мне защитить свой приватный ключ?
- Существует множество способов защитить свой приватный ключ и использовать его для отправки транзакций. В этом руководстве мы будем использовать файл
.env. Однако вы также можете использовать отдельного провайдера, который хранит приватные ключи, использовать файл хранилища ключей или другие варианты.
5. В чем разница между eth_sendTransaction и eth_sendRawTransaction?
eth_sendTransaction и eth_sendRawTransaction — это функции программного интерфейса приложения (API) Эфириума, которые транслируют транзакцию в сеть Эфириума, чтобы она была добавлена в будущий блок. Они отличаются тем, как обрабатывают подписание транзакций.
eth_sendTransactionиспользуется для отправки неподписанных транзакций, что означает, что узел, на который вы отправляете, должен управлять вашим приватным ключом, чтобы он мог подписать транзакцию перед ее трансляцией в цепь. Поскольку Alchemy не хранит приватные ключи пользователей, они не поддерживают этот метод.eth_sendRawTransaction(открывается в новой вкладке) используется для трансляции транзакций, которые уже были подписаны. Это означает, что сначала вам нужно подписать транзакцию своим приватным ключом (в viem с помощьюsignTransaction(открывается в новой вкладке) с локальным аккаунтом (открывается в новой вкладке)), а затем передать результат вeth_sendRawTransaction.
При использовании viem доступ к eth_sendRawTransaction осуществляется путем вызова функции sendRawTransaction (открывается в новой вкладке).
Именно это мы и будем использовать в данном руководстве.
6. Что такое библиотека Web3?
- Библиотека Web3 — это обертка вокруг стандартных вызовов JSON-RPC, которая довольно часто используется в разработке для Эфириума.
- Существует множество библиотек Web3 для разных языков. В этом руководстве мы будем использовать viem (открывается в новой вкладке), которая написана на TypeScript и работает в любом проекте на JavaScript. Вы можете ознакомиться с другими вариантами здесь, например, с Ethers.js (открывается в новой вкладке).
Хорошо, теперь, когда мы разобрались с некоторыми из этих вопросов, давайте перейдем к руководству. Не стесняйтесь задавать вопросы в любое время в Дискорде (открывается в новой вкладке) Alchemy!
7. Как отправлять безопасные, оптимизированные по газу и приватные транзакции?
- У Alchemy есть набор ресурсов для транзакций (открывается в новой вкладке). Вы можете использовать их для отправки транзакций, симуляции транзакций до их выполнения, отправки приватных транзакций и транзакций, оптимизированных по газу.
- Вы также можете использовать вебхуки Alchemy (открывается в новой вкладке), чтобы получать уведомления, когда ваша транзакция извлекается из мемпула и добавляется в цепь.
ПРИМЕЧАНИЕ: Для этого руководства требуется аккаунт Alchemy, адрес Эфириума или кошелек МетаМаск, а также установленные Node.js и npm. Если у вас их нет, выполните следующие шаги:
- Создайте бесплатный аккаунт Alchemy (открывается в новой вкладке)
- Создайте аккаунт МетаМаск (открывается в новой вкладке) (или получите адрес Эфириума)
- Установите Node.js и npm (открывается в новой вкладке)
Шаги для отправки вашей транзакции
1. Создайте приложение Alchemy в тестовой сети Sepolia
Перейдите в свою панель управления Alchemy (открывается в новой вкладке) и создайте новое приложение, выбрав Sepolia (или любую другую тестовую сеть) в качестве вашей сети.
2. Запросите ETH из крана Sepolia
Следуйте инструкциям в кране Sepolia от Alchemy (открывается в новой вкладке), чтобы получить ETH, или используйте один из других кранов Sepolia. Краны выдают небольшие суммы (кран Alchemy дает 0.1 ETH в день), чего вполне достаточно для этого руководства. Убедитесь, что вы указали свой адрес Эфириума в сети Sepolia (из МетаМаск), а не в другой сети. После выполнения инструкций дважды проверьте, что вы получили ETH на свой кошелек.
3. Создайте новую директорию проекта и перейдите в нее с помощью cd
Создайте новую директорию проекта из командной строки (терминала для Mac) и перейдите в нее:
mkdir sendtx-example
cd sendtx-example
4. Установите viem (или любую библиотеку Web3)
Выполните следующую команду в директории вашего проекта, чтобы установить viem (открывается в новой вкладке):
Обратите внимание, если вы хотите использовать библиотеку Ethers.js, следуйте инструкциям здесь (открывается в новой вкладке).
npm init -y
npm install viem
5. Установите dotenv
Мы будем использовать файл .env для безопасного хранения нашего ключа API и приватного ключа.
npm install dotenv
6. Создайте файл .env
Создайте файл .env в директории вашего проекта и добавьте следующее (заменив «your-api-url» и «your-private-key»)
- Чтобы найти URL-адрес API Alchemy, перейдите на страницу сведений о приложении, которое вы только что создали на своей панели управления, нажмите «View Key» в правом верхнем углу и скопируйте HTTP URL.
- Чтобы найти свой приватный ключ с помощью МетаМаск, ознакомьтесь с этим руководством (открывается в новой вкладке). Используйте аккаунт, на котором хранятся только ETH тестовой сети.
API_URL="your-api-url"
PRIVATE_KEY="your-private-key"
.env! Пожалуйста, убедитесь, что вы никогда не делитесь и не раскрываете свой файл .env кому-либо, так как при этом вы ставите под угрозу свои секреты. Если вы используете систему контроля версий, добавьте ваш .env в файл gitignore.7. Создайте файл sendTx.js
Отлично, теперь, когда наши конфиденциальные данные защищены в файле .env, давайте начнем писать код. В нашем примере отправки транзакции мы отправим 0.001 ETH на другой адрес, который вы контролируете, например, на второй аккаунт в МетаМаск.
Создайте файл sendTx.js, в котором мы настроим и отправим нашу примерную транзакцию, и добавьте в него следующие строки кода:
require("dotenv").config({ quiet: true })
const { createPublicClient, createWalletClient, http, parseEther } = require("viem")
const { privateKeyToAccount } = require("viem/accounts")
const { sepolia } = require("viem/chains")
async function main() {
const { API_URL, PRIVATE_KEY } = process.env
const account = privateKeyToAccount(
PRIVATE_KEY.startsWith("0x") ? PRIVATE_KEY : `0x${PRIVATE_KEY}`
)
const publicClient = createPublicClient({
chain: sepolia,
transport: http(API_URL),
})
const walletClient = createWalletClient({
account,
chain: sepolia,
transport: http(API_URL),
})
const nonce = await publicClient.getTransactionCount({
address: account.address,
blockTag: "pending",
}) // нонс начинает отсчет с 0
const transaction = await walletClient.prepareTransactionRequest({
to: "0xYourSecondAddress", // TODO: замените на Адрес, на который вы хотите отправить ETH
value: parseEther("0.001"), // 0.001 ETH
gas: 21000n,
nonce,
// необязательное поле данных для отправки сообщения или выполнения смарт-контракта
})
const signedTx = await walletClient.signTransaction(transaction)
try {
const hash = await walletClient.sendRawTransaction({
serializedTransaction: signedTx,
})
console.log("🎉 The hash of your transaction is:", hash)
const receipt = await publicClient.waitForTransactionReceipt({ hash })
console.log(`Transaction ${receipt.status} in block ${receipt.blockNumber}`)
} catch (error) {
console.log(
"❗Something went wrong while submitting your transaction:",
error.details ?? error.message
)
}
}
main()
Обязательно замените 0xYourSecondAddress на адрес, на который вы хотите отправить ETH. Скрипт извлекает ваш собственный (отправляющий) адрес из PRIVATE_KEY, поэтому вам не нужно его вводить.
Теперь, прежде чем мы перейдем к запуску этого кода, давайте поговорим о некоторых его компонентах.
account: локальный аккаунт, созданный из вашего приватного ключа с помощьюprivateKeyToAccount(открывается в новой вкладке). Подписание происходит на вашем компьютере, и приватный ключ никогда не отправляется в Alchemy.publicClientиwalletClient: клиенты viem, которые отправляют запросы JSON-RPC на ваш URL-адрес Alchemy. Публичный клиент читает из цепи, а клиент кошелька подготавливает и подписывает транзакции для вашего аккаунта.nonce: спецификация нонса используется для отслеживания количества транзакций, отправленных с вашего адреса. Нам это нужно в целях безопасности и для предотвращения атак повторного воспроизведения. Чтобы получить количество транзакций, отправленных с вашего адреса, мы используем getTransactionCount (открывается в новой вкладке). viem также заполнил бы это за вас, но мы извлекаем его здесь явно, чтобы показать, откуда он берется.transaction: объект транзакции имеет несколько аспектов, которые нам нужно указать.prepareTransactionRequest(открывается в новой вкладке) заполняет остальное за нас, включаяchainIdи поля комиссий EIP-1559maxFeePerGasиmaxPriorityFeePerGas, основываясь на текущих условиях сети.to: это адрес, на который мы хотим отправить ETH.value: это сумма, которую мы хотим отправить, указанная в Wei, где 10^18 Wei = 1 ETH.parseEther(открывается в новой вкладке) конвертирует сумму в ETH в Wei за нас. Вашему аккаунту нужно немного больше этой суммы, так как он также платит за газ.gas: существует множество способов определить правильное количество газа для включения в вашу транзакцию. Alchemy поддерживает вебхуки (открывается в новой вкладке), которые могут уведомлять вас об активности ончейн. Для транзакций в Мейннете хорошей практикой является проверка текущих условий газа, чтобы определить правильное количество газа для включения. Обычный перевод ETH на обычный адрес всегда использует ровно 21000 газа, что является минимумом для любой транзакции, поэтому мы указываем здесь 21000. Если вы опуститеgas, viem оценит его за вас.nonce: см. определение нонса выше. Нонс начинает отсчет с нуля.- [НЕОБЯЗАТЕЛЬНО] data: используется для отправки дополнительной информации с вашим переводом или вызова смарт-контракта, не требуется для переводов баланса, ознакомьтесь с примечанием ниже.
signedTx: для подписания нашего объекта транзакции мы будем использовать методsignTransaction, который подписывает его локально с помощью аккаунта, созданного из нашегоPRIVATE_KEY.sendRawTransaction: как только у нас есть подписанная транзакция, мы можем отправить ее для включения в последующий блок, используяsendRawTransaction, который вызываетeth_sendRawTransaction.waitForTransactionReceipt: ожидает, пока транзакция не будет включена в блок, и возвращает ее квитанцию.
Примечание о данных (data) В Эфириуме можно отправлять два основных типа транзакций.
- Перевод баланса: отправка ETH с одного адреса на другой. Поле данных не требуется, однако, если вы хотите отправить дополнительную информацию вместе с вашей транзакцией, вы можете включить эту информацию в формате HEX в это поле.
- Например, допустим, мы хотели записать хеш документа IPFS в цепь Эфириума, чтобы дать ему неизменяемую временную метку. Наше поле данных тогда должно выглядеть как
data: toHex("IPFS hash"), используяtoHex(открывается в новой вкладке) из viem. И теперь любой может запросить цепь и увидеть, когда этот документ был добавлен.
- Например, допустим, мы хотели записать хеш документа IPFS в цепь Эфириума, чтобы дать ему неизменяемую временную метку. Наше поле данных тогда должно выглядеть как
- Транзакция смарт-контракта: выполнение некоторого кода смарт-контракта в цепи. В этом случае поле данных должно содержать функцию смарт-контракта, которую вы хотите выполнить, вместе с любыми параметрами.
- Для практического примера ознакомьтесь с руководством по смарт-контракту Hello World.
8. Запустите код с помощью node sendTx.js
Вернитесь в свой терминал или командную строку и выполните:
node sendTx.js
9. Посмотрите вашу транзакцию в обозревателе блоков
Скрипт выводит хеш транзакции, как только узел принимает транзакцию, затем ожидает, пока она не будет включена в блок (обычно в течение нескольких секунд), и выводит результат. Чтобы увидеть подробности, вставьте хеш в обозреватель блоков Sepolia, такой как Sepolia Etherscan (открывается в новой вкладке) или Blockscout (открывается в новой вкладке). Там вы можете наблюдать, как транзакция переходит из статуса ожидания во включенную, и видеть сумму, комиссии и блок, в который она попала.
Если вместо этого вы видите ошибку insufficient funds, на вашем аккаунте недостаточно Sepolia ETH для покрытия суммы перевода и газа. Вернитесь к шагу 2 и запросите больше из крана.
Ура! Вы только что отправили свою первую транзакцию Эфириума с использованием Alchemy 🎉
Для отзывов и предложений по этому руководству, пожалуйста, напишите Elan в Дискорде (открывается в новой вкладке) Alchemy!
Первоначально опубликовано Alchemy.