Skip to content

Commit

Permalink
feat: contract creation query update (#148)
Browse files Browse the repository at this point in the history
Co-authored-by: banteg <[email protected]>
  • Loading branch information
antazoey and banteg authored Aug 26, 2024
1 parent e07641a commit 2ab946c
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 15 deletions.
15 changes: 12 additions & 3 deletions ape_etherscan/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import Optional

from ape.api import PluginConfig, QueryAPI, QueryType, ReceiptAPI
from ape.api.query import AccountTransactionQuery, ContractCreationQuery
from ape.api.query import AccountTransactionQuery, ContractCreation, ContractCreationQuery
from ape.exceptions import QueryEngineError
from ape.utils import singledispatchmethod

Expand Down Expand Up @@ -121,12 +121,21 @@ def get_account_transactions(self, query: AccountTransactionQuery) -> Iterator[R
yield receipt

@perform_query.register
def get_contract_creation_receipt(self, query: ContractCreationQuery) -> Iterator[ReceiptAPI]:
def get_contract_creation_receipt(
self, query: ContractCreationQuery
) -> Iterator[ContractCreation]:
client = self._client_factory.get_contract_client(query.contract)
creation_data = client.get_creation_data()
if len(creation_data) == 0:
return
elif len(creation_data) != 1:
raise ValueError("Expecting single creation data.")

yield self.chain_manager.get_receipt(creation_data[0].txHash)
receipt = self.chain_manager.get_receipt(creation_data[0].txHash)
yield ContractCreation(
txn_hash=receipt.txn_hash,
block=receipt.block_number,
deployer=receipt.sender,
# factory is not implemented by this query provider
factory=None,
)
22 changes: 11 additions & 11 deletions ape_etherscan/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@ class EtherscanInstance:


class SourceCodeResponse(BaseModel):
abi: list = Field([], alias="ABI")
name: str = Field("unknown", alias="ContractName")
source_code: str = Field("", alias="SourceCode")
compiler_version: str = Field("", alias="CompilerVersion")
optimization_used: bool = Field(True, alias="OptimizationUsed")
optimization_runs: int = Field(200, alias="Runs")
evm_version: str = Field("Default", alias="EVMVersion")
library: str = Field("", alias="Library")
license_type: str = Field("", alias="LicenseType")
abi: list = Field(default=[], alias="ABI")
name: str = Field(default="unknown", alias="ContractName")
source_code: str = Field(default="", alias="SourceCode")
compiler_version: str = Field(default="", alias="CompilerVersion")
optimization_used: bool = Field(default=True, alias="OptimizationUsed")
optimization_runs: int = Field(default=200, alias="Runs")
evm_version: str = Field(default="Default", alias="EVMVersion")
library: str = Field(default="", alias="Library")
license_type: str = Field(default="", alias="LicenseType")
proxy: bool = Field(False, alias="Proxy")
implementation: str = Field("", alias="Implementation")
swarm_source: str = Field("", alias="SwarmSource")
implementation: str = Field(default="", alias="Implementation")
swarm_source: str = Field(default="", alias="SwarmSource")

@field_validator("optimization_used", "proxy", mode="before")
@classmethod
Expand Down
4 changes: 3 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,8 @@ def add_handler(
):
if isinstance(return_value, (str, dict)):
return_value = self.get_mock_response(return_value)
elif isinstance(return_value, list):
return_value = self.get_mock_response({"result": return_value})

def handler(self, method, base_uri, params=None, data=None, headers=None):
actual_params = params if method.lower() == "get" else data
Expand Down Expand Up @@ -455,7 +457,7 @@ def get_mock_response(
# Mock wasn't set.
response_data = {**kwargs}

assert isinstance(response_data, dict)
assert isinstance(response_data, (list, dict))
return self._get_mock_response(response_data=response_data, **kwargs)

def _get_mock_response(
Expand Down
31 changes: 31 additions & 0 deletions tests/test_query.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import pytest
from ape.api.query import ContractCreationQuery
from ape.utils import ManagerAccessMixin


@pytest.fixture
def query_engine():
return ManagerAccessMixin.query_manager.engines["etherscan"]


def test_contract_creation_receipt(query_engine, mock_backend):
address = "0x388C818CA8B9251b393131C08a736A67ccB19297"
creator = "0xDB65702A9b26f8a643a31a4c84b9392589e03D7c"

# Setup backend.
params = {"action": "getcontractcreation", "contractaddresses": [address]}
return_value = [
{
"contractAddress": address,
"contractCreator": creator.lower(),
"txHash": "0xd72cf25e4a5fe3677b6f9b2ae13771e02ad66f8d2419f333bb8bde3147bd4294",
}
]
mock_backend.add_handler("GET", "contract", params, return_value=return_value)

# Perform query.
query = ContractCreationQuery(contract=address, columns=["*"])
result = list(query_engine.perform_query(query))

assert len(result) == 1
assert result[0].deployer == creator

0 comments on commit 2ab946c

Please sign in to comment.