Отправка ETH
Как отправить ETH через ethers v6: собрать транзакцию, подписать её кошельком и дождаться подтверждения в блоке.
Что значит отправить ETH
Отправка ETH — это транзакция, которая переводит value с одного EOA на другой адрес.
Она меняет State Ethereum, поэтому её должен подписать кошелёк, а отправитель платит gas.
Отправляем ETH в локальной сети
Запустите локальную сеть Hardhat в отдельном терминале:
npx hardhat nodeЗатем выполните TypeScript-код:
import { ethers } from "ethers";
const provider = new ethers.JsonRpcProvider("http://127.0.0.1:8545");
// Первый тестовый аккаунт Hardhat. Не используйте этот ключ в mainnet.
const sender = new ethers.Wallet(
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
provider,
);
// Второй тестовый аккаунт Hardhat.
const recipient = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8";
const senderBalanceBefore = await provider.getBalance(sender.address);
const recipientBalanceBefore = await provider.getBalance(recipient);
console.log("Sender:", sender.address);
console.log("Recipient:", recipient);
console.log("Sender before:", ethers.formatEther(senderBalanceBefore), "ETH");
console.log("Recipient before:", ethers.formatEther(recipientBalanceBefore), "ETH");
const tx = await sender.sendTransaction({
to: recipient,
value: ethers.parseEther("0.1"),
});
console.log("Transaction hash:", tx.hash);
const receipt = await tx.wait();
if (!receipt || receipt.status !== 1) {
throw new Error("Транзакция не была успешно выполнена");
}
const senderBalanceAfter = await provider.getBalance(sender.address);
const recipientBalanceAfter = await provider.getBalance(recipient);
const fee = receipt.gasUsed * receipt.gasPrice;
console.log("Block:", receipt.blockNumber);
console.log("Gas used:", receipt.gasUsed.toString());
console.log("Fee:", ethers.formatEther(fee), "ETH");
console.log("Sender after:", ethers.formatEther(senderBalanceAfter), "ETH");
console.log("Recipient after:", ethers.formatEther(recipientBalanceAfter), "ETH");Код отправляет 0.1 ETH между двумя тестовыми аккаунтами Hardhat и ждёт, пока транзакция попадёт в блок.
Как это работает
new ethers.JsonRpcProvider("http://127.0.0.1:8545") — подключается к локальной Ethereum-сети.
new ethers.Wallet(privateKey, provider) — создаёт signer: объект, который умеет подписывать и отправлять транзакции.
sender.sendTransaction({ to, value }) — создаёт, подписывает и отправляет транзакцию через RPC.
ethers.parseEther("0.1") — переводит человекочитаемое значение ETH в wei.
tx.hash — идентификатор отправленной транзакции. По нему можно искать транзакцию в RPC или explorer.
tx.wait() — ждёт, пока транзакцию включат в блок, и возвращает receipt.
receipt.status — показывает результат выполнения: 1 означает success, 0 означает failed.
receipt.gasUsed * receipt.gasPrice — считает фактическую комиссию за транзакцию.
Что меняется после отправки
Баланс получателя увеличится ровно на 0.1 ETH.
Баланс отправителя уменьшится на сумму перевода и комиссию:
senderAfter = senderBefore - value - fee
recipientAfter = recipientBefore + valueДаже простой перевод ETH стоит gas, потому что сеть проверяет подпись, nonce, баланс отправителя и записывает новый State.
Частые ошибки
Передавать ETH как число 0.1 → используйте ethers.parseEther("0.1"). В транзакции value должен быть в wei.
Не ждать tx.wait() → hash означает только отправку в RPC. State меняется после включения транзакции в блок.
Использовать тестовый private key в публичной сети → ключи Hardhat известны всем. Они подходят только для локальной сети.
Что дальше
- Оценка газа (estimateGas) — проверить, сколько gas понадобится до отправки
- EIP-1559: maxFeePerGas vs gasPrice — понять, как задаются комиссии в современных транзакциях
- Статусы TX: pending / confirmed / failed — разобраться, что происходит после отправки hash