aboutsummaryrefslogblamecommitdiffstats
path: root/rpc/api/eth.go
blob: a78e492ff5ffccf3912cbe5931e2ded7781dfcca (plain) (tree)
1
2
3
4
5
6
7
8
9
                                         
                                                
  
                                                                                  



                                                                              
                                                                             
                                                                 
                                                               


                                                                           
                                                                                  
 






                       

             
                                                
                                                        
                                             
                                             


                                                    
                               

 



                             

                                                     
                    



                                      


                       
                                                                   


                                           





                                                                                     
                                                                               










                                                                                                      
                                                                                
                                                                          

                                                                                       
                                                                                     
                                                                                     






















                                                                                                         
                                                                                    
                                                                            
                                                                                         
                                                                                           


         
                             

                                                                               


                                    
                                        









                                                    
                                                                       






                                                             
                                   
                                

 



                                         
                                                                        


                                        
                                                                        


                                                   
                                                                           

                                                

 
                                                                          







                                                                                  
                                                                               


                                          
                                                                        


                                                    
                                                                        


                                        
                                                                         
                                                                        

                                              


                                                                                       




                         
                                                                        
                                                                  

 
                                                                          







                                                                                                  
                                                                            







                                                                                            
                                                                                   





                                                                               
                                             

 
                                                                                              



                                                                    
                                                    

                               
         
                                                                 

 
                                                                                                




                                                                    
                                                             

                               
         
                                                                 

 
                                                                                        




                                                                    
                                                    
                         

                               
                                                           

 
                                                                                          




                                                                    
                                                             
                         

                               
                                                           

 
                                                                       







                                                                             

                                                                    









                                                                    
                                                                                 
                                



                                                                    
                                             





                               






































                                                                                                                   
                                                                               










                                                                    







                                                                                                           





                               











                                                                                             
                                                                           








                                                     
                                                             


         
                                                                    












                                                         
                                                                     


                                                             
                                                                            







                                                                                                                                                         
                                                                              



                                                                    
                                                         


                               
                                                                                   

 
                                                                                





                                                                   


                               
                                                                                   

 
                                                                                    


















                                                                                   
                                                                                                 




                                                                    
                                                  
                       

                               
                                                                 
                                                                           

                               
                                                          


         
                                                                                                   




                                                                    
                                                           
                       

                               
                                                                 
                                                                           


                                                                       
                                                  

 
                                                                                           




                                                                    
                                                  
                       

                               
                                                                  
                                                                     


                                                                       
                                            

 
                                                                                             




                                                                    
                                                           
                       

                               
                                                                 
                                                                     

                               
                                                    


         
                                                                            







                                                     
                                                                               
















                                                                                                         
                                                                         








                                                                                                                
                                                                              


                                                         
                                                                                           


                                                               
                                                                               






                                                                    
                                                                                
















                                                                                     
                                                                             







                                                                    
                                                                       






                                                                                                                             
                                                                       
                                    

                                                      
                                                                  


                               

 
                                                                          





                                                                                                                                 
 


                                                                              
                                                                     

                                                                                     
                        

 





                                                                      
                                                 
 

                                                           
                                                                                                                       



                                                                                                                                                     
 
                                                                        

 


                                                                                   
                                                                                            













                                                                  
                                                                       





                                                      






                                                                                     
                                                               
                                                                         
                                             



                                                                     
                                    
                                       

                                               
                                                   




                             
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package api

import (
    "bytes"
    "encoding/json"
    "math/big"

    "fmt"

    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/common/natspec"
    "github.com/ethereum/go-ethereum/eth"
    "github.com/ethereum/go-ethereum/rlp"
    "github.com/ethereum/go-ethereum/rpc/codec"
    "github.com/ethereum/go-ethereum/rpc/shared"
    "github.com/ethereum/go-ethereum/xeth"
    "gopkg.in/fatih/set.v0"
)

const (
    EthApiVersion = "1.0"
)

// eth api provider
// See https://github.com/ethereum/wiki/wiki/JSON-RPC
type ethApi struct {
    xeth     *xeth.XEth
    ethereum *eth.Ethereum
    methods  map[string]ethhandler
    codec    codec.ApiCoder
}

// eth callback handler
type ethhandler func(*ethApi, *shared.Request) (interface{}, error)

