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