🎯 Initial commit: Uniswap Auto CLP trading system

Core Components:
- uniswap_manager.py: V3 concentrated liquidity position manager
- clp_hedger.py: Hyperliquid perpetuals hedging bot
- requirements.txt: Python dependencies
- .gitignore: Security exclusions for sensitive data
- doc/: Project documentation
- tools/: Utility scripts and Git agent

Features:
- Automated liquidity provision on Uniswap V3 (WETH/USDC)
- Delta-neutral hedging using Hyperliquid perpetuals
- Position lifecycle management (open/close/rebalance)
- Automated backup and version control system

Security:
- Private keys and tokens excluded from version control
- Environment variables properly handled
- Automated security validation for backups

Git Agent:
- Hourly automated backups to separate branches
- Keep last 100 backups (~4 days coverage)
- Detailed change tracking and parameter monitoring
- Push to Gitea server automatically
- Manual main branch control preserved
- No performance tracking for privacy
- No notifications for simplicity

Files Added:
- git_agent.py: Main automation script
- agent_config.json: Configuration with Gitea settings
- git_utils.py: Git operations wrapper
- backup_manager.py: Backup branch management
- change_detector.py: File change analysis
- cleanup_manager.py: 100-backup rotation
- commit_formatter.py: Detailed commit messages
- README_GIT_AGENT.md: Complete usage documentation
This commit is contained in:
2025-12-19 20:30:48 +01:00
commit 5ca16ec33f
18 changed files with 4207 additions and 0 deletions

View File

@ -0,0 +1,108 @@
# Low Latency Optimization Plan: Memory Sharing Integration
## Overview
Currently, the system consists of two separate processes (`uniswap_manager_refactored.py` and `clp_hedger.py`) communicating via a file (`hedge_status.json`). This introduces inevitable latency due to:
1. **Polling Intervals:** The hedger must "sleep" and "wake up" to check the file.
2. **File I/O:** Reading/writing to disk is thousands of times slower than memory operations.
3. **Synchronization:** Potential race conditions if both try to access the file simultaneously.
## Goal
Eliminate file reliance to achieve **sub-millisecond** reaction times between "Uniswap Position Out of Range" detection and "Hedge Close" execution.
## Proposed Architecture: Unified Multi-Threaded Bot
Instead of two independent scripts, we will merge them into a single Python application running two concurrent threads that share a common data object in memory.
### Key Components
1. **`SharedState` Class (The Brain)**
* A thread-safe data structure (using `threading.Lock`) that holds the current position status, price, and range.
* **Events:** Uses `threading.Event` (e.g., `close_signal`) to allow the Manager to *instantly* wake up the Hedger without waiting for a sleep cycle to finish.
2. **`UniswapManager` Thread**
* **Role:** Monitors on-chain data (RPC).
* **Action:** When it detects "Out of Range", it updates `SharedState` and sets `close_signal.set()`.
3. **`ClpHedger` Thread**
* **Role:** Manages the Hyperliquid hedge.
* **Action:** Instead of `time.sleep(1)`, it waits on `close_signal.wait(timeout=1)`.
* **Reaction:** If `close_signal` is triggered, it executes the close logic **immediately** (0 latency).
4. **`main_bot.py` (The Entry Point)**
* Initializes `SharedState`.
* Starts `UniswapManager` and `ClpHedger` as threads.
* Handles centralized logging and clean shutdown.
## Implementation Steps
### Step 1: Create `SharedState`
Define a class that replaces the JSON file structure.
```python
class SharedState:
def __init__(self):
self.lock = threading.Lock()
self.close_event = threading.Event()
self.position_data = {} # Stores the dict formerly in JSON
def update_position(self, data):
with self.lock:
self.position_data.update(data)
def get_position(self):
with self.lock:
return self.position_data.copy()
def trigger_emergency_close(self):
self.close_event.set()
```
### Step 2: Refactor `uniswap_manager_refactored.py`
* Convert the script into a class `UniswapManager`.
* Replace all `load_status_data()` and `save_status_data()` calls with `self.shared_state.update_position(...)`.
* When "Out of Range" is detected:
```python
# Old
update_position_status(token_id, "CLOSING")
# New
self.shared_state.update_position({'status': 'CLOSING'})
self.shared_state.trigger_emergency_close() # Wakes up Hedger instantly
```
### Step 3: Refactor `clp_hedger.py`
* Convert the script into a class `ClpHedger`.
* Replace file reading logic with `self.shared_state.get_position()`.
* Update the main loop to handle the event:
```python
# Old
time.sleep(CHECK_INTERVAL)
# New
# Wait for 1 second OR immediate signal
if self.shared_state.close_event.wait(timeout=1.0):
self.close_all_positions()
self.shared_state.close_event.clear()
```
### Step 4: Create `main_bot.py`
```python
if __name__ == "__main__":
state = SharedState()
manager = UniswapManager(state)
hedger = ClpHedger(state)
t1 = threading.Thread(target=manager.run)
t2 = threading.Thread(target=hedger.run)
t1.start()
t2.start()
t1.join()
t2.join()
```
## Benefits
1. **Zero Latency:** The moment the Manager sets the event, the Hedger reacts. No polling delay.
2. **Reliability:** No file corruption risks (like the JSON error experienced earlier).
3. **Efficiency:** Reduces disk I/O, extending SD card/drive life and reducing CPU usage.