var (
    ethMapping = map[string]ethhandler{
        "eth_accounts":                            (*ethApi).Accounts,
        "eth_blockNumber":                         (*ethApi).BlockNumber,
        "eth_getBalance":                          (*ethApi).GetBalance,
        "eth_protocolVersion":                     (*ethApi).ProtocolVersion,
        "eth_coinbase":                            (*ethApi).Coinbase,
        "eth_mining":                              (*ethApi).IsMining,
        "eth_syncing":                             (*ethApi).IsSyncing,
        "eth_gasPrice":                            (*ethApi).GasPrice,
        "eth_getStorage":                          (*ethApi).GetStorage,
        "eth_storageAt":                           (*ethApi).GetStorage,
        "eth_getStorageAt":                        (*ethApi).GetStorageAt,
        "eth_getTransactionCount":                 (*ethApi).GetTransactionCount,
        "eth_getBlockTransactionCountByHash":      (*ethApi).GetBlockTransactionCountByHash,
        "eth_getBlockTransactionCountByNumber":    (*ethApi).GetBlockTransactionCountByNumber,
        "eth_getUncleCountByBlockHash":            (*ethApi).GetUncleCountByBlockHash,
        "eth_getUncleCountByBlockNumber":          (*ethApi).GetUncleCountByBlockNumber,
        "eth_getData":                             (*ethApi).GetData,
        "eth_getCode":                             (*ethApi).GetData,
        "eth_getNatSpec":                          (*ethApi).GetNatSpec,
        "eth_sign":                                (*ethApi).Sign,
        "eth_sendRawTransaction":                  (*ethApi).SubmitTransaction,
        "eth_submitTransaction":                   (*ethApi).SubmitTransaction,
        "eth_sendTransaction":                     (*ethApi).SendTransaction,
        "eth_signTransaction":                     (*ethApi).SignTransaction,
        "eth_transact":                            (*ethApi).SendTransaction,
        "eth_estimateGas":                         (*ethApi).EstimateGas,
        "eth_call":                                (*ethApi).Call,
        "eth_flush":                               (*ethApi).Flush,
        "eth_getBlockByHash":                      (*ethApi).GetBlockByHash,
        "eth_getBlockByNumber":                    (*ethApi).GetBlockByNumber,
        "eth_getTransactionByHash":                (*ethApi).GetTransactionByHash,
        "eth_getTransactionByBlockNumberAndIndex": (*ethApi).GetTransactionByBlockNumberAndIndex,
        "eth_getTransactionByBlockHashAndIndex":   (*ethApi).GetTransactionByBlockHashAndIndex,
        "eth_getUncleByBlockHashAndIndex":         (*ethApi).GetUncleByBlockHashAndIndex,
        "eth_getUncleByBlockNumberAndIndex":       (*ethApi).GetUncleByBlockNumberAndIndex,
        "eth_getCompilers":                        (*ethApi).GetCompilers,
        "eth_compileSolidity":                     (*ethApi).CompileSolidity,
        "eth_newFilter":                           (*ethApi).NewFilter,
        "eth_newBlockFilter":                      (*ethApi).NewBlockFilter,
        "eth_newPendingTransactionFilter":         (*ethApi).NewPendingTransactionFilter,
        "eth_uninstallFilter":                     (*ethApi).UninstallFilter,
        "eth_getFilterChanges":                    (*ethApi).GetFilterChanges,
        "eth_getFilterLogs":                       (*ethApi).GetFilterLogs,
        "eth_getLogs":                             (*ethApi).GetLogs,
        "eth_hashrate":                            (*ethApi).Hashrate,
        "eth_getWork":                             (*ethApi).GetWork,
        "eth_submitWork":                          (*ethApi).SubmitWork,
        "eth_submitHashrate":                      (*ethApi).SubmitHashrate,
        "eth_resend":                              (*ethApi).Resend,
        "eth_pendingTransactions":                 (*ethApi).PendingTransactions,
        "eth_getTransactionReceipt":               (*ethApi).GetTransactionReceipt,
    }
)

// create new ethApi instance
func NewEthApi(xeth *xeth.XEth, eth *eth.Ethereum, codec codec.Codec) *ethApi {
    return &ethApi{xeth, eth, ethMapping, codec.New(nil)}
}

// collection with supported methods
func (self *ethApi) Methods() []string {
    methods := make([]string, len(self.methods))
    i := 0
    for k := range self.methods {
        methods[i] = k
        i++
    }
    return methods
}

