Add transaction executor helper
This commit is contained in:
@@ -1,2 +1,6 @@
|
||||
class UnknownAccountError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class TransactionRevertError(Exception):
|
||||
pass
|
||||
|
||||
1
crypto_dev_signer/helper/__init__.py
Normal file
1
crypto_dev_signer/helper/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .tx import TxExecutor
|
||||
71
crypto_dev_signer/helper/tx.py
Normal file
71
crypto_dev_signer/helper/tx.py
Normal file
@@ -0,0 +1,71 @@
|
||||
# standard imports
|
||||
import logging
|
||||
|
||||
# third-party imports
|
||||
from crypto_dev_signer.eth.transaction import EIP155Transaction
|
||||
|
||||
# local imports
|
||||
from crypto_dev_signer.error import TransactionRevertError
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
class TxExecutor:
|
||||
|
||||
def __init__(self, sender, signer, dispatcher, reporter, nonce, chain_id, fee_helper, fee_price_helper, block=False):
|
||||
self.sender = sender
|
||||
self.nonce = nonce
|
||||
self.signer = signer
|
||||
self.dispatcher = dispatcher
|
||||
self.reporter = reporter
|
||||
self.block = bool(block)
|
||||
self.chain_id = chain_id
|
||||
self.tx_hashes = []
|
||||
self.fee_price_helper = fee_price_helper
|
||||
self.fee_helper = fee_helper
|
||||
|
||||
|
||||
def sign_and_send(self, builder, force_wait=False):
|
||||
fee_units = self.fee_helper(self.sender, None, None)
|
||||
|
||||
tx_tpl = {
|
||||
'from': self.sender,
|
||||
'chainId': self.chain_id,
|
||||
'fee': fee_units,
|
||||
'feePrice': self.fee_price_helper(),
|
||||
'nonce': self.nonce,
|
||||
}
|
||||
tx = None
|
||||
for b in builder:
|
||||
tx = b(tx_tpl, tx)
|
||||
|
||||
logg.debug('from {} nonce {} tx {}'.format(self.sender, self.nonce, tx))
|
||||
|
||||
chain_tx = EIP155Transaction(tx, self.nonce, self.chain_id)
|
||||
signature = self.signer.signTransaction(chain_tx)
|
||||
chain_tx_serialized = chain_tx.rlp_serialize()
|
||||
tx_hash = self.dispatcher('0x' + chain_tx_serialized.hex())
|
||||
self.tx_hashes.append(tx_hash)
|
||||
self.nonce += 1
|
||||
rcpt = None
|
||||
if self.block or force_wait:
|
||||
rcpt = self.wait_for(tx_hash)
|
||||
logg.info('tx {} fee used: {}'.format(tx_hash.hex(), rcpt['feeUsed']))
|
||||
return (tx_hash.hex(), rcpt)
|
||||
|
||||
|
||||
def wait_for(self, tx_hash=None):
|
||||
if tx_hash == None:
|
||||
tx_hash = self.tx_hashes[len(self.tx_hashes)-1]
|
||||
i = 1
|
||||
while True:
|
||||
try:
|
||||
#return self.w3.eth.getTransactionReceipt(tx_hash)
|
||||
return self.reporter(tx_hash)
|
||||
except web3.exceptions.TransactionNotFound:
|
||||
logg.debug('poll #{} for {}'.format(i, tx_hash.hex()))
|
||||
i += 1
|
||||
time.sleep(1)
|
||||
if rcpt['status'] == 0:
|
||||
raise TransactionRevertError(tx_hash)
|
||||
return rcpt
|
||||
33
crypto_dev_signer/keystore/dict.py
Normal file
33
crypto_dev_signer/keystore/dict.py
Normal file
@@ -0,0 +1,33 @@
|
||||
# standard imports
|
||||
import logging
|
||||
|
||||
# local imports
|
||||
from . import keyapi
|
||||
from .interface import Keystore
|
||||
from crypto_dev_signer.error import UnknownAccountError
|
||||
from crypto_dev_signer.common import strip_hex_prefix
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
class DictKeystore(Keystore):
|
||||
|
||||
def __init__(self):
|
||||
self.keys = {}
|
||||
|
||||
|
||||
def get(self, address, password=None):
|
||||
if password != None:
|
||||
logg.debug('password ignored as dictkeystore doesnt do encryption')
|
||||
try:
|
||||
return self.keys[address]
|
||||
except KeyError:
|
||||
raise UnknownAccountError(address)
|
||||
|
||||
|
||||
def import_key(self, pk, password=None):
|
||||
pubk = keyapi.private_key_to_public_key(pk)
|
||||
address_hex = pubk.to_checksum_address()
|
||||
address_hex_clean = strip_hex_prefix(address_hex)
|
||||
self.keys[address_hex_clean] = pk.to_bytes()
|
||||
return address_hex
|
||||
Reference in New Issue
Block a user