PHP项目链上数据如何解析查询展示

wen PHP项目 31

本文目录导读:

PHP项目链上数据如何解析查询展示

  1. 链上数据获取方式
  2. 数据解析处理
  3. 数据存储与查询
  4. 数据展示实现
  5. 性能优化建议
  6. 安全注意事项

针对PHP项目链上数据的解析、查询与展示,我为你整理了一套完整的技术方案:

链上数据获取方式

通过区块链节点RPC接口

// 以太坊节点RPC调用示例
function getEthBalance($address) {
    $data = [
        'jsonrpc' => '2.0',
        'method' => 'eth_getBalance',
        'params' => [$address, 'latest'],
        'id' => 1
    ];
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://mainnet.infura.io/v3/YOUR_API_KEY');
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($ch);
    curl_close($ch);
    return json_decode($response, true);
}

使用区块链数据索引服务

// 使用The Graph API查询
$query = '
{
  transfers(first: 10, orderBy: timestamp, orderDirection: desc) {
    from
    to
    value
    timestamp
  }
}';
$response = file_get_contents('https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2', false, stream_context_create([
    'http' => [
        'method' => 'POST',
        'header' => 'Content-Type: application/json',
        'content' => json_encode(['query' => $query])
    ]
]));

数据解析处理

ABI解码工具类

class BlockchainDataParser {
    // 解析ERC20交易数据
    public function parseERC20Transfer($inputData) {
        $methodId = substr($inputData, 0, 10);
        $params = substr($inputData, 10);
        // Transfer方法ID: 0xa9059cbb
        if ($methodId === '0xa9059cbb') {
            $to = '0x' . substr($params, 24, 40);
            $value = hexdec(substr($params, 64, 64));
            return [
                'to' => $to,
                'value' => $this->fromWei($value)
            ];
        }
        return null;
    }
    // Wei转ETH
    public function fromWei($wei, $decimals = 18) {
        return bcdiv($wei, bcpow('10', $decimals), $decimals);
    }
}

事件日志解析

class EventLogParser {
    public function parseEventLogs($logs) {
        $events = [];
        foreach ($logs as $log) {
            // 解析主题
            $topics = $log['topics'];
            // 解析数据
            $data = $this->hexToString($log['data']);
            $events[] = [
                'address' => $log['address'],
                'topics' => $topics,
                'data' => $data,
                'blockNumber' => $log['blockNumber']
            ];
        }
        return $events;
    }
    private function hexToString($hex) {
        $string = '';
        for ($i = 0; $i < strlen($hex) - 1; $i += 2) {
            $string .= chr(hexdec($hex[$i] . $hex[$i + 1]));
        }
        return $string;
    }
}

数据存储与查询

数据库结构设计

CREATE TABLE block_transactions (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    tx_hash VARCHAR(66) UNIQUE NOT NULL,
    block_number INT NOT NULL,
    from_address VARCHAR(42) NOT NULL,
    to_address VARCHAR(42),
    value DECIMAL(65, 18),
    gas_used BIGINT,
    gas_price BIGINT,
    input_data TEXT,
    status TINYINT DEFAULT 1,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_block_number (block_number),
    INDEX idx_from_address (from_address),
    INDEX idx_to_address (to_address)
);

数据同步脚本

class BlockchainSync {
    private $db;
    private $web3;
    public function syncLatestBlocks($fromBlock, $toBlock) {
        for ($block = $fromBlock; $block <= $toBlock; $block++) {
            $blockData = $this->web3->eth_getBlockByNumber($block, true);
            if ($blockData) {
                $this->processBlockTransactions($blockData);
            }
        }
    }
    private function processBlockTransactions($blockData) {
        foreach ($blockData['transactions'] as $tx) {
            $this->saveTransaction([
                'tx_hash' => $tx['hash'],
                'block_number' => hexdec($blockData['number']),
                'from_address' => $tx['from'],
                'to_address' => $tx['to'] ?? null,
                'value' => hexdec($tx['value']),
                'gas_used' => hexdec($tx['gas']),
                'gas_price' => hexdec($tx['gasPrice']),
                'input_data' => $tx['input']
            ]);
        }
    }
}

