agentic-aqua 0.3.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.
- agentic_aqua-0.3.0/.cursorrules +1 -0
- agentic_aqua-0.3.0/.github/workflows/publish.yml +32 -0
- agentic_aqua-0.3.0/.gitignore +68 -0
- agentic_aqua-0.3.0/AGENTS.md +444 -0
- agentic_aqua-0.3.0/LICENSE +21 -0
- agentic_aqua-0.3.0/PKG-INFO +327 -0
- agentic_aqua-0.3.0/PUBLISHING.md +114 -0
- agentic_aqua-0.3.0/README.md +295 -0
- agentic_aqua-0.3.0/claude.md +1 -0
- agentic_aqua-0.3.0/prompt_test_read_only.md +183 -0
- agentic_aqua-0.3.0/prompt_test_send_real_btc.md +107 -0
- agentic_aqua-0.3.0/prompt_test_send_real_lbtc.md +91 -0
- agentic_aqua-0.3.0/pyproject.toml +68 -0
- agentic_aqua-0.3.0/scripts/cli_smoke_send_btc.py +157 -0
- agentic_aqua-0.3.0/scripts/cli_smoke_send_lbtc.py +209 -0
- agentic_aqua-0.3.0/scripts/publish.sh +54 -0
- agentic_aqua-0.3.0/src/aqua/__init__.py +3 -0
- agentic_aqua-0.3.0/src/aqua/ankara.py +90 -0
- agentic_aqua-0.3.0/src/aqua/assets.py +92 -0
- agentic_aqua-0.3.0/src/aqua/bitcoin.py +387 -0
- agentic_aqua-0.3.0/src/aqua/boltz.py +165 -0
- agentic_aqua-0.3.0/src/aqua/cli/__init__.py +5 -0
- agentic_aqua-0.3.0/src/aqua/cli/btc.py +81 -0
- agentic_aqua-0.3.0/src/aqua/cli/commands.py +30 -0
- agentic_aqua-0.3.0/src/aqua/cli/lightning.py +87 -0
- agentic_aqua-0.3.0/src/aqua/cli/liquid.py +201 -0
- agentic_aqua-0.3.0/src/aqua/cli/main.py +45 -0
- agentic_aqua-0.3.0/src/aqua/cli/output.py +68 -0
- agentic_aqua-0.3.0/src/aqua/cli/password.py +49 -0
- agentic_aqua-0.3.0/src/aqua/cli/serve.py +13 -0
- agentic_aqua-0.3.0/src/aqua/cli/wallet.py +150 -0
- agentic_aqua-0.3.0/src/aqua/lightning.py +387 -0
- agentic_aqua-0.3.0/src/aqua/server.py +1175 -0
- agentic_aqua-0.3.0/src/aqua/storage.py +342 -0
- agentic_aqua-0.3.0/src/aqua/tools.py +740 -0
- agentic_aqua-0.3.0/src/aqua/wallet.py +362 -0
- agentic_aqua-0.3.0/tests/__init__.py +1 -0
- agentic_aqua-0.3.0/tests/conftest.py +9 -0
- agentic_aqua-0.3.0/tests/smoke/__init__.py +0 -0
- agentic_aqua-0.3.0/tests/smoke/test_cli_read_only.py +254 -0
- agentic_aqua-0.3.0/tests/test_ankara.py +281 -0
- agentic_aqua-0.3.0/tests/test_assets.py +60 -0
- agentic_aqua-0.3.0/tests/test_bitcoin.py +272 -0
- agentic_aqua-0.3.0/tests/test_boltz.py +312 -0
- agentic_aqua-0.3.0/tests/test_cli.py +681 -0
- agentic_aqua-0.3.0/tests/test_lightning.py +942 -0
- agentic_aqua-0.3.0/tests/test_server.py +74 -0
- agentic_aqua-0.3.0/tests/test_storage.py +394 -0
- agentic_aqua-0.3.0/tests/test_tools.py +784 -0
- agentic_aqua-0.3.0/uv.lock +874 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
AGENTS.md
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
permissions:
|
|
11
|
+
id-token: write # For trusted publishing
|
|
12
|
+
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- name: Install uv
|
|
17
|
+
uses: astral-sh/setup-uv@v4
|
|
18
|
+
with:
|
|
19
|
+
version: "latest"
|
|
20
|
+
|
|
21
|
+
- name: Set up Python
|
|
22
|
+
uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.12"
|
|
25
|
+
|
|
26
|
+
- name: Build package
|
|
27
|
+
run: uv build
|
|
28
|
+
|
|
29
|
+
- name: Publish to PyPI
|
|
30
|
+
run: uv publish
|
|
31
|
+
env:
|
|
32
|
+
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
|
|
23
|
+
# Virtual environments
|
|
24
|
+
venv/
|
|
25
|
+
ENV/
|
|
26
|
+
env/
|
|
27
|
+
.venv/
|
|
28
|
+
|
|
29
|
+
# IDE
|
|
30
|
+
.idea/
|
|
31
|
+
.vscode/
|
|
32
|
+
*.swp
|
|
33
|
+
*.swo
|
|
34
|
+
*~
|
|
35
|
+
|
|
36
|
+
# Testing
|
|
37
|
+
.pytest_cache/
|
|
38
|
+
.coverage
|
|
39
|
+
htmlcov/
|
|
40
|
+
.tox/
|
|
41
|
+
.nox/
|
|
42
|
+
|
|
43
|
+
# Type checking
|
|
44
|
+
.mypy_cache/
|
|
45
|
+
|
|
46
|
+
# Build
|
|
47
|
+
*.manifest
|
|
48
|
+
*.spec
|
|
49
|
+
|
|
50
|
+
# Local config
|
|
51
|
+
.env
|
|
52
|
+
.env.local
|
|
53
|
+
|
|
54
|
+
# Wallet data (never commit!)
|
|
55
|
+
.liquid-wallet/ # Legacy, will be removed
|
|
56
|
+
.aqua-mcp/ # Legacy, replaced by .aqua/
|
|
57
|
+
.aqua/
|
|
58
|
+
|
|
59
|
+
# AI
|
|
60
|
+
.claude/
|
|
61
|
+
.cursor/
|
|
62
|
+
.aider/
|
|
63
|
+
.tldr/
|
|
64
|
+
.tldrignore
|
|
65
|
+
.mcp.json
|
|
66
|
+
specs/
|
|
67
|
+
.omc/
|
|
68
|
+
.omx/
|
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
# Agentic AQUA - Specification
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
MCP (Model Context Protocol) server for interacting with the **Liquid Network** and **Bitcoin**. Enables AI assistants to manage Liquid and Bitcoin wallets through AQUA. One mnemonic can back both networks (unified wallet).
|
|
6
|
+
|
|
7
|
+
Built on **LWK (Liquid Wallet Kit)** Python bindings from Blockstream and **BDK (Bitcoin Development Kit)** Python bindings for Bitcoin.
|
|
8
|
+
|
|
9
|
+
## Architecture
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
AI Assistant ←→ MCP Server (Python) ←→ LWK (Liquid) ──→ Electrum/Esplora (Blockstream)
|
|
13
|
+
│
|
|
14
|
+
└──→ BDK (Bitcoin) ──→ Esplora (Blockstream)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
No local server required. Liquid uses Electrum/Esplora; Bitcoin uses Esplora only. All via Blockstream's public infrastructure.
|
|
18
|
+
|
|
19
|
+
## Tools (20 total)
|
|
20
|
+
|
|
21
|
+
Liquid tools use the `lw_` prefix; Bitcoin tools use the `btc_` prefix; unified tools are `unified_*`; Lightning tools are `lightning_*`.
|
|
22
|
+
|
|
23
|
+
### Wallet Management
|
|
24
|
+
|
|
25
|
+
| Tool | Description | Parameters |
|
|
26
|
+
|------|-------------|------------|
|
|
27
|
+
| `lw_generate_mnemonic` | Generate a new BIP39 mnemonic | (default: 12 words) |
|
|
28
|
+
| `lw_import_mnemonic` | Import wallet from mnemonic; also creates Bitcoin wallet from same mnemonic (unified) | `mnemonic`: string, `wallet_name`: optional, `network`: mainnet/testnet, `password`: optional |
|
|
29
|
+
| `lw_export_descriptor` | Export CT descriptor (watch-only) | `wallet_name`: optional |
|
|
30
|
+
| `lw_import_descriptor` | Import watch-only wallet from CT descriptor | `descriptor`: string, `wallet_name`: string, `network`: optional |
|
|
31
|
+
| `lw_list_wallets` | List all wallets | (none) |
|
|
32
|
+
| `delete_wallet` | Delete a wallet and all its cached data. Agent MUST check balances and confirm with user before calling. Use the `delete_wallet` prompt for the safe workflow. | `wallet_name`: string |
|
|
33
|
+
|
|
34
|
+
### Wallet Operations (Liquid)
|
|
35
|
+
|
|
36
|
+
| Tool | Description | Parameters |
|
|
37
|
+
|------|-------------|------------|
|
|
38
|
+
| `lw_balance` | Get wallet balance (all assets) | `wallet_name`: optional |
|
|
39
|
+
| `lw_address` | Generate new receive address | `wallet_name`: optional, `index`: optional |
|
|
40
|
+
| `lw_transactions` | List transaction history | `wallet_name`: optional, `limit`: optional (default: 10) |
|
|
41
|
+
|
|
42
|
+
### Transactions (Liquid)
|
|
43
|
+
|
|
44
|
+
| Tool | Description | Parameters |
|
|
45
|
+
|------|-------------|------------|
|
|
46
|
+
| `lw_send` | Create, sign and broadcast L-BTC transaction | `wallet_name`, `address`, `amount` (sats), `password`: optional |
|
|
47
|
+
| `lw_send_asset` | Send a specific Liquid asset | `wallet_name`, `address`, `amount` (sats), `asset_id`, `password`: optional |
|
|
48
|
+
| `lw_tx_status` | Get transaction status (txid or Blockstream URL) | `tx`: string (64-char hex txid or blockstream.info URL) |
|
|
49
|
+
|
|
50
|
+
### Bitcoin (btc_*)
|
|
51
|
+
|
|
52
|
+
| Tool | Description | Parameters |
|
|
53
|
+
|------|-------------|------------|
|
|
54
|
+
| `btc_balance` | Get Bitcoin wallet balance in satoshis | `wallet_name`: optional |
|
|
55
|
+
| `btc_address` | Generate Bitcoin receive address (bc1...) | `wallet_name`: optional, `index`: optional |
|
|
56
|
+
| `btc_transactions` | List Bitcoin transaction history | `wallet_name`: optional, `limit`: optional (default: 10) |
|
|
57
|
+
| `btc_send` | Send BTC to an address | `wallet_name`, `address`, `amount` (sats), `fee_rate`: optional (sat/vB), `password`: optional |
|
|
58
|
+
|
|
59
|
+
### Unified
|
|
60
|
+
|
|
61
|
+
| Tool | Description | Parameters |
|
|
62
|
+
|------|-------------|------------|
|
|
63
|
+
| `unified_balance` | Get balance for both Bitcoin and Liquid | `wallet_name`: optional |
|
|
64
|
+
|
|
65
|
+
### Lightning (Unified Interface)
|
|
66
|
+
|
|
67
|
+
| Tool | Description | Parameters |
|
|
68
|
+
|------|-------------|------------|
|
|
69
|
+
| `lightning_receive` | Generate a Lightning invoice to receive L-BTC into Liquid wallet (~1-2 min after payment). Limits: 100 – 25,000,000 sats | `amount`: int (sats), `wallet_name`: optional (default: "default"), `password`: optional |
|
|
70
|
+
| `lightning_send` | Pay a Lightning invoice using L-BTC via Boltz submarine swap. Fees: ~0.1% + miner fees. Limits: 100 – 25,000,000 sats | `invoice`: BOLT11 string (lnbc... or lntb...), `wallet_name`: optional, `password`: optional |
|
|
71
|
+
| `lightning_transaction_status` | Check status of a Lightning swap (send or receive). For receive: auto-claims L-BTC when settled. For send: retrieves preimage when claimed. | `swap_id`: string |
|
|
72
|
+
|
|
73
|
+
## Resources (3 total)
|
|
74
|
+
|
|
75
|
+
MCP resources provide static documentation to AI assistants.
|
|
76
|
+
|
|
77
|
+
| URI | Name | Description |
|
|
78
|
+
|-----|------|-------------|
|
|
79
|
+
| `aqua://docs/quickstart` | Quick Start Guide | Creating wallets, checking balance, receiving/sending funds |
|
|
80
|
+
| `aqua://docs/networks` | Network Reference | Bitcoin and Liquid network details, address formats, explorers, common assets |
|
|
81
|
+
| `aqua://docs/security` | Security Best Practices | Password usage, at-rest encryption, backup, watch-only wallets, recovery |
|
|
82
|
+
|
|
83
|
+
## Prompts (14 total)
|
|
84
|
+
|
|
85
|
+
MCP prompts provide pre-built conversation starters for common workflows.
|
|
86
|
+
|
|
87
|
+
| Prompt | Description | Arguments |
|
|
88
|
+
|--------|-------------|-----------|
|
|
89
|
+
| `create_new_wallet` | Create a new wallet with mnemonic and optional at-rest password | `wallet_name`: optional, `network`: optional |
|
|
90
|
+
| `import_seed` | Import an existing wallet from a mnemonic | `wallet_name`: optional |
|
|
91
|
+
| `show_balance` | Show wallet balance (both networks by default) | `wallet_name`: optional |
|
|
92
|
+
| `bitcoin_balance` | Show only Bitcoin balance | `wallet_name`: optional |
|
|
93
|
+
| `liquid_balance` | Show only Liquid balance (all assets) | `wallet_name`: optional |
|
|
94
|
+
| `generate_address` | Generate an address to receive funds | `network`: required (bitcoin/liquid), `wallet_name`: optional |
|
|
95
|
+
| `show_transactions` | View transaction history | `network`: optional (bitcoin/liquid), `wallet_name`: optional |
|
|
96
|
+
| `send_bitcoin` | Send Bitcoin to an address | `wallet_name`: optional |
|
|
97
|
+
| `send_liquid` | Send L-BTC or other Liquid asset | `wallet_name`: optional |
|
|
98
|
+
| `transaction_status` | Check transaction status | `network`: optional (bitcoin/liquid) |
|
|
99
|
+
| `list_wallets` | Show all wallets | (none) |
|
|
100
|
+
| `export_descriptor` | Export descriptor for watch-only wallet | `wallet_name`: optional |
|
|
101
|
+
| `delete_wallet` | Safely delete a wallet with balance check and seed backup reminder | `wallet_name`: required |
|
|
102
|
+
| `pay_lightning` | Pay a Lightning invoice using Liquid Bitcoin | `wallet_name`: optional |
|
|
103
|
+
|
|
104
|
+
## Data Storage
|
|
105
|
+
|
|
106
|
+
Wallet data stored in `~/.aqua/`:
|
|
107
|
+
```
|
|
108
|
+
~/.aqua/
|
|
109
|
+
├── config.json # Network settings, defaults
|
|
110
|
+
├── wallets/
|
|
111
|
+
│ ├── default.json # Encrypted wallet data
|
|
112
|
+
│ └── work.json
|
|
113
|
+
├── swaps/ # Boltz submarine swap data (for refund recovery)
|
|
114
|
+
│ └── {swap_id}.json # Contains swap details + refund private key
|
|
115
|
+
├── ankara_swaps/ # Ankara Lightning receive swap data (legacy)
|
|
116
|
+
│ └── {swap_id}.json # Contains swap details + preimage when settled
|
|
117
|
+
├── lightning_swaps/ # Unified Lightning swap data (send & receive)
|
|
118
|
+
│ └── {swap_id}.json # Contains swap details + status + optional preimage
|
|
119
|
+
└── cache/
|
|
120
|
+
└── <wallet_name>/
|
|
121
|
+
└── btc/
|
|
122
|
+
└── bdk.sqlite # BDK persistence (Bitcoin)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Wallet File Structure
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"name": "default",
|
|
130
|
+
"network": "mainnet",
|
|
131
|
+
"descriptor": "ct(slip77(...),elwpkh(...))",
|
|
132
|
+
"btc_descriptor": "wpkh([...]/0/*)#...",
|
|
133
|
+
"btc_change_descriptor": "wpkh([...]/1/*)#...",
|
|
134
|
+
"encrypted_mnemonic": "...",
|
|
135
|
+
"watch_only": false,
|
|
136
|
+
"created_at": "2026-02-20T12:00:00Z"
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
`btc_descriptor` and `btc_change_descriptor` (BIP84) are set when the wallet is imported from mnemonic (unified wallet). Omitted for watch-only or descriptor-only imports.
|
|
141
|
+
|
|
142
|
+
### Swap File Structure (Boltz)
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"swap_id": "abc123",
|
|
147
|
+
"address": "lq1...",
|
|
148
|
+
"expected_amount": 50069,
|
|
149
|
+
"claim_public_key": "03...",
|
|
150
|
+
"swap_tree": {...},
|
|
151
|
+
"timeout_block_height": 2500000,
|
|
152
|
+
"refund_private_key": "...",
|
|
153
|
+
"refund_public_key": "...",
|
|
154
|
+
"invoice": "lnbc...",
|
|
155
|
+
"status": "transaction.claimed",
|
|
156
|
+
"network": "mainnet",
|
|
157
|
+
"created_at": "2026-03-06T12:00:00Z",
|
|
158
|
+
"lockup_txid": "...",
|
|
159
|
+
"preimage": "...",
|
|
160
|
+
"claim_txid": "..."
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
File permissions: `0o600` (contains private refund key for recovery).
|
|
165
|
+
|
|
166
|
+
### Ankara Swap File Structure
|
|
167
|
+
|
|
168
|
+
```json
|
|
169
|
+
{
|
|
170
|
+
"swap_id": "ankara_uuid_123",
|
|
171
|
+
"boltz_swap_id": "boltz_abc_456",
|
|
172
|
+
"invoice": "lnbc...",
|
|
173
|
+
"address": "lq1...",
|
|
174
|
+
"amount": 100000,
|
|
175
|
+
"wallet_name": "default",
|
|
176
|
+
"status": "pending",
|
|
177
|
+
"created_at": "2026-03-12T12:00:00Z",
|
|
178
|
+
"preimage": null
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
File permissions: `0o600`. Status progresses: `pending` → `claimed` → `settled`. Preimage populated when settled.
|
|
183
|
+
|
|
184
|
+
### Lightning Swap File Structure (Unified)
|
|
185
|
+
|
|
186
|
+
Unified Lightning swap storage for both send (Boltz) and receive (Ankara) operations:
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
{
|
|
190
|
+
"swap_id": "ankara_uuid_123",
|
|
191
|
+
"swap_type": "receive",
|
|
192
|
+
"provider": "ankara",
|
|
193
|
+
"invoice": "lnbc...",
|
|
194
|
+
"amount": 100000,
|
|
195
|
+
"wallet_name": "default",
|
|
196
|
+
"status": "pending",
|
|
197
|
+
"network": "mainnet",
|
|
198
|
+
"created_at": "2026-03-12T12:00:00Z",
|
|
199
|
+
"receive_address": "lq1...",
|
|
200
|
+
"preimage": null
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Or for send swaps (Boltz):
|
|
205
|
+
|
|
206
|
+
```json
|
|
207
|
+
{
|
|
208
|
+
"swap_id": "boltz_swap_456",
|
|
209
|
+
"swap_type": "send",
|
|
210
|
+
"provider": "boltz",
|
|
211
|
+
"invoice": "lnbc...",
|
|
212
|
+
"amount": 50069,
|
|
213
|
+
"wallet_name": "default",
|
|
214
|
+
"status": "processing",
|
|
215
|
+
"network": "mainnet",
|
|
216
|
+
"created_at": "2026-03-12T12:00:00Z",
|
|
217
|
+
"lockup_txid": "abc123...",
|
|
218
|
+
"timeout_block_height": 2500000,
|
|
219
|
+
"refund_private_key": "..."
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
File permissions: `0o600`. Status values: `pending` | `processing` | `completed` | `failed`. The `lightning_transaction_status` tool auto-claims settled receive swaps.
|
|
224
|
+
|
|
225
|
+
### Config Structure
|
|
226
|
+
|
|
227
|
+
```json
|
|
228
|
+
{
|
|
229
|
+
"network": "mainnet",
|
|
230
|
+
"default_wallet": "default",
|
|
231
|
+
"electrum_url": null,
|
|
232
|
+
"auto_sync": true
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Security Considerations
|
|
237
|
+
|
|
238
|
+
1. **Mnemonic Storage**: When a password is provided, it encrypts the mnemonic at rest (PBKDF2 480k iterations + Fernet). Without password, the mnemonic is stored as base64 (not encrypted). NOTE: this password is NOT a BIP39 passphrase — derived keys depend solely on the mnemonic, so the same mnemonic restores identical descriptors in any BIP39-compliant wallet.
|
|
239
|
+
2. **Watch-Only Mode**: Supports CT descriptors for balance checking without signing capability
|
|
240
|
+
3. **No Server**: All operations are local + public Electrum/Esplora servers
|
|
241
|
+
4. **Network Isolation**: Mainnet/testnet wallets are kept separate
|
|
242
|
+
5. **File Permissions**: Wallet directory created with `0o700`, files with `0o600`
|
|
243
|
+
6. **Atomic Writes**: Wallet files written via temp files to prevent corruption
|
|
244
|
+
|
|
245
|
+
## Networks
|
|
246
|
+
|
|
247
|
+
**Liquid**
|
|
248
|
+
|
|
249
|
+
| Network | Electrum Server | Esplora |
|
|
250
|
+
|---------|-----------------|---------|
|
|
251
|
+
| Mainnet | `blockstream.info:995` | `https://blockstream.info/liquid/api` |
|
|
252
|
+
| Testnet | `blockstream.info:465` | `https://blockstream.info/liquidtestnet/api` |
|
|
253
|
+
|
|
254
|
+
**Bitcoin**
|
|
255
|
+
|
|
256
|
+
| Network | Esplora |
|
|
257
|
+
|---------|---------|
|
|
258
|
+
| Mainnet | `https://blockstream.info/api` |
|
|
259
|
+
| Testnet | `https://blockstream.info/testnet/api` |
|
|
260
|
+
|
|
261
|
+
## Dependencies
|
|
262
|
+
|
|
263
|
+
- `lwk` - Liquid Wallet Kit Python bindings
|
|
264
|
+
- `bdkpython` - Bitcoin Development Kit Python bindings (>=2.2.0)
|
|
265
|
+
- `mcp` - Model Context Protocol SDK
|
|
266
|
+
- `cryptography` - For mnemonic encryption (PBKDF2 + Fernet)
|
|
267
|
+
- `coincurve` - secp256k1 for Boltz swap keypair generation
|
|
268
|
+
|
|
269
|
+
## Ankara Integration
|
|
270
|
+
|
|
271
|
+
Ankara backend (`test.aquabtc.com`) provides Lightning → L-BTC swaps (receive side).
|
|
272
|
+
|
|
273
|
+
**API Endpoint**: Configurable via `ANKARA_API_URL` environment variable (defaults to `https://test.aquabtc.com`)
|
|
274
|
+
|
|
275
|
+
**Endpoints**:
|
|
276
|
+
- `POST /api/v1/lightning/swaps/create/` - Create receive invoice
|
|
277
|
+
- `POST /api/v1/lightning/swaps/{swap_id}/claim/` - Claim settled swap
|
|
278
|
+
- `GET /api/v1/lightning/lnurlp/verify/{swap_id}` - Verify settlement status
|
|
279
|
+
|
|
280
|
+
**Amount Limits**: 100 – 25,000,000 sats (no authentication required)
|
|
281
|
+
|
|
282
|
+
## Bitcoin Implementation Details
|
|
283
|
+
|
|
284
|
+
### BDK Constants
|
|
285
|
+
|
|
286
|
+
| Constant | Value | Purpose |
|
|
287
|
+
|----------|-------|---------|
|
|
288
|
+
| `STOP_GAP` | 20 | Max consecutive unused addresses to scan before stopping |
|
|
289
|
+
| `PARALLEL_REQUESTS` | 3 | Concurrent Esplora API requests during full_scan |
|
|
290
|
+
|
|
291
|
+
### BDK Send Flow
|
|
292
|
+
|
|
293
|
+
1. **Validate** amount > 0, fee_rate > 0 (if provided), wallet has mnemonic
|
|
294
|
+
2. **Decrypt** mnemonic using password (if encrypted at rest)
|
|
295
|
+
3. **Load** wallet with signing capability (`_get_wallet_with_signer`)
|
|
296
|
+
4. **Sync** wallet via Esplora `full_scan` to get latest UTXOs
|
|
297
|
+
5. **Build** PSBT with `TxBuilder`, set recipient and optional fee rate
|
|
298
|
+
6. **Sign** with `trust_witness_utxo=True`, `try_finalize=True`
|
|
299
|
+
7. **Broadcast** via Esplora client
|
|
300
|
+
8. **Return** txid in display format (big-endian, matching block explorers)
|
|
301
|
+
|
|
302
|
+
### TXID Format
|
|
303
|
+
|
|
304
|
+
Transaction IDs are returned in **big-endian display format** (byte-reversed hex), matching what block explorers show. BDK internally uses little-endian.
|
|
305
|
+
|
|
306
|
+
## Error Handling
|
|
307
|
+
|
|
308
|
+
All tools return structured errors:
|
|
309
|
+
|
|
310
|
+
```json
|
|
311
|
+
{
|
|
312
|
+
"error": {
|
|
313
|
+
"code": "INSUFFICIENT_FUNDS",
|
|
314
|
+
"message": "Not enough L-BTC to complete transaction",
|
|
315
|
+
"details": {
|
|
316
|
+
"required": 10000,
|
|
317
|
+
"available": 5000
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Common error codes: `ValueError`, `INSUFFICIENT_FUNDS`, `Generic`.
|
|
324
|
+
|
|
325
|
+
## Example Flows
|
|
326
|
+
|
|
327
|
+
### Create New Wallet (Unified)
|
|
328
|
+
|
|
329
|
+
```
|
|
330
|
+
1. lw_generate_mnemonic()
|
|
331
|
+
→ { "mnemonic": "abandon abandon ...", "words": 12 }
|
|
332
|
+
|
|
333
|
+
2. lw_import_mnemonic(mnemonic="...", network="mainnet")
|
|
334
|
+
→ { "wallet_name": "default", "descriptor": "ct(...)", "btc_descriptor": "wpkh(...)" }
|
|
335
|
+
|
|
336
|
+
3. lw_address(wallet_name="default") → Liquid address (lq1...)
|
|
337
|
+
btc_address(wallet_name="default") → Bitcoin address (bc1...)
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Check Balance & Send
|
|
341
|
+
|
|
342
|
+
```
|
|
343
|
+
1. lw_balance(wallet_name="default")
|
|
344
|
+
→ { "balances": [{ "ticker": "L-BTC", "amount_sats": 100000 }, ...] }
|
|
345
|
+
|
|
346
|
+
2. unified_balance(wallet_name="default")
|
|
347
|
+
→ { "bitcoin": { "balance_sats": 50000 }, "liquid": { "balances": [...] } }
|
|
348
|
+
|
|
349
|
+
3. lw_send(wallet_name="default", address="lq1...", amount=50000)
|
|
350
|
+
→ { "txid": "abc123...", "amount": 50000 }
|
|
351
|
+
|
|
352
|
+
4. btc_balance(wallet_name="default") → { "balance_sats": 0, "balance_btc": 0 }
|
|
353
|
+
btc_send(wallet_name="default", address="bc1...", amount=10000, password="...")
|
|
354
|
+
→ { "txid": "...", "amount": 10000 }
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Watch-Only Import
|
|
358
|
+
|
|
359
|
+
```
|
|
360
|
+
1. lw_import_descriptor(descriptor="ct(slip77(...),elwpkh(...))", wallet_name="cold")
|
|
361
|
+
→ { "wallet_name": "cold", "watch_only": true }
|
|
362
|
+
|
|
363
|
+
2. lw_balance(wallet_name="cold")
|
|
364
|
+
→ { "balances": [...] }
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Check Transaction Status
|
|
368
|
+
|
|
369
|
+
```
|
|
370
|
+
1. lw_tx_status(tx="abc123...")
|
|
371
|
+
→ { "txid": "abc123...", "status": "confirmed", "confirmations": 5, "explorer_url": "https://..." }
|
|
372
|
+
|
|
373
|
+
2. lw_tx_status(tx="https://blockstream.info/liquid/tx/abc123...")
|
|
374
|
+
→ { "txid": "abc123...", "network": "mainnet", "status": "unconfirmed", ... }
|
|
375
|
+
```
|
|
376
|
+
## Development Environment
|
|
377
|
+
|
|
378
|
+
This is a Python/uv project. Always use `uv` commands (uv sync, uv run, uvx) instead of pip, venv, or other Python package managers.
|
|
379
|
+
|
|
380
|
+
## Development
|
|
381
|
+
|
|
382
|
+
### Project Structure
|
|
383
|
+
|
|
384
|
+
```
|
|
385
|
+
agentic-aqua/
|
|
386
|
+
├── AGENTS.md # This file (specs)
|
|
387
|
+
├── README.md # User documentation
|
|
388
|
+
├── pyproject.toml # Python package config
|
|
389
|
+
├── src/
|
|
390
|
+
│ └── aqua/
|
|
391
|
+
│ ├── __init__.py
|
|
392
|
+
│ ├── server.py # MCP server entry point (tools, resources, prompts)
|
|
393
|
+
│ ├── tools.py # Tool implementations (lw_*, btc_*, unified_*, lightning_*)
|
|
394
|
+
│ ├── wallet.py # Liquid wallet (LWK)
|
|
395
|
+
│ ├── bitcoin.py # Bitcoin wallet (BDK)
|
|
396
|
+
│ ├── lightning.py # Lightning abstraction layer (unified send/receive manager)
|
|
397
|
+
│ ├── boltz.py # Boltz Exchange integration (submarine swaps, send)
|
|
398
|
+
│ ├── ankara.py # Ankara backend integration (Lightning receive)
|
|
399
|
+
│ ├── assets.py # Asset registry
|
|
400
|
+
│ └── storage.py # Persistence layer (encryption, config, wallet data)
|
|
401
|
+
└── tests/
|
|
402
|
+
├── test_tools.py
|
|
403
|
+
├── test_lightning.py
|
|
404
|
+
├── test_storage.py
|
|
405
|
+
├── test_bitcoin.py
|
|
406
|
+
├── test_boltz.py
|
|
407
|
+
├── test_ankara.py
|
|
408
|
+
└── test_server.py
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Running Tests
|
|
412
|
+
|
|
413
|
+
```bash
|
|
414
|
+
uv sync --all-extras
|
|
415
|
+
uv run python -m pytest tests/
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### Local Development
|
|
419
|
+
|
|
420
|
+
```bash
|
|
421
|
+
uv sync
|
|
422
|
+
uv run python -m aqua.server
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
## TLDR Integration
|
|
428
|
+
|
|
429
|
+
For code exploration, PREFER these TLDR tools over raw Grep/Glob:
|
|
430
|
+
|
|
431
|
+
| Tool | When to use |
|
|
432
|
+
|------|-------------|
|
|
433
|
+
| `mcp__tldr__semantic` | Find code by behavior ("validate tokens", "handle errors") |
|
|
434
|
+
| `mcp__tldr__structure` | Get function/class map of project |
|
|
435
|
+
| `mcp__tldr__context` | Get call graph from entry point (95% token savings) |
|
|
436
|
+
| `mcp__tldr__impact` | Before refactoring, find all callers |
|
|
437
|
+
| `mcp__tldr__arch` | Detect architectural layers |
|
|
438
|
+
| `mcp__tldr__change_impact` | Find tests affected by changes |
|
|
439
|
+
|
|
440
|
+
Use standard Grep/Glob only for: exact string matches, simple file lookups, config/env searches.
|
|
441
|
+
|
|
442
|
+
---
|
|
443
|
+
|
|
444
|
+
*Last updated: 2026-03-17*
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|