2021-08-21 09:27:40 +02:00
|
|
|
# external imports
|
2021-06-28 07:48:36 +02:00
|
|
|
from hexathon import (
|
|
|
|
add_0x,
|
|
|
|
strip_0x,
|
|
|
|
)
|
|
|
|
|
|
|
|
# local imports
|
|
|
|
from chainlib.jsonrpc import JSONRPCRequest
|
|
|
|
|
|
|
|
|
2021-08-21 09:27:40 +02:00
|
|
|
def nonce(address, confirmed=False, id_generator=None):
|
|
|
|
"""Generate json-rpc query to retrieve next nonce of address from node.
|
|
|
|
|
|
|
|
:param address: Address to retrieve nonce for, in hex
|
|
|
|
:type address: str
|
|
|
|
:param id_generator: json-rpc id generator
|
|
|
|
:type id_generator: chainlib.connection.JSONRPCIdGenerator
|
|
|
|
:rtype: dict
|
|
|
|
:returns: rpc query object
|
|
|
|
"""
|
2021-06-28 07:48:36 +02:00
|
|
|
j = JSONRPCRequest(id_generator)
|
|
|
|
o = j.template()
|
|
|
|
o['method'] = 'eth_getTransactionCount'
|
|
|
|
o['params'].append(address)
|
|
|
|
o['params'].append('pending')
|
2021-08-21 09:27:40 +02:00
|
|
|
if confirmed:
|
|
|
|
o['params'].append('latest')
|
|
|
|
else:
|
|
|
|
o['params'].append('pending')
|
2021-06-28 07:48:36 +02:00
|
|
|
return j.finalize(o)
|
|
|
|
|
|
|
|
|
2021-08-21 09:27:40 +02:00
|
|
|
def nonce_confirmed(address, id_generator=None):
|
|
|
|
return nonce(address, confirmed=True, id_generator=id_generator)
|
|
|
|
|
|
|
|
|
2021-06-28 07:48:36 +02:00
|
|
|
class NonceOracle:
|
2021-08-21 09:27:40 +02:00
|
|
|
"""Base class for the nonce parameter helpers.
|
2021-06-28 07:48:36 +02:00
|
|
|
|
2021-08-21 09:27:40 +02:00
|
|
|
:param address: Address to retireve nonce for, in hex
|
|
|
|
:type address: str
|
|
|
|
:param id_generator: json-rpc id generator
|
|
|
|
:type id_generator: chainlib.connection.JSONRPCIdGenerator
|
|
|
|
"""
|
2021-06-28 07:48:36 +02:00
|
|
|
def __init__(self, address, id_generator=None):
|
|
|
|
self.address = address
|
|
|
|
self.id_generator = id_generator
|
|
|
|
self.nonce = self.get_nonce()
|
|
|
|
|
|
|
|
|
|
|
|
def get_nonce(self):
|
2021-08-21 09:27:40 +02:00
|
|
|
"""Load initial nonce value.
|
|
|
|
"""
|
2021-06-28 07:48:36 +02:00
|
|
|
raise NotImplementedError('Class must be extended')
|
|
|
|
|
|
|
|
|
|
|
|
def next_nonce(self):
|
2021-08-21 09:27:40 +02:00
|
|
|
"""Return next nonce value and advance.
|
|
|
|
|
|
|
|
:rtype: int
|
|
|
|
:returns: Next nonce for address.
|
|
|
|
"""
|
2021-06-28 07:48:36 +02:00
|
|
|
n = self.nonce
|
|
|
|
self.nonce += 1
|
|
|
|
return n
|
|
|
|
|
|
|
|
|
|
|
|
class RPCNonceOracle(NonceOracle):
|
2021-08-21 09:27:40 +02:00
|
|
|
"""JSON-RPC only nonce parameter helper.
|
|
|
|
|
|
|
|
:param address: Address to retireve nonce for, in hex
|
|
|
|
:type address: str
|
|
|
|
:param conn: RPC connection
|
|
|
|
:type conn: chainlib.connection.RPCConnection
|
|
|
|
:param id_generator: json-rpc id generator
|
|
|
|
:type id_generator: chainlib.connection.JSONRPCIdGenerator
|
|
|
|
"""
|
2021-06-28 07:48:36 +02:00
|
|
|
def __init__(self, address, conn, id_generator=None):
|
|
|
|
self.conn = conn
|
|
|
|
super(RPCNonceOracle, self).__init__(address, id_generator=id_generator)
|
|
|
|
|
|
|
|
|
|
|
|
def get_nonce(self):
|
2021-08-21 09:27:40 +02:00
|
|
|
"""Load and return nonce value from network.
|
|
|
|
|
|
|
|
Note! First call to next_nonce after calling get_nonce will return the same value!
|
|
|
|
|
|
|
|
:rtype: int
|
|
|
|
:returns: Initial nonce
|
|
|
|
"""
|
2021-06-28 07:48:36 +02:00
|
|
|
o = nonce(self.address, id_generator=self.id_generator)
|
|
|
|
r = self.conn.do(o)
|
|
|
|
n = strip_0x(r)
|
|
|
|
return int(n, 16)
|
|
|
|
|
|
|
|
|
|
|
|
class OverrideNonceOracle(NonceOracle):
|
2021-08-21 09:27:40 +02:00
|
|
|
"""Manually set initial nonce value.
|
2021-06-28 07:48:36 +02:00
|
|
|
|
2021-08-21 09:27:40 +02:00
|
|
|
:param address: Address to retireve nonce for, in hex
|
|
|
|
:type address: str
|
|
|
|
:param nonce: Nonce value
|
|
|
|
:type nonce: int
|
|
|
|
:param id_generator: json-rpc id generator (not used)
|
|
|
|
:type id_generator: chainlib.connection.JSONRPCIdGenerator
|
|
|
|
"""
|
|
|
|
def __init__(self, address, nonce, id_generator=None):
|
|
|
|
self.initial_nonce = nonce
|
|
|
|
self.nonce = self.initial_nonce
|
|
|
|
super(OverrideNonceOracle, self).__init__(address, id_generator=id_generator)
|
2021-06-28 07:48:36 +02:00
|
|
|
|
|
|
|
|
|
|
|
def get_nonce(self):
|
2021-08-21 09:27:40 +02:00
|
|
|
"""Returns initial nonce value set at object construction.
|
|
|
|
|
|
|
|
:rtype: int
|
|
|
|
:returns: Initial nonce value.
|
|
|
|
"""
|
|
|
|
return self.initial_nonce
|
2021-06-28 07:48:36 +02:00
|
|
|
|
|
|
|
|
|
|
|
DefaultNonceOracle = RPCNonceOracle
|