Refactor `eth_` RPC:s to improve support for Truffle, web3.js etc

pull/3506/head
Sebastian Johnsson 4 years ago
parent 0aa7f1c708
commit cf4f6dd321
  1. 1
      node/api.go
  2. 11
      rpc/blockchain.go
  3. 43
      rpc/eth/rpc.go
  4. 343
      rpc/eth/types.go
  5. 14
      rpc/net.go
  6. 13
      rpc/pool.go
  7. 10
      rpc/rpc.go
  8. 41
      rpc/transaction.go
  9. 37
      rpc/utils/utils.go

@ -117,6 +117,7 @@ func (node *Node) APIs(harmony *hmy.Harmony) []rpc.API {
Service: filters.NewPublicFilterAPI(harmony, false),
Public: true,
},
hmy_rpc.NewPublicNetAPI(node.host, harmony.ChainID, hmy_rpc.Eth),
}
}

@ -16,6 +16,7 @@ import (
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/numeric"
rpc_common "github.com/harmony-one/harmony/rpc/common"
eth "github.com/harmony-one/harmony/rpc/eth"
v1 "github.com/harmony-one/harmony/rpc/v1"
v2 "github.com/harmony-one/harmony/rpc/v2"
"github.com/harmony-one/harmony/shard"
@ -150,16 +151,19 @@ func (s *PublicBlockchainService) GetBlockByNumber(
leader := s.hmy.GetLeaderAddress(blk.Header().Coinbase(), blk.Header().Epoch())
var rpcBlock interface{}
switch s.version {
case V1, Eth:
case V1:
rpcBlock, err = v1.NewBlock(blk, blockArgs, leader)
case V2:
rpcBlock, err = v2.NewBlock(blk, blockArgs, leader)
case Eth:
rpcBlock, err = eth.NewBlock(blk, blockArgs, leader)
default:
return nil, ErrUnknownRPCVersion
}
if err != nil {
return nil, err
}
response, err = NewStructuredResponse(rpcBlock)
if err != nil {
return nil, err
@ -171,6 +175,7 @@ func (s *PublicBlockchainService) GetBlockByNumber(
response[field] = nil
}
}
return response, err
}
@ -207,10 +212,12 @@ func (s *PublicBlockchainService) GetBlockByHash(
leader := s.hmy.GetLeaderAddress(blk.Header().Coinbase(), blk.Header().Epoch())
var rpcBlock interface{}
switch s.version {
case V1, Eth:
case V1:
rpcBlock, err = v1.NewBlock(blk, blockArgs, leader)
case V2:
rpcBlock, err = v2.NewBlock(blk, blockArgs, leader)
case Eth:
rpcBlock, err = eth.NewBlock(blk, blockArgs, leader)
default:
return nil, ErrUnknownRPCVersion
}

@ -0,0 +1,43 @@
package v1
import (
"context"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/rpc"
"github.com/harmony-one/harmony/hmy"
internal_common "github.com/harmony-one/harmony/internal/common"
)
// PublicEthService provides an API to access to the Eth endpoints for the Harmony blockchain.
type PublicEthService struct {
hmy *hmy.Harmony
}
// NewPublicEthService creates a new API for the RPC interface
func NewPublicEthService(hmy *hmy.Harmony, namespace string) rpc.API {
if namespace == "" {
namespace = "eth"
}
return rpc.API{
Namespace: namespace,
Version: "1.0",
Service: &PublicEthService{hmy},
Public: true,
}
}
// GetBalance returns the amount of Atto for the given address in the state of the
// given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
// block numbers are also allowed.
func (s *PublicEthService) GetBalance(
ctx context.Context, address string, blockNr rpc.BlockNumber,
) (*hexutil.Big, error) {
addr := internal_common.ParseAddr(address)
balance, err := s.hmy.GetBalance(ctx, addr, blockNr)
if err != nil {
return nil, err
}
return (*hexutil.Big)(balance), nil
}

@ -0,0 +1,343 @@
package v1
import (
"fmt"
"math/big"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/harmony-one/harmony/core/types"
internal_common "github.com/harmony-one/harmony/internal/common"
rpc_common "github.com/harmony-one/harmony/rpc/common"
rpc_utils "github.com/harmony-one/harmony/rpc/utils"
)
// BlockWithTxHash represents a block that will serialize to the RPC representation of a block
// having ONLY transaction hashes in the Transaction fields.
type BlockWithTxHash struct {
Number *hexutil.Big `json:"number"`
ViewID *hexutil.Big `json:"viewID"`
Epoch *hexutil.Big `json:"epoch"`
Hash common.Hash `json:"hash"`
ParentHash common.Hash `json:"parentHash"`
Nonce uint64 `json:"nonce"`
MixHash common.Hash `json:"mixHash"`
LogsBloom ethtypes.Bloom `json:"logsBloom"`
StateRoot common.Hash `json:"stateRoot"`
Miner string `json:"miner"`
Difficulty uint64 `json:"difficulty"`
ExtraData hexutil.Bytes `json:"extraData"`
Size hexutil.Uint64 `json:"size"`
GasLimit hexutil.Uint64 `json:"gasLimit"`
GasUsed hexutil.Uint64 `json:"gasUsed"`
Timestamp hexutil.Uint64 `json:"timestamp"`
TransactionsRoot common.Hash `json:"transactionsRoot"`
ReceiptsRoot common.Hash `json:"receiptsRoot"`
Uncles []common.Hash `json:"uncles"`
Transactions []common.Hash `json:"transactions"`
Signers []string `json:"signers,omitempty"`
}
// BlockWithFullTx represents a block that will serialize to the RPC representation of a block
// having FULL transactions in the Transaction fields.
type BlockWithFullTx struct {
Number *hexutil.Big `json:"number"`
ViewID *hexutil.Big `json:"viewID"`
Epoch *hexutil.Big `json:"epoch"`
Hash common.Hash `json:"hash"`
ParentHash common.Hash `json:"parentHash"`
Nonce uint64 `json:"nonce"`
MixHash common.Hash `json:"mixHash"`
LogsBloom ethtypes.Bloom `json:"logsBloom"`
StateRoot common.Hash `json:"stateRoot"`
Miner string `json:"miner"`
Difficulty uint64 `json:"difficulty"`
ExtraData hexutil.Bytes `json:"extraData"`
Size hexutil.Uint64 `json:"size"`
GasLimit hexutil.Uint64 `json:"gasLimit"`
GasUsed hexutil.Uint64 `json:"gasUsed"`
Timestamp hexutil.Uint64 `json:"timestamp"`
TransactionsRoot common.Hash `json:"transactionsRoot"`
ReceiptsRoot common.Hash `json:"receiptsRoot"`
Uncles []common.Hash `json:"uncles"`
Transactions []*Transaction `json:"transactions"`
Signers []string `json:"signers,omitempty"`
}
// Transaction represents a transaction that will serialize to the RPC representation of a transaction
type Transaction struct {
BlockHash common.Hash `json:"blockHash"`
BlockNumber *hexutil.Big `json:"blockNumber"`
From string `json:"from"`
Timestamp hexutil.Uint64 `json:"timestamp"`
Gas hexutil.Uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"`
Hash common.Hash `json:"hash"`
Input hexutil.Bytes `json:"input"`
Nonce hexutil.Uint64 `json:"nonce"`
To string `json:"to"`
TransactionIndex hexutil.Uint `json:"transactionIndex"`
Value *hexutil.Big `json:"value"`
ShardID uint32 `json:"shardID"`
ToShardID uint32 `json:"toShardID"`
V *hexutil.Big `json:"v"`
R *hexutil.Big `json:"r"`
S *hexutil.Big `json:"s"`
}
// TxReceipt represents a transaction receipt that will serialize to the RPC representation.
type TxReceipt struct {
BlockHash common.Hash `json:"blockHash"`
TransactionHash common.Hash `json:"transactionHash"`
BlockNumber hexutil.Uint64 `json:"blockNumber"`
TransactionIndex hexutil.Uint64 `json:"transactionIndex"`
GasUsed hexutil.Uint64 `json:"gasUsed"`
CumulativeGasUsed hexutil.Uint64 `json:"cumulativeGasUsed"`
ContractAddress common.Address `json:"contractAddress"`
Logs []*types.Log `json:"logs"`
LogsBloom ethtypes.Bloom `json:"logsBloom"`
ShardID uint32 `json:"shardID"`
From string `json:"from"`
To string `json:"to"`
Root hexutil.Bytes `json:"root"`
Status hexutil.Uint `json:"status"`
}
// CxReceipt represents a CxReceipt that will serialize to the RPC representation of a CxReceipt
type CxReceipt struct {
BlockHash common.Hash `json:"blockHash"`
BlockNumber *hexutil.Big `json:"blockNumber"`
TxHash common.Hash `json:"hash"`
From string `json:"from"`
To string `json:"to"`
ShardID uint32 `json:"shardID"`
ToShardID uint32 `json:"toShardID"`
Amount *hexutil.Big `json:"value"`
}
// NewTransaction returns a transaction that will serialize to the RPC
// representation, with the given location metadata set (if available).
// Note that all txs on Harmony are replay protected (post EIP155 epoch).
func NewTransaction(
tx *types.Transaction, blockHash common.Hash,
blockNumber uint64, timestamp uint64, index uint64,
) (*Transaction, error) {
from, err := tx.SenderAddress()
if err != nil {
return nil, err
}
v, r, s := tx.RawSignatureValues()
result := &Transaction{
Gas: hexutil.Uint64(tx.GasLimit()),
GasPrice: (*hexutil.Big)(tx.GasPrice()),
Hash: tx.Hash(),
Input: hexutil.Bytes(tx.Data()),
Nonce: hexutil.Uint64(tx.Nonce()),
Value: (*hexutil.Big)(tx.Value()),
ShardID: tx.ShardID(),
ToShardID: tx.ToShardID(),
Timestamp: hexutil.Uint64(timestamp),
V: (*hexutil.Big)(v),
R: (*hexutil.Big)(r),
S: (*hexutil.Big)(s),
}
if blockHash != (common.Hash{}) {
result.BlockHash = blockHash
result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber))
result.TransactionIndex = hexutil.Uint(index)
}
result.From, result.To, err = rpc_utils.ConvertAddresses(&from, tx.To(), false)
if err != nil {
return nil, err
}
return result, nil
}
// NewReceipt returns an ETH transaction transaction that will serialize to the RPC representation.
func NewReceipt(
tx interface{}, blockHash common.Hash, blockNumber, blockIndex uint64, receipt *types.Receipt,
) (interface{}, error) {
plainTx, ok := tx.(*types.Transaction)
if ok {
return NewTxReceipt(plainTx, blockHash, blockNumber, blockIndex, receipt)
}
return nil, fmt.Errorf("unknown transaction type for RPC receipt")
}
// NewTxReceipt returns a transaction receipt that will serialize to the RPC representation
func NewTxReceipt(
tx *types.Transaction, blockHash common.Hash, blockNumber, blockIndex uint64, receipt *types.Receipt,
) (*TxReceipt, error) {
// Set correct to & from address
senderAddr, err := tx.SenderAddress()
if err != nil {
return nil, err
}
sender, receiver, err := rpc_utils.ConvertAddresses(&senderAddr, tx.To(), false)
if err != nil {
return nil, err
}
// Declare receipt
txReceipt := &TxReceipt{
BlockHash: blockHash,
TransactionHash: tx.Hash(),
BlockNumber: hexutil.Uint64(blockNumber),
TransactionIndex: hexutil.Uint64(blockIndex),
GasUsed: hexutil.Uint64(receipt.GasUsed),
CumulativeGasUsed: hexutil.Uint64(receipt.CumulativeGasUsed),
Logs: receipt.Logs,
LogsBloom: receipt.Bloom,
ShardID: tx.ShardID(),
From: sender,
To: receiver,
Root: receipt.PostState,
Status: hexutil.Uint(receipt.Status),
}
// Set empty array for empty logs
if receipt.Logs == nil {
txReceipt.Logs = []*types.Log{}
}
// If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation
if receipt.ContractAddress != (common.Address{}) {
txReceipt.ContractAddress = receipt.ContractAddress
}
return txReceipt, nil
}
// NewBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are
// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain
// transaction hashes.
func NewBlock(b *types.Block, blockArgs *rpc_common.BlockArgs, leader string) (interface{}, error) {
if strings.HasPrefix(leader, "one1") {
// Handle hex address
addr, err := internal_common.Bech32ToAddress(leader)
if err != nil {
return nil, err
}
leader = addr.String()
}
if blockArgs.FullTx {
return NewBlockWithFullTx(b, blockArgs, leader)
}
return NewBlockWithTxHash(b, blockArgs, leader)
}
// NewBlockWithTxHash ..
func NewBlockWithTxHash(
b *types.Block, blockArgs *rpc_common.BlockArgs, leader string,
) (*BlockWithTxHash, error) {
if blockArgs.FullTx {
return nil, fmt.Errorf("block args specifies full tx, but requested RPC block with only tx hash")
}
head := b.Header()
blk := &BlockWithTxHash{
Number: (*hexutil.Big)(head.Number()),
ViewID: (*hexutil.Big)(head.ViewID()),
Epoch: (*hexutil.Big)(head.Epoch()),
Hash: b.Hash(),
ParentHash: head.ParentHash(),
Nonce: 0, // Remove this because we don't have it in our header
MixHash: head.MixDigest(),
LogsBloom: head.Bloom(),
StateRoot: head.Root(),
Miner: leader,
Difficulty: 0, // Remove this because we don't have it in our header
ExtraData: hexutil.Bytes(head.Extra()),
Size: hexutil.Uint64(b.Size()),
GasLimit: hexutil.Uint64(head.GasLimit()),
GasUsed: hexutil.Uint64(head.GasUsed()),
Timestamp: hexutil.Uint64(head.Time().Uint64()),
TransactionsRoot: head.TxHash(),
ReceiptsRoot: head.ReceiptHash(),
Uncles: []common.Hash{},
Transactions: []common.Hash{},
}
for _, tx := range b.Transactions() {
blk.Transactions = append(blk.Transactions, tx.Hash())
}
if blockArgs.WithSigners {
blk.Signers = blockArgs.Signers
}
return blk, nil
}
// NewBlockWithFullTx ..
func NewBlockWithFullTx(
b *types.Block, blockArgs *rpc_common.BlockArgs, leader string,
) (*BlockWithFullTx, error) {
if !blockArgs.FullTx {
return nil, fmt.Errorf("block args specifies NO full tx, but requested RPC block with full tx")
}
head := b.Header()
blk := &BlockWithFullTx{
Number: (*hexutil.Big)(head.Number()),
ViewID: (*hexutil.Big)(head.ViewID()),
Epoch: (*hexutil.Big)(head.Epoch()),
Hash: b.Hash(),
ParentHash: head.ParentHash(),
Nonce: 0, // Remove this because we don't have it in our header
MixHash: head.MixDigest(),
LogsBloom: head.Bloom(),
StateRoot: head.Root(),
Miner: leader,
Difficulty: 0, // Remove this because we don't have it in our header
ExtraData: hexutil.Bytes(head.Extra()),
Size: hexutil.Uint64(b.Size()),
GasLimit: hexutil.Uint64(head.GasLimit()),
GasUsed: hexutil.Uint64(head.GasUsed()),
Timestamp: hexutil.Uint64(head.Time().Uint64()),
TransactionsRoot: head.TxHash(),
ReceiptsRoot: head.ReceiptHash(),
Uncles: []common.Hash{},
Transactions: []*Transaction{},
}
for _, tx := range b.Transactions() {
fmtTx, err := NewTransactionFromBlockHash(b, tx.Hash())
if err != nil {
return nil, err
}
blk.Transactions = append(blk.Transactions, fmtTx)
}
if blockArgs.WithSigners {
blk.Signers = blockArgs.Signers
}
return blk, nil
}
// NewTransactionFromBlockHash returns a transaction that will serialize to the RPC representation.
func NewTransactionFromBlockHash(b *types.Block, hash common.Hash) (*Transaction, error) {
for idx, tx := range b.Transactions() {
if tx.Hash() == hash {
return NewTransactionFromBlockIndex(b, uint64(idx))
}
}
return nil, fmt.Errorf("tx %v not found in block %v", hash, b.Hash().String())
}
// NewTransactionFromBlockIndex returns a transaction that will serialize to the RPC representation.
func NewTransactionFromBlockIndex(b *types.Block, index uint64) (*Transaction, error) {
txs := b.Transactions()
if index >= uint64(len(txs)) {
return nil, fmt.Errorf(
"tx index %v greater than or equal to number of transactions on block %v", index, b.Hash().String(),
)
}
return NewTransaction(txs[index], b.Hash(), b.NumberU64(), b.Time().Uint64(), index)
}

