Подпись ETH транзакций в PHP
Мы уже умеем коннектиться к блокчейн ноде и читать данные из блокчейна. Теперь попробуем отправить ETH с одного адреса на другой.
Подготовка
Мы будем работать в тестнете Sepolia, поэтому это нужно явно указать в коде:
1
2
$node = new SWeb3('https://eth.public-rpc.com');
$node->chainId = 0xaa36a7; // Sepolia network
Узнать id сети можно здесь.
Далее прописываем свой адрес и приватный ключ (будет использоваться для подписи транзакции):
1
2
3
4
$node->setPersonalData(
'0x7e2f443930Ad42609b29efeFef7E132d9022DFBc',
'your-private-key-value',
);
Параметры транзакции
Итак, начнем по порядку. Что нам нужно знать, чтобы создать транзакцию? Адрес отправителя и получателя у нас есть. Value - количество ETH, которое хотим отправить тоже знаем. Что такое nonce и gas?
Nonce
Nonce - это индекс транзакции на адресе, с которого мы отправляем транзакции (как и любой индекс начинается с нуля). Этот механизм нужен для предотвращения атаки double spend - когда мы одновременно отправляем 2 транзакции и пытаемся использовать сумму, которая у нас есть дважды. С каждой транзакцией нужно отправить nonce и дальше блокчейн нода уже провалидирует его.
1
$nonce = $node->personal->getNonce();
Чтобы получить nonce можно запросить у ноды кол-во транзакций с нашего адреса
eth_getTransactionCount
. По сути это количество и будет равно nonce.
1 2 3 4 $nonce = $node->call( 'eth_getTransactionCount', [$node->personal->address, 'pending'] )->result,
Value
Value - это сколько мы хотим передать Eth. Важно помнить, что всё передается в 16-ой системе. Плюс число указывается в минимальном номинале. Для Эфира это 1 Wei = 0,000000000000000001 Eth.
Wei — это минимальный номинал в блокчейне Ethereum. 1 Wei = 0,000000000000000001 Eth.
Мы будем отправлять 0.0001 Eth, что будет равно 100000000000000 Wei:
1
$value = Utils::toWei('0.0001', 'ether'); // 100000000000000 Wei
Gas
Что такое Gas? В блокчейне Ethereum каждая операция имеют свою вычислительную цену. Например, сохранить данные в блокчейн - дороже всего, изменить - дешевле, прочитать - вообще бесплатно. И вот эта стоимость операции измеряется в своих единицах, называемых gas. Gas также имеет свою стоимость в Eth, и здесь, когда мы указываем gas, мы говорим сколько максимум газа мы готовы потратить, или за сколько максимум газа мы готовы заплатить.
Gas — это единица измерения количества вычислительных ресурсов, необходимых для выполнения определенных операций в блокчейне.
Считаем сколько gas-а потребуется для выполнения нашей транзакции:
1
2
3
4
5
6
$sendParams = [
'from' => $node->personal->address,
'to' => $addressTo,
'value' => Utils::toWei('0.0001', 'ether'),
];
$gas = Utils::hexToBn($node->call('eth_estimateGas', [$sendParams])->result);
Для это вызываем у ноды метод eth_estimateGas
и передаем параметры нашей будущей транзакции: адрес отправителя, адрес получателя и сколько мы планируем отправить.
На самом деле цена перевода эфира фиксирована и равна 21000 газа, поэтому для простых переводов Eth на EOA адрес вызывать
eth_estimateGas
не обязательно.
Все числа в ответе от ноды мы будем получать в 16-ой системе. Поэтому используем хелпер
Utils::hexToBn()
для конвертации hex числа вBigInteger
.
Отправка в блокчейн
Сейчас у нас есть всё необходимое для создания и отправки транзакции в блокчейн:
1
2
3
4
5
6
7
8
9
$transaction = [
'from' => $node->personal->address,
'to' => $addressTo,
'value' => $node->utils->toWei('0.0001', 'ether'),
'nonce' => $nonce,
'gasLimit' => $gas,
];
$hash = $node->send($sendParams)->result;
Под капотом при вызове $node->send(...)
будет транзакция будет подписана нашим приватным ключом (будет получен hex транзакции). А затем транзакция будет забродкащена на ноду (будет вызван json-rpc метод eth_sendRawTransaction
). В результате мы получим хэш транзакции, с которым можно пойти в эксплорер и найти её на блокчейне.
Где взять ETH в тестнете? Есть несколько faucet-ов, где можно получить бесплатно несколько ETH. Например, от Google или от Automata.