数据展示实现

API接口设计

// 交易查询API
Route::get('/transactions/{address}', function($address) {
    $transactions = DB::table('block_transactions')
        ->where('from_address', $address)
        ->orWhere('to_address', $address)
        ->orderBy('block_number', 'desc')
        ->paginate(20);
    return response()->json([
        'code' => 200,
        'data' => $transactions,
        'total' => $transactions->total()
    ]);
});

链上数据可视化

// 使用Highcharts展示交易趋势
class TransactionChartService {
    public function getTransactionTrend($days = 30) {
        $trendData = [];
        for ($i = $days - 1; $i >= 0; $i--) {
            $date = date('Y-m-d', strtotime("-$i days"));
            $count = DB::table('block_transactions')
                ->whereDate('created_at', $date)
                ->count();
            $trendData[] = [
                'date' => $date,
                'count' => $count
            ];
        }
        return $trendData;
    }
}

前端展示组件

<!-- 区块链交易列表 -->
<div class="transactions-table">
    <table>
        <thead>
            <tr>
                <th>交易哈希</th>
                <th>区块高度</th>
                <th>发送地址</th>
                <th>接收地址</th>
                <th>金额</th>
                <th>时间</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($transactions as $tx): ?>
            <tr>
                <td class="tx-hash" title="<?= $tx['tx_hash'] ?>">
                    <?= substr($tx['tx_hash'], 0, 10) . '...' ?>
                </td>
                <td><?= $tx['block_number'] ?></td>
                <td class="address"><?= substr($tx['from_address'], 0, 6) . '...' ?></td>
                <td class="address"><?= substr($tx['to_address'], 0, 6) . '...' ?></td>
                <td class="amount">
                    <?= number_format($tx['value'], 4) ?> ETH
                </td>
                <td><?= $tx['created_at'] ?></td>
            </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
</div>
<script>
// 实时更新交易数据
function updateTransactions() {
    $.ajax({
        url: '/api/transactions/latest',
        success: function(data) {
            // 更新表格数据
            updateTable(data.transactions);
        }
    });
}
setInterval(updateTransactions, 5000);
</script>

性能优化建议

缓存策略

class BlockchainCache {
    public function getCachedData($key, $callback, $ttl = 300) {
        $cacheKey = "blockchain:{$key}";
        // 尝试从缓存获取
        $data = Redis::get($cacheKey);
        if (!$data) {
            // 从区块链获取数据
            $data = $callback();
            // 存入缓存
            Redis::setex($cacheKey, $ttl, json_encode($data));
        }
        return json_decode($data, true);
    }
}

数据索引优化

  • 对常用查询字段建立索引
  • 使用分区表管理历史数据
  • 定期清理过期数据

异步处理

// 使用队列处理区块链数据同步
class ProcessBlockchainData implements ShouldQueue {
    public function handle() {
        $sync = new BlockchainSync();
        // 处理数据同步
    }
}

安全注意事项

  1. 输入验证

    // 地址验证
    function validateAddress($address) {
     return preg_match('/^0x[a-fA-F0-9]{40}$/', $address);
    }
  2. 防SQL注入

    // 使用预处理语句
    $stmt = $db->prepare("SELECT * FROM transactions WHERE tx_hash = ?");
    $stmt->execute([$txHash]);
  3. 速率限制

    // API请求限制
    Route::middleware('throttle:60,1')->group(function () {
     Route::get('/api/blockchain/*', 'BlockchainController@index');
    });

这套方案涵盖了PHP项目处理链上数据的完整流程,你可以根据具体需求选择合适的组件和实现方式。

抱歉,评论功能暂时关闭!