@agentlayer.tech/wallet 0.1.30 → 0.1.32
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/.openclaw/extensions/agent-wallet/README.md +1 -2
- package/.openclaw/extensions/agent-wallet/dist/index.js +6 -340
- package/.openclaw/extensions/agent-wallet/index.ts +6 -340
- package/.openclaw/extensions/agent-wallet/openclaw.plugin.json +0 -43
- package/.openclaw/extensions/agent-wallet/package.json +1 -1
- package/.openclaw/extensions/agent-wallet/skills/wallet-operator/SKILL.md +1 -3
- package/CHANGELOG.md +35 -0
- package/README.md +0 -5
- package/agent-wallet/.env.example +0 -12
- package/agent-wallet/README.md +0 -35
- package/agent-wallet/agent_wallet/btc_user_wallets.py +32 -1
- package/agent-wallet/agent_wallet/config.py +11 -7
- package/agent-wallet/agent_wallet/evm_user_wallets.py +2 -0
- package/agent-wallet/agent_wallet/openclaw_adapter.py +1 -655
- package/agent-wallet/agent_wallet/openclaw_cli.py +0 -7
- package/agent-wallet/agent_wallet/providers/evm_portfolio.py +18 -42
- package/agent-wallet/agent_wallet/providers/jupiter.py +1 -307
- package/agent-wallet/agent_wallet/providers/wdk_btc_local.py +31 -3
- package/agent-wallet/agent_wallet/providers/wdk_evm_local.py +37 -3
- package/agent-wallet/agent_wallet/transaction_policy.py +0 -262
- package/agent-wallet/agent_wallet/wallet_layer/base.py +0 -100
- package/agent-wallet/agent_wallet/wallet_layer/solana.py +1 -1118
- package/agent-wallet/openclaw.plugin.json +0 -4
- package/agent-wallet/pyproject.toml +1 -1
- package/agent-wallet/scripts/install_agent_wallet.py +113 -6
- package/agent-wallet/scripts/install_openclaw_local_config.py +7 -5
- package/agent-wallet/skills/wallet-operator/SKILL.md +1 -5
- package/bin/openclaw-agent-wallet.mjs +103 -36
- package/claude-code/plugins/agent-wallet/scripts/run_mcp.sh +7 -2
- package/codex/plugins/agent-wallet/server.py +2 -118
- package/hermes/plugins/agent_wallet/tools.py +1 -1
- package/package.json +1 -1
- package/wdk-btc-wallet/src/local_vault.js +45 -68
- package/wdk-btc-wallet/src/server.js +1 -0
- package/wdk-evm-wallet/README.md +4 -3
- package/wdk-evm-wallet/src/config.js +15 -0
- package/wdk-evm-wallet/src/local_vault.js +45 -68
- package/wdk-evm-wallet/src/server.js +1 -0
- package/agent-wallet/agent_wallet/providers/houdini.py +0 -539
package/agent-wallet/README.md
CHANGED
|
@@ -89,18 +89,11 @@ Current safe tools:
|
|
|
89
89
|
- `stake_sol_native`
|
|
90
90
|
- `transfer_spl_token`
|
|
91
91
|
- `swap_solana_tokens` - Solana Jupiter swaps; prefer `intent_preview` -> chat confirmation -> `intent_execute` so execution refreshes the quote inside approved limits.
|
|
92
|
-
- `swap_solana_privately` - Houdini-backed private Solana payout flow for same-token `SOL->SOL` or `USDC->USDC` transfers to a destination wallet.
|
|
93
|
-
- `get_solana_private_swap_status`
|
|
94
|
-
- `get_jupiter_earn_tokens`
|
|
95
|
-
- `get_jupiter_earn_positions`
|
|
96
|
-
- `get_jupiter_earn_earnings`
|
|
97
92
|
- `get_kamino_lend_markets`
|
|
98
93
|
- `get_kamino_lend_market_reserves`
|
|
99
94
|
- `get_kamino_lend_user_obligations`
|
|
100
95
|
- `get_kamino_lend_user_rewards`
|
|
101
96
|
- `get_kamino_open_positions`
|
|
102
|
-
- `jupiter_earn_deposit`
|
|
103
|
-
- `jupiter_earn_withdraw`
|
|
104
97
|
- `kamino_lend_deposit`
|
|
105
98
|
- `kamino_lend_withdraw`
|
|
106
99
|
- `kamino_lend_borrow`
|
|
@@ -122,8 +115,6 @@ Temporarily disabled but kept in the codebase for later re-enable:
|
|
|
122
115
|
The signing tool still requires explicit `user_confirmed=true`.
|
|
123
116
|
Transfer, native staking, swap, and Aave position-management tools support `preview`, `prepare`, and `execute` modes. The safe operational path is still preview-first. `prepare` now returns an execution plan only and never exposes signed transaction bytes to the agent. `execute` works only when the backend has a signer and `sign_only=false`.
|
|
124
117
|
|
|
125
|
-
Exception: `swap_solana_privately` is intentionally optimized for `preview -> execute`. Hosts should not insert a separate `prepare` step for Houdini private payouts because it adds no execution value and only burns additional provider quota.
|
|
126
|
-
|
|
127
118
|
Policy defaults:
|
|
128
119
|
|
|
129
120
|
- read-only tools are always allowed
|
|
@@ -194,38 +185,12 @@ For production `mainnet`, prefer a dedicated RPC instead of the public Solana en
|
|
|
194
185
|
|
|
195
186
|
Production recommendation: treat RPC as deployment-owned config, not wallet logic. Runtime env wins over `openclaw.json` plugin config, so keep `Alchemy/Helius/QuickNode` endpoints in deployment secrets or service env and use plugin `rpcUrl` / `rpcUrls` only as local fallback.
|
|
196
187
|
|
|
197
|
-
For Houdini-backed private Solana payouts, also provide:
|
|
198
|
-
|
|
199
|
-
- `HOUDINI_API_KEY`
|
|
200
|
-
- `HOUDINI_API_SECRET`
|
|
201
|
-
- `HOUDINI_USER_IP`
|
|
202
|
-
- optional `HOUDINI_USER_AGENT`
|
|
203
|
-
- optional `HOUDINI_USER_TIMEZONE`
|
|
204
|
-
|
|
205
|
-
The current MVP intentionally keeps the scope narrow:
|
|
206
|
-
|
|
207
|
-
- supported private routes are same-token Solana payouts only
|
|
208
|
-
- `SOL -> SOL`
|
|
209
|
-
- `USDC -> USDC`
|
|
210
|
-
- execution binds to the approved Houdini `quoteId`, creates a single private exchange, and sends the exact Solana deposit locally from the wallet
|
|
211
|
-
|
|
212
|
-
This is a private payout flow expressed in Houdini's swap terminology. Cross-token private swaps can be added later without changing the OpenClaw/Hermes approval model.
|
|
213
|
-
|
|
214
|
-
For production, the cleaner setup is to place Houdini partner secrets on `provider-gateway` and let `agent-wallet` consume the narrow gateway endpoints through `PROVIDER_GATEWAY_URL` and optional `PROVIDER_GATEWAY_BEARER_TOKEN`. In that mode:
|
|
215
|
-
|
|
216
|
-
- the gateway owns `HOUDINI_API_KEY` / `HOUDINI_API_SECRET`
|
|
217
|
-
- the gateway derives the authoritative user IP from ingress
|
|
218
|
-
- `agent-wallet` still performs preview/prepare/execute, local transaction verification, signing, and broadcast
|
|
219
|
-
- direct Houdini env vars can be omitted from the wallet runtime
|
|
220
|
-
|
|
221
188
|
For OpenClaw onboarding, `agent-wallet` now ships with a hosted default provider gateway:
|
|
222
189
|
|
|
223
190
|
- `https://agent-layer-production.up.railway.app`
|
|
224
191
|
|
|
225
192
|
So users do not need to enter `PROVIDER_GATEWAY_URL` manually for the default Bags launch/fees flows or shared mainnet RPC path. You only need to set `PROVIDER_GATEWAY_URL` yourself if you want to override that hosted default with your own deployment.
|
|
226
193
|
|
|
227
|
-
That same provider gateway path can now also cover Jupiter Earn reads and transaction-building. Ordinary Jupiter swap routing remains direct.
|
|
228
|
-
|
|
229
194
|
For a self-hosted install where each operator brings their own RPC key, a minimal Solana setup can be just:
|
|
230
195
|
|
|
231
196
|
```bash
|
|
@@ -6,7 +6,12 @@ import json
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
from typing import Any
|
|
8
8
|
|
|
9
|
-
from agent_wallet.config import
|
|
9
|
+
from agent_wallet.config import (
|
|
10
|
+
normalize_btc_network,
|
|
11
|
+
resolve_boot_key,
|
|
12
|
+
resolve_openclaw_home,
|
|
13
|
+
settings,
|
|
14
|
+
)
|
|
10
15
|
from agent_wallet.providers.wdk_btc_local import WdkBtcLocalClient
|
|
11
16
|
from agent_wallet.user_wallets import normalize_user_id
|
|
12
17
|
from agent_wallet.wallet_layer.base import WalletBackendError
|
|
@@ -16,6 +21,28 @@ def _normalize_btc_network(value: str | None) -> str:
|
|
|
16
21
|
return normalize_btc_network(value)
|
|
17
22
|
|
|
18
23
|
|
|
24
|
+
def _maybe_store_btc_wallet_password(password: str) -> bool:
|
|
25
|
+
"""Seal the BTC vault password so signing can decrypt-on-demand without re-entry.
|
|
26
|
+
|
|
27
|
+
Mirrors the EVM flow: once sealed under the boot key, the local BTC client
|
|
28
|
+
injects it automatically on each signing request.
|
|
29
|
+
"""
|
|
30
|
+
value = str(password or "").strip()
|
|
31
|
+
if not value:
|
|
32
|
+
return False
|
|
33
|
+
boot_key = resolve_boot_key()
|
|
34
|
+
if not boot_key:
|
|
35
|
+
return False
|
|
36
|
+
from agent_wallet.sealed_keys import resolve_sealed_keys_path, seal_keys, unseal_keys
|
|
37
|
+
|
|
38
|
+
sealed_path = resolve_sealed_keys_path()
|
|
39
|
+
existing = unseal_keys(boot_key) if sealed_path.exists() else {}
|
|
40
|
+
if existing.get("wdk_btc_wallet_password") == value:
|
|
41
|
+
return False
|
|
42
|
+
seal_keys(boot_key, {**existing, "wdk_btc_wallet_password": value})
|
|
43
|
+
return True
|
|
44
|
+
|
|
45
|
+
|
|
19
46
|
def _resolve_service_url(service_url: str | None = None) -> str:
|
|
20
47
|
effective = (service_url or settings.wdk_btc_service_url).strip()
|
|
21
48
|
if not effective:
|
|
@@ -72,6 +99,7 @@ def create_user_btc_wallet(
|
|
|
72
99
|
"walletId": created["walletId"],
|
|
73
100
|
"accountIndex": effective_account_index,
|
|
74
101
|
"network": effective_network,
|
|
102
|
+
"password": password,
|
|
75
103
|
},
|
|
76
104
|
)
|
|
77
105
|
binding = {
|
|
@@ -87,6 +115,7 @@ def create_user_btc_wallet(
|
|
|
87
115
|
"updated_at": created.get("updatedAt"),
|
|
88
116
|
}
|
|
89
117
|
_write_wallet_binding(resolve_user_btc_wallet_path(user_id, effective_network), binding)
|
|
118
|
+
_maybe_store_btc_wallet_password(password)
|
|
90
119
|
return {
|
|
91
120
|
**binding,
|
|
92
121
|
"unlocked": bool(created.get("unlocked", True)),
|
|
@@ -123,6 +152,7 @@ def import_user_btc_wallet(
|
|
|
123
152
|
"walletId": created["walletId"],
|
|
124
153
|
"accountIndex": effective_account_index,
|
|
125
154
|
"network": effective_network,
|
|
155
|
+
"password": password,
|
|
126
156
|
},
|
|
127
157
|
)
|
|
128
158
|
binding = {
|
|
@@ -162,6 +192,7 @@ def unlock_user_btc_wallet(
|
|
|
162
192
|
"timeoutSeconds": 0,
|
|
163
193
|
},
|
|
164
194
|
)
|
|
195
|
+
_maybe_store_btc_wallet_password(password)
|
|
165
196
|
return {
|
|
166
197
|
**binding,
|
|
167
198
|
"unlocked": bool(payload.get("unlocked", True)),
|
|
@@ -49,18 +49,11 @@ class Settings(BaseSettings):
|
|
|
49
49
|
jupiter_ultra_api_base_url: str = "https://lite-api.jup.ag/ultra/v1"
|
|
50
50
|
jupiter_price_api_base_url: str = "https://lite-api.jup.ag/price/v3"
|
|
51
51
|
jupiter_portfolio_api_base_url: str = "https://api.jup.ag/portfolio/v1"
|
|
52
|
-
jupiter_lend_api_base_url: str = "https://api.jup.ag/lend/v1"
|
|
53
52
|
jupiter_api_key: str = ""
|
|
54
53
|
lifi_api_base_url: str = "https://li.quest/v1"
|
|
55
54
|
lifi_api_key: str = ""
|
|
56
55
|
lifi_integrator: str = "openclaw"
|
|
57
56
|
lifi_default_deny_bridges: str = "mayan"
|
|
58
|
-
houdini_api_base_url: str = "https://api-partner.houdiniswap.com/v2"
|
|
59
|
-
houdini_api_key: str = ""
|
|
60
|
-
houdini_api_secret: str = ""
|
|
61
|
-
houdini_user_ip: str = ""
|
|
62
|
-
houdini_user_agent: str = "AgentLayer/0.1.12"
|
|
63
|
-
houdini_user_timezone: str = "UTC"
|
|
64
57
|
flash_api_base_url: str = ""
|
|
65
58
|
flash_sdk_bridge_command: str = ""
|
|
66
59
|
flash_sdk_bridge_mode: str = "mock"
|
|
@@ -457,6 +450,17 @@ def resolve_evm_wallet_password() -> str:
|
|
|
457
450
|
)
|
|
458
451
|
|
|
459
452
|
|
|
453
|
+
def resolve_btc_wallet_password() -> str:
|
|
454
|
+
"""Resolve the local BTC vault password from env or the sealed secret store."""
|
|
455
|
+
direct = os.getenv("WDK_BTC_WALLET_PASSWORD", "").strip()
|
|
456
|
+
if direct:
|
|
457
|
+
return direct
|
|
458
|
+
return _resolve_sealed_secret(
|
|
459
|
+
"wdk_btc_wallet_password",
|
|
460
|
+
"btc_wallet_password",
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
|
|
460
464
|
def use_encrypted_user_wallets() -> bool:
|
|
461
465
|
"""Per-user wallet files are always encrypted in the hardened runtime."""
|
|
462
466
|
return True
|
|
@@ -529,6 +529,7 @@ def create_user_evm_wallet(
|
|
|
529
529
|
"walletId": created["walletId"],
|
|
530
530
|
"accountIndex": effective_account_index,
|
|
531
531
|
"network": effective_network,
|
|
532
|
+
"password": password,
|
|
532
533
|
},
|
|
533
534
|
)
|
|
534
535
|
binding = {
|
|
@@ -581,6 +582,7 @@ def import_user_evm_wallet(
|
|
|
581
582
|
"walletId": created["walletId"],
|
|
582
583
|
"accountIndex": effective_account_index,
|
|
583
584
|
"network": effective_network,
|
|
585
|
+
"password": password,
|
|
584
586
|
},
|
|
585
587
|
)
|
|
586
588
|
binding = {
|