mirror of
https://github.com/status-im/status-go.git
synced 2025-01-24 13:41:24 +00:00
a9eb5a7d2b
We need to be able to sign more than just transactions to make DApps work properly. This change separates signing requests from the transactions and make it more general to prepare to intoduce different types of signing requests. This change is designed to preserve status APIs, so it is backward-comparible with the current API bindings.
87 lines
2.8 KiB
Go
87 lines
2.8 KiB
Go
package transactions
|
|
|
|
import (
|
|
"context"
|
|
"math/big"
|
|
|
|
ethereum "github.com/ethereum/go-ethereum"
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
"github.com/ethereum/go-ethereum/rlp"
|
|
|
|
"github.com/status-im/status-go/geth/rpc"
|
|
)
|
|
|
|
// rpcWrapper wraps provides convenient interface for ethereum RPC APIs we need for sending transactions
|
|
type rpcWrapper struct {
|
|
rpcClient *rpc.Client
|
|
}
|
|
|
|
func newRPCWrapper(client *rpc.Client) *rpcWrapper {
|
|
return &rpcWrapper{rpcClient: client}
|
|
}
|
|
|
|
// PendingNonceAt returns the account nonce of the given account in the pending state.
|
|
// This is the nonce that should be used for the next transaction.
|
|
func (w *rpcWrapper) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) {
|
|
var result hexutil.Uint64
|
|
err := w.rpcClient.CallContext(ctx, &result, "eth_getTransactionCount", account, "pending")
|
|
return uint64(result), err
|
|
}
|
|
|
|
// SuggestGasPrice retrieves the currently suggested gas price to allow a timely
|
|
// execution of a transaction.
|
|
func (w *rpcWrapper) SuggestGasPrice(ctx context.Context) (*big.Int, error) {
|
|
var hex hexutil.Big
|
|
if err := w.rpcClient.CallContext(ctx, &hex, "eth_gasPrice"); err != nil {
|
|
return nil, err
|
|
}
|
|
return (*big.Int)(&hex), nil
|
|
}
|
|
|
|
// EstimateGas tries to estimate the gas needed to execute a specific transaction based on
|
|
// the current pending state of the backend blockchain. There is no guarantee that this is
|
|
// the true gas limit requirement as other transactions may be added or removed by miners,
|
|
// but it should provide a basis for setting a reasonable default.
|
|
func (w *rpcWrapper) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error) {
|
|
var hex hexutil.Uint64
|
|
err := w.rpcClient.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg))
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return uint64(hex), nil
|
|
}
|
|
|
|
// SendTransaction injects a signed transaction into the pending pool for execution.
|
|
//
|
|
// If the transaction was a contract creation use the TransactionReceipt method to get the
|
|
// contract address after the transaction has been mined.
|
|
func (w *rpcWrapper) SendTransaction(ctx context.Context, tx *types.Transaction) error {
|
|
data, err := rlp.EncodeToBytes(tx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return w.rpcClient.CallContext(ctx, nil, "eth_sendRawTransaction", common.ToHex(data))
|
|
}
|
|
|
|
func toCallArg(msg ethereum.CallMsg) interface{} {
|
|
arg := map[string]interface{}{
|
|
"from": msg.From,
|
|
"to": msg.To,
|
|
}
|
|
if len(msg.Data) > 0 {
|
|
arg["data"] = hexutil.Bytes(msg.Data)
|
|
}
|
|
if msg.Value != nil {
|
|
arg["value"] = (*hexutil.Big)(msg.Value)
|
|
}
|
|
if msg.Gas != 0 {
|
|
arg["gas"] = hexutil.Uint64(msg.Gas)
|
|
}
|
|
if msg.GasPrice != nil {
|
|
arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice)
|
|
}
|
|
return arg
|
|
}
|