brawny 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- brawny-0.1.0/PKG-INFO +156 -0
- brawny-0.1.0/README.md +109 -0
- brawny-0.1.0/pyproject.toml +126 -0
- brawny-0.1.0/setup.cfg +4 -0
- brawny-0.1.0/src/brawny/__init__.py +104 -0
- brawny-0.1.0/src/brawny/_context.py +216 -0
- brawny-0.1.0/src/brawny/_rpc/__init__.py +38 -0
- brawny-0.1.0/src/brawny/_rpc/broadcast.py +172 -0
- brawny-0.1.0/src/brawny/_rpc/clients.py +98 -0
- brawny-0.1.0/src/brawny/_rpc/context.py +49 -0
- brawny-0.1.0/src/brawny/_rpc/errors.py +252 -0
- brawny-0.1.0/src/brawny/_rpc/gas.py +127 -0
- brawny-0.1.0/src/brawny/_rpc/manager.py +982 -0
- brawny-0.1.0/src/brawny/_rpc/selector.py +156 -0
- brawny-0.1.0/src/brawny/accounts.py +534 -0
- brawny-0.1.0/src/brawny/alerts/__init__.py +130 -0
- brawny-0.1.0/src/brawny/alerts/abi_resolver.py +530 -0
- brawny-0.1.0/src/brawny/alerts/base.py +152 -0
- brawny-0.1.0/src/brawny/alerts/context.py +271 -0
- brawny-0.1.0/src/brawny/alerts/contracts.py +635 -0
- brawny-0.1.0/src/brawny/alerts/encoded_call.py +201 -0
- brawny-0.1.0/src/brawny/alerts/errors.py +267 -0
- brawny-0.1.0/src/brawny/alerts/events.py +680 -0
- brawny-0.1.0/src/brawny/alerts/function_caller.py +364 -0
- brawny-0.1.0/src/brawny/alerts/send.py +191 -0
- brawny-0.1.0/src/brawny/api.py +657 -0
- brawny-0.1.0/src/brawny/chain.py +93 -0
- brawny-0.1.0/src/brawny/cli/__init__.py +16 -0
- brawny-0.1.0/src/brawny/cli/app.py +17 -0
- brawny-0.1.0/src/brawny/cli/bootstrap.py +37 -0
- brawny-0.1.0/src/brawny/cli/commands/__init__.py +39 -0
- brawny-0.1.0/src/brawny/cli/commands/abi.py +93 -0
- brawny-0.1.0/src/brawny/cli/commands/accounts.py +632 -0
- brawny-0.1.0/src/brawny/cli/commands/console.py +495 -0
- brawny-0.1.0/src/brawny/cli/commands/contract.py +139 -0
- brawny-0.1.0/src/brawny/cli/commands/health.py +112 -0
- brawny-0.1.0/src/brawny/cli/commands/init_project.py +86 -0
- brawny-0.1.0/src/brawny/cli/commands/intents.py +130 -0
- brawny-0.1.0/src/brawny/cli/commands/job_dev.py +255 -0
- brawny-0.1.0/src/brawny/cli/commands/jobs.py +307 -0
- brawny-0.1.0/src/brawny/cli/commands/maintenance.py +114 -0
- brawny-0.1.0/src/brawny/cli/commands/migrate.py +50 -0
- brawny-0.1.0/src/brawny/cli/commands/networks.py +253 -0
- brawny-0.1.0/src/brawny/cli/commands/run.py +249 -0
- brawny-0.1.0/src/brawny/cli/commands/script.py +209 -0
- brawny-0.1.0/src/brawny/cli/commands/signer.py +248 -0
- brawny-0.1.0/src/brawny/cli/helpers.py +265 -0
- brawny-0.1.0/src/brawny/cli_templates.py +1445 -0
- brawny-0.1.0/src/brawny/config/__init__.py +74 -0
- brawny-0.1.0/src/brawny/config/models.py +365 -0
- brawny-0.1.0/src/brawny/config/parser.py +492 -0
- brawny-0.1.0/src/brawny/config/routing.py +55 -0
- brawny-0.1.0/src/brawny/config/validation.py +244 -0
- brawny-0.1.0/src/brawny/daemon/__init__.py +14 -0
- brawny-0.1.0/src/brawny/daemon/context.py +63 -0
- brawny-0.1.0/src/brawny/daemon/core.py +514 -0
- brawny-0.1.0/src/brawny/daemon/loops.py +221 -0
- brawny-0.1.0/src/brawny/db/__init__.py +78 -0
- brawny-0.1.0/src/brawny/db/base.py +842 -0
- brawny-0.1.0/src/brawny/db/base_new.py +165 -0
- brawny-0.1.0/src/brawny/db/circuit_breaker.py +97 -0
- brawny-0.1.0/src/brawny/db/global_cache.py +298 -0
- brawny-0.1.0/src/brawny/db/mappers.py +175 -0
- brawny-0.1.0/src/brawny/db/migrate.py +299 -0
- brawny-0.1.0/src/brawny/db/migrations/001_init.sql +185 -0
- brawny-0.1.0/src/brawny/db/migrations/002_add_included_block.sql +7 -0
- brawny-0.1.0/src/brawny/db/migrations/003_add_broadcast_at.sql +10 -0
- brawny-0.1.0/src/brawny/db/migrations/004_broadcast_binding.sql +20 -0
- brawny-0.1.0/src/brawny/db/migrations/005_add_retry_after.sql +9 -0
- brawny-0.1.0/src/brawny/db/migrations/006_add_retry_count_column.sql +11 -0
- brawny-0.1.0/src/brawny/db/migrations/007_add_gap_tracking.sql +18 -0
- brawny-0.1.0/src/brawny/db/migrations/008_add_transactions.sql +72 -0
- brawny-0.1.0/src/brawny/db/ops/__init__.py +29 -0
- brawny-0.1.0/src/brawny/db/ops/attempts.py +108 -0
- brawny-0.1.0/src/brawny/db/ops/blocks.py +83 -0
- brawny-0.1.0/src/brawny/db/ops/cache.py +93 -0
- brawny-0.1.0/src/brawny/db/ops/intents.py +278 -0
- brawny-0.1.0/src/brawny/db/ops/jobs.py +110 -0
- brawny-0.1.0/src/brawny/db/ops/nonces.py +322 -0
- brawny-0.1.0/src/brawny/db/postgres.py +2134 -0
- brawny-0.1.0/src/brawny/db/postgres_new.py +196 -0
- brawny-0.1.0/src/brawny/db/queries.py +536 -0
- brawny-0.1.0/src/brawny/db/sqlite.py +2391 -0
- brawny-0.1.0/src/brawny/db/sqlite_new.py +191 -0
- brawny-0.1.0/src/brawny/history.py +126 -0
- brawny-0.1.0/src/brawny/interfaces.py +136 -0
- brawny-0.1.0/src/brawny/jobs/__init__.py +26 -0
- brawny-0.1.0/src/brawny/jobs/base.py +387 -0
- brawny-0.1.0/src/brawny/jobs/discovery.py +188 -0
- brawny-0.1.0/src/brawny/jobs/job_validation.py +111 -0
- brawny-0.1.0/src/brawny/jobs/kv.py +95 -0
- brawny-0.1.0/src/brawny/jobs/registry.py +259 -0
- brawny-0.1.0/src/brawny/keystore.py +484 -0
- brawny-0.1.0/src/brawny/lifecycle.py +704 -0
- brawny-0.1.0/src/brawny/logging.py +290 -0
- brawny-0.1.0/src/brawny/metrics.py +568 -0
- brawny-0.1.0/src/brawny/model/__init__.py +53 -0
- brawny-0.1.0/src/brawny/model/contexts.py +212 -0
- brawny-0.1.0/src/brawny/model/enums.py +70 -0
- brawny-0.1.0/src/brawny/model/errors.py +194 -0
- brawny-0.1.0/src/brawny/model/events.py +93 -0
- brawny-0.1.0/src/brawny/model/startup.py +20 -0
- brawny-0.1.0/src/brawny/model/types.py +470 -0
- brawny-0.1.0/src/brawny/networks/__init__.py +96 -0
- brawny-0.1.0/src/brawny/networks/config.py +269 -0
- brawny-0.1.0/src/brawny/networks/manager.py +423 -0
- brawny-0.1.0/src/brawny/obs/__init__.py +67 -0
- brawny-0.1.0/src/brawny/obs/emit.py +158 -0
- brawny-0.1.0/src/brawny/obs/health.py +175 -0
- brawny-0.1.0/src/brawny/obs/heartbeat.py +133 -0
- brawny-0.1.0/src/brawny/scheduler/__init__.py +19 -0
- brawny-0.1.0/src/brawny/scheduler/poller.py +408 -0
- brawny-0.1.0/src/brawny/scheduler/reorg.py +405 -0
- brawny-0.1.0/src/brawny/scheduler/runner.py +664 -0
- brawny-0.1.0/src/brawny/scheduler/shutdown.py +371 -0
- brawny-0.1.0/src/brawny/script_tx.py +297 -0
- brawny-0.1.0/src/brawny/scripting.py +251 -0
- brawny-0.1.0/src/brawny/startup.py +48 -0
- brawny-0.1.0/src/brawny/telegram.py +351 -0
- brawny-0.1.0/src/brawny/testing.py +107 -0
- brawny-0.1.0/src/brawny/tx/__init__.py +41 -0
- brawny-0.1.0/src/brawny/tx/executor.py +1057 -0
- brawny-0.1.0/src/brawny/tx/fees.py +50 -0
- brawny-0.1.0/src/brawny/tx/intent.py +406 -0
- brawny-0.1.0/src/brawny/tx/monitor.py +628 -0
- brawny-0.1.0/src/brawny/tx/nonce.py +498 -0
- brawny-0.1.0/src/brawny/tx/replacement.py +456 -0
- brawny-0.1.0/src/brawny/tx/utils.py +26 -0
- brawny-0.1.0/src/brawny/utils.py +205 -0
- brawny-0.1.0/src/brawny/validation.py +69 -0
- brawny-0.1.0/src/brawny.egg-info/PKG-INFO +156 -0
- brawny-0.1.0/src/brawny.egg-info/SOURCES.txt +134 -0
- brawny-0.1.0/src/brawny.egg-info/dependency_links.txt +1 -0
- brawny-0.1.0/src/brawny.egg-info/entry_points.txt +2 -0
- brawny-0.1.0/src/brawny.egg-info/requires.txt +26 -0
- brawny-0.1.0/src/brawny.egg-info/top_level.txt +1 -0
brawny-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: brawny
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Block-driven Ethereum job/transaction execution framework
|
|
5
|
+
Author-email: yearn <dev@yearn.fi>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/yearn/brawny
|
|
8
|
+
Project-URL: Documentation, https://github.com/yearn/brawny#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/yearn/brawny.git
|
|
10
|
+
Project-URL: Issues, https://github.com/yearn/brawny/issues
|
|
11
|
+
Keywords: ethereum,web3,blockchain,jobs,transactions
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
Requires-Dist: web3<8.0,>=7.0
|
|
24
|
+
Requires-Dist: click<9.0,>=8.1
|
|
25
|
+
Requires-Dist: pyyaml<7.0,>=6.0
|
|
26
|
+
Requires-Dist: python-dotenv<2.0,>=1.0
|
|
27
|
+
Requires-Dist: structlog<25.0,>=24.1
|
|
28
|
+
Requires-Dist: httpx<1.0,>=0.26
|
|
29
|
+
Requires-Dist: psycopg[binary]<4.0,>=3.1
|
|
30
|
+
Requires-Dist: psycopg-pool<4.0,>=3.2
|
|
31
|
+
Requires-Dist: rich<14.0,>=13.0
|
|
32
|
+
Requires-Dist: prometheus-client<1.0,>=0.20
|
|
33
|
+
Requires-Dist: prompt_toolkit<4.0,>=3.0
|
|
34
|
+
Requires-Dist: pygments<3.0,>=2.17
|
|
35
|
+
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: pytest<9.0,>=8.0; extra == "dev"
|
|
37
|
+
Requires-Dist: pytest-asyncio<1.0,>=0.23; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest-cov<5.0,>=4.1; extra == "dev"
|
|
39
|
+
Requires-Dist: mypy<2.0,>=1.8; extra == "dev"
|
|
40
|
+
Requires-Dist: ruff<1.0,>=0.2; extra == "dev"
|
|
41
|
+
Requires-Dist: black<25.0,>=24.1; extra == "dev"
|
|
42
|
+
Requires-Dist: pre-commit<4.0,>=3.6; extra == "dev"
|
|
43
|
+
Provides-Extra: test
|
|
44
|
+
Requires-Dist: pytest<9.0,>=8.0; extra == "test"
|
|
45
|
+
Requires-Dist: pytest-asyncio<1.0,>=0.23; extra == "test"
|
|
46
|
+
Requires-Dist: pytest-cov<5.0,>=4.1; extra == "test"
|
|
47
|
+
|
|
48
|
+
# brawny
|
|
49
|
+
|
|
50
|
+
Block-driven Ethereum job and transaction execution framework, inspired by [eth-brownie](https://github.com/eth-brownie/brownie).
|
|
51
|
+
|
|
52
|
+
**Brownie-style ergonomics**: brawny mirrors Brownie's developer experience with familiar patterns—`accounts`, `Contract()`, `chain`, `history`, and an interactive console. If you've used Brownie, you'll feel right at home.
|
|
53
|
+
|
|
54
|
+
## Installation (Local Development)
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Clone and install the framework
|
|
58
|
+
git clone https://github.com/yearn/brawny.git
|
|
59
|
+
cd brawny
|
|
60
|
+
pip install -e .
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Quick Start
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Create a new keeper project
|
|
67
|
+
mkdir my-keeper && cd my-keeper
|
|
68
|
+
brawny init
|
|
69
|
+
|
|
70
|
+
# Install your project (brawny is already installed from above)
|
|
71
|
+
pip install -e .
|
|
72
|
+
|
|
73
|
+
# Configure
|
|
74
|
+
cp .env.example .env
|
|
75
|
+
# Edit .env: set RPC_URL and BRAWNY_KEYSTORE_PASSWORD_WORKER
|
|
76
|
+
|
|
77
|
+
# Import a signer key (will prompt for password)
|
|
78
|
+
brawny accounts import --name worker --private-key 0xYOUR_PRIVATE_KEY
|
|
79
|
+
|
|
80
|
+
# Run
|
|
81
|
+
brawny start
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
See `docs/quickstart.md` for a longer walkthrough.
|
|
85
|
+
|
|
86
|
+
## Project Structure
|
|
87
|
+
|
|
88
|
+
After `brawny init`, your project looks like:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
my-keeper/
|
|
92
|
+
├── my_keeper/ # Your Python package
|
|
93
|
+
│ └── __init__.py
|
|
94
|
+
├── jobs/
|
|
95
|
+
│ ├── __init__.py
|
|
96
|
+
│ └── _examples.py # Reference implementations (not registered)
|
|
97
|
+
├── interfaces/ # Place ABI JSON files here
|
|
98
|
+
├── monitoring/ # Prometheus + Grafana stack
|
|
99
|
+
│ ├── docker-compose.yml
|
|
100
|
+
│ └── grafana/...
|
|
101
|
+
├── pyproject.toml
|
|
102
|
+
├── config.yaml
|
|
103
|
+
├── .env.example
|
|
104
|
+
├── .gitignore
|
|
105
|
+
└── AGENTS.md # AI agent guide for writing jobs
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The `AGENTS.md` file contains a comprehensive guide for AI agents to generate correct, idiomatic jobs.
|
|
109
|
+
|
|
110
|
+
## Minimal Job Example
|
|
111
|
+
|
|
112
|
+
Create `jobs/harvester.py`:
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
from brawny import Job, job, Contract, trigger, intent, block
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@job(signer="worker")
|
|
119
|
+
class HarvestJob(Job):
|
|
120
|
+
name = "Harvest Example"
|
|
121
|
+
check_interval_blocks = 50
|
|
122
|
+
vault_address = "0xYourVault"
|
|
123
|
+
|
|
124
|
+
def check(self):
|
|
125
|
+
vault = Contract(self.vault_address)
|
|
126
|
+
pending = vault.pendingRewards()
|
|
127
|
+
if pending > 1_000_000_000_000_000_000:
|
|
128
|
+
return trigger(
|
|
129
|
+
reason="Harvest pending rewards",
|
|
130
|
+
data={"pending": pending},
|
|
131
|
+
idempotency_parts=[block.number // 50],
|
|
132
|
+
)
|
|
133
|
+
return None
|
|
134
|
+
|
|
135
|
+
def build_intent(self, trig):
|
|
136
|
+
vault = Contract(self.vault_address)
|
|
137
|
+
return intent(
|
|
138
|
+
signer_address=self._signer_name,
|
|
139
|
+
to_address=self.vault_address,
|
|
140
|
+
data=vault.harvest.encode_input(),
|
|
141
|
+
min_confirmations=2,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
def alert_triggered(self, ctx):
|
|
145
|
+
return f"Harvest triggered: {ctx.trigger.data['pending'] / 1e18:.4f}"
|
|
146
|
+
|
|
147
|
+
def alert_confirmed(self, ctx):
|
|
148
|
+
return f"Harvest confirmed: {ctx.tx.hash}"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Docs
|
|
152
|
+
|
|
153
|
+
- `docs/quickstart.md`
|
|
154
|
+
- `docs/cli.md`
|
|
155
|
+
- `docs/job-lifecycle.md`
|
|
156
|
+
- `docs/alerts.md`
|
brawny-0.1.0/README.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# brawny
|
|
2
|
+
|
|
3
|
+
Block-driven Ethereum job and transaction execution framework, inspired by [eth-brownie](https://github.com/eth-brownie/brownie).
|
|
4
|
+
|
|
5
|
+
**Brownie-style ergonomics**: brawny mirrors Brownie's developer experience with familiar patterns—`accounts`, `Contract()`, `chain`, `history`, and an interactive console. If you've used Brownie, you'll feel right at home.
|
|
6
|
+
|
|
7
|
+
## Installation (Local Development)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Clone and install the framework
|
|
11
|
+
git clone https://github.com/yearn/brawny.git
|
|
12
|
+
cd brawny
|
|
13
|
+
pip install -e .
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Create a new keeper project
|
|
20
|
+
mkdir my-keeper && cd my-keeper
|
|
21
|
+
brawny init
|
|
22
|
+
|
|
23
|
+
# Install your project (brawny is already installed from above)
|
|
24
|
+
pip install -e .
|
|
25
|
+
|
|
26
|
+
# Configure
|
|
27
|
+
cp .env.example .env
|
|
28
|
+
# Edit .env: set RPC_URL and BRAWNY_KEYSTORE_PASSWORD_WORKER
|
|
29
|
+
|
|
30
|
+
# Import a signer key (will prompt for password)
|
|
31
|
+
brawny accounts import --name worker --private-key 0xYOUR_PRIVATE_KEY
|
|
32
|
+
|
|
33
|
+
# Run
|
|
34
|
+
brawny start
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
See `docs/quickstart.md` for a longer walkthrough.
|
|
38
|
+
|
|
39
|
+
## Project Structure
|
|
40
|
+
|
|
41
|
+
After `brawny init`, your project looks like:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
my-keeper/
|
|
45
|
+
├── my_keeper/ # Your Python package
|
|
46
|
+
│ └── __init__.py
|
|
47
|
+
├── jobs/
|
|
48
|
+
│ ├── __init__.py
|
|
49
|
+
│ └── _examples.py # Reference implementations (not registered)
|
|
50
|
+
├── interfaces/ # Place ABI JSON files here
|
|
51
|
+
├── monitoring/ # Prometheus + Grafana stack
|
|
52
|
+
│ ├── docker-compose.yml
|
|
53
|
+
│ └── grafana/...
|
|
54
|
+
├── pyproject.toml
|
|
55
|
+
├── config.yaml
|
|
56
|
+
├── .env.example
|
|
57
|
+
├── .gitignore
|
|
58
|
+
└── AGENTS.md # AI agent guide for writing jobs
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The `AGENTS.md` file contains a comprehensive guide for AI agents to generate correct, idiomatic jobs.
|
|
62
|
+
|
|
63
|
+
## Minimal Job Example
|
|
64
|
+
|
|
65
|
+
Create `jobs/harvester.py`:
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from brawny import Job, job, Contract, trigger, intent, block
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@job(signer="worker")
|
|
72
|
+
class HarvestJob(Job):
|
|
73
|
+
name = "Harvest Example"
|
|
74
|
+
check_interval_blocks = 50
|
|
75
|
+
vault_address = "0xYourVault"
|
|
76
|
+
|
|
77
|
+
def check(self):
|
|
78
|
+
vault = Contract(self.vault_address)
|
|
79
|
+
pending = vault.pendingRewards()
|
|
80
|
+
if pending > 1_000_000_000_000_000_000:
|
|
81
|
+
return trigger(
|
|
82
|
+
reason="Harvest pending rewards",
|
|
83
|
+
data={"pending": pending},
|
|
84
|
+
idempotency_parts=[block.number // 50],
|
|
85
|
+
)
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
def build_intent(self, trig):
|
|
89
|
+
vault = Contract(self.vault_address)
|
|
90
|
+
return intent(
|
|
91
|
+
signer_address=self._signer_name,
|
|
92
|
+
to_address=self.vault_address,
|
|
93
|
+
data=vault.harvest.encode_input(),
|
|
94
|
+
min_confirmations=2,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
def alert_triggered(self, ctx):
|
|
98
|
+
return f"Harvest triggered: {ctx.trigger.data['pending'] / 1e18:.4f}"
|
|
99
|
+
|
|
100
|
+
def alert_confirmed(self, ctx):
|
|
101
|
+
return f"Harvest confirmed: {ctx.tx.hash}"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Docs
|
|
105
|
+
|
|
106
|
+
- `docs/quickstart.md`
|
|
107
|
+
- `docs/cli.md`
|
|
108
|
+
- `docs/job-lifecycle.md`
|
|
109
|
+
- `docs/alerts.md`
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "brawny"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Block-driven Ethereum job/transaction execution framework"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "yearn", email = "dev@yearn.fi"}
|
|
14
|
+
]
|
|
15
|
+
keywords = ["ethereum", "web3", "blockchain", "jobs", "transactions"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Operating System :: OS Independent",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
dependencies = [
|
|
29
|
+
"web3>=7.0,<8.0",
|
|
30
|
+
"click>=8.1,<9.0",
|
|
31
|
+
"pyyaml>=6.0,<7.0",
|
|
32
|
+
"python-dotenv>=1.0,<2.0",
|
|
33
|
+
"structlog>=24.1,<25.0",
|
|
34
|
+
"httpx>=0.26,<1.0",
|
|
35
|
+
"psycopg[binary]>=3.1,<4.0",
|
|
36
|
+
"psycopg-pool>=3.2,<4.0",
|
|
37
|
+
"rich>=13.0,<14.0",
|
|
38
|
+
"prometheus-client>=0.20,<1.0",
|
|
39
|
+
"prompt_toolkit>=3.0,<4.0",
|
|
40
|
+
"pygments>=2.17,<3.0",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[project.optional-dependencies]
|
|
44
|
+
dev = [
|
|
45
|
+
"pytest>=8.0,<9.0",
|
|
46
|
+
"pytest-asyncio>=0.23,<1.0",
|
|
47
|
+
"pytest-cov>=4.1,<5.0",
|
|
48
|
+
"mypy>=1.8,<2.0",
|
|
49
|
+
"ruff>=0.2,<1.0",
|
|
50
|
+
"black>=24.1,<25.0",
|
|
51
|
+
"pre-commit>=3.6,<4.0",
|
|
52
|
+
]
|
|
53
|
+
test = [
|
|
54
|
+
"pytest>=8.0,<9.0",
|
|
55
|
+
"pytest-asyncio>=0.23,<1.0",
|
|
56
|
+
"pytest-cov>=4.1,<5.0",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
[project.scripts]
|
|
60
|
+
brawny = "brawny.cli:main"
|
|
61
|
+
|
|
62
|
+
[project.urls]
|
|
63
|
+
Homepage = "https://github.com/yearn/brawny"
|
|
64
|
+
Documentation = "https://github.com/yearn/brawny#readme"
|
|
65
|
+
Repository = "https://github.com/yearn/brawny.git"
|
|
66
|
+
Issues = "https://github.com/yearn/brawny/issues"
|
|
67
|
+
|
|
68
|
+
[tool.setuptools.packages.find]
|
|
69
|
+
where = ["src"]
|
|
70
|
+
|
|
71
|
+
[tool.setuptools.package-data]
|
|
72
|
+
brawny = ["py.typed", "db/migrations/*.sql"]
|
|
73
|
+
|
|
74
|
+
[tool.pytest.ini_options]
|
|
75
|
+
testpaths = ["tests"]
|
|
76
|
+
asyncio_mode = "auto"
|
|
77
|
+
python_files = ["test_*.py"]
|
|
78
|
+
python_functions = ["test_*"]
|
|
79
|
+
addopts = "-v --tb=short"
|
|
80
|
+
|
|
81
|
+
[tool.mypy]
|
|
82
|
+
python_version = "3.10"
|
|
83
|
+
warn_return_any = true
|
|
84
|
+
warn_unused_configs = true
|
|
85
|
+
disallow_untyped_defs = true
|
|
86
|
+
disallow_incomplete_defs = true
|
|
87
|
+
check_untyped_defs = true
|
|
88
|
+
strict_optional = true
|
|
89
|
+
warn_redundant_casts = true
|
|
90
|
+
warn_unused_ignores = true
|
|
91
|
+
show_error_codes = true
|
|
92
|
+
exclude = ["tests/", "docs/"]
|
|
93
|
+
|
|
94
|
+
[[tool.mypy.overrides]]
|
|
95
|
+
module = ["web3.*", "eth_account.*", "hexbytes.*"]
|
|
96
|
+
ignore_missing_imports = true
|
|
97
|
+
|
|
98
|
+
[tool.ruff]
|
|
99
|
+
target-version = "py310"
|
|
100
|
+
line-length = 100
|
|
101
|
+
src = ["src", "tests"]
|
|
102
|
+
|
|
103
|
+
[tool.ruff.lint]
|
|
104
|
+
select = [
|
|
105
|
+
"E", # pycodestyle errors
|
|
106
|
+
"W", # pycodestyle warnings
|
|
107
|
+
"F", # Pyflakes
|
|
108
|
+
"I", # isort
|
|
109
|
+
"B", # flake8-bugbear
|
|
110
|
+
"C4", # flake8-comprehensions
|
|
111
|
+
"UP", # pyupgrade
|
|
112
|
+
"ARG", # flake8-unused-arguments
|
|
113
|
+
"SIM", # flake8-simplify
|
|
114
|
+
]
|
|
115
|
+
ignore = [
|
|
116
|
+
"E501", # line too long (handled by formatter)
|
|
117
|
+
"B008", # do not perform function calls in argument defaults
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
[tool.ruff.lint.isort]
|
|
121
|
+
known-first-party = ["brawny"]
|
|
122
|
+
|
|
123
|
+
[tool.black]
|
|
124
|
+
line-length = 100
|
|
125
|
+
target-version = ["py310", "py311"]
|
|
126
|
+
include = '\.pyi?$'
|
brawny-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""
|
|
2
|
+
brawny: Block-driven Ethereum job/transaction execution framework.
|
|
3
|
+
|
|
4
|
+
This package provides a robust, production-ready framework for scheduling
|
|
5
|
+
and executing Ethereum transactions based on block events.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from brawny.jobs.base import Job
|
|
9
|
+
from brawny.jobs.registry import registry, job
|
|
10
|
+
from brawny.model.types import (
|
|
11
|
+
BlockInfo,
|
|
12
|
+
Trigger,
|
|
13
|
+
TxAttempt,
|
|
14
|
+
TxIntent,
|
|
15
|
+
TxIntentSpec,
|
|
16
|
+
to_wei,
|
|
17
|
+
)
|
|
18
|
+
from brawny.model.contexts import (
|
|
19
|
+
BlockContext,
|
|
20
|
+
CheckContext,
|
|
21
|
+
BuildContext,
|
|
22
|
+
AlertContext,
|
|
23
|
+
)
|
|
24
|
+
from brawny.model.events import DecodedEvent, find_event, events_by_name
|
|
25
|
+
from brawny.telegram import telegram, get_telegram, TelegramBot
|
|
26
|
+
from brawny.testing import job_context
|
|
27
|
+
from brawny.interfaces import interface
|
|
28
|
+
|
|
29
|
+
# Implicit context helpers (Flask-like pattern)
|
|
30
|
+
from brawny.api import (
|
|
31
|
+
block,
|
|
32
|
+
ctx, # Get current phase context (CheckContext or BuildContext)
|
|
33
|
+
trigger,
|
|
34
|
+
intent,
|
|
35
|
+
shorten,
|
|
36
|
+
explorer_link,
|
|
37
|
+
gas_ok,
|
|
38
|
+
gas_quote,
|
|
39
|
+
kv, # Persistent KV store
|
|
40
|
+
rpc, # RPC proxy (internal package renamed to _rpc to avoid collision)
|
|
41
|
+
get_address_from_alias,
|
|
42
|
+
Contract, # Brownie-style
|
|
43
|
+
Wei, # Brownie-style
|
|
44
|
+
web3, # Brownie-style
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Brownie-style singletons for scripts
|
|
48
|
+
from brawny.accounts import accounts, Account
|
|
49
|
+
from brawny.history import history
|
|
50
|
+
from brawny.chain import chain
|
|
51
|
+
from brawny.networks import network
|
|
52
|
+
|
|
53
|
+
__version__ = "0.1.0"
|
|
54
|
+
|
|
55
|
+
__all__ = [
|
|
56
|
+
"__version__",
|
|
57
|
+
"Job",
|
|
58
|
+
"job",
|
|
59
|
+
"registry",
|
|
60
|
+
"BlockInfo",
|
|
61
|
+
"Trigger",
|
|
62
|
+
"TxAttempt",
|
|
63
|
+
"TxIntent",
|
|
64
|
+
"TxIntentSpec",
|
|
65
|
+
"to_wei",
|
|
66
|
+
# Phase-specific contexts (OE7)
|
|
67
|
+
"BlockContext",
|
|
68
|
+
"CheckContext",
|
|
69
|
+
"BuildContext",
|
|
70
|
+
"AlertContext",
|
|
71
|
+
# Events
|
|
72
|
+
"DecodedEvent",
|
|
73
|
+
"find_event",
|
|
74
|
+
"events_by_name",
|
|
75
|
+
# Implicit context helpers
|
|
76
|
+
"block",
|
|
77
|
+
"ctx",
|
|
78
|
+
"trigger",
|
|
79
|
+
"intent",
|
|
80
|
+
"shorten",
|
|
81
|
+
"explorer_link",
|
|
82
|
+
"gas_ok",
|
|
83
|
+
"gas_quote",
|
|
84
|
+
"kv",
|
|
85
|
+
"rpc",
|
|
86
|
+
"get_address_from_alias",
|
|
87
|
+
# Brownie-style helpers
|
|
88
|
+
"Contract",
|
|
89
|
+
"Wei",
|
|
90
|
+
"web3",
|
|
91
|
+
# Brownie-style singletons
|
|
92
|
+
"accounts",
|
|
93
|
+
"Account",
|
|
94
|
+
"history",
|
|
95
|
+
"chain",
|
|
96
|
+
"network",
|
|
97
|
+
# Telegram
|
|
98
|
+
"telegram",
|
|
99
|
+
"get_telegram",
|
|
100
|
+
"TelegramBot",
|
|
101
|
+
# Testing
|
|
102
|
+
"job_context",
|
|
103
|
+
"interface",
|
|
104
|
+
]
|