Skip to content

Commit

Permalink
Add eth_getBalance, update eth_estimateGas
Browse files Browse the repository at this point in the history
  • Loading branch information
dcb9 committed Sep 28, 2018
1 parent dd59271 commit 063c4c5
Show file tree
Hide file tree
Showing 10 changed files with 225 additions and 13 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -691,10 +691,14 @@ curl --header 'Content-Type: application/json' --data \
- tags, "pending" and "earliest", are unsupported
- eth_accounts
- eth_getCode
- eth_newFilter
- eth_newBlockFilter
- eth_getFilterChanges
- only support filters created with `eth_newBlockFilter`
- eth_uninstallFilter
- eth_getFilterLogs
- eth_getBlockByNumber
- eth_estimateGas
- eth_getBalance

## Known issues

Expand Down
15 changes: 15 additions & 0 deletions pkg/eth/rpc_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,3 +417,18 @@ func (r *NewFilterRequest) UnmarshalJSON(data []byte) error {
}

type NewFilterResponse string

// ========== eth_getBalance ============= //

type GetBalanceRequest struct {
Address string
Block json.RawMessage
}

func (r *GetBalanceRequest) UnmarshalJSON(data []byte) error {
tmp := []interface{}{&r.Address, &r.Block}

return json.Unmarshal(data, &tmp)
}

type GetBalanceResponse string
1 change: 1 addition & 0 deletions pkg/qtum/jsonrpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const (
MethodGetAddressesByAccount = "getaddressesbyaccount"
MethodGetAccountInfo = "getaccountinfo"
MethodGenerate = "generate"
MethodListUnspent = "listunspent"
)

type JSONRPCRequest struct {
Expand Down
21 changes: 21 additions & 0 deletions pkg/qtum/method.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,24 @@ func (m *Method) SearchLogs(req *SearchLogsRequest) (receipts SearchLogsResponse
}
return
}

func (m *Method) CallContract(req *CallContractRequest) (resp *CallContractResponse, err error) {
if err := m.Request(MethodCallContract, req, &resp); err != nil {
return nil, err
}
return
}

func (m *Method) GetAccountInfo(req *GetAccountInfoRequest) (resp *GetAccountInfoResponse, err error) {
if err := m.Request(MethodGetAccountInfo, req, &resp); err != nil {
return nil, err
}
return
}

func (m *Method) ListUnspent(req *ListUnspentRequest) (resp *ListUnspentResponse, err error) {
if err := m.Request(MethodListUnspent, req, &resp); err != nil {
return nil, err
}
return
}
93 changes: 93 additions & 0 deletions pkg/qtum/rpc_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -868,3 +868,96 @@ func (r *GetBlockRequest) MarshalJSON() ([]byte, error) {
verbosity,
})
}

// ========== ListUnspent ============= //
type (

/*
Arguments:
1. minconf (numeric, optional, default=1) The minimum confirmations to filter
2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter
3. "addresses" (string) A json array of qtum addresses to filter
[
"address" (string) qtum address
,...
]
4. include_unsafe (bool, optional, default=true) Include outputs that are not safe to spend
See description of "safe" attribute below.
5. query_options (json, optional) JSON with query options
{
"minimumAmount" (numeric or string, default=0) Minimum value of each UTXO in QTUM
"maximumAmount" (numeric or string, default=unlimited) Maximum value of each UTXO in QTUM
"maximumCount" (numeric or string, default=unlimited) Maximum number of UTXOs
"minimumSumAmount" (numeric or string, default=unlimited) Minimum sum value of all UTXOs in QTUM
}
*/
ListUnspentRequest struct {
MinConf int
MaxConf int
Addresses []string
}

/*
[ (array of json object)
{
"txid" : "txid", (string) the transaction id
"vout" : n, (numeric) the vout value
"address" : "address", (string) the qtum address
"account" : "account", (string) DEPRECATED. The associated account, or "" for the default account
"scriptPubKey" : "key", (string) the script key
"amount" : x.xxx, (numeric) the transaction output amount in QTUM
"confirmations" : n, (numeric) The number of confirmations
"redeemScript" : n (string) The redeemScript if scriptPubKey is P2SH
"spendable" : xxx, (bool) Whether we have the private keys to spend this output
"solvable" : xxx, (bool) Whether we know how to spend this output, ignoring the lack of keys
"safe" : xxx (bool) Whether this output is considered safe to spend. Unconfirmed transactions
from outside keys and unconfirmed replacement transactions are considered unsafe
and are not eligible for spending by fundrawtransaction and sendtoaddress.
}
,...
]
[
{
"txid": "a8d97ae8bb819cd4aa98ed2ddaef4969783aee845461a9ea5a88184ad58f44fe",
"vout": 2,
"address": "qUbxboqjBRp96j3La8D1RYkyqx5uQbJPoW",
"account": "",
"scriptPubKey": "210299d391f528b9edd07284c7e23df8415232a8ce41531cf460a390ce32b4efd112ac",
"amount": 15007.10682200,
"confirmations": 532,
"spendable": true,
"solvable": true,
"safe": true
}
]
*/
ListUnspentResponse []struct {
Txid string `json:"txid"`
Vout int `json:"vout"`
Address string `json:"address"`
Account string `json:"account"`
ScriptPubKey string `json:"scriptPubKey"`
Amount float64 `json:"amount"`
Confirmations int `json:"confirmations"`
Spendable bool `json:"spendable"`
Solvable bool `json:"solvable"`
Safe bool `json:"safe"`
}
)

func NewListUnspentRequest(addresses ...string) *ListUnspentRequest {
return &ListUnspentRequest{
MinConf: 1,
MaxConf: 99999999,
Addresses: addresses,
}
}

func (r *ListUnspentRequest) MarshalJSON() ([]byte, error) {
return json.Marshal([]interface{}{
r.MinConf,
r.MaxConf,
r.Addresses,
})
}
6 changes: 3 additions & 3 deletions pkg/transformer/eth_call.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ func (p *ProxyETHCall) Request(rawreq *eth.JSONRPCRequest) (interface{}, error)

