mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-02-04 00:05:22 +00:00
add more query fields and resolvers to graphql api
after EIP2718/EIP2930, we have additional fields: type AccessTuple { address: Address! storageKeys : [Bytes32!] } type Transaction { r: BigInt! s: BigInt! v: BigInt! # Envelope transaction support type: Int accessList: [AccessTuple!] } close #606
This commit is contained in:
parent
af1537fcab
commit
0ecf9fe1af
@ -33,6 +33,7 @@ type
|
|||||||
ethPending = "Pending"
|
ethPending = "Pending"
|
||||||
ethQuery = "Query"
|
ethQuery = "Query"
|
||||||
ethMutation = "Mutation"
|
ethMutation = "Mutation"
|
||||||
|
ethAccessTuple = "AccessTuple"
|
||||||
|
|
||||||
HeaderNode = ref object of Node
|
HeaderNode = ref object of Node
|
||||||
header: BlockHeader
|
header: BlockHeader
|
||||||
@ -54,6 +55,9 @@ type
|
|||||||
index: int
|
index: int
|
||||||
tx: TxNode
|
tx: TxNode
|
||||||
|
|
||||||
|
AclNode = ref object of Node
|
||||||
|
acl: AccessPair
|
||||||
|
|
||||||
GraphqlContextRef = ref GraphqlContextObj
|
GraphqlContextRef = ref GraphqlContextObj
|
||||||
GraphqlContextObj = object of Graphql
|
GraphqlContextObj = object of Graphql
|
||||||
ids: array[EthTypes, Name]
|
ids: array[EthTypes, Name]
|
||||||
@ -104,6 +108,14 @@ proc logNode(ctx: GraphqlContextRef, log: Log, index: int, tx: TxNode): Node =
|
|||||||
tx: tx
|
tx: tx
|
||||||
)
|
)
|
||||||
|
|
||||||
|
proc aclNode(ctx: GraphqlContextRef, accessPair: AccessPair): Node =
|
||||||
|
AclNode(
|
||||||
|
kind: nkMap,
|
||||||
|
typeName: ctx.ids[ethAccessTuple],
|
||||||
|
pos: Pos(),
|
||||||
|
acl: accessPair
|
||||||
|
)
|
||||||
|
|
||||||
proc getAccountDb(chainDB: BaseChainDB, header: BlockHeader): ReadOnlyStateDB =
|
proc getAccountDb(chainDB: BaseChainDB, header: BlockHeader): ReadOnlyStateDB =
|
||||||
## Retrieves the account db from canonical head
|
## Retrieves the account db from canonical head
|
||||||
## we don't use accounst_cache here because it's only read operations
|
## we don't use accounst_cache here because it's only read operations
|
||||||
@ -638,6 +650,34 @@ proc txLogs(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
|||||||
list.add logNode(ctx, n, i, tx)
|
list.add logNode(ctx, n, i, tx)
|
||||||
ok(list)
|
ok(list)
|
||||||
|
|
||||||
|
proc txR(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
|
let tx = TxNode(parent)
|
||||||
|
bigIntNode(tx.tx.R)
|
||||||
|
|
||||||
|
proc txS(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
|
let tx = TxNode(parent)
|
||||||
|
bigIntNode(tx.tx.S)
|
||||||
|
|
||||||
|
proc txV(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
|
let tx = TxNode(parent)
|
||||||
|
bigIntNode(tx.tx.V)
|
||||||
|
|
||||||
|
proc txType(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
|
let tx = TxNode(parent)
|
||||||
|
let typ = resp(ord(tx.tx.txType))
|
||||||
|
ok(typ)
|
||||||
|
|
||||||
|
proc txAccessList(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
|
let ctx = GraphqlContextRef(ud)
|
||||||
|
let tx = TxNode(parent)
|
||||||
|
if tx.tx.txType == LegacyTxType:
|
||||||
|
ok(respNull())
|
||||||
|
else:
|
||||||
|
var list = respList()
|
||||||
|
for x in tx.tx.accessListTx.accessList:
|
||||||
|
list.add aclNode(ctx, x)
|
||||||
|
ok(list)
|
||||||
|
|
||||||
const txProcs = {
|
const txProcs = {
|
||||||
"from": txFrom,
|
"from": txFrom,
|
||||||
"hash": txHash,
|
"hash": txHash,
|
||||||
@ -653,7 +693,31 @@ const txProcs = {
|
|||||||
"gasUsed": txGasUsed,
|
"gasUsed": txGasUsed,
|
||||||
"cumulativeGasUsed": txCumulativeGasUsed,
|
"cumulativeGasUsed": txCumulativeGasUsed,
|
||||||
"createdContract": txCreatedContract,
|
"createdContract": txCreatedContract,
|
||||||
"logs": txLogs
|
"logs": txLogs,
|
||||||
|
"r": txR,
|
||||||
|
"s": txS,
|
||||||
|
"v": txV,
|
||||||
|
"type": txType,
|
||||||
|
"accessList": txAccessList
|
||||||
|
}
|
||||||
|
|
||||||
|
proc aclAddress(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
|
let acl = AclNode(parent)
|
||||||
|
resp(acl.acl.address)
|
||||||
|
|
||||||
|
proc aclStorageKeys(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
|
let acl = AclNode(parent)
|
||||||
|
if acl.acl.storageKeys.len == 0:
|
||||||
|
ok(respNull())
|
||||||
|
else:
|
||||||
|
var list = respList()
|
||||||
|
for n in acl.acl.storageKeys:
|
||||||
|
list.add resp(n).get()
|
||||||
|
ok(list)
|
||||||
|
|
||||||
|
const aclProcs = {
|
||||||
|
"address": aclAddress,
|
||||||
|
"storageKeys": aclStorageKeys
|
||||||
}
|
}
|
||||||
|
|
||||||
proc blockNumberImpl(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
proc blockNumberImpl(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
@ -1086,17 +1150,17 @@ type
|
|||||||
qcFields = "fields"
|
qcFields = "fields"
|
||||||
qcBlock = "block"
|
qcBlock = "block"
|
||||||
qcTransaction = "Transaction"
|
qcTransaction = "Transaction"
|
||||||
|
|
||||||
EthQueryComplexity = ref object of QueryComplexity
|
EthQueryComplexity = ref object of QueryComplexity
|
||||||
names: array[QcNames, Name]
|
names: array[QcNames, Name]
|
||||||
|
|
||||||
proc calcQC(qc: QueryComplexity, field: FieldRef): int {.cdecl,
|
proc calcQC(qc: QueryComplexity, field: FieldRef): int {.cdecl,
|
||||||
gcsafe, raises: [Defect, CatchableError].} =
|
gcsafe, raises: [Defect, CatchableError].} =
|
||||||
let qc = EthQueryComplexity(qc)
|
let qc = EthQueryComplexity(qc)
|
||||||
if field.parentType.sym.name == qc.names[qcType] and
|
if field.parentType.sym.name == qc.names[qcType] and
|
||||||
field.field.name.name == qc.names[qcFields]:
|
field.field.name.name == qc.names[qcFields]:
|
||||||
return 100
|
return 100
|
||||||
elif field.parentType.sym.name == qc.names[qcTransaction] and
|
elif field.parentType.sym.name == qc.names[qcTransaction] and
|
||||||
field.field.name.name == qc.names[qcBlock]:
|
field.field.name.name == qc.names[qcBlock]:
|
||||||
return 100
|
return 100
|
||||||
else:
|
else:
|
||||||
@ -1110,7 +1174,7 @@ proc newQC(ctx: GraphqlContextRef): EthQueryComplexity =
|
|||||||
let name = ctx.createName($n)
|
let name = ctx.createName($n)
|
||||||
qc.names[n] = name
|
qc.names[n] = name
|
||||||
qc
|
qc
|
||||||
|
|
||||||
proc initEthApi(ctx: GraphqlContextRef) =
|
proc initEthApi(ctx: GraphqlContextRef) =
|
||||||
ctx.customScalar("Bytes32", scalarBytes32)
|
ctx.customScalar("Bytes32", scalarBytes32)
|
||||||
ctx.customScalar("Address", scalarAddress)
|
ctx.customScalar("Address", scalarAddress)
|
||||||
@ -1131,10 +1195,11 @@ proc initEthApi(ctx: GraphqlContextRef) =
|
|||||||
ctx.addResolvers(ctx, ctx.ids[ethPending ], pendingProcs)
|
ctx.addResolvers(ctx, ctx.ids[ethPending ], pendingProcs)
|
||||||
ctx.addResolvers(ctx, ctx.ids[ethQuery ], queryProcs)
|
ctx.addResolvers(ctx, ctx.ids[ethQuery ], queryProcs)
|
||||||
ctx.addResolvers(ctx, ctx.ids[ethMutation ], mutationProcs)
|
ctx.addResolvers(ctx, ctx.ids[ethMutation ], mutationProcs)
|
||||||
|
ctx.addResolvers(ctx, ctx.ids[ethAccessTuple], aclProcs)
|
||||||
|
|
||||||
var qc = newQC(ctx)
|
var qc = newQC(ctx)
|
||||||
ctx.addInstrument(qc)
|
ctx.addInstrument(qc)
|
||||||
|
|
||||||
let res = ctx.parseSchema(ethSchema)
|
let res = ctx.parseSchema(ethSchema)
|
||||||
if res.isErr:
|
if res.isErr:
|
||||||
echo res.error
|
echo res.error
|
||||||
|
@ -62,6 +62,15 @@ type Log {
|
|||||||
transaction: Transaction!
|
transaction: Transaction!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# EIP-2718 Access List
|
||||||
|
type AccessTuple {
|
||||||
|
# access list address
|
||||||
|
address: Address!
|
||||||
|
|
||||||
|
# access list storage keys, null if not present
|
||||||
|
storageKeys: [Bytes32!]
|
||||||
|
}
|
||||||
|
|
||||||
# Transaction is an Ethereum transaction.
|
# Transaction is an Ethereum transaction.
|
||||||
type Transaction {
|
type Transaction {
|
||||||
# Hash is the hash of this transaction.
|
# Hash is the hash of this transaction.
|
||||||
@ -123,6 +132,21 @@ type Transaction {
|
|||||||
# Logs is a list of log entries emitted by this transaction. If the
|
# Logs is a list of log entries emitted by this transaction. If the
|
||||||
# transaction has not yet been mined, this field will be null.
|
# transaction has not yet been mined, this field will be null.
|
||||||
logs: [Log!]
|
logs: [Log!]
|
||||||
|
|
||||||
|
# signature field R
|
||||||
|
r: BigInt!
|
||||||
|
|
||||||
|
# signature fields S
|
||||||
|
s: BigInt!
|
||||||
|
|
||||||
|
# signature fields V
|
||||||
|
v: BigInt!
|
||||||
|
|
||||||
|
# EIP 2718: envelope transaction support
|
||||||
|
type: Int
|
||||||
|
|
||||||
|
# EIP 2930: optional access list, null if not present
|
||||||
|
accessList: [AccessTuple!]
|
||||||
}
|
}
|
||||||
|
|
||||||
# BlockFilterCriteria encapsulates log filter criteria for a filter applied
|
# BlockFilterCriteria encapsulates log filter criteria for a filter applied
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
{"name":"Bytes"},
|
{"name":"Bytes"},
|
||||||
{"name":"String"},
|
{"name":"String"},
|
||||||
{"name":"Bytes32"},
|
{"name":"Bytes32"},
|
||||||
|
{"name":"AccessTuple"},
|
||||||
{"name":"BlockFilterCriteria"},
|
{"name":"BlockFilterCriteria"},
|
||||||
{"name":"ID"},
|
{"name":"ID"},
|
||||||
{"name":"Pending"},
|
{"name":"Pending"},
|
||||||
@ -194,6 +195,14 @@
|
|||||||
logs {
|
logs {
|
||||||
__typename
|
__typename
|
||||||
}
|
}
|
||||||
|
r
|
||||||
|
s
|
||||||
|
v
|
||||||
|
type
|
||||||
|
accessList {
|
||||||
|
address
|
||||||
|
storageKeys
|
||||||
|
}
|
||||||
}
|
}
|
||||||
transactionAt(index: 0) {
|
transactionAt(index: 0) {
|
||||||
__typename
|
__typename
|
||||||
@ -230,7 +239,12 @@
|
|||||||
"gasUsed":21000,
|
"gasUsed":21000,
|
||||||
"cumulativeGasUsed":21000,
|
"cumulativeGasUsed":21000,
|
||||||
"createdContract":null,
|
"createdContract":null,
|
||||||
"logs":[]
|
"logs":[],
|
||||||
|
"r":"0x77c7cd36820c71821c1aed59de46e70e701c4a8dd89c9ba508ab722210f60da8",
|
||||||
|
"s":"0x3f29825d40c7c3f7bff3ca69267e0f3fb74b2d18b8c2c4e3c135b5d3b06e288d",
|
||||||
|
"v":"0x1b",
|
||||||
|
"type":0,
|
||||||
|
"accessList":null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"transactionAt":{
|
"transactionAt":{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user