github.com/ethereum/go-ethereum@v1.16.1/ethclient/ethclient.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package ethclient provides a client for the Ethereum RPC API. 18 package ethclient 19 20 import ( 21 "context" 22 "encoding/json" 23 "errors" 24 "fmt" 25 "math/big" 26 27 "github.com/ethereum/go-ethereum" 28 "github.com/ethereum/go-ethereum/common" 29 "github.com/ethereum/go-ethereum/common/hexutil" 30 "github.com/ethereum/go-ethereum/core/types" 31 "github.com/ethereum/go-ethereum/rpc" 32 ) 33 34 // Client defines typed wrappers for the Ethereum RPC API. 35 type Client struct { 36 c *rpc.Client 37 } 38 39 // Dial connects a client to the given URL. 40 func Dial(rawurl string) (*Client, error) { 41 return DialContext(context.Background(), rawurl) 42 } 43 44 // DialContext connects a client to the given URL with context. 45 func DialContext(ctx context.Context, rawurl string) (*Client, error) { 46 c, err := rpc.DialContext(ctx, rawurl) 47 if err != nil { 48 return nil, err 49 } 50 return NewClient(c), nil 51 } 52 53 // NewClient creates a client that uses the given RPC client. 54 func NewClient(c *rpc.Client) *Client { 55 return &Client{c} 56 } 57 58 // Close closes the underlying RPC connection. 59 func (ec *Client) Close() { 60 ec.c.Close() 61 } 62 63 // Client gets the underlying RPC client. 64 func (ec *Client) Client() *rpc.Client { 65 return ec.c 66 } 67 68 // Blockchain Access 69 70 // ChainID retrieves the current chain ID for transaction replay protection. 71 func (ec *Client) ChainID(ctx context.Context) (*big.Int, error) { 72 var result hexutil.Big 73 err := ec.c.CallContext(ctx, &result, "eth_chainId") 74 if err != nil { 75 return nil, err 76 } 77 return (*big.Int)(&result), err 78 } 79 80 // BlockByHash returns the given full block. 81 // 82 // Note that loading full blocks requires two requests. Use HeaderByHash 83 // if you don't need all transactions or uncle headers. 84 func (ec *Client) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { 85 return ec.getBlock(ctx, "eth_getBlockByHash", hash, true) 86 } 87 88 // BlockByNumber returns a block from the current canonical chain. 89 // If `number` is nil, the latest known block is returned. 90 // 91 // Use `HeaderByNumber` if you don't need full transaction data or uncle headers. 92 // 93 // Supported special block number tags: 94 // - `earliest` : The genesis (earliest) block 95 // - `latest` : The most recently included block 96 // - `safe` : The latest safe head block 97 // - `finalized` : The latest finalized block 98 // - `pending` : The pending block 99 // 100 // Example usage: 101 // 102 // ```go 103 // BlockByNumber(context.Background(), big.NewInt(int64(rpc.LatestBlockNumber))) 104 // ``` 105 func (ec *Client) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { 106 return ec.getBlock(ctx, "eth_getBlockByNumber", toBlockNumArg(number), true) 107 } 108 109 // BlockNumber returns the most recent block number 110 func (ec *Client) BlockNumber(ctx context.Context) (uint64, error) { 111 var result hexutil.Uint64 112 err := ec.c.CallContext(ctx, &result, "eth_blockNumber") 113 return uint64(result), err 114 } 115 116 // PeerCount returns the number of p2p peers as reported by the net_peerCount method. 117 func (ec *Client) PeerCount(ctx context.Context) (uint64, error) { 118 var result hexutil.Uint64 119 err := ec.c.CallContext(ctx, &result, "net_peerCount") 120 return uint64(result), err 121 } 122 123 // BlockReceipts returns the receipts of a given block number or hash. 124 func (ec *Client) BlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]*types.Receipt, error) { 125 var r []*types.Receipt 126 err := ec.c.CallContext(ctx, &r, "eth_getBlockReceipts", blockNrOrHash.String()) 127 if err == nil && r == nil { 128 return nil, ethereum.NotFound 129 } 130 return r, err 131 } 132 133 type rpcBlock struct { 134 Hash *common.Hash `json:"hash"` 135 Transactions []rpcTransaction `json:"transactions"` 136 UncleHashes []common.Hash `json:"uncles"` 137 Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"` 138 } 139 140 func (ec *Client) getBlock(ctx context.Context, method string, args ...interface{}) (*types.Block, error) { 141 var raw json.RawMessage 142 err := ec.c.CallContext(ctx, &raw, method, args...) 143 if err != nil { 144 return nil, err 145 } 146 147 // Decode header and transactions. 148 var head *types.Header 149 if err := json.Unmarshal(raw, &head); err != nil { 150 return nil, err 151 } 152 // When the block is not found, the API returns JSON null. 153 if head == nil { 154 return nil, ethereum.NotFound 155 } 156 157 var body rpcBlock 158 if err := json.Unmarshal(raw, &body); err != nil { 159 return nil, err 160 } 161 // Pending blocks don't return a block hash, compute it for sender caching. 162 if body.Hash == nil { 163 tmp := head.Hash() 164 body.Hash = &tmp 165 } 166 167 // Quick-verify transaction and uncle lists. This mostly helps with debugging the server. 168 if head.UncleHash == types.EmptyUncleHash && len(body.UncleHashes) > 0 { 169 return nil, errors.New("server returned non-empty uncle list but block header indicates no uncles") 170 } 171 if head.UncleHash != types.EmptyUncleHash && len(body.UncleHashes) == 0 { 172 return nil, errors.New("server returned empty uncle list but block header indicates uncles") 173 } 174 if head.TxHash == types.EmptyTxsHash && len(body.Transactions) > 0 { 175 return nil, errors.New("server returned non-empty transaction list but block header indicates no transactions") 176 } 177 if head.TxHash != types.EmptyTxsHash && len(body.Transactions) == 0 { 178 return nil, errors.New("server returned empty transaction list but block header indicates transactions") 179 } 180 // Load uncles because they are not included in the block response. 181 var uncles []*types.Header 182 if len(body.UncleHashes) > 0 { 183 uncles = make([]*types.Header, len(body.UncleHashes)) 184 reqs := make([]rpc.BatchElem, len(body.UncleHashes)) 185 for i := range reqs { 186 reqs[i] = rpc.BatchElem{ 187 Method: "eth_getUncleByBlockHashAndIndex", 188 Args: []interface{}{body.Hash, hexutil.EncodeUint64(uint64(i))}, 189 Result: &uncles[i], 190 } 191 } 192 if err := ec.c.BatchCallContext(ctx, reqs); err != nil { 193 return nil, err 194 } 195 for i := range reqs { 196 if reqs[i].Error != nil { 197 return nil, reqs[i].Error 198 } 199 if uncles[i] == nil { 200 return nil, fmt.Errorf("got null header for uncle %d of block %x", i, body.Hash[:]) 201 } 202 } 203 } 204 // Fill the sender cache of transactions in the block. 205 txs := make([]*types.Transaction, len(body.Transactions)) 206 for i, tx := range body.Transactions { 207 if tx.From != nil { 208 setSenderFromServer(tx.tx, *tx.From, *body.Hash) 209 } 210 txs[i] = tx.tx 211 } 212 213 return types.NewBlockWithHeader(head).WithBody( 214 types.Body{ 215 Transactions: txs, 216 Uncles: uncles, 217 Withdrawals: body.Withdrawals, 218 }), nil 219 } 220 221 // HeaderByHash returns the block header with the given hash. 222 func (ec *Client) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { 223 var head *types.Header 224 err := ec.c.CallContext(ctx, &head, "eth_getBlockByHash", hash, false) 225 if err == nil && head == nil { 226 err = ethereum.NotFound 227 } 228 return head, err 229 } 230 231 // HeaderByNumber returns a block header from the current canonical chain. 232 // If `number` is nil, the latest known block header is returned. 233 // 234 // Supported special block number tags: 235 // - `earliest` : The genesis (earliest) block 236 // - `latest` : The most recently included block 237 // - `safe` : The latest safe head block 238 // - `finalized` : The latest finalized block 239 // - `pending` : The pending block 240 // 241 // Example usage: 242 // 243 // ```go 244 // HeaderByNumber(context.Background(), big.NewInt(int64(rpc.LatestBlockNumber))) 245 // ``` 246 func (ec *Client) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { 247 var head *types.Header 248 err := ec.c.CallContext(ctx, &head, "eth_getBlockByNumber", toBlockNumArg(number), false) 249 if err == nil && head == nil { 250 err = ethereum.NotFound 251 } 252 return head, err 253 } 254 255 type rpcTransaction struct { 256 tx *types.Transaction 257 txExtraInfo 258 } 259 260 type txExtraInfo struct { 261 BlockNumber *string `json:"blockNumber,omitempty"` 262 BlockHash *common.Hash `json:"blockHash,omitempty"` 263 From *common.Address `json:"from,omitempty"` 264 } 265 266 func (tx *rpcTransaction) UnmarshalJSON(msg []byte) error { 267 if err := json.Unmarshal(msg, &tx.tx); err != nil { 268 return err 269 } 270 return json.Unmarshal(msg, &tx.txExtraInfo) 271 } 272 273 // TransactionByHash returns the transaction with the given hash. 274 func (ec *Client) TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) { 275 var json *rpcTransaction 276 err = ec.c.CallContext(ctx, &json, "eth_getTransactionByHash", hash) 277 if err != nil { 278 return nil, false, err 279 } else if json == nil { 280 return nil, false, ethereum.NotFound 281 } else if _, r, _ := json.tx.RawSignatureValues(); r == nil { 282 return nil, false, errors.New("server returned transaction without signature") 283 } 284 if json.From != nil && json.BlockHash != nil { 285 setSenderFromServer(json.tx, *json.From, *json.BlockHash) 286 } 287 return json.tx, json.BlockNumber == nil, nil 288 } 289 290 // TransactionSender returns the sender address of the given transaction. The transaction 291 // must be known to the remote node and included in the blockchain at the given block and 292 // index. The sender is the one derived by the protocol at the time of inclusion. 293 // 294 // There is a fast-path for transactions retrieved by TransactionByHash and 295 // TransactionInBlock. Getting their sender address can be done without an RPC interaction. 296 func (ec *Client) TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) { 297 // Try to load the address from the cache. 298 sender, err := types.Sender(&senderFromServer{blockhash: block}, tx) 299 if err == nil { 300 return sender, nil 301 } 302 303 // It was not found in cache, ask the server. 304 var meta struct { 305 Hash common.Hash 306 From common.Address 307 } 308 if err = ec.c.CallContext(ctx, &meta, "eth_getTransactionByBlockHashAndIndex", block, hexutil.Uint64(index)); err != nil { 309 return common.Address{}, err 310 } 311 if meta.Hash == (common.Hash{}) || meta.Hash != tx.Hash() { 312 return common.Address{}, errors.New("wrong inclusion block/index") 313 } 314 return meta.From, nil 315 } 316 317 // TransactionCount returns the total number of transactions in the given block. 318 func (ec *Client) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) { 319 var num hexutil.Uint 320 err := ec.c.CallContext(ctx, &num, "eth_getBlockTransactionCountByHash", blockHash) 321 return uint(num), err 322 } 323 324 // TransactionInBlock returns a single transaction at index in the given block. 325 func (ec *Client) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) { 326 var json *rpcTransaction 327 err := ec.c.CallContext(ctx, &json, "eth_getTransactionByBlockHashAndIndex", blockHash, hexutil.Uint64(index)) 328 if err != nil { 329 return nil, err 330 } 331 if json == nil { 332 return nil, ethereum.NotFound 333 } else if _, r, _ := json.tx.RawSignatureValues(); r == nil { 334 return nil, errors.New("server returned transaction without signature") 335 } 336 if json.From != nil && json.BlockHash != nil { 337 setSenderFromServer(json.tx, *json.From, *json.BlockHash) 338 } 339 return json.tx, err 340 } 341 342 // TransactionReceipt returns the receipt of a transaction by transaction hash. 343 // Note that the receipt is not available for pending transactions. 344 func (ec *Client) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { 345 var r *types.Receipt 346 err := ec.c.CallContext(ctx, &r, "eth_getTransactionReceipt", txHash) 347 if err == nil && r == nil { 348 return nil, ethereum.NotFound 349 } 350 return r, err 351 } 352 353 // SyncProgress retrieves the current progress of the sync algorithm. If there's 354 // no sync currently running, it returns nil. 355 func (ec *Client) SyncProgress(ctx context.Context) (*ethereum.SyncProgress, error) { 356 var raw json.RawMessage 357 if err := ec.c.CallContext(ctx, &raw, "eth_syncing"); err != nil { 358 return nil, err 359 } 360 // Handle the possible response types 361 var syncing bool 362 if err := json.Unmarshal(raw, &syncing); err == nil { 363 return nil, nil // Not syncing (always false) 364 } 365 var p *rpcProgress 366 if err := json.Unmarshal(raw, &p); err != nil { 367 return nil, err 368 } 369 return p.toSyncProgress(), nil 370 } 371 372 // SubscribeNewHead subscribes to notifications about the current blockchain head 373 // on the given channel. 374 func (ec *Client) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) { 375 sub, err := ec.c.EthSubscribe(ctx, ch, "newHeads") 376 if err != nil { 377 // Defensively prefer returning nil interface explicitly on error-path, instead 378 // of letting default golang behavior wrap it with non-nil interface that stores 379 // nil concrete type value. 380 return nil, err 381 } 382 return sub, nil 383 } 384 385 // State Access 386 387 // NetworkID returns the network ID for this client. 388 func (ec *Client) NetworkID(ctx context.Context) (*big.Int, error) { 389 version := new(big.Int) 390 var ver string 391 if err := ec.c.CallContext(ctx, &ver, "net_version"); err != nil { 392 return nil, err 393 } 394 if _, ok := version.SetString(ver, 0); !ok { 395 return nil, fmt.Errorf("invalid net_version result %q", ver) 396 } 397 return version, nil 398 } 399 400 // BalanceAt returns the wei balance of the given account. 401 // The block number can be nil, in which case the balance is taken from the latest known block. 402 func (ec *Client) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) { 403 var result hexutil.Big 404 err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, toBlockNumArg(blockNumber)) 405 return (*big.Int)(&result), err 406 } 407 408 // BalanceAtHash returns the wei balance of the given account. 409 func (ec *Client) BalanceAtHash(ctx context.Context, account common.Address, blockHash common.Hash) (*big.Int, error) { 410 var result hexutil.Big 411 err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, rpc.BlockNumberOrHashWithHash(blockHash, false)) 412 return (*big.Int)(&result), err 413 } 414 415 // StorageAt returns the value of key in the contract storage of the given account. 416 // The block number can be nil, in which case the value is taken from the latest known block. 417 func (ec *Client) StorageAt(ctx context.Context, account common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) { 418 var result hexutil.Bytes 419 err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, toBlockNumArg(blockNumber)) 420 return result, err 421 } 422 423 // StorageAtHash returns the value of key in the contract storage of the given account. 424 func (ec *Client) StorageAtHash(ctx context.Context, account common.Address, key common.Hash, blockHash common.Hash) ([]byte, error) { 425 var result hexutil.Bytes 426 err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, rpc.BlockNumberOrHashWithHash(blockHash, false)) 427 return result, err 428 } 429 430 // CodeAt returns the contract code of the given account. 431 // The block number can be nil, in which case the code is taken from the latest known block. 432 func (ec *Client) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) { 433 var result hexutil.Bytes 434 err := ec.c.CallContext(ctx, &result, "eth_getCode", account, toBlockNumArg(blockNumber)) 435 return result, err 436 } 437 438 // CodeAtHash returns the contract code of the given account. 439 func (ec *Client) CodeAtHash(ctx context.Context, account common.Address, blockHash common.Hash) ([]byte, error) { 440 var result hexutil.Bytes 441 err := ec.c.CallContext(ctx, &result, "eth_getCode", account, rpc.BlockNumberOrHashWithHash(blockHash, false)) 442 return result, err 443 } 444 445 // NonceAt returns the account nonce of the given account. 446 // The block number can be nil, in which case the nonce is taken from the latest known block. 447 func (ec *Client) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) { 448 var result hexutil.Uint64 449 err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, toBlockNumArg(blockNumber)) 450 return uint64(result), err 451 } 452 453 // NonceAtHash returns the account nonce of the given account. 454 func (ec *Client) NonceAtHash(ctx context.Context, account common.Address, blockHash common.Hash) (uint64, error) { 455 var result hexutil.Uint64 456 err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, rpc.BlockNumberOrHashWithHash(blockHash, false)) 457 return uint64(result), err 458 } 459 460 // Filters 461 462 // FilterLogs executes a filter query. 463 func (ec *Client) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { 464 var result []types.Log 465 arg, err := toFilterArg(q) 466 if err != nil { 467 return nil, err 468 } 469 err = ec.c.CallContext(ctx, &result, "eth_getLogs", arg) 470 return result, err 471 } 472 473 // SubscribeFilterLogs subscribes to the results of a streaming filter query. 474 func (ec *Client) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { 475 arg, err := toFilterArg(q) 476 if err != nil { 477 return nil, err 478 } 479 sub, err := ec.c.EthSubscribe(ctx, ch, "logs", arg) 480 if err != nil { 481 // Defensively prefer returning nil interface explicitly on error-path, instead 482 // of letting default golang behavior wrap it with non-nil interface that stores 483 // nil concrete type value. 484 return nil, err 485 } 486 return sub, nil 487 } 488 489 func toFilterArg(q ethereum.FilterQuery) (interface{}, error) { 490 arg := map[string]interface{}{ 491 "address": q.Addresses, 492 "topics": q.Topics, 493 } 494 if q.BlockHash != nil { 495 arg["blockHash"] = *q.BlockHash 496 if q.FromBlock != nil || q.ToBlock != nil { 497 return nil, errors.New("cannot specify both BlockHash and FromBlock/ToBlock") 498 } 499 } else { 500 if q.FromBlock == nil { 501 arg["fromBlock"] = "0x0" 502 } else { 503 arg["fromBlock"] = toBlockNumArg(q.FromBlock) 504 } 505 arg["toBlock"] = toBlockNumArg(q.ToBlock) 506 } 507 return arg, nil 508 } 509 510 // Pending State 511 512 // PendingBalanceAt returns the wei balance of the given account in the pending state. 513 func (ec *Client) PendingBalanceAt(ctx context.Context, account common.Address) (*big.Int, error) { 514 var result hexutil.Big 515 err := ec.c.CallContext(ctx, &result, "eth_getBalance", account, "pending") 516 return (*big.Int)(&result), err 517 } 518 519 // PendingStorageAt returns the value of key in the contract storage of the given account in the pending state. 520 func (ec *Client) PendingStorageAt(ctx context.Context, account common.Address, key common.Hash) ([]byte, error) { 521 var result hexutil.Bytes 522 err := ec.c.CallContext(ctx, &result, "eth_getStorageAt", account, key, "pending") 523 return result, err 524 } 525 526 // PendingCodeAt returns the contract code of the given account in the pending state. 527 func (ec *Client) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { 528 var result hexutil.Bytes 529 err := ec.c.CallContext(ctx, &result, "eth_getCode", account, "pending") 530 return result, err 531 } 532 533 // PendingNonceAt returns the account nonce of the given account in the pending state. 534 // This is the nonce that should be used for the next transaction. 535 func (ec *Client) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { 536 var result hexutil.Uint64 537 err := ec.c.CallContext(ctx, &result, "eth_getTransactionCount", account, "pending") 538 return uint64(result), err 539 } 540 541 // PendingTransactionCount returns the total number of transactions in the pending state. 542 func (ec *Client) PendingTransactionCount(ctx context.Context) (uint, error) { 543 var num hexutil.Uint 544 err := ec.c.CallContext(ctx, &num, "eth_getBlockTransactionCountByNumber", "pending") 545 return uint(num), err 546 } 547 548 // Contract Calling 549 550 // CallContract executes a message call transaction, which is directly executed in the VM 551 // of the node, but never mined into the blockchain. 552 // 553 // blockNumber selects the block height at which the call runs. It can be nil, in which 554 // case the code is taken from the latest known block. Note that state from very old 555 // blocks might not be available. 556 func (ec *Client) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { 557 var hex hexutil.Bytes 558 err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), toBlockNumArg(blockNumber)) 559 if err != nil { 560 return nil, err 561 } 562 return hex, nil 563 } 564 565 // CallContractAtHash is almost the same as CallContract except that it selects 566 // the block by block hash instead of block height. 567 func (ec *Client) CallContractAtHash(ctx context.Context, msg ethereum.CallMsg, blockHash common.Hash) ([]byte, error) { 568 var hex hexutil.Bytes 569 err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), rpc.BlockNumberOrHashWithHash(blockHash, false)) 570 if err != nil { 571 return nil, err 572 } 573 return hex, nil 574 } 575 576 // PendingCallContract executes a message call transaction using the EVM. 577 // The state seen by the contract call is the pending state. 578 func (ec *Client) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) { 579 var hex hexutil.Bytes 580 err := ec.c.CallContext(ctx, &hex, "eth_call", toCallArg(msg), "pending") 581 if err != nil { 582 return nil, err 583 } 584 return hex, nil 585 } 586 587 // SuggestGasPrice retrieves the currently suggested gas price to allow a timely 588 // execution of a transaction. 589 func (ec *Client) SuggestGasPrice(ctx context.Context) (*big.Int, error) { 590 var hex hexutil.Big 591 if err := ec.c.CallContext(ctx, &hex, "eth_gasPrice"); err != nil { 592 return nil, err 593 } 594 return (*big.Int)(&hex), nil 595 } 596 597 // SuggestGasTipCap retrieves the currently suggested gas tip cap after 1559 to 598 // allow a timely execution of a transaction. 599 func (ec *Client) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { 600 var hex hexutil.Big 601 if err := ec.c.CallContext(ctx, &hex, "eth_maxPriorityFeePerGas"); err != nil { 602 return nil, err 603 } 604 return (*big.Int)(&hex), nil 605 } 606 607 // BlobBaseFee retrieves the current blob base fee. 608 func (ec *Client) BlobBaseFee(ctx context.Context) (*big.Int, error) { 609 var hex hexutil.Big 610 if err := ec.c.CallContext(ctx, &hex, "eth_blobBaseFee"); err != nil { 611 return nil, err 612 } 613 return (*big.Int)(&hex), nil 614 } 615 616 type feeHistoryResultMarshaling struct { 617 OldestBlock *hexutil.Big `json:"oldestBlock"` 618 Reward [][]*hexutil.Big `json:"reward,omitempty"` 619 BaseFee []*hexutil.Big `json:"baseFeePerGas,omitempty"` 620 GasUsedRatio []float64 `json:"gasUsedRatio"` 621 } 622 623 // FeeHistory retrieves the fee market history. 624 func (ec *Client) FeeHistory(ctx context.Context, blockCount uint64, lastBlock *big.Int, rewardPercentiles []float64) (*ethereum.FeeHistory, error) { 625 var res feeHistoryResultMarshaling 626 if err := ec.c.CallContext(ctx, &res, "eth_feeHistory", hexutil.Uint(blockCount), toBlockNumArg(lastBlock), rewardPercentiles); err != nil { 627 return nil, err 628 } 629 reward := make([][]*big.Int, len(res.Reward)) 630 for i, r := range res.Reward { 631 reward[i] = make([]*big.Int, len(r)) 632 for j, r := range r { 633 reward[i][j] = (*big.Int)(r) 634 } 635 } 636 baseFee := make([]*big.Int, len(res.BaseFee)) 637 for i, b := range res.BaseFee { 638 baseFee[i] = (*big.Int)(b) 639 } 640 return ðereum.FeeHistory{ 641 OldestBlock: (*big.Int)(res.OldestBlock), 642 Reward: reward, 643 BaseFee: baseFee, 644 GasUsedRatio: res.GasUsedRatio, 645 }, nil 646 } 647 648 // EstimateGas tries to estimate the gas needed to execute a specific transaction based on 649 // the current state of the backend blockchain. There is no guarantee that this is the 650 // true gas limit requirement as other transactions may be added or removed by miners, but 651 // it should provide a basis for setting a reasonable default. 652 // 653 // Note that the state used by this method is implementation-defined by the remote RPC 654 // server, but it's reasonable to assume that it will either be the pending or latest 655 // state. 656 func (ec *Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error) { 657 var hex hexutil.Uint64 658 err := ec.c.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg)) 659 if err != nil { 660 return 0, err 661 } 662 return uint64(hex), nil 663 } 664 665 // EstimateGasAtBlock is almost the same as EstimateGas except that it selects the block height 666 // instead of using the remote RPC's default state for gas estimation. 667 func (ec *Client) EstimateGasAtBlock(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) (uint64, error) { 668 var hex hexutil.Uint64 669 err := ec.c.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg), toBlockNumArg(blockNumber)) 670 if err != nil { 671 return 0, err 672 } 673 return uint64(hex), nil 674 } 675 676 // EstimateGasAtBlockHash is almost the same as EstimateGas except that it selects the block 677 // hash instead of using the remote RPC's default state for gas estimation. 678 func (ec *Client) EstimateGasAtBlockHash(ctx context.Context, msg ethereum.CallMsg, blockHash common.Hash) (uint64, error) { 679 var hex hexutil.Uint64 680 err := ec.c.CallContext(ctx, &hex, "eth_estimateGas", toCallArg(msg), rpc.BlockNumberOrHashWithHash(blockHash, false)) 681 if err != nil { 682 return 0, err 683 } 684 return uint64(hex), nil 685 } 686 687 // SendTransaction injects a signed transaction into the pending pool for execution. 688 // 689 // If the transaction was a contract creation use the TransactionReceipt method to get the 690 // contract address after the transaction has been mined. 691 func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction) error { 692 data, err := tx.MarshalBinary() 693 if err != nil { 694 return err 695 } 696 return ec.c.CallContext(ctx, nil, "eth_sendRawTransaction", hexutil.Encode(data)) 697 } 698 699 // RevertErrorData returns the 'revert reason' data of a contract call. 700 // 701 // This can be used with CallContract and EstimateGas, and only when the server is Geth. 702 func RevertErrorData(err error) ([]byte, bool) { 703 var ec rpc.Error 704 var ed rpc.DataError 705 if errors.As(err, &ec) && errors.As(err, &ed) && ec.ErrorCode() == 3 { 706 if eds, ok := ed.ErrorData().(string); ok { 707 revertData, err := hexutil.Decode(eds) 708 if err == nil { 709 return revertData, true 710 } 711 } 712 } 713 return nil, false 714 } 715 716 func toBlockNumArg(number *big.Int) string { 717 if number == nil { 718 return "latest" 719 } 720 if number.Sign() >= 0 { 721 return hexutil.EncodeBig(number) 722 } 723 // It's negative. 724 if number.IsInt64() { 725 return rpc.BlockNumber(number.Int64()).String() 726 } 727 // It's negative and large, which is invalid. 728 return fmt.Sprintf("<invalid %d>", number) 729 } 730 731 func toCallArg(msg ethereum.CallMsg) interface{} { 732 arg := map[string]interface{}{ 733 "from": msg.From, 734 "to": msg.To, 735 } 736 if len(msg.Data) > 0 { 737 arg["input"] = hexutil.Bytes(msg.Data) 738 } 739 if msg.Value != nil { 740 arg["value"] = (*hexutil.Big)(msg.Value) 741 } 742 if msg.Gas != 0 { 743 arg["gas"] = hexutil.Uint64(msg.Gas) 744 } 745 if msg.GasPrice != nil { 746 arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice) 747 } 748 if msg.GasFeeCap != nil { 749 arg["maxFeePerGas"] = (*hexutil.Big)(msg.GasFeeCap) 750 } 751 if msg.GasTipCap != nil { 752 arg["maxPriorityFeePerGas"] = (*hexutil.Big)(msg.GasTipCap) 753 } 754 if msg.AccessList != nil { 755 arg["accessList"] = msg.AccessList 756 } 757 if msg.BlobGasFeeCap != nil { 758 arg["maxFeePerBlobGas"] = (*hexutil.Big)(msg.BlobGasFeeCap) 759 } 760 if msg.BlobHashes != nil { 761 arg["blobVersionedHashes"] = msg.BlobHashes 762 } 763 if msg.AuthorizationList != nil { 764 arg["authorizationList"] = msg.AuthorizationList 765 } 766 return arg 767 } 768 769 // rpcProgress is a copy of SyncProgress with hex-encoded fields. 770 type rpcProgress struct { 771 StartingBlock hexutil.Uint64 772 CurrentBlock hexutil.Uint64 773 HighestBlock hexutil.Uint64 774 775 PulledStates hexutil.Uint64 776 KnownStates hexutil.Uint64 777 778 SyncedAccounts hexutil.Uint64 779 SyncedAccountBytes hexutil.Uint64 780 SyncedBytecodes hexutil.Uint64 781 SyncedBytecodeBytes hexutil.Uint64 782 SyncedStorage hexutil.Uint64 783 SyncedStorageBytes hexutil.Uint64 784 HealedTrienodes hexutil.Uint64 785 HealedTrienodeBytes hexutil.Uint64 786 HealedBytecodes hexutil.Uint64 787 HealedBytecodeBytes hexutil.Uint64 788 HealingTrienodes hexutil.Uint64 789 HealingBytecode hexutil.Uint64 790 TxIndexFinishedBlocks hexutil.Uint64 791 TxIndexRemainingBlocks hexutil.Uint64 792 StateIndexRemaining hexutil.Uint64 793 } 794 795 func (p *rpcProgress) toSyncProgress() *ethereum.SyncProgress { 796 if p == nil { 797 return nil 798 } 799 return ðereum.SyncProgress{ 800 StartingBlock: uint64(p.StartingBlock), 801 CurrentBlock: uint64(p.CurrentBlock), 802 HighestBlock: uint64(p.HighestBlock), 803 PulledStates: uint64(p.PulledStates), 804 KnownStates: uint64(p.KnownStates), 805 SyncedAccounts: uint64(p.SyncedAccounts), 806 SyncedAccountBytes: uint64(p.SyncedAccountBytes), 807 SyncedBytecodes: uint64(p.SyncedBytecodes), 808 SyncedBytecodeBytes: uint64(p.SyncedBytecodeBytes), 809 SyncedStorage: uint64(p.SyncedStorage), 810 SyncedStorageBytes: uint64(p.SyncedStorageBytes), 811 HealedTrienodes: uint64(p.HealedTrienodes), 812 HealedTrienodeBytes: uint64(p.HealedTrienodeBytes), 813 HealedBytecodes: uint64(p.HealedBytecodes), 814 HealedBytecodeBytes: uint64(p.HealedBytecodeBytes), 815 HealingTrienodes: uint64(p.HealingTrienodes), 816 HealingBytecode: uint64(p.HealingBytecode), 817 TxIndexFinishedBlocks: uint64(p.TxIndexFinishedBlocks), 818 TxIndexRemainingBlocks: uint64(p.TxIndexRemainingBlocks), 819 StateIndexRemaining: uint64(p.StateIndexRemaining), 820 } 821 }