From 23fe79903f81cae703acd1092d2f469d3efc79d6 Mon Sep 17 00:00:00 2001 From: Alex Barnsley <8069294+alexbarnsley@users.noreply.github.com> Date: Mon, 24 Feb 2025 18:21:01 +0000 Subject: [PATCH 1/5] refactor: transaction builder handle strings from unit converter --- crypto/transactions/builder/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/transactions/builder/base.py b/crypto/transactions/builder/base.py index 89330386..59336753 100644 --- a/crypto/transactions/builder/base.py +++ b/crypto/transactions/builder/base.py @@ -25,7 +25,7 @@ def __str__(self): def new(cls, data: Optional[dict] = None): return cls(data) - def gas_limit(self, gas_limit: int): + def gas_limit(self, gas_limit: int | str): self.transaction.data['gasLimit'] = gas_limit return self @@ -33,7 +33,7 @@ def recipient_address(self, recipient_address: str): self.transaction.data['recipientAddress'] = recipient_address return self - def gas_price(self, gas_price: int): + def gas_price(self, gas_price: int | str): self.transaction.data['gasPrice'] = gas_price return self From 34b7499baa25e0ae58c714cc89155c9d274fb72b Mon Sep 17 00:00:00 2001 From: Alex Barnsley <8069294+alexbarnsley@users.noreply.github.com> Date: Mon, 24 Feb 2025 18:21:23 +0000 Subject: [PATCH 2/5] test --- tests/transactions/builder/conftest.py | 6 ++++++ .../builder/test_transfer_builder.py | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/tests/transactions/builder/conftest.py b/tests/transactions/builder/conftest.py index c819610c..7e43b9a1 100644 --- a/tests/transactions/builder/conftest.py +++ b/tests/transactions/builder/conftest.py @@ -17,3 +17,9 @@ def username(): """Username used for tests""" return 'fixture' + +@pytest.fixture +def address(): + """Address used for tests""" + + return '0x6F0182a0cc707b055322CcF6d4CB6a5Aff1aEb22' diff --git a/tests/transactions/builder/test_transfer_builder.py b/tests/transactions/builder/test_transfer_builder.py index 7a053bb7..e1b2fe0c 100644 --- a/tests/transactions/builder/test_transfer_builder.py +++ b/tests/transactions/builder/test_transfer_builder.py @@ -1,4 +1,5 @@ from crypto.transactions.builder.transfer_builder import TransferBuilder +from crypto.utils.unit_converter import UnitConverter def test_it_should_sign_it_with_a_passphrase(passphrase, load_transaction_fixture): fixture = load_transaction_fixture('transfer') @@ -27,3 +28,21 @@ def test_it_should_sign_it_with_a_passphrase(passphrase, load_transaction_fixtur assert builder.transaction.serialize().hex() == fixture['serialized'] assert builder.transaction.data['id'] == fixture['data']['id'] assert builder.verify() + +def test_it_should_handle_unit_converter(passphrase, address): + builder = ( + TransferBuilder() + .gas_price(UnitConverter.parse_units(5, 'gwei')) + .nonce('1') + .gas_limit(UnitConverter.parse_units(0.1, 'gwei')) + .recipient_address(address) + .value(UnitConverter.parse_units(10, 'ark')) + .sign(passphrase) + ) + + assert builder.transaction.data['gasPrice'] == '5000000000' + assert builder.transaction.data['nonce'] == '1' + assert builder.transaction.data['gasLimit'] == '100000000' + assert builder.transaction.data['value'] == '10000000000000000000' + + assert builder.verify() From 59ef10c42ba8771eddc09e7323a04642178030c0 Mon Sep 17 00:00:00 2001 From: Alex Barnsley <8069294+alexbarnsley@users.noreply.github.com> Date: Mon, 24 Feb 2025 18:21:47 +0000 Subject: [PATCH 3/5] tidy --- tests/transactions/test_serializer.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/transactions/test_serializer.py b/tests/transactions/test_serializer.py index d97ebb5c..c355b111 100644 --- a/tests/transactions/test_serializer.py +++ b/tests/transactions/test_serializer.py @@ -14,7 +14,6 @@ def test_transfer_serialization(load_transaction_fixture): def test_vote_serialization(load_transaction_fixture): fixture = load_transaction_fixture('vote') transaction = Vote(fixture['data']) - print(f"transaction: {transaction.data}") serializer = Serializer.new(transaction) assert serializer.serialize().hex() == fixture['serialized'] @@ -34,4 +33,4 @@ def test_validator_resignation_serialization(load_transaction_fixture): fixture = load_transaction_fixture('validator-resignation') transaction = ValidatorResignation(fixture['data']) serializer = Serializer.new(transaction) - assert serializer.serialize().hex() == fixture['serialized'] \ No newline at end of file + assert serializer.serialize().hex() == fixture['serialized'] From 57d82b71b780dd47035b50b6e0b464459a9cd751 Mon Sep 17 00:00:00 2001 From: Alex Barnsley <8069294+alexbarnsley@users.noreply.github.com> Date: Mon, 24 Feb 2025 18:24:49 +0000 Subject: [PATCH 4/5] use union for typehint --- crypto/transactions/builder/base.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crypto/transactions/builder/base.py b/crypto/transactions/builder/base.py index 59336753..95dbbaf4 100644 --- a/crypto/transactions/builder/base.py +++ b/crypto/transactions/builder/base.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import Optional, Union from crypto.configuration.network import get_network from crypto.identity.private_key import PrivateKey @@ -25,7 +25,7 @@ def __str__(self): def new(cls, data: Optional[dict] = None): return cls(data) - def gas_limit(self, gas_limit: int | str): + def gas_limit(self, gas_limit: Union[int, str]): self.transaction.data['gasLimit'] = gas_limit return self @@ -33,7 +33,7 @@ def recipient_address(self, recipient_address: str): self.transaction.data['recipientAddress'] = recipient_address return self - def gas_price(self, gas_price: int | str): + def gas_price(self, gas_price: Union[int, str]): self.transaction.data['gasPrice'] = gas_price return self From f0536e887303f4099fee8f4e84f1a64c32cd11a7 Mon Sep 17 00:00:00 2001 From: Alex Barnsley <8069294+alexbarnsley@users.noreply.github.com> Date: Wed, 26 Feb 2025 13:22:34 +0000 Subject: [PATCH 5/5] use int for unit converter and relevant values --- crypto/transactions/builder/base.py | 13 ++--- .../transactions/builder/transfer_builder.py | 4 +- crypto/utils/unit_converter.py | 8 +-- .../builder/test_evm_call_builder.py | 2 +- .../builder/test_transfer_builder.py | 8 +-- .../builder/test_unvote_builder.py | 4 +- .../test_validator_registration_builder.py | 4 +- .../test_validator_resignation_builder.py | 4 +- .../transactions/builder/test_vote_builder.py | 4 +- tests/utils/test_unit_converter.py | 56 +++++++++---------- 10 files changed, 53 insertions(+), 54 deletions(-) diff --git a/crypto/transactions/builder/base.py b/crypto/transactions/builder/base.py index 95dbbaf4..e0621711 100644 --- a/crypto/transactions/builder/base.py +++ b/crypto/transactions/builder/base.py @@ -1,5 +1,4 @@ -from typing import Optional, Union - +from typing import Optional from crypto.configuration.network import get_network from crypto.identity.private_key import PrivateKey from crypto.transactions.types.abstract_transaction import AbstractTransaction @@ -8,7 +7,7 @@ class AbstractTransactionBuilder: def __init__(self, data: Optional[dict] = None): default_data = { - 'value': '0', + 'value': 0, 'senderPublicKey': '', 'gasPrice': '5', 'nonce': '1', @@ -25,16 +24,16 @@ def __str__(self): def new(cls, data: Optional[dict] = None): return cls(data) - def gas_limit(self, gas_limit: Union[int, str]): - self.transaction.data['gasLimit'] = gas_limit + def gas_limit(self, gas_limit: int): + self.transaction.data['gasLimit'] = int(gas_limit) return self def recipient_address(self, recipient_address: str): self.transaction.data['recipientAddress'] = recipient_address return self - def gas_price(self, gas_price: Union[int, str]): - self.transaction.data['gasPrice'] = gas_price + def gas_price(self, gas_price: int): + self.transaction.data['gasPrice'] = int(gas_price) return self def nonce(self, nonce: str): diff --git a/crypto/transactions/builder/transfer_builder.py b/crypto/transactions/builder/transfer_builder.py index 9af863c8..5029e06e 100644 --- a/crypto/transactions/builder/transfer_builder.py +++ b/crypto/transactions/builder/transfer_builder.py @@ -3,8 +3,8 @@ class TransferBuilder(AbstractTransactionBuilder): - def value(self, value: str): - self.transaction.data['value'] = value + def value(self, value: int): + self.transaction.data['value'] = int(value) self.transaction.refresh_payload_data() return self diff --git a/crypto/utils/unit_converter.py b/crypto/utils/unit_converter.py index 39688849..be991922 100644 --- a/crypto/utils/unit_converter.py +++ b/crypto/utils/unit_converter.py @@ -8,18 +8,18 @@ class UnitConverter: ARK_MULTIPLIER = '1000000000000000000' # 1e18 @staticmethod - def parse_units(value: Union[float, int, str, Decimal], unit='ark') -> str: + def parse_units(value: Union[float, int, str, Decimal], unit='ark') -> int: value = Decimal(str(value)) unit = unit.lower() if unit == 'wei': - return format((value * Decimal(UnitConverter.WEI_MULTIPLIER)).normalize(), 'f') + return int((value * Decimal(UnitConverter.WEI_MULTIPLIER)).normalize()) if unit == 'gwei': - return format((value * Decimal(UnitConverter.GWEI_MULTIPLIER)).normalize(), 'f') + return int((value * Decimal(UnitConverter.GWEI_MULTIPLIER)).normalize()) if unit == 'ark': - return format((value * Decimal(UnitConverter.ARK_MULTIPLIER)).normalize(), 'f') + return int((value * Decimal(UnitConverter.ARK_MULTIPLIER)).normalize()) raise ValueError(f"Unsupported unit: {unit}. Supported units are 'wei', 'gwei', and 'ark'.") diff --git a/tests/transactions/builder/test_evm_call_builder.py b/tests/transactions/builder/test_evm_call_builder.py index 3dfc1635..edfc7a71 100644 --- a/tests/transactions/builder/test_evm_call_builder.py +++ b/tests/transactions/builder/test_evm_call_builder.py @@ -19,7 +19,7 @@ def test_evm_call_transaction(passphrase, load_transaction_fixture): assert builder.transaction.data['network'] == fixture['data']['network'] assert builder.transaction.data['gasLimit'] == fixture['data']['gasLimit'] assert builder.transaction.data['recipientAddress'].lower() == fixture['data']['recipientAddress'].lower() - assert builder.transaction.data['value'] == fixture['data']['value'] + assert builder.transaction.data['value'] == int(fixture['data']['value']) assert builder.transaction.data['v'] == fixture['data']['v'] assert builder.transaction.data['r'] == fixture['data']['r'] assert builder.transaction.data['s'] == fixture['data']['s'] diff --git a/tests/transactions/builder/test_transfer_builder.py b/tests/transactions/builder/test_transfer_builder.py index e1b2fe0c..4df0c498 100644 --- a/tests/transactions/builder/test_transfer_builder.py +++ b/tests/transactions/builder/test_transfer_builder.py @@ -20,7 +20,7 @@ def test_it_should_sign_it_with_a_passphrase(passphrase, load_transaction_fixtur assert builder.transaction.data['network'] == fixture['data']['network'] assert builder.transaction.data['gasLimit'] == fixture['data']['gasLimit'] assert builder.transaction.data['recipientAddress'] == fixture['data']['recipientAddress'] - assert builder.transaction.data['value'] == fixture['data']['value'] + assert builder.transaction.data['value'] == int(fixture['data']['value']) assert builder.transaction.data['v'] == fixture['data']['v'] assert builder.transaction.data['r'] == fixture['data']['r'] assert builder.transaction.data['s'] == fixture['data']['s'] @@ -40,9 +40,9 @@ def test_it_should_handle_unit_converter(passphrase, address): .sign(passphrase) ) - assert builder.transaction.data['gasPrice'] == '5000000000' + assert builder.transaction.data['gasPrice'] == 5000000000 assert builder.transaction.data['nonce'] == '1' - assert builder.transaction.data['gasLimit'] == '100000000' - assert builder.transaction.data['value'] == '10000000000000000000' + assert builder.transaction.data['gasLimit'] == 100000000 + assert builder.transaction.data['value'] == 10000000000000000000 assert builder.verify() diff --git a/tests/transactions/builder/test_unvote_builder.py b/tests/transactions/builder/test_unvote_builder.py index 56bd3929..dd430f3c 100644 --- a/tests/transactions/builder/test_unvote_builder.py +++ b/tests/transactions/builder/test_unvote_builder.py @@ -18,7 +18,7 @@ def test_unvote_transaction(passphrase, load_transaction_fixture): assert builder.transaction.data['network'] == fixture['data']['network'] assert builder.transaction.data['gasLimit'] == fixture['data']['gasLimit'] assert builder.transaction.data['recipientAddress'] == fixture['data']['recipientAddress'] - assert builder.transaction.data['value'] == fixture['data']['value'] + assert builder.transaction.data['value'] == int(fixture['data']['value']) assert builder.transaction.data['v'] == fixture['data']['v'] assert builder.transaction.data['r'] == fixture['data']['r'] assert builder.transaction.data['s'] == fixture['data']['s'] @@ -44,7 +44,7 @@ def test_unvote_transaction_with_default_recipient_address(passphrase, load_tran assert builder.transaction.data['network'] == fixture['data']['network'] assert builder.transaction.data['gasLimit'] == fixture['data']['gasLimit'] assert builder.transaction.data['recipientAddress'].lower() == fixture['data']['recipientAddress'].lower() - assert builder.transaction.data['value'] == fixture['data']['value'] + assert builder.transaction.data['value'] == int(fixture['data']['value']) assert builder.transaction.data['v'] == fixture['data']['v'] assert builder.transaction.data['r'] == fixture['data']['r'] assert builder.transaction.data['s'] == fixture['data']['s'] diff --git a/tests/transactions/builder/test_validator_registration_builder.py b/tests/transactions/builder/test_validator_registration_builder.py index 73221b44..9ef26601 100644 --- a/tests/transactions/builder/test_validator_registration_builder.py +++ b/tests/transactions/builder/test_validator_registration_builder.py @@ -20,7 +20,7 @@ def test_validator_registration_transaction(passphrase, validator_public_key, lo assert builder.transaction.data['network'] == fixture['data']['network'] assert builder.transaction.data['gasLimit'] == fixture['data']['gasLimit'] assert builder.transaction.data['recipientAddress'] == fixture['data']['recipientAddress'] - assert builder.transaction.data['value'] == fixture['data']['value'] + assert builder.transaction.data['value'] == int(fixture['data']['value']) assert builder.transaction.data['v'] == fixture['data']['v'] assert builder.transaction.data['r'] == fixture['data']['r'] assert builder.transaction.data['s'] == fixture['data']['s'] @@ -47,7 +47,7 @@ def test_validator_registration_transaction_with_default_recipient_address(passp assert builder.transaction.data['network'] == fixture['data']['network'] assert builder.transaction.data['gasLimit'] == fixture['data']['gasLimit'] assert builder.transaction.data['recipientAddress'].lower() == fixture['data']['recipientAddress'].lower() - assert builder.transaction.data['value'] == fixture['data']['value'] + assert builder.transaction.data['value'] == int(fixture['data']['value']) assert builder.transaction.data['v'] == fixture['data']['v'] assert builder.transaction.data['r'] == fixture['data']['r'] assert builder.transaction.data['s'] == fixture['data']['s'] diff --git a/tests/transactions/builder/test_validator_resignation_builder.py b/tests/transactions/builder/test_validator_resignation_builder.py index 9a2c359d..b5cb95fe 100644 --- a/tests/transactions/builder/test_validator_resignation_builder.py +++ b/tests/transactions/builder/test_validator_resignation_builder.py @@ -18,7 +18,7 @@ def test_validator_resignation_transaction(passphrase, load_transaction_fixture) assert builder.transaction.data['network'] == fixture['data']['network'] assert builder.transaction.data['gasLimit'] == fixture['data']['gasLimit'] assert builder.transaction.data['recipientAddress'] == fixture['data']['recipientAddress'] - assert builder.transaction.data['value'] == fixture['data']['value'] + assert builder.transaction.data['value'] == int(fixture['data']['value']) assert builder.transaction.data['v'] == fixture['data']['v'] assert builder.transaction.data['r'] == fixture['data']['r'] assert builder.transaction.data['s'] == fixture['data']['s'] @@ -44,7 +44,7 @@ def test_validator_resignation_transaction_with_default_recipient_address(passph assert builder.transaction.data['network'] == fixture['data']['network'] assert builder.transaction.data['gasLimit'] == fixture['data']['gasLimit'] assert builder.transaction.data['recipientAddress'].lower() == fixture['data']['recipientAddress'].lower() - assert builder.transaction.data['value'] == fixture['data']['value'] + assert builder.transaction.data['value'] == int(fixture['data']['value']) assert builder.transaction.data['v'] == fixture['data']['v'] assert builder.transaction.data['r'] == fixture['data']['r'] assert builder.transaction.data['s'] == fixture['data']['s'] diff --git a/tests/transactions/builder/test_vote_builder.py b/tests/transactions/builder/test_vote_builder.py index afa815e8..234124d4 100644 --- a/tests/transactions/builder/test_vote_builder.py +++ b/tests/transactions/builder/test_vote_builder.py @@ -19,7 +19,7 @@ def test_vote_transaction(passphrase, load_transaction_fixture): assert builder.transaction.data['network'] == fixture['data']['network'] assert builder.transaction.data['gasLimit'] == fixture['data']['gasLimit'] assert builder.transaction.data['recipientAddress'] == fixture['data']['recipientAddress'] - assert builder.transaction.data['value'] == fixture['data']['value'] + assert builder.transaction.data['value'] == int(fixture['data']['value']) assert builder.transaction.data['v'] == fixture['data']['v'] assert builder.transaction.data['r'] == fixture['data']['r'] assert builder.transaction.data['s'] == fixture['data']['s'] @@ -46,7 +46,7 @@ def test_vote_transaction_with_default_recipient_address(passphrase, load_transa assert builder.transaction.data['network'] == fixture['data']['network'] assert builder.transaction.data['gasLimit'] == fixture['data']['gasLimit'] assert builder.transaction.data['recipientAddress'].lower() == fixture['data']['recipientAddress'].lower() - assert builder.transaction.data['value'] == fixture['data']['value'] + assert builder.transaction.data['value'] == int(fixture['data']['value']) assert builder.transaction.data['v'] == fixture['data']['v'] assert builder.transaction.data['r'] == fixture['data']['r'] assert builder.transaction.data['s'] == fixture['data']['s'] diff --git a/tests/utils/test_unit_converter.py b/tests/utils/test_unit_converter.py index 64886b12..af8e4c44 100644 --- a/tests/utils/test_unit_converter.py +++ b/tests/utils/test_unit_converter.py @@ -2,41 +2,41 @@ from decimal import Decimal def test_it_should_parse_units_into_wei(): - assert UnitConverter.parse_units(1, 'wei') == '1' - assert UnitConverter.parse_units(1.0, 'wei') == '1' - assert UnitConverter.parse_units('1', 'wei') == '1' - assert UnitConverter.parse_units('1.0', 'wei') == '1' + assert UnitConverter.parse_units(1, 'wei') == 1 + assert UnitConverter.parse_units(1.0, 'wei') == 1 + assert UnitConverter.parse_units('1', 'wei') == 1 + assert UnitConverter.parse_units('1.0', 'wei') == 1 - assert UnitConverter.parse_units(Decimal(1), 'wei') == '1' - assert UnitConverter.parse_units(Decimal(1.0), 'wei') == '1' - assert UnitConverter.parse_units(Decimal('1'), 'wei') == '1' - assert UnitConverter.parse_units(Decimal('1.0'), 'wei') == '1' + assert UnitConverter.parse_units(Decimal(1), 'wei') == 1 + assert UnitConverter.parse_units(Decimal(1.0), 'wei') == 1 + assert UnitConverter.parse_units(Decimal('1'), 'wei') == 1 + assert UnitConverter.parse_units(Decimal('1.0'), 'wei') == 1 def test_it_should_parse_units_into_gwei(): - assert UnitConverter.parse_units(1, 'gwei') == '1000000000' - assert UnitConverter.parse_units(1.0, 'gwei') == '1000000000' - assert UnitConverter.parse_units('1', 'gwei') == '1000000000' - assert UnitConverter.parse_units('1.0', 'gwei') == '1000000000' + assert UnitConverter.parse_units(1, 'gwei') == 1000000000 + assert UnitConverter.parse_units(1.0, 'gwei') == 1000000000 + assert UnitConverter.parse_units('1', 'gwei') == 1000000000 + assert UnitConverter.parse_units('1.0', 'gwei') == 1000000000 - assert UnitConverter.parse_units(Decimal(1), 'gwei') == '1000000000' - assert UnitConverter.parse_units(Decimal(1.0), 'gwei') == '1000000000' - assert UnitConverter.parse_units(Decimal('1'), 'gwei') == '1000000000' - assert UnitConverter.parse_units(Decimal('1.0'), 'gwei') == '1000000000' + assert UnitConverter.parse_units(Decimal(1), 'gwei') == 1000000000 + assert UnitConverter.parse_units(Decimal(1.0), 'gwei') == 1000000000 + assert UnitConverter.parse_units(Decimal('1'), 'gwei') == 1000000000 + assert UnitConverter.parse_units(Decimal('1.0'), 'gwei') == 1000000000 def test_it_should_parse_units_into_ark(): - assert UnitConverter.parse_units(1, 'ark') == '1000000000000000000' - assert UnitConverter.parse_units(1.0, 'ark') == '1000000000000000000' - assert UnitConverter.parse_units('1', 'ark') == '1000000000000000000' - assert UnitConverter.parse_units('1.0', 'ark') == '1000000000000000000' + assert UnitConverter.parse_units(1, 'ark') == 1000000000000000000 + assert UnitConverter.parse_units(1.0, 'ark') == 1000000000000000000 + assert UnitConverter.parse_units('1', 'ark') == 1000000000000000000 + assert UnitConverter.parse_units('1.0', 'ark') == 1000000000000000000 - assert UnitConverter.parse_units(Decimal(1), 'ark') == '1000000000000000000' - assert UnitConverter.parse_units(Decimal(1.0), 'ark') == '1000000000000000000' - assert UnitConverter.parse_units(Decimal('1'), 'ark') == '1000000000000000000' - assert UnitConverter.parse_units(Decimal('1.0'), 'ark') == '1000000000000000000' + assert UnitConverter.parse_units(Decimal(1), 'ark') == 1000000000000000000 + assert UnitConverter.parse_units(Decimal(1.0), 'ark') == 1000000000000000000 + assert UnitConverter.parse_units(Decimal('1'), 'ark') == 1000000000000000000 + assert UnitConverter.parse_units(Decimal('1.0'), 'ark') == 1000000000000000000 def test_it_should_parse_decimal_units_into_ark(): - assert UnitConverter.parse_units(0.1, 'ark') == '100000000000000000' - assert UnitConverter.parse_units('0.1', 'ark') == '100000000000000000' + assert UnitConverter.parse_units(0.1, 'ark') == 100000000000000000 + assert UnitConverter.parse_units('0.1', 'ark') == 100000000000000000 def test_it_should_format_units_from_wei(): assert UnitConverter.format_units(1, 'wei') == 1.0 @@ -76,8 +76,8 @@ def test_it_should_throw_exception_for_unsupported_unit_in_format(): assert str(e) == 'Unsupported unit: unsupported. Supported units are \'wei\', \'gwei\', and \'ark\'.' def test_it_should_parse_units_into_ark_with_fraction(): - assert UnitConverter.parse_units(0.1, 'ark') == '100000000000000000' - assert UnitConverter.parse_units('0.1', 'ark') == '100000000000000000' + assert UnitConverter.parse_units(0.1, 'ark') == 100000000000000000 + assert UnitConverter.parse_units('0.1', 'ark') == 100000000000000000 def test_it_should_convert_wei_to_ark(): assert UnitConverter.wei_to_ark(1, 'DARK') == '0.000000000000000001 DARK'