commit f0e00152b71c8111efe1ddb212261b043c54168a
parent 347e117eb95db40afded7fa333d336d78f9ede09
Author: nolash <dev@holbrook.no>
Date: Sun, 10 Jan 2021 18:27:44 +0100
Add eth adapter to tx helper
Diffstat:
6 files changed, 97 insertions(+), 20 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
@@ -1,7 +1,7 @@
* 0.4.13-unreleased
- Implement DictKeystore
- Remove unused insert_key method in keystore interface
- - Add transaction executor helper
+ - Add transaction executor helper, with adapter helper for eth
* 0.4.12
- Enforce hex strings in signer backend for sign message
* 0.4.11
diff --git a/crypto_dev_signer/eth/helper/__init__.py b/crypto_dev_signer/eth/helper/__init__.py
@@ -0,0 +1 @@
+from .tx import EthTxExecutor
diff --git a/crypto_dev_signer/eth/helper/tx.py b/crypto_dev_signer/eth/helper/tx.py
@@ -0,0 +1,49 @@
+# standard imports
+import logging
+
+# local imports
+from crypto_dev_signer.helper import TxExecutor
+
+logg = logging.getLogger()
+logging.getLogger('web3').setLevel(logging.CRITICAL)
+logging.getLogger('urllib3').setLevel(logging.CRITICAL)
+
+
+class EthTxExecutor(TxExecutor):
+
+ def __init__(self, w3, sender, signer, chain_id, verifier=None, block=False):
+ self.w3 = w3
+ nonce = self.w3.eth.getTransactionCount(sender, 'pending')
+ super(EthTxExecutor, self).__init__(sender, signer, self.translator, self.dispatcher, self.reporter, nonce, chain_id, self.fee_helper, self.fee_price_helper, verifier, block)
+
+
+ def fee_helper(self, tx):
+ estimate = self.w3.eth.estimateGas(tx)
+ if estimate < 21000:
+ estimate = 21000
+ logg.debug('estimate {} {}'.format(tx, estimate))
+ return estimate
+
+
+ def fee_price_helper(self):
+ return self.w3.eth.gasPrice
+
+
+ def dispatcher(self, tx):
+ return self.w3.eth.sendRawTransaction(tx)
+
+
+ def reporter(self, tx):
+ return self.w3.eth.getTransactionReceipt(tx)
+
+
+ def translator(self, tx):
+ if tx.get('feePrice') != None:
+ tx['gasPrice'] = tx['feePrice']
+ del tx['feePrice']
+
+ if tx.get('feeUnits') != None:
+ tx['gas'] = tx['feeUnits']
+ del tx['feeUnits']
+
+ return tx
diff --git a/crypto_dev_signer/helper/tx.py b/crypto_dev_signer/helper/tx.py
@@ -13,8 +13,9 @@ logg = logging.getLogger()
class TxExecutor:
- def __init__(self, sender, signer, dispatcher, reporter, nonce, chain_id, fee_helper=None, fee_price_helper=None, verifier=None, block=False):
+ def __init__(self, sender, signer, translator, dispatcher, reporter, nonce, chain_id, fee_helper=None, fee_price_helper=None, verifier=None, block=False):
self.sender = sender
+ self.translator = translator
self.nonce = nonce
self.signer = signer
self.dispatcher = dispatcher
@@ -33,7 +34,7 @@ class TxExecutor:
self.verifier = verifier
- def noop_fee_helper(self, sender, code, inputs):
+ def noop_fee_helper(self, tx):
return 1
@@ -45,21 +46,29 @@ class TxExecutor:
return rcpt
+ def noop_translator(self, tx):
+ return tx
+
+
def sign_and_send(self, builder, force_wait=False):
- fee_units = self.fee_helper(self.sender, None, None)
+
+ fee_price = self.fee_price_helper()
tx_tpl = {
'from': self.sender,
'chainId': self.chain_id,
- 'feeUnits': fee_units,
- 'feePrice': self.fee_price_helper(),
+ 'feeUnits': 0, #fee_units,
+ 'feePrice': fee_price,
'nonce': self.nonce,
}
- tx = tx_tpl
+ tx = self.translator(tx_tpl)
for b in builder:
tx = b(tx)
+ tx['feeUnits'] = self.fee_helper(tx)
+ tx = self.translator(tx)
+
logg.debug('from {} nonce {} tx {}'.format(self.sender, self.nonce, tx))
chain_tx = EIP155Transaction(tx, self.nonce, self.chain_id)
diff --git a/setup.py b/setup.py
@@ -24,13 +24,14 @@ f.close()
setup(
name="crypto-dev-signer",
- version="0.4.13b1",
+ version="0.4.13b2",
description="A signer and keystore daemon and library for cryptocurrency software development",
author="Louis Holbrook",
author_email="dev@holbrook.no",
packages=[
'crypto_dev_signer.eth.signer',
'crypto_dev_signer.eth.web3ext',
+ 'crypto_dev_signer.eth.helper',
'crypto_dev_signer.eth',
'crypto_dev_signer.keystore',
'crypto_dev_signer.runnable',
diff --git a/test/test_helper.py b/test/test_helper.py
@@ -3,10 +3,14 @@ import unittest
import logging
import os
+# third-party imports
+import web3
+
# local imports
from crypto_dev_signer.keystore import DictKeystore
from crypto_dev_signer.eth.signer import ReferenceSigner
from crypto_dev_signer.helper import TxExecutor
+from crypto_dev_signer.eth.helper import EthTxExecutor
logging.basicConfig(level=logging.DEBUG)
logg = logging.getLogger()
@@ -29,21 +33,23 @@ class MockEthTxBackend:
def fee_price_helper(self):
return 21
- def fee_helper(self, sender, code, inputs):
- logg.debug('fee helper code {} inputs {}'.format(code, inputs))
+ def fee_helper(self, tx):
+ logg.debug('fee helper tx {}'.format(tx))
return 2
def builder(self, tx):
- return {
- 'from': tx['from'],
- 'to': '0x' + os.urandom(20).hex(),
- 'data': '',
- 'gasPrice': tx['feePrice'],
- 'gas': tx['feeUnits'],
- }
+ return tx
def builder_two(self, tx):
- tx['value'] = 1024
+ tx['value'] = 10243
+ tx['to'] = web3.Web3.toChecksumAddress('0x' + os.urandom(20).hex())
+ tx['data'] = ''
+ if tx.get('feePrice') != None:
+ tx['gasPrice'] = tx['feePrice']
+ del tx['feePrice']
+ if tx.get('feeUnits') != None:
+ tx['gas'] = tx['feeUnits']
+ del tx['feeUnits']
return tx
@@ -66,10 +72,21 @@ class TestHelper(unittest.TestCase):
def test_helper(self):
backend = MockEthTxBackend()
- executor = TxExecutor(self.address_hex, self.signer, backend.dispatcher, backend.reporter, 666, 13, backend.fee_helper, backend.fee_price_helper, backend.verifier)
+ executor = TxExecutor(self.address_hex, self.signer, backend.builder, backend.dispatcher, backend.reporter, 666, 13, backend.fee_helper, backend.fee_price_helper, backend.verifier)
+
+ tx_ish = {'from': self.address_hex}
+ executor.sign_and_send([backend.builder_two])
+
+
+ def test_eth_helper(self):
+ backend = MockEthTxBackend()
+ w3 = web3.Web3(web3.Web3.HTTPProvider('http://localhost:8545'))
+ executor = EthTxExecutor(w3, self.address_hex, self.signer, 8996)
tx_ish = {'from': self.address_hex}
- executor.sign_and_send([backend.builder, backend.builder_two])
+ #executor.sign_and_send([backend.builder, backend.builder_two])
+ with self.assertRaises(ValueError):
+ executor.sign_and_send([backend.builder_two])
if __name__ == '__main__':