2019-03-23 20:54:28 +00:00
import
2022-06-29 15:44:08 +00:00
json_rpc / jsonmarshal ,
stew / byteutils ,
2023-01-31 01:32:17 +00:00
hexstrings , options , eth / common , json
2018-08-13 18:25:21 +00:00
2022-01-24 13:08:33 +00:00
from
web3 / ethtypes import FixedBytes
2022-09-03 18:15:35 +00:00
export FixedBytes , common
2022-01-24 13:08:33 +00:00
2023-01-31 01:32:17 +00:00
{. push raises : [ ] . }
2018-08-13 18:25:21 +00:00
#[
Notes :
* Some of the types suppose ' n u l l ' when there is no appropriate value .
2018-08-28 20:37:44 +00:00
To allow for this , you can use Option [ T ] or use refs so the JSON transform can convert to ` JNull ` .
2018-08-15 12:14:32 +00:00
* Parameter objects from users must have their data verified so will use EthAddressStr instead of EthAddres , for example
* Objects returned to the user can use native Nimbus types , where hexstrings provides converters to hex strings .
This is because returned arrays in JSON is
a ) not an efficient use of space
b ) not the format the user expects ( for example addresses are expected to be hex strings prefixed by " 0x " )
2018-08-13 18:25:21 +00:00
] #
type
SyncState * = object
2018-08-15 12:14:32 +00:00
# Returned to user
2020-07-22 16:51:26 +00:00
startingBlock * : HexQuantityStr # BlockNumber
currentBlock * : HexQuantityStr # BlockNumber
highestBlock * : HexQuantityStr # BlockNumber
2018-08-13 18:25:21 +00:00
2020-07-23 15:30:42 +00:00
TxSend * = object
2018-08-15 12:14:32 +00:00
# Parameter from user
2020-07-23 15:30:42 +00:00
source * : EthAddressStr # 20 bytes, the address the transaction is send from.
to * : Option [ EthAddressStr ] # (optional when creating new contract) 20 bytes, the address the transaction is directed to.
gas * : Option [ HexQuantityStr ] # (optional, default: 90000) integer of the gas provided for the transaction execution. It will return unused gas.
gasPrice * : Option [ HexQuantityStr ] # (optional, default: To-Be-Determined) integer of the gasPrice used for each paid gas.
value * : Option [ HexQuantityStr ] # (optional) integer of the value sent with this transaction.
data * : HexDataStr # TODO: Support more data. The compiled code of a contract OR the hash of the invoked method signature and encoded parameters. For details see Ethereum Contract ABI.
nonce * : Option [ HexQuantityStr ] # (optional) integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce
2018-08-13 18:25:21 +00:00
2018-10-16 00:10:01 +00:00
EthCall * = object
2018-08-15 12:14:32 +00:00
# Parameter from user
2020-07-24 12:44:36 +00:00
source * : Option [ EthAddressStr ] # (optional) The address the transaction is send from.
to * : Option [ EthAddressStr ] # (optional in eth_estimateGas, not in eth_call) The address the transaction is directed to.
2021-10-26 15:18:08 +00:00
gas * : Option [ HexQuantityStr ] # (optional) Integer of the gas provided for the transaction execution. eth_call consumes zero gas, but this parameter may be needed by some executions.
2020-07-24 12:44:36 +00:00
gasPrice * : Option [ HexQuantityStr ] # (optional) Integer of the gasPrice used for each paid gas.
2021-10-26 15:18:08 +00:00
maxFeePerGas * : Option [ HexQuantityStr ] # (optional) MaxFeePerGas is the maximum fee per gas offered, in wei.
maxPriorityFeePerGas * : Option [ HexQuantityStr ] # (optional) MaxPriorityFeePerGas is the maximum miner tip per gas offered, in wei.
2020-07-24 12:44:36 +00:00
value * : Option [ HexQuantityStr ] # (optional) Integer of the value sent with this transaction.
2020-07-28 16:48:45 +00:00
data * : Option [ EthHashStr ] # (optional) Hash of the method signature and encoded parameters. For details see Ethereum Contract ABI.
2018-08-13 18:25:21 +00:00
## A block object, or null when no block was found
2019-02-05 19:15:50 +00:00
## Note that this includes slightly different information from eth/common.BlockHeader
2018-08-28 20:37:44 +00:00
BlockObject * = object
2018-08-15 12:14:32 +00:00
# Returned to user
2023-08-17 04:08:01 +00:00
number * : Option [ HexQuantityStr ] # the block number. null when its pending block.
hash * : Option [ Hash256 ] # hash of the block. null when its pending block.
parentHash * : Hash256 # hash of the parent block.
nonce * : Option [ HexDataStr ] # hash of the generated proof-of-work. null when its pending block.
sha3Uncles * : Hash256 # SHA3 of the uncles data in the block.
logsBloom * : FixedBytes [ 256 ] # the bloom filter for the logs of the block. null when its pending block.
transactionsRoot * : Hash256 # the root of the transaction trie of the block.
stateRoot * : Hash256 # the root of the final state trie of the block.
receiptsRoot * : Hash256 # the root of the receipts trie of the block.
miner * : EthAddress # the address of the beneficiary to whom the mining rewards were given.
difficulty * : HexQuantityStr # integer of the difficulty for this block.
totalDifficulty * : HexQuantityStr # integer of the total difficulty of the chain until this block.
extraData * : HexDataStr # the "extra data" field of this block.
2023-08-30 16:29:48 +00:00
mixHash * : Hash256
2023-08-17 04:08:01 +00:00
size * : HexQuantityStr # integer the size of this block in bytes.
gasLimit * : HexQuantityStr # the maximum gas allowed in this block.
gasUsed * : HexQuantityStr # the total used gas by all transactions in this block.
timestamp * : HexQuantityStr # the unix timestamp for when the block was collated.
2022-03-21 09:17:28 +00:00
baseFeePerGas * : Option [ HexQuantityStr ]
2023-08-17 04:08:01 +00:00
transactions * : seq [ JsonNode ] # list of transaction objects, or 32 Bytes transaction hashes depending on the last given parameter.
uncles * : seq [ Hash256 ] # list of uncle hashes.
2023-08-16 10:05:14 +00:00
withdrawals * : Option [ seq [ WithdrawalObject ] ] # list of validator withdrawals
withdrawalsRoot * : Option [ Hash256 ] # EIP-4895
blobGasUsed * : Option [ HexQuantityStr ] # EIP-4844
excessBlobGas * : Option [ HexQuantityStr ] # EIP-4844
2023-08-30 16:29:48 +00:00
parentBeaconBlockRoot * : Option [ Hash256 ] # EIP-4788
2018-08-13 18:25:21 +00:00
TransactionObject * = object # A transaction object, or null when no transaction was found:
2018-08-15 12:14:32 +00:00
# Returned to user
2023-08-17 04:08:01 +00:00
` type ` * : HexQuantityStr # EIP-2718, with 0x0 for Legacy
blockHash * : Option [ Hash256 ] # hash of the block where this transaction was in. null when its pending.
blockNumber * : Option [ HexQuantityStr ] # block number where this transaction was in. null when its pending.
` from ` * : EthAddress # address of the sender.
gas * : HexQuantityStr # gas provided by the sender.
gasPrice * : HexQuantityStr # gas price provided by the sender in Wei.
maxFeePerGas * : HexQuantityStr # EIP-1559
maxPriorityFeePerGas * : HexQuantityStr # EIP-1559
hash * : Hash256 # hash of the transaction.
input * : Blob # the data send along with the transaction.
nonce * : HexQuantityStr # the number of transactions made by the sender prior to this one.
to * : Option [ EthAddress ] # address of the receiver. null when its a contract creation transaction.
2020-07-30 07:21:11 +00:00
transactionIndex * : Option [ HexQuantityStr ] # integer of the transactions index position in the block. null when its pending.
2023-08-17 04:08:01 +00:00
value * : HexQuantityStr # value transferred in Wei.
v * : HexQuantityStr # ECDSA recovery id
r * : HexQuantityStr # 32 Bytes - ECDSA signature r
2023-08-30 16:29:48 +00:00
s * : HexQuantityStr # 32 Bytes - ECDSA signature s
2023-08-17 04:08:01 +00:00
chainId * : Option [ HexQuantityStr ] # EIP-159
accessList * : Option [ seq [ AccessTuple ] ] # EIP-2930
maxFeePerBlobGas * : Option [ HexQuantityStr ] # EIP-4844
versionedHashes * : Option [ VersionedHashes ] # EIP-4844
2023-08-16 10:05:14 +00:00
AccessTuple * = object
address * : EthAddress
storageKeys * : seq [ Hash256 ]
2018-08-13 18:25:21 +00:00
2023-04-12 12:20:52 +00:00
WithdrawalObject * = object
index * : HexQuantityStr
validatorIndex * : HexQuantityStr
address * : EthAddress
amount * : HexQuantityStr
2018-08-22 16:39:42 +00:00
FilterLog * = object
2018-08-15 12:14:32 +00:00
# Returned to user
2022-06-29 15:44:08 +00:00
removed * : bool # true when the log was removed, due to a chain reorganization. false if its a valid log.
logIndex * : Option [ HexQuantityStr ] # integer of the log index position in the block. null when its pending log.
transactionIndex * : Option [ HexQuantityStr ] # integer of the transactions index position log was created from. null when its pending log.
transactionHash * : Option [ Hash256 ] # hash of the transactions this log was created from. null when its pending log.
blockHash * : Option [ Hash256 ] # hash of the block where this log was in. null when its pending. null when its pending log.
blockNumber * : Option [ HexQuantityStr ] # the block number where this log was in. null when its pending. null when its pending log.
address * : EthAddress # address from which this log originated.
data * : seq [ byte ] # contains one or more 32 Bytes non-indexed arguments of the log.
topics * : seq [ Hash256 ] # array of 0 to 4 32 Bytes DATA of indexed log arguments.
# (In solidity: The first topic is the hash of the signature of the event.
# (e.g. Deposit(address,bytes32,uint256)), except you declared the event with the anonymous specifier.)
2018-08-17 22:51:05 +00:00
ReceiptObject * = object
# A transaction receipt object, or null when no receipt was found:
2018-08-28 20:37:44 +00:00
transactionHash * : Hash256 # hash of the transaction.
2020-07-30 07:21:11 +00:00
transactionIndex * : HexQuantityStr # integer of the transactions index position in the block.
2018-08-28 20:37:44 +00:00
blockHash * : Hash256 # hash of the block where this transaction was in.
2020-07-30 07:21:11 +00:00
blockNumber * : HexQuantityStr # block number where this transaction was in.
` from ` * : EthAddress # address of the sender.
2018-08-28 20:37:44 +00:00
to * : Option [ EthAddress ] # address of the receiver. null when its a contract creation transaction.
2020-07-30 07:21:11 +00:00
cumulativeGasUsed * : HexQuantityStr # the total amount of gas used when this transaction was executed in the block.
gasUsed * : HexQuantityStr # the amount of gas used by this specific transaction alone.
2018-08-28 20:37:44 +00:00
contractAddress * : Option [ EthAddress ] # the contract address created, if the transaction was a contract creation, otherwise null.
2023-03-27 19:10:43 +00:00
logs * : seq [ FilterLog ] # list of log objects which this transaction generated.
2022-01-24 13:08:33 +00:00
logsBloom * : FixedBytes [ 256 ] # bloom filter for light clients to quickly retrieve related logs.
2023-03-27 19:10:43 +00:00
` type ` * : HexQuantityStr
2018-11-28 15:04:57 +00:00
root * : Option [ Hash256 ] # post-transaction stateroot (pre Byzantium).
2022-06-27 06:01:20 +00:00
status * : Option [ HexQuantityStr ] # 1 = success, 0 = failure.
2022-04-05 10:32:54 +00:00
effectiveGasPrice * : HexQuantityStr # The actual value per gas deducted from the senders account.
# Before EIP-1559, this is equal to the transaction's gas price.
# After, it is equal to baseFeePerGas + min(maxFeePerGas - baseFeePerGas, maxPriorityFeePerGas).
2018-08-17 22:51:05 +00:00
2018-08-21 21:21:41 +00:00
FilterOptions * = object
# Parameter from user
2022-06-29 15:44:08 +00:00
fromBlock * : Option [ string ] # (optional, default: "latest") integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions.
toBlock * : Option [ string ] # (optional, default: "latest") integer block number, or "latest" for the last mined block or "pending", "earliest" for not yet mined transactions.
address * : seq [ EthAddress ] # (optional) contract address or a list of addresses from which logs should originate.
topics * : seq [ Option [ seq [ Hash256 ] ] ] # (optional) list of DATA topics. Topics are order-dependent. Each topic can also be a list of DATA with "or" options.
2022-09-10 19:00:27 +00:00
blockHash * : Option [ Hash256 ] # (optional) hash of the block. If its present, fromBlock and toBlock, should be none. Introduced in EIP234
2022-06-29 15:44:08 +00:00
2023-01-31 01:32:17 +00:00
proc fromJson * ( n : JsonNode , argName : string , result : var FilterOptions )
{. gcsafe , raises : [ KeyError , ValueError ] . } =
proc getOptionString ( argName : string ) : Option [ string ]
{. gcsafe , raises : [ KeyError , ValueError ] . } =
2022-06-29 15:44:08 +00:00
let s = n . getOrDefault ( argName )
if s = = nil :
return none [ string ] ( )
elif s . kind = = JNull :
return none [ string ] ( )
else :
s . kind . expect ( JString , argName )
return some [ string ] ( s . getStr ( ) )
2023-01-31 01:32:17 +00:00
proc getAddress ( ) : seq [ EthAddress ] {. gcsafe , raises : [ ValueError ] . } =
2022-06-29 15:44:08 +00:00
## Address can by provided in two formats:
## 1. {"address": "hexAddress"}
## 2. {"address": ["hexAddress1", "hexAddress2" ...]}
## So either as sigle string or array of strings
let addressNode = n . getOrDefault ( " address " )
if addressNode . isNil :
return @ [ ]
else :
case addressNode . kind
of JString :
var addrs : EthAddress
fromJson ( addressNode , " address " , addrs )
return @ [ addrs ]
of JArray :
var addresses = newSeq [ EthAddress ] ( )
for i , e in addressNode . elems :
if e . kind = = JString and e . str . isValidEthAddress :
var address : EthAddress
hexToByteArray ( e . getStr ( ) , address )
addresses . add ( address )
else :
let msg = " Address at index " & $ i & " is not a valid Ethereum address "
raise newException ( ValueError , msg )
return addresses
else :
raise newException ( ValueError , " Parameter ' address` should be either string or of array of strings " )
2023-01-31 01:32:17 +00:00
proc getTopics ( ) : seq [ Option [ seq [ Hash256 ] ] ] {. gcsafe , raises : [ ValueError ] . } =
2022-06-29 15:44:08 +00:00
## Topics can be provided in many forms:
## [] "anything"
## [A] "A in first position (and anything after)"
## [null, B] "anything in first position AND B in second position (and anything after)"
## [A, B] "A in first position AND B in second position (and anything after)"
## [[A, B], [A, B]] "(A OR B) in first position AND (A OR B) in second position (and anything after)"
##
## In this custom deserialized JNull is desarializing to None subtopic seq.
## alternative would be to deserialize to empty seq, it would simplify some
## filters code but would be less explicit
let topicsNode = n . getOrDefault ( " topics " )
if topicsNode . isNil :
return @ [ ]
else :
topicsNode . kind . expect ( JArray , " topics " )
var filterArr = newSeq [ Option [ seq [ Hash256 ] ] ] ( )
for i , e in topicsNode . elems :
case e . kind
of JNull :
# catch all match
filterArr . add ( none [ seq [ Hash256 ] ] ( ) )
of JString :
let hexstring = e . getStr ( )
# specific topic match
if hexstring . isValidHash256 :
var hash : Hash256
hexToByteArray ( hexstring , hash . data )
filterArr . add ( some ( @ [ hash ] ) )
else :
let msg = " Invalid topic at pos: " & $ i & " . Expected 32byte hex string "
raise newException ( ValueError , msg )
of JArray :
if len ( e . elems ) = = 0 :
filterArr . add ( none [ seq [ Hash256 ] ] ( ) )
else :
var orFilters = newSeq [ Hash256 ] ( )
for j , orTopic in e . elems :
if orTopic . kind = = JString and orTopic . str . isValidHash256 :
var hash : Hash256
hexToByteArray ( orTopic . getStr ( ) , hash . data )
orFilters . add ( hash )
else :
let msg = " Invlid topic at pos: " & $ i & " , sub pos: " & $ j & " . Expected 32byte hex string "
raise newException ( ValueError , msg )
filterArr . add ( some ( orFilters ) )
else :
let msg = " Invalid arg at pos: " & $ i & " . Expected (null, string, array) "
raise newException ( ValueError , msg )
return filterArr
2023-01-31 01:32:17 +00:00
proc getBlockHash ( ) : Option [ Hash256 ] {. gcsafe , raises : [ KeyError , ValueError ] . } =
2022-09-10 19:00:27 +00:00
let s = getOptionString ( " blockHash " )
2022-06-29 15:44:08 +00:00
if s . isNone ( ) :
return none [ Hash256 ] ( )
else :
let strHash = s . unsafeGet ( )
if strHash . isValidHash256 :
var hash : Hash256
hexToByteArray ( strHash , hash . data )
return some ( hash )
else :
2022-09-10 19:00:27 +00:00
let msg = " Invalid ' blockHash ' . Expected 32byte hex string "
2022-06-29 15:44:08 +00:00
raise newException ( ValueError , msg )
n . kind . expect ( JObject , argName )
let blockHash = getBlockHash ( )
# TODO: Tags should deserialize to some kind of Enum, to avoid using raw strings
# in other layers. But this should be done on all endpoint to keep them constistent
let fromBlock = getOptionString ( " fromBlock " )
let toBlock = getOptionString ( " toBlock " )
if blockHash . isSome ( ) :
if fromBlock . isSome ( ) or toBlock . isSome ( ) :
raise newException ( ValueError , " fromBlock and toBlock are not allowed if blockHash is present " )
result . fromBlock = fromBlock
result . toBlock = toBlock
result . address = getAddress ( )
result . topics = getTopics ( )
2022-09-10 19:00:27 +00:00
result . blockHash = blockHash