github.com/lmittmann/w3@v0.20.0/w3types/message.go (about)

     1  package w3types
     2  
     3  import (
     4  	"encoding/json"
     5  	"math/big"
     6  
     7  	"github.com/ethereum/go-ethereum"
     8  	"github.com/ethereum/go-ethereum/common"
     9  	"github.com/ethereum/go-ethereum/common/hexutil"
    10  	"github.com/ethereum/go-ethereum/core/types"
    11  )
    12  
    13  // Message represents a transaction without the signature.
    14  //
    15  // If no input data is given, but Func is not null, the input data is
    16  // automatically encoded from the given Func and Args arguments by many
    17  // functions that accept a Message struct as an argument.
    18  type Message struct {
    19  	From                  common.Address  // Sender
    20  	To                    *common.Address // Recipient
    21  	Nonce                 uint64
    22  	GasPrice              *big.Int
    23  	GasFeeCap             *big.Int
    24  	GasTipCap             *big.Int
    25  	Gas                   uint64
    26  	Value                 *big.Int
    27  	Input                 []byte // Input data
    28  	AccessList            types.AccessList
    29  	BlobGasFeeCap         *big.Int
    30  	BlobHashes            []common.Hash
    31  	SetCodeAuthorizations []types.SetCodeAuthorization
    32  
    33  	Func Func  // Func to encode
    34  	Args []any // Arguments for Func
    35  }
    36  
    37  // Set sets msg to the given Message and returns it.
    38  func (msg *Message) Set(msg2 *Message) *Message {
    39  	msg.From = msg2.From
    40  	msg.To = msg2.To
    41  	msg.Nonce = msg2.Nonce
    42  	msg.GasPrice = msg2.GasPrice
    43  	msg.GasFeeCap = msg2.GasFeeCap
    44  	msg.GasTipCap = msg2.GasTipCap
    45  	msg.Gas = msg2.Gas
    46  	msg.Value = msg2.Value
    47  	msg.Input = msg2.Input
    48  	msg.AccessList = msg2.AccessList
    49  	msg.BlobGasFeeCap = msg2.BlobGasFeeCap
    50  	msg.BlobHashes = msg2.BlobHashes
    51  	msg.SetCodeAuthorizations = msg2.SetCodeAuthorizations
    52  	msg.Func = msg2.Func
    53  	msg.Args = msg2.Args
    54  	return msg
    55  }
    56  
    57  // SetTx sets msg to the [types.Transaction] tx and returns msg.
    58  func (msg *Message) SetTx(tx *types.Transaction, signer types.Signer) (*Message, error) {
    59  	from, err := types.Sender(signer, tx)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  
    64  	msg.From = from
    65  	msg.To = tx.To()
    66  	msg.Nonce = tx.Nonce()
    67  	msg.GasPrice = tx.GasPrice()
    68  	msg.GasFeeCap = tx.GasFeeCap()
    69  	msg.GasTipCap = tx.GasTipCap()
    70  	msg.Gas = tx.Gas()
    71  	msg.Value = tx.Value()
    72  	msg.Input = tx.Data()
    73  	msg.AccessList = tx.AccessList()
    74  	msg.BlobGasFeeCap = tx.BlobGasFeeCap()
    75  	msg.BlobHashes = tx.BlobHashes()
    76  	msg.SetCodeAuthorizations = tx.SetCodeAuthorizations()
    77  	return msg, nil
    78  }
    79  
    80  // MustSetTx is like [SetTx] but panics if the sender retrieval fails.
    81  func (msg *Message) MustSetTx(tx *types.Transaction, signer types.Signer) *Message {
    82  	msg, err := msg.SetTx(tx, signer)
    83  	if err != nil {
    84  		panic(err)
    85  	}
    86  	return msg
    87  }
    88  
    89  // SetCallMsg sets msg to the [ethereum.CallMsg] callMsg and returns msg.
    90  func (msg *Message) SetCallMsg(callMsg ethereum.CallMsg) *Message {
    91  	msg.From = callMsg.From
    92  	msg.To = callMsg.To
    93  	msg.Gas = callMsg.Gas
    94  	msg.GasPrice = callMsg.GasPrice
    95  	msg.GasFeeCap = callMsg.GasFeeCap
    96  	msg.GasTipCap = callMsg.GasTipCap
    97  	msg.Value = callMsg.Value
    98  	msg.Input = callMsg.Data
    99  	msg.AccessList = callMsg.AccessList
   100  	msg.BlobGasFeeCap = callMsg.BlobGasFeeCap
   101  	msg.BlobHashes = callMsg.BlobHashes
   102  	return msg
   103  }
   104  
   105  type message struct {
   106  	From                  *common.Address              `json:"from,omitempty"`
   107  	To                    *common.Address              `json:"to,omitempty"`
   108  	Nonce                 hexutil.Uint64               `json:"nonce,omitempty"`
   109  	GasPrice              *hexutil.Big                 `json:"gasPrice,omitempty"`
   110  	GasFeeCap             *hexutil.Big                 `json:"maxFeePerGas,omitempty"`
   111  	GasTipCap             *hexutil.Big                 `json:"maxPriorityFeePerGas,omitempty"`
   112  	Gas                   hexutil.Uint64               `json:"gas,omitempty"`
   113  	Value                 *hexutil.Big                 `json:"value,omitempty"`
   114  	Input                 hexutil.Bytes                `json:"input,omitempty"`
   115  	Data                  hexutil.Bytes                `json:"data,omitempty"`
   116  	AccessList            types.AccessList             `json:"accessList,omitempty"`
   117  	BlobGasFeeCap         *hexutil.Big                 `json:"maxFeePerBlobGas,omitempty"`
   118  	BlobHashes            []common.Hash                `json:"blobVersionedHashes,omitempty"`
   119  	SetCodeAuthorizations []types.SetCodeAuthorization `json:"authorizationList,omitempty"`
   120  }
   121  
   122  // MarshalJSON implements the [json.Marshaler].
   123  func (msg *Message) MarshalJSON() ([]byte, error) {
   124  	var enc message
   125  	if msg.From != (common.Address{}) {
   126  		enc.From = &msg.From
   127  	}
   128  	enc.To = msg.To
   129  	enc.Nonce = hexutil.Uint64(msg.Nonce)
   130  	if msg.GasPrice != nil {
   131  		enc.GasPrice = (*hexutil.Big)(msg.GasPrice)
   132  	}
   133  	if msg.GasFeeCap != nil {
   134  		enc.GasFeeCap = (*hexutil.Big)(msg.GasFeeCap)
   135  	}
   136  	if msg.GasTipCap != nil {
   137  		enc.GasTipCap = (*hexutil.Big)(msg.GasTipCap)
   138  	}
   139  	if msg.Gas > 0 {
   140  		enc.Gas = hexutil.Uint64(msg.Gas)
   141  	}
   142  	if msg.Value != nil {
   143  		enc.Value = (*hexutil.Big)(msg.Value)
   144  	}
   145  	if len(msg.Input) > 0 {
   146  		enc.Data = msg.Input
   147  	}
   148  	if len(msg.AccessList) > 0 {
   149  		enc.AccessList = msg.AccessList
   150  	}
   151  	if msg.BlobGasFeeCap != nil {
   152  		enc.BlobGasFeeCap = (*hexutil.Big)(msg.BlobGasFeeCap)
   153  	}
   154  	if len(msg.BlobHashes) > 0 {
   155  		enc.BlobHashes = msg.BlobHashes
   156  	}
   157  	if len(msg.SetCodeAuthorizations) > 0 {
   158  		enc.SetCodeAuthorizations = msg.SetCodeAuthorizations
   159  	}
   160  	return json.Marshal(&enc)
   161  }
   162  
   163  // UnmarshalJSON implements the [json.Unmarshaler].
   164  func (msg *Message) UnmarshalJSON(data []byte) error {
   165  	var dec message
   166  	if err := json.Unmarshal(data, &dec); err != nil {
   167  		return err
   168  	}
   169  
   170  	if dec.From != nil {
   171  		msg.From = *dec.From
   172  	}
   173  	msg.To = dec.To
   174  	msg.Nonce = uint64(dec.Nonce)
   175  	if dec.GasFeeCap != nil {
   176  		msg.GasFeeCap = (*big.Int)(dec.GasFeeCap)
   177  	}
   178  	if dec.GasTipCap != nil {
   179  		msg.GasTipCap = (*big.Int)(dec.GasTipCap)
   180  	}
   181  	if dec.GasPrice != nil {
   182  		msg.GasPrice = (*big.Int)(dec.GasPrice)
   183  		if msg.GasFeeCap == nil { // TODO: drop this logic here
   184  			msg.GasFeeCap = msg.GasPrice
   185  		}
   186  	}
   187  	msg.Gas = uint64(dec.Gas)
   188  	if dec.Value != nil {
   189  		msg.Value = (*big.Int)(dec.Value)
   190  	}
   191  	if len(dec.Input) > 0 {
   192  		msg.Input = dec.Input
   193  	} else if len(dec.Data) > 0 {
   194  		msg.Input = dec.Data
   195  	}
   196  	if len(dec.AccessList) > 0 {
   197  		msg.AccessList = dec.AccessList
   198  	}
   199  	if dec.BlobGasFeeCap != nil {
   200  		msg.BlobGasFeeCap = (*big.Int)(dec.BlobGasFeeCap)
   201  	}
   202  	if len(dec.BlobHashes) > 0 {
   203  		msg.BlobHashes = dec.BlobHashes
   204  	}
   205  	if len(dec.SetCodeAuthorizations) > 0 {
   206  		msg.SetCodeAuthorizations = dec.SetCodeAuthorizations
   207  	}
   208  	return nil
   209  }