105 lines
3.0 KiB
Python
105 lines
3.0 KiB
Python
# standard imports
|
|
import copy
|
|
import logging
|
|
import json
|
|
import datetime
|
|
import time
|
|
import socket
|
|
from urllib.request import (
|
|
Request,
|
|
urlopen,
|
|
)
|
|
|
|
# third-party imports
|
|
from hexathon import (
|
|
add_0x,
|
|
strip_0x,
|
|
)
|
|
|
|
# local imports
|
|
from .error import (
|
|
DefaultErrorParser,
|
|
RevertEthException,
|
|
)
|
|
from .sign import (
|
|
sign_transaction,
|
|
)
|
|
from chainlib.connection import (
|
|
JSONRPCHTTPConnection,
|
|
JSONRPCUnixConnection,
|
|
error_parser,
|
|
)
|
|
from chainlib.jsonrpc import (
|
|
jsonrpc_template,
|
|
jsonrpc_result,
|
|
)
|
|
from chainlib.eth.tx import (
|
|
unpack,
|
|
)
|
|
|
|
logg = logging.getLogger(__name__)
|
|
|
|
|
|
class EthHTTPConnection(JSONRPCHTTPConnection):
|
|
|
|
def wait(self, tx_hash_hex, delay=0.5, timeout=0.0, error_parser=error_parser):
|
|
t = datetime.datetime.utcnow()
|
|
i = 0
|
|
while True:
|
|
o = jsonrpc_template()
|
|
o['method'] ='eth_getTransactionReceipt'
|
|
o['params'].append(add_0x(tx_hash_hex))
|
|
req = Request(
|
|
self.location,
|
|
method='POST',
|
|
)
|
|
req.add_header('Content-Type', 'application/json')
|
|
data = json.dumps(o)
|
|
logg.debug('(HTTP) poll receipt attempt {} {}'.format(i, data))
|
|
res = urlopen(req, data=data.encode('utf-8'))
|
|
r = json.load(res)
|
|
|
|
e = jsonrpc_result(r, error_parser)
|
|
if e != None:
|
|
logg.debug('(HTTP) poll receipt completed {}'.format(r))
|
|
logg.debug('e {}'.format(strip_0x(e['status'])))
|
|
if strip_0x(e['status']) == '00':
|
|
raise RevertEthException(tx_hash_hex)
|
|
return e
|
|
|
|
if timeout > 0.0:
|
|
delta = (datetime.datetime.utcnow() - t) + datetime.timedelta(seconds=delay)
|
|
if delta.total_seconds() >= timeout:
|
|
raise TimeoutError(tx_hash)
|
|
|
|
time.sleep(delay)
|
|
i += 1
|
|
|
|
|
|
class EthUnixConnection(JSONRPCUnixConnection):
|
|
|
|
def wait(self, tx_hash_hex, delay=0.5, timeout=0.0, error_parser=error_parser):
|
|
raise NotImplementedError('Not yet implemented for unix socket')
|
|
|
|
|
|
class EthUnixSignerConnection(EthUnixConnection):
|
|
|
|
def sign_transaction_to_rlp(self, tx):
|
|
txs = tx.serialize()
|
|
logg.debug('serializing {}'.format(txs))
|
|
# TODO: because some rpc servers may fail when chainId is included, we are forced to spend cpu here on this
|
|
chain_id = txs.get('chainId') or 1
|
|
if self.chain_spec != None:
|
|
chain_id = self.chain_spec.chain_id()
|
|
txs['chainId'] = add_0x(chain_id.to_bytes(2, 'big').hex())
|
|
txs['from'] = add_0x(tx.sender)
|
|
o = sign_transaction(txs)
|
|
r = self.do(o)
|
|
logg.debug('sig got {}'.format(r))
|
|
return bytes.fromhex(strip_0x(r))
|
|
|
|
|
|
def sign_message(self, msg):
|
|
o = sign_message(msg)
|
|
return self.do(o)
|