// Execute given request
func (self *ethApi) Execute(req *shared.Request) (interface{}, error) {
    if callback, ok := self.methods[req.Method]; ok {
        return callback(self, req)
    }

    return nil, shared.NewNotImplementedError(req.Method)
}

func (self *ethApi) Name() string {
    return shared.EthApiName
}

func (self *ethApi) ApiVersion() string {
    return EthApiVersion
}

func (self *ethApi) Accounts(req *shared.Request) (interface{}, error) {
    return self.xeth.Accounts(), nil
}

func (self *ethApi) Hashrate(req *shared.Request) (interface{}, error) {
    return newHexNum(self.xeth.HashRate()), nil
}

func (self *ethApi) BlockNumber(req *shared.Request) (interface{}, error) {
    num := self.xeth.CurrentBlock().Number()
    return newHexNum(num.Bytes()), nil
}

func (self *ethApi) GetBalance(req *shared.Request) (interface{}, error) {
    args := new(GetBalanceArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    return self.xeth.AtStateNum(args.BlockNumber).BalanceAt(args.Address), nil
}

func (self *ethApi) ProtocolVersion(req *shared.Request) (interface{}, error) {
    return self.xeth.EthVersion(), nil
}

func (self *ethApi) Coinbase(req *shared.Request) (interface{}, error) {
    return newHexData(self.xeth.Coinbase()), nil
}

func (self *ethApi) IsMining(req *shared.Request) (interface{}, error) {
    return self.xeth.IsMining(), nil
}

func (self *ethApi) IsSyncing(req *shared.Request) (interface{}, error) {
    origin, current, height := self.ethereum.Downloader().Progress()
    if current < height {
        return map[string]interface{}{
            "startingBlock": newHexNum(big.NewInt(int64(origin)).Bytes()),
            "currentBlock":  newHexNum(big.NewInt(int64(current)).Bytes()),
            "highestBlock":  newHexNum(big.NewInt(int64(height)).Bytes()),
        }, nil
    }
    return false, nil
}

func (self *ethApi) GasPrice(req *shared.Request) (interface{}, error) {
    return newHexNum(self.xeth.DefaultGasPrice().Bytes()), nil
}

func (self *ethApi) GetStorage(req *shared.Request) (interface{}, error) {
    args := new(GetStorageArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    return self.xeth.AtStateNum(args.BlockNumber).State().SafeGet(args.Address).Storage(), nil
}

func (self *ethApi) GetStorageAt(req *shared.Request) (interface{}, error) {
    args := new(GetStorageAtArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    return self.xeth.AtStateNum(args.BlockNumber).StorageAt(args.Address, args.Key), nil
}

func (self *ethApi) GetTransactionCount(req *shared.Request) (interface{}, error) {
    args := new(GetTxCountArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    count := self.xeth.AtStateNum(args.BlockNumber).TxCountAt(args.Address)
    return fmt.Sprintf("%#x", count), nil
}

func (self *ethApi) GetBlockTransactionCountByHash(req *shared.Request) (interface{}, error) {
    args := new(HashArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }
    block := self.xeth.EthBlockByHash(args.Hash)
    if block == nil {
        return nil, nil
    }
    return fmt.Sprintf("%#x", len(block.Transactions())), nil
}

func (self *ethApi) GetBlockTransactionCountByNumber(req *shared.Request) (interface{}, error) {
    args := new(BlockNumArg)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    block := self.xeth.EthBlockByNumber(args.BlockNumber)
    if block == nil {
        return nil, nil
    }
    return fmt.Sprintf("%#x", len(block.Transactions())), nil
}

func (self *ethApi) GetUncleCountByBlockHash(req *shared.Request) (interface{}, error) {
    args := new(HashArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    block := self.xeth.EthBlockByHash(args.Hash)
    if block == nil {
        return nil, nil
    }
    return fmt.Sprintf("%#x", len(block.Uncles())), nil
}

func (self *ethApi) GetUncleCountByBlockNumber(req *shared.Request) (interface{}, error) {
    args := new(BlockNumArg)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    block := self.xeth.EthBlockByNumber(args.BlockNumber)
    if block == nil {
        return nil, nil
    }
    return fmt.Sprintf("%#x", len(block.Uncles())), nil
}

func (self *ethApi) GetData(req *shared.Request) (interface{}, error) {
    args := new(GetDataArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }
    v := self.xeth.AtStateNum(args.BlockNumber).CodeAtBytes(args.Address)
    return newHexData(v), nil
}

func (self *ethApi) Sign(req *shared.Request) (interface{}, error) {
    args := new(NewSigArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }
    v, err := self.xeth.Sign(args.From, args.Data, false)
    if err != nil {
        return nil, err
    }
    return v, nil
}

func (self *ethApi) SubmitTransaction(req *shared.Request) (interface{}, error) {
    args := new(NewDataArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    v, err := self.xeth.PushTx(args.Data)
    if err != nil {
        return nil, err
    }
    return v, nil
}

// JsonTransaction is returned as response by the JSON RPC. It contains the
// signed RLP encoded transaction as Raw and the signed transaction object as Tx.
type JsonTransaction struct {
    Raw string `json:"raw"`
    Tx  *tx    `json:"tx"`
}

func (self *ethApi) SignTransaction(req *shared.Request) (interface{}, error) {
    args := new(NewTxArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    // nonce may be nil ("guess" mode)
    var nonce string
    if args.Nonce != nil {
        nonce = args.Nonce.String()
    }

    var gas, price string
    if args.Gas != nil {
        gas = args.Gas.String()
    }
    if args.GasPrice != nil {
        price = args.GasPrice.String()
    }
    tx, err := self.xeth.SignTransaction(args.From, args.To, nonce, args.Value.String(), gas, price, args.Data)
    if err != nil {
        return nil, err
    }

    data, err := rlp.EncodeToBytes(tx)
    if err != nil {
        return nil, err
    }

    return JsonTransaction{"0x" + common.Bytes2Hex(data), newTx(tx)}, nil
}

func (self *ethApi) SendTransaction(req *shared.Request) (interface{}, error) {
    args := new(NewTxArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    // nonce may be nil ("guess" mode)
    var nonce string
    if args.Nonce != nil {
        nonce = args.Nonce.String()
    }

    var gas, price string
    if args.Gas != nil {
        gas = args.Gas.String()
    }
    if args.GasPrice != nil {
        price = args.GasPrice.String()
    }
    v, err := self.xeth.Transact(args.From, args.To, nonce, args.Value.String(), gas, price, args.Data)
    if err != nil {
        return nil, err
    }
    return v, nil
}

func (self *ethApi) GetNatSpec(req *shared.Request) (interface{}, error) {
    args := new(NewTxArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    var jsontx = fmt.Sprintf(`{"params":[{"to":"%s","data": "%s"}]}`, args.To, args.Data)
    notice := natspec.GetNotice(self.xeth, jsontx, self.ethereum.HTTPClient())

    return notice, nil
}

func (self *ethApi) EstimateGas(req *shared.Request) (interface{}, error) {
    _, gas, err := self.doCall(req.Params)
    if err != nil {
        return nil, err
    }

    // TODO unwrap the parent method's ToHex call
    if len(gas) == 0 {
        return newHexNum(0), nil
    } else {
        return newHexNum(common.String2Big(gas)), err
    }
}

func (self *ethApi) Call(req *shared.Request) (interface{}, error) {
    v, _, err := self.doCall(req.Params)
    if err != nil {
        return nil, err
    }

    // TODO unwrap the parent method's ToHex call
    if v == "0x0" {
        return newHexData([]byte{}), nil
    } else {
        return newHexData(common.FromHex(v)), nil
    }
}

func (self *ethApi) Flush(req *shared.Request) (interface{}, error) {
    return nil, shared.NewNotImplementedError(req.Method)
}

func (self *ethApi) doCall(params json.RawMessage) (string, string, error) {
    args := new(CallArgs)
    if err := self.codec.Decode(params, &args); err != nil {
        return "", "", err
    }

    return self.xeth.AtStateNum(args.BlockNumber).Call(args.From, args.To, args.Value.String(), args.Gas.String(), args.GasPrice.String(), args.Data)
}

func (self *ethApi) GetBlockByHash(req *shared.Request) (interface{}, error) {
    args := new(GetBlockByHashArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }
    block := self.xeth.EthBlockByHash(args.BlockHash)
    if block == nil {
        return nil, nil
    }
    return NewBlockRes(block, self.xeth.Td(block.Hash()), args.IncludeTxs), nil
}

func (self *ethApi) GetBlockByNumber(req *shared.Request) (interface{}, error) {
    args := new(GetBlockByNumberArgs)
    if err := json.Unmarshal(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    block := self.xeth.EthBlockByNumber(args.BlockNumber)
    if block == nil {
        return nil, nil
    }
    return NewBlockRes(block, self.xeth.Td(block.Hash()), args.IncludeTxs), nil
}

func (self *ethApi) GetTransactionByHash(req *shared.Request) (interface{}, error) {
    args := new(HashArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    tx, bhash, bnum, txi := self.xeth.EthTransactionByHash(args.Hash)
    if tx != nil {
        v := NewTransactionRes(tx)
        // if the blockhash is 0, assume this is a pending transaction
        if bytes.Compare(bhash.Bytes(), bytes.Repeat([]byte{0}, 32)) != 0 {
            v.BlockHash = newHexData(bhash)
            v.BlockNumber = newHexNum(bnum)
            v.TxIndex = newHexNum(txi)
        }
        return v, nil
    }
    return nil, nil
}

func (self *ethApi) GetTransactionByBlockHashAndIndex(req *shared.Request) (interface{}, error) {
    args := new(HashIndexArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    raw := self.xeth.EthBlockByHash(args.Hash)
    if raw == nil {
        return nil, nil
    }
    block := NewBlockRes(raw, self.xeth.Td(raw.Hash()), true)
    if args.Index >= int64(len(block.Transactions)) || args.Index < 0 {
        return nil, nil
    } else {
        return block.Transactions[args.Index], nil
    }
}

func (self *ethApi) GetTransactionByBlockNumberAndIndex(req *shared.Request) (interface{}, error) {
    args := new(BlockNumIndexArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    raw := self.xeth.EthBlockByNumber(args.BlockNumber)
    if raw == nil {
        return nil, nil
    }
    block := NewBlockRes(raw, self.xeth.Td(raw.Hash()), true)
    if args.Index >= int64(len(block.Transactions)) || args.Index < 0 {
        // return NewValidationError("Index", "does not exist")
        return nil, nil
    }
    return block.Transactions[args.Index], nil
}

func (self *ethApi) GetUncleByBlockHashAndIndex(req *shared.Request) (interface{}, error) {
    args := new(HashIndexArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    raw := self.xeth.EthBlockByHash(args.Hash)
    if raw == nil {
        return nil, nil
    }
    block := NewBlockRes(raw, self.xeth.Td(raw.Hash()), false)
    if args.Index >= int64(len(block.Uncles)) || args.Index < 0 {
        // return NewValidationError("Index", "does not exist")
        return nil, nil
    }
    return block.Uncles[args.Index], nil
}

func (self *ethApi) GetUncleByBlockNumberAndIndex(req *shared.Request) (interface{}, error) {
    args := new(BlockNumIndexArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    raw := self.xeth.EthBlockByNumber(args.BlockNumber)
    if raw == nil {
        return nil, nil
    }
    block := NewBlockRes(raw, self.xeth.Td(raw.Hash()), true)
    if args.Index >= int64(len(block.Uncles)) || args.Index < 0 {
        return nil, nil
    } else {
        return block.Uncles[args.Index], nil
    }
}

func (self *ethApi) GetCompilers(req *shared.Request) (interface{}, error) {
    var lang string
    if solc, _ := self.xeth.Solc(); solc != nil {
        lang = "Solidity"
    }
    c := []string{lang}
    return c, nil
}

func (self *ethApi) CompileSolidity(req *shared.Request) (interface{}, error) {
    solc, _ := self.xeth.Solc()
    if solc == nil {
        return nil, shared.NewNotAvailableError(req.Method, "solc (solidity compiler) not found")
    }

    args := new(SourceArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    contracts, err := solc.Compile(args.Source)
    if err != nil {
        return nil, err
    }
    return contracts, nil
}

func (self *ethApi) NewFilter(req *shared.Request) (interface{}, error) {
    args := new(BlockFilterArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    id := self.xeth.NewLogFilter(args.Earliest, args.Latest, args.Skip, args.Max, args.Address, args.Topics)
    return newHexNum(big.NewInt(int64(id)).Bytes()), nil
}

func (self *ethApi) NewBlockFilter(req *shared.Request) (interface{}, error) {
    return newHexNum(self.xeth.NewBlockFilter()), nil
}

func (self *ethApi) NewPendingTransactionFilter(req *shared.Request) (interface{}, error) {
    return newHexNum(self.xeth.NewTransactionFilter()), nil
}

func (self *ethApi) UninstallFilter(req *shared.Request) (interface{}, error) {
    args := new(FilterIdArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }
    return self.xeth.UninstallFilter(args.Id), nil
}

func (self *ethApi) GetFilterChanges(req *shared.Request) (interface{}, error) {
    args := new(FilterIdArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    switch self.xeth.GetFilterType(args.Id) {
    case xeth.BlockFilterTy:
        return NewHashesRes(self.xeth.BlockFilterChanged(args.Id)), nil
    case xeth.TransactionFilterTy:
        return NewHashesRes(self.xeth.TransactionFilterChanged(args.Id)), nil
    case xeth.LogFilterTy:
        return NewLogsRes(self.xeth.LogFilterChanged(args.Id)), nil
    default:
        return []string{}, nil // reply empty string slice
    }
}

func (self *ethApi) GetFilterLogs(req *shared.Request) (interface{}, error) {
    args := new(FilterIdArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    return NewLogsRes(self.xeth.Logs(args.Id)), nil
}

func (self *ethApi) GetLogs(req *shared.Request) (interface{}, error) {
    args := new(BlockFilterArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }
    return NewLogsRes(self.xeth.AllLogs(args.Earliest, args.Latest, args.Skip, args.Max, args.Address, args.Topics)), nil
}

func (self *ethApi) GetWork(req *shared.Request) (interface{}, error) {
    self.xeth.SetMining(true, 0)
    ret, err := self.xeth.RemoteMining().GetWork()
    if err != nil {
        return nil, shared.NewNotReadyError("mining work")
    } else {
        return ret, nil
    }
}

func (self *ethApi) SubmitWork(req *shared.Request) (interface{}, error) {
    args := new(SubmitWorkArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }
    return self.xeth.RemoteMining().SubmitWork(args.Nonce, common.HexToHash(args.Digest), common.HexToHash(args.Header)), nil
}

func (self *ethApi) SubmitHashrate(req *shared.Request) (interface{}, error) {
    args := new(SubmitHashRateArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return false, shared.NewDecodeParamError(err.Error())
    }
    self.xeth.RemoteMining().SubmitHashrate(common.HexToHash(args.Id), args.Rate)
    return true, nil
}

func (self *ethApi) Resend(req *shared.Request) (interface{}, error) {
    args := new(ResendArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    from := common.HexToAddress(args.Tx.From)

    pending := self.ethereum.TxPool().GetTransactions()
    for _, p := range pending {
        if pFrom, err := p.FromFrontier(); err == nil && pFrom == from && p.SigHash() == args.Tx.tx.SigHash() {
            self.ethereum.TxPool().RemoveTx(common.HexToHash(args.Tx.Hash))
            return self.xeth.Transact(args.Tx.From, args.Tx.To, args.Tx.Nonce, args.Tx.Value, args.GasLimit, args.GasPrice, args.Tx.Data)
        }
    }

    return nil, fmt.Errorf("Transaction %s not found", args.Tx.Hash)
}

func (self *ethApi) PendingTransactions(req *shared.Request) (interface{}, error) {
    txs := self.ethereum.TxPool().GetTransactions()

    // grab the accounts from the account manager. This will help with determining which
    // transactions should be returned.
    accounts, err := self.ethereum.AccountManager().Accounts()
    if err != nil {
        return nil, err
    }

    // Add the accouns to a new set
    accountSet := set.New()
    for _, account := range accounts {
        accountSet.Add(account.Address)
    }

    var ltxs []*tx
    for _, tx := range txs {
        if from, _ := tx.FromFrontier(); accountSet.Has(from) {
            ltxs = append(ltxs, newTx(tx))
        }
    }

    return ltxs, nil
}

func (self *ethApi) GetTransactionReceipt(req *shared.Request) (interface{}, error) {
    args := new(HashArgs)
    if err := self.codec.Decode(req.Params, &args); err != nil {
        return nil, shared.NewDecodeParamError(err.Error())
    }

    txhash := common.BytesToHash(common.FromHex(args.Hash))
    tx, bhash, bnum, txi := self.xeth.EthTransactionByHash(args.Hash)
    rec := self.xeth.GetTxReceipt(txhash)
    // We could have an error of "not found". Should disambiguate
    // if err != nil {
    //  return err, nil
    // }
    if rec != nil && tx != nil {
        v := NewReceiptRes(rec)
        v.BlockHash = newHexData(bhash)
        v.BlockNumber = newHexNum(bnum)
        v.TransactionIndex = newHexNum(txi)
        return v, nil
    }

    return nil, nil
}