View File

@ -0,0 +1,139 @@
# Python Blockchain Development & Review Guidelines
## Overview
This document outlines the standards for writing, reviewing, and deploying Python scripts that interact with EVM-based blockchains (Ethereum, Arbitrum, etc.). These guidelines prioritize **capital preservation**, **transaction robustness**, and **system stability**.
---
## 1. Transaction Handling & Lifecycle
*High-reliability transaction management is the core of a production bot. Never "fire and forget."*
### 1.1. Timeout & Receipt Management
- **Requirement:** Never send a transaction without immediately waiting for its receipt or tracking its hash.
- **Why:** The RPC might accept the tx, but it could be dropped from the mempool or stuck indefinitely.
- **Code Standard:**
```python
# BAD
w3.eth.send_raw_transaction(signed_txn.rawTransaction)
# GOOD
tx_hash = w3.eth.send_raw_transaction(signed_txn.rawTransaction)
try:
receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=120)
except TimeExhausted:
# Handle stuck transaction (bump gas or cancel)
handle_stuck_transaction(tx_hash)
```
### 1.2. Verification of Success
- **Requirement:** Explicitly check `receipt.status == 1`.
- **Why:** A transaction can be mined (success=True) but execution can revert (status=0).
- **Code Standard:**
```python
if receipt.status != 1:
raise TransactionRevertedError(f"Tx {tx_hash.hex()} reverted on-chain")
```
### 1.3. Gas Management & Stuck Transactions
- **Requirement:** Do not hardcode gas prices. Use dynamic estimation.
- **Mechanism:**
- For EIP-1559 chains (Arbitrum/Base/Mainnet), use `maxFeePerGas` and `maxPriorityFeePerGas`.
- Implement a "Gas Bumping" mechanism: If a tx is not mined in $X$ seconds, resubmit with 10-20% higher gas using the **same nonce**.
### 1.4. Nonce Management
- **Requirement:** In high-frequency loops, track the nonce locally.
- **Why:** `w3.eth.get_transaction_count(addr, 'pending')` is often slow or eventually consistent on some RPCs, leading to "Nonce too low" or "Replacement transaction underpriced" errors.
---
## 2. Financial Logic & Precision
### 2.1. No Floating Point Math for Token Amounts
- **Requirement:** NEVER use standard python `float` for calculating token amounts or prices involved in protocol interactions.
- **Standard:** Use `decimal.Decimal` or integer math (Wei).
- **Why:** `0.1 + 0.2 != 0.3` in floating point. This causes dust errors and "Insufficient Balance" reverts.
```python
# BAD
amount = balance * 0.5
# GOOD
amount = int(Decimal(balance) * Decimal("0.5"))
```
### 2.2. Slippage Protection
- **Requirement:** Never use `0` for `amountOutMinimum` or `sqrtPriceLimitX96` in production.
- **Standard:** Calculate expected output and apply a config-defined slippage (e.g., 0.1%).
- **Why:** Front-running and sandwich attacks will drain value from `amountOutMin: 0` trades.
### 2.3. Approval Handling
- **Requirement:** Check allowance before approving.
- **Standard:**
- Verify `allowance >= amount`.
- If `allowance == 0`, approve.
- **Note:** Some tokens (USDT) require approving `0` before approving a new amount if an allowance already exists.
---
## 3. Security & Safety
### 3.1. Secrets Management
- **Requirement:** No private keys or mnemonics in source code.
- **Standard:** Use `.env` files (loaded via `python-dotenv`) or proper secrets managers.
- **Review Check:** `grep -r "0x..." .` to ensure no keys were accidentally committed.
### 3.2. Address Validation
- **Requirement:** All addresses must be checksummed before use.
- **Standard:**
```python
# Input
target_address = "0xc364..."
# Validation
if not Web3.is_address(target_address):
raise ValueError("Invalid address")
checksum_address = Web3.to_checksum_address(target_address)
```
### 3.3. Simulation (Dry Run)
- **Requirement:** For complex logic (like batch swaps), use `contract.functions.method().call()` before `.build_transaction()`.
- **Why:** If the `.call()` fails (reverts), the transaction will definitely fail. Save gas by catching logic errors off-chain.
---
## 4. Coding Style & Observability
### 4.1. Logging
- **Requirement:** No `print()` statements. Use `logging` module.
- **Standard:**
- `INFO`: High-level state changes (e.g., "Position Opened").
- `DEBUG`: API responses, specific calc steps.
- `ERROR`: Stack traces and critical failures.
- **Traceability:** Log the Transaction Hash **immediately** upon sending, not after waiting. If the script crashes while waiting, you need the hash to check the chain manually.
### 4.2. Idempotency & State Recovery
- **Requirement:** Scripts must be restartable without double-spending.
- **Standard:** Before submitting a "Open Position" transaction, read the chain (or `hedge_status.json`) to ensure a position isn't already open.
### 4.3. Type Hinting
- **Requirement:** Use Python type hints for clarity.
- **Standard:**
```python
def execute_swap(
token_in: str,
amount: int,
slippage_pct: float = 0.5
) -> str: # Returns tx_hash
```
---
## 5. Review Checklist (Copy-Paste for PRs)
- [ ] **Secrets:** No private keys in code?
- [ ] **Math:** Is `Decimal` or Integer math used for all financial calcs?
- [ ] **Slippage:** Is `amountOutMinimum` > 0?
- [ ] **Timeouts:** Does `wait_for_transaction_receipt` have a timeout?
- [ ] **Status Check:** Is `receipt.status` checked for success/revert?
- [ ] **Gas:** Are gas limits and prices dynamic/reasonable?
- [ ] **Addresses:** Are all addresses Checksummed?
- [ ] **Restartability:** What happens if the script dies halfway through?