func (p *ProxyETHCall) request(ethreq *eth.CallRequest) (*eth.CallResponse, error) {
// eth req -> qtum req
params, err := p.ToRequest(ethreq)
qtumreq, err := p.ToRequest(ethreq)
if err != nil {
return nil, err
}

var qtumresp *qtum.CallContractResponse
if err = p.Qtum.Request(qtum.MethodCallContract, params, &qtumresp); err != nil {
qtumresp, err := p.CallContract(qtumreq)
if err != nil {
return nil, err
}

Expand Down
25 changes: 21 additions & 4 deletions pkg/transformer/eth_estimateGas.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,39 @@ package transformer
import (
"github.com/dcb9/janus/pkg/eth"
"github.com/dcb9/janus/pkg/qtum"
"github.com/ethereum/go-ethereum/common/hexutil"
)

// ProxyETHEstimateGas implements ETHProxy
type ProxyETHEstimateGas struct {
*qtum.Qtum
*ProxyETHCall
}

func (p *ProxyETHEstimateGas) Method() string {
return "eth_estimateGas"
}

func (p *ProxyETHEstimateGas) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) {
return p.request()
var ethreq eth.CallRequest
if err := unmarshalRequest(rawreq.Params, &ethreq); err != nil {
return nil, err
}

// eth req -> qtum req
qtumreq, err := p.ToRequest(&ethreq)
if err != nil {
return nil, err
}

qtumresp, err := p.CallContract(qtumreq)
if err != nil {
return nil, err
}

return p.toResp(qtumresp)
}

func (p *ProxyETHEstimateGas) request() (*eth.EstimateGasResponse, error) {
gas := eth.EstimateGasResponse("0x500000")
func (p *ProxyETHEstimateGas) toResp(qtumresp *qtum.CallContractResponse) (*eth.EstimateGasResponse, error) {
gas := eth.EstimateGasResponse(hexutil.EncodeUint64(uint64(qtumresp.ExecutionResult.GasUsed)))
return &gas, nil
}
59 changes: 59 additions & 0 deletions pkg/transformer/eth_getBalance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package transformer

import (
"github.com/dcb9/janus/pkg/eth"
"github.com/dcb9/janus/pkg/qtum"
"github.com/dcb9/janus/pkg/utils"
"github.com/ethereum/go-ethereum/common/hexutil"
)

// ProxyETHGetBalance implements ETHProxy
type ProxyETHGetBalance struct {
*qtum.Qtum
}

func (p *ProxyETHGetBalance) Method() string {
return "eth_getBalance"
}

func (p *ProxyETHGetBalance) Request(rawreq *eth.JSONRPCRequest) (interface{}, error) {
var req eth.GetBalanceRequest
if err := unmarshalRequest(rawreq.Params, &req); err != nil {
return nil, err
}

addr := utils.RemoveHexPrefix(req.Address)
{
// is address a contract or an account?
qtumreq := qtum.GetAccountInfoRequest(addr)
qtumresp, err := p.GetAccountInfo(&qtumreq)

// the address is a contract
if err == nil {
// the unit of the balance Satoshi
return hexutil.EncodeUint64(uint64(qtumresp.Balance)), nil
}
}

{
// try account
base58Addr, err := p.FromHexAddress(addr)
if err != nil {
return nil, err
}

qtumreq := qtum.NewListUnspentRequest(base58Addr)
qtumresp, err := p.ListUnspent(qtumreq)
if err != nil {
return nil, err
}

balance := float64(0)
for _, utxo := range *qtumresp {
balance += utxo.Amount
}

// 1 QTUM = 10 ^ 8 Satoshi
return hexutil.EncodeUint64(uint64(balance * 10e8)), nil
}
}
6 changes: 3 additions & 3 deletions pkg/transformer/eth_getCode.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ func (p *ProxyETHGetCode) Request(rawreq *eth.JSONRPCRequest) (interface{}, erro
func (p *ProxyETHGetCode) request(ethreq *eth.GetCodeRequest) (eth.GetCodeResponse, error) {
qtumreq := qtum.GetAccountInfoRequest(utils.RemoveHexPrefix(ethreq.Address))

var qtumresp qtum.GetAccountInfoResponse
if err := p.Qtum.Request(qtum.MethodGetAccountInfo, &qtumreq, &qtumresp); err != nil {
return "", nil
qtumresp, err := p.GetAccountInfo(&qtumreq)
if err != nil {
return "", err
}

// qtum res -> eth res
Expand Down
6 changes: 4 additions & 2 deletions pkg/transformer/transformer.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,10 @@ func (t *Transformer) getProxy(rpcReq *eth.JSONRPCRequest) (ETHProxy, error) {
func DefaultProxies(qtumRPCClient *qtum.Qtum) []ETHProxy {
filter := eth.NewFilterSimulator()
getFilterChanges := &ProxyETHGetFilterChanges{Qtum: qtumRPCClient, filter: filter}
ethCall := &ProxyETHCall{Qtum: qtumRPCClient}

return []ETHProxy{
&ProxyETHCall{Qtum: qtumRPCClient},
ethCall,
&ProxyETHPersonalUnlockAccount{},
&ProxyETHBlockNumber{Qtum: qtumRPCClient},
&ProxyETHNetVersion{Qtum: qtumRPCClient},
Expand All @@ -95,8 +96,9 @@ func DefaultProxies(qtumRPCClient *qtum.Qtum) []ETHProxy {
&ProxyETHGetFilterLogs{ProxyETHGetFilterChanges: getFilterChanges},
&ProxyETHUninstallFilter{Qtum: qtumRPCClient, filter: filter},

&ProxyETHEstimateGas{Qtum: qtumRPCClient},
&ProxyETHEstimateGas{ProxyETHCall: ethCall},
&ProxyETHGetBlockByNumber{Qtum: qtumRPCClient},
&ProxyETHGetBalance{Qtum: qtumRPCClient},
}
}

Expand Down

0 comments on commit 063c4c5

Please sign in to comment.