diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 20e289d..fbad7aa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -46,4 +46,4 @@ A pull request represents the start of a discussion, and doesn't necessarily nee If you are opening a work-in-progress pull request to verify that it passes CI tests, please consider [marking it as a draft](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests#draft-pull-requests). -Join the Ethereum Python [Discord](https://discord.gg/PcEJ54yX) if you have any questions. +Join the ApeWorX [Discord](https://discord.gg/apeworx) if you have any questions. diff --git a/ape_bsc/ecosystem.py b/ape_bsc/ecosystem.py index 508f31b..d8f8381 100644 --- a/ape_bsc/ecosystem.py +++ b/ape_bsc/ecosystem.py @@ -1,8 +1,14 @@ -from typing import cast +from typing import Optional, Type, Union, cast +from ape.api import TransactionAPI from ape.api.config import PluginConfig from ape.api.networks import LOCAL_NETWORK_NAME +from ape.exceptions import ApeException +from ape.types import TransactionSignature from ape_ethereum.ecosystem import Ethereum, NetworkConfig +from ape_ethereum.transactions import DynamicFeeTransaction, StaticFeeTransaction, TransactionType +from eth_typing import HexStr +from eth_utils import add_0x_prefix, decode_hex NETWORKS = { # chain_id, network_id @@ -22,3 +28,77 @@ class BSC(Ethereum): @property def config(self) -> BSCConfig: # type: ignore[override] return cast(BSCConfig, self.config_manager.get_config("bsc")) + + def create_transaction(self, **kwargs) -> TransactionAPI: + """ + Returns a transaction using the given constructor kwargs. + Overridden because does not support + + **kwargs: Kwargs for the transaction class. + + Returns: + :class:`~ape.api.transactions.TransactionAPI` + """ + + transaction_type = _get_transaction_type(kwargs.get("type")) + kwargs["type"] = transaction_type.value + txn_class = _get_transaction_cls(transaction_type) + + if "required_confirmations" not in kwargs or kwargs["required_confirmations"] is None: + # Attempt to use default required-confirmations from `ape-config.yaml`. + required_confirmations = 0 + active_provider = self.network_manager.active_provider + if active_provider: + required_confirmations = active_provider.network.required_confirmations + + kwargs["required_confirmations"] = required_confirmations + + if isinstance(kwargs.get("chainId"), str): + kwargs["chainId"] = int(kwargs["chainId"], 16) + + if "input" in kwargs: + kwargs["data"] = decode_hex(kwargs.pop("input").hex()) + + if all(field in kwargs for field in ("v", "r", "s")): + kwargs["signature"] = TransactionSignature( + v=kwargs["v"], + r=bytes(kwargs["r"]), + s=bytes(kwargs["s"]), + ) + + return txn_class.parse_obj(kwargs) + + +def _get_transaction_type(_type: Optional[Union[int, str, bytes]]) -> TransactionType: + if not _type: + return TransactionType.STATIC + + if _type is None: + _type = TransactionType.STATIC.value + elif isinstance(_type, int): + _type = f"0{_type}" + elif isinstance(_type, bytes): + _type = _type.hex() + + suffix = _type.replace("0x", "") + if len(suffix) == 1: + _type = f"{_type.rstrip(suffix)}0{suffix}" + + return TransactionType(add_0x_prefix(HexStr(_type))) + + +class ApeBSCError(ApeException): + """ + Raised in the ape-bsc plugin. + """ + + +def _get_transaction_cls(transaction_type: TransactionType) -> Type[TransactionAPI]: + transaction_types = { + TransactionType.STATIC: StaticFeeTransaction, + TransactionType.DYNAMIC: DynamicFeeTransaction, + } + if transaction_type not in transaction_types: + raise ApeBSCError(f"Transaction type '{transaction_type}' not supported.") + + return transaction_types[transaction_type] diff --git a/tests/conftest.py b/tests/conftest.py index 278ae0f..f3966e3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -22,3 +22,14 @@ def runner(): @pytest.fixture def cli(): return ape_cli + + +@pytest.fixture +def provider(networks): + with networks.bsc.local.use_provider("test"): + yield + + +@pytest.fixture +def account(accounts): + return accounts.test_accounts[0] diff --git a/tests/test_provider.py b/tests/test_provider.py index 02dc1a6..e5efa51 100644 --- a/tests/test_provider.py +++ b/tests/test_provider.py @@ -1,7 +1,6 @@ -def test_use_provider(accounts, networks): - with networks.bsc.local.use_provider("test"): - account = accounts.test_accounts[0] - receipt = account.transfer(account, 100) - - assert not receipt.failed - assert receipt.value == 100 +def test_use_provider(account, provider): + receipt = account.transfer(account, 100) + assert not receipt.failed + assert receipt.value == 100 + # Ensure uses type 0 by default. + assert receipt.transaction.type == 0