graphql: embed *Resolver instead of backend interface (#25468)
This creates some infrastructure to share resources between graphql API objects.
This commit is contained in:
parent
948e08d55b
commit
f809cf6ea6
|
@ -76,14 +76,14 @@ func (b *Long) UnmarshalGraphQL(input interface{}) error {
|
|||
|
||||
// Account represents an Ethereum account at a particular block.
|
||||
type Account struct {
|
||||
backend ethapi.Backend
|
||||
r *Resolver
|
||||
address common.Address
|
||||
blockNrOrHash rpc.BlockNumberOrHash
|
||||
}
|
||||
|
||||
// getState fetches the StateDB object for an account.
|
||||
func (a *Account) getState(ctx context.Context) (*state.StateDB, error) {
|
||||
state, _, err := a.backend.StateAndHeaderByNumberOrHash(ctx, a.blockNrOrHash)
|
||||
state, _, err := a.r.backend.StateAndHeaderByNumberOrHash(ctx, a.blockNrOrHash)
|
||||
return state, err
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ func (a *Account) Balance(ctx context.Context) (hexutil.Big, error) {
|
|||
func (a *Account) TransactionCount(ctx context.Context) (hexutil.Uint64, error) {
|
||||
// Ask transaction pool for the nonce which includes pending transactions
|
||||
if blockNr, ok := a.blockNrOrHash.Number(); ok && blockNr == rpc.PendingBlockNumber {
|
||||
nonce, err := a.backend.GetPoolNonce(ctx, a.address)
|
||||
nonce, err := a.r.backend.GetPoolNonce(ctx, a.address)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ func (a *Account) Storage(ctx context.Context, args struct{ Slot common.Hash })
|
|||
|
||||
// Log represents an individual log message. All arguments are mandatory.
|
||||
type Log struct {
|
||||
backend ethapi.Backend
|
||||
r *Resolver
|
||||
transaction *Transaction
|
||||
log *types.Log
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ func (l *Log) Transaction(ctx context.Context) *Transaction {
|
|||
|
||||
func (l *Log) Account(ctx context.Context, args BlockNumberArgs) *Account {
|
||||
return &Account{
|
||||
backend: l.backend,
|
||||
r: l.r,
|
||||
address: l.log.Address,
|
||||
blockNrOrHash: args.NumberOrLatest(),
|
||||
}
|
||||
|
@ -183,30 +183,30 @@ func (at *AccessTuple) StorageKeys(ctx context.Context) []common.Hash {
|
|||
// Transaction represents an Ethereum transaction.
|
||||
// backend and hash are mandatory; all others will be fetched when required.
|
||||
type Transaction struct {
|
||||
backend ethapi.Backend
|
||||
hash common.Hash
|
||||
tx *types.Transaction
|
||||
block *Block
|
||||
index uint64
|
||||
r *Resolver
|
||||
hash common.Hash
|
||||
tx *types.Transaction
|
||||
block *Block
|
||||
index uint64
|
||||
}
|
||||
|
||||
// resolve returns the internal transaction object, fetching it if needed.
|
||||
func (t *Transaction) resolve(ctx context.Context) (*types.Transaction, error) {
|
||||
if t.tx == nil {
|
||||
// Try to return an already finalized transaction
|
||||
tx, blockHash, _, index, err := t.backend.GetTransaction(ctx, t.hash)
|
||||
tx, blockHash, _, index, err := t.r.backend.GetTransaction(ctx, t.hash)
|
||||
if err == nil && tx != nil {
|
||||
t.tx = tx
|
||||
blockNrOrHash := rpc.BlockNumberOrHashWithHash(blockHash, false)
|
||||
t.block = &Block{
|
||||
backend: t.backend,
|
||||
r: t.r,
|
||||
numberOrHash: &blockNrOrHash,
|
||||
}
|
||||
t.index = index
|
||||
return t.tx, nil
|
||||
}
|
||||
// No finalized transaction, try to retrieve it from the pool
|
||||
t.tx = t.backend.GetPoolTransaction(t.hash)
|
||||
t.tx = t.r.backend.GetPoolTransaction(t.hash)
|
||||
}
|
||||
return t.tx, nil
|
||||
}
|
||||
|
@ -354,7 +354,7 @@ func (t *Transaction) To(ctx context.Context, args BlockNumberArgs) (*Account, e
|
|||
return nil, nil
|
||||
}
|
||||
return &Account{
|
||||
backend: t.backend,
|
||||
r: t.r,
|
||||
address: *to,
|
||||
blockNrOrHash: args.NumberOrLatest(),
|
||||
}, nil
|
||||
|
@ -365,10 +365,10 @@ func (t *Transaction) From(ctx context.Context, args BlockNumberArgs) (*Account,
|
|||
if err != nil || tx == nil {
|
||||
return nil, err
|
||||
}
|
||||
signer := types.LatestSigner(t.backend.ChainConfig())
|
||||
signer := types.LatestSigner(t.r.backend.ChainConfig())
|
||||
from, _ := types.Sender(signer, tx)
|
||||
return &Account{
|
||||
backend: t.backend,
|
||||
r: t.r,
|
||||
address: from,
|
||||
blockNrOrHash: args.NumberOrLatest(),
|
||||
}, nil
|
||||
|
@ -443,7 +443,7 @@ func (t *Transaction) CreatedContract(ctx context.Context, args BlockNumberArgs)
|
|||
return nil, err
|
||||
}
|
||||
return &Account{
|
||||
backend: t.backend,
|
||||
r: t.r,
|
||||
address: receipt.ContractAddress,
|
||||
blockNrOrHash: args.NumberOrLatest(),
|
||||
}, nil
|
||||
|
@ -457,7 +457,7 @@ func (t *Transaction) Logs(ctx context.Context) (*[]*Log, error) {
|
|||
ret := make([]*Log, 0, len(receipt.Logs))
|
||||
for _, log := range receipt.Logs {
|
||||
ret = append(ret, &Log{
|
||||
backend: t.backend,
|
||||
r: t.r,
|
||||
transaction: t,
|
||||
log: log,
|
||||
})
|
||||
|
@ -539,7 +539,7 @@ type BlockType int
|
|||
// backend, and numberOrHash are mandatory. All other fields are lazily fetched
|
||||
// when required.
|
||||
type Block struct {
|
||||
backend ethapi.Backend
|
||||
r *Resolver
|
||||
numberOrHash *rpc.BlockNumberOrHash
|
||||
hash common.Hash
|
||||
header *types.Header
|
||||
|
@ -558,7 +558,7 @@ func (b *Block) resolve(ctx context.Context) (*types.Block, error) {
|
|||
b.numberOrHash = &latest
|
||||
}
|
||||
var err error
|
||||
b.block, err = b.backend.BlockByNumberOrHash(ctx, *b.numberOrHash)
|
||||
b.block, err = b.r.backend.BlockByNumberOrHash(ctx, *b.numberOrHash)
|
||||
if b.block != nil && b.header == nil {
|
||||
b.header = b.block.Header()
|
||||
if hash, ok := b.numberOrHash.Hash(); ok {
|
||||
|
@ -578,9 +578,9 @@ func (b *Block) resolveHeader(ctx context.Context) (*types.Header, error) {
|
|||
var err error
|
||||
if b.header == nil {
|
||||
if b.hash != (common.Hash{}) {
|
||||
b.header, err = b.backend.HeaderByHash(ctx, b.hash)
|
||||
b.header, err = b.r.backend.HeaderByHash(ctx, b.hash)
|
||||
} else {
|
||||
b.header, err = b.backend.HeaderByNumberOrHash(ctx, *b.numberOrHash)
|
||||
b.header, err = b.r.backend.HeaderByNumberOrHash(ctx, *b.numberOrHash)
|
||||
}
|
||||
}
|
||||
return b.header, err
|
||||
|
@ -598,7 +598,7 @@ func (b *Block) resolveReceipts(ctx context.Context) ([]*types.Receipt, error) {
|
|||
}
|
||||
hash = header.Hash()
|
||||
}
|
||||
receipts, err := b.backend.GetReceipts(ctx, hash)
|
||||
receipts, err := b.r.backend.GetReceipts(ctx, hash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -659,7 +659,7 @@ func (b *Block) NextBaseFeePerGas(ctx context.Context) (*hexutil.Big, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chaincfg := b.backend.ChainConfig()
|
||||
chaincfg := b.r.backend.ChainConfig()
|
||||
if header.BaseFee == nil {
|
||||
// Make sure next block doesn't enable EIP-1559
|
||||
if !chaincfg.IsLondon(new(big.Int).Add(header.Number, common.Big1)) {
|
||||
|
@ -679,7 +679,7 @@ func (b *Block) Parent(ctx context.Context) (*Block, error) {
|
|||
}
|
||||
num := rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(b.header.Number.Uint64() - 1))
|
||||
return &Block{
|
||||
backend: b.backend,
|
||||
r: b.r,
|
||||
numberOrHash: &num,
|
||||
hash: b.header.ParentHash,
|
||||
}, nil
|
||||
|
@ -767,7 +767,7 @@ func (b *Block) Ommers(ctx context.Context) (*[]*Block, error) {
|
|||
for _, uncle := range block.Uncles() {
|
||||
blockNumberOrHash := rpc.BlockNumberOrHashWithHash(uncle.Hash(), false)
|
||||
ret = append(ret, &Block{
|
||||
backend: b.backend,
|
||||
r: b.r,
|
||||
numberOrHash: &blockNumberOrHash,
|
||||
header: uncle,
|
||||
})
|
||||
|
@ -800,7 +800,7 @@ func (b *Block) TotalDifficulty(ctx context.Context) (hexutil.Big, error) {
|
|||
}
|
||||
h = header.Hash()
|
||||
}
|
||||
td := b.backend.GetTd(ctx, h)
|
||||
td := b.r.backend.GetTd(ctx, h)
|
||||
if td == nil {
|
||||
return hexutil.Big{}, fmt.Errorf("total difficulty not found %x", b.hash)
|
||||
}
|
||||
|
@ -853,7 +853,7 @@ func (b *Block) Miner(ctx context.Context, args BlockNumberArgs) (*Account, erro
|
|||
return nil, err
|
||||
}
|
||||
return &Account{
|
||||
backend: b.backend,
|
||||
r: b.r,
|
||||
address: header.Coinbase,
|
||||
blockNrOrHash: args.NumberOrLatest(),
|
||||
}, nil
|
||||
|
@ -876,11 +876,11 @@ func (b *Block) Transactions(ctx context.Context) (*[]*Transaction, error) {
|
|||
ret := make([]*Transaction, 0, len(block.Transactions()))
|
||||
for i, tx := range block.Transactions() {
|
||||
ret = append(ret, &Transaction{
|
||||
backend: b.backend,
|
||||
hash: tx.Hash(),
|
||||
tx: tx,
|
||||
block: b,
|
||||
index: uint64(i),
|
||||
r: b.r,
|
||||
hash: tx.Hash(),
|
||||
tx: tx,
|
||||
block: b,
|
||||
index: uint64(i),
|
||||
})
|
||||
}
|
||||
return &ret, nil
|
||||
|
@ -897,11 +897,11 @@ func (b *Block) TransactionAt(ctx context.Context, args struct{ Index int32 }) (
|
|||
}
|
||||
tx := txs[args.Index]
|
||||
return &Transaction{
|
||||
backend: b.backend,
|
||||
hash: tx.Hash(),
|
||||
tx: tx,
|
||||
block: b,
|
||||
index: uint64(args.Index),
|
||||
r: b.r,
|
||||
hash: tx.Hash(),
|
||||
tx: tx,
|
||||
block: b,
|
||||
index: uint64(args.Index),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -917,7 +917,7 @@ func (b *Block) OmmerAt(ctx context.Context, args struct{ Index int32 }) (*Block
|
|||
uncle := uncles[args.Index]
|
||||
blockNumberOrHash := rpc.BlockNumberOrHashWithHash(uncle.Hash(), false)
|
||||
return &Block{
|
||||
backend: b.backend,
|
||||
r: b.r,
|
||||
numberOrHash: &blockNumberOrHash,
|
||||
header: uncle,
|
||||
}, nil
|
||||
|
@ -944,7 +944,7 @@ type BlockFilterCriteria struct {
|
|||
|
||||
// runFilter accepts a filter and executes it, returning all its results as
|
||||
// `Log` objects.
|
||||
func runFilter(ctx context.Context, be ethapi.Backend, filter *filters.Filter) ([]*Log, error) {
|
||||
func runFilter(ctx context.Context, r *Resolver, filter *filters.Filter) ([]*Log, error) {
|
||||
logs, err := filter.Logs(ctx)
|
||||
if err != nil || logs == nil {
|
||||
return nil, err
|
||||
|
@ -952,8 +952,8 @@ func runFilter(ctx context.Context, be ethapi.Backend, filter *filters.Filter) (
|
|||
ret := make([]*Log, 0, len(logs))
|
||||
for _, log := range logs {
|
||||
ret = append(ret, &Log{
|
||||
backend: be,
|
||||
transaction: &Transaction{backend: be, hash: log.TxHash},
|
||||
r: r,
|
||||
transaction: &Transaction{r: r, hash: log.TxHash},
|
||||
log: log,
|
||||
})
|
||||
}
|
||||
|
@ -978,10 +978,10 @@ func (b *Block) Logs(ctx context.Context, args struct{ Filter BlockFilterCriteri
|
|||
hash = header.Hash()
|
||||
}
|
||||
// Construct the range filter
|
||||
filter := filters.NewBlockFilter(b.backend, hash, addresses, topics)
|
||||
filter := filters.NewBlockFilter(b.r.backend, hash, addresses, topics)
|
||||
|
||||
// Run the filter and return all the logs
|
||||
return runFilter(ctx, b.backend, filter)
|
||||
return runFilter(ctx, b.r, filter)
|
||||
}
|
||||
|
||||
func (b *Block) Account(ctx context.Context, args struct {
|
||||
|
@ -994,7 +994,7 @@ func (b *Block) Account(ctx context.Context, args struct {
|
|||
}
|
||||
}
|
||||
return &Account{
|
||||
backend: b.backend,
|
||||
r: b.r,
|
||||
address: args.Address,
|
||||
blockNrOrHash: *b.numberOrHash,
|
||||
}, nil
|
||||
|
@ -1041,7 +1041,7 @@ func (b *Block) Call(ctx context.Context, args struct {
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
result, err := ethapi.DoCall(ctx, b.backend, args.Data, *b.numberOrHash, nil, b.backend.RPCEVMTimeout(), b.backend.RPCGasCap())
|
||||
result, err := ethapi.DoCall(ctx, b.r.backend, args.Data, *b.numberOrHash, nil, b.r.backend.RPCEVMTimeout(), b.r.backend.RPCGasCap())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1066,31 +1066,31 @@ func (b *Block) EstimateGas(ctx context.Context, args struct {
|
|||
return 0, err
|
||||
}
|
||||
}
|
||||
gas, err := ethapi.DoEstimateGas(ctx, b.backend, args.Data, *b.numberOrHash, b.backend.RPCGasCap())
|
||||
gas, err := ethapi.DoEstimateGas(ctx, b.r.backend, args.Data, *b.numberOrHash, b.r.backend.RPCGasCap())
|
||||
return Long(gas), err
|
||||
}
|
||||
|
||||
type Pending struct {
|
||||
backend ethapi.Backend
|
||||
r *Resolver
|
||||
}
|
||||
|
||||
func (p *Pending) TransactionCount(ctx context.Context) (int32, error) {
|
||||
txs, err := p.backend.GetPoolTransactions()
|
||||
txs, err := p.r.backend.GetPoolTransactions()
|
||||
return int32(len(txs)), err
|
||||
}
|
||||
|
||||
func (p *Pending) Transactions(ctx context.Context) (*[]*Transaction, error) {
|
||||
txs, err := p.backend.GetPoolTransactions()
|
||||
txs, err := p.r.backend.GetPoolTransactions()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := make([]*Transaction, 0, len(txs))
|
||||
for i, tx := range txs {
|
||||
ret = append(ret, &Transaction{
|
||||
backend: p.backend,
|
||||
hash: tx.Hash(),
|
||||
tx: tx,
|
||||
index: uint64(i),
|
||||
r: p.r,
|
||||
hash: tx.Hash(),
|
||||
tx: tx,
|
||||
index: uint64(i),
|
||||
})
|
||||
}
|
||||
return &ret, nil
|
||||
|
@ -1101,7 +1101,7 @@ func (p *Pending) Account(ctx context.Context, args struct {
|
|||
}) *Account {
|
||||
pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
|
||||
return &Account{
|
||||
backend: p.backend,
|
||||
r: p.r,
|
||||
address: args.Address,
|
||||
blockNrOrHash: pendingBlockNr,
|
||||
}
|
||||
|
@ -1111,7 +1111,7 @@ func (p *Pending) Call(ctx context.Context, args struct {
|
|||
Data ethapi.TransactionArgs
|
||||
}) (*CallResult, error) {
|
||||
pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
|
||||
result, err := ethapi.DoCall(ctx, p.backend, args.Data, pendingBlockNr, nil, p.backend.RPCEVMTimeout(), p.backend.RPCGasCap())
|
||||
result, err := ethapi.DoCall(ctx, p.r.backend, args.Data, pendingBlockNr, nil, p.r.backend.RPCEVMTimeout(), p.r.backend.RPCGasCap())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1131,7 +1131,7 @@ func (p *Pending) EstimateGas(ctx context.Context, args struct {
|
|||
Data ethapi.TransactionArgs
|
||||
}) (Long, error) {
|
||||
pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
|
||||
gas, err := ethapi.DoEstimateGas(ctx, p.backend, args.Data, pendingBlockNr, p.backend.RPCGasCap())
|
||||
gas, err := ethapi.DoEstimateGas(ctx, p.r.backend, args.Data, pendingBlockNr, p.r.backend.RPCGasCap())
|
||||
return Long(gas), err
|
||||
}
|
||||
|
||||
|
@ -1152,19 +1152,19 @@ func (r *Resolver) Block(ctx context.Context, args struct {
|
|||
number := rpc.BlockNumber(*args.Number)
|
||||
numberOrHash := rpc.BlockNumberOrHashWithNumber(number)
|
||||
block = &Block{
|
||||
backend: r.backend,
|
||||
r: r,
|
||||
numberOrHash: &numberOrHash,
|
||||
}
|
||||
} else if args.Hash != nil {
|
||||
numberOrHash := rpc.BlockNumberOrHashWithHash(*args.Hash, false)
|
||||
block = &Block{
|
||||
backend: r.backend,
|
||||
r: r,
|
||||
numberOrHash: &numberOrHash,
|
||||
}
|
||||
} else {
|
||||
numberOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
|
||||
block = &Block{
|
||||
backend: r.backend,
|
||||
r: r,
|
||||
numberOrHash: &numberOrHash,
|
||||
}
|
||||
}
|
||||
|
@ -1199,7 +1199,7 @@ func (r *Resolver) Blocks(ctx context.Context, args struct {
|
|||
for i := from; i <= to; i++ {
|
||||
numberOrHash := rpc.BlockNumberOrHashWithNumber(i)
|
||||
block := &Block{
|
||||
backend: r.backend,
|
||||
r: r,
|
||||
numberOrHash: &numberOrHash,
|
||||
}
|
||||
// Resolve the header to check for existence.
|
||||
|
@ -1218,13 +1218,13 @@ func (r *Resolver) Blocks(ctx context.Context, args struct {
|
|||
}
|
||||
|
||||
func (r *Resolver) Pending(ctx context.Context) *Pending {
|
||||
return &Pending{r.backend}
|
||||
return &Pending{r}
|
||||
}
|
||||
|
||||
func (r *Resolver) Transaction(ctx context.Context, args struct{ Hash common.Hash }) (*Transaction, error) {
|
||||
tx := &Transaction{
|
||||
backend: r.backend,
|
||||
hash: args.Hash,
|
||||
r: r,
|
||||
hash: args.Hash,
|
||||
}
|
||||
// Resolve the transaction; if it doesn't exist, return nil.
|
||||
t, err := tx.resolve(ctx)
|
||||
|
@ -1284,8 +1284,8 @@ func (r *Resolver) Logs(ctx context.Context, args struct{ Filter FilterCriteria
|
|||
topics = *args.Filter.Topics
|
||||
}
|
||||
// Construct the range filter
|
||||
filter := filters.NewRangeFilter(filters.Backend(r.backend), begin, end, addresses, topics)
|
||||
return runFilter(ctx, r.backend, filter)
|
||||
filter := filters.NewRangeFilter(r.backend, begin, end, addresses, topics)
|
||||
return runFilter(ctx, r, filter)
|
||||
}
|
||||
|
||||
func (r *Resolver) GasPrice(ctx context.Context) (hexutil.Big, error) {
|
||||
|
|
|
@ -56,10 +56,6 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// New constructs a new GraphQL service instance.
|
||||
func New(stack *node.Node, backend ethapi.Backend, cors, vhosts []string) error {
|
||||
if backend == nil {
|
||||
panic("missing backend")
|
||||
}
|
||||
// check if http server with given endpoint exists and enable graphQL on it
|
||||
return newHandler(stack, backend, cors, vhosts)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue