PHP通过Geth客户端获取ETH地址存款交易的RPC API问题
Hey there! Let's get those deposit transactions sorted out for you using Geth's JSON-RPC and PHP. It sounds like you might be mixing up how transaction data and contract logs work—so let's break this down based on exactly what you're trying to pull: native ETH deposits, or deposit events from a smart contract.
Native ETH transfers don't emit contract logs by default, so the filter methods you tried (which target logs) won't catch these directly. Instead, you'll need to scan blocks for transactions where the to field matches your target address.
Here's a practical PHP implementation:
- First, get the latest block number to know your upper limit.
- Iterate through blocks (start from a reasonable block instead of 0x0 to save time) and fetch full transaction details for each block.
- Check each transaction's
tofield against your target address (normalize to lowercase to avoid case mismatches).
$targetAddress = '0x14e15d73db916e14fdb91de38da2c591818...'; $rpcUrl = 'http://localhost:8545'; // Your Geth RPC endpoint // Helper function to send JSON-RPC requests function sendRpcRequest($url, $method, $params) { $payload = json_encode([ 'jsonrpc' => '2.0', 'method' => $method, 'params' => $params, 'id' => rand(1, 1000) // Random ID to avoid conflicts ]); $ch = curl_init($url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); // Handle errors gracefully if ($response === false) { throw new Exception("Failed to connect to Geth RPC"); } $result = json_decode($response, true); if (isset($result['error'])) { throw new Exception("RPC Error: " . $result['error']['message']); } return $result; } try { // Get latest block number $latestBlockResponse = sendRpcRequest($rpcUrl, 'eth_blockNumber', []); $latestBlockNum = hexdec($latestBlockResponse['result']); // Start from block 0 (adjust this to a later block if you know your address was created then) $startBlock = 0; // Iterate through blocks in chunks to avoid overwhelming the node $chunkSize = 1000; for ($i = $startBlock; $i <= $latestBlockNum; $i += $chunkSize) { $endBlock = min($i + $chunkSize - 1, $latestBlockNum); echo "Scanning blocks " . $i . " to " . $endBlock . "...\n"; for ($blockNum = $i; $blockNum <= $endBlock; $blockNum++) { $blockHex = '0x' . dechex($blockNum); $blockResponse = sendRpcRequest($rpcUrl, 'eth_getBlockByNumber', [$blockHex, true]); $block = $blockResponse['result']; if (empty($block['transactions'])) continue; foreach ($block['transactions'] as $tx) { if (strtolower($tx['to']) === strtolower($targetAddress)) { // This is a deposit transaction—process it as needed echo "Deposit Found:\n"; echo " TX Hash: " . $tx['hash'] . "\n"; echo " Amount (ETH): " . hexdec($tx['value']) / 1e18 . "\n"; echo " Block Number: " . hexdec($tx['blockNumber']) . "\n\n"; } } } } } catch (Exception $e) { echo "Error: " . $e->getMessage() . "\n"; }
Important note: Scanning every block from 0x0 will be extremely slow on a full node. If you know when your address was first used, set $startBlock to that block number to drastically speed things up.
If your target address is a smart contract that emits a Deposit event (common in DeFi protocols), you can use the filter methods you tried—but you need to add the event's topic hash to your filter parameters.
First, generate the topic hash from the event's Solidity signature. For example, if your contract has this event:
event Deposit(address indexed user, uint256 amount);
The event signature is Deposit(address,uint256). Generate its Keccak-256 hash in PHP:
$eventSignature = 'Deposit(address,uint256)'; $topicHash = '0x' . hash('keccak256', $eventSignature);
Then update your eth_newFilter request to include this topic:
$filterRequest = [ 'jsonrpc' => '2.0', 'method' => 'eth_newFilter', 'params' => [ [ 'fromBlock' => '0x0', 'toBlock' => 'latest', 'address' => $targetAddress, 'topics' => [$topicHash] ] ], 'id' => 1 ]; // Send the request and get the filter ID $filterResponse = sendRpcRequest($rpcUrl, 'eth_newFilter', $filterRequest['params']); $filterId = $filterResponse['result']; // Fetch all logs matching the filter $logsResponse = sendRpcRequest($rpcUrl, 'eth_getFilterLogs', [$filterId]); $logs = $logsResponse['result']; // Decode the log data (example for the Deposit event above) foreach ($logs as $log) { // Decode indexed user address (first topic after the hash) $userAddress = '0x' . substr($log['topics'][1], 26); // Decode amount from data field $amount = hexdec($log['data']) / 1e18; echo "Deposit Event:\n"; echo " User: " . $userAddress . "\n"; echo " Amount (ETH): " . $amount . "\n"; echo " TX Hash: " . $log['transactionHash'] . "\n\n"; } // Don't forget to delete the filter when done sendRpcRequest($rpcUrl, 'eth_uninstallFilter', [$filterId]);
- For large block ranges, split your requests into smaller chunks (like 10,000 blocks at a time) to avoid timeouts or overwhelming your Geth node.
- Ensure your Geth node is fully synced—light nodes won't have access to all historical data.
- Always handle RPC errors in your code to avoid unexpected crashes.
内容的提问来源于stack exchange,提问作者kishan

