github.com/status-im/status-go@v1.1.0/transactions/types.go (about)

     1  package transactions
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"errors"
     7  	"math/big"
     8  
     9  	ethereum "github.com/ethereum/go-ethereum"
    10  	"github.com/ethereum/go-ethereum/accounts/abi/bind"
    11  	"github.com/ethereum/go-ethereum/common"
    12  	"github.com/ethereum/go-ethereum/common/hexutil"
    13  
    14  	"github.com/status-im/status-go/eth-node/types"
    15  	wallet_common "github.com/status-im/status-go/services/wallet/common"
    16  )
    17  
    18  var (
    19  	// ErrInvalidSendTxArgs is returned when the structure of SendTxArgs is ambigious.
    20  	ErrInvalidSendTxArgs = errors.New("transaction arguments are invalid")
    21  	// ErrUnexpectedArgs is returned when args are of unexpected length.
    22  	ErrUnexpectedArgs = errors.New("unexpected args")
    23  	//ErrInvalidTxSender is returned when selected account is different than From field.
    24  	ErrInvalidTxSender = errors.New("transaction can only be send by its creator")
    25  	//ErrAccountDoesntExist is sent when provided sub-account is not stored in database.
    26  	ErrAccountDoesntExist = errors.New("account doesn't exist")
    27  )
    28  
    29  // PendingNonceProvider provides information about nonces.
    30  type PendingNonceProvider interface {
    31  	PendingNonceAt(ctx context.Context, account common.Address) (uint64, error)
    32  }
    33  
    34  // GasCalculator provides methods for estimating and pricing gas.
    35  type GasCalculator interface {
    36  	ethereum.GasEstimator
    37  	ethereum.GasPricer
    38  }
    39  
    40  // SendTxArgs represents the arguments to submit a new transaction into the transaction pool.
    41  // This struct is based on go-ethereum's type in internal/ethapi/api.go, but we have freedom
    42  // over the exact layout of this struct.
    43  type SendTxArgs struct {
    44  	From                 types.Address   `json:"from"`
    45  	To                   *types.Address  `json:"to"`
    46  	Gas                  *hexutil.Uint64 `json:"gas"`
    47  	GasPrice             *hexutil.Big    `json:"gasPrice"`
    48  	Value                *hexutil.Big    `json:"value"`
    49  	Nonce                *hexutil.Uint64 `json:"nonce"`
    50  	MaxFeePerGas         *hexutil.Big    `json:"maxFeePerGas"`
    51  	MaxPriorityFeePerGas *hexutil.Big    `json:"maxPriorityFeePerGas"`
    52  	// We keep both "input" and "data" for backward compatibility.
    53  	// "input" is a preferred field.
    54  	// see `vendor/github.com/ethereum/go-ethereum/internal/ethapi/api.go:1107`
    55  	Input types.HexBytes `json:"input"`
    56  	Data  types.HexBytes `json:"data"`
    57  
    58  	// additional data
    59  	MultiTransactionID wallet_common.MultiTransactionIDType
    60  	Symbol             string
    61  }
    62  
    63  // Valid checks whether this structure is filled in correctly.
    64  func (args SendTxArgs) Valid() bool {
    65  	// if at least one of the fields is empty, it is a valid struct
    66  	if isNilOrEmpty(args.Input) || isNilOrEmpty(args.Data) {
    67  		return true
    68  	}
    69  
    70  	// we only allow both fields to present if they have the same data
    71  	return bytes.Equal(args.Input, args.Data)
    72  }
    73  
    74  // IsDynamicFeeTx checks whether dynamic fee parameters are set for the tx
    75  func (args SendTxArgs) IsDynamicFeeTx() bool {
    76  	return args.MaxFeePerGas != nil && args.MaxPriorityFeePerGas != nil
    77  }
    78  
    79  // GetInput returns either Input or Data field's value dependent on what is filled.
    80  func (args SendTxArgs) GetInput() types.HexBytes {
    81  	if !isNilOrEmpty(args.Input) {
    82  		return args.Input
    83  	}
    84  
    85  	return args.Data
    86  }
    87  
    88  func (args SendTxArgs) ToTransactOpts(signerFn bind.SignerFn) *bind.TransactOpts {
    89  	var gasFeeCap *big.Int
    90  	if args.MaxFeePerGas != nil {
    91  		gasFeeCap = (*big.Int)(args.MaxFeePerGas)
    92  	}
    93  
    94  	var gasTipCap *big.Int
    95  	if args.MaxPriorityFeePerGas != nil {
    96  		gasTipCap = (*big.Int)(args.MaxPriorityFeePerGas)
    97  	}
    98  
    99  	var nonce *big.Int
   100  	if args.Nonce != nil {
   101  		nonce = new(big.Int).SetUint64((uint64)(*args.Nonce))
   102  	}
   103  
   104  	var gasPrice *big.Int
   105  	if args.GasPrice != nil {
   106  		gasPrice = (*big.Int)(args.GasPrice)
   107  	}
   108  
   109  	var gasLimit uint64
   110  	if args.Gas != nil {
   111  		gasLimit = uint64(*args.Gas)
   112  	}
   113  
   114  	var noSign = false
   115  	if signerFn == nil {
   116  		noSign = true
   117  	}
   118  
   119  	return &bind.TransactOpts{
   120  		From:      common.Address(args.From),
   121  		Signer:    signerFn,
   122  		GasPrice:  gasPrice,
   123  		GasLimit:  gasLimit,
   124  		GasFeeCap: gasFeeCap,
   125  		GasTipCap: gasTipCap,
   126  		Nonce:     nonce,
   127  		NoSign:    noSign,
   128  	}
   129  }
   130  
   131  func isNilOrEmpty(bytes types.HexBytes) bool {
   132  	return len(bytes) == 0
   133  }