как отобразить баланс токенов через Ethereum RPC?
$id = 0;
$data = array();
$data['jsonrpc'] = '2.0';
$data['id'] = $id++;
$data['method'] = 'eth_call';
$data['params'] = [['from' => '0x0...', 'to' => '0x0...', 'data' => 'contract byte code here 0x0...'], 'latest'];
$ch = curl_init();
...
Вернуть:
{"jsonrpc":"2.0","id":0,"result":"0x"}
Что делать дальше? Вызовите метод контракта balanceOf? Как это сделать?
Чтобы получить баланс токена с eth_call
тебе нужно to
а также data
параметр. to
адрес контракта, здесь нам нужно сгенерировать data
параметр. Как док eth_call говорит,
data: DATA — (необязательно) хэш метода и подписи
параметры. Подробнее см. Ethereum-Контракт-ABI
Возьми это Транзакция с токеном EOS как пример.
Адрес контракта:0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0
Адрес держателя токена:0x0b88516a6d22bf8e0d3657effbd41577c5fd4cb7
Вы можете увидеть код контракта Вот.
contract ERC20 {
function totalSupply() constant returns (uint supply);
function balanceOf( address who ) constant returns (uint value);
function allowance( address owner, address spender ) constant returns (uint _allowance);
function transfer( address to, uint value) returns (bool ok);
function transferFrom( address from, address to, uint value) returns (bool ok);
function approve( address spender, uint value ) returns (bool ok);
event Transfer( address indexed from, address indexed to, uint value);
event Approval( address indexed owner, address indexed spender, uint value);
}
>>> from web3 import Web3
>>> Web3.sha3("balanceOf(address)")
HexBytes('0x70a08231b98ef4ca268c9cc3f6b4590e4bfec28280db06bb5d45e689f2a360be')
Возьмите первые четыре байта 70a08231
адрес: эквивалентный uint160, за исключением предполагаемой интерпретации
и язык ввода.int: enc (X) — кодирование дополнения X к двоичному порядку байтов
дополнен на стороне более высокого порядка (слева) 0xff для отрицательного X и
с нулевыми байтами для положительного X, так что длина кратна
32 байта.
Заполнение 20-байтового адреса токена до 32 байт 0
адрес держателя токена:
0000000000000000000000000b88516a6d22bf8e0d3657effbd41577c5fd4cb7
Затем скомбинируем селектор функции и закодированный параметр, получим data
параметр:
0x70a082310000000000000000000000000b88516a6d22bf8e0d3657effbd41577c5fd4cb7
Сделайте запрос с:
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_call","params":[{"to": "0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0", "data":"0x70a082310000000000000000000000000b88516a6d22bf8e0d3657effbd41577c5fd4cb7"}, "latest"],"id":67}' -H "Content-Type: application/json" http://127.0.0.1:8545/
вот результат скручивания (здесь вы можете получить другой ответ, так как может быть некоторая транзакция с этим адресом, выполненная после моего запроса)
{"jsonrpc":"2.0","id":67,"result":"0x00000000000000000000000000000000000000000000014a314d9ff9b20b9800"}
Вы можете изменить преобразование баланса в шестнадцатеричном формате в десятичное
>>> 0x00000000000000000000000000000000000000000000014a314d9ff9b20b9800
6090978215900000000000
Проверьте результат,
При вызове функции контракта Solidity, в общем случае, data
должно быть следующим, закодировано как шестнадцатеричная строка:
Сигнатура функции для токена ERC20 balanceOf
является balanceOf(address)
, Хеш keccak-256 есть 70a08231b98ef4ca268c9cc3f6b4590e4bfec28280db06bb5d45e689f2a360be
поэтому первые четыре байта 70a08231
,
Функция принимает только один параметр: адрес учетной записи, баланс которой вы пытаетесь найти. Чтобы кодировать ABI, просто добавьте слева нули, пока он не станет длиной 32 байта. Поскольку адреса имеют размер 20 байтов, это означает добавление 12 байтов нулей (или 24 символов в шестнадцатеричном формате).
Итак, полный data
поле должно быть "0x70a08231" + "000000000000000000000000" + address
,
Для транзакции токена необходимо использовать eth_sendTransaction
,
Могу я порекомендовать правильную библиотеку ERC20 для PHP, которую я разработал сам.
https://www.furqansiddiqui.com/libraries/erc20-php/
https://github.com/furqansiddiqui/erc20-php
Пример кода для получения баланса:
<?php
$geth = new EthereumRPC('127.0.0.1', 8545);
$erc20 = new \ERC20\ERC20($geth);
// Pass ERC20 contract address as argument below
$token = $erc20->token('0xd26114cd6EE289AccF82350c8d8487fedB8A0C07');
var_dump($token->name()); # string(8) "OMGToken"var_dump($token->symbol()); # string(3) "OMG"var_dump($token->decimals()); # int(18)
var_dump($token->balanceOf('0x...')); // Enter ethereum address here