@agentlayer.tech/wallet 0.1.0

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.
Files changed (96) hide show
  1. package/.openclaw/AGENTS.md +98 -0
  2. package/.openclaw/extensions/agent-wallet/README.md +127 -0
  3. package/.openclaw/extensions/agent-wallet/index.ts +1520 -0
  4. package/.openclaw/extensions/agent-wallet/openclaw.plugin.json +184 -0
  5. package/.openclaw/extensions/agent-wallet/package.json +11 -0
  6. package/.openclaw/extensions/agent-wallet/skills/wallet-operator/SKILL.md +20 -0
  7. package/CHANGELOG.md +42 -0
  8. package/LICENSE +104 -0
  9. package/README.md +332 -0
  10. package/RELEASING.md +204 -0
  11. package/agent-wallet/.env.example +62 -0
  12. package/agent-wallet/AGENTS.md +129 -0
  13. package/agent-wallet/README.md +527 -0
  14. package/agent-wallet/agent_wallet/__init__.py +11 -0
  15. package/agent-wallet/agent_wallet/approval.py +161 -0
  16. package/agent-wallet/agent_wallet/bootstrap.py +178 -0
  17. package/agent-wallet/agent_wallet/btc_user_wallets.py +217 -0
  18. package/agent-wallet/agent_wallet/config.py +382 -0
  19. package/agent-wallet/agent_wallet/encrypted_storage.py +161 -0
  20. package/agent-wallet/agent_wallet/evm_user_wallets.py +370 -0
  21. package/agent-wallet/agent_wallet/exceptions.py +9 -0
  22. package/agent-wallet/agent_wallet/file_ops.py +34 -0
  23. package/agent-wallet/agent_wallet/http_client.py +25 -0
  24. package/agent-wallet/agent_wallet/models.py +66 -0
  25. package/agent-wallet/agent_wallet/nonce_registry.py +59 -0
  26. package/agent-wallet/agent_wallet/openclaw_adapter.py +5128 -0
  27. package/agent-wallet/agent_wallet/openclaw_cli.py +626 -0
  28. package/agent-wallet/agent_wallet/openclaw_runtime.py +272 -0
  29. package/agent-wallet/agent_wallet/plugin_bundle.py +42 -0
  30. package/agent-wallet/agent_wallet/providers/__init__.py +1 -0
  31. package/agent-wallet/agent_wallet/providers/bags.py +259 -0
  32. package/agent-wallet/agent_wallet/providers/evm_portfolio.py +470 -0
  33. package/agent-wallet/agent_wallet/providers/jupiter.py +567 -0
  34. package/agent-wallet/agent_wallet/providers/kamino.py +215 -0
  35. package/agent-wallet/agent_wallet/providers/lifi.py +277 -0
  36. package/agent-wallet/agent_wallet/providers/solana_rpc.py +470 -0
  37. package/agent-wallet/agent_wallet/providers/wdk_btc_local.py +114 -0
  38. package/agent-wallet/agent_wallet/providers/wdk_evm_local.py +205 -0
  39. package/agent-wallet/agent_wallet/sealed_keys.py +61 -0
  40. package/agent-wallet/agent_wallet/solana_stake.py +103 -0
  41. package/agent-wallet/agent_wallet/solana_tx.py +93 -0
  42. package/agent-wallet/agent_wallet/spending_limits.py +101 -0
  43. package/agent-wallet/agent_wallet/transaction_policy.py +518 -0
  44. package/agent-wallet/agent_wallet/user_wallets.py +355 -0
  45. package/agent-wallet/agent_wallet/validation.py +31 -0
  46. package/agent-wallet/agent_wallet/wallet_layer/__init__.py +1 -0
  47. package/agent-wallet/agent_wallet/wallet_layer/base.py +808 -0
  48. package/agent-wallet/agent_wallet/wallet_layer/base58.py +44 -0
  49. package/agent-wallet/agent_wallet/wallet_layer/factory.py +102 -0
  50. package/agent-wallet/agent_wallet/wallet_layer/solana.py +4252 -0
  51. package/agent-wallet/agent_wallet/wallet_layer/wdk_btc.py +272 -0
  52. package/agent-wallet/agent_wallet/wallet_layer/wdk_evm.py +1628 -0
  53. package/agent-wallet/examples/bootstrap_wallet.py +21 -0
  54. package/agent-wallet/examples/openclaw_runtime_onboarding.py +28 -0
  55. package/agent-wallet/examples/openclaw_user_wallet_example.py +31 -0
  56. package/agent-wallet/examples/openclaw_wallet_adapter_example.py +33 -0
  57. package/agent-wallet/openclaw.plugin.json +138 -0
  58. package/agent-wallet/pyproject.toml +31 -0
  59. package/agent-wallet/scripts/bootstrap_openclaw_btc.py +278 -0
  60. package/agent-wallet/scripts/build_release_bundle.py +188 -0
  61. package/agent-wallet/scripts/finalize_openclaw_local_wallet_config.py +121 -0
  62. package/agent-wallet/scripts/install_agent_wallet.py +505 -0
  63. package/agent-wallet/scripts/install_openclaw_local_config.py +226 -0
  64. package/agent-wallet/scripts/install_openclaw_sealed_keys.py +105 -0
  65. package/agent-wallet/scripts/manage_openclaw_btc_wallet.py +244 -0
  66. package/agent-wallet/scripts/reveal_btc_seed.sh +130 -0
  67. package/agent-wallet/scripts/security_utils.py +37 -0
  68. package/agent-wallet/scripts/setup_btc_wallet.sh +146 -0
  69. package/agent-wallet/scripts/switch_openclaw_wallet_network.py +106 -0
  70. package/agent-wallet/skills/wallet-operator/SKILL.md +128 -0
  71. package/bin/openclaw-agent-wallet.mjs +487 -0
  72. package/install-from-github.sh +134 -0
  73. package/package.json +61 -0
  74. package/setup.sh +40 -0
  75. package/wdk-btc-wallet/README.md +325 -0
  76. package/wdk-btc-wallet/bootstrap.sh +22 -0
  77. package/wdk-btc-wallet/package-lock.json +1839 -0
  78. package/wdk-btc-wallet/package.json +18 -0
  79. package/wdk-btc-wallet/run-local.sh +21 -0
  80. package/wdk-btc-wallet/src/config.js +160 -0
  81. package/wdk-btc-wallet/src/json.js +35 -0
  82. package/wdk-btc-wallet/src/local_vault.js +432 -0
  83. package/wdk-btc-wallet/src/network_state.js +84 -0
  84. package/wdk-btc-wallet/src/server.js +257 -0
  85. package/wdk-btc-wallet/src/wdk_btc_wallet.js +332 -0
  86. package/wdk-evm-wallet/README.md +183 -0
  87. package/wdk-evm-wallet/bootstrap.sh +8 -0
  88. package/wdk-evm-wallet/package-lock.json +2340 -0
  89. package/wdk-evm-wallet/package.json +23 -0
  90. package/wdk-evm-wallet/run-local.sh +12 -0
  91. package/wdk-evm-wallet/src/config.js +274 -0
  92. package/wdk-evm-wallet/src/json.js +35 -0
  93. package/wdk-evm-wallet/src/local_vault.js +430 -0
  94. package/wdk-evm-wallet/src/network_state.js +92 -0
  95. package/wdk-evm-wallet/src/server.js +575 -0
  96. package/wdk-evm-wallet/src/wdk_evm_wallet.js +4981 -0