@ -6,6 +6,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/rpc"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/p2p"
)
@ -22,10 +23,12 @@ func NewPublicNetAPI(net p2p.Host, chainID uint64, version Version) rpc.API {
// manually set different namespace to preserve legacy behavior
var namespace string
switch version {
case V1, Eth:
case V1:
namespace = netV1Namespace
case V2:
namespace = netV2Namespace
case Eth:
namespace = netNamespace
default:
utils.Logger().Error().Msgf("Unknown version %v, ignoring API.", version)
return rpc.API{}
@ -54,6 +57,11 @@ func (s *PublicNetService) PeerCount(ctx context.Context) (interface{}, error) {
}
// Version returns the network version, i.e. ChainID identifying which network we are using
func (s *PublicNetService) Version(ctx context.Context) string {
return fmt.Sprintf("%d", s.chainID)
func (s *PublicNetService) Version(ctx context.Context) interface{} {
switch s.version {
case Eth:
return hexutil.Uint64(nodeconfig.GetDefaultConfig().GetNetworkType().ChainConfig().EthCompatibleChainID.Uint64())
default:
return fmt.Sprintf("%d", s.chainID)
}
}

@ -16,6 +16,7 @@ import (
common2 "github.com/harmony-one/harmony/internal/common"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"github.com/harmony-one/harmony/internal/utils"
eth "github.com/harmony-one/harmony/rpc/eth"
v1 "github.com/harmony-one/harmony/rpc/v1"
v2 "github.com/harmony-one/harmony/rpc/v2"
staking "github.com/harmony-one/harmony/staking/types"
@ -184,7 +185,7 @@ func (s *PublicPoolService) PendingTransactions(
if plainTx, ok := pending[i].(*types.Transaction); ok {
var tx interface{}
switch s.version {
case V1, Eth:
case V1:
tx, err = v1.NewTransaction(plainTx, common.Hash{}, 0, 0, 0)
if err != nil {
utils.Logger().Debug().
@ -200,6 +201,14 @@ func (s *PublicPoolService) PendingTransactions(
Msgf("%v error at %v", LogTag, "PendingTransactions")
continue // Legacy behavior is to not return error here
}
case Eth:
tx, err = eth.NewTransaction(plainTx, common.Hash{}, 0, 0, 0)
if err != nil {
utils.Logger().Debug().
Err(err).
Msgf("%v error at %v", LogTag, "PendingTransactions")
continue // Legacy behavior is to not return error here
}
default:
return nil, ErrUnknownRPCVersion
}
@ -239,7 +248,7 @@ func (s *PublicPoolService) PendingStakingTransactions(
} else if stakingTx, ok := pending[i].(*staking.StakingTransaction); ok {
var tx interface{}
switch s.version {
case V1, Eth:
case V1:
tx, err = v1.NewStakingTransaction(stakingTx, common.Hash{}, 0, 0, 0)
if err != nil {
utils.Logger().Debug().

@ -10,6 +10,7 @@ import (
"github.com/harmony-one/harmony/hmy"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
"github.com/harmony-one/harmony/internal/utils"
eth "github.com/harmony-one/harmony/rpc/eth"
v1 "github.com/harmony-one/harmony/rpc/v1"
v2 "github.com/harmony-one/harmony/rpc/v2"
)
@ -34,15 +35,16 @@ const (
// WSPortOffset ..
WSPortOffset = 800
netV1Namespace = "net"
netNamespace = "net"
netV1Namespace = "netv1"
netV2Namespace = "netv2"
)
var (
// HTTPModules ..
HTTPModules = []string{"hmy", "hmyv2", "eth", "debug", netV1Namespace, netV2Namespace, "explorer"}
HTTPModules = []string{"hmy", "hmyv2", "eth", "debug", netNamespace, netV1Namespace, netV2Namespace, "explorer"}
// WSModules ..
WSModules = []string{"hmy", "hmyv2", "eth", "debug", netV1Namespace, netV2Namespace, "web3"}
WSModules = []string{"hmy", "hmyv2", "eth", "debug", netNamespace, netV1Namespace, netV2Namespace, "web3"}
httpListener net.Listener
httpHandler *rpc.Server
@ -140,7 +142,7 @@ func getAPIs(hmy *hmy.Harmony, debugEnable bool) []rpc.API {
NewPublicTracerAPI(hmy, Debug),
// Legacy methods (subject to removal)
v1.NewPublicLegacyAPI(hmy, "hmy"),
v1.NewPublicLegacyAPI(hmy, "eth"),
eth.NewPublicEthService(hmy, "eth"),
v2.NewPublicLegacyAPI(hmy, "hmyv2"),
}

@ -18,6 +18,7 @@ import (
internal_common "github.com/harmony-one/harmony/internal/common"
"github.com/harmony-one/harmony/internal/params"
"github.com/harmony-one/harmony/internal/utils"
eth "github.com/harmony-one/harmony/rpc/eth"
v1 "github.com/harmony-one/harmony/rpc/v1"
v2 "github.com/harmony-one/harmony/rpc/v2"
staking "github.com/harmony-one/harmony/staking/types"
@ -173,7 +174,7 @@ func (s *PublicTransactionService) GetTransactionByHash(
// Format the response according to the version
switch s.version {
case V1, Eth:
case V1:
tx, err := v1.NewTransaction(tx, blockHash, blockNumber, block.Time().Uint64(), index)
if err != nil {
return nil, err
@ -185,6 +186,12 @@ func (s *PublicTransactionService) GetTransactionByHash(
return nil, err
}
return NewStructuredResponse(tx)
case Eth:
tx, err := eth.NewTransaction(tx, blockHash, blockNumber, block.Time().Uint64(), index)
if err != nil {
return nil, err
}
return NewStructuredResponse(tx)
default:
return nil, ErrUnknownRPCVersion
}
@ -213,7 +220,7 @@ func (s *PublicTransactionService) GetStakingTransactionByHash(
}
switch s.version {
case V1, Eth:
case V1:
tx, err := v1.NewStakingTransaction(stx, blockHash, blockNumber, block.Time().Uint64(), index)
if err != nil {
return nil, err
@ -402,7 +409,7 @@ func (s *PublicTransactionService) GetTransactionByBlockNumberAndIndex(
// Format response according to version
switch s.version {
case V1, Eth:
case V1:
tx, err := v1.NewTransactionFromBlockIndex(block, uint64(index))
if err != nil {
return nil, err
@ -414,6 +421,12 @@ func (s *PublicTransactionService) GetTransactionByBlockNumberAndIndex(
return nil, err
}
return NewStructuredResponse(tx)
case Eth:
tx, err := eth.NewTransactionFromBlockIndex(block, uint64(index))
if err != nil {
return nil, err
}
return NewStructuredResponse(tx)
default:
return nil, ErrUnknownRPCVersion
}
@ -435,7 +448,7 @@ func (s *PublicTransactionService) GetTransactionByBlockHashAndIndex(
// Format response according to version
switch s.version {
case V1, Eth:
case V1:
tx, err := v1.NewTransactionFromBlockIndex(block, uint64(index))
if err != nil {
return nil, err
@ -447,6 +460,12 @@ func (s *PublicTransactionService) GetTransactionByBlockHashAndIndex(
return nil, err
}
return NewStructuredResponse(tx)
case Eth:
tx, err := eth.NewTransactionFromBlockIndex(block, uint64(index))
if err != nil {
return nil, err
}
return NewStructuredResponse(tx)
default:
return nil, ErrUnknownRPCVersion
}
@ -526,7 +545,7 @@ func (s *PublicTransactionService) GetStakingTransactionByBlockNumberAndIndex(
// Format response according to version
switch s.version {
case V1, Eth:
case V1:
tx, err := v1.NewStakingTransactionFromBlockIndex(block, uint64(index))
if err != nil {
return nil, err
@ -608,7 +627,7 @@ func (s *PublicTransactionService) GetTransactionReceipt(
// Format response according to version
var RPCReceipt interface{}
switch s.version {
case V1, Eth:
case V1:
if tx == nil {
RPCReceipt, err = v1.NewReceipt(stx, blockHash, blockNumber, index, receipt)
} else {
@ -628,6 +647,16 @@ func (s *PublicTransactionService) GetTransactionReceipt(
return nil, err
}
return NewStructuredResponse(RPCReceipt)
case Eth:
if tx == nil {
RPCReceipt, err = eth.NewReceipt(stx, blockHash, blockNumber, index, receipt)
} else {
RPCReceipt, err = eth.NewReceipt(tx, blockHash, blockNumber, index, receipt)
}
if err != nil {
return nil, err
}
return NewStructuredResponse(RPCReceipt)
default:
return nil, ErrUnknownRPCVersion
}

@ -0,0 +1,37 @@
package utils
import (
"strings"
"github.com/ethereum/go-ethereum/common"
internal_common "github.com/harmony-one/harmony/internal/common"
)
// ConvertAddresses - converts to bech32 depending on the RPC version
func ConvertAddresses(from *common.Address, to *common.Address, convertToBech32 bool) (string, string, error) {
fromAddr := strings.ToLower(from.String())
toAddr := ""
if to != nil {
toAddr = strings.ToLower(to.String())
}
if convertToBech32 {
return base16toBech32(from, to)
}
return fromAddr, toAddr, nil
}
func base16toBech32(from *common.Address, to *common.Address) (fromAddr string, toAddr string, err error) {
if fromAddr, err = internal_common.AddressToBech32(*from); err != nil {
return "", "", err
}
if to != nil {
if toAddr, err = internal_common.AddressToBech32(*to); err != nil {
return "", "", err
}
}
return fromAddr, toAddr, nil
}
Loading…
Cancel
Save