package server import ( "git.grassecon.net/grassrootseconomics/openethereum-node-status/pkg/rpc" "git.grassecon.net/grassrootseconomics/openethereum-node-status/pkg/util" "github.com/rs/zerolog/log" "github.com/ybbus/jsonrpc/v2" ) var ( RpcClient rpc.RpcClient ) type ( BatchHealthResponse struct { SyncComplete bool ChainName string } BatchMetricsResponse struct { GasPrice uint64 BlockNumber uint64 PeerCount uint64 PendingTx []pendingTx PendingTxCount int Enode string } pendingTx struct { Hash string `json:"hash"` From string `json:"from"` To string `json:"to"` } ) func batchHealthCall() (bool, BatchHealthResponse) { var batchResponse BatchHealthResponse rpcResponses, err := RpcClient.EthBatchRpcCall(jsonrpc.RPCRequests{ // The rpc call id here is guranteed to be in order of appearance starting from index 0 jsonrpc.NewRequest("eth_syncing"), jsonrpc.NewRequest("parity_chain"), }) if err != nil { log.Error(). Err(err). Str("module", "server"). Msg("error in batch responses") return false, batchResponse } // Order and format isn't guranteed with batch calls therefore we individually process/transform each result in the map if syncStatus, ok := rpcResponses[0]; ok { val, err := syncStatus.GetBool() if err != nil { return false, batchResponse } // If sync is complete the rpc result is false, however this call dones't gurantee all blocks have been imported batchResponse.SyncComplete = !val } if chainName, ok := rpcResponses[1]; ok { val, err := chainName.GetString() if err != nil { return false, batchResponse } batchResponse.ChainName = val } return true, batchResponse } func batchMetricsCall() (bool, BatchMetricsResponse) { var batchResponse BatchMetricsResponse rpcResponses, err := RpcClient.EthBatchRpcCall(jsonrpc.RPCRequests{ // The rpc call id here is guranteed to be in order of appearance starting from index 0 jsonrpc.NewRequest("eth_gasPrice"), jsonrpc.NewRequest("eth_blockNumber"), jsonrpc.NewRequest("net_peerCount"), jsonrpc.NewRequest("parity_pendingTransactions"), jsonrpc.NewRequest("parity_enode"), }) if err != nil { log.Error(). Err(err). Str("module", "server"). Msg("error in batch responses") return false, batchResponse } // Order and format isn't guranteed with batch calls therefore we individually process/transform each result in the map if gasPrice, ok := rpcResponses[0]; ok { // TODO: decode hex val, err := gasPrice.GetString() if err != nil { return false, batchResponse } // If sync is complete the rpc result is false, however this call dones't gurantee all blocks have been imported batchResponse.GasPrice = util.Hex2Int(val) } if blockNumber, ok := rpcResponses[1]; ok { val, err := blockNumber.GetString() if err != nil { return false, batchResponse } batchResponse.BlockNumber = util.Hex2Int(val) } if peerCount, ok := rpcResponses[2]; ok { val, err := peerCount.GetString() if err != nil { return false, batchResponse } batchResponse.PeerCount = util.Hex2Int(val) } if pendingTransactionsArray, ok := rpcResponses[3]; ok { var pendingTransactions = []pendingTx{} err := pendingTransactionsArray.GetObject(&pendingTransactions) if err != nil { return false, batchResponse } batchResponse.PendingTxCount = len(pendingTransactions) batchResponse.PendingTx = pendingTransactions } if enode, ok := rpcResponses[4]; ok { val, err := enode.GetString() if err != nil { return false, batchResponse } batchResponse.Enode = val } return true, batchResponse }