@intentsolutionsio/flash-loan-simulator 1.0.0 → 1.0.5
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.
- package/README.md +31 -12
- package/agents/flashloan-agent.md +17 -0
- package/package.json +1 -1
- package/skills/simulating-flash-loans/ARD.md +21 -7
- package/skills/simulating-flash-loans/PRD.md +9 -3
- package/skills/simulating-flash-loans/SKILL.md +29 -8
- package/skills/simulating-flash-loans/references/errors.md +47 -2
- package/skills/simulating-flash-loans/references/examples.md +12 -0
- package/skills/simulating-flash-loans/references/implementation.md +6 -0
- package/skills/simulating-flash-loans/scripts/flash_simulator.py +29 -85
- package/skills/simulating-flash-loans/scripts/formatters.py +19 -51
- package/skills/simulating-flash-loans/scripts/profit_calculator.py +16 -16
- package/skills/simulating-flash-loans/scripts/protocol_adapters.py +2 -8
- package/skills/simulating-flash-loans/scripts/risk_assessor.py +6 -17
- package/skills/simulating-flash-loans/scripts/strategy_engine.py +6 -14
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
## RPC Connection Errors
|
|
4
4
|
|
|
5
5
|
### ERR-001: RPC Connection Timeout
|
|
6
|
+
|
|
6
7
|
```
|
|
7
8
|
Error: Request timed out after 30000ms
|
|
8
9
|
```
|
|
@@ -10,16 +11,20 @@ Error: Request timed out after 30000ms
|
|
|
10
11
|
**Cause:** Network latency or overloaded RPC endpoint.
|
|
11
12
|
|
|
12
13
|
**Solution:**
|
|
14
|
+
|
|
13
15
|
1. Switch to a different RPC endpoint:
|
|
16
|
+
|
|
14
17
|
```yaml
|
|
15
18
|
rpc_endpoints:
|
|
16
|
-
ethereum: "
|
|
19
|
+
ethereum: "eth" # Free, no signup
|
|
17
20
|
backup: "https://eth.llamarpc.com" # Alternative
|
|
18
21
|
```
|
|
22
|
+
|
|
19
23
|
2. Increase timeout in settings.yaml
|
|
20
24
|
3. Check network connectivity
|
|
21
25
|
|
|
22
26
|
### ERR-002: RPC Rate Limited
|
|
27
|
+
|
|
23
28
|
```
|
|
24
29
|
Error: 429 Too Many Requests
|
|
25
30
|
```
|
|
@@ -27,11 +32,14 @@ Error: 429 Too Many Requests
|
|
|
27
32
|
**Cause:** Free RPC tier limits exceeded.
|
|
28
33
|
|
|
29
34
|
**Solution:**
|
|
35
|
+
|
|
30
36
|
1. Add delay between requests:
|
|
37
|
+
|
|
31
38
|
```python
|
|
32
39
|
import time
|
|
33
40
|
time.sleep(0.5) # 500ms between calls
|
|
34
41
|
```
|
|
42
|
+
|
|
35
43
|
2. Switch to a different free RPC (rotate between Ankr, Chainstack, Llamarpc)
|
|
36
44
|
3. Use a private RPC for production (Alchemy, Chainstack, Infura, or QuickNode)
|
|
37
45
|
|
|
@@ -40,6 +48,7 @@ Error: 429 Too Many Requests
|
|
|
40
48
|
## Simulation Errors
|
|
41
49
|
|
|
42
50
|
### ERR-010: Insufficient Liquidity
|
|
51
|
+
|
|
43
52
|
```
|
|
44
53
|
Error: Loan amount exceeds available liquidity
|
|
45
54
|
Provider: Aave V3
|
|
@@ -50,11 +59,13 @@ Requested: 100,000 ETH
|
|
|
50
59
|
**Cause:** Flash loan amount exceeds pool depth.
|
|
51
60
|
|
|
52
61
|
**Solution:**
|
|
62
|
+
|
|
53
63
|
1. Reduce loan amount
|
|
54
64
|
2. Split across multiple providers
|
|
55
65
|
3. Use a different asset with more liquidity
|
|
56
66
|
|
|
57
67
|
### ERR-011: Unsupported Asset
|
|
68
|
+
|
|
58
69
|
```
|
|
59
70
|
Error: Asset 'SHIB' not supported by provider 'dYdX'
|
|
60
71
|
```
|
|
@@ -62,14 +73,18 @@ Error: Asset 'SHIB' not supported by provider 'dYdX'
|
|
|
62
73
|
**Cause:** Provider doesn't support the requested token.
|
|
63
74
|
|
|
64
75
|
**Solution:**
|
|
76
|
+
|
|
65
77
|
1. Check provider's supported assets:
|
|
78
|
+
|
|
66
79
|
```bash
|
|
67
80
|
python flash_simulator.py compare SHIB 1000
|
|
68
81
|
```
|
|
82
|
+
|
|
69
83
|
2. Use a different provider (Aave V3 supports more assets)
|
|
70
84
|
3. Swap to a supported intermediary token
|
|
71
85
|
|
|
72
86
|
### ERR-012: Chain Mismatch
|
|
87
|
+
|
|
73
88
|
```
|
|
74
89
|
Error: Provider 'dYdX' not available on chain 'polygon'
|
|
75
90
|
```
|
|
@@ -77,6 +92,7 @@ Error: Provider 'dYdX' not available on chain 'polygon'
|
|
|
77
92
|
**Cause:** Provider only operates on specific chains.
|
|
78
93
|
|
|
79
94
|
**Solution:**
|
|
95
|
+
|
|
80
96
|
1. Check provider chains:
|
|
81
97
|
- dYdX: Ethereum only
|
|
82
98
|
- Aave V3: Ethereum, Polygon, Arbitrum, Optimism, Avalanche
|
|
@@ -88,6 +104,7 @@ Error: Provider 'dYdX' not available on chain 'polygon'
|
|
|
88
104
|
## Strategy Errors
|
|
89
105
|
|
|
90
106
|
### ERR-020: No Profitable Route
|
|
107
|
+
|
|
91
108
|
```
|
|
92
109
|
Error: All simulated routes result in loss
|
|
93
110
|
Best route: -0.05 ETH (-$125.00)
|
|
@@ -96,12 +113,14 @@ Best route: -0.05 ETH (-$125.00)
|
|
|
96
113
|
**Cause:** Current market conditions don't support the arbitrage.
|
|
97
114
|
|
|
98
115
|
**Solution:**
|
|
116
|
+
|
|
99
117
|
1. Wait for better price differences
|
|
100
118
|
2. Try different token pairs
|
|
101
119
|
3. Consider smaller trade sizes (less slippage)
|
|
102
120
|
4. Check for stale price data
|
|
103
121
|
|
|
104
122
|
### ERR-021: Negative Profit Margin
|
|
123
|
+
|
|
105
124
|
```
|
|
106
125
|
Warning: Strategy unprofitable after costs
|
|
107
126
|
Gross profit: +0.10 ETH
|
|
@@ -112,12 +131,14 @@ Net profit: -0.05 ETH
|
|
|
112
131
|
**Cause:** Costs (gas + fees) exceed the arbitrage opportunity.
|
|
113
132
|
|
|
114
133
|
**Solution:**
|
|
134
|
+
|
|
115
135
|
1. Use a zero-fee provider (dYdX)
|
|
116
136
|
2. Wait for lower gas prices
|
|
117
137
|
3. Increase trade size to improve margin ratio
|
|
118
138
|
4. Find larger price discrepancies
|
|
119
139
|
|
|
120
140
|
### ERR-022: High MEV Competition
|
|
141
|
+
|
|
121
142
|
```
|
|
122
143
|
Warning: MEV competition score 85/100
|
|
123
144
|
This pair has high bot activity
|
|
@@ -126,6 +147,7 @@ This pair has high bot activity
|
|
|
126
147
|
**Cause:** ETH/USDC and similar pairs are heavily competed.
|
|
127
148
|
|
|
128
149
|
**Solution:**
|
|
150
|
+
|
|
129
151
|
1. Use Flashbots Protect for private transactions
|
|
130
152
|
2. Try less-competitive pairs
|
|
131
153
|
3. Consider smaller, faster trades
|
|
@@ -136,6 +158,7 @@ This pair has high bot activity
|
|
|
136
158
|
## Risk Assessment Errors
|
|
137
159
|
|
|
138
160
|
### ERR-030: Critical Risk Score
|
|
161
|
+
|
|
139
162
|
```
|
|
140
163
|
Warning: Risk score 78/100 (CRITICAL)
|
|
141
164
|
Viability: NO-GO
|
|
@@ -144,14 +167,18 @@ Viability: NO-GO
|
|
|
144
167
|
**Cause:** Multiple risk factors are elevated.
|
|
145
168
|
|
|
146
169
|
**Solution:**
|
|
170
|
+
|
|
147
171
|
1. Review individual risk factors:
|
|
172
|
+
|
|
148
173
|
```bash
|
|
149
174
|
python flash_simulator.py arbitrage ETH USDC 100 --risk-analysis
|
|
150
175
|
```
|
|
176
|
+
|
|
151
177
|
2. Address the highest-scoring factors
|
|
152
178
|
3. Consider a different strategy or timing
|
|
153
179
|
|
|
154
180
|
### ERR-031: Protocol Risk Warning
|
|
181
|
+
|
|
155
182
|
```
|
|
156
183
|
Warning: Using unaudited protocol 'NewDEX'
|
|
157
184
|
Protocol risk score: 80/100
|
|
@@ -160,6 +187,7 @@ Protocol risk score: 80/100
|
|
|
160
187
|
**Cause:** Less-established protocol increases smart contract risk.
|
|
161
188
|
|
|
162
189
|
**Solution:**
|
|
190
|
+
|
|
163
191
|
1. Verify protocol audits before using
|
|
164
192
|
2. Stick to well-audited protocols (Aave, Uniswap, Balancer)
|
|
165
193
|
3. Limit exposure to newer protocols
|
|
@@ -169,6 +197,7 @@ Protocol risk score: 80/100
|
|
|
169
197
|
## Gas Estimation Errors
|
|
170
198
|
|
|
171
199
|
### ERR-040: Gas Price Spike
|
|
200
|
+
|
|
172
201
|
```
|
|
173
202
|
Warning: Current gas price 150 gwei (normal: 30 gwei)
|
|
174
203
|
Strategy breakeven gas: 45 gwei
|
|
@@ -177,16 +206,20 @@ Strategy breakeven gas: 45 gwei
|
|
|
177
206
|
**Cause:** Network congestion causing unprofitable gas costs.
|
|
178
207
|
|
|
179
208
|
**Solution:**
|
|
209
|
+
|
|
180
210
|
1. Wait for gas prices to normalize
|
|
181
211
|
2. Use gas oracles to estimate future prices:
|
|
212
|
+
|
|
182
213
|
```python
|
|
183
214
|
# Check if current gas is above breakeven
|
|
184
215
|
if current_gas > breakeven_gas:
|
|
185
216
|
print("Wait for lower gas prices")
|
|
186
217
|
```
|
|
218
|
+
|
|
187
219
|
3. Set gas price limits in execution scripts
|
|
188
220
|
|
|
189
221
|
### ERR-041: Gas Estimation Failed
|
|
222
|
+
|
|
190
223
|
```
|
|
191
224
|
Error: Could not estimate gas for transaction
|
|
192
225
|
```
|
|
@@ -194,6 +227,7 @@ Error: Could not estimate gas for transaction
|
|
|
194
227
|
**Cause:** Transaction would revert on-chain.
|
|
195
228
|
|
|
196
229
|
**Solution:**
|
|
230
|
+
|
|
197
231
|
1. Check token approvals
|
|
198
232
|
2. Verify sufficient balances
|
|
199
233
|
3. Test on forked mainnet first
|
|
@@ -204,11 +238,13 @@ Error: Could not estimate gas for transaction
|
|
|
204
238
|
## Input Validation Errors
|
|
205
239
|
|
|
206
240
|
### ERR-050: Invalid Amount
|
|
241
|
+
|
|
207
242
|
```
|
|
208
243
|
Error: Invalid amount 'abc' - must be numeric
|
|
209
244
|
```
|
|
210
245
|
|
|
211
246
|
**Solution:**
|
|
247
|
+
|
|
212
248
|
```bash
|
|
213
249
|
# Correct usage
|
|
214
250
|
python flash_simulator.py arbitrage ETH USDC 100 # Integer
|
|
@@ -216,6 +252,7 @@ python flash_simulator.py arbitrage ETH USDC 100.5 # Decimal
|
|
|
216
252
|
```
|
|
217
253
|
|
|
218
254
|
### ERR-051: Invalid Token Symbol
|
|
255
|
+
|
|
219
256
|
```
|
|
220
257
|
Error: Unknown token 'ETHEREUM' - did you mean 'ETH'?
|
|
221
258
|
```
|
|
@@ -224,11 +261,13 @@ Error: Unknown token 'ETHEREUM' - did you mean 'ETH'?
|
|
|
224
261
|
Use standard token symbols: ETH, WETH, USDC, USDT, DAI, WBTC
|
|
225
262
|
|
|
226
263
|
### ERR-052: Invalid Provider
|
|
264
|
+
|
|
227
265
|
```
|
|
228
266
|
Error: Unknown provider 'aavev3' - valid options: aave, dydx, balancer, uniswap
|
|
229
267
|
```
|
|
230
268
|
|
|
231
269
|
**Solution:**
|
|
270
|
+
|
|
232
271
|
```bash
|
|
233
272
|
# Use lowercase provider names
|
|
234
273
|
python flash_simulator.py arbitrage ETH USDC 100 --provider aave
|
|
@@ -239,6 +278,7 @@ python flash_simulator.py arbitrage ETH USDC 100 --provider aave
|
|
|
239
278
|
## Output/Format Errors
|
|
240
279
|
|
|
241
280
|
### ERR-060: JSON Export Failed
|
|
281
|
+
|
|
242
282
|
```
|
|
243
283
|
Error: Cannot serialize Decimal to JSON
|
|
244
284
|
```
|
|
@@ -246,6 +286,7 @@ Error: Cannot serialize Decimal to JSON
|
|
|
246
286
|
**Cause:** Custom Decimal types not handled.
|
|
247
287
|
|
|
248
288
|
**Solution:** The simulator handles this automatically. If using custom code:
|
|
289
|
+
|
|
249
290
|
```python
|
|
250
291
|
from formatters import DecimalEncoder
|
|
251
292
|
import json
|
|
@@ -257,7 +298,9 @@ json.dumps(data, cls=DecimalEncoder)
|
|
|
257
298
|
## Recovery Procedures
|
|
258
299
|
|
|
259
300
|
### Complete Reset
|
|
301
|
+
|
|
260
302
|
If simulator is in an inconsistent state:
|
|
303
|
+
|
|
261
304
|
```bash
|
|
262
305
|
# Clear any cached data
|
|
263
306
|
rm -rf ~/.cache/flash-simulator/
|
|
@@ -267,14 +310,16 @@ pip install --upgrade web3 httpx
|
|
|
267
310
|
```
|
|
268
311
|
|
|
269
312
|
### Verify RPC Connectivity
|
|
313
|
+
|
|
270
314
|
```bash
|
|
271
315
|
# Test RPC endpoint
|
|
272
316
|
curl -X POST -H "Content-Type: application/json" \
|
|
273
317
|
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
|
|
274
|
-
|
|
318
|
+
eth
|
|
275
319
|
```
|
|
276
320
|
|
|
277
321
|
### Test Simulation Engine
|
|
322
|
+
|
|
278
323
|
```bash
|
|
279
324
|
# Run built-in demo
|
|
280
325
|
python strategy_engine.py
|
|
@@ -14,6 +14,7 @@ python flash_simulator.py arbitrage ETH USDC 100 \
|
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
**Expected Output:**
|
|
17
|
+
|
|
17
18
|
```
|
|
18
19
|
==================== FLASH LOAN SIMULATION ====================
|
|
19
20
|
|
|
@@ -70,6 +71,7 @@ python flash_simulator.py compare ETH 100
|
|
|
70
71
|
```
|
|
71
72
|
|
|
72
73
|
**Expected Output:**
|
|
74
|
+
|
|
73
75
|
```
|
|
74
76
|
=================== PROVIDER COMPARISON ===================
|
|
75
77
|
|
|
@@ -97,6 +99,7 @@ python flash_simulator.py arbitrage ETH USDC 100 --full
|
|
|
97
99
|
```
|
|
98
100
|
|
|
99
101
|
**Expected Output:**
|
|
102
|
+
|
|
100
103
|
```
|
|
101
104
|
==================== FLASH LOAN SIMULATION ====================
|
|
102
105
|
[... strategy result ...]
|
|
@@ -174,6 +177,7 @@ python flash_simulator.py triangular ETH USDC WBTC ETH --amount 50
|
|
|
174
177
|
```
|
|
175
178
|
|
|
176
179
|
**Expected Output:**
|
|
180
|
+
|
|
177
181
|
```
|
|
178
182
|
==================== FLASH LOAN SIMULATION ====================
|
|
179
183
|
|
|
@@ -240,6 +244,7 @@ python flash_simulator.py liquidation \
|
|
|
240
244
|
```
|
|
241
245
|
|
|
242
246
|
**Expected Output:**
|
|
247
|
+
|
|
243
248
|
```
|
|
244
249
|
==================== FLASH LOAN SIMULATION ====================
|
|
245
250
|
|
|
@@ -296,6 +301,7 @@ python flash_simulator.py arbitrage ETH USDC 100 --full --output json > simulati
|
|
|
296
301
|
```
|
|
297
302
|
|
|
298
303
|
**Example JSON Output:**
|
|
304
|
+
|
|
299
305
|
```json
|
|
300
306
|
{
|
|
301
307
|
"simulation": {
|
|
@@ -369,6 +375,7 @@ python flash_simulator.py arbitrage ETH USDC 100 \
|
|
|
369
375
|
```
|
|
370
376
|
|
|
371
377
|
**Key Difference:**
|
|
378
|
+
|
|
372
379
|
- Flash loan fee: 0.00 ETH (vs 0.09 ETH with Aave)
|
|
373
380
|
- Net profit increases by ~$225
|
|
374
381
|
|
|
@@ -386,6 +393,7 @@ python flash_simulator.py arbitrage ETH USDC 100 \
|
|
|
386
393
|
```
|
|
387
394
|
|
|
388
395
|
This adjusts:
|
|
396
|
+
|
|
389
397
|
- All USD calculations use $3,500/ETH
|
|
390
398
|
- Gas costs calculated at 50 gwei
|
|
391
399
|
- Breakeven gas price recalculated
|
|
@@ -482,6 +490,7 @@ if __name__ == "__main__":
|
|
|
482
490
|
## Integration Patterns
|
|
483
491
|
|
|
484
492
|
### Batch Analysis
|
|
493
|
+
|
|
485
494
|
```bash
|
|
486
495
|
# Analyze multiple pairs
|
|
487
496
|
for pair in "ETH-USDC" "WBTC-ETH" "ETH-DAI"; do
|
|
@@ -491,6 +500,7 @@ done
|
|
|
491
500
|
```
|
|
492
501
|
|
|
493
502
|
### Pipeline Integration
|
|
503
|
+
|
|
494
504
|
```bash
|
|
495
505
|
# Feed into analysis pipeline
|
|
496
506
|
python flash_simulator.py arbitrage ETH USDC 100 --output json | \
|
|
@@ -498,6 +508,7 @@ python flash_simulator.py arbitrage ETH USDC 100 --output json | \
|
|
|
498
508
|
```
|
|
499
509
|
|
|
500
510
|
### Automated Monitoring
|
|
511
|
+
|
|
501
512
|
```bash
|
|
502
513
|
# Check profitability every minute
|
|
503
514
|
while true; do
|
|
@@ -523,6 +534,7 @@ All examples are for educational purposes only. Flash loan strategies involve si
|
|
|
523
534
|
4. **Market Risk**: Prices change between simulation and execution
|
|
524
535
|
|
|
525
536
|
Always:
|
|
537
|
+
|
|
526
538
|
- Test on testnets first
|
|
527
539
|
- Start with small amounts
|
|
528
540
|
- Use MEV protection in production
|
|
@@ -40,6 +40,7 @@ When `--risk-analysis` is enabled, four risk factors are scored 0-100:
|
|
|
40
40
|
- **Liquidity Risk** (0-100): Whether pool depth supports the trade size. Score > 80 means trade may move price significantly.
|
|
41
41
|
|
|
42
42
|
Overall viability grades:
|
|
43
|
+
|
|
43
44
|
- **A**: All risks low, high confidence
|
|
44
45
|
- **B**: Moderate risks, proceed with caution
|
|
45
46
|
- **C**: High risks, likely unprofitable
|
|
@@ -48,20 +49,25 @@ Overall viability grades:
|
|
|
48
49
|
## Output Modes
|
|
49
50
|
|
|
50
51
|
**Quick Mode** (default):
|
|
52
|
+
|
|
51
53
|
- Net profit/loss, provider recommendation, Go/No-Go verdict
|
|
52
54
|
|
|
53
55
|
**Breakdown Mode** (`--breakdown`):
|
|
56
|
+
|
|
54
57
|
- Step-by-step transaction flow, individual cost components, slippage estimates
|
|
55
58
|
|
|
56
59
|
**Comparison Mode** (`--compare-providers`):
|
|
60
|
+
|
|
57
61
|
- All providers ranked by net profit, fee differences, liquidity availability
|
|
58
62
|
|
|
59
63
|
**Risk Analysis** (`--risk-analysis`):
|
|
64
|
+
|
|
60
65
|
- Competition score, execution probability, protocol safety, overall viability grade
|
|
61
66
|
|
|
62
67
|
## Educational Disclaimer
|
|
63
68
|
|
|
64
69
|
**FOR EDUCATIONAL PURPOSES ONLY.** Flash loan strategies involve significant risks:
|
|
70
|
+
|
|
65
71
|
- Smart contract bugs can cause total loss of borrowed funds
|
|
66
72
|
- MEV bots compete for the same opportunities with faster infrastructure
|
|
67
73
|
- Gas costs can exceed profits, especially during network congestion
|
|
@@ -18,7 +18,6 @@ Usage:
|
|
|
18
18
|
import argparse
|
|
19
19
|
import sys
|
|
20
20
|
from decimal import Decimal, InvalidOperation
|
|
21
|
-
from typing import Optional
|
|
22
21
|
|
|
23
22
|
from strategy_engine import (
|
|
24
23
|
StrategyFactory,
|
|
@@ -77,77 +76,39 @@ EDUCATIONAL DISCLAIMER:
|
|
|
77
76
|
subparsers = parser.add_subparsers(dest="command", help="Simulation type")
|
|
78
77
|
|
|
79
78
|
# Arbitrage subcommand
|
|
80
|
-
arb_parser = subparsers.add_parser(
|
|
81
|
-
|
|
82
|
-
)
|
|
83
|
-
arb_parser.add_argument(
|
|
84
|
-
|
|
85
|
-
)
|
|
86
|
-
arb_parser.add_argument(
|
|
87
|
-
"output_token", help="Output token (e.g., USDC)"
|
|
88
|
-
)
|
|
89
|
-
arb_parser.add_argument(
|
|
90
|
-
"amount", type=str, help="Loan amount"
|
|
91
|
-
)
|
|
92
|
-
arb_parser.add_argument(
|
|
93
|
-
"--dex-buy", default="sushiswap", help="DEX to buy on (default: sushiswap)"
|
|
94
|
-
)
|
|
95
|
-
arb_parser.add_argument(
|
|
96
|
-
"--dex-sell", default="uniswap", help="DEX to sell on (default: uniswap)"
|
|
97
|
-
)
|
|
98
|
-
arb_parser.add_argument(
|
|
99
|
-
"--provider", default="aave", help="Flash loan provider (default: aave)"
|
|
100
|
-
)
|
|
79
|
+
arb_parser = subparsers.add_parser("arbitrage", help="Simple two-DEX arbitrage simulation")
|
|
80
|
+
arb_parser.add_argument("input_token", help="Input token (e.g., ETH)")
|
|
81
|
+
arb_parser.add_argument("output_token", help="Output token (e.g., USDC)")
|
|
82
|
+
arb_parser.add_argument("amount", type=str, help="Loan amount")
|
|
83
|
+
arb_parser.add_argument("--dex-buy", default="sushiswap", help="DEX to buy on (default: sushiswap)")
|
|
84
|
+
arb_parser.add_argument("--dex-sell", default="uniswap", help="DEX to sell on (default: uniswap)")
|
|
85
|
+
arb_parser.add_argument("--provider", default="aave", help="Flash loan provider (default: aave)")
|
|
101
86
|
|
|
102
87
|
# Triangular arbitrage subcommand
|
|
103
|
-
tri_parser = subparsers.add_parser(
|
|
104
|
-
|
|
105
|
-
)
|
|
106
|
-
tri_parser.add_argument(
|
|
107
|
-
"tokens", nargs="+", help="Token path (e.g., ETH USDC WBTC ETH)"
|
|
108
|
-
)
|
|
109
|
-
tri_parser.add_argument(
|
|
110
|
-
"--amount", type=str, required=True, help="Loan amount"
|
|
111
|
-
)
|
|
112
|
-
tri_parser.add_argument(
|
|
113
|
-
"--provider", default="aave", help="Flash loan provider (default: aave)"
|
|
114
|
-
)
|
|
88
|
+
tri_parser = subparsers.add_parser("triangular", help="Multi-hop circular arbitrage simulation")
|
|
89
|
+
tri_parser.add_argument("tokens", nargs="+", help="Token path (e.g., ETH USDC WBTC ETH)")
|
|
90
|
+
tri_parser.add_argument("--amount", type=str, required=True, help="Loan amount")
|
|
91
|
+
tri_parser.add_argument("--provider", default="aave", help="Flash loan provider (default: aave)")
|
|
115
92
|
|
|
116
93
|
# Liquidation subcommand
|
|
117
|
-
liq_parser = subparsers.add_parser(
|
|
118
|
-
|
|
119
|
-
)
|
|
120
|
-
liq_parser.add_argument(
|
|
121
|
-
"--protocol", default="aave", help="Lending protocol (default: aave)"
|
|
122
|
-
)
|
|
94
|
+
liq_parser = subparsers.add_parser("liquidation", help="Liquidation opportunity analysis")
|
|
95
|
+
liq_parser.add_argument("--protocol", default="aave", help="Lending protocol (default: aave)")
|
|
123
96
|
liq_parser.add_argument(
|
|
124
97
|
"--health-factor",
|
|
125
98
|
type=float,
|
|
126
99
|
default=0.95,
|
|
127
100
|
help="Health factor threshold (default: 0.95)",
|
|
128
101
|
)
|
|
129
|
-
liq_parser.add_argument(
|
|
130
|
-
|
|
131
|
-
)
|
|
132
|
-
liq_parser.add_argument(
|
|
133
|
-
"--debt", default="USDC", help="Debt asset (default: USDC)"
|
|
134
|
-
)
|
|
135
|
-
liq_parser.add_argument(
|
|
136
|
-
"--amount", type=str, default="10", help="Debt amount to liquidate"
|
|
137
|
-
)
|
|
138
|
-
liq_parser.add_argument(
|
|
139
|
-
"--provider", default="aave", help="Flash loan provider (default: aave)"
|
|
140
|
-
)
|
|
102
|
+
liq_parser.add_argument("--collateral", default="ETH", help="Collateral asset (default: ETH)")
|
|
103
|
+
liq_parser.add_argument("--debt", default="USDC", help="Debt asset (default: USDC)")
|
|
104
|
+
liq_parser.add_argument("--amount", type=str, default="10", help="Debt amount to liquidate")
|
|
105
|
+
liq_parser.add_argument("--provider", default="aave", help="Flash loan provider (default: aave)")
|
|
141
106
|
|
|
142
107
|
# Compare providers subcommand
|
|
143
|
-
cmp_parser = subparsers.add_parser(
|
|
144
|
-
"compare", help="Compare flash loan providers"
|
|
145
|
-
)
|
|
108
|
+
cmp_parser = subparsers.add_parser("compare", help="Compare flash loan providers")
|
|
146
109
|
cmp_parser.add_argument("asset", help="Asset to borrow (e.g., ETH)")
|
|
147
110
|
cmp_parser.add_argument("amount", type=str, help="Amount to borrow")
|
|
148
|
-
cmp_parser.add_argument(
|
|
149
|
-
"--chain", default="ethereum", help="Chain (default: ethereum)"
|
|
150
|
-
)
|
|
111
|
+
cmp_parser.add_argument("--chain", default="ethereum", help="Chain (default: ethereum)")
|
|
151
112
|
|
|
152
113
|
# Global options
|
|
153
114
|
for sub in [arb_parser, tri_parser, liq_parser]:
|
|
@@ -223,9 +184,7 @@ def run_arbitrage(args: argparse.Namespace) -> int:
|
|
|
223
184
|
providers = None
|
|
224
185
|
|
|
225
186
|
if args.full or hasattr(args, "compare_providers") and args.compare_providers:
|
|
226
|
-
calculator = ProfitCalculator(
|
|
227
|
-
eth_price_usd=args.eth_price, gas_price_gwei=args.gas_price
|
|
228
|
-
)
|
|
187
|
+
calculator = ProfitCalculator(eth_price_usd=args.eth_price, gas_price_gwei=args.gas_price)
|
|
229
188
|
breakdown = calculator.calculate_breakdown(result)
|
|
230
189
|
|
|
231
190
|
if args.full or (hasattr(args, "risk_analysis") and args.risk_analysis):
|
|
@@ -234,9 +193,7 @@ def run_arbitrage(args: argparse.Namespace) -> int:
|
|
|
234
193
|
|
|
235
194
|
if args.full or (hasattr(args, "compare_providers") and args.compare_providers):
|
|
236
195
|
manager = ProviderManager()
|
|
237
|
-
providers = manager.compare_providers(
|
|
238
|
-
args.input_token.upper(), amount, "ethereum"
|
|
239
|
-
)
|
|
196
|
+
providers = manager.compare_providers(args.input_token.upper(), amount, "ethereum")
|
|
240
197
|
|
|
241
198
|
# Format output
|
|
242
199
|
output_result(args, result, breakdown, assessment, providers)
|
|
@@ -276,18 +233,14 @@ def run_triangular(args: argparse.Namespace) -> int:
|
|
|
276
233
|
providers = None
|
|
277
234
|
|
|
278
235
|
if args.full:
|
|
279
|
-
calculator = ProfitCalculator(
|
|
280
|
-
eth_price_usd=args.eth_price, gas_price_gwei=args.gas_price
|
|
281
|
-
)
|
|
236
|
+
calculator = ProfitCalculator(eth_price_usd=args.eth_price, gas_price_gwei=args.gas_price)
|
|
282
237
|
breakdown = calculator.calculate_breakdown(result)
|
|
283
238
|
|
|
284
239
|
assessor = RiskAssessor(eth_price_usd=args.eth_price)
|
|
285
240
|
assessment = assessor.assess(result)
|
|
286
241
|
|
|
287
242
|
manager = ProviderManager()
|
|
288
|
-
providers = manager.compare_providers(
|
|
289
|
-
args.tokens[0].upper(), amount, "ethereum"
|
|
290
|
-
)
|
|
243
|
+
providers = manager.compare_providers(args.tokens[0].upper(), amount, "ethereum")
|
|
291
244
|
|
|
292
245
|
if hasattr(args, "risk_analysis") and args.risk_analysis:
|
|
293
246
|
assessor = RiskAssessor(eth_price_usd=args.eth_price)
|
|
@@ -330,18 +283,14 @@ def run_liquidation(args: argparse.Namespace) -> int:
|
|
|
330
283
|
providers = None
|
|
331
284
|
|
|
332
285
|
if args.full:
|
|
333
|
-
calculator = ProfitCalculator(
|
|
334
|
-
eth_price_usd=args.eth_price, gas_price_gwei=args.gas_price
|
|
335
|
-
)
|
|
286
|
+
calculator = ProfitCalculator(eth_price_usd=args.eth_price, gas_price_gwei=args.gas_price)
|
|
336
287
|
breakdown = calculator.calculate_breakdown(result)
|
|
337
288
|
|
|
338
289
|
assessor = RiskAssessor(eth_price_usd=args.eth_price)
|
|
339
290
|
assessment = assessor.assess(result)
|
|
340
291
|
|
|
341
292
|
manager = ProviderManager()
|
|
342
|
-
providers = manager.compare_providers(
|
|
343
|
-
args.debt.upper(), amount, "ethereum"
|
|
344
|
-
)
|
|
293
|
+
providers = manager.compare_providers(args.debt.upper(), amount, "ethereum")
|
|
345
294
|
|
|
346
295
|
if hasattr(args, "risk_analysis") and args.risk_analysis:
|
|
347
296
|
assessor = RiskAssessor(eth_price_usd=args.eth_price)
|
|
@@ -362,9 +311,7 @@ def run_compare(args: argparse.Namespace) -> int:
|
|
|
362
311
|
return 1
|
|
363
312
|
|
|
364
313
|
manager = ProviderManager()
|
|
365
|
-
providers = manager.compare_providers(
|
|
366
|
-
args.asset.upper(), amount, args.chain.lower()
|
|
367
|
-
)
|
|
314
|
+
providers = manager.compare_providers(args.asset.upper(), amount, args.chain.lower())
|
|
368
315
|
|
|
369
316
|
if not providers:
|
|
370
317
|
print(
|
|
@@ -375,7 +322,7 @@ def run_compare(args: argparse.Namespace) -> int:
|
|
|
375
322
|
|
|
376
323
|
# Format output
|
|
377
324
|
if args.output == "json":
|
|
378
|
-
|
|
325
|
+
JSONFormatter()
|
|
379
326
|
# Create a minimal result for JSON output
|
|
380
327
|
output = {
|
|
381
328
|
"comparison": {
|
|
@@ -396,6 +343,7 @@ def run_compare(args: argparse.Namespace) -> int:
|
|
|
396
343
|
],
|
|
397
344
|
}
|
|
398
345
|
import json
|
|
346
|
+
|
|
399
347
|
print(json.dumps(output, indent=2))
|
|
400
348
|
else:
|
|
401
349
|
console = ConsoleFormatter()
|
|
@@ -436,11 +384,7 @@ def output_result(
|
|
|
436
384
|
|
|
437
385
|
# Show provider comparison if calculated
|
|
438
386
|
if providers:
|
|
439
|
-
print(
|
|
440
|
-
console.format_provider_comparison(
|
|
441
|
-
providers, result.loan_asset, result.loan_amount
|
|
442
|
-
)
|
|
443
|
-
)
|
|
387
|
+
print(console.format_provider_comparison(providers, result.loan_asset, result.loan_amount))
|
|
444
388
|
|
|
445
389
|
# Always show quick summary at end
|
|
446
390
|
print(console.format_quick_summary(result, assessment))
|