Files
zeekayandHanzo Dev 64519916bf the corporate name is Lux Industries Inc
Lux Partners Limited is not the entity behind this work. Every place the
old name stood — copyright lines, site footers, brand config, legal and
compliance text — now names the company that actually holds it.

lux.fund is the exception and is not renamed to match: that site belongs
to Lux Assets Management LLC, a different company, and it says so.

Two kinds of line were left for a person rather than rewritten. A dated
news item recording that Lux Partners Limited was established in the Isle
of Man is a historical fact, and renaming it would falsify the record. And
a sentence asserting that the company is domiciled in the Isle of Man is a
claim about a jurisdiction, not a name — an Inc or an LLC is not an Isle
of Man company, so swapping the name there would assert something untrue.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-28 13:01:04 -07:00

776 lines
23 KiB
Go

// Copyright (c) 2025 Lux Industries Inc
// SPDX-License-Identifier: MIT
package api
import (
"context"
"encoding/json"
"fmt"
"net/http"
"strconv"
"strings"
)
// RPCHandler handles Etherscan-compatible API requests
type RPCHandler struct {
repo *Repository
}
// NewRPCHandler creates a new RPC handler
func NewRPCHandler(repo *Repository) *RPCHandler {
return &RPCHandler{repo: repo}
}
// RPCResponse is the Etherscan-style API response
type RPCResponse struct {
Status string `json:"status"`
Message string `json:"message"`
Result interface{} `json:"result"`
}
// Handle processes RPC API requests
func (h *RPCHandler) Handle(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
module := r.URL.Query().Get("module")
action := r.URL.Query().Get("action")
var resp RPCResponse
switch module {
case "account":
resp = h.handleAccount(r.Context(), action, r)
case "contract":
resp = h.handleContract(r.Context(), action, r)
case "transaction":
resp = h.handleTransaction(r.Context(), action, r)
case "block":
resp = h.handleBlock(r.Context(), action, r)
case "logs":
resp = h.handleLogs(r.Context(), action, r)
case "token":
resp = h.handleToken(r.Context(), action, r)
case "stats":
resp = h.handleStats(r.Context(), action, r)
case "proxy":
resp = h.handleProxy(r.Context(), action, r)
default:
resp = RPCResponse{
Status: "0",
Message: "NOTOK",
Result: "Invalid module",
}
}
json.NewEncoder(w).Encode(resp)
}
func (h *RPCHandler) handleAccount(ctx context.Context, action string, r *http.Request) RPCResponse {
switch action {
case "balance":
return h.getBalance(ctx, r)
case "balancemulti":
return h.getBalanceMulti(ctx, r)
case "txlist":
return h.getTxList(ctx, r)
case "txlistinternal":
return h.getInternalTxList(ctx, r)
case "tokentx":
return h.getTokenTx(ctx, r)
case "tokennfttx":
return h.getTokenNftTx(ctx, r)
case "token1155tx":
return h.getToken1155Tx(ctx, r)
case "getminedblocks":
return h.getMinedBlocks(ctx, r)
case "tokenbalance":
return h.getTokenBalance(ctx, r)
default:
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Invalid action"}
}
}
func (h *RPCHandler) getBalance(ctx context.Context, r *http.Request) RPCResponse {
address := r.URL.Query().Get("address")
if address == "" {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Missing address"}
}
balance, err := h.repo.GetAddressBalance(ctx, address)
if err != nil {
return RPCResponse{Status: "0", Message: "NOTOK", Result: err.Error()}
}
return RPCResponse{Status: "1", Message: "OK", Result: balance}
}
func (h *RPCHandler) getBalanceMulti(ctx context.Context, r *http.Request) RPCResponse {
addresses := r.URL.Query().Get("address")
if addresses == "" {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Missing address"}
}
addrList := strings.Split(addresses, ",")
type BalanceResult struct {
Account string `json:"account"`
Balance string `json:"balance"`
}
var results []BalanceResult
for _, addr := range addrList {
addr = strings.TrimSpace(addr)
balance, _ := h.repo.GetAddressBalance(ctx, addr)
results = append(results, BalanceResult{Account: addr, Balance: balance})
}
return RPCResponse{Status: "1", Message: "OK", Result: results}
}
func (h *RPCHandler) getTxList(ctx context.Context, r *http.Request) RPCResponse {
address := r.URL.Query().Get("address")
if address == "" {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Missing address"}
}
page, _ := strconv.Atoi(r.URL.Query().Get("page"))
offset, _ := strconv.Atoi(r.URL.Query().Get("offset"))
if offset <= 0 {
offset = 10
}
if page <= 0 {
page = 1
}
result, err := h.repo.GetAddressTransactions(ctx, address, page-1, offset)
if err != nil {
return RPCResponse{Status: "0", Message: "NOTOK", Result: err.Error()}
}
// Convert to Etherscan format
txs := result.Items.([]Transaction)
var etherscanTxs []map[string]interface{}
for _, tx := range txs {
etx := map[string]interface{}{
"hash": tx.Hash,
"blockNumber": fmt.Sprintf("%d", *tx.BlockNumber),
"timeStamp": fmt.Sprintf("%d", tx.Timestamp.Unix()),
"from": tx.From.Hash,
"to": "",
"value": tx.Value,
"gas": fmt.Sprintf("%d", tx.Gas),
"gasPrice": tx.GasPrice,
"gasUsed": fmt.Sprintf("%d", *tx.GasUsed),
"nonce": fmt.Sprintf("%d", tx.Nonce),
"input": tx.Input,
"transactionIndex": fmt.Sprintf("%d", *tx.TransactionIndex),
"isError": "0",
"txreceipt_status": "1",
"contractAddress": "",
"confirmations": fmt.Sprintf("%d", tx.Confirmations),
}
if tx.To != nil {
etx["to"] = tx.To.Hash
}
if tx.Status == "error" {
etx["isError"] = "1"
etx["txreceipt_status"] = "0"
}
if tx.CreatedContract != nil {
etx["contractAddress"] = tx.CreatedContract.Hash
}
etherscanTxs = append(etherscanTxs, etx)
}
return RPCResponse{Status: "1", Message: "OK", Result: etherscanTxs}
}
func (h *RPCHandler) getInternalTxList(ctx context.Context, r *http.Request) RPCResponse {
address := r.URL.Query().Get("address")
txhash := r.URL.Query().Get("txhash")
page, _ := strconv.Atoi(r.URL.Query().Get("page"))
offset, _ := strconv.Atoi(r.URL.Query().Get("offset"))
if offset <= 0 {
offset = 10
}
if page <= 0 {
page = 1
}
var result *PaginatedResponse
var err error
if txhash != "" {
result, err = h.repo.GetInternalTransactions(ctx, txhash, page-1, offset)
} else if address != "" {
// For address-based internal tx query
result = &PaginatedResponse{Items: []InternalTransaction{}}
} else {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Missing address or txhash"}
}
if err != nil {
return RPCResponse{Status: "0", Message: "NOTOK", Result: err.Error()}
}
// Convert to Etherscan format
itxs := result.Items.([]InternalTransaction)
var etherscanTxs []map[string]interface{}
for _, itx := range itxs {
etx := map[string]interface{}{
"hash": itx.TxHash,
"blockNumber": fmt.Sprintf("%d", itx.BlockNumber),
"from": itx.From.Hash,
"to": "",
"value": itx.Value,
"gas": fmt.Sprintf("%d", itx.Gas),
"gasUsed": fmt.Sprintf("%d", *itx.GasUsed),
"input": itx.Input,
"type": itx.CallType,
"isError": "0",
"errCode": "",
}
if itx.To != nil {
etx["to"] = itx.To.Hash
}
if itx.Success != nil && !*itx.Success {
etx["isError"] = "1"
etx["errCode"] = itx.Error
}
etherscanTxs = append(etherscanTxs, etx)
}
return RPCResponse{Status: "1", Message: "OK", Result: etherscanTxs}
}
func (h *RPCHandler) getTokenTx(ctx context.Context, r *http.Request) RPCResponse {
address := r.URL.Query().Get("address")
contractAddress := r.URL.Query().Get("contractaddress")
if address == "" && contractAddress == "" {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Missing address"}
}
page, _ := strconv.Atoi(r.URL.Query().Get("page"))
offset, _ := strconv.Atoi(r.URL.Query().Get("offset"))
if offset <= 0 {
offset = 10
}
if page <= 0 {
page = 1
}
targetAddr := address
if targetAddr == "" {
targetAddr = contractAddress
}
result, err := h.repo.GetAddressTokenTransfers(ctx, targetAddr, page-1, offset)
if err != nil {
return RPCResponse{Status: "0", Message: "NOTOK", Result: err.Error()}
}
// Convert to Etherscan format
transfers := result.Items.([]TokenTransfer)
var etherscanTxs []map[string]interface{}
for _, t := range transfers {
// Filter by contractAddress if provided
if contractAddress != "" && !strings.EqualFold(t.Token.Address, contractAddress) {
continue
}
etx := map[string]interface{}{
"hash": t.TxHash,
"blockNumber": fmt.Sprintf("%d", t.BlockNumber),
"timeStamp": fmt.Sprintf("%d", t.Timestamp.Unix()),
"from": t.From.Hash,
"to": t.To.Hash,
"value": t.Total.Value,
"contractAddress": t.Token.Address,
"tokenName": t.Token.Name,
"tokenSymbol": t.Token.Symbol,
"tokenDecimal": fmt.Sprintf("%d", *t.Token.Decimals),
"transactionIndex": fmt.Sprintf("%d", t.LogIndex),
"gas": "0",
"gasPrice": "0",
"gasUsed": "0",
}
etherscanTxs = append(etherscanTxs, etx)
}
return RPCResponse{Status: "1", Message: "OK", Result: etherscanTxs}
}
func (h *RPCHandler) getTokenNftTx(ctx context.Context, r *http.Request) RPCResponse {
// Similar to getTokenTx but for ERC-721
return h.getTokenTx(ctx, r)
}
func (h *RPCHandler) getToken1155Tx(ctx context.Context, r *http.Request) RPCResponse {
// Similar to getTokenTx but for ERC-1155
return h.getTokenTx(ctx, r)
}
func (h *RPCHandler) getMinedBlocks(ctx context.Context, r *http.Request) RPCResponse {
// Return empty for now - would need miner tracking
return RPCResponse{Status: "1", Message: "OK", Result: []interface{}{}}
}
func (h *RPCHandler) getTokenBalance(ctx context.Context, r *http.Request) RPCResponse {
address := r.URL.Query().Get("address")
contractAddress := r.URL.Query().Get("contractaddress")
if address == "" || contractAddress == "" {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Missing address or contractaddress"}
}
// Query token balance from database
// For now return 0 - would need token balance tracking
return RPCResponse{Status: "1", Message: "OK", Result: "0"}
}
func (h *RPCHandler) handleContract(ctx context.Context, action string, r *http.Request) RPCResponse {
switch action {
case "getabi":
return h.getABI(ctx, r)
case "getsourcecode":
return h.getSourceCode(ctx, r)
case "getcontractcreation":
return h.getContractCreation(ctx, r)
default:
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Invalid action"}
}
}
func (h *RPCHandler) getABI(ctx context.Context, r *http.Request) RPCResponse {
address := r.URL.Query().Get("address")
if address == "" {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Missing address"}
}
contract, err := h.repo.GetSmartContract(ctx, address)
if err != nil {
return RPCResponse{Status: "0", Message: "NOTOK-Contract source code not verified", Result: ""}
}
if !contract.IsVerified {
return RPCResponse{Status: "0", Message: "NOTOK-Contract source code not verified", Result: ""}
}
return RPCResponse{Status: "1", Message: "OK", Result: string(contract.ABI)}
}
func (h *RPCHandler) getSourceCode(ctx context.Context, r *http.Request) RPCResponse {
address := r.URL.Query().Get("address")
if address == "" {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Missing address"}
}
contract, err := h.repo.GetSmartContract(ctx, address)
if err != nil {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Contract not found"}
}
result := []map[string]interface{}{
{
"SourceCode": contract.SourceCode,
"ABI": string(contract.ABI),
"ContractName": contract.Name,
"CompilerVersion": contract.CompilerVersion,
"OptimizationUsed": "0",
"Runs": contract.OptimizationRuns,
"ConstructorArguments": contract.ConstructorArgs,
"EVMVersion": contract.EVMVersion,
"Library": "",
"LicenseType": contract.LicenseType,
"Proxy": "0",
"Implementation": "",
"SwarmSource": "",
},
}
if contract.OptimizationEnabled {
result[0]["OptimizationUsed"] = "1"
}
if contract.IsProxy {
result[0]["Proxy"] = "1"
if len(contract.Implementations) > 0 {
result[0]["Implementation"] = contract.Implementations[0].Address
}
}
return RPCResponse{Status: "1", Message: "OK", Result: result}
}
func (h *RPCHandler) getContractCreation(ctx context.Context, r *http.Request) RPCResponse {
addresses := r.URL.Query().Get("contractaddresses")
if addresses == "" {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Missing contractaddresses"}
}
addrList := strings.Split(addresses, ",")
var results []map[string]interface{}
for _, addr := range addrList {
addr = strings.TrimSpace(addr)
address, err := h.repo.GetAddress(ctx, addr)
if err != nil || !address.IsContract {
continue
}
result := map[string]interface{}{
"contractAddress": addr,
"contractCreator": "",
"txHash": "",
}
if address.Creator != nil {
result["contractCreator"] = address.Creator.Hash
}
if address.CreationTxHash != "" {
result["txHash"] = address.CreationTxHash
}
results = append(results, result)
}
return RPCResponse{Status: "1", Message: "OK", Result: results}
}
func (h *RPCHandler) handleTransaction(ctx context.Context, action string, r *http.Request) RPCResponse {
switch action {
case "getstatus":
return h.getTxStatus(ctx, r)
case "gettxreceiptstatus":
return h.getTxReceiptStatus(ctx, r)
default:
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Invalid action"}
}
}
func (h *RPCHandler) getTxStatus(ctx context.Context, r *http.Request) RPCResponse {
txhash := r.URL.Query().Get("txhash")
if txhash == "" {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Missing txhash"}
}
tx, err := h.repo.GetTransactionByHash(ctx, txhash)
if err != nil {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Transaction not found"}
}
result := map[string]interface{}{
"isError": "0",
"errDescription": "",
}
if tx.Status == "error" {
result["isError"] = "1"
result["errDescription"] = tx.RevertReason
}
return RPCResponse{Status: "1", Message: "OK", Result: result}
}
func (h *RPCHandler) getTxReceiptStatus(ctx context.Context, r *http.Request) RPCResponse {
txhash := r.URL.Query().Get("txhash")
if txhash == "" {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Missing txhash"}
}
tx, err := h.repo.GetTransactionByHash(ctx, txhash)
if err != nil {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Transaction not found"}
}
status := "1"
if tx.Status == "error" {
status = "0"
}
return RPCResponse{Status: "1", Message: "OK", Result: map[string]string{"status": status}}
}
func (h *RPCHandler) handleBlock(ctx context.Context, action string, r *http.Request) RPCResponse {
switch action {
case "getblockreward":
return h.getBlockReward(ctx, r)
case "getblockcountdown":
return h.getBlockCountdown(ctx, r)
case "getblocknobytime":
return h.getBlockByTime(ctx, r)
case "dailyavgblocksize":
return h.getDailyBlockSize(ctx, r)
case "dailyblkcount":
return h.getDailyBlockCount(ctx, r)
default:
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Invalid action"}
}
}
func (h *RPCHandler) getBlockReward(ctx context.Context, r *http.Request) RPCResponse {
blockno := r.URL.Query().Get("blockno")
if blockno == "" {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Missing blockno"}
}
height, err := strconv.ParseUint(blockno, 10, 64)
if err != nil {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Invalid blockno"}
}
block, err := h.repo.GetBlockByNumber(ctx, height)
if err != nil {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Block not found"}
}
result := map[string]interface{}{
"blockNumber": fmt.Sprintf("%d", block.Height),
"timeStamp": fmt.Sprintf("%d", block.Timestamp.Unix()),
"blockMiner": "",
"blockReward": "0",
"uncles": []interface{}{},
"uncleInclusionReward": "0",
}
if block.Miner != nil {
result["blockMiner"] = block.Miner.Hash
}
return RPCResponse{Status: "1", Message: "OK", Result: result}
}
func (h *RPCHandler) getBlockCountdown(ctx context.Context, r *http.Request) RPCResponse {
// Return countdown to target block
return RPCResponse{Status: "1", Message: "OK", Result: map[string]interface{}{
"CurrentBlock": "0",
"CountdownBlock": "0",
"RemainingBlock": "0",
"EstimateTimeInSec": "0",
}}
}
func (h *RPCHandler) getBlockByTime(ctx context.Context, r *http.Request) RPCResponse {
// Get block by timestamp
return RPCResponse{Status: "1", Message: "OK", Result: "0"}
}
func (h *RPCHandler) getDailyBlockSize(ctx context.Context, r *http.Request) RPCResponse {
return RPCResponse{Status: "1", Message: "OK", Result: []interface{}{}}
}
func (h *RPCHandler) getDailyBlockCount(ctx context.Context, r *http.Request) RPCResponse {
return RPCResponse{Status: "1", Message: "OK", Result: []interface{}{}}
}
func (h *RPCHandler) handleLogs(ctx context.Context, action string, r *http.Request) RPCResponse {
if action != "getLogs" {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Invalid action"}
}
address := r.URL.Query().Get("address")
fromBlock, _ := strconv.ParseUint(r.URL.Query().Get("fromBlock"), 10, 64)
toBlock, _ := strconv.ParseUint(r.URL.Query().Get("toBlock"), 10, 64)
topic0 := r.URL.Query().Get("topic0")
topic1 := r.URL.Query().Get("topic1")
topic2 := r.URL.Query().Get("topic2")
topic3 := r.URL.Query().Get("topic3")
topics := []string{topic0, topic1, topic2, topic3}
page, _ := strconv.Atoi(r.URL.Query().Get("page"))
offset, _ := strconv.Atoi(r.URL.Query().Get("offset"))
if offset <= 0 {
offset = 1000
}
if page <= 0 {
page = 1
}
result, err := h.repo.GetLogs(ctx, address, fromBlock, toBlock, topics, page-1, offset)
if err != nil {
return RPCResponse{Status: "0", Message: "NOTOK", Result: err.Error()}
}
// Convert to Etherscan format
logs := result.Items.([]Log)
var etherscanLogs []map[string]interface{}
for _, log := range logs {
elog := map[string]interface{}{
"address": log.Address.Hash,
"topics": log.Topics,
"data": log.Data,
"blockNumber": fmt.Sprintf("0x%x", log.BlockNumber),
"transactionHash": log.TxHash,
"transactionIndex": fmt.Sprintf("0x%x", 0),
"blockHash": log.BlockHash,
"logIndex": fmt.Sprintf("0x%x", log.Index),
"removed": false,
}
etherscanLogs = append(etherscanLogs, elog)
}
return RPCResponse{Status: "1", Message: "OK", Result: etherscanLogs}
}
func (h *RPCHandler) handleToken(ctx context.Context, action string, r *http.Request) RPCResponse {
switch action {
case "tokeninfo":
return h.getTokenInfo(ctx, r)
case "tokenholderlist":
return h.getTokenHolderList(ctx, r)
case "tokensupply":
return h.getTokenSupply(ctx, r)
case "tokensupplyhistory":
return h.getTokenSupplyHistory(ctx, r)
default:
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Invalid action"}
}
}
func (h *RPCHandler) getTokenInfo(ctx context.Context, r *http.Request) RPCResponse {
contractAddress := r.URL.Query().Get("contractaddress")
if contractAddress == "" {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Missing contractaddress"}
}
token, err := h.repo.GetToken(ctx, contractAddress)
if err != nil {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Token not found"}
}
result := []map[string]interface{}{
{
"contractAddress": token.Address,
"tokenName": token.Name,
"symbol": token.Symbol,
"divisor": fmt.Sprintf("%d", *token.Decimals),
"tokenType": token.Type,
"totalSupply": token.TotalSupply,
"description": "",
"website": "",
"email": "",
"blog": "",
"reddit": "",
"slack": "",
"facebook": "",
"twitter": "",
"bitcointalk": "",
"github": "",
"telegram": "",
"wechat": "",
"linkedin": "",
"discord": "",
"whitepaper": "",
},
}
return RPCResponse{Status: "1", Message: "OK", Result: result}
}
func (h *RPCHandler) getTokenHolderList(ctx context.Context, r *http.Request) RPCResponse {
contractAddress := r.URL.Query().Get("contractaddress")
if contractAddress == "" {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Missing contractaddress"}
}
page, _ := strconv.Atoi(r.URL.Query().Get("page"))
offset, _ := strconv.Atoi(r.URL.Query().Get("offset"))
if offset <= 0 {
offset = 10
}
if page <= 0 {
page = 1
}
// Would need to query token_balances table
return RPCResponse{Status: "1", Message: "OK", Result: []interface{}{}}
}
func (h *RPCHandler) getTokenSupply(ctx context.Context, r *http.Request) RPCResponse {
contractAddress := r.URL.Query().Get("contractaddress")
if contractAddress == "" {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Missing contractaddress"}
}
token, err := h.repo.GetToken(ctx, contractAddress)
if err != nil {
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Token not found"}
}
return RPCResponse{Status: "1", Message: "OK", Result: token.TotalSupply}
}
func (h *RPCHandler) getTokenSupplyHistory(ctx context.Context, r *http.Request) RPCResponse {
return RPCResponse{Status: "1", Message: "OK", Result: []interface{}{}}
}
func (h *RPCHandler) handleStats(ctx context.Context, action string, r *http.Request) RPCResponse {
switch action {
case "ethsupply":
return h.getEthSupply(ctx, r)
case "ethprice":
return h.getEthPrice(ctx, r)
case "chainsize":
return h.getChainSize(ctx, r)
case "nodecount":
return h.getNodeCount(ctx, r)
default:
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Invalid action"}
}
}
func (h *RPCHandler) getEthSupply(ctx context.Context, r *http.Request) RPCResponse {
// Return total supply
return RPCResponse{Status: "1", Message: "OK", Result: "0"}
}
func (h *RPCHandler) getEthPrice(ctx context.Context, r *http.Request) RPCResponse {
return RPCResponse{Status: "1", Message: "OK", Result: map[string]interface{}{
"ethbtc": "0",
"ethbtc_timestamp": "0",
"ethusd": "0",
"ethusd_timestamp": "0",
}}
}
func (h *RPCHandler) getChainSize(ctx context.Context, r *http.Request) RPCResponse {
return RPCResponse{Status: "1", Message: "OK", Result: []interface{}{}}
}
func (h *RPCHandler) getNodeCount(ctx context.Context, r *http.Request) RPCResponse {
return RPCResponse{Status: "1", Message: "OK", Result: map[string]interface{}{
"UTCDate": "",
"TotalNodeCount": 0,
}}
}
func (h *RPCHandler) handleProxy(ctx context.Context, action string, r *http.Request) RPCResponse {
switch action {
case "eth_blockNumber":
return RPCResponse{Status: "1", Message: "OK", Result: "0x0"}
case "eth_getBlockByNumber":
return RPCResponse{Status: "1", Message: "OK", Result: nil}
case "eth_getTransactionByHash":
return RPCResponse{Status: "1", Message: "OK", Result: nil}
case "eth_getTransactionReceipt":
return RPCResponse{Status: "1", Message: "OK", Result: nil}
case "eth_call":
return RPCResponse{Status: "1", Message: "OK", Result: "0x"}
case "eth_getCode":
return RPCResponse{Status: "1", Message: "OK", Result: "0x"}
case "eth_getStorageAt":
return RPCResponse{Status: "1", Message: "OK", Result: "0x"}
case "eth_gasPrice":
return RPCResponse{Status: "1", Message: "OK", Result: "0x0"}
case "eth_estimateGas":
return RPCResponse{Status: "1", Message: "OK", Result: "0x0"}
default:
return RPCResponse{Status: "0", Message: "NOTOK", Result: "Invalid action"}
}
}