grpahql: add EIP-2718 and EIP-1559 features to graphql API
EIP-2718: - chainID: Long! of Query - chainID: Long of Transaction EIP-1559: - baseFeePerGas: BigInt of Block - effectiveGasPrice: BigInt of Transaction - maxFeePerGas: BigInt of Transaction - maxPriorityFeePerGas: BigInt of Transaction
This commit is contained in:
parent
7a42d037f2
commit
f3d194c05e
|
@ -49,6 +49,7 @@ type
|
||||||
blockNumber: BlockNumber
|
blockNumber: BlockNumber
|
||||||
receipt: Receipt
|
receipt: Receipt
|
||||||
gasUsed: GasInt
|
gasUsed: GasInt
|
||||||
|
baseFee: Option[UInt256]
|
||||||
|
|
||||||
LogNode = ref object of Node
|
LogNode = ref object of Node
|
||||||
log: Log
|
log: Log
|
||||||
|
@ -88,14 +89,15 @@ proc accountNode(ctx: GraphqlContextRef, acc: Account, address: EthAddress, db:
|
||||||
db: db
|
db: db
|
||||||
)
|
)
|
||||||
|
|
||||||
proc txNode(ctx: GraphqlContextRef, tx: Transaction, index: int, blockNumber: BlockNumber): Node =
|
proc txNode(ctx: GraphqlContextRef, tx: Transaction, index: int, blockNumber: BlockNumber, baseFee: Option[UInt256]): Node =
|
||||||
TxNode(
|
TxNode(
|
||||||
kind: nkMap,
|
kind: nkMap,
|
||||||
typeName: ctx.ids[ethTransaction],
|
typeName: ctx.ids[ethTransaction],
|
||||||
pos: Pos(),
|
pos: Pos(),
|
||||||
tx: tx,
|
tx: tx,
|
||||||
index: index,
|
index: index,
|
||||||
blockNumber: blockNumber
|
blockNumber: blockNumber,
|
||||||
|
baseFee: baseFee
|
||||||
)
|
)
|
||||||
|
|
||||||
proc logNode(ctx: GraphqlContextRef, log: Log, index: int, tx: TxNode): Node =
|
proc logNode(ctx: GraphqlContextRef, log: Log, index: int, tx: TxNode): Node =
|
||||||
|
@ -254,7 +256,7 @@ proc getTxs(ctx: GraphqlContextRef, header: BlockHeader): RespResult =
|
||||||
var index = 0
|
var index = 0
|
||||||
for n in getBlockTransactionData(ctx.chainDB, header.txRoot):
|
for n in getBlockTransactionData(ctx.chainDB, header.txRoot):
|
||||||
let tx = rlp.decode(n, Transaction)
|
let tx = rlp.decode(n, Transaction)
|
||||||
list.add txNode(ctx, tx, index, header.blockNumber)
|
list.add txNode(ctx, tx, index, header.blockNumber, header.fee)
|
||||||
inc index
|
inc index
|
||||||
|
|
||||||
index = 0
|
index = 0
|
||||||
|
@ -276,7 +278,7 @@ proc getTxAt(ctx: GraphqlContextRef, header: BlockHeader, index: int): RespResul
|
||||||
try:
|
try:
|
||||||
var tx: Transaction
|
var tx: Transaction
|
||||||
if getTransaction(ctx.chainDB, header.txRoot, index, tx):
|
if getTransaction(ctx.chainDB, header.txRoot, index, tx):
|
||||||
let txn = txNode(ctx, tx, index, header.blockNumber)
|
let txn = txNode(ctx, tx, index, header.blockNumber, header.fee)
|
||||||
|
|
||||||
var i = 0
|
var i = 0
|
||||||
var prevUsed = 0.GasInt
|
var prevUsed = 0.GasInt
|
||||||
|
@ -595,10 +597,47 @@ proc txValue(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.}
|
||||||
bigIntNode(tx.tx.value)
|
bigIntNode(tx.tx.value)
|
||||||
|
|
||||||
proc txGasPrice(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
proc txGasPrice(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
let ctx = GraphqlContextRef(ud)
|
|
||||||
let tx = TxNode(parent)
|
let tx = TxNode(parent)
|
||||||
|
if tx.tx.txType == TxEip1559:
|
||||||
|
if tx.baseFee.isNone:
|
||||||
|
return bigIntNode(tx.tx.gasPrice)
|
||||||
|
|
||||||
|
let baseFee = tx.baseFee.get().truncate(GasInt)
|
||||||
|
let priorityFee = min(tx.tx.maxPriorityFee, tx.tx.maxFee - baseFee)
|
||||||
|
bigIntNode(priorityFee + baseFee)
|
||||||
|
else:
|
||||||
bigIntNode(tx.tx.gasPrice)
|
bigIntNode(tx.tx.gasPrice)
|
||||||
|
|
||||||
|
proc txMaxFeePerGas(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
|
let tx = TxNode(parent)
|
||||||
|
if tx.tx.txType == TxEip1559:
|
||||||
|
bigIntNode(tx.tx.maxFee)
|
||||||
|
else:
|
||||||
|
ok(respNull())
|
||||||
|
|
||||||
|
proc txMaxPriorityFeePerGas(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
|
let tx = TxNode(parent)
|
||||||
|
if tx.tx.txType == TxEip1559:
|
||||||
|
bigIntNode(tx.tx.maxPriorityFee)
|
||||||
|
else:
|
||||||
|
ok(respNull())
|
||||||
|
|
||||||
|
proc txEffectiveGasPrice(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
|
let tx = TxNode(parent)
|
||||||
|
if tx.baseFee.isNone:
|
||||||
|
return bigIntNode(tx.tx.gasPrice)
|
||||||
|
|
||||||
|
let baseFee = tx.baseFee.get().truncate(GasInt)
|
||||||
|
let priorityFee = min(tx.tx.maxPriorityFee, tx.tx.maxFee - baseFee)
|
||||||
|
bigIntNode(priorityFee + baseFee)
|
||||||
|
|
||||||
|
proc txChainId(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
|
let tx = TxNode(parent)
|
||||||
|
if tx.tx.txType == TxLegacy:
|
||||||
|
ok(respNull())
|
||||||
|
else:
|
||||||
|
longNode(tx.tx.chainId.uint64)
|
||||||
|
|
||||||
proc txGas(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
proc txGas(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
let ctx = GraphqlContextRef(ud)
|
let ctx = GraphqlContextRef(ud)
|
||||||
let tx = TxNode(parent)
|
let tx = TxNode(parent)
|
||||||
|
@ -706,7 +745,11 @@ const txProcs = {
|
||||||
"s": txS,
|
"s": txS,
|
||||||
"v": txV,
|
"v": txV,
|
||||||
"type": txType,
|
"type": txType,
|
||||||
"accessList": txAccessList
|
"accessList": txAccessList,
|
||||||
|
"maxFeePerGas": txMaxFeePerGas,
|
||||||
|
"maxPriorityFeePerGas": txMaxPriorityFeePerGas,
|
||||||
|
"effectiveGasPrice": txEffectiveGasPrice,
|
||||||
|
"chainID": txChainId
|
||||||
}
|
}
|
||||||
|
|
||||||
proc aclAddress(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
proc aclAddress(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
|
@ -919,6 +962,13 @@ proc blockEstimateGas(ud: RootRef, params: Args, parent: Node): RespResult {.api
|
||||||
except Exception as em:
|
except Exception as em:
|
||||||
err("estimateGas error: " & em.msg)
|
err("estimateGas error: " & em.msg)
|
||||||
|
|
||||||
|
proc blockBaseFeePerGas(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
|
let h = HeaderNode(parent)
|
||||||
|
if h.header.fee.isSome:
|
||||||
|
bigIntNode(h.header.fee.get)
|
||||||
|
else:
|
||||||
|
ok(respNull())
|
||||||
|
|
||||||
const blockProcs = {
|
const blockProcs = {
|
||||||
"parent": blockParent,
|
"parent": blockParent,
|
||||||
"number": blockNumberImpl,
|
"number": blockNumberImpl,
|
||||||
|
@ -946,7 +996,8 @@ const blockProcs = {
|
||||||
"logs": blockLogs,
|
"logs": blockLogs,
|
||||||
"account": blockAccount,
|
"account": blockAccount,
|
||||||
"call": blockCall,
|
"call": blockCall,
|
||||||
"estimateGas": blockEstimateGas
|
"estimateGas": blockEstimateGas,
|
||||||
|
"baseFeePerGas": blockBaseFeePerGas
|
||||||
}
|
}
|
||||||
|
|
||||||
proc callResultData(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
proc callResultData(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
|
@ -1118,6 +1169,14 @@ proc querySyncing(ud: RootRef, params: Args, parent: Node): RespResult {.apiPrag
|
||||||
let ctx = GraphqlContextRef(ud)
|
let ctx = GraphqlContextRef(ud)
|
||||||
ok(respMap(ctx.ids[ethSyncState]))
|
ok(respMap(ctx.ids[ethSyncState]))
|
||||||
|
|
||||||
|
proc queryMaxPriorityFeePerGas(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
|
# TODO: stub, missing impl
|
||||||
|
err("not implemented")
|
||||||
|
|
||||||
|
proc queryChainId(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
|
let ctx = GraphqlContextRef(ud)
|
||||||
|
longNode(ctx.chainDB.config.chainId.uint64)
|
||||||
|
|
||||||
const queryProcs = {
|
const queryProcs = {
|
||||||
"account": queryAccount,
|
"account": queryAccount,
|
||||||
"block": queryBlock,
|
"block": queryBlock,
|
||||||
|
@ -1127,7 +1186,9 @@ const queryProcs = {
|
||||||
"logs": queryLogs,
|
"logs": queryLogs,
|
||||||
"gasPrice": queryGasPrice,
|
"gasPrice": queryGasPrice,
|
||||||
"protocolVersion": queryProtocolVersion,
|
"protocolVersion": queryProtocolVersion,
|
||||||
"syncing": querySyncing
|
"syncing": querySyncing,
|
||||||
|
"maxPriorityFeePerGas": queryMaxPriorityFeePerGas,
|
||||||
|
"chainID": queryChainId
|
||||||
}
|
}
|
||||||
|
|
||||||
proc sendRawTransaction(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
proc sendRawTransaction(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} =
|
||||||
|
|
|
@ -97,6 +97,12 @@ type Transaction {
|
||||||
# GasPrice is the price offered to miners for gas, in wei per unit.
|
# GasPrice is the price offered to miners for gas, in wei per unit.
|
||||||
gasPrice: BigInt!
|
gasPrice: BigInt!
|
||||||
|
|
||||||
|
# MaxFeePerGas is the maximum fee per gas offered to include a transaction, in wei.
|
||||||
|
maxFeePerGas: BigInt
|
||||||
|
|
||||||
|
# MaxPriorityFeePerGas is the maximum miner tip per gas offered to include a transaction, in wei.
|
||||||
|
maxPriorityFeePerGas: BigInt
|
||||||
|
|
||||||
# Gas is the maximum amount of gas this transaction can consume.
|
# Gas is the maximum amount of gas this transaction can consume.
|
||||||
gas: Long!
|
gas: Long!
|
||||||
|
|
||||||
|
@ -124,6 +130,14 @@ type Transaction {
|
||||||
# will be null.
|
# will be null.
|
||||||
cumulativeGasUsed: Long
|
cumulativeGasUsed: Long
|
||||||
|
|
||||||
|
# EffectiveGasPrice is actual value per gas deducted from the sender's
|
||||||
|
# account. Before EIP-1559, this is equal to the transaction's gas price.
|
||||||
|
# After EIP-1559, it is baseFeePerGas + min(maxFeePerGas - baseFeePerGas,
|
||||||
|
# maxPriorityFeePerGas). Legacy transactions and EIP-2930 transactions are
|
||||||
|
# coerced into the EIP-1559 format by setting both maxFeePerGas and
|
||||||
|
# maxPriorityFeePerGas as the transaction's gas price.
|
||||||
|
effectiveGasPrice: BigInt
|
||||||
|
|
||||||
# CreatedContract is the account that was created by a contract creation
|
# CreatedContract is the account that was created by a contract creation
|
||||||
# transaction. If the transaction was not a contract creation transaction,
|
# transaction. If the transaction was not a contract creation transaction,
|
||||||
# or it has not yet been mined, this field will be null.
|
# or it has not yet been mined, this field will be null.
|
||||||
|
@ -147,6 +161,10 @@ type Transaction {
|
||||||
|
|
||||||
# EIP 2930: optional access list, null if not present
|
# EIP 2930: optional access list, null if not present
|
||||||
accessList: [AccessTuple!]
|
accessList: [AccessTuple!]
|
||||||
|
|
||||||
|
# If type == 0, chainID returns null.
|
||||||
|
# If type > 0, chainID returns replay protection chainID
|
||||||
|
chainID: Long
|
||||||
}
|
}
|
||||||
|
|
||||||
# BlockFilterCriteria encapsulates log filter criteria for a filter applied
|
# BlockFilterCriteria encapsulates log filter criteria for a filter applied
|
||||||
|
@ -209,6 +227,9 @@ type Block {
|
||||||
# GasUsed is the amount of gas that was used executing transactions in this block.
|
# GasUsed is the amount of gas that was used executing transactions in this block.
|
||||||
gasUsed: Long!
|
gasUsed: Long!
|
||||||
|
|
||||||
|
# BaseFeePerGas is the fee perunit of gas burned by the protocol in this block.
|
||||||
|
baseFeePerGas: BigInt
|
||||||
|
|
||||||
# Timestamp is the unix timestamp at which this block was mined.
|
# Timestamp is the unix timestamp at which this block was mined.
|
||||||
timestamp: BigInt!
|
timestamp: BigInt!
|
||||||
|
|
||||||
|
@ -282,6 +303,12 @@ input CallData {
|
||||||
# GasPrice is the price, in wei, offered for each unit of gas.
|
# GasPrice is the price, in wei, offered for each unit of gas.
|
||||||
gasPrice: BigInt
|
gasPrice: BigInt
|
||||||
|
|
||||||
|
# MaxFeePerGas is the maximum fee per gas offered, in wei.
|
||||||
|
maxFeePerGas: BigInt
|
||||||
|
|
||||||
|
# MaxPriorityFeePerGas is the maximum miner tip per gas offered, in wei.
|
||||||
|
maxPriorityFeePerGas: BigInt
|
||||||
|
|
||||||
# Value is the value, in wei, sent along with the call.
|
# Value is the value, in wei, sent along with the call.
|
||||||
value: BigInt
|
value: BigInt
|
||||||
|
|
||||||
|
@ -394,11 +421,18 @@ type Query {
|
||||||
# ensure a transaction is mined in a timely fashion.
|
# ensure a transaction is mined in a timely fashion.
|
||||||
gasPrice: BigInt!
|
gasPrice: BigInt!
|
||||||
|
|
||||||
|
# MaxPriorityFeePerGas returns the node's estimate of a gas tip sufficient
|
||||||
|
# to ensure a transaction is mined in a timely fashion.
|
||||||
|
maxPriorityFeePerGas: BigInt!
|
||||||
|
|
||||||
# ProtocolVersion returns the current wire protocol version number.
|
# ProtocolVersion returns the current wire protocol version number.
|
||||||
protocolVersion: Int!
|
protocolVersion: Int!
|
||||||
|
|
||||||
# Syncing returns information on the current synchronisation state.
|
# Syncing returns information on the current synchronisation state.
|
||||||
syncing: SyncState
|
syncing: SyncState
|
||||||
|
|
||||||
|
# ChainID returns the current chain ID for transaction replay protection.
|
||||||
|
chainID: Long!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
name = "query.block(number)"
|
name = "query.block(number)"
|
||||||
code = """
|
code = """
|
||||||
{
|
{
|
||||||
|
chainID
|
||||||
block(number: 3) {
|
block(number: 3) {
|
||||||
__typename
|
__typename
|
||||||
number
|
number
|
||||||
|
@ -68,6 +69,7 @@
|
||||||
}
|
}
|
||||||
extraData
|
extraData
|
||||||
gasLimit
|
gasLimit
|
||||||
|
baseFeePerGas
|
||||||
gasUsed
|
gasUsed
|
||||||
timestamp
|
timestamp
|
||||||
logsBloom
|
logsBloom
|
||||||
|
@ -104,6 +106,7 @@
|
||||||
"""
|
"""
|
||||||
result = """
|
result = """
|
||||||
{
|
{
|
||||||
|
"chainID":1,
|
||||||
"block":{
|
"block":{
|
||||||
"__typename":"Block",
|
"__typename":"Block",
|
||||||
"number":3,
|
"number":3,
|
||||||
|
@ -127,6 +130,7 @@
|
||||||
},
|
},
|
||||||
"extraData":"0x42",
|
"extraData":"0x42",
|
||||||
"gasLimit":3141592,
|
"gasLimit":3141592,
|
||||||
|
"baseFeePerGas":null,
|
||||||
"gasUsed":21000,
|
"gasUsed":21000,
|
||||||
"timestamp":"0x54c99839",
|
"timestamp":"0x54c99839",
|
||||||
"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
@ -203,6 +207,11 @@
|
||||||
address
|
address
|
||||||
storageKeys
|
storageKeys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maxFeePerGas
|
||||||
|
maxPriorityFeePerGas
|
||||||
|
effectiveGasPrice
|
||||||
|
chainID
|
||||||
}
|
}
|
||||||
transactionAt(index: 0) {
|
transactionAt(index: 0) {
|
||||||
__typename
|
__typename
|
||||||
|
@ -244,7 +253,11 @@
|
||||||
"s":"0x773806df18e22db29acde1dd96c0418e28738af7f520e5e2c5c673494029e5",
|
"s":"0x773806df18e22db29acde1dd96c0418e28738af7f520e5e2c5c673494029e5",
|
||||||
"v":"0x1b",
|
"v":"0x1b",
|
||||||
"type":0,
|
"type":0,
|
||||||
"accessList":null
|
"accessList":null,
|
||||||
|
"maxFeePerGas":null,
|
||||||
|
"maxPriorityFeePerGas":null,
|
||||||
|
"effectiveGasPrice":"0x3e8",
|
||||||
|
"chainID":null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"transactionAt":{
|
"transactionAt":{
|
||||||
|
|
Loading…
Reference in New Issue