Skip to content

Commit

Permalink
Add order signing and order book api (#7)
Browse files Browse the repository at this point in the history
* start porting order signing code from cow sdk

* refactor codegen

* complete order signing module

* add component tests

* add order book api

* remove order signing

* add order book tests

* add ideas

* chore: add e2e order quote to post example

* fix: order link print

* update readme

* merge into order book api

* refactor request strategy and merge with updated order book api

* add refactors

* compose config with api base

* fix example interface errors

* fix: remove generated app data schemas

* fix tests using async mock on sync function

* Pyright and Ci fix (#13)

* wip: fix poetry lock

* fix: pyright types

* wip: fix cache

---------

Co-authored-by: Pedro Yves Fracari <[email protected]>
Co-authored-by: Pedro Yves Fracari <[email protected]>
  • Loading branch information
3 people authored Apr 15, 2024
1 parent b2ca788 commit 54fd0ec
Show file tree
Hide file tree
Showing 53 changed files with 2,786 additions and 510 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
USER_ADDRESS=
PRIVATE_KEY=
6 changes: 5 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
strategy:
matrix:
python-version: [
"3.8", "3.9", "3.10", "3.11", "3.12",
"3.10", "3.11", "3.12",
]
timeout-minutes: 10
steps:
Expand All @@ -32,6 +32,10 @@ jobs:
cache: poetry
cache-dependency-path: poetry.lock

- name: Poetry lock
run: |
poetry lock
- name: Install dependencies
run: |
poetry install
Expand Down
17 changes: 9 additions & 8 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.1.4
hooks:
# Run the linter.
- id: ruff
# Run the formatter.
- id: ruff-format
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.3.7
hooks:
# Run the linter.
- id: ruff
args: [--fix]
# Run the formatter.
- id: ruff-format
24 changes: 15 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
.PHONY: codegen
.PHONY: codegen web3_codegen orderbook_codegen subgraph_codegen test lint format remove_unused_imports

codegen: web3_codegen orderbook_codegen subgraph_codegen

web3_codegen:
poetry run web3_codegen
# web3_codegen:
# poetry run web3_codegen

orderbook_codegen:
datamodel-codegen --url="https://raw.githubusercontent.com/cowprotocol/services/v2.245.1/crates/orderbook/openapi.yml" --output cow_py/order_book/__generated__/model.py --target-python-version 3.12 --output-model-type pydantic_v2.BaseModel --input-file-type openapi
poetry run datamodel-codegen --url="https://raw.githubusercontent.com/cowprotocol/services/v2.245.1/crates/orderbook/openapi.yml" --output cow_py/order_book/generated/model.py --target-python-version 3.12 --output-model-type pydantic_v2.BaseModel --input-file-type openapi

subgraph_codegen:
ariadne-codegen
poetry run ariadne-codegen

test:
pytest -s
poetry run pytest -s

lint:
ruff check . --fix
poetry run ruff check . --fix

format:
ruff format
format: remove_unused_imports
poetry run ruff format

remove_unused_imports:
poetry run pycln --all .

typecheck:
poetry run pyright
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ pip install cow_py
Here's a simple example to get your hooves dirty:

```python
# TODO: this code is aspirational, this API doesn't exist
from cow_py.order_book import OrderBook

# Initialize the OrderBook
order_book = OrderBook()
from cow_py.order_book.api import OrderBookApi, UID

# Initialize the OrderBookApi
order_book_api = OrderBookApi()

# Fetch and display orders
orders = order_book.get_orders()
orders = order_book.get_order_by_uid(UID("0x..."))
print(orders)
```

Expand Down
22 changes: 12 additions & 10 deletions cow_py/codegen/__generated__/ComposableCow.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions cow_py/codegen/__generated__/ExtensibleFallbackHandler.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions cow_py/codegen/__generated__/Milkman.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 13 additions & 4 deletions cow_py/codegen/__generated__/TWAP.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions cow_py/codegen/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .abi_handler import ABIHandler

__all__ = [
"ABIHandler",
]
104 changes: 62 additions & 42 deletions cow_py/codegen/abi_handler.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import importlib.resources
import re
from typing import Any, Dict, List

from pybars import Compiler
from cow_py.codegen.components.abi_loader import FileAbiLoader
import importlib.resources

from cow_py.codegen.components import templates
from cow_py.codegen.components.abi_loader import FileAbiLoader
from cow_py.codegen.components.templates import partials

from cow_py.codegen.solidity_converter import SolidityConverter

CAMEL_TO_SNAKE_REGEX = re.compile(
Expand Down Expand Up @@ -48,6 +49,12 @@ def _get_partials_files() -> str:
return [str(x) for x in pkg_files.iterdir() if x.suffix == ".hbs"] # type: ignore


class ABIHandlerError(Exception):
"""Raised when an error occurs in the ABI handler."""

pass


class ABIHandler:
"""
Handles the generation of Python classes and methods from Ethereum contract ABIs.
Expand Down Expand Up @@ -77,10 +84,15 @@ def generate(self) -> str:
Returns:
str: The generated Python code as a string.
"""
template_data = self._prepare_template_data()
return self._render_template(template_data)
Raises:
ABIHandlerError: If an error occurs during ABI processing or code generation.
"""
try:
template_data = self._prepare_template_data()
return self._render_template(template_data)
except Exception as e:
raise ABIHandlerError(f"Error generating code: {str(e)}") from e

def _prepare_template_data(self) -> Dict[str, Any]:
"""
Expand All @@ -91,27 +103,46 @@ def _prepare_template_data(self) -> Dict[str, Any]:
Returns:
Dict[str, Any]: A dictionary containing the structured data for rendering.
"""
methods, data_classes, enums = [], [], []
generated_structs, generated_enums = set(), set()

abi = FileAbiLoader(self.abi_file_path).load_abi()

for item in abi:
if item["type"] == "function":
methods.append(self._process_function(item))
for param in item["inputs"] + item.get("outputs", []):
self._process_parameters(
param, data_classes, enums, generated_structs, generated_enums
)
return {
"abiPath": self.abi_file_path,
"contractName": self.contract_name,
"methods": methods,
"dataClasses": data_classes,
"enums": enums,
}
Raises:
ABIHandlerError: If an error occurs during ABI processing.
"""
try:
methods, data_classes, enums = [], [], []
generated_structs, generated_enums = set(), set()

abi = FileAbiLoader(self.abi_file_path).load_abi()

for item in abi:
if item["type"] == "function":
methods.append(self._process_function(item))
for param in item["inputs"] + item.get("outputs", []):
self._process_parameters(
param,
data_classes,
enums,
generated_structs,
generated_enums,
)
elif item["type"] == "event":
for param in item["inputs"]:
self._process_parameters(
param,
data_classes,
enums,
generated_structs,
generated_enums,
)

return {
"abiPath": self.abi_file_path,
"contractName": self.contract_name,
"methods": methods,
"dataClasses": data_classes,
"enums": enums,
}
except Exception as e:
raise ABIHandlerError(f"Error preparing template data: {str(e)}") from e

def _process_parameters(
self, param, data_classes, enums, generated_structs, generated_enums
Expand All @@ -134,15 +165,11 @@ def _process_parameters(
and param["internalType"] not in generated_enums
):
enum_name = SolidityConverter._get_struct_name(param["internalType"])
enums.append(
{
"name": enum_name,
"values": [
{"name": "VALUE_1", "value": 1},
{"name": "VALUE_2", "value": 2},
],
}
)
enum_values = [
{"name": item["name"], "value": item["value"]}
for item in param["components"]
]
enums.append({"name": enum_name, "values": enum_values})
generated_enums.add(param["internalType"])

def _process_function(self, function_item: Dict[str, Any]) -> Dict[str, Any]:
Expand All @@ -169,13 +196,6 @@ def _process_function(self, function_item: Dict[str, Any]) -> Dict[str, Any]:
"originalName": original_name,
}

def _process_enum(self, enum_item: Dict[str, Any]) -> Dict[str, Any]:
enum_name = enum_item["name"]
enum_values = [
{"name": v["name"], "value": v["value"]} for v in enum_item["values"]
]
return {"name": enum_name, "values": enum_values}

def _generate_function_input_args_with_types(
self, function_item: Dict[str, Any]
) -> List[Dict[str, Any]]:
Expand Down
6 changes: 4 additions & 2 deletions cow_py/codegen/components/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from cow_py.codegen.components.abi_loader import FileAbiLoader
from cow_py.codegen.components.base_contract import BaseContract
from cow_py.codegen.components.base_mixin import BaseMixin
from cow_py.codegen.components.contract_factory import ContractFactory
from cow_py.codegen.components.abi_loader import FileAbiLoader
from cow_py.codegen.components.contract_loader import ContractLoader
from cow_py.codegen.components.base_mixin import BaseMixin
from cow_py.codegen.components.get_abi_file import get_abi_file
from cow_py.codegen.components.templates import partials

__all__ = [
"BaseContract",
Expand All @@ -12,4 +13,5 @@
"ContractLoader",
"BaseMixin",
"get_abi_file",
"partials",
]
4 changes: 2 additions & 2 deletions cow_py/codegen/components/abi_loader.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import List, Any
from abc import ABC, abstractmethod
import json
from abc import ABC, abstractmethod
from typing import Any, List


class AbiLoader(ABC):
Expand Down
Loading

0 comments on commit 54fd0ec

Please sign in to comment.