View File

@ -0,0 +1,71 @@
# Uniswap Manager Workflow Documentation
This document describes the operational logic of the `uniswap_manager_refactored.py` script, specifically focusing on how it handles position lifecycle events.
## 1. Out of Range Workflow (Position Closing)
When the script detects that an active Concentrated Liquidity Position (CLP) has moved out of its defined tick range, the following sequence occurs:
1. **Detection (Monitoring Loop):**
* The `main` loop runs every `MONITOR_INTERVAL_SECONDS` (default: 60s).
* It retrieves the active position's `tickLower` and `tickUpper` from on-chain data.
* It fetches the current pool `tick`.
* It determines if the position is out of range (`current_tick < tickLower` or `current_tick >= tickUpper`).
2. **Logging:**
* A warning is logged to both console and file: `🛑 Closing Position {token_id} (Out of Range)`.
3. **Status Update -> "CLOSING":**
* The `hedge_status.json` file is updated to mark the position status as `"CLOSING"`.
* **Purpose:** This signals external Hedger bots (watching this file) to halt hedging operations or close their hedges immediately.
4. **Liquidity Removal:**
* The script executes a `decreaseLiquidity` transaction on the `NonfungiblePositionManager` contract.
* It removes 100% of the liquidity, converting the position back into the underlying tokens (WETH and USDC) in the wallet.
5. **Fee Collection:**
* Immediately following liquidity removal, a `collect` transaction is sent to claim all accrued trading fees.
6. **Status Update -> "CLOSED":**
* Upon successful confirmation of the transactions, `hedge_status.json` is updated to status `"CLOSED"`.
* A `timestamp_close` is recorded.
7. **Rebalancing (Optional/Configuration Dependent):**
* The script checks the `REBALANCE_ON_CLOSE_BELOW_RANGE` flag.
* **Scenario:** If the price fell **BELOW** the range, the position is 100% WETH.
* **Action:** If implemented, the script may perform a swap (e.g., selling 50% of the WETH for USDC) to rebalance the portfolio before opening a new position.
* *Current State:* The logic identifies this condition but requires the specific swap logic implementation (currently a `pass` placeholder in the refactored script).
8. **Cycle Reset:**
* The script returns to the monitoring loop.
* In the next cycle, detecting no "OPEN" position, it will evaluate `OPEN_POSITION_ENABLED` to potentially calculate and mint a **new** position centered on the current market price.
## 2. New Position Creation (Opening)
When no active position exists and `OPEN_POSITION_ENABLED` is `True`:
1. **Market Analysis:**
* Fetches current pool price and tick.
* Calculates a new range (default: +/- 2.5%) centered on the current tick.
2. **Investment Calculation:**
* Uses `TARGET_INVESTMENT_VALUE_USDC` (default: $200).
* If set to `"MAX"`, it calculates the maximum affordable position based on wallet balances minus a safety buffer.
* Calculates the precise amount of Token0 and Token1 required for the target value at the current price and range.
3. **Preparation (Swap & Approve):**
* Checks wallet balances.
* **Auto-Wrap:** Wraps ETH to WETH if necessary.
* **Auto-Swap:** Swaps surplus tokens (e.g., excess USDC for WETH) to match the required ratio for the new position.
* **Approvals:** Checks and sends `approve` transactions for the Position Manager if allowances are insufficient.
4. **Minting:**
* Sends the `mint` transaction to create the new NFT position.
* Applies a slippage tolerance (default: 0.5%) to `amountMin` parameters.
5. **Status Recording:**
* On success, updates `hedge_status.json` with the new position details (Token ID, Range, Entry Price, Initial Amounts).
* Sets status to `"OPEN"`.
---
*Last Updated: December 19, 2025*