2019-10-08 03:32:28 +00:00
|
|
|
package rpc
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
2020-04-02 00:43:59 +00:00
|
|
|
"math/big"
|
2019-10-08 03:32:28 +00:00
|
|
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/client/context"
|
|
|
|
"github.com/cosmos/ethermint/x/evm/types"
|
|
|
|
|
|
|
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
|
|
|
"github.com/ethereum/go-ethereum/eth/filters"
|
|
|
|
"github.com/ethereum/go-ethereum/rpc"
|
|
|
|
)
|
|
|
|
|
|
|
|
// PublicFilterAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec.
|
|
|
|
type PublicFilterAPI struct {
|
2020-04-02 00:43:59 +00:00
|
|
|
cliCtx context.CLIContext
|
|
|
|
backend Backend
|
|
|
|
filters map[rpc.ID]*Filter // ID to filter; TODO: change to sync.Map in case of concurrent writes
|
2019-10-08 03:32:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewPublicEthAPI creates an instance of the public ETH Web3 API.
|
2020-04-02 00:43:59 +00:00
|
|
|
func NewPublicFilterAPI(cliCtx context.CLIContext, backend Backend) *PublicFilterAPI {
|
2019-10-08 03:32:28 +00:00
|
|
|
return &PublicFilterAPI{
|
2020-04-02 00:43:59 +00:00
|
|
|
cliCtx: cliCtx,
|
|
|
|
backend: backend,
|
|
|
|
filters: make(map[rpc.ID]*Filter),
|
2019-10-08 03:32:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-02 00:43:59 +00:00
|
|
|
// NewFilter instantiates a new filter.
|
|
|
|
func (e *PublicFilterAPI) NewFilter(criteria filters.FilterCriteria) rpc.ID {
|
|
|
|
id := rpc.NewID()
|
|
|
|
e.filters[id] = NewFilter(e.backend, &criteria)
|
|
|
|
return id
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewBlockFilter instantiates a new block filter.
|
|
|
|
func (e *PublicFilterAPI) NewBlockFilter() rpc.ID {
|
|
|
|
id := rpc.NewID()
|
|
|
|
e.filters[id] = NewBlockFilter(e.backend)
|
|
|
|
return id
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewPendingTransactionFilter instantiates a new pending transaction filter.
|
|
|
|
func (e *PublicFilterAPI) NewPendingTransactionFilter() rpc.ID {
|
|
|
|
id := rpc.NewID()
|
|
|
|
e.filters[id] = NewPendingTransactionFilter(e.backend)
|
|
|
|
return id
|
|
|
|
}
|
|
|
|
|
|
|
|
// UninstallFilter uninstalls a filter with the given ID.
|
|
|
|
func (e *PublicFilterAPI) UninstallFilter(id rpc.ID) bool {
|
|
|
|
e.filters[id].uninstallFilter()
|
|
|
|
delete(e.filters, id)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetFilterChanges returns an array of changes since the last poll.
|
|
|
|
// If the filter is a log filter, it returns an array of Logs.
|
|
|
|
// If the filter is a block filter, it returns an array of block hashes.
|
|
|
|
// If the filter is a pending transaction filter, it returns an array of transaction hashes.
|
2020-04-07 20:00:06 +00:00
|
|
|
func (e *PublicFilterAPI) GetFilterChanges(id rpc.ID) (interface{}, error) {
|
2020-04-02 00:43:59 +00:00
|
|
|
return e.filters[id].getFilterChanges()
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetFilterLogs returns an array of all logs matching filter with given id.
|
|
|
|
func (e *PublicFilterAPI) GetFilterLogs(id rpc.ID) []*ethtypes.Log {
|
|
|
|
return e.filters[id].getFilterLogs()
|
|
|
|
}
|
|
|
|
|
2019-10-08 03:32:28 +00:00
|
|
|
// GetLogs returns logs matching the given argument that are stored within the state.
|
|
|
|
//
|
|
|
|
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs
|
|
|
|
func (e *PublicFilterAPI) GetLogs(criteria filters.FilterCriteria) ([]*ethtypes.Log, error) {
|
|
|
|
var filter *Filter
|
|
|
|
if criteria.BlockHash != nil {
|
|
|
|
/*
|
|
|
|
Still need to add blockhash in prepare function for log entry
|
|
|
|
*/
|
2020-04-02 00:43:59 +00:00
|
|
|
filter = NewFilterWithBlockHash(e.backend, &criteria)
|
2019-10-08 03:32:28 +00:00
|
|
|
results := e.getLogs()
|
|
|
|
logs := filterLogs(results, nil, nil, filter.addresses, filter.topics)
|
|
|
|
return logs, nil
|
|
|
|
}
|
2020-01-07 20:56:49 +00:00
|
|
|
// Convert the RPC block numbers into internal representations
|
|
|
|
begin := rpc.LatestBlockNumber.Int64()
|
|
|
|
if criteria.FromBlock != nil {
|
|
|
|
begin = criteria.FromBlock.Int64()
|
|
|
|
}
|
|
|
|
from := big.NewInt(begin)
|
|
|
|
end := rpc.LatestBlockNumber.Int64()
|
|
|
|
if criteria.ToBlock != nil {
|
|
|
|
end = criteria.ToBlock.Int64()
|
|
|
|
}
|
|
|
|
to := big.NewInt(end)
|
|
|
|
results := e.getLogs()
|
|
|
|
logs := filterLogs(results, from, to, criteria.Addresses, criteria.Topics)
|
|
|
|
|
|
|
|
return returnLogs(logs), nil
|
2019-10-08 03:32:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (e *PublicFilterAPI) getLogs() (results []*ethtypes.Log) {
|
|
|
|
l, _, err := e.cliCtx.QueryWithData(fmt.Sprintf("custom/%s/logs", types.ModuleName), nil)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("error from querier %e ", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := json.Unmarshal(l, &results); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return results
|
|
|
|
}
|
|
|
|
|
|
|
|
// returnLogs is a helper that will return an empty log array in case the given logs array is nil,
|
|
|
|
// otherwise the given logs array is returned.
|
|
|
|
func returnLogs(logs []*ethtypes.Log) []*ethtypes.Log {
|
|
|
|
if logs == nil {
|
|
|
|
return []*ethtypes.Log{}
|
|
|
|
}
|
|
|
|
return logs
|
2019-10-31 15:09:40 +00:00
|
|
|
}
|