ApeWorX / ApeWorX/web3.py

Pythonic class generator from contract's ABI

Open
#3,016 4 comments 5 reactions 0 assignees View on GitHub
priority: p3 nice to have
Dominant language
Python
Stars
5.5k
Forks
1.7k
Avg merge
3d 10h
Merged PRs (30d)
2

Description

**General**
Currently, in web3py contract functions are dynamically generated in runtime. However code completion, type inference, and other intelligent features provided by IDEs doesn't work seamlessly with dynamically generated code.

It's easier to interact with smart contracts when interface and documentation is in human-readable state - just in simple pythonic classes generated via cli.

**Benefits**

- Type Safety: Statically generated contract classes bring type safety to the interaction with smart contracts. By generating contract classes, developers can leverage the power of static type checking provided by Python tools like mypy.
- Code Readability and Maintainability: Statically generated contract classes provide a clean and concise interface for interacting with smart contracts. Developers can easily understand the available contract functions, their parameters, and return types, leading to more expressive and self-documented code.
- Mocking: Statically generated contract classes allow for effective mocking of contract interactions during testing. It's just easier to use pytest mocks instead of mocking the provider.
- Forward Compatibility: If a contract is upgraded or modified, developers can regenerate the contract classes and see all compatibility issues.

**Pseudocode generation example**

MyContract.json
```
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
}
],
"name": "contractFunctionName",
"outputs": [
{
"components": [
{
"internalType": "uint256",
"name": "firstInt",
"type": "uint256"
},
{
"internalType": "bytes32",
"name": "secondByte",
"type": "bytes32"
}
],
"internalType": "struct MyContract.SimpleStruct",
"name": "inputStructName",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
```

```bash
python3 web3 generate_class_from_abi ./MyContract.json
```

Generation example `my_contract.py`
```python
# Could be dataclass or pydentic class
@dataclass
class SimpleStruct:
first_int: int
second_bytes: bytes


class MyContract(Contract):
def __init__(w3, address):
# Load abi from source json
abi = self._load_abi()

# Some contract initialization and generation from ContractFactoryClass
....

def contract_function_name(self, role: bytes, block_identifier) -> SimpleStruct:
# Here some validation that role is 32 bytes only
# ...
result = self.functions.contractFunctionName(role).call(block_identifier=block_identifier)

return SimpleStruct(result)
```
**Possible features**
- From camelCase to snake_case
- Input validations
- Custom exception generation that contract could throw

**Challenges**
- No CLI in web3py.
- ABI updating. Just overwrite whole file?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.