github.com/core-coin/go-core/v2@v2.1.9/graphql/graphql.go (about) 1 // Copyright 2019 by the Authors 2 // This file is part of the go-core library. 3 // 4 // The go-core 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-core 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-core library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package graphql provides a GraphQL interface to Core node data. 18 package graphql 19 20 import ( 21 "context" 22 "errors" 23 "math/big" 24 "time" 25 26 "github.com/core-coin/go-core/v2/internal/xcbapi" 27 28 core "github.com/core-coin/go-core/v2" 29 "github.com/core-coin/go-core/v2/common" 30 "github.com/core-coin/go-core/v2/common/hexutil" 31 "github.com/core-coin/go-core/v2/core/rawdb" 32 "github.com/core-coin/go-core/v2/core/state" 33 "github.com/core-coin/go-core/v2/core/types" 34 "github.com/core-coin/go-core/v2/core/vm" 35 "github.com/core-coin/go-core/v2/rlp" 36 "github.com/core-coin/go-core/v2/rpc" 37 "github.com/core-coin/go-core/v2/xcb/filters" 38 ) 39 40 var ( 41 errBlockInvariant = errors.New("block objects must be instantiated with at least one of num or hash") 42 ) 43 44 // Account represents an Core account at a particular block. 45 type Account struct { 46 backend xcbapi.Backend 47 address common.Address 48 blockNrOrHash rpc.BlockNumberOrHash 49 } 50 51 // getState fetches the StateDB object for an account. 52 func (a *Account) getState(ctx context.Context) (*state.StateDB, error) { 53 state, _, err := a.backend.StateAndHeaderByNumberOrHash(ctx, a.blockNrOrHash) 54 return state, err 55 } 56 57 func (a *Account) Address(ctx context.Context) (common.Address, error) { 58 return a.address, nil 59 } 60 61 func (a *Account) Balance(ctx context.Context) (hexutil.Big, error) { 62 state, err := a.getState(ctx) 63 if err != nil { 64 return hexutil.Big{}, err 65 } 66 return hexutil.Big(*state.GetBalance(a.address)), nil 67 } 68 69 func (a *Account) TransactionCount(ctx context.Context) (hexutil.Uint64, error) { 70 state, err := a.getState(ctx) 71 if err != nil { 72 return 0, err 73 } 74 return hexutil.Uint64(state.GetNonce(a.address)), nil 75 } 76 77 func (a *Account) Code(ctx context.Context) (hexutil.Bytes, error) { 78 state, err := a.getState(ctx) 79 if err != nil { 80 return hexutil.Bytes{}, err 81 } 82 return state.GetCode(a.address), nil 83 } 84 85 func (a *Account) Storage(ctx context.Context, args struct{ Slot common.Hash }) (common.Hash, error) { 86 state, err := a.getState(ctx) 87 if err != nil { 88 return common.Hash{}, err 89 } 90 return state.GetState(a.address, args.Slot), nil 91 } 92 93 // Log represents an individual log message. All arguments are mandatory. 94 type Log struct { 95 backend xcbapi.Backend 96 transaction *Transaction 97 log *types.Log 98 } 99 100 func (l *Log) Transaction(ctx context.Context) *Transaction { 101 return l.transaction 102 } 103 104 func (l *Log) Account(ctx context.Context, args BlockNumberArgs) *Account { 105 return &Account{ 106 backend: l.backend, 107 address: l.log.Address, 108 blockNrOrHash: args.NumberOrLatest(), 109 } 110 } 111 112 func (l *Log) Index(ctx context.Context) int32 { 113 return int32(l.log.Index) 114 } 115 116 func (l *Log) Topics(ctx context.Context) []common.Hash { 117 return l.log.Topics 118 } 119 120 func (l *Log) Data(ctx context.Context) hexutil.Bytes { 121 return l.log.Data 122 } 123 124 // Transaction represents an Core transaction. 125 // backend and hash are mandatory; all others will be fetched when required. 126 type Transaction struct { 127 backend xcbapi.Backend 128 hash common.Hash 129 tx *types.Transaction 130 block *Block 131 index uint64 132 } 133 134 // resolve returns the internal transaction object, fetching it if needed. 135 func (t *Transaction) resolve(ctx context.Context) (*types.Transaction, error) { 136 if t.tx == nil { 137 tx, blockHash, _, index := rawdb.ReadTransaction(t.backend.ChainDb(), t.hash) 138 if tx != nil { 139 t.tx = tx 140 blockNrOrHash := rpc.BlockNumberOrHashWithHash(blockHash, false) 141 t.block = &Block{ 142 backend: t.backend, 143 numberOrHash: &blockNrOrHash, 144 } 145 t.index = index 146 } else { 147 t.tx = t.backend.GetPoolTransaction(t.hash) 148 } 149 } 150 return t.tx, nil 151 } 152 153 func (t *Transaction) Hash(ctx context.Context) common.Hash { 154 return t.hash 155 } 156 157 func (t *Transaction) InputData(ctx context.Context) (hexutil.Bytes, error) { 158 tx, err := t.resolve(ctx) 159 if err != nil || tx == nil { 160 return hexutil.Bytes{}, err 161 } 162 return tx.Data(), nil 163 } 164 165 func (t *Transaction) Energy(ctx context.Context) (hexutil.Uint64, error) { 166 tx, err := t.resolve(ctx) 167 if err != nil || tx == nil { 168 return 0, err 169 } 170 return hexutil.Uint64(tx.Energy()), nil 171 } 172 173 func (t *Transaction) EnergyPrice(ctx context.Context) (hexutil.Big, error) { 174 tx, err := t.resolve(ctx) 175 if err != nil || tx == nil { 176 return hexutil.Big{}, err 177 } 178 return hexutil.Big(*tx.EnergyPrice()), nil 179 } 180 181 func (t *Transaction) Value(ctx context.Context) (hexutil.Big, error) { 182 tx, err := t.resolve(ctx) 183 if err != nil || tx == nil { 184 return hexutil.Big{}, err 185 } 186 return hexutil.Big(*tx.Value()), nil 187 } 188 189 func (t *Transaction) Nonce(ctx context.Context) (hexutil.Uint64, error) { 190 tx, err := t.resolve(ctx) 191 if err != nil || tx == nil { 192 return 0, err 193 } 194 return hexutil.Uint64(tx.Nonce()), nil 195 } 196 197 func (t *Transaction) To(ctx context.Context, args BlockNumberArgs) (*Account, error) { 198 tx, err := t.resolve(ctx) 199 if err != nil || tx == nil { 200 return nil, err 201 } 202 to := tx.To() 203 if to == nil { 204 return nil, nil 205 } 206 return &Account{ 207 backend: t.backend, 208 address: *to, 209 blockNrOrHash: args.NumberOrLatest(), 210 }, nil 211 } 212 213 func (t *Transaction) From(ctx context.Context, args BlockNumberArgs) (*Account, error) { 214 tx, err := t.resolve(ctx) 215 if err != nil || tx == nil { 216 return nil, err 217 } 218 signer := types.NewNucleusSigner(big.NewInt(int64(tx.NetworkID()))) 219 from, err := types.Sender(signer, tx) 220 if err != nil { 221 return nil, err 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) EnergyUsed(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.EnergyUsed) 278 return &ret, nil 279 } 280 281 func (t *Transaction) CumulativeEnergyUsed(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.CumulativeEnergyUsed) 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 Core block. 321 // backend, and numberOrHash are mandatory. All other fields are lazily fetched 322 // when required. 323 type Block struct { 324 backend xcbapi.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 = 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) EnergyLimit(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.EnergyLimit), nil 418 } 419 420 func (b *Block) EnergyUsed(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.EnergyUsed), 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 header.Nonce[:], nil 468 } 469 470 func (b *Block) TransactionsRoot(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.TxHash, nil 476 } 477 478 func (b *Block) StateRoot(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.Root, nil 484 } 485 486 func (b *Block) ReceiptsRoot(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.ReceiptHash, nil 492 } 493 494 func (b *Block) OmmerHash(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.UncleHash, nil 500 } 501 502 func (b *Block) OmmerCount(ctx context.Context) (*int32, error) { 503 block, err := b.resolve(ctx) 504 if err != nil || block == nil { 505 return nil, err 506 } 507 count := int32(len(block.Uncles())) 508 return &count, err 509 } 510 511 func (b *Block) Ommers(ctx context.Context) (*[]*Block, error) { 512 block, err := b.resolve(ctx) 513 if err != nil || block == nil { 514 return nil, err 515 } 516 ret := make([]*Block, 0, len(block.Uncles())) 517 for _, uncle := range block.Uncles() { 518 blockNumberOrHash := rpc.BlockNumberOrHashWithHash(uncle.Hash(), false) 519 ret = append(ret, &Block{ 520 backend: b.backend, 521 numberOrHash: &blockNumberOrHash, 522 header: uncle, 523 }) 524 } 525 return &ret, nil 526 } 527 528 func (b *Block) ExtraData(ctx context.Context) (hexutil.Bytes, error) { 529 header, err := b.resolveHeader(ctx) 530 if err != nil { 531 return hexutil.Bytes{}, err 532 } 533 return header.Extra, nil 534 } 535 536 func (b *Block) LogsBloom(ctx context.Context) (hexutil.Bytes, error) { 537 header, err := b.resolveHeader(ctx) 538 if err != nil { 539 return hexutil.Bytes{}, err 540 } 541 return header.Bloom.Bytes(), nil 542 } 543 544 func (b *Block) TotalDifficulty(ctx context.Context) (hexutil.Big, error) { 545 h := b.hash 546 if h == (common.Hash{}) { 547 header, err := b.resolveHeader(ctx) 548 if err != nil { 549 return hexutil.Big{}, err 550 } 551 h = header.Hash() 552 } 553 return hexutil.Big(*b.backend.GetTd(ctx, h)), nil 554 } 555 556 // BlockNumberArgs encapsulates arguments to accessors that specify a block number. 557 type BlockNumberArgs struct { 558 // TODO: Ideally we could use input unions to allow the query to specify the 559 // block parameter by hash, block number, or tag but input unions aren't part of the 560 // standard GraphQL schema SDL yet, see: https://github.com/graphql/graphql-spec/issues/488 561 Block *hexutil.Uint64 562 } 563 564 // NumberOr returns the provided block number argument, or the "current" block number or hash if none 565 // was provided. 566 func (a BlockNumberArgs) NumberOr(current rpc.BlockNumberOrHash) rpc.BlockNumberOrHash { 567 if a.Block != nil { 568 blockNr := rpc.BlockNumber(*a.Block) 569 return rpc.BlockNumberOrHashWithNumber(blockNr) 570 } 571 return current 572 } 573 574 // NumberOrLatest returns the provided block number argument, or the "latest" block number if none 575 // was provided. 576 func (a BlockNumberArgs) NumberOrLatest() rpc.BlockNumberOrHash { 577 return a.NumberOr(rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)) 578 } 579 580 func (b *Block) Miner(ctx context.Context, args BlockNumberArgs) (*Account, error) { 581 header, err := b.resolveHeader(ctx) 582 if err != nil { 583 return nil, err 584 } 585 return &Account{ 586 backend: b.backend, 587 address: header.Coinbase, 588 blockNrOrHash: args.NumberOrLatest(), 589 }, nil 590 } 591 592 func (b *Block) TransactionCount(ctx context.Context) (*int32, error) { 593 block, err := b.resolve(ctx) 594 if err != nil || block == nil { 595 return nil, err 596 } 597 count := int32(len(block.Transactions())) 598 return &count, err 599 } 600 601 func (b *Block) Transactions(ctx context.Context) (*[]*Transaction, error) { 602 block, err := b.resolve(ctx) 603 if err != nil || block == nil { 604 return nil, err 605 } 606 ret := make([]*Transaction, 0, len(block.Transactions())) 607 for i, tx := range block.Transactions() { 608 ret = append(ret, &Transaction{ 609 backend: b.backend, 610 hash: tx.Hash(), 611 tx: tx, 612 block: b, 613 index: uint64(i), 614 }) 615 } 616 return &ret, nil 617 } 618 619 func (b *Block) TransactionAt(ctx context.Context, args struct{ Index int32 }) (*Transaction, error) { 620 block, err := b.resolve(ctx) 621 if err != nil || block == nil { 622 return nil, err 623 } 624 txs := block.Transactions() 625 if args.Index < 0 || int(args.Index) >= len(txs) { 626 return nil, nil 627 } 628 tx := txs[args.Index] 629 return &Transaction{ 630 backend: b.backend, 631 hash: tx.Hash(), 632 tx: tx, 633 block: b, 634 index: uint64(args.Index), 635 }, nil 636 } 637 638 func (b *Block) OmmerAt(ctx context.Context, args struct{ Index int32 }) (*Block, error) { 639 block, err := b.resolve(ctx) 640 if err != nil || block == nil { 641 return nil, err 642 } 643 uncles := block.Uncles() 644 if args.Index < 0 || int(args.Index) >= len(uncles) { 645 return nil, nil 646 } 647 uncle := uncles[args.Index] 648 blockNumberOrHash := rpc.BlockNumberOrHashWithHash(uncle.Hash(), false) 649 return &Block{ 650 backend: b.backend, 651 numberOrHash: &blockNumberOrHash, 652 header: uncle, 653 }, nil 654 } 655 656 // BlockFilterCriteria encapsulates criteria passed to a `logs` accessor inside 657 // a block. 658 type BlockFilterCriteria struct { 659 Addresses *[]common.Address // restricts matches to events created by specific contracts 660 661 // The Topic list restricts matches to particular event topics. Each event has a list 662 // of topics. Topics matches a prefix of that list. An empty element slice matches any 663 // topic. Non-empty elements represent an alternative that matches any of the 664 // contained topics. 665 // 666 // Examples: 667 // {} or nil matches any topic list 668 // {{A}} matches topic A in first position 669 // {{}, {B}} matches any topic in first position, B in second position 670 // {{A}, {B}} matches topic A in first position, B in second position 671 // {{A, B}}, {C, D}} matches topic (A OR B) in first position, (C OR D) in second position 672 Topics *[][]common.Hash 673 } 674 675 // runFilter accepts a filter and executes it, returning all its results as 676 // `Log` objects. 677 func runFilter(ctx context.Context, be xcbapi.Backend, filter *filters.Filter) ([]*Log, error) { 678 logs, err := filter.Logs(ctx) 679 if err != nil || logs == nil { 680 return nil, err 681 } 682 ret := make([]*Log, 0, len(logs)) 683 for _, log := range logs { 684 ret = append(ret, &Log{ 685 backend: be, 686 transaction: &Transaction{backend: be, hash: log.TxHash}, 687 log: log, 688 }) 689 } 690 return ret, nil 691 } 692 693 func (b *Block) Logs(ctx context.Context, args struct{ Filter BlockFilterCriteria }) ([]*Log, error) { 694 var addresses []common.Address 695 if args.Filter.Addresses != nil { 696 addresses = *args.Filter.Addresses 697 } 698 var topics [][]common.Hash 699 if args.Filter.Topics != nil { 700 topics = *args.Filter.Topics 701 } 702 hash := b.hash 703 if hash == (common.Hash{}) { 704 header, err := b.resolveHeader(ctx) 705 if err != nil { 706 return nil, err 707 } 708 hash = header.Hash() 709 } 710 // Construct the range filter 711 filter := filters.NewBlockFilter(b.backend, hash, addresses, topics) 712 713 // Run the filter and return all the logs 714 return runFilter(ctx, b.backend, filter) 715 } 716 717 func (b *Block) Account(ctx context.Context, args struct { 718 Address common.Address 719 }) (*Account, error) { 720 if b.numberOrHash == nil { 721 _, err := b.resolveHeader(ctx) 722 if err != nil { 723 return nil, err 724 } 725 } 726 return &Account{ 727 backend: b.backend, 728 address: args.Address, 729 blockNrOrHash: *b.numberOrHash, 730 }, nil 731 } 732 733 // CallData encapsulates arguments to `call` or `estimateEnergy`. 734 // All arguments are optional. 735 type CallData struct { 736 From *common.Address // The Core address the call is from. 737 To *common.Address // The Core address the call is to. 738 Energy *hexutil.Uint64 // The amount of energy provided for the call. 739 EnergyPrice *hexutil.Big // The price of each unit of energy, in ore. 740 Value *hexutil.Big // The value sent along with the call. 741 Data *hexutil.Bytes // Any data sent with the call. 742 } 743 744 // CallResult encapsulates the result of an invocation of the `call` accessor. 745 type CallResult struct { 746 data hexutil.Bytes // The return data from the call 747 energyUsed hexutil.Uint64 // The amount of energy used 748 status hexutil.Uint64 // The return status of the call - 0 for failure or 1 for success. 749 } 750 751 func (c *CallResult) Data() hexutil.Bytes { 752 return c.data 753 } 754 755 func (c *CallResult) EnergyUsed() hexutil.Uint64 { 756 return c.energyUsed 757 } 758 759 func (c *CallResult) Status() hexutil.Uint64 { 760 return c.status 761 } 762 763 func (b *Block) Call(ctx context.Context, args struct { 764 Data xcbapi.CallArgs 765 }) (*CallResult, error) { 766 if b.numberOrHash == nil { 767 _, err := b.resolve(ctx) 768 if err != nil { 769 return nil, err 770 } 771 } 772 result, err := xcbapi.DoCall(ctx, b.backend, args.Data, *b.numberOrHash, nil, vm.Config{}, 5*time.Second, b.backend.RPCEnergyCap()) 773 if err != nil { 774 return nil, err 775 } 776 status := hexutil.Uint64(1) 777 if result.Failed() { 778 status = 0 779 } 780 781 return &CallResult{ 782 data: result.ReturnData, 783 energyUsed: hexutil.Uint64(result.UsedEnergy), 784 status: status, 785 }, nil 786 } 787 788 func (b *Block) EstimateEnergy(ctx context.Context, args struct { 789 Data xcbapi.CallArgs 790 }) (hexutil.Uint64, error) { 791 if b.numberOrHash == nil { 792 _, err := b.resolveHeader(ctx) 793 if err != nil { 794 return hexutil.Uint64(0), err 795 } 796 } 797 energy, err := xcbapi.DoEstimateEnergy(ctx, b.backend, args.Data, *b.numberOrHash, b.backend.RPCEnergyCap()) 798 return energy, err 799 } 800 801 type Pending struct { 802 backend xcbapi.Backend 803 } 804 805 func (p *Pending) TransactionCount(ctx context.Context) (int32, error) { 806 txs, err := p.backend.GetPoolTransactions() 807 return int32(len(txs)), err 808 } 809 810 func (p *Pending) Transactions(ctx context.Context) (*[]*Transaction, error) { 811 txs, err := p.backend.GetPoolTransactions() 812 if err != nil { 813 return nil, err 814 } 815 ret := make([]*Transaction, 0, len(txs)) 816 for i, tx := range txs { 817 ret = append(ret, &Transaction{ 818 backend: p.backend, 819 hash: tx.Hash(), 820 tx: tx, 821 index: uint64(i), 822 }) 823 } 824 return &ret, nil 825 } 826 827 func (p *Pending) Account(ctx context.Context, args struct { 828 Address common.Address 829 }) *Account { 830 pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) 831 return &Account{ 832 backend: p.backend, 833 address: args.Address, 834 blockNrOrHash: pendingBlockNr, 835 } 836 } 837 838 func (p *Pending) Call(ctx context.Context, args struct { 839 Data xcbapi.CallArgs 840 }) (*CallResult, error) { 841 pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) 842 result, err := xcbapi.DoCall(ctx, p.backend, args.Data, pendingBlockNr, nil, vm.Config{}, 5*time.Second, p.backend.RPCEnergyCap()) 843 if err != nil { 844 return nil, err 845 } 846 status := hexutil.Uint64(1) 847 if result.Failed() { 848 status = 0 849 } 850 851 return &CallResult{ 852 data: result.ReturnData, 853 energyUsed: hexutil.Uint64(result.UsedEnergy), 854 status: status, 855 }, nil 856 } 857 858 func (p *Pending) EstimateEnergy(ctx context.Context, args struct { 859 Data xcbapi.CallArgs 860 }) (hexutil.Uint64, error) { 861 pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber) 862 return xcbapi.DoEstimateEnergy(ctx, p.backend, args.Data, pendingBlockNr, p.backend.RPCEnergyCap()) 863 } 864 865 // Resolver is the top-level object in the GraphQL hierarchy. 866 type Resolver struct { 867 backend xcbapi.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(*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 := xcbapi.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) EnergyPrice(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 func (r *Resolver) NetworkID(ctx context.Context) (hexutil.Big, error) { 1014 return hexutil.Big(*r.backend.ChainConfig().NetworkID), nil 1015 } 1016 1017 // SyncState represents the synchronisation status returned from the `syncing` accessor. 1018 type SyncState struct { 1019 progress core.SyncProgress 1020 } 1021 1022 func (s *SyncState) StartingBlock() hexutil.Uint64 { 1023 return hexutil.Uint64(s.progress.StartingBlock) 1024 } 1025 1026 func (s *SyncState) CurrentBlock() hexutil.Uint64 { 1027 return hexutil.Uint64(s.progress.CurrentBlock) 1028 } 1029 1030 func (s *SyncState) HighestBlock() hexutil.Uint64 { 1031 return hexutil.Uint64(s.progress.HighestBlock) 1032 } 1033 1034 func (s *SyncState) PulledStates() *hexutil.Uint64 { 1035 ret := hexutil.Uint64(s.progress.PulledStates) 1036 return &ret 1037 } 1038 1039 func (s *SyncState) KnownStates() *hexutil.Uint64 { 1040 ret := hexutil.Uint64(s.progress.KnownStates) 1041 return &ret 1042 } 1043 1044 // Syncing returns false in case the node is currently not syncing with the network. It can be up to date or has not 1045 // yet received the latest block headers from its pears. In case it is synchronizing: 1046 // - startingBlock: block number this node started to synchronise from 1047 // - currentBlock: block number this node is currently importing 1048 // - highestBlock: block number of the highest block header this node has received from peers 1049 // - pulledStates: number of state entries processed until now 1050 // - knownStates: number of known state entries that still need to be pulled 1051 func (r *Resolver) Syncing() (*SyncState, error) { 1052 progress := r.backend.Downloader().Progress() 1053 1054 // Return not syncing if the synchronisation already completed 1055 if progress.CurrentBlock >= progress.HighestBlock { 1056 return nil, nil 1057 } 1058 // Otherwise gather the block sync stats 1059 return &SyncState{progress}, nil 1060 }