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 }