web3-agent-kit 0.6.0__tar.gz → 0.8.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.
- {web3_agent_kit-0.6.0/web3_agent_kit.egg-info → web3_agent_kit-0.8.0}/PKG-INFO +115 -2
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/README.md +114 -1
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/pyproject.toml +1 -1
- web3_agent_kit-0.8.0/src/airdrop/__init__.py +65 -0
- web3_agent_kit-0.8.0/src/airdrop/base.py +268 -0
- web3_agent_kit-0.8.0/src/airdrop/galxe.py +327 -0
- web3_agent_kit-0.8.0/src/airdrop/gleam.py +208 -0
- web3_agent_kit-0.8.0/src/airdrop/multi_wallet.py +264 -0
- web3_agent_kit-0.8.0/src/airdrop/social.py +430 -0
- web3_agent_kit-0.8.0/src/airdrop/tracker.py +339 -0
- web3_agent_kit-0.8.0/src/airdrop/zealy.py +234 -0
- web3_agent_kit-0.8.0/src/api/__init__.py +138 -0
- web3_agent_kit-0.8.0/src/api/models.py +162 -0
- web3_agent_kit-0.8.0/src/api/routes/__init__.py +25 -0
- web3_agent_kit-0.8.0/src/api/routes/approval.py +80 -0
- web3_agent_kit-0.8.0/src/api/routes/bridge.py +59 -0
- web3_agent_kit-0.8.0/src/api/routes/dca.py +111 -0
- web3_agent_kit-0.8.0/src/api/routes/gas.py +46 -0
- web3_agent_kit-0.8.0/src/api/routes/portfolio.py +45 -0
- web3_agent_kit-0.8.0/src/api/routes/swap.py +63 -0
- web3_agent_kit-0.8.0/src/api/routes/wallet.py +54 -0
- web3_agent_kit-0.8.0/src/api/routes/watcher.py +89 -0
- web3_agent_kit-0.8.0/src/api/routes/yield_opt.py +72 -0
- web3_agent_kit-0.8.0/tests/test_airdrop.py +439 -0
- web3_agent_kit-0.8.0/tests/test_api.py +420 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/tests/test_new_features.py +14 -7
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0/web3_agent_kit.egg-info}/PKG-INFO +115 -2
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/web3_agent_kit.egg-info/SOURCES.txt +22 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/LICENSE +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/setup.cfg +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/setup.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/src/__init__.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/src/agent.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/src/approval_manager.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/src/bridge.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/src/chain.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/src/dca_bot.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/src/defi/__init__.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/src/gas_optimizer.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/src/llm.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/src/multi_wallet.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/src/plugins/__init__.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/src/plugins/examples/gas_tracker.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/src/portfolio.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/src/sniper.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/src/utils/__init__.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/src/wallet.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/src/wallet_watcher.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/src/yield_optimizer.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/tests/test_bridge.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/tests/test_core.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/tests/test_dca_bot.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/tests/test_defi.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/tests/test_llm.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/tests/test_multi_wallet.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/tests/test_plugins.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/tests/test_portfolio.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/tests/test_sniper.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/tests/test_yield_optimizer.py +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/web3_agent_kit.egg-info/dependency_links.txt +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/web3_agent_kit.egg-info/requires.txt +0 -0
- {web3_agent_kit-0.6.0 → web3_agent_kit-0.8.0}/web3_agent_kit.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: web3-agent-kit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: Open-source framework for building autonomous AI agents that interact with blockchain networks
|
|
5
5
|
Author-email: Maulana <khasbim240803@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -68,6 +68,7 @@ Building AI agents that interact with blockchains is **hard**. You need to juggl
|
|
|
68
68
|
| **Security** | Manual approval checks | Auto-scan & revoke risky approvals |
|
|
69
69
|
| **Alerts** | Manual whale tracking | Auto-monitor wallets, instant alerts |
|
|
70
70
|
| **Multi-wallet** | Manage keys manually | Batch ops, consolidated portfolio, wallet groups |
|
|
71
|
+
| **Airdrops** | Manual quest hunting | Auto-track campaigns, multi-wallet farming, Sybil-safe |
|
|
71
72
|
| **Extensibility** | Hard-coded logic | Plugin system — community can extend anything |
|
|
72
73
|
| **Error Handling** | Manual retry logic | Auto-fallback across LLM providers & RPCs |
|
|
73
74
|
|
|
@@ -141,6 +142,7 @@ Building AI agents that interact with blockchains is **hard**. You need to juggl
|
|
|
141
142
|
| **Wallet Watcher** | ✅ | ❌ | ❌ | ❌ |
|
|
142
143
|
| **Yield Optimizer** | ✅ | ❌ | ❌ | ❌ |
|
|
143
144
|
| **Multi-Wallet** | ✅ | ❌ | ❌ | ❌ |
|
|
145
|
+
| **Airdrops** | ✅ | ❌ | ❌ | ❌ |
|
|
144
146
|
| **Plugin System** | ✅ | ❌ | ❌ | ❌ |
|
|
145
147
|
| **Safety Rails** | ✅ Governor | ❌ | ❌ | ❌ |
|
|
146
148
|
| **Natural Language** | ✅ | Partial | ❌ | ❌ |
|
|
@@ -236,6 +238,55 @@ python my_agent.py
|
|
|
236
238
|
|
|
237
239
|
---
|
|
238
240
|
|
|
241
|
+
## 🌐 REST API
|
|
242
|
+
|
|
243
|
+
Full HTTP API for all modules — use from any language (JavaScript, curl, etc):
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
# Start the API server
|
|
247
|
+
python -m src.api
|
|
248
|
+
|
|
249
|
+
# Or with API key
|
|
250
|
+
WEB3_API_KEY=your-secret python -m src.api
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**Endpoints:**
|
|
254
|
+
|
|
255
|
+
| Endpoint | Method | Description |
|
|
256
|
+
|----------|--------|-------------|
|
|
257
|
+
| `/wallet/info` | GET | Wallet info + balance |
|
|
258
|
+
| `/swap/quote` | GET | Get swap quote |
|
|
259
|
+
| `/swap/execute` | POST | Execute token swap |
|
|
260
|
+
| `/portfolio/` | GET | Portfolio dashboard |
|
|
261
|
+
| `/gas/estimate` | GET | Gas estimates (EIP-1559) |
|
|
262
|
+
| `/gas/recommendation` | GET | Gas timing recommendation |
|
|
263
|
+
| `/watcher/list` | GET | List watched wallets |
|
|
264
|
+
| `/watcher/add` | POST | Add wallet to watch |
|
|
265
|
+
| `/approval/scan` | GET | Scan token approvals |
|
|
266
|
+
| `/approval/risk` | GET | Risk report |
|
|
267
|
+
| `/dca/orders` | GET/POST | List/create DCA orders |
|
|
268
|
+
| `/yield/opportunities` | GET | Scan yield opportunities |
|
|
269
|
+
| `/yield/best` | GET | Find best yield |
|
|
270
|
+
| `/bridge/quote` | GET | Get bridge quote |
|
|
271
|
+
| `/bridge/execute` | POST | Execute bridge |
|
|
272
|
+
| `/health` | GET | Health check |
|
|
273
|
+
| `/docs` | GET | Swagger UI |
|
|
274
|
+
| `/redoc` | GET | ReDoc documentation |
|
|
275
|
+
|
|
276
|
+
**Example:**
|
|
277
|
+
```bash
|
|
278
|
+
# Get gas estimate
|
|
279
|
+
curl http://localhost:8000/gas/estimate?chain=ethereum
|
|
280
|
+
|
|
281
|
+
# Get swap quote
|
|
282
|
+
curl "http://localhost:8000/swap/quote?token_in=ETH&token_out=USDC&amount_in=1.0"
|
|
283
|
+
|
|
284
|
+
# Scan approvals
|
|
285
|
+
curl http://localhost:8000/approval/scan?chain=ethereum
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
239
290
|
## 🎯 Showcase
|
|
240
291
|
|
|
241
292
|
### Telegram Bot
|
|
@@ -267,6 +318,7 @@ Features: balance check, token swap, portfolio tracking, token sniper, cross-cha
|
|
|
267
318
|
| `examples/multi_wallet.py` | Multi-wallet management + batch ops |
|
|
268
319
|
| `examples/plugin_system.py` | Plugin system usage + custom plugins |
|
|
269
320
|
| `examples/dca_bot.py` | Dollar-cost averaging bot with intervals & limits |
|
|
321
|
+
| `examples/api_server.py` | REST API server with Swagger docs |
|
|
270
322
|
| `examples/airdrop_farmer.py` | Multi-chain airdrop farming |
|
|
271
323
|
| `examples/sniper_bot.py` | Token launch sniper |
|
|
272
324
|
| `examples/portfolio_tracker.py` | Portfolio tracking & reporting |
|
|
@@ -353,6 +405,54 @@ print(summary)
|
|
|
353
405
|
|
|
354
406
|
---
|
|
355
407
|
|
|
408
|
+
## 🪂 Airdrop Automation
|
|
409
|
+
|
|
410
|
+
Discover, track, and complete airdrop campaigns across multiple platforms:
|
|
411
|
+
|
|
412
|
+
```python
|
|
413
|
+
from web3_agent_kit.airdrop import (
|
|
414
|
+
GalxePlatform, ZealyPlatform, GleamCampaign,
|
|
415
|
+
AirdropTracker, AirdropFarmer, SocialTaskManager,
|
|
416
|
+
PlatformConfig, TaskType, SybilAvoidanceConfig,
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
# Track campaigns across platforms
|
|
420
|
+
tracker = AirdropTracker()
|
|
421
|
+
|
|
422
|
+
# Galxe integration
|
|
423
|
+
galxe = GalxePlatform(config=PlatformConfig(api_key="your_key"))
|
|
424
|
+
galxe.login({"api_key": "your_key"})
|
|
425
|
+
tasks = galxe.get_tasks("campaign_id")
|
|
426
|
+
for task in tasks:
|
|
427
|
+
galxe.complete_task(task)
|
|
428
|
+
|
|
429
|
+
# Social task automation
|
|
430
|
+
social = SocialTaskManager()
|
|
431
|
+
social.complete_social_task(TaskType.SOCIAL_TWITTER_FOLLOW, "defi_project")
|
|
432
|
+
social.complete_social_task(TaskType.SOCIAL_DISCORD_JOIN, "https://discord.gg/invite")
|
|
433
|
+
|
|
434
|
+
# Multi-wallet farming with Sybil avoidance
|
|
435
|
+
farmer = AirdropFarmer(
|
|
436
|
+
wallet_manager=manager,
|
|
437
|
+
group="airdrop",
|
|
438
|
+
config=SybilAvoidanceConfig(
|
|
439
|
+
min_delay_between_wallets=60,
|
|
440
|
+
max_delay_between_wallets=600,
|
|
441
|
+
max_tasks_per_wallet_per_day=10,
|
|
442
|
+
),
|
|
443
|
+
)
|
|
444
|
+
results = farmer.farm_campaign(campaign, execute=True)
|
|
445
|
+
|
|
446
|
+
# Export report
|
|
447
|
+
tracker.export_json("./airdrop_report.json")
|
|
448
|
+
tracker.export_csv("./airdrop_report.csv")
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
**Supported platforms:** Gleam.io, Zealy (Crew3), Galxe (Project Galaxy)
|
|
452
|
+
**Social tasks:** Twitter, Discord, Telegram, YouTube, GitHub
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
356
456
|
## 🌉 Bridge Agent
|
|
357
457
|
|
|
358
458
|
Cross-chain transfers via Li.Fi and Socket:
|
|
@@ -483,13 +583,26 @@ web3-agent-kit/
|
|
|
483
583
|
│ ├── bridge.py # Cross-chain bridge agent
|
|
484
584
|
│ ├── yield_optimizer.py # Yield optimizer + auto-compound
|
|
485
585
|
│ ├── multi_wallet.py # Multi-wallet manager + batch ops
|
|
586
|
+
│ ├── airdrop/ # Airdrop automation module
|
|
587
|
+
│ │ ├── __init__.py # Package exports
|
|
588
|
+
│ │ ├── base.py # Base platform abstraction
|
|
589
|
+
│ │ ├── gleam.py # Gleam.io automation
|
|
590
|
+
│ │ ├── zealy.py # Zealy quest automation
|
|
591
|
+
│ │ ├── galxe.py # Galxe campaign automation
|
|
592
|
+
│ │ ├── social.py # Social task helpers
|
|
593
|
+
│ │ ├── tracker.py # Airdrop tracker
|
|
594
|
+
│ │ └── multi_wallet.py # Multi-wallet farming
|
|
486
595
|
│ ├── plugins/
|
|
487
596
|
│ │ ├── __init__.py # Plugin system (base, registry, manager)
|
|
488
597
|
│ │ └── examples/
|
|
489
598
|
│ │ └── gas_tracker.py
|
|
599
|
+
│ ├── api/
|
|
600
|
+
│ │ ├── __init__.py # FastAPI REST API server
|
|
601
|
+
│ │ ├── models.py # Pydantic request/response models
|
|
602
|
+
│ │ └── routes/ # API route handlers
|
|
490
603
|
│ └── defi/
|
|
491
604
|
│ └── __init__.py # Uniswap, Aerodrome, Aave, Curve
|
|
492
|
-
├── examples/ #
|
|
605
|
+
├── examples/ # 15 ready-to-use examples
|
|
493
606
|
├── tests/ # Test suite
|
|
494
607
|
└── docs/ # Documentation
|
|
495
608
|
```
|
|
@@ -34,6 +34,7 @@ Building AI agents that interact with blockchains is **hard**. You need to juggl
|
|
|
34
34
|
| **Security** | Manual approval checks | Auto-scan & revoke risky approvals |
|
|
35
35
|
| **Alerts** | Manual whale tracking | Auto-monitor wallets, instant alerts |
|
|
36
36
|
| **Multi-wallet** | Manage keys manually | Batch ops, consolidated portfolio, wallet groups |
|
|
37
|
+
| **Airdrops** | Manual quest hunting | Auto-track campaigns, multi-wallet farming, Sybil-safe |
|
|
37
38
|
| **Extensibility** | Hard-coded logic | Plugin system — community can extend anything |
|
|
38
39
|
| **Error Handling** | Manual retry logic | Auto-fallback across LLM providers & RPCs |
|
|
39
40
|
|
|
@@ -107,6 +108,7 @@ Building AI agents that interact with blockchains is **hard**. You need to juggl
|
|
|
107
108
|
| **Wallet Watcher** | ✅ | ❌ | ❌ | ❌ |
|
|
108
109
|
| **Yield Optimizer** | ✅ | ❌ | ❌ | ❌ |
|
|
109
110
|
| **Multi-Wallet** | ✅ | ❌ | ❌ | ❌ |
|
|
111
|
+
| **Airdrops** | ✅ | ❌ | ❌ | ❌ |
|
|
110
112
|
| **Plugin System** | ✅ | ❌ | ❌ | ❌ |
|
|
111
113
|
| **Safety Rails** | ✅ Governor | ❌ | ❌ | ❌ |
|
|
112
114
|
| **Natural Language** | ✅ | Partial | ❌ | ❌ |
|
|
@@ -202,6 +204,55 @@ python my_agent.py
|
|
|
202
204
|
|
|
203
205
|
---
|
|
204
206
|
|
|
207
|
+
## 🌐 REST API
|
|
208
|
+
|
|
209
|
+
Full HTTP API for all modules — use from any language (JavaScript, curl, etc):
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
# Start the API server
|
|
213
|
+
python -m src.api
|
|
214
|
+
|
|
215
|
+
# Or with API key
|
|
216
|
+
WEB3_API_KEY=your-secret python -m src.api
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**Endpoints:**
|
|
220
|
+
|
|
221
|
+
| Endpoint | Method | Description |
|
|
222
|
+
|----------|--------|-------------|
|
|
223
|
+
| `/wallet/info` | GET | Wallet info + balance |
|
|
224
|
+
| `/swap/quote` | GET | Get swap quote |
|
|
225
|
+
| `/swap/execute` | POST | Execute token swap |
|
|
226
|
+
| `/portfolio/` | GET | Portfolio dashboard |
|
|
227
|
+
| `/gas/estimate` | GET | Gas estimates (EIP-1559) |
|
|
228
|
+
| `/gas/recommendation` | GET | Gas timing recommendation |
|
|
229
|
+
| `/watcher/list` | GET | List watched wallets |
|
|
230
|
+
| `/watcher/add` | POST | Add wallet to watch |
|
|
231
|
+
| `/approval/scan` | GET | Scan token approvals |
|
|
232
|
+
| `/approval/risk` | GET | Risk report |
|
|
233
|
+
| `/dca/orders` | GET/POST | List/create DCA orders |
|
|
234
|
+
| `/yield/opportunities` | GET | Scan yield opportunities |
|
|
235
|
+
| `/yield/best` | GET | Find best yield |
|
|
236
|
+
| `/bridge/quote` | GET | Get bridge quote |
|
|
237
|
+
| `/bridge/execute` | POST | Execute bridge |
|
|
238
|
+
| `/health` | GET | Health check |
|
|
239
|
+
| `/docs` | GET | Swagger UI |
|
|
240
|
+
| `/redoc` | GET | ReDoc documentation |
|
|
241
|
+
|
|
242
|
+
**Example:**
|
|
243
|
+
```bash
|
|
244
|
+
# Get gas estimate
|
|
245
|
+
curl http://localhost:8000/gas/estimate?chain=ethereum
|
|
246
|
+
|
|
247
|
+
# Get swap quote
|
|
248
|
+
curl "http://localhost:8000/swap/quote?token_in=ETH&token_out=USDC&amount_in=1.0"
|
|
249
|
+
|
|
250
|
+
# Scan approvals
|
|
251
|
+
curl http://localhost:8000/approval/scan?chain=ethereum
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
205
256
|
## 🎯 Showcase
|
|
206
257
|
|
|
207
258
|
### Telegram Bot
|
|
@@ -233,6 +284,7 @@ Features: balance check, token swap, portfolio tracking, token sniper, cross-cha
|
|
|
233
284
|
| `examples/multi_wallet.py` | Multi-wallet management + batch ops |
|
|
234
285
|
| `examples/plugin_system.py` | Plugin system usage + custom plugins |
|
|
235
286
|
| `examples/dca_bot.py` | Dollar-cost averaging bot with intervals & limits |
|
|
287
|
+
| `examples/api_server.py` | REST API server with Swagger docs |
|
|
236
288
|
| `examples/airdrop_farmer.py` | Multi-chain airdrop farming |
|
|
237
289
|
| `examples/sniper_bot.py` | Token launch sniper |
|
|
238
290
|
| `examples/portfolio_tracker.py` | Portfolio tracking & reporting |
|
|
@@ -319,6 +371,54 @@ print(summary)
|
|
|
319
371
|
|
|
320
372
|
---
|
|
321
373
|
|
|
374
|
+
## 🪂 Airdrop Automation
|
|
375
|
+
|
|
376
|
+
Discover, track, and complete airdrop campaigns across multiple platforms:
|
|
377
|
+
|
|
378
|
+
```python
|
|
379
|
+
from web3_agent_kit.airdrop import (
|
|
380
|
+
GalxePlatform, ZealyPlatform, GleamCampaign,
|
|
381
|
+
AirdropTracker, AirdropFarmer, SocialTaskManager,
|
|
382
|
+
PlatformConfig, TaskType, SybilAvoidanceConfig,
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
# Track campaigns across platforms
|
|
386
|
+
tracker = AirdropTracker()
|
|
387
|
+
|
|
388
|
+
# Galxe integration
|
|
389
|
+
galxe = GalxePlatform(config=PlatformConfig(api_key="your_key"))
|
|
390
|
+
galxe.login({"api_key": "your_key"})
|
|
391
|
+
tasks = galxe.get_tasks("campaign_id")
|
|
392
|
+
for task in tasks:
|
|
393
|
+
galxe.complete_task(task)
|
|
394
|
+
|
|
395
|
+
# Social task automation
|
|
396
|
+
social = SocialTaskManager()
|
|
397
|
+
social.complete_social_task(TaskType.SOCIAL_TWITTER_FOLLOW, "defi_project")
|
|
398
|
+
social.complete_social_task(TaskType.SOCIAL_DISCORD_JOIN, "https://discord.gg/invite")
|
|
399
|
+
|
|
400
|
+
# Multi-wallet farming with Sybil avoidance
|
|
401
|
+
farmer = AirdropFarmer(
|
|
402
|
+
wallet_manager=manager,
|
|
403
|
+
group="airdrop",
|
|
404
|
+
config=SybilAvoidanceConfig(
|
|
405
|
+
min_delay_between_wallets=60,
|
|
406
|
+
max_delay_between_wallets=600,
|
|
407
|
+
max_tasks_per_wallet_per_day=10,
|
|
408
|
+
),
|
|
409
|
+
)
|
|
410
|
+
results = farmer.farm_campaign(campaign, execute=True)
|
|
411
|
+
|
|
412
|
+
# Export report
|
|
413
|
+
tracker.export_json("./airdrop_report.json")
|
|
414
|
+
tracker.export_csv("./airdrop_report.csv")
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
**Supported platforms:** Gleam.io, Zealy (Crew3), Galxe (Project Galaxy)
|
|
418
|
+
**Social tasks:** Twitter, Discord, Telegram, YouTube, GitHub
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
322
422
|
## 🌉 Bridge Agent
|
|
323
423
|
|
|
324
424
|
Cross-chain transfers via Li.Fi and Socket:
|
|
@@ -449,13 +549,26 @@ web3-agent-kit/
|
|
|
449
549
|
│ ├── bridge.py # Cross-chain bridge agent
|
|
450
550
|
│ ├── yield_optimizer.py # Yield optimizer + auto-compound
|
|
451
551
|
│ ├── multi_wallet.py # Multi-wallet manager + batch ops
|
|
552
|
+
│ ├── airdrop/ # Airdrop automation module
|
|
553
|
+
│ │ ├── __init__.py # Package exports
|
|
554
|
+
│ │ ├── base.py # Base platform abstraction
|
|
555
|
+
│ │ ├── gleam.py # Gleam.io automation
|
|
556
|
+
│ │ ├── zealy.py # Zealy quest automation
|
|
557
|
+
│ │ ├── galxe.py # Galxe campaign automation
|
|
558
|
+
│ │ ├── social.py # Social task helpers
|
|
559
|
+
│ │ ├── tracker.py # Airdrop tracker
|
|
560
|
+
│ │ └── multi_wallet.py # Multi-wallet farming
|
|
452
561
|
│ ├── plugins/
|
|
453
562
|
│ │ ├── __init__.py # Plugin system (base, registry, manager)
|
|
454
563
|
│ │ └── examples/
|
|
455
564
|
│ │ └── gas_tracker.py
|
|
565
|
+
│ ├── api/
|
|
566
|
+
│ │ ├── __init__.py # FastAPI REST API server
|
|
567
|
+
│ │ ├── models.py # Pydantic request/response models
|
|
568
|
+
│ │ └── routes/ # API route handlers
|
|
456
569
|
│ └── defi/
|
|
457
570
|
│ └── __init__.py # Uniswap, Aerodrome, Aave, Curve
|
|
458
|
-
├── examples/ #
|
|
571
|
+
├── examples/ # 15 ready-to-use examples
|
|
459
572
|
├── tests/ # Test suite
|
|
460
573
|
└── docs/ # Documentation
|
|
461
574
|
```
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "web3-agent-kit"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.8.0"
|
|
8
8
|
description = "Open-source framework for building autonomous AI agents that interact with blockchain networks"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Airdrop automation module — discover, track, and complete airdrop campaigns."""
|
|
2
|
+
|
|
3
|
+
from .base import (
|
|
4
|
+
BaseAirdropPlatform,
|
|
5
|
+
PlatformConfig,
|
|
6
|
+
AirdropTask,
|
|
7
|
+
AirdropCampaign,
|
|
8
|
+
TaskType,
|
|
9
|
+
TaskStatus,
|
|
10
|
+
)
|
|
11
|
+
from .gleam import GleamCampaign
|
|
12
|
+
from .zealy import ZealyPlatform, ZealyQuest, ZealyLeaderboardEntry
|
|
13
|
+
from .galxe import GalxePlatform, GalxeCredential, GalxePoints
|
|
14
|
+
from .social import (
|
|
15
|
+
SocialTaskManager,
|
|
16
|
+
SocialAccount,
|
|
17
|
+
SocialPlatform,
|
|
18
|
+
SocialTaskResult,
|
|
19
|
+
TwitterHelper,
|
|
20
|
+
DiscordHelper,
|
|
21
|
+
TelegramHelper,
|
|
22
|
+
YouTubeHelper,
|
|
23
|
+
GitHubHelper,
|
|
24
|
+
)
|
|
25
|
+
from .tracker import AirdropTracker, AirdropReward, AirdropSummary
|
|
26
|
+
from .multi_wallet import AirdropFarmer, SybilAvoidanceConfig, FarmResult, WalletFarmProgress
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
# Base
|
|
30
|
+
"BaseAirdropPlatform",
|
|
31
|
+
"PlatformConfig",
|
|
32
|
+
"AirdropTask",
|
|
33
|
+
"AirdropCampaign",
|
|
34
|
+
"TaskType",
|
|
35
|
+
"TaskStatus",
|
|
36
|
+
# Gleam
|
|
37
|
+
"GleamCampaign",
|
|
38
|
+
# Zealy
|
|
39
|
+
"ZealyPlatform",
|
|
40
|
+
"ZealyQuest",
|
|
41
|
+
"ZealyLeaderboardEntry",
|
|
42
|
+
# Galxe
|
|
43
|
+
"GalxePlatform",
|
|
44
|
+
"GalxeCredential",
|
|
45
|
+
"GalxePoints",
|
|
46
|
+
# Social
|
|
47
|
+
"SocialTaskManager",
|
|
48
|
+
"SocialAccount",
|
|
49
|
+
"SocialPlatform",
|
|
50
|
+
"SocialTaskResult",
|
|
51
|
+
"TwitterHelper",
|
|
52
|
+
"DiscordHelper",
|
|
53
|
+
"TelegramHelper",
|
|
54
|
+
"YouTubeHelper",
|
|
55
|
+
"GitHubHelper",
|
|
56
|
+
# Tracker
|
|
57
|
+
"AirdropTracker",
|
|
58
|
+
"AirdropReward",
|
|
59
|
+
"AirdropSummary",
|
|
60
|
+
# Multi-wallet farming
|
|
61
|
+
"AirdropFarmer",
|
|
62
|
+
"SybilAvoidanceConfig",
|
|
63
|
+
"FarmResult",
|
|
64
|
+
"WalletFarmProgress",
|
|
65
|
+
]
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"""Base airdrop platform abstraction — common interface for all platforms."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import time
|
|
7
|
+
from abc import ABC, abstractmethod
|
|
8
|
+
from dataclasses import dataclass, field
|
|
9
|
+
from enum import Enum
|
|
10
|
+
from typing import Optional
|
|
11
|
+
|
|
12
|
+
import requests
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class TaskType(Enum):
|
|
18
|
+
"""Types of airdrop tasks."""
|
|
19
|
+
SOCIAL_TWITTER_FOLLOW = "twitter_follow"
|
|
20
|
+
SOCIAL_TWITTER_RETWEET = "twitter_retweet"
|
|
21
|
+
SOCIAL_TWITTER_LIKE = "twitter_like"
|
|
22
|
+
SOCIAL_TWITTER_COMMENT = "twitter_comment"
|
|
23
|
+
SOCIAL_DISCORD_JOIN = "discord_join"
|
|
24
|
+
SOCIAL_DISCORD_VERIFY = "discord_verify"
|
|
25
|
+
SOCIAL_TELEGRAM_JOIN = "telegram_join"
|
|
26
|
+
SOCIAL_YOUTUBE_SUBSCRIBE = "youtube_subscribe"
|
|
27
|
+
SOCIAL_GITHUB_STAR = "github_star"
|
|
28
|
+
SOCIAL_GITHUB_FORK = "github_fork"
|
|
29
|
+
ON_CHAIN_TX = "on_chain_tx"
|
|
30
|
+
ON_CHAIN_SWAP = "on_chain_swap"
|
|
31
|
+
ON_CHAIN_BRIDGE = "on_chain_bridge"
|
|
32
|
+
ON_CHAIN_STAKE = "on_chain_stake"
|
|
33
|
+
QUIZ = "quiz"
|
|
34
|
+
VISIT_URL = "visit_url"
|
|
35
|
+
WALLET_CONNECT = "wallet_connect"
|
|
36
|
+
REFERRAL = "referral"
|
|
37
|
+
CUSTOM = "custom"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class TaskStatus(Enum):
|
|
41
|
+
"""Status of a task."""
|
|
42
|
+
PENDING = "pending"
|
|
43
|
+
IN_PROGRESS = "in_progress"
|
|
44
|
+
COMPLETED = "completed"
|
|
45
|
+
VERIFIED = "verified"
|
|
46
|
+
FAILED = "failed"
|
|
47
|
+
SKIPPED = "skipped"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass
|
|
51
|
+
class AirdropTask:
|
|
52
|
+
"""A single airdrop task."""
|
|
53
|
+
task_id: str
|
|
54
|
+
platform: str
|
|
55
|
+
task_type: TaskType
|
|
56
|
+
title: str
|
|
57
|
+
description: str = ""
|
|
58
|
+
url: str = ""
|
|
59
|
+
points: float = 0
|
|
60
|
+
status: TaskStatus = TaskStatus.PENDING
|
|
61
|
+
completed_at: Optional[float] = None
|
|
62
|
+
metadata: dict = field(default_factory=dict)
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def is_social(self) -> bool:
|
|
66
|
+
return self.task_type.name.startswith("SOCIAL_")
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def is_on_chain(self) -> bool:
|
|
70
|
+
return self.task_type.name.startswith("ON_CHAIN_")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@dataclass
|
|
74
|
+
class AirdropCampaign:
|
|
75
|
+
"""An airdrop campaign listing."""
|
|
76
|
+
campaign_id: str
|
|
77
|
+
platform: str
|
|
78
|
+
name: str
|
|
79
|
+
description: str = ""
|
|
80
|
+
url: str = ""
|
|
81
|
+
total_points: float = 0
|
|
82
|
+
earned_points: float = 0
|
|
83
|
+
deadline: Optional[float] = None
|
|
84
|
+
tasks: list[AirdropTask] = field(default_factory=list)
|
|
85
|
+
is_active: bool = True
|
|
86
|
+
metadata: dict = field(default_factory=dict)
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def progress(self) -> float:
|
|
90
|
+
if self.total_points == 0:
|
|
91
|
+
return 0.0
|
|
92
|
+
return self.earned_points / self.total_points
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def is_expired(self) -> bool:
|
|
96
|
+
if self.deadline is None:
|
|
97
|
+
return False
|
|
98
|
+
return time.time() > self.deadline
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@dataclass
|
|
102
|
+
class PlatformConfig:
|
|
103
|
+
"""Configuration for an airdrop platform."""
|
|
104
|
+
api_key: Optional[str] = None
|
|
105
|
+
session_cookie: Optional[str] = None
|
|
106
|
+
user_agent: str = (
|
|
107
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
|
108
|
+
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
|
109
|
+
"Chrome/120.0.0.0 Safari/537.36"
|
|
110
|
+
)
|
|
111
|
+
rate_limit_delay: float = 2.0
|
|
112
|
+
max_retries: int = 3
|
|
113
|
+
retry_delay: float = 5.0
|
|
114
|
+
timeout: int = 30
|
|
115
|
+
proxy: Optional[str] = None
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class BaseAirdropPlatform(ABC):
|
|
119
|
+
"""Abstract base class for all airdrop platform integrations.
|
|
120
|
+
|
|
121
|
+
Provides common functionality: session management, rate limiting,
|
|
122
|
+
retry logic, and the standard interface every platform must implement.
|
|
123
|
+
|
|
124
|
+
Example::
|
|
125
|
+
|
|
126
|
+
class MyPlatform(BaseAirdropPlatform):
|
|
127
|
+
platform_name = "my_platform"
|
|
128
|
+
|
|
129
|
+
def login(self, credentials):
|
|
130
|
+
...
|
|
131
|
+
|
|
132
|
+
def get_tasks(self, campaign_id):
|
|
133
|
+
...
|
|
134
|
+
|
|
135
|
+
def complete_task(self, task):
|
|
136
|
+
...
|
|
137
|
+
|
|
138
|
+
def verify_completion(self, task):
|
|
139
|
+
...
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
platform_name: str = "unknown"
|
|
143
|
+
|
|
144
|
+
def __init__(self, config: Optional[PlatformConfig] = None):
|
|
145
|
+
self.config = config or PlatformConfig()
|
|
146
|
+
self.session = requests.Session()
|
|
147
|
+
self.session.headers.update({
|
|
148
|
+
"User-Agent": self.config.user_agent,
|
|
149
|
+
})
|
|
150
|
+
if self.config.session_cookie:
|
|
151
|
+
self.session.cookies.set("session", self.config.session_cookie)
|
|
152
|
+
if self.config.proxy:
|
|
153
|
+
self.session.proxies = {"http": self.config.proxy, "https": self.config.proxy}
|
|
154
|
+
self._last_request_time: float = 0
|
|
155
|
+
self._authenticated: bool = False
|
|
156
|
+
logger.info(f"Initialized {self.platform_name} platform")
|
|
157
|
+
|
|
158
|
+
@abstractmethod
|
|
159
|
+
def login(self, credentials: dict) -> bool:
|
|
160
|
+
"""Authenticate with the platform.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
credentials: Platform-specific credentials.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
True if login succeeded.
|
|
167
|
+
"""
|
|
168
|
+
...
|
|
169
|
+
|
|
170
|
+
@abstractmethod
|
|
171
|
+
def get_tasks(self, campaign_id: str) -> list[AirdropTask]:
|
|
172
|
+
"""Get available tasks for a campaign.
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
campaign_id: Platform-specific campaign identifier.
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
List of AirdropTask objects.
|
|
179
|
+
"""
|
|
180
|
+
...
|
|
181
|
+
|
|
182
|
+
@abstractmethod
|
|
183
|
+
def complete_task(self, task: AirdropTask) -> bool:
|
|
184
|
+
"""Attempt to complete a task.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
task: The task to complete.
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
True if task was completed successfully.
|
|
191
|
+
"""
|
|
192
|
+
...
|
|
193
|
+
|
|
194
|
+
@abstractmethod
|
|
195
|
+
def verify_completion(self, task: AirdropTask) -> bool:
|
|
196
|
+
"""Verify that a task is completed.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
task: The task to verify.
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
True if verified as completed.
|
|
203
|
+
"""
|
|
204
|
+
...
|
|
205
|
+
|
|
206
|
+
def discover_campaigns(self) -> list[AirdropCampaign]:
|
|
207
|
+
"""Discover available campaigns. Override in subclasses.
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
List of AirdropCampaign objects.
|
|
211
|
+
"""
|
|
212
|
+
return []
|
|
213
|
+
|
|
214
|
+
def _rate_limit(self):
|
|
215
|
+
"""Enforce rate limiting between requests."""
|
|
216
|
+
elapsed = time.time() - self._last_request_time
|
|
217
|
+
if elapsed < self.config.rate_limit_delay:
|
|
218
|
+
sleep_time = self.config.rate_limit_delay - elapsed
|
|
219
|
+
logger.debug(f"Rate limiting: sleeping {sleep_time:.1f}s")
|
|
220
|
+
time.sleep(sleep_time)
|
|
221
|
+
self._last_request_time = time.time()
|
|
222
|
+
|
|
223
|
+
def _request(
|
|
224
|
+
self,
|
|
225
|
+
method: str,
|
|
226
|
+
url: str,
|
|
227
|
+
**kwargs,
|
|
228
|
+
) -> requests.Response:
|
|
229
|
+
"""Make an HTTP request with rate limiting and retry logic.
|
|
230
|
+
|
|
231
|
+
Args:
|
|
232
|
+
method: HTTP method (GET, POST, etc.).
|
|
233
|
+
url: Request URL.
|
|
234
|
+
**kwargs: Passed to requests.
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
Response object.
|
|
238
|
+
|
|
239
|
+
Raises:
|
|
240
|
+
requests.RequestException: After all retries exhausted.
|
|
241
|
+
"""
|
|
242
|
+
kwargs.setdefault("timeout", self.config.timeout)
|
|
243
|
+
last_error = None
|
|
244
|
+
|
|
245
|
+
for attempt in range(self.config.max_retries):
|
|
246
|
+
self._rate_limit()
|
|
247
|
+
try:
|
|
248
|
+
response = self.session.request(method, url, **kwargs)
|
|
249
|
+
if response.status_code == 429:
|
|
250
|
+
retry_after = int(response.headers.get("Retry-After", self.config.retry_delay))
|
|
251
|
+
logger.warning(f"Rate limited, waiting {retry_after}s")
|
|
252
|
+
time.sleep(retry_after)
|
|
253
|
+
continue
|
|
254
|
+
response.raise_for_status()
|
|
255
|
+
return response
|
|
256
|
+
except requests.RequestException as e:
|
|
257
|
+
last_error = e
|
|
258
|
+
logger.warning(f"Request failed (attempt {attempt + 1}): {e}")
|
|
259
|
+
if attempt < self.config.max_retries - 1:
|
|
260
|
+
time.sleep(self.config.retry_delay * (attempt + 1))
|
|
261
|
+
|
|
262
|
+
raise last_error # type: ignore[misc]
|
|
263
|
+
|
|
264
|
+
def _get(self, url: str, **kwargs) -> requests.Response:
|
|
265
|
+
return self._request("GET", url, **kwargs)
|
|
266
|
+
|
|
267
|
+
def _post(self, url: str, **kwargs) -> requests.Response:
|
|
268
|
+
return self._request("POST", url, **kwargs)
|