-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- not type checking - no utility functions
- Loading branch information
Showing
22 changed files
with
243 additions
and
2,322 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
[MASTER] | ||
disable=fixme,too-few-public-methods,too-many-instance-attributes,too-many-arguments,logging-fstring-interpolation,too-many-locals,duplicate-code, def buy_amount(self) -> Decimal: | ||
[MAIN] | ||
|
||
extension-pkg-allow-list=pydantic | ||
disable=logging-fstring-interpolation |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,18 +8,18 @@ git clone [email protected]:cowprotocol/solver-template-py.git | |
|
||
## Install Requirements | ||
|
||
1. Python 3.10 (or probably also 3.9) | ||
2. Rust v1.60.0 or Docker | ||
1. Python 3.11 or Docker (for running the solver) | ||
2. Rust v1.60.0 or Docker (for running the autopilot and driver) REMOVE DRIVER FROM THIS TEMPLATE. THIS SHOULD BE EXPLAINED IN SOME TUTORIAL and not be part of this solver template | ||
|
||
```sh | ||
python3.10 -m venv venv | ||
python3 -m venv venv | ||
source ./venv/bin/activate | ||
pip install -r requirements.txt | ||
``` | ||
|
||
# Run Solver Server | ||
|
||
```shell | ||
```sh | ||
python -m src._server | ||
``` | ||
|
||
|
@@ -32,79 +32,27 @@ docker run -p 8000:8000 gchr.io/cowprotocol/solver-template-py | |
or build your own docker image with | ||
|
||
```sh | ||
docker build -t test-solver-image . | ||
docker build -t solver-template-py . | ||
``` | ||
|
||
and run it with | ||
```sh | ||
docker run -p 8000:8000 solver-template-py | ||
``` | ||
|
||
# Feed an Auction Instance to the Solver | ||
|
||
```shell | ||
```sh | ||
curl -X POST "http://127.0.0.1:8000/solve" \ | ||
-H "accept: application/json" \ | ||
-H "Content-Type: application/json" \ | ||
--data "@data/small_example.json" | ||
``` | ||
|
||
# Connect to the orderbook: | ||
|
||
Run the driver (auction dispatcher in DryRun mode). Configured to read the orderbook | ||
from our staging environment on Gnosis Chain. These parameters can be altered | ||
in [.env](.env) | ||
|
||
## With Docker | ||
|
||
If you have docker installed then you can run this. | ||
|
||
```shell | ||
docker run -it --rm --env-file .env --add-host host.docker.internal:host-gateway ghcr.io/cowprotocol/services solver | ||
``` | ||
|
||
or without an env file (as described in | ||
the [How to Write a Solver Tutorial](https://docs.cow.fi/tutorials/how-to-write-a-solver)) | ||
|
||
```shell | ||
docker run -it --rm --add-host host.docker.internal:host-gateway ghcr.io/cowprotocol/services solver \ | ||
--orderbook-url https://barn.api.cow.fi/xdai/api \ | ||
--base-tokens 0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83 \ | ||
--node-url "https://rpc.gnosischain.com" \ | ||
--cow-dex-ag-solver-url "http://127.0.0.1:8000" \ | ||
--solver-account 0x7942a2b3540d1ec40b2740896f87aecb2a588731 \ | ||
--solvers CowDexAg \ | ||
--transaction-strategy DryRun | ||
``` | ||
|
||
Here we have used the orderbook-url for our staging environment on Gnosis Chain (very low traffic) so you can work with your own orders. A complete list of orderbook URLs can be found in a table at the bottom of the services repo [README](https://github.com/cowprotocol/services#solvers) | ||
|
||
## Without Docker | ||
|
||
Clone the services project with | ||
|
||
```shell | ||
git clone https://github.com/cowprotocol/services.git | ||
``` | ||
|
||
```shell | ||
cargo run -p solver -- \ | ||
--orderbook-url https://barn.api.cow.fi/xdai/api \ | ||
--base-tokens 0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83 \ | ||
--node-url "https://rpc.gnosischain.com" \ | ||
--cow-dex-ag-solver-url "http://127.0.0.1:8000" \ | ||
--solver-account 0x7942a2b3540d1ec40b2740896f87aecb2a588731 \ | ||
--solvers CowDexAg \ | ||
--transaction-strategy DryRun \ | ||
--log-filter=info,solver=debug | ||
``` | ||
|
||
# Place an order | ||
|
||
Navigate to [barn.cowswap.exchange/](https://barn.cowswap.exchange/#/swap) and place a | ||
tiny (real) order. See your driver pick it up and include it in the next auction being | ||
sent to your solver | ||
# Connect to the orderbook TBD: | ||
|
||
# References | ||
# References TBD | ||
|
||
- How to Build a Solver: https://docs.cow.fi/tutorials/how-to-write-a-solver | ||
- In Depth Solver | ||
Specification: https://docs.cow.fi/off-chain-services/in-depth-solver-specification | ||
- Settlement Contract (namely the settle | ||
method): https://github.com/cowprotocol/contracts/blob/ff6fb7cad7787b8d43a6468809cacb799601a10e/src/contracts/GPv2Settlement.sol#L121-L143 | ||
- Interaction Model (Currently missing from this framework): https://github.com/cowprotocol/services/blob/cda5e36db34c55e7bf9eb4ea8b6e36ecb046f2b2/crates/shared/src/http_solver/model.rs#L125-L130 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,2 @@ | ||
[mypy] | ||
python_version = 3.10 | ||
|
||
|
||
[mypy-src.*] | ||
allow_untyped_calls = True | ||
allow_any_generics = True | ||
|
||
[mypy-uvicorn.*] | ||
ignore_missing_imports = True | ||
|
||
[mypy-fastapi] | ||
implicit_reexport = True | ||
python_version = 3.11 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,42 @@ | ||
black==22.3.0 | ||
fastapi==0.65.2 | ||
uvicorn==0.17.6 | ||
pylint==2.13.5 | ||
python-dotenv==0.20.0 | ||
pydantic==1.9.0 | ||
pytest==7.1.1 | ||
makefun==1.13.1 | ||
mypy==0.942 | ||
aiohttp==3.9.1 | ||
aiosignal==1.3.1 | ||
annotated-types==0.6.0 | ||
anyio==3.7.1 | ||
astroid==3.0.2 | ||
attrs==23.1.0 | ||
black==23.12.0 | ||
certifi==2023.11.17 | ||
click==8.1.7 | ||
dill==0.3.7 | ||
fastapi==0.105.0 | ||
frozenlist==1.4.1 | ||
h11==0.14.0 | ||
httpcore==1.0.2 | ||
httptools==0.6.1 | ||
httpx==0.25.2 | ||
idna==3.6 | ||
iniconfig==2.0.0 | ||
isort==5.13.2 | ||
mccabe==0.7.0 | ||
multidict==6.0.4 | ||
mypy==1.7.1 | ||
mypy-extensions==1.0.0 | ||
packaging==23.2 | ||
pathspec==0.12.1 | ||
platformdirs==4.1.0 | ||
pluggy==1.3.0 | ||
pydantic==2.5.2 | ||
pydantic_core==2.14.5 | ||
pylint==3.0.3 | ||
pytest==7.4.3 | ||
python-dotenv==1.0.0 | ||
PyYAML==6.0.1 | ||
sniffio==1.3.0 | ||
starlette==0.27.0 | ||
tomlkit==0.12.3 | ||
typing_extensions==4.9.0 | ||
uvicorn==0.24.0.post1 | ||
uvloop==0.19.0 | ||
watchfiles==0.21.0 | ||
websockets==12.0 | ||
yarl==1.9.4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,124 +1,60 @@ | ||
""" | ||
This is the project's Entry point. | ||
""" | ||
from __future__ import annotations | ||
|
||
import argparse | ||
import decimal | ||
import logging | ||
|
||
from typing import Any | ||
import uvicorn | ||
from dotenv import load_dotenv | ||
from fastapi import FastAPI, Request | ||
from fastapi.middleware.gzip import GZipMiddleware | ||
from pydantic import BaseSettings | ||
|
||
from src.models.batch_auction import BatchAuction | ||
from src.models.solver_args import SolverArgs | ||
from src.util.schema import ( | ||
BatchAuctionModel, | ||
SettledBatchAuctionModel, | ||
) | ||
|
||
# Set decimal precision. | ||
decimal.getcontext().prec = 100 | ||
|
||
# Holds parameters passed on the command line when invoking the server. | ||
# These will be merged with request solver parameters | ||
SERVER_ARGS = None | ||
|
||
from fastapi import FastAPI | ||
|
||
# ++++ Interface definition ++++ | ||
# from src.models.solve_model import Auction, Solution | ||
|
||
|
||
# Server settings: Can be overridden by passing them as env vars or in a .env file. | ||
# Example: PORT=8001 python -m src._server | ||
class ServerSettings(BaseSettings): | ||
"""Basic Server Settings""" | ||
|
||
host: str = "0.0.0.0" | ||
port: int = 8000 | ||
|
||
|
||
server_settings = ServerSettings() | ||
logging.basicConfig(level=logging.DEBUG) | ||
|
||
# ++++ Endpoints: ++++ | ||
|
||
|
||
app = FastAPI(title="Batch auction solver") | ||
app.add_middleware(GZipMiddleware) | ||
|
||
|
||
@app.get("/health", status_code=200) | ||
def health() -> bool: | ||
"""Convenience endpoint to check if server is alive.""" | ||
return True | ||
|
||
|
||
@app.post("/notify", response_model=bool) | ||
async def notify(request: Request) -> bool: | ||
async def notify(notification: dict[str, Any]) -> bool: | ||
"""Print response from notify endpoint.""" | ||
print(f"Notify request {await request.json()}") | ||
logging.debug(f"Notification: {notification}") | ||
return True | ||
|
||
|
||
@app.post("/solve", response_model=SettledBatchAuctionModel) | ||
async def solve(problem: BatchAuctionModel, request: Request): # type: ignore | ||
# @app.post("/solve", response_model=Solution) | ||
# async def solve(auction: Auction, request: Request): # type: ignore | ||
@app.post("/solve") | ||
async def solve(auction: dict[str, Any]) -> dict[str, Any]: | ||
"""API POST solve endpoint handler""" | ||
logging.debug(f"Received solve request {await request.json()}") | ||
solver_args = SolverArgs.from_request(request=request, meta=problem.metadata) | ||
|
||
batch = BatchAuction.from_dict(problem.dict(), solver_args.instance_name) | ||
|
||
print("Received Batch Auction", batch.name) | ||
print("Parameters Supplied", solver_args) | ||
logging.debug(f"Received solve request: {auction}") | ||
|
||
# 1. Solve BatchAuction: update batch_auction with | ||
# batch.solve() | ||
# 1. Solve Auction | ||
# (add code) | ||
|
||
trivial_solution = { | ||
"orders": {}, | ||
"foreign_liquidity_orders": [], | ||
"amms": {}, | ||
solution = { | ||
"id": "123", | ||
"trades": [], | ||
"prices": {}, | ||
"approvals": [], | ||
"interaction_data": [], | ||
"interactions": [], | ||
"solver": "solvertemplate", | ||
"score": "0", | ||
"weth": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", | ||
} | ||
|
||
print("\n\n*************\n\nReturning solution: " + str(trivial_solution)) | ||
return trivial_solution | ||
logging.debug(f"Returning solution: {solution}") | ||
|
||
# return Solution(**solution) | ||
return solution | ||
|
||
|
||
# ++++ Server setup: ++++ | ||
|
||
|
||
if __name__ == "__main__": | ||
load_dotenv() | ||
|
||
parser = argparse.ArgumentParser( | ||
fromfile_prefix_chars="@", | ||
formatter_class=argparse.ArgumentDefaultsHelpFormatter, | ||
) | ||
# TODO - enable flag to write files to persistent storage | ||
# parser.add_argument( | ||
# "--write_auxiliary_files", | ||
# type=bool, | ||
# default=False, | ||
# help="Write auxiliary instance and optimization files, or not.", | ||
# ) | ||
|
||
parser.add_argument( | ||
"--log-level", | ||
type=str, | ||
default="info", | ||
help="Log level", | ||
) | ||
|
||
SERVER_ARGS = parser.parse_args() | ||
uvicorn.run( | ||
"__main__:app", | ||
host=server_settings.host, | ||
port=server_settings.port, | ||
log_level=SERVER_ARGS.log_level, | ||
host="0.0.0.0", | ||
port=8000, | ||
) |
Oops, something went wrong.