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