diff --git a/crypto/configuration/network.py b/crypto/configuration/network.py index c98debc..3602051 100644 --- a/crypto/configuration/network.py +++ b/crypto/configuration/network.py @@ -1,53 +1,26 @@ -from datetime import datetime -from typing import Type, TypedDict, Union -from crypto.networks.mainnet import Mainnet +from crypto.networks.abstract_network import AbstractNetwork from crypto.networks.testnet import Testnet -class NetworkType(TypedDict): - epoch: datetime - wif: str - chain_id: int +class Network: + _network: AbstractNetwork -network: NetworkType = { - 'epoch': Testnet.epoch, - 'wif': Testnet.wif, - 'chain_id': Testnet.chain_id, -} + @classmethod + def set_network(cls, network: AbstractNetwork) -> None: + """Set what network you want to use in the crypto library -def set_network(network_object: Union[Type[Mainnet], Type[Testnet]]) -> None: - """Set what network you want to use in the crypto library + Args: + network_object: Testnet, Devnet, Mainnet + """ - Args: - network_object: Testnet, Devnet, Mainnet - """ - global network + cls._network = network - network = { - 'epoch': network_object.epoch, - 'wif': network_object.wif, - 'chain_id': network_object.chain_id, - } + @classmethod + def get_network(cls) -> AbstractNetwork: + """Get settings for a selected network -def get_network() -> NetworkType: - """Get settings for a selected network, default network is devnet + Returns: + AbstractNetwork: network settings (default network is testnet) + """ + return cls._network - Returns: - dict: network settings (default network is devnet) - """ - return network - -def set_custom_network(epoch: datetime, wif: str, chain_id: int) -> None: - """Set custom network - - Args: - epoch (datetime): chains epoch time - wif (str): chains wif - chain_id (int): chain id - """ - global network - - network = { - 'epoch': epoch, - 'wif': wif, - 'chain_id': chain_id - } +Network.set_network(Testnet()) diff --git a/crypto/identity/private_key.py b/crypto/identity/private_key.py index 5e1956a..9b186e1 100644 --- a/crypto/identity/private_key.py +++ b/crypto/identity/private_key.py @@ -4,7 +4,7 @@ from Cryptodome.Hash import keccak from base58 import b58decode -from crypto.configuration.network import get_network +from crypto.configuration.network import Network from crypto.enums.constants import Constants class PrivateKey(object): @@ -76,7 +76,7 @@ def from_wif(cls, wif: str): wif = b58decode(wif).hex() version = wif[0:2] - if version != get_network()['wif']: + if version != Network.get_network().wif(): raise ValueError(f"Invalid network version: {version}") private_key = wif[2:66] diff --git a/crypto/identity/wif.py b/crypto/identity/wif.py index a8860db..ba3cb90 100644 --- a/crypto/identity/wif.py +++ b/crypto/identity/wif.py @@ -5,7 +5,7 @@ from binary.unsigned_integer.writer import write_bit8 -from crypto.configuration.network import get_network +from crypto.configuration.network import Network def wif_from_passphrase(passphrase: str, network_wif: Optional[str] = None): """Get wif from passphrase @@ -18,9 +18,9 @@ def wif_from_passphrase(passphrase: str, network_wif: Optional[str] = None): string: wif """ if not network_wif: - network = get_network() + network = Network.get_network() - network_wif = network['wif'] + network_wif = network.wif() private_key = hashlib.sha256(passphrase.encode()) seed = write_bit8(int(network_wif, 16)) + private_key.digest() + write_bit8(0x01) diff --git a/crypto/networks/abstract_network.py b/crypto/networks/abstract_network.py new file mode 100644 index 0000000..6e5ec64 --- /dev/null +++ b/crypto/networks/abstract_network.py @@ -0,0 +1,14 @@ +from abc import ABC, abstractmethod + +class AbstractNetwork(ABC): + @abstractmethod + def chain_id(self) -> int: + """Return the chain ID of the network.""" + + @abstractmethod + def epoch(self) -> str: + """Return the epoch time of the network.""" + + @abstractmethod + def wif(self) -> str: + """Return the WIF (Wallet Import Format) of the network.""" diff --git a/crypto/networks/mainnet.py b/crypto/networks/mainnet.py index 921d84a..9fa8ad1 100644 --- a/crypto/networks/mainnet.py +++ b/crypto/networks/mainnet.py @@ -1,6 +1,11 @@ -from datetime import datetime +from crypto.networks.abstract_network import AbstractNetwork -class Mainnet(object): - epoch = datetime(2017, 3, 21, 13, 00, 00) - wif = 'ba' - chain_id = 10000 +class Mainnet(AbstractNetwork): + def chain_id(self): + return 10000 + + def epoch(self): + return '2017-03-21T13:00:00.000Z' + + def wif(self): + return 'ba' diff --git a/crypto/networks/testnet.py b/crypto/networks/testnet.py index 9796dbc..56995c1 100644 --- a/crypto/networks/testnet.py +++ b/crypto/networks/testnet.py @@ -1,6 +1,11 @@ -from datetime import datetime +from crypto.networks.abstract_network import AbstractNetwork -class Testnet(object): - epoch = datetime(2017, 3, 21, 13, 00, 00) - wif = 'ba' - chain_id = 10000 +class Testnet(AbstractNetwork): + def chain_id(self): + return 10000 + + def epoch(self): + return '2017-03-21T13:00:00.000Z' + + def wif(self): + return 'ba' diff --git a/crypto/transactions/builder/base.py b/crypto/transactions/builder/base.py index 133dc58..8d71366 100644 --- a/crypto/transactions/builder/base.py +++ b/crypto/transactions/builder/base.py @@ -1,5 +1,4 @@ -from typing import Optional -from crypto.configuration.network import get_network +from crypto.configuration.network import Network from crypto.identity.private_key import PrivateKey from crypto.transactions.types.abstract_transaction import AbstractTransaction @@ -11,7 +10,7 @@ def __init__(self, data: dict): 'senderPublicKey': '', 'gasPrice': '5', 'nonce': '1', - 'network': get_network()['chain_id'], + 'network': Network.get_network().chain_id(), 'gasLimit': 1_000_000, 'data': '', diff --git a/crypto/transactions/types/abstract_transaction.py b/crypto/transactions/types/abstract_transaction.py index 5e26d35..16b8454 100644 --- a/crypto/transactions/types/abstract_transaction.py +++ b/crypto/transactions/types/abstract_transaction.py @@ -1,14 +1,12 @@ import json from typing import Optional -from crypto.configuration.network import get_network from crypto.enums.constants import Constants from crypto.enums.contract_abi_type import ContractAbiType from crypto.identity.address import address_from_public_key from crypto.identity.private_key import PrivateKey from crypto.utils.transaction_utils import TransactionUtils from coincurve import PublicKey -from crypto.utils.abi_decoder import AbiDecoder class AbstractTransaction: def __init__(self, data: dict): diff --git a/crypto/utils/slot.py b/crypto/utils/slot.py index 23b3d08..c0aa763 100644 --- a/crypto/utils/slot.py +++ b/crypto/utils/slot.py @@ -1,20 +1,24 @@ -from datetime import datetime +from datetime import datetime, timezone -from crypto.configuration.network import get_network +from crypto.configuration.network import Network -def get_time(): +def get_time() -> int: """Get the time difference between now and network start. Returns: int: difference in seconds """ - now = datetime.utcnow() - network = get_network() - seconds = int((now - network['epoch']).total_seconds()) + now = datetime.now(timezone.utc) + + seconds = int((now - get_epoch()).total_seconds()) + return seconds def get_epoch(): - network = get_network() - return network['epoch'] + epoch_str = Network.get_network().epoch() + if epoch_str.endswith("Z"): + epoch_str = epoch_str[:-1] + "+00:00" + + return datetime.fromisoformat(epoch_str) diff --git a/tests/configuration/test_network.py b/tests/configuration/test_network.py index d16c784..5ac1654 100644 --- a/tests/configuration/test_network.py +++ b/tests/configuration/test_network.py @@ -1,35 +1,44 @@ from datetime import datetime -from crypto.configuration.network import get_network, set_custom_network, set_network +from crypto.configuration.network import Network +from crypto.networks.abstract_network import AbstractNetwork from crypto.networks.testnet import Testnet from crypto.networks.mainnet import Mainnet +class CustomNetwork(AbstractNetwork): + def epoch(self): + return "2024-01-01T13:00:00.000Z" + + def wif(self): + return "82" + + def chain_id(self): + return 20000 def test_get_network(): - result = get_network() - assert result['chain_id'] == 10000 + result = Network.get_network() + assert result.chain_id() == 10000 def test_set_network(): # mainnet - set_network(Mainnet) - result = get_network() - assert result['wif'] == 'ba' - assert result['chain_id'] == 10000 + Network.set_network(Mainnet()) + result = Network.get_network() + assert result.wif() == 'ba' + assert result.chain_id() == 10000 # testnet - set_network(Testnet) - result = get_network() - assert result['wif'] == 'ba' - assert result['chain_id'] == 10000 + Network.set_network(Testnet()) + result = Network.get_network() + assert result.wif() == 'ba' + assert result.chain_id() == 10000 - set_network(Testnet) # set back to Testnet so other tests don't fail + Network.set_network(Testnet()) # set back to Testnet so other tests don't fail def test_set_custom_network(): - epoch_time = datetime(2017, 1, 1, 13, 00, 00) - set_custom_network(epoch_time, '82', 10000) - result = get_network() - assert result['wif'] == '82' - assert result['epoch'] == epoch_time - assert result['chain_id'] == 10000 - - set_network(Testnet) # set back to Testnet so other tests don't fail + Network.set_network(CustomNetwork()) + result = Network.get_network() + assert result.wif() == '82' + assert result.epoch() == "2024-01-01T13:00:00.000Z" + assert result.chain_id() == 20000 + + Network.set_network(Testnet()) # set back to Testnet so other tests don't fail diff --git a/tests/conftest.py b/tests/conftest.py index ac64cb4..8b8bfe1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,7 @@ import pytest import json import os -from crypto.configuration.network import set_network +from crypto.configuration.network import Network from crypto.networks.testnet import Testnet @@ -11,7 +11,7 @@ def configure_network(): Configures the network to Testnet before running any tests. This fixture runs automatically once per test session. """ - set_network(Testnet) + Network.set_network(Testnet()) @pytest.fixture def load_transaction_fixture(): diff --git a/tests/identity/test_wif.py b/tests/identity/test_wif.py index ec3b12e..b3934df 100644 --- a/tests/identity/test_wif.py +++ b/tests/identity/test_wif.py @@ -1,10 +1,10 @@ -from crypto.configuration.network import set_network +from crypto.configuration.network import Network from crypto.identity.wif import wif_from_passphrase from crypto.networks.testnet import Testnet def test_wif_from_passphrase(identity): - set_network(Testnet) + Network.set_network(Testnet()) result = wif_from_passphrase(identity['passphrase']) assert result == identity['data']['wif']