chainlib-eth

Ethereum implementation of the chainlib interface
Info | Log | Files | Refs | README | LICENSE

nonce.py (3659B)


      1 # external imports
      2 from hexathon import (
      3         add_0x,
      4         strip_0x,
      5         )
      6 
      7 # local imports
      8 from chainlib.nonce import NonceOracle as BaseNonceOracle
      9 from chainlib.jsonrpc import JSONRPCRequest
     10 
     11 
     12 def nonce(address, confirmed=False, id_generator=None):
     13     """Generate json-rpc query to retrieve next nonce of address from node.
     14 
     15     :param address: Address to retrieve nonce for, in hex
     16     :type address: str
     17     :param id_generator: json-rpc id generator 
     18     :type id_generator: chainlib.connection.JSONRPCIdGenerator
     19     :rtype: dict
     20     :returns: rpc query object
     21     """
     22     j = JSONRPCRequest(id_generator)
     23     o = j.template()
     24     o['method'] = 'eth_getTransactionCount'
     25     o['params'].append(address)
     26     if confirmed:
     27         o['params'].append('latest')
     28     else:
     29         o['params'].append('pending')
     30     return j.finalize(o)
     31 
     32 
     33 def nonce_confirmed(address, id_generator=None):
     34     return nonce(address, confirmed=True, id_generator=id_generator)
     35 
     36 
     37 class NonceOracle(BaseNonceOracle):
     38     """Base class for the nonce parameter helpers.
     39 
     40     :param address: Address to retireve nonce for, in hex
     41     :type address: str
     42     :param id_generator: json-rpc id generator 
     43     :type id_generator: chainlib.connection.JSONRPCIdGenerator
     44     """
     45     def __init__(self, address, id_generator=None, confirmed=None):
     46         self.id_generator = id_generator
     47         super(NonceOracle, self).__init__(add_0x(address), confirmed=confirmed)
     48 
     49 
     50     def get_nonce(self, confirmed=False):
     51         """Load initial nonce value.
     52         """
     53         raise NotImplementedError('Class must be extended')
     54 
     55 
     56     def next_nonce(self):
     57         """Return next nonce value and advance.
     58 
     59         :rtype: int
     60         :returns: Next nonce for address.
     61         """
     62         n = self.nonce
     63         self.nonce += 1
     64         return n
     65 
     66 
     67 class RPCNonceOracle(NonceOracle):
     68     """JSON-RPC only nonce parameter helper.
     69 
     70     :param address: Address to retireve nonce for, in hex
     71     :type address: str
     72     :param conn: RPC connection
     73     :type conn: chainlib.connection.RPCConnection
     74     :param id_generator: json-rpc id generator 
     75     :type id_generator: chainlib.connection.JSONRPCIdGenerator
     76     """
     77     def __init__(self, address, conn, id_generator=None, confirmed=False):
     78         self.conn = conn
     79         super(RPCNonceOracle, self).__init__(address, id_generator=id_generator, confirmed=confirmed)
     80 
     81 
     82     def get_nonce(self, confirmed=False):
     83         """Load and return nonce value from network.
     84 
     85         Note! First call to next_nonce after calling get_nonce will return the same value!
     86 
     87         :rtype: int
     88         :returns: Initial nonce
     89         """
     90         o = nonce(self.address, confirmed=confirmed, id_generator=self.id_generator)
     91         r = self.conn.do(o)
     92         n = strip_0x(r)
     93         return int(n, 16)
     94 
     95 
     96 class OverrideNonceOracle(NonceOracle):
     97     """Manually set initial nonce value.
     98 
     99     :param address: Address to retireve nonce for, in hex
    100     :type address: str
    101     :param nonce: Nonce value
    102     :type nonce: int
    103     :param id_generator: json-rpc id generator (not used)
    104     :type id_generator: chainlib.connection.JSONRPCIdGenerator
    105     """
    106     def __init__(self, address, nonce, id_generator=None, confirmed=False):
    107         self.initial_nonce = nonce
    108         self.nonce = self.initial_nonce
    109         super(OverrideNonceOracle, self).__init__(address, id_generator=id_generator, confirmed=confirmed)
    110 
    111 
    112     def get_nonce(self, confirmed=False):
    113         """Returns initial nonce value set at object construction.
    114 
    115         :rtype: int
    116         :returns: Initial nonce value.
    117         """
    118         return self.initial_nonce
    119 
    120 
    121 DefaultNonceOracle = RPCNonceOracle