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