@@ -0,0 +1,129 @@
1
+ # AGENTS.md
2
+
3
+ ## Scope
4
+ These instructions apply to the entire `agent-wallet/` tree.
5
+
6
+ ## Purpose
7
+ `agent-wallet` is the authoritative Python wallet backend used by OpenClaw. It is the source of truth for wallet behavior, safety policy, and Solana execution. It owns:
8
+
9
+ - wallet runtime configuration
10
+ - per-user wallet provisioning
11
+ - Solana read/write operations
12
+ - approval-token validation for sensitive execution
13
+ - OpenClaw-facing adapter and CLI bridge
14
+ - local installer and config patching scripts
15
+
16
+ ## Architecture map
17
+
18
+ ### Main entrypoints
19
+ - `agent_wallet/openclaw_cli.py` - JSON CLI bridge invoked by the TypeScript OpenClaw extension.
20
+ - `agent_wallet/openclaw_runtime.py` - assembles a runtime context for one OpenClaw user session.
21
+ - `agent_wallet/openclaw_adapter.py` - exposes backend operations as safe agent-facing tools and enforces preview/prepare/execute policy.
22
+ - `agent_wallet/plugin_bundle.py` - builds the manifest/tool bundle exposed to hosts.
23
+ - `agent_wallet/wallet_layer/factory.py` - constructs the active backend implementation.
24
+ - `agent_wallet/wallet_layer/solana.py` - primary Solana backend implementation.
25
+
26
+ ### Configuration and secrets
27
+ - `agent_wallet/config.py` - central place for runtime settings, RPC resolution, boot key resolution, and sealed secret loading.
28
+ - `agent_wallet/sealed_keys.py` - encrypted secret bundle support for `~/.openclaw/sealed_keys.json`.
29
+ - `agent_wallet/encrypted_storage.py` - encrypted wallet file helpers.
30
+ - `agent_wallet/validation.py` - shared input validation and error shaping.
31
+
32
+ ### Wallet backend
33
+ - `agent_wallet/solana_tx.py` - transaction build, sign, and verification helpers.
34
+ - `agent_wallet/solana_stake.py` - stake-specific wallet operations.
35
+ - `agent_wallet/user_wallets.py` - per-user wallet paths, creation, loading, and migration behavior.
36
+ - `agent_wallet/bootstrap.py` - wallet bootstrap helpers and address pinning.
37
+
38
+ ### Transaction safety
39
+ - `agent_wallet/approval.py` - host-issued approval tokens.
40
+ - `agent_wallet/nonce_registry.py` - single-use token replay protection.
41
+ - `agent_wallet/transaction_policy.py` - policy validation around transaction execution.
42
+ - `agent_wallet/spending_limits.py` - spending guardrails.
43
+ - `agent_wallet/models.py` - canonical JSON payloads and tool metadata.
44
+
45
+ ### OpenClaw integration
46
+ - `agent_wallet/openclaw_cli.py` is the compatibility boundary for the OpenClaw TypeScript plugin.
47
+ - `agent_wallet/openclaw_runtime.py` owns per-session runtime assembly and user wallet onboarding.
48
+ - `agent_wallet/openclaw_adapter.py` is the policy gate for agent-facing tools.
49
+ - `agent_wallet/plugin_bundle.py` defines the host-facing manifest and tool bundle.
50
+ - Keep these files aligned whenever tool names, config fields, or approval semantics change.
51
+
52
+ ### Scripts
53
+ - `scripts/install_agent_wallet.py` - local installer for Python env + OpenClaw config setup.
54
+ - `scripts/install_openclaw_local_config.py` - writes plugin config into OpenClaw config.
55
+ - `scripts/install_openclaw_sealed_keys.py` - provisions sealed runtime secrets.
56
+ - `scripts/switch_openclaw_wallet_network.py` - helper for switching the configured Solana network.
57
+ - `scripts/finalize_openclaw_local_wallet_config.py` - local config finalization helper when the runtime is already present.
58
+
59
+ ## Working rules
60
+
61
+ ### Keep responsibilities separated
62
+ - Keep host bridge logic in `openclaw_cli.py` and `openclaw_runtime.py`.
63
+ - Keep agent-facing safety and tool exposure in `openclaw_adapter.py`.
64
+ - Keep chain-specific behavior in `wallet_layer/solana.py`, `solana_tx.py`, and `solana_stake.py`.
65
+ - Keep config precedence in `config.py`; do not duplicate env resolution elsewhere unless necessary.
66
+ - Keep `.openclaw/` as the host-side bridge layer. Wallet policy and signing rules belong here, not in the OpenClaw extension.
67
+
68
+ ### Security invariants
69
+ - Do not add runtime support for loading `AGENT_WALLET_MASTER_KEY`, `AGENT_WALLET_APPROVAL_SECRET`, or `SOLANA_AGENT_PRIVATE_KEY` directly from runtime env again.
70
+ - Do not put secrets into plugin config JSON.
71
+ - Preserve the `preview -> prepare -> execute` flow for write operations.
72
+ - `prepare` must never return signed transaction bytes.
73
+ - `execute` must continue requiring a host-issued `approval_token`.
74
+ - On `mainnet`, preserve explicit confirmation requirements and warnings.
75
+ - Treat `user_confirmed=true`, `approval_token`, and the mainnet confirmation fields as mandatory safety gates, not optional metadata.
76
+ - Never weaken wallet validation to make a tool easier to call.
77
+
78
+ ### Update discipline
79
+ - Prefer fixing behavior in the Python backend instead of patching around it in scripts.
80
+ - When adding or removing a tool, keep the following in sync:
81
+ - `agent_wallet/openclaw_adapter.py`
82
+ - `agent_wallet/plugin_bundle.py`
83
+ - OpenClaw extension tool registration in `.openclaw/extensions/agent-wallet/index.ts`
84
+ - relevant docs/tests
85
+ - When changing config keys, keep the following in sync:
86
+ - `agent_wallet/config.py`
87
+ - `agent_wallet/openclaw_cli.py`
88
+ - `.openclaw/extensions/agent-wallet/openclaw.plugin.json`
89
+ - installer scripts and README examples
90
+ - When changing approval or signing behavior, update the runtime, adapter, CLI bridge, and smoke tests together.
91
+ - If a change affects the OpenClaw bridge, update the TypeScript extension and the Python contract in the same change set.
92
+
93
+ ### Coding style
94
+ - Follow existing Python style and type-hint usage.
95
+ - Keep changes minimal and local to the owning module.
96
+ - Avoid introducing framework-heavy abstractions; this repo is intentionally direct.
97
+ - Prefer explicit JSON-serializable return payloads because the CLI bridge depends on them.
98
+ - Preserve existing public payload shapes unless a coordinated contract change is required.
99
+
100
+ ## Validation
101
+ - Prefer targeted smoke tests first, then broader runs if needed.
102
+ - Relevant tests live under `tests/` and are mostly smoke-style.
103
+ - Good focused examples:
104
+ - `tests/smoke_openclaw_cli.py`
105
+ - `tests/smoke_openclaw_adapter.py`
106
+ - `tests/smoke_openclaw_runtime.py`
107
+ - `tests/smoke_install_agent_wallet.py`
108
+ - `tests/smoke_sealed_keys.py`
109
+ - `tests/smoke_solana_tx.py`
110
+
111
+ ## Common change patterns
112
+
113
+ ### If changing tool behavior
114
+ 1. Update backend or adapter.
115
+ 2. Verify preview/prepare/execute semantics.
116
+ 3. Sync tool metadata exposed to OpenClaw.
117
+ 4. Update or add smoke tests.
118
+
119
+ ### If changing config or install flow
120
+ 1. Update `config.py` and any CLI/env mapping.
121
+ 2. Update installer scripts.
122
+ 3. Update README snippets and examples.
123
+ 4. Run install/config smoke tests.
124
+
125
+ ### If changing Solana execution logic
126
+ 1. Keep address validation and policy checks intact.
127
+ 2. Preserve sign-only behavior.
128
+ 3. Preserve exact confirmation summaries used for approval tokens.
129
+ 4. Re-run the most specific Solana smoke tests available.
@@ -0,0 +1,527 @@
1
+ # OpenClaw Agent Wallet
2
+
3
+ Reusable wallet backend for OpenClaw agents.
4
+
5
+ Current focus:
6
+
7
+ - simple local Solana support
8
+ - separate local BTC and EVM custody runtimes
9
+ - send-enabled local operation with optional sign-only mode
10
+ - minimal external API surface
11
+ - easy embedding into agent runtimes or MCP adapters
12
+
13
+ ## OpenClaw integration
14
+
15
+ The package now includes a thin adapter for agent runtimes:
16
+
17
+ - `agent_wallet.openclaw_adapter.OpenClawWalletAdapter`
18
+ - `agent_wallet.plugin_bundle.build_openclaw_plugin_bundle`
19
+ - `agent_wallet.openclaw_runtime.onboard_openclaw_user_wallet`
20
+ - `agent_wallet.openclaw_cli` for the official OpenClaw TypeScript plugin bridge
21
+
22
+ It provides:
23
+
24
+ - tool specs for agent registration
25
+ - runtime instructions for safe wallet usage
26
+ - a single `invoke()` method for safe dispatch
27
+ - OpenClaw-style plugin manifest and skill bundle
28
+ - explicit network-aware results so the host and agent can see `devnet` vs `mainnet`
29
+
30
+ Current safe tools:
31
+
32
+ - `get_wallet_capabilities`
33
+ - `get_wallet_address`
34
+ - `get_wallet_balance`
35
+ - `get_evm_token_metadata`
36
+ - `get_btc_transfer_history`
37
+ - `get_btc_fee_rates`
38
+ - `get_btc_max_spendable`
39
+ - `transfer_btc`
40
+ - `get_evm_token_balance`
41
+ - `get_evm_fee_rates`
42
+ - `get_evm_transaction_receipt`
43
+ - `get_evm_swap_quote`
44
+ - `swap_evm_tokens`
45
+ - `get_evm_aave_account`
46
+ - `get_evm_aave_reserves`
47
+ - `get_evm_aave_positions`
48
+ - `manage_evm_aave_position`
49
+ - `get_lifi_supported_chains`
50
+ - `get_lifi_quote`
51
+ - `get_lifi_transfer_status`
52
+ - `transfer_evm_native`
53
+ - `transfer_evm_token`
54
+ - `swap_evm_lifi_cross_chain_tokens` - EVM-origin LI.FI routes from Ethereum/Base to Ethereum/Base/Solana when LI.FI returns a route.
55
+ - `swap_solana_lifi_cross_chain_tokens` - Solana-origin LI.FI routes from Solana to Ethereum/Base when LI.FI returns a route.
56
+ - `get_wallet_portfolio`
57
+ - `get_solana_token_prices`
58
+ - `get_solana_staking_validators`
59
+ - `get_solana_stake_account`
60
+ - `sign_wallet_message`
61
+ - `transfer_sol`
62
+ - `stake_sol_native`
63
+ - `transfer_spl_token`
64
+ - `swap_solana_tokens`
65
+ - `get_jupiter_earn_tokens`
66
+ - `get_jupiter_earn_positions`
67
+ - `get_jupiter_earn_earnings`
68
+ - `get_kamino_lend_markets`
69
+ - `get_kamino_lend_market_reserves`
70
+ - `get_kamino_lend_user_obligations`
71
+ - `get_kamino_lend_user_rewards`
72
+ - `jupiter_earn_deposit`
73
+ - `jupiter_earn_withdraw`
74
+ - `kamino_lend_deposit`
75
+ - `kamino_lend_withdraw`
76
+ - `kamino_lend_borrow`
77
+ - `kamino_lend_repay`
78
+ - `close_empty_token_accounts`
79
+ - `deactivate_solana_stake`
80
+ - `withdraw_solana_stake`
81
+ - `request_devnet_airdrop`
82
+
83
+ Temporarily disabled but kept in the codebase for later re-enable:
84
+
85
+ - `get_jupiter_portfolio_platforms`
86
+ - `get_jupiter_portfolio`
87
+ - `get_jupiter_staked_jup`
88
+
89
+ The signing tool still requires explicit `user_confirmed=true`.
90
+ 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`.
91
+
92
+ Policy defaults:
93
+
94
+ - read-only tools are always allowed
95
+ - `prepare` requires `user_intent=true`
96
+ - `prepare` does not return signed transaction bytes
97
+ - `execute` requires a host-issued `approval_token` bound to the exact previewed operation
98
+ - on mainnet networks, that `approval_token` must include explicit mainnet confirmation
99
+ - on mainnet networks, preview and prepare responses include a `confirmation_summary` and `mainnet_warning` to force a clearer final confirmation step
100
+
101
+ ## Install
102
+
103
+ ```bash
104
+ cd agent-wallet
105
+ pip install -e .
106
+ ```
107
+
108
+ If you want a simpler local setup flow, use the installer:
109
+
110
+ ```bash
111
+ sh ../setup.sh
112
+ ```
113
+
114
+ If you already use a local coding agent on the same machine, it can run this installer for you. You can simply ask the agent to install the wallet, and it can perform the file setup, Python setup, and OpenClaw config patching steps automatically.
115
+
116
+ By default it will:
117
+
118
+ - create `.env` from `.env.example` if missing
119
+ - create `.venv` and install `agent-wallet` into it
120
+ - install Node dependencies for `wdk-btc-wallet` and `wdk-evm-wallet`
121
+ - create a minimal `~/.openclaw/openclaw.json` if needed
122
+ - run `install_openclaw_local_config.py` automatically when the required secret env vars are already present
123
+ - otherwise return a JSON summary with `pending_env` and the exact next configure command
124
+
125
+ For a future `curl | bash` entrypoint, the repo now also includes a remote bootstrap wrapper at [`install-from-github.sh`](/Users/yuriytsygankov/Documents/openclaw_skill/install-from-github.sh). That script resolves the newest matching release bundle asset from GitHub Release metadata, downloads it, and then delegates to `setup.sh`.
126
+
127
+ For release assets, use the bundle builder:
128
+
129
+ ```bash
130
+ python3 agent-wallet/scripts/build_release_bundle.py
131
+ ```
132
+
133
+ That produces a release tarball with a broad runtime/backend slice of the repo while excluding the marketing site, docs site, local notes, and generated/dev artifacts.
134
+
135
+ The boundary stays the same: the operator must still provide the root secrets. The installer may be executed by an agent, but `AGENT_WALLET_BOOT_KEY`, `AGENT_WALLET_MASTER_KEY`, and `AGENT_WALLET_APPROVAL_SECRET` should be created or chosen by the user and then supplied to the runtime environment.
136
+
137
+ For a no-network or pre-existing Python setup, add:
138
+
139
+ ```bash
140
+ python3 scripts/install_agent_wallet.py --skip-python-setup --skip-node-setup
141
+ ```
142
+
143
+ ## Configuration
144
+
145
+ Copy `.env.example` to `.env` and choose one of two modes:
146
+
147
+ 1. Read-only:
148
+ set `SOLANA_AGENT_PUBLIC_KEY`
149
+
150
+ 2. Signing:
151
+ set `SOLANA_AGENT_PRIVATE_KEY` or `SOLANA_AGENT_KEYPAIR_PATH`
152
+
153
+ For production `mainnet`, prefer a dedicated RPC instead of the public Solana endpoint. You can now configure either:
154
+
155
+ - `SOLANA_RPC_URL` for one primary endpoint
156
+ - `SOLANA_RPC_URLS` as a comma-separated ordered failover list
157
+ - or just `ALCHEMY_API_KEY` / `HELIUS_API_KEY`, which auto-derive a primary Solana RPC for `mainnet` or `devnet`
158
+
159
+ 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.
160
+
161
+ For OpenClaw onboarding, `agent-wallet` now ships with a hosted default provider gateway:
162
+
163
+ - `https://agent-layer-production.up.railway.app`
164
+
165
+ 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.
166
+
167
+ That same provider gateway path can now also cover Jupiter Earn reads and transaction-building. Ordinary Jupiter swap routing remains direct.
168
+
169
+ For a self-hosted install where each operator brings their own RPC key, a minimal Solana setup can be just:
170
+
171
+ ```bash
172
+ AGENT_WALLET_BOOT_KEY=...
173
+ ALCHEMY_API_KEY=...
174
+ # or
175
+ HELIUS_API_KEY=...
176
+ ```
177
+
178
+ `AGENT_WALLET_BOOT_KEY` is the root local secret for the wallet runtime. It is not a wallet private key, not a Solana keypair, and not something provided by this repository or by OpenClaw. The operator must generate it locally and keep it safe.
179
+
180
+ What it is used for:
181
+
182
+ - unlocking `~/.openclaw/sealed_keys.json`
183
+ - decrypting the stored `master_key`, `approval_secret`, and optional signer `private_key`
184
+ - allowing the runtime to start without placing those secrets directly in plain environment variables
185
+
186
+ What it is not:
187
+
188
+ - not the on-chain wallet address
189
+ - not the Solana signing key
190
+ - not a key that should be committed to GitHub
191
+ - not something the agent should silently invent and hide from the operator
192
+
193
+ Recommended generation:
194
+
195
+ ```bash
196
+ openssl rand -base64 32
197
+ ```
198
+
199
+ Alternative:
200
+
201
+ ```bash
202
+ python3 -c "import secrets; print(secrets.token_urlsafe(32))"
203
+ ```
204
+
205
+ Recommended handling:
206
+
207
+ - store it in a password manager or local secret store
208
+ - export it locally in shell env or deployment env
209
+ - keep a backup, because losing it means the existing `sealed_keys.json` bundle can no longer be decrypted
210
+
211
+ Example:
212
+
213
+ ```bash
214
+ export AGENT_WALLET_BOOT_KEY='paste-generated-secret-here'
215
+ ```
216
+
217
+ In that mode, `agent-wallet` will auto-resolve:
218
+
219
+ - `mainnet` -> `https://solana-mainnet.g.alchemy.com/v2/<ALCHEMY_API_KEY>`
220
+ - `devnet` -> `https://solana-devnet.g.alchemy.com/v2/<ALCHEMY_API_KEY>`
221
+ - `mainnet` -> `https://mainnet.helius-rpc.com/?api-key=<HELIUS_API_KEY>`
222
+ - `devnet` -> `https://devnet.helius-rpc.com/?api-key=<HELIUS_API_KEY>`
223
+
224
+ and still append the official Solana endpoint as fallback.
225
+
226
+ For OpenClaw self-hosting, this means users can keep their own Alchemy/Helius key locally in `.env` or shell env. Nothing needs to be proxied or hosted by us.
227
+
228
+ For OpenClaw install/runtime, the intended creation flow is:
229
+
230
+ 1. OpenClaw plugin config sets `backend=solana_local`
231
+ 2. Optional: set `network=devnet`
232
+ 3. Optional: set `autoCreateWallet=true`
233
+ 4. On first startup, if no keypair exists and auto-create is enabled, the plugin creates a local wallet file under `~/.openclaw/wallets/`
234
+
235
+ For multi-user OpenClaw integration, use `agent_wallet.user_wallets.create_wallet_backend_for_user(user_id)`.
236
+ That provisions a wallet per user under:
237
+ `~/.openclaw/users/<normalized-user-id>/wallets/solana-<network>-agent.json`
238
+
239
+ For the local BTC backend (`backend=wdk_btc_local`), the host-side lifecycle now follows the same pattern:
240
+
241
+ - the local `wdk-btc-wallet` service holds the encrypted seed vault
242
+ - the BTC service is localhost-only and no longer accepts remote service URLs through the OpenClaw BTC flow
243
+ - `agent-wallet` talks to it through a local bearer token loaded from `~/.openclaw/wdk-btc-wallet/local-auth-token`
244
+ - `agent-wallet` stores only a per-user BTC wallet binding under `~/.openclaw/users/<normalized-user-id>/wallets/btc-<network>-agent.json`
245
+ - you can manage that binding through `agent_wallet.openclaw_cli`:
246
+ - `btc-wallet-create`
247
+ - `btc-wallet-import`
248
+ - `btc-wallet-get`
249
+ - `btc-wallet-unlock`
250
+ - `btc-wallet-lock`
251
+ - or more conveniently through `scripts/manage_openclaw_btc_wallet.py`
252
+
253
+ Example host-side BTC wallet creation:
254
+
255
+ ```bash
256
+ printf '%s\n' 'your-local-btc-password' | \
257
+ python -m agent_wallet.openclaw_cli btc-wallet-create \
258
+ --user-id alice@example.com \
259
+ --password-stdin \
260
+ --config-json '{"backend":"wdk_btc_local","network":"testnet","wdkBtcServiceUrl":"http://127.0.0.1:8080"}'
261
+ ```
262
+
263
+ If you want a friendlier host-shell flow, use:
264
+
265
+ ```bash
266
+ python scripts/manage_openclaw_btc_wallet.py setup \
267
+ --user-id alice@example.com \
268
+ --network testnet \
269
+ --service-url http://127.0.0.1:8080
270
+ ```
271
+
272
+ `setup` is the easiest host path:
273
+
274
+ - if no BTC wallet binding exists for that `user_id`, it creates one
275
+ - if the binding already exists, it unlocks the existing wallet
276
+ - it returns an `openclaw_config_hint` payload you can paste into plugin config if needed
277
+
278
+ If you want a true one-command OpenClaw bootstrap, use:
279
+
280
+ ```bash
281
+ python agent-wallet/scripts/bootstrap_openclaw_btc.py \
282
+ --user-id alice@example.com \
283
+ --network testnet \
284
+ --service-url http://127.0.0.1:8080
285
+ ```
286
+
287
+ For BTC mainnet, use the same bootstrap with `--network mainnet`. The script normalizes that to `bitcoin` in plugin config automatically.
288
+
289
+ For the simplest host-side UX, use the shell wrapper instead:
290
+
291
+ ```bash
292
+ sh agent-wallet/scripts/setup_btc_wallet.sh
293
+ ```
294
+
295
+ That is the intended "agent/host installs, user only enters password" entrypoint:
296
+
297
+ - the script wraps the full BTC bootstrap
298
+ - it auto-starts the local `wdk-btc-wallet` service for localhost URLs if needed
299
+ - it asks for `user-id` and shows a small `mainnet / testnet / regtest` menu if you did not pass them as args or env
300
+ - it prompts for the BTC wallet password interactively unless you explicitly pass `--password-stdin`
301
+ - it prefers `/tmp/agent-wallet-venv/bin/python`, then `agent-wallet/.venv/bin/python`, and only then falls back to system `python3`
302
+ - it creates or unlocks the BTC wallet binding and patches local OpenClaw config in one pass
303
+ - it relies on the local auth token generated by `wdk-btc-wallet`; you do not need to paste that token into OpenClaw config
304
+
305
+ Useful optional env defaults:
306
+
307
+ ```bash
308
+ export OPENCLAW_BTC_USER_ID=alice@example.com
309
+ export OPENCLAW_BTC_NETWORK=mainnet
310
+ export OPENCLAW_BTC_SERVICE_URL=http://127.0.0.1:8080
311
+ ```
312
+
313
+ Then the wrapper can run with no arguments at all.
314
+
315
+ That script:
316
+
317
+ - runs BTC wallet `setup`
318
+ - checks `wdk-btc-wallet /health`
319
+ - auto-starts the local `wdk-btc-wallet` service if `--service-url` points to `127.0.0.1` or `localhost` and the service is not already running
320
+ - creates or updates `~/.openclaw/openclaw.json`
321
+ - configures `backend=wdk_btc_local`
322
+ - writes the local BTC service URL into plugin config
323
+ - keeps the local bearer token out of plugin config JSON
324
+
325
+ If your local `wdk-btc-wallet` repo lives somewhere else, pass:
326
+
327
+ ```bash
328
+ --wdk-wallet-root /absolute/path/to/wdk-btc-wallet
329
+ ```
330
+
331
+ To reveal the seed phrase later as the user/host:
332
+
333
+ ```bash
334
+ sh agent-wallet/scripts/reveal_btc_seed.sh
335
+ ```
336
+
337
+ That wrapper also prompts for `user-id` and network if you do not pass them explicitly.
338
+
339
+ This remains host-only. The agent does not get a seed-reveal tool.
340
+
341
+ After that, `onboard` and `invoke` can use the bound BTC wallet by `user_id` without manually passing `wdkBtcWalletId` every time.
342
+
343
+ For the local EVM backend (`backend=wdk_evm_local`), the lifecycle mirrors the BTC path:
344
+
345
+ - the local `wdk-evm-wallet` service holds the encrypted seed vault
346
+ - the EVM service is localhost-only and no longer accepts remote service URLs through the OpenClaw EVM flow
347
+ - `agent-wallet` talks to it through a local bearer token loaded from `~/.openclaw/wdk-evm-wallet/local-auth-token`
348
+ - `agent-wallet` stores only a per-user EVM wallet binding under `~/.openclaw/users/<normalized-user-id>/wallets/evm-<network>-agent.json`
349
+ - supported EVM networks are `ethereum`, `sepolia`, `base`, and `base-sepolia`
350
+ - OpenClaw-facing EVM tools accept an optional per-call `network` override for `ethereum` or `base`, so the agent can switch between the two mainnet EVM paths without editing host config
351
+ - EVM `get_wallet_balance` now returns an enriched portfolio-style payload with native balance, discovered ERC-20 balances, and USD values when token discovery and pricing are available
352
+ - if a requested EVM network binding is missing, `agent-wallet` auto-binds it from the same local wallet when there is exactly one reusable EVM wallet for that user or when `wdkEvmWalletId` is provided explicitly
353
+ - you can manage that binding through `agent_wallet.openclaw_cli`:
354
+ - `evm-wallet-create`
355
+ - `evm-wallet-import`
356
+ - `evm-wallet-get`
357
+ - `evm-wallet-unlock`
358
+ - `evm-wallet-lock`
359
+
360
+ Example host-side EVM wallet creation:
361
+
362
+ ```bash
363
+ printf '%s\n' 'your-local-evm-password' | \
364
+ python -m agent_wallet.openclaw_cli evm-wallet-create \
365
+ --user-id alice@example.com \
366
+ --password-stdin \
367
+ --config-json '{"backend":"wdk_evm_local","network":"sepolia","wdkEvmServiceUrl":"http://127.0.0.1:8081"}'
368
+ ```
369
+
370
+ After that, `onboard` and `invoke` can use the bound EVM wallet by `user_id` without manually passing `wdkEvmWalletId` every time.
371
+
372
+ Per-user wallets are now encrypted at rest in one hardened mode:
373
+
374
+ - runtime must have `AGENT_WALLET_BOOT_KEY`
375
+ - runtime secrets live only in `~/.openclaw/sealed_keys.json`
376
+ - per-user HKDF derivation is always on for `user_id + network`
377
+ - per-user wallet files are always encrypted
378
+ - `AGENT_WALLET_MIGRATE_PLAINTEXT_USER_WALLETS=true` controls whether legacy plaintext/global-master wallets are auto-migrated on load
379
+
380
+ Do not store `masterKey`, `privateKey`, or approval secrets in plugin config JSON or direct runtime environment variables.
381
+ `AGENT_WALLET_MASTER_KEY`, `AGENT_WALLET_APPROVAL_SECRET`, and `SOLANA_AGENT_PRIVATE_KEY` are now provisioning-only inputs for installer/admin scripts and are rejected by the runtime.
382
+ Create or update that sealed file with:
383
+
384
+ ```bash
385
+ AGENT_WALLET_BOOT_KEY=... \
386
+ AGENT_WALLET_MASTER_KEY=... \
387
+ AGENT_WALLET_APPROVAL_SECRET=... \
388
+ python scripts/install_openclaw_sealed_keys.py
389
+ ```
390
+
391
+ Add `SOLANA_AGENT_PRIVATE_KEY=...` as well if you want the local signer secret to live in the sealed bundle instead of plain env.
392
+ If you already run `python scripts/install_openclaw_local_config.py` with `AGENT_WALLET_BOOT_KEY` and one or more of those secret env vars set, the installer now creates or updates `sealed_keys.json` automatically in the same pass.
393
+
394
+ If a legacy plaintext per-user wallet already exists, the helper will migrate it in place on the next successful load when a sealed master key is available.
395
+ Existing encrypted wallets created under the old global master-key mode are also migrated in place on the next successful load.
396
+
397
+ Mainnet hardening:
398
+
399
+ - per-user wallets now pin the expected wallet address in a sidecar file
400
+ - if a pinned `mainnet` wallet file disappears, the runtime refuses to silently create a replacement wallet
401
+ - this reduces the risk of a user unknowingly switching to a fresh address and losing access to funds at the original address
402
+
403
+ Operational helpers for the host runtime are also available in `agent_wallet.user_wallets`:
404
+
405
+ - `get_user_wallet_storage_info(...)`
406
+ - `export_user_wallet_backup(...)`
407
+ - `rotate_user_wallet_encryption(...)`
408
+
409
+ These are service-level helpers for OpenClaw runtime/admin flows and are intentionally not exposed as agent tools.
410
+
411
+ Recommended host-side runtime flow:
412
+
413
+ 1. OpenClaw resolves the authenticated `user_id`
414
+ 2. Host runtime calls `onboard_openclaw_user_wallet(user_id, ...)`
415
+ 3. The helper provisions or loads the user wallet, builds the backend, adapter, and plugin bundle
416
+ 4. Host runtime stores `session_metadata()` and registers `serializable_bundle()["tools"]`
417
+ 5. Tool execution is delegated to `context.plugin_bundle["invoke"]`
418
+
419
+ This keeps wallet creation and custody in the host/runtime layer while the agent only sees the safe tool surface.
420
+
421
+ ## Network switching
422
+
423
+ The wallet backend is already network-scoped:
424
+
425
+ - `devnet` and `mainnet` use different wallet files
426
+ - per-user wallets are stored as `solana-<network>-agent.json`
427
+ - switching networks does not mix balances or stake accounts across clusters
428
+
429
+ For a local OpenClaw install, use:
430
+
431
+ ```bash
432
+ python agent-wallet/scripts/switch_openclaw_wallet_network.py --network devnet
433
+ python agent-wallet/scripts/switch_openclaw_wallet_network.py --network mainnet
434
+ ```
435
+
436
+ Useful flags:
437
+
438
+ - `--show-only` shows which wallet path will be used without changing config
439
+ - `--sign-only` or `--no-sign-only` updates the execution mode together with the network
440
+ - `--rpc-url` updates the local fallback RPC endpoint for the selected network
441
+
442
+ ## Jupiter coverage
443
+
444
+ Current Jupiter integration now includes:
445
+
446
+ - `Ultra Swap` as the default swap path, with legacy `Metis` fallback
447
+ - `Price API` token lookup
448
+ - `Earn` reads and deposit/withdraw transaction building
449
+
450
+ Operational notes:
451
+
452
+ - Jupiter `Earn` can use the hosted or self-hosted provider gateway for shared onboarding-friendly access.
453
+ - Ordinary Jupiter swap routing remains direct and does not go through the provider gateway.
454
+ - Jupiter `Portfolio` implementation remains in the backend, but the agent-facing tools are temporarily disabled.
455
+ - The Jupiter config fields and provider code are intentionally kept so these surfaces can be restored later without rebuilding the integration from scratch.
456
+
457
+ ## Native staking coverage
458
+
459
+ Current native Solana staking integration now includes:
460
+
461
+ - validator discovery via Solana `getVoteAccounts`
462
+ - stake account inspection with activation status
463
+ - native `stake SOL` flow via the Solana Stake Program
464
+ - native stake deactivation
465
+ - native stake withdraw
466
+
467
+ Operational notes:
468
+
469
+ - this path uses Solana RPC and the Stake Program directly, without third-party DeFi APIs
470
+ - stake creation allocates a new stake account controlled by the connected wallet as staker and withdrawer
471
+ - preview and prepare were live-checked on devnet against a real wallet context
472
+
473
+ ## Official OpenClaw plugin
474
+
475
+ For the official OpenClaw agent, the repository now includes a workspace extension at:
476
+
477
+ `.openclaw/extensions/agent-wallet`
478
+
479
+ That extension uses the documented OpenClaw plugin shape:
480
+
481
+ - `index.ts`
482
+ - `openclaw.plugin.json`
483
+ - `skills/wallet-operator/SKILL.md`
484
+
485
+ It forwards tool execution to the Python bridge CLI:
486
+
487
+ `python -m agent_wallet.openclaw_cli`
488
+
489
+ This keeps the official OpenClaw-facing layer in TypeScript while the actual wallet/security logic remains in the Python backend.
490
+
491
+ Public-safe helper scripts are available in `agent-wallet/scripts/`:
492
+
493
+ - `install_openclaw_local_config.py`
494
+ - `finalize_openclaw_local_wallet_config.py`
495
+
496
+ Both scripts now use generic defaults instead of hardcoded local usernames or paths. Sensitive secrets must be supplied via protected environment variables, not config JSON or CLI arguments.
497
+
498
+ Recommended devnet setup:
499
+
500
+ ```bash
501
+ AGENT_WALLET_BACKEND=solana_local
502
+ AGENT_WALLET_BOOT_KEY=change-this-in-production
503
+ SOLANA_NETWORK=devnet
504
+ SOLANA_RPC_URLS=https://api.devnet.solana.com
505
+ SOLANA_AUTO_CREATE_WALLET=true
506
+ AGENT_WALLET_SIGN_ONLY=false
507
+ ```
508
+
509
+ ## Current scope
510
+
511
+ - Solana balance lookup
512
+ - capability discovery
513
+ - message signing
514
+ - local keypair signer
515
+
516
+ The package now supports:
517
+
518
+ - transfer preview
519
+ - Jupiter token price lookup
520
+ - native SOL transfer execution
521
+ - native SOL staking preview, preparation, and execution
522
+ - native stake deactivation and withdraw flows
523
+ - SPL token transfer preview and execution by mint address
524
+ - Jupiter-based swap preview and execution on mainnet
525
+ - compact swap `fee_summary` in preview/prepare/execute, including known network fees and route fee bps when Jupiter provides them
526
+ - zero-balance token account cleanup
527
+ - devnet/testnet faucet airdrop
@@ -0,0 +1,11 @@
1
+ """OpenClaw agent wallet package."""
2
+
3
+ __all__ = [
4
+ "config",
5
+ "exceptions",
6
+ "models",
7
+ "openclaw_runtime",
8
+ "providers",
9
+ "validation",
10
+ "wallet_layer",
11
+ ]