gitee.com/liu-zhao234568/cntest@v1.0.0/graphql/graphql.go (about) 1 // Copyright 2019 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 graphql provides a GraphQL interface to Ethereum node data. 18 package graphql 19 20 import ( 21 "context" 22 "errors" 23 "fmt" 24 "math/big" 25 "strconv" 26 "time" 27 28 "gitee.com/liu-zhao234568/cntest/common" 29 "gitee.com/liu-zhao234568/cntest/common/hexutil" 30 "gitee.com/liu-zhao234568/cntest/common/math" 31 "gitee.com/liu-zhao234568/cntest/core/state" 32 "gitee.com/liu-zhao234568/cntest/core/types" 33 "gitee.com/liu-zhao234568/cntest/eth/filters" 34 "gitee.com/liu-zhao234568/cntest/internal/ethapi" 35 "gitee.com/liu-zhao234568/cntest/rpc" 36 ) 37 38 var ( 39 errBlockInvariant = errors.New("block objects must be instantiated with at least one of num or hash") 40 ) 41 42 type Long int64 43 44 // ImplementsGraphQLType returns true if Long implements the provided GraphQL type. 45 func (b Long) ImplementsGraphQLType(name string) bool { return name == "Long" } 46 47 // UnmarshalGraphQL unmarshals the provided GraphQL query data. 48 func (b *Long) UnmarshalGraphQL(input interface{}) error { 49 var err error 50 switch input := input.(type) { 51 case string: 52 // uncomment to support hex values 53 //if strings.HasPrefix(input, "0x") { 54 // // apply leniency and support hex representations of longs. 55 // value, err := hexutil.DecodeUint64(input) 56 // *b = Long(value) 57 // return err 58 //} else { 59 value, err := strconv.ParseInt(input, 10, 64) 60 *b = Long(value) 61 return err 62 //} 63 case int32: 64 *b = Long(input) 65 case int64: 66 *b = Long(input) 67 default: 68 err = fmt.Errorf("unexpected type %T for Long", input) 69 } 70 return err 71 } 72 73 // Account represents an Ethereum account at a particular block. 74 type Account struct { 75 backend ethapi.Backend 76 address common.Address 77 blockNrOrHash rpc.BlockNumberOrHash 78 } 79 80 // getState fetches the StateDB object for an account. 81 func (a *Account) getState(ctx context.Context) (*state.StateDB, error) { 82 state, _, err := a.backend.StateAndHeaderByNumberOrHash(ctx, a.blockNrOrHash) 83 return state, err 84 } 85 86 func (a *Account) Address(ctx context.Context) (common.Address, error) { 87 return a.address, nil 88 } 89 90 func (a *Account) Balance(ctx context.Context) (hexutil.Big, error) { 91 state, err := a.getState(ctx) 92 if err != nil { 93 return hexutil.Big{}, err 94 } 95 balance := state.GetBalance(a.address) 96 if balance == nil { 97 return hexutil.Big{}, fmt.Errorf("failed to load balance %x", a.address) 98 } 99 return hexutil.Big(*balance), nil 100 } 101 102 func (a *Account) TransactionCount(ctx context.Context) (hexutil.Uint64, error) { 103 state, err := a.getState(ctx) 104 if err != nil { 105 return 0, err 106 } 107 return hexutil.Uint64(state.GetNonce(a.address)), nil 108 } 109 110 func (a *Account) Code(ctx context.Context) (hexutil.Bytes, error) { 111 state, err := a.getState(ctx) 112 if err != nil { 113 return hexutil.Bytes{}, err 114 } 115 return state.GetCode(a.address), nil 116 } 117 118 func (a *Account) Storage(ctx context.Context, args struct{ Slot common.Hash }) (common.Hash, error) { 119 state, err := a.getState(ctx) 120 if err != nil { 121 return common.Hash{}, err 122 } 123 return state.GetState(a.address, args.Slot), nil 124 } 125 126 // Log represents an individual log message. All arguments are mandatory. 127 type Log struct { 128 backend ethapi.Backend 129 transaction *Transaction 130 log *types.Log 131 } 132 133 func (l *Log) Transaction(ctx context.Context) *Transaction { 134 return l.transaction 135 } 136 137 func (l *Log) Account(ctx context.Context, args BlockNumberArgs) *Account { 138 return &Account{ 139 backend: l.backend, 140 address: l.log.Address, 141 blockNrOrHash: args.NumberOrLatest(), 142 } 143 } 144 145 func (l *Log) Index(ctx context.Context) int32 { 146 return int32(l.log.Index) 147 } 148 149 func (l *Log) Topics(ctx context.Context) []common.Hash { 150 return l.log.Topics 151 } 152 153 func (l *Log) Data(ctx context.Context) hexutil.Bytes { 154 return l.log.Data 155 } 156 157 // AccessTuple represents EIP-2930 158 type AccessTuple struct { 159 address common.Address 160 storageKeys *[]common.Hash 161 } 162 163 func (at *AccessTuple) Address(ctx context.Context) common.Address { 164 return at.address 165 } 166 167 func (at *AccessTuple) StorageKeys(ctx context.Context) *[]common.Hash { 168 return at.storageKeys 169 } 170 171 // Transaction represents an Ethereum transaction. 172 // backend and hash are mandatory; all others will be fetched when required. 173 type Transaction struct { 174 backend ethapi.Backend 175 hash common.Hash 176 tx *types.Transaction 177 block *Block 178 index uint64 179 } 180 181 // resolve returns the internal transaction object, fetching it if needed. 182 func (t *Transaction) resolve(ctx context.Context) (*types.Transaction, error) { 183 if t.tx == nil { 184 // Try to return an already finalized transaction 185 tx, blockHash, _, index, err := t.backend.GetTransaction(ctx, t.hash) 186 if err == nil && tx != nil { 187 t.tx = tx 188 blockNrOrHash := rpc.BlockNumberOrHashWithHash(blockHash, false) 189 t.block = &Block{ 190 backend: t.backend, 191 numberOrHash: &blockNrOrHash, 192 } 193 t.index = index 194 return t.tx, nil 195 } 196 // No finalized transaction, try to retrieve it from the pool 197 t.tx = t.backend.GetPoolTransaction(t.hash) 198 } 199 return t.tx, nil 200 } 201 202 func (t *Transaction) Hash(ctx context.Context) common.Hash { 203 return t.hash 204 } 205 206 func (t *Transaction) InputData(ctx context.Context) (hexutil.Bytes, error) { 207 tx, err := t.resolve(ctx) 208 if err != nil || tx == nil { 209 return hexutil.Bytes{}, err 210 } 211 return tx.Data(), nil 212 } 213 214 func (t *Transaction) Gas(ctx context.Context) (hexutil.Uint64, error) { 215 tx, err := t.resolve(ctx) 216 if err != nil || tx == nil { 217 return 0, err 218 } 219 return hexutil.Uint64(tx.Gas()), nil 220 } 221 222 func (t *Transaction) GasPrice(ctx context.Context) (hexutil.Big, error) { 223 tx, err := t.resolve(ctx) 224 if err != nil || tx == nil { 225 return hexutil.Big{}, err 226 } 227 switch tx.Type() { 228 case types.AccessListTxType: 229 return hexutil.Big(*tx.GasPrice()), nil 230 case types.DynamicFeeTxType: 231 if t.block != nil { 232 if baseFee, _ := t.block.BaseFeePerGas(ctx); baseFee != nil { 233 // price = min(tip, gasFeeCap - baseFee) + baseFee 234 return (hexutil.Big)(*math.BigMin(new(big.Int).Add(tx.GasTipCap(), baseFee.ToInt()), tx.GasFeeCap())), nil 235 } 236 } 237 return hexutil.Big(*tx.GasPrice()), nil 238 default: 239 return hexutil.Big(*tx.GasPrice()), nil 240 } 241 } 242 243 func (t *Transaction) EffectiveGasPrice(ctx context.Context) (*hexutil.Big, error) { 244 tx, err := t.resolve(ctx) 245 if err != nil || tx == nil { 246 return nil, err 247 } 248 header, err := t.block.resolveHeader(ctx) 249 if err != nil || header == nil { 250 return nil, err 251 } 252 if header.BaseFee == nil { 253 return (*hexutil.Big)(tx.GasPrice()), nil 254 } 255 return (*hexutil.Big)(math.BigMin(new(big.Int).Add(tx.GasTipCap(), header.BaseFee), tx.GasFeeCap())), nil 256 } 257 258 func (t *Transaction) MaxFeePerGas(ctx context.Context) (*hexutil.Big, error) { 259 tx, err := t.resolve(ctx) 260 if err != nil || tx == nil { 261 return nil, err 262 } 263 switch tx.Type() { 264 case types.AccessListTxType: 265 return nil, nil 266 case types.DynamicFeeTxType: 267 return (*hexutil.Big)(tx.GasFeeCap()), nil 268 default: 269 return nil, nil 270 } 271 } 272 273 func (t *Transaction) MaxPriorityFeePerGas(ctx context.Context) (*hexutil.Big, error) { 274 tx, err := t.resolve(ctx) 275 if err != nil || tx == nil { 276 return nil, err 277 } 278 switch tx.Type() { 279 case types.AccessListTxType: 280 return nil, nil 281 case types.DynamicFeeTxType: 282 return (*hexutil.Big)(tx.GasTipCap()), nil 283 default: 284 return nil, nil 285 } 286 } 287 288 func (t *Transaction) Value(ctx context.Context) (hexutil.Big, error) { 289 tx, err := t.resolve(ctx) 290 if err != nil || tx == nil { 291 return hexutil.Big{}, err 292 } 293 if tx.Value() == nil { 294 return hexutil.Big{}, fmt.Errorf("invalid transaction value %x", t.hash) 295 } 296 return hexutil.Big(*tx.Value()), nil 297 } 298 299 func (t *Transaction) Nonce(ctx context.Context) (hexutil.Uint64, error) { 300 tx, err := t.resolve(ctx) 301 if err != nil || tx == nil { 302 return 0, err 303 } 304 return hexutil.Uint64(tx.Nonce()), nil 305 } 306 307 func (t *Transaction) To(ctx context.Context, args BlockNumberArgs) (*Account, error) { 308 tx, err := t.resolve(ctx) 309 if err != nil || tx == nil { 310 return nil, err 311 } 312 to := tx.To() 313 if to == nil { 314 return nil, nil 315 } 316 return &Account{ 317 backend: t.backend, 318 address: *to, 319 blockNrOrHash: args.NumberOrLatest(), 320 }, nil 321 } 322 323 func (t *Transaction) From(ctx context.Context, args BlockNumberArgs) (*Account, error) { 324 tx, err := t.resolve(ctx) 325 if err != nil || tx == nil { 326 return nil, err 327 } 328 signer := types.LatestSigner(t.backend.ChainConfig()) 329 from, _ := types.Sender(signer, tx) 330 return &Account{ 331 backend: t.backend, 332 address: from, 333 blockNrOrHash: args.NumberOrLatest(), 334 }, nil 335 } 336 337 func (t *Transaction) Block(ctx context.Context) (*Block, error) { 338 if _, err := t.resolve(ctx); err != nil { 339 return nil, err 340 } 341 return t.block, nil 342 } 343 344 func (t *Transaction) Index(ctx context.Context) (*int32, error) { 345 if _, err := t.resolve(ctx); err != nil { 346 return nil, err 347 } 348 if t.block == nil { 349 return nil, nil 350 } 351 index := int32(t.index) 352 return &index, nil 353 } 354 355 // getReceipt returns the receipt associated with this transaction, if any. 356 func (t *Transaction) getReceipt(ctx context.Context) (*types.Receipt, error) { 357 if _, err := t.resolve(ctx); err != nil { 358 return nil, err 359 } 360 if t.block == nil { 361 return nil, nil 362 } 363 receipts, err := t.block.resolveReceipts(ctx) 364 if err != nil { 365 return nil, err 366 } 367 return receipts[t.index], nil 368 } 369 370 func (t *Transaction) Status(ctx context.Context) (*Long, error) { 371 receipt, err := t.getReceipt(ctx) 372 if err != nil || receipt == nil { 373 return nil, err 374 } 375 ret := Long(receipt.Status) 376 return &ret, nil 377 } 378 379 func (t *Transaction) GasUsed(ctx context.Context) (*Long, error) { 380 receipt, err := t.getReceipt(ctx) 381 if err != nil || receipt == nil { 382 return nil, err 383 } 384 ret := Long(receipt.GasUsed) 385 return &ret, nil 386 } 387 388 func (t *Transaction) CumulativeGasUsed(ctx context.Context) (*Long, error) { 389 receipt, err := t.getReceipt(ctx) 390 if err != nil || receipt == nil { 391 return nil, err 392 } 393 ret := Long(receipt.CumulativeGasUsed) 394 return &ret, nil 395 } 396 397 func (t *Transaction) CreatedContract(ctx context.Context, args BlockNumberArgs) (*Account, error) { 398 receipt, err := t.getReceipt(ctx) 399 if err != nil || receipt == nil || receipt.ContractAddress == (common.Address{}) { 400 return nil, err 401 } 402 return &Account{ 403 backend: t.backend, 404 address: receipt.ContractAddress, 405 blockNrOrHash: args.NumberOrLatest(), 406 }, nil 407 } 408 409 func (t *Transaction) Logs(ctx context.Context) (*[]*Log, error) { 410 receipt, err := t.getReceipt(ctx) 411 if err != nil || receipt == nil { 412 return nil, err 413 } 414 ret := make([]*Log, 0, len(receipt.Logs)) 415 for _, log := range receipt.Logs { 416 ret = append(ret, &Log{ 417 backend: t.backend, 418 transaction: t, 419 log: log, 420 }) 421 } 422 return &ret, nil 423 } 424 425 func (t *Transaction) Type(ctx context.Context) (*int32, error) { 426 tx, err := t.resolve(ctx) 427 if err != nil { 428 return nil, err 429 } 430 txType := int32(tx.Type()) 431 return &txType, nil 432 } 433 434 func (t *Transaction) AccessList(ctx context.Context) (*[]*AccessTuple, error) { 435 tx, err := t.resolve(ctx) 436 if err != nil || tx == nil { 437 return nil, err 438 } 439 accessList := tx.AccessList() 440 ret := make([]*AccessTuple, 0, len(accessList)) 441 for _, al := range accessList { 442 ret = append(ret, &AccessTuple{ 443 address: al.Address, 444 storageKeys: &al.StorageKeys, 445 }) 446 } 447 return &ret, nil 448 } 449 450 func (t *Transaction) R(ctx context.Context) (hexutil.Big, error) { 451 tx, err := t.resolve(ctx) 452 if err != nil || tx == nil { 453 return hexutil.Big{}, err 454 } 455 _, r, _ := tx.RawSignatureValues() 456 return hexutil.Big(*r), nil 457 } 458 459 func (t *Transaction) S(ctx context.Context) (hexutil.Big, error) { 460 tx, err := t.resolve(ctx) 461 if err != nil || tx == nil { 462 return hexutil.Big{}, err 463 } 464 _, _, s := tx.RawSignatureValues() 465 return hexutil.Big(*s), nil 466 } 467 468 func (t *Transaction) V(ctx context.Context) (hexutil.Big, error) { 469 tx, err := t.resolve(ctx) 470 if err != nil || tx == nil { 471 return hexutil.Big{}, err 472 } 473 v, _, _ := tx.RawSignatureValues() 474 return hexutil.Big(*v), nil 475 } 476 477 type BlockType int 478 479 // Block represents an Ethereum block. 480 // backend, and numberOrHash are mandatory. All other fields are lazily fetched 481 // when required. 482 type Block struct { 483 backend ethapi.Backend 484 numberOrHash *rpc.BlockNumberOrHash 485 hash common.Hash 486 header *types.Header 487 block *types.Block 488 receipts []*types.Receipt 489 } 490 491 // resolve returns the internal Block object representing this block, fetching 492 // it if necessary. 493 func (b *Block) resolve(ctx context.Context) (*types.Block, error) { 494 if b.block != nil { 495 return b.block, nil 496 } 497 if b.numberOrHash == nil { 498 latest := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) 499 b.numberOrHash = &latest 500 } 501 var err error 502 b.block, err = b.backend.BlockByNumberOrHash(ctx, *b.numberOrHash) 503 if b.block != nil && b.header == nil { 504 b.header = b.block.Header() 505 if hash, ok := b.numberOrHash.Hash(); ok { 506 b.hash = hash 507 } 508 } 509 return b.block, err 510 } 511 512 // resolveHeader returns the internal Header object for this block, fetching it 513 // if necessary. Call this function instead of `resolve` unless you need the 514 // additional data (transactions and uncles). 515 func (b *Block) resolveHeader(ctx context.Context) (*types.Header, error) { 516 if b.numberOrHash == nil && b.hash == (common.Hash{}) { 517 return nil, errBlockInvariant 518 } 519 var err error 520 if b.header == nil { 521 if b.hash != (common.Hash{}) { 522 b.header, err = b.backend.HeaderByHash(ctx, b.hash) 523 } else { 524 b.header, err = b.backend.HeaderByNumberOrHash(ctx, *b.numberOrHash) 525 } 526 } 527 return b.header, err 528 } 529 530 // resolveReceipts returns the list of receipts for this block, fetching them 531 // if necessary. 532 func (b *Block) resolveReceipts(ctx context.Context) ([]*types.Receipt, error) { 533 if b.receipts == nil { 534 hash := b.hash 535 if hash == (common.Hash{}) { 536 header, err := b.resolveHeader(ctx) 537 if err != nil { 538 return nil, err 539 } 540 hash = header.Hash() 541 } 542 receipts, err := b.backend.GetReceipts(ctx, hash) 543 if err != nil { 544 return nil, err 545 } 546 b.receipts = receipts 547 } 548 return b.receipts, nil 549 } 550 551 func (b *Block) Number(ctx context.Context) (Long, error) { 552 header, err := b.resolveHeader(ctx) 553 if err != nil { 554 return 0, err 555 } 556 557 return Long(header.Number.Uint64()), nil 558 } 559 560 func (b *Block) Hash(ctx context.Context) (common.Hash, error) { 561 if b.hash == (common.Hash{}) { 562 header, err := b.resolveHeader(ctx) 563 if err != nil { 564 return common.Hash{}, err 565 } 566 b.hash = header.Hash() 567 } 568 return b.hash, nil 569 } 570 571 func (b *Block) GasLimit(ctx context.Context) (Long, error) { 572 header, err := b.resolveHeader(ctx) 573 if err != nil { 574 return 0, err 575 } 576 return Long(header.GasLimit), nil 577 } 578 579 func (b *Block) GasUsed(ctx context.Context) (Long, error) { 580 header, err := b.resolveHeader(ctx) 581 if err != nil { 582 return 0, err 583 } 584 return Long(header.GasUsed), nil 585 } 586 587 func (b *Block) BaseFeePerGas(ctx context.Context) (*hexutil.Big, error) { 588 header, err := b.resolveHeader(ctx) 589 if err != nil { 590 return nil, err 591 } 592 if header.BaseFee == nil { 593 return nil, nil 594 } 595 return (*hexutil.Big)(header.BaseFee), nil 596 } 597 598 func (b *Block) Parent(ctx context.Context) (*Block, error) { 599 // If the block header hasn't been fetched, and we'll need it, fetch it. 600 if b.numberOrHash == nil && b.header == nil { 601 if _, err := b.resolveHeader(ctx); err != nil { 602 return nil, err 603 } 604 } 605 if b.header != nil && b.header.Number.Uint64() > 0 { 606 num := rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(b.header.Number.Uint64() - 1)) 607 return &Block{ 608 backend: b.backend, 609 numberOrHash: &num, 610 hash: b.header.ParentHash, 611 }, nil 612 } 613 return nil, nil 614 } 615 616 func (b *Block) Difficulty(ctx context.Context) (hexutil.Big, error) { 617 header, err := b.resolveHeader(ctx) 618 if err != nil { 619 return hexutil.Big{}, err 620 } 621 return hexutil.Big(*header.Difficulty), nil 622 } 623 624 func (b *Block) Timestamp(ctx context.Context) (hexutil.Uint64, error) { 625 header, err := b.resolveHeader(ctx) 626 if err != nil { 627 return 0, err 628 } 629 return hexutil.Uint64(header.Time), nil 630 } 631 632 func (b *Block) Nonce(ctx context.Context) (hexutil.Bytes, error) { 633 header, err := b.resolveHeader(ctx) 634 if err != nil { 635 return hexutil.Bytes{}, err 636 } 637 return header.Nonce[:], nil 638 } 639 640 func (b *Block) MixHash(ctx context.Context) (common.Hash, error) { 641 header, err := b.resolveHeader(ctx) 642 if err != nil { 643 return common.Hash{}, err 644 } 645 return header.MixDigest, nil 646 } 647 648 func (b *Block) TransactionsRoot(ctx context.Context) (common.Hash, error) { 649 header, err := b.resolveHeader(ctx) 650 if err != nil { 651 return common.Hash{}, err 652 } 653 return header.TxHash, nil 654 } 655 656 func (b *Block) StateRoot(ctx context.Context) (common.Hash, error) { 657 header, err := b.resolveHeader(ctx) 658 if err != nil { 659 return common.Hash{}, err 660 } 661 return header.Root, nil 662 } 663 664 func (b *Block) ReceiptsRoot(ctx context.Context) (common.Hash, error) { 665 header, err := b.resolveHeader(ctx) 666 if err != nil { 667 return common.Hash{}, err 668 } 669 return header.ReceiptHash, nil 670 } 671 672 func (b *Block) OmmerHash(ctx context.Context) (common.Hash, error) { 673 header, err := b.resolveHeader(ctx) 674 if err != nil { 675 return common.Hash{}, err 676 } 677 return header.UncleHash, nil 678 } 679 680 func (b *Block) OmmerCount(ctx context.Context) (*int32, error) { 681 block, err := b.resolve(ctx) 682 if err != nil || block == nil { 683 return nil, err 684 } 685 count := int32(len(block.Uncles())) 686 return &count, err 687 } 688 689 func (b *Block) Ommers(ctx context.Context) (*[]*Block, error) { 690 block, err := b.resolve(ctx) 691 if err != nil || block == nil { 692 return nil, err 693 } 694 ret := make([]*Block, 0, len(block.Uncles())) 695 for _, uncle := range block.Uncles() { 696 blockNumberOrHash := rpc.BlockNumberOrHashWithHash(uncle.Hash(), false) 697 ret = append(ret, &Block{ 698 backend: b.backend, 699 numberOrHash: &blockNumberOrHash, 700 header: uncle, 701 }) 702 } 703 return &ret, nil 704 } 705 706 func (b *Block) ExtraData(ctx context.Context) (hexutil.Bytes, error) { 707 header, err := b.resolveHeader(ctx) 708 if err != nil { 709 return hexutil.Bytes{}, err 710 } 711 return header.Extra, nil 712 } 713 714 func (b *Block) LogsBloom(ctx context.Context) (hexutil.Bytes, error) { 715 header, err := b.resolveHeader(ctx) 716 if err != nil { 717 return hexutil.Bytes{}, err 718 } 719 return header.Bloom.Bytes(), nil 720 } 721 722 func (b *Block) TotalDifficulty(ctx context.Context) (hexutil.Big, error) { 723 h := b.hash 724 if h == (common.Hash{}) { 725 header, err := b.resolveHeader(ctx) 726 if err != nil { 727 return hexutil.Big{}, err 728 } 729 h = header.Hash() 730 } 731 td := b.backend.GetTd(ctx, h) 732 if td == nil { 733 return hexutil.Big{}, fmt.Errorf("total difficulty not found %x", b.hash) 734 } 735 return hexutil.Big(*td), nil 736 } 737 738 // BlockNumberArgs encapsulates arguments to accessors that specify a block number. 739 type BlockNumberArgs struct { 740 // TODO: Ideally we could use input unions to allow the query to specify the 741 // block parameter by hash, block number, or tag but input unions aren't part of the 742 // standard GraphQL schema SDL yet, see: https://github.com/graphql/graphql-spec/issues/488 743 Block *hexutil.Uint64 744 } 745 746 // NumberOr returns the provided block number argument, or the "current" block number or hash if none 747 // was provided. 748 func (a BlockNumberArgs) NumberOr(current rpc.BlockNumberOrHash) rpc.BlockNumberOrHash { 749 if a.Block != nil { 750 blockNr := rpc.BlockNumber(*a.Block) 751 return rpc.BlockNumberOrHashWithNumber(blockNr) 752 } 753 return current 754 } 755 756 // NumberOrLatest returns the provided block number argument, or the "latest" block number if none 757 // was provided. 758 func (a BlockNumberArgs) NumberOrLatest() rpc.BlockNumberOrHash { 759 return a.NumberOr(rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)) 760 } 761 762 func (b *Block) Miner(ctx context.Context, args BlockNumberArgs) (*Account, error) { 763 header, err := b.resolveHeader(ctx) 764 if err != nil { 765 return nil, err 766 } 767 return &Account{ 768 backend: b.backend, 769 address: header.Coinbase, 770 blockNrOrHash: args.NumberOrLatest(), 771 }, nil 772 } 773 774 func (b *Block) TransactionCount(ctx context.Context) (*int32, error) { 775 block, err := b.resolve(ctx) 776 if err != nil || block == nil { 777 return nil, err 778 } 779 count := int32(len(block.Transactions())) 780 return &count, err 781 } 782 783 func (b *Block) Transactions(ctx context.Context) (*[]*Transaction, error) { 784 block, err := b.resolve(ctx) 785 if err != nil || block == nil { 786 return nil, err 787 } 788 ret := make([]*Transaction, 0, len(block.Transactions())) 789 for i, tx := range block.Transactions() { 790 ret = append(ret, &Transaction{ 791 backend: b.backend, 792 hash: tx.Hash(), 793 tx: tx, 794 block: b, 795 index: uint64(i), 796 }) 797 } 798 return &ret, nil 799 } 800 801 func (b *Block) TransactionAt(ctx context.Context, args struct{ Index int32 }) (*Transaction, error) { 802 block, err := b.resolve(ctx) 803 if err != nil || block == nil { 804 return nil, err 805 } 806 txs := block.Transactions() 807 if args.Index < 0 || int(args.Index) >= len(txs) { 808 return nil, nil 809 } 810 tx := txs[args.Index] 811 return &Transaction{ 812 backend: b.backend, 813 hash: tx.Hash(), 814 tx: tx, 815 block: b, 816 index: uint64(args.Index), 817 }, nil 818 } 819 820 func (b *Block) OmmerAt(ctx context.Context, args struct{ Index int32 }) (*Block, error) { 821 block, err := b.resolve(ctx) 822 if err != nil || block == nil { 823 return nil, err 824 } 825 uncles := block.Uncles() 826 if args.Index < 0 || int(args.Index) >= len(uncles) { 827 return nil, nil 828 } 829 uncle := uncles[args.Index] 830 blockNumberOrHash := rpc.BlockNumberOrHashWithHash(uncle.Hash(), false) 831 return &Block{ 832 backend: b.backend, 833 numberOrHash: &blockNumberOrHash, 834 header: uncle, 835 }, nil 836 } 837 838 // BlockFilterCriteria encapsulates criteria passed to a `logs` accessor inside 839 // a block. 840 type BlockFilterCriteria struct { 841 Addresses *[]common.Address // restricts matches to events created by specific contracts 842 843 // The Topic list restricts matches to particular event topics. Each event has a list 844 // of topics. Topics matches a prefix of that list. An empty element slice matches any 845 // topic. Non-empty elements represent an alternative that matches any of the 846 // contained topics. 847 // 848 // Examples: 849 // {} or nil matches any topic list 850 // {{A}} matches topic A in first position 851 // {{}, {B}} matches any topic in first position, B in second position 852 // {{A}, {B}} matches topic A in first position, B in second position 853 // {{A, B}}, {C, D}} matches topic (A OR B) in first position, (C OR D) in second position 854 Topics *[][]common.Hash 855 } 856 857 // runFilter accepts a filter and executes it, returning all its results as 858 // `Log` objects. 859 func runFilter(ctx context.Context, be ethapi.Backend, filter *filters.Filter) ([]*Log, error) { 860 logs, err := filter.Logs(ctx) 861 if err != nil || logs == nil { 862 return nil, err 863 } 864 ret := make([]*Log, 0, len(logs)) 865 for _, log := range logs { 866 ret = append(ret, &Log{ 867 backend: be, 868 transaction: &Transaction{backend: be, hash: log.TxHash}, 869 log: log, 870 }) 871 } 872 return ret, nil 873 } 874 875 func (b *Block) Logs(ctx context.Context, args struct{ Filter BlockFilterCriteria }) ([]*Log, error) { 876 var addresses []common.Address 877 if args.Filter.Addresses != nil { 878 addresses = *args.Filter.Addresses 879 } 880 var topics [][]common.Hash 881 if args.Filter.Topics != nil { 882 topics = *args.Filter.Topics 883 } 884 hash := b.hash 885 if hash == (common.Hash{}) { 886 header, err := b.resolveHeader(ctx) 887 if err != nil { 888 return nil, err 889 } 890 hash = header.Hash() 891 } 892 // Construct the range filter 893 filter := filters.NewBlockFilter(b.backend, hash, addresses, topics) 894 895 // Run the filter and return all the logs 896 return runFilter(ctx, b.backend, filter) 897 } 898 899 func (b *Block) Account(ctx context.Context, args struct { 900 Address common.Address 901 }) (*Account, error) { 902 if b.numberOrHash == nil { 903 _, err := b.resolveHeader(ctx) 904 if err != nil { 905 return nil, err 906 } 907 } 908 return &Account{ 909 backend: b.backend, 910 address: args.Address, 911 blockNrOrHash: *b.numberOrHash, 912 }, nil 913 } 914 915 // CallData encapsulates arguments to `call` or `estimateGas`. 916 // All arguments are optional. 917 type CallData struct { 918 From *common.Address // The Ethereum address the call is from. 919 To *common.Address // The Ethereum address the call is to. 920 Gas *hexutil.Uint64 // The amount of gas provided for the call. 921 GasPrice *hexutil.Big // The price of each unit of gas, in wei. 922 MaxFeePerGas *hexutil.Big // The max price of each unit of gas, in wei (1559). 923 MaxPriorityFeePerGas *hexutil.Big // The max tip of each unit of gas, in wei (1559). 924 Value *hexutil.Big // The value sent along with the call. 925 Data *hexutil.Bytes // Any data sent with the call. 926 } 927 928 // CallResult encapsulates the result of an invocation of the `call` accessor. 929 type CallResult struct { 930 data hexutil.Bytes // The return data from the call 931 gasUsed Long // The amount of gas used 932 status Long // The return status of the call - 0 for failure or 1 for success. 933 } 934 935 func (c *CallResult) Data() hexutil.Bytes { 936 return c.data 937 } 938 939 func (c *CallResult) GasUsed() Long { 940 return c.gasUsed 941 } 942 943 func (c *CallResult) Status() Long { 944 return c.status 945 } 946 947 func (b *Block) Call(ctx context.Context, args struct { 948 Data ethapi.TransactionArgs 949 }) (*CallResult, error) { 950 if b.numberOrHash == nil { 951 _, err := b.resolve(ctx) 952 if err != nil { 953 return nil, err 954 } 955 } 956 result, err := ethapi.DoCall(ctx, b.backend, args.Data, *b.numberOrHash, nil, 5*time.Second, b.backend.RPCGasCap()) 957 if err != nil { 958 return nil, err 959 } 960 status := Long(1) 961 if result.Failed() { 962 status = 0 963 } 964 965 return &CallResult{ 966 data: result.ReturnData, 967 gasUsed: Long(result.UsedGas), 968 status: status, 969 }, nil 970 } 971 972 func (b *Block) EstimateGas(ctx context.Context, args struct { 973 Data ethapi.TransactionArgs 974 }) (Long, error) { 975 if b.numberOrHash == nil { 976 _, err := b.resolveHeader(ctx) 977 if err != nil { 978 return 0, err 979 } 980 } 981 gas, err := ethapi.DoEstimateGas(ctx, b.backend, args.Data, *b.numberOrHash, b.backend.RPCGasCap()) 982 return Long(gas), err 983 } 984 985 type Pending struct { 986 backend ethapi.Backend 987 } 988 989 func (p *Pending) TransactionCount(ctx context.Context) (int32, error) { 990 txs, err := p.backend.GetPoolTransactions() 991 return int32(len(txs)), err 992 } 993 994 func (p *Pending) Transactions(ctx context.Context) (*[]*Transaction, error) { 995 txs, err := p.backend.GetPoolTransactions() 996 if err != nil { 997 return nil, err 998 } 999 ret := make([]*Transaction, 0, len(txs)) 1000 for i, tx := range txs { 1001 ret = append(ret, &Transaction{ 1002 backend: p.backend, 1003 hash: tx.Hash(), 1004 tx: tx, 1005 index: uint64(i), 1006 }) 1007 } 1008 return &ret, nil 1009 } 1010 1011 func (p *Pending) Account(ctx context.Context, args struct { 1012 Address common.Address 1013 }) *Account { 1014 pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) 1015 return &Account{ 1016 backend: p.backend, 1017 address: args.Address, 1018 blockNrOrHash: pendingBlockNr, 1019 } 1020 } 1021 1022 func (p *Pending) Call(ctx context.Context, args struct { 1023 Data ethapi.TransactionArgs 1024 }) (*CallResult, error) { 1025 pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) 1026 result, err := ethapi.DoCall(ctx, p.backend, args.Data, pendingBlockNr, nil, 5*time.Second, p.backend.RPCGasCap()) 1027 if err != nil { 1028 return nil, err 1029 } 1030 status := Long(1) 1031 if result.Failed() { 1032 status = 0 1033 } 1034 1035 return &CallResult{ 1036 data: result.ReturnData, 1037 gasUsed: Long(result.UsedGas), 1038 status: status, 1039 }, nil 1040 } 1041 1042 func (p *Pending) EstimateGas(ctx context.Context, args struct { 1043 Data ethapi.TransactionArgs 1044 }) (Long, error) { 1045 pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) 1046 gas, err := ethapi.DoEstimateGas(ctx, p.backend, args.Data, pendingBlockNr, p.backend.RPCGasCap()) 1047 return Long(gas), err 1048 } 1049 1050 // Resolver is the top-level object in the GraphQL hierarchy. 1051 type Resolver struct { 1052 backend ethapi.Backend 1053 } 1054 1055 func (r *Resolver) Block(ctx context.Context, args struct { 1056 Number *Long 1057 Hash *common.Hash 1058 }) (*Block, error) { 1059 var block *Block 1060 if args.Number != nil { 1061 if *args.Number < 0 { 1062 return nil, nil 1063 } 1064 number := rpc.BlockNumber(*args.Number) 1065 numberOrHash := rpc.BlockNumberOrHashWithNumber(number) 1066 block = &Block{ 1067 backend: r.backend, 1068 numberOrHash: &numberOrHash, 1069 } 1070 } else if args.Hash != nil { 1071 numberOrHash := rpc.BlockNumberOrHashWithHash(*args.Hash, false) 1072 block = &Block{ 1073 backend: r.backend, 1074 numberOrHash: &numberOrHash, 1075 } 1076 } else { 1077 numberOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) 1078 block = &Block{ 1079 backend: r.backend, 1080 numberOrHash: &numberOrHash, 1081 } 1082 } 1083 // Resolve the header, return nil if it doesn't exist. 1084 // Note we don't resolve block directly here since it will require an 1085 // additional network request for light client. 1086 h, err := block.resolveHeader(ctx) 1087 if err != nil { 1088 return nil, err 1089 } else if h == nil { 1090 return nil, nil 1091 } 1092 return block, nil 1093 } 1094 1095 func (r *Resolver) Blocks(ctx context.Context, args struct { 1096 From *Long 1097 To *Long 1098 }) ([]*Block, error) { 1099 from := rpc.BlockNumber(*args.From) 1100 1101 var to rpc.BlockNumber 1102 if args.To != nil { 1103 to = rpc.BlockNumber(*args.To) 1104 } else { 1105 to = rpc.BlockNumber(r.backend.CurrentBlock().Number().Int64()) 1106 } 1107 if to < from { 1108 return []*Block{}, nil 1109 } 1110 ret := make([]*Block, 0, to-from+1) 1111 for i := from; i <= to; i++ { 1112 numberOrHash := rpc.BlockNumberOrHashWithNumber(i) 1113 ret = append(ret, &Block{ 1114 backend: r.backend, 1115 numberOrHash: &numberOrHash, 1116 }) 1117 } 1118 return ret, nil 1119 } 1120 1121 func (r *Resolver) Pending(ctx context.Context) *Pending { 1122 return &Pending{r.backend} 1123 } 1124 1125 func (r *Resolver) Transaction(ctx context.Context, args struct{ Hash common.Hash }) (*Transaction, error) { 1126 tx := &Transaction{ 1127 backend: r.backend, 1128 hash: args.Hash, 1129 } 1130 // Resolve the transaction; if it doesn't exist, return nil. 1131 t, err := tx.resolve(ctx) 1132 if err != nil { 1133 return nil, err 1134 } else if t == nil { 1135 return nil, nil 1136 } 1137 return tx, nil 1138 } 1139 1140 func (r *Resolver) SendRawTransaction(ctx context.Context, args struct{ Data hexutil.Bytes }) (common.Hash, error) { 1141 tx := new(types.Transaction) 1142 if err := tx.UnmarshalBinary(args.Data); err != nil { 1143 return common.Hash{}, err 1144 } 1145 hash, err := ethapi.SubmitTransaction(ctx, r.backend, tx) 1146 return hash, err 1147 } 1148 1149 // FilterCriteria encapsulates the arguments to `logs` on the root resolver object. 1150 type FilterCriteria struct { 1151 FromBlock *hexutil.Uint64 // beginning of the queried range, nil means genesis block 1152 ToBlock *hexutil.Uint64 // end of the range, nil means latest block 1153 Addresses *[]common.Address // restricts matches to events created by specific contracts 1154 1155 // The Topic list restricts matches to particular event topics. Each event has a list 1156 // of topics. Topics matches a prefix of that list. An empty element slice matches any 1157 // topic. Non-empty elements represent an alternative that matches any of the 1158 // contained topics. 1159 // 1160 // Examples: 1161 // {} or nil matches any topic list 1162 // {{A}} matches topic A in first position 1163 // {{}, {B}} matches any topic in first position, B in second position 1164 // {{A}, {B}} matches topic A in first position, B in second position 1165 // {{A, B}}, {C, D}} matches topic (A OR B) in first position, (C OR D) in second position 1166 Topics *[][]common.Hash 1167 } 1168 1169 func (r *Resolver) Logs(ctx context.Context, args struct{ Filter FilterCriteria }) ([]*Log, error) { 1170 // Convert the RPC block numbers into internal representations 1171 begin := rpc.LatestBlockNumber.Int64() 1172 if args.Filter.FromBlock != nil { 1173 begin = int64(*args.Filter.FromBlock) 1174 } 1175 end := rpc.LatestBlockNumber.Int64() 1176 if args.Filter.ToBlock != nil { 1177 end = int64(*args.Filter.ToBlock) 1178 } 1179 var addresses []common.Address 1180 if args.Filter.Addresses != nil { 1181 addresses = *args.Filter.Addresses 1182 } 1183 var topics [][]common.Hash 1184 if args.Filter.Topics != nil { 1185 topics = *args.Filter.Topics 1186 } 1187 // Construct the range filter 1188 filter := filters.NewRangeFilter(filters.Backend(r.backend), begin, end, addresses, topics) 1189 return runFilter(ctx, r.backend, filter) 1190 } 1191 1192 func (r *Resolver) GasPrice(ctx context.Context) (hexutil.Big, error) { 1193 tipcap, err := r.backend.SuggestGasTipCap(ctx) 1194 if err != nil { 1195 return hexutil.Big{}, err 1196 } 1197 if head := r.backend.CurrentHeader(); head.BaseFee != nil { 1198 tipcap.Add(tipcap, head.BaseFee) 1199 } 1200 return (hexutil.Big)(*tipcap), nil 1201 } 1202 1203 func (r *Resolver) MaxPriorityFeePerGas(ctx context.Context) (hexutil.Big, error) { 1204 tipcap, err := r.backend.SuggestGasTipCap(ctx) 1205 if err != nil { 1206 return hexutil.Big{}, err 1207 } 1208 return (hexutil.Big)(*tipcap), nil 1209 } 1210 1211 func (r *Resolver) ChainID(ctx context.Context) (hexutil.Big, error) { 1212 return hexutil.Big(*r.backend.ChainConfig().ChainID), nil 1213 } 1214 1215 // SyncState represents the synchronisation status returned from the `syncing` accessor. 1216 type SyncState struct { 1217 progress ethereum.SyncProgress 1218 } 1219 1220 func (s *SyncState) StartingBlock() hexutil.Uint64 { 1221 return hexutil.Uint64(s.progress.StartingBlock) 1222 } 1223 1224 func (s *SyncState) CurrentBlock() hexutil.Uint64 { 1225 return hexutil.Uint64(s.progress.CurrentBlock) 1226 } 1227 1228 func (s *SyncState) HighestBlock() hexutil.Uint64 { 1229 return hexutil.Uint64(s.progress.HighestBlock) 1230 } 1231 1232 func (s *SyncState) PulledStates() *hexutil.Uint64 { 1233 ret := hexutil.Uint64(s.progress.PulledStates) 1234 return &ret 1235 } 1236 1237 func (s *SyncState) KnownStates() *hexutil.Uint64 { 1238 ret := hexutil.Uint64(s.progress.KnownStates) 1239 return &ret 1240 } 1241 1242 // Syncing returns false in case the node is currently not syncing with the network. It can be up to date or has not 1243 // yet received the latest block headers from its pears. In case it is synchronizing: 1244 // - startingBlock: block number this node started to synchronise from 1245 // - currentBlock: block number this node is currently importing 1246 // - highestBlock: block number of the highest block header this node has received from peers 1247 // - pulledStates: number of state entries processed until now 1248 // - knownStates: number of known state entries that still need to be pulled 1249 func (r *Resolver) Syncing() (*SyncState, error) { 1250 progress := r.backend.Downloader().Progress() 1251 1252 // Return not syncing if the synchronisation already completed 1253 if progress.CurrentBlock >= progress.HighestBlock { 1254 return nil, nil 1255 } 1256 // Otherwise gather the block sync stats 1257 return &SyncState{progress}, nil 1258 }