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