@agentlayer.tech/wallet 0.1.23 → 0.1.25
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 +2 -2
- package/.openclaw/extensions/agent-wallet/dist/index.js +112 -93
- package/.openclaw/extensions/agent-wallet/index.ts +112 -93
- package/.openclaw/extensions/agent-wallet/package.json +1 -1
- package/CHANGELOG.md +9 -0
- package/README.md +25 -8
- package/agent-wallet/README.md +3 -2
- package/agent-wallet/agent_wallet/openclaw_adapter.py +0 -66
- package/agent-wallet/pyproject.toml +1 -1
- package/agent-wallet/scripts/install_openclaw_local_config.py +59 -5
- package/agent-wallet/skills/wallet-operator/SKILL.md +5 -5
- package/package.json +5 -3
- package/wdk-evm-wallet/package-lock.json +123 -309
- package/wdk-evm-wallet/package.json +10 -3
package/README.md
CHANGED
|
@@ -249,15 +249,19 @@ Lido:
|
|
|
249
249
|
|
|
250
250
|
Across these service-backed flows, read operations remain directly callable, while write operations stay behind preview, explicit intent, and host-issued approval tokens before execution.
|
|
251
251
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
Solana:
|
|
252
|
+
For the default Solana flow, run the installer directly:
|
|
255
253
|
|
|
256
254
|
```bash
|
|
257
|
-
|
|
258
|
-
export AGENT_WALLET_MASTER_KEY="$(openssl rand -base64 32)"
|
|
259
|
-
export AGENT_WALLET_APPROVAL_SECRET="$(openssl rand -base64 32)"
|
|
255
|
+
npx @agentlayer.tech/wallet install --yes
|
|
260
256
|
```
|
|
257
|
+
|
|
258
|
+
That installs the runtime, patches the OpenClaw plugin config, generates local
|
|
259
|
+
runtime secrets when missing, and creates the first encrypted per-user Solana
|
|
260
|
+
mainnet wallet. The agent receives the public address and guarded wallet tools,
|
|
261
|
+
not the private key.
|
|
262
|
+
|
|
263
|
+
BTC and EVM are separate host-side setup flows.
|
|
264
|
+
|
|
261
265
|
Bitcoin:
|
|
262
266
|
|
|
263
267
|
```bash
|
|
@@ -272,7 +276,17 @@ sh agent-wallet/scripts/setup_evm_wallet.sh
|
|
|
272
276
|
|
|
273
277
|
That host-side bootstrap can auto-start the local `wdk-evm-wallet` service, create or unlock the vault wallet, bind both `base` and `ethereum` for the same local user, and patch OpenClaw config to `backend=wdk_evm_local`.
|
|
274
278
|
|
|
275
|
-
|
|
279
|
+
Advanced operators can still supply their own runtime provisioning secrets
|
|
280
|
+
instead of using `--yes` auto-generation:
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
export AGENT_WALLET_BOOT_KEY="$(openssl rand -base64 32)"
|
|
284
|
+
export AGENT_WALLET_MASTER_KEY="$(openssl rand -base64 32)"
|
|
285
|
+
export AGENT_WALLET_APPROVAL_SECRET="$(openssl rand -base64 32)"
|
|
286
|
+
npx @agentlayer.tech/wallet install --no-auto-secrets
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
If you prefer Python instead of `openssl`:
|
|
276
290
|
|
|
277
291
|
```bash
|
|
278
292
|
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
|
|
@@ -284,7 +298,10 @@ Run it three times and assign the outputs to:
|
|
|
284
298
|
- `AGENT_WALLET_MASTER_KEY`
|
|
285
299
|
- `AGENT_WALLET_APPROVAL_SECRET`
|
|
286
300
|
|
|
287
|
-
|
|
301
|
+
These variables are provisioning inputs only. Runtime secrets are sealed into
|
|
302
|
+
`~/.openclaw/sealed_keys.json`; normal runtime execution should use
|
|
303
|
+
`AGENT_WALLET_BOOT_KEY` or `AGENT_WALLET_BOOT_KEY_FILE`, not direct
|
|
304
|
+
`AGENT_WALLET_MASTER_KEY` / `AGENT_WALLET_APPROVAL_SECRET` env loading.
|
|
288
305
|
|
|
289
306
|
## Connect the MCP server
|
|
290
307
|
|
package/agent-wallet/README.md
CHANGED
|
@@ -129,8 +129,9 @@ Policy defaults:
|
|
|
129
129
|
- read-only tools are always allowed
|
|
130
130
|
- `prepare` requires `user_intent=true`
|
|
131
131
|
- `prepare` does not return signed transaction bytes
|
|
132
|
-
- `execute` requires
|
|
133
|
-
-
|
|
132
|
+
- backend `execute` requires an internal authorization token bound to the exact previewed operation
|
|
133
|
+
- in OpenClaw, the extension handles that internal authorization automatically after the user explicitly confirms the shown summary in chat; do not ask OpenClaw users for `/approve`, buttons, popups, or a manual token
|
|
134
|
+
- on mainnet networks, that internal authorization must include explicit mainnet confirmation
|
|
134
135
|
- on mainnet networks, preview and prepare responses include a `confirmation_summary` and `mainnet_warning` to force a clearer final confirmation step
|
|
135
136
|
|
|
136
137
|
## Install
|
|
@@ -4428,19 +4428,6 @@ class OpenClawWalletAdapter:
|
|
|
4428
4428
|
raise WalletBackendError(
|
|
4429
4429
|
"approved preview payload does not match the approval token. Generate a new preview and approval before execute."
|
|
4430
4430
|
)
|
|
4431
|
-
preview_summary = self._build_confirmation_summary(
|
|
4432
|
-
action_label="Flash Trade open position",
|
|
4433
|
-
payload=approved_preview,
|
|
4434
|
-
)
|
|
4435
|
-
summary_without_digest = {
|
|
4436
|
-
key: value
|
|
4437
|
-
for key, value in approval_summary_copy.items()
|
|
4438
|
-
if key != "_preview_digest"
|
|
4439
|
-
}
|
|
4440
|
-
if preview_summary != summary_without_digest:
|
|
4441
|
-
raise WalletBackendError(
|
|
4442
|
-
"approved preview payload does not match the approval token. Generate a new preview and approval before execute."
|
|
4443
|
-
)
|
|
4444
4431
|
execute_preview = dict(approved_preview)
|
|
4445
4432
|
else:
|
|
4446
4433
|
execute_preview = await active_backend.preview_flash_trade_open_position(
|
|
@@ -4567,19 +4554,6 @@ class OpenClawWalletAdapter:
|
|
|
4567
4554
|
raise WalletBackendError(
|
|
4568
4555
|
"approved preview payload does not match the approval token. Generate a new preview and approval before execute."
|
|
4569
4556
|
)
|
|
4570
|
-
preview_summary = self._build_confirmation_summary(
|
|
4571
|
-
action_label="Flash Trade close position",
|
|
4572
|
-
payload=approved_preview,
|
|
4573
|
-
)
|
|
4574
|
-
summary_without_digest = {
|
|
4575
|
-
key: value
|
|
4576
|
-
for key, value in approval_summary_copy.items()
|
|
4577
|
-
if key != "_preview_digest"
|
|
4578
|
-
}
|
|
4579
|
-
if preview_summary != summary_without_digest:
|
|
4580
|
-
raise WalletBackendError(
|
|
4581
|
-
"approved preview payload does not match the approval token. Generate a new preview and approval before execute."
|
|
4582
|
-
)
|
|
4583
4557
|
execute_preview = dict(approved_preview)
|
|
4584
4558
|
else:
|
|
4585
4559
|
execute_preview = await active_backend.preview_flash_trade_close_position(
|
|
@@ -5376,19 +5350,6 @@ class OpenClawWalletAdapter:
|
|
|
5376
5350
|
raise WalletBackendError(
|
|
5377
5351
|
"approved preview payload does not match the approval token. Generate a new preview and approval before execute."
|
|
5378
5352
|
)
|
|
5379
|
-
preview_summary = self._build_confirmation_summary(
|
|
5380
|
-
action_label="Swap",
|
|
5381
|
-
payload=approved_preview,
|
|
5382
|
-
)
|
|
5383
|
-
summary_without_digest = {
|
|
5384
|
-
key: value
|
|
5385
|
-
for key, value in approval_summary_copy.items()
|
|
5386
|
-
if key != "_preview_digest"
|
|
5387
|
-
}
|
|
5388
|
-
if preview_summary != summary_without_digest:
|
|
5389
|
-
raise WalletBackendError(
|
|
5390
|
-
"approved preview payload does not match the approval token. Generate a new preview and approval before execute."
|
|
5391
|
-
)
|
|
5392
5353
|
execute_preview = dict(approved_preview)
|
|
5393
5354
|
else:
|
|
5394
5355
|
execute_preview = await self.backend.preview_swap(
|
|
@@ -5525,19 +5486,6 @@ class OpenClawWalletAdapter:
|
|
|
5525
5486
|
raise WalletBackendError(
|
|
5526
5487
|
"approved preview payload does not match the approval token. Generate a new preview and approval before execute."
|
|
5527
5488
|
)
|
|
5528
|
-
preview_summary = self._build_confirmation_summary(
|
|
5529
|
-
action_label="Solana private swap",
|
|
5530
|
-
payload=approved_preview,
|
|
5531
|
-
)
|
|
5532
|
-
summary_without_digest = {
|
|
5533
|
-
key: value
|
|
5534
|
-
for key, value in approval_summary_copy.items()
|
|
5535
|
-
if key != "_preview_digest"
|
|
5536
|
-
}
|
|
5537
|
-
if preview_summary != summary_without_digest:
|
|
5538
|
-
raise WalletBackendError(
|
|
5539
|
-
"approved preview payload does not match the approval token. Generate a new preview and approval before execute."
|
|
5540
|
-
)
|
|
5541
5489
|
execute_preview = dict(approved_preview)
|
|
5542
5490
|
|
|
5543
5491
|
self._require_execute_approval(
|
|
@@ -5593,20 +5541,6 @@ class OpenClawWalletAdapter:
|
|
|
5593
5541
|
raise WalletBackendError(
|
|
5594
5542
|
"approved preview payload does not match the approval token. Generate a new preview and approval before continue."
|
|
5595
5543
|
)
|
|
5596
|
-
preview_summary = self._build_confirmation_summary(
|
|
5597
|
-
action_label="Solana private swap",
|
|
5598
|
-
payload=approved_preview,
|
|
5599
|
-
)
|
|
5600
|
-
summary_without_digest = {
|
|
5601
|
-
key: value
|
|
5602
|
-
for key, value in approval_summary_copy.items()
|
|
5603
|
-
if key != "_preview_digest"
|
|
5604
|
-
}
|
|
5605
|
-
if preview_summary != summary_without_digest:
|
|
5606
|
-
raise WalletBackendError(
|
|
5607
|
-
"approved preview payload does not match the approval token. Generate a new preview and approval before continue."
|
|
5608
|
-
)
|
|
5609
|
-
|
|
5610
5544
|
self._require_execute_approval(
|
|
5611
5545
|
approval_token=approval_token,
|
|
5612
5546
|
tool_name="swap_solana_privately",
|
|
@@ -16,7 +16,7 @@ from agent_wallet.file_ops import atomic_write_text, chmod_if_exists
|
|
|
16
16
|
from agent_wallet.sealed_keys import resolve_sealed_keys_path, seal_keys, unseal_keys
|
|
17
17
|
from security_utils import write_redacted_backup
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
LEGACY_ALLOWLIST_TOOLS = [
|
|
20
20
|
"get_wallet_capabilities",
|
|
21
21
|
"get_wallet_address",
|
|
22
22
|
"get_wallet_balance",
|
|
@@ -57,6 +57,62 @@ X402_TOOLS = [
|
|
|
57
57
|
]
|
|
58
58
|
|
|
59
59
|
|
|
60
|
+
def _extract_tool_allowlist_from_manifest(manifest_path: Path) -> list[str]:
|
|
61
|
+
try:
|
|
62
|
+
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
|
|
63
|
+
except (FileNotFoundError, json.JSONDecodeError):
|
|
64
|
+
return []
|
|
65
|
+
|
|
66
|
+
tools = manifest.get("contracts", {}).get("tools", [])
|
|
67
|
+
if not isinstance(tools, list):
|
|
68
|
+
return []
|
|
69
|
+
|
|
70
|
+
allowlist: list[str] = []
|
|
71
|
+
for item in tools:
|
|
72
|
+
tool_name = str(item).strip()
|
|
73
|
+
if tool_name and tool_name not in allowlist:
|
|
74
|
+
allowlist.append(tool_name)
|
|
75
|
+
return allowlist
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _load_extension_tool_allowlist(extension_path: Path) -> list[str]:
|
|
79
|
+
manifest_candidates = [
|
|
80
|
+
extension_path / "openclaw.plugin.json",
|
|
81
|
+
_repo_root() / ".openclaw" / "extensions" / "agent-wallet" / "openclaw.plugin.json",
|
|
82
|
+
]
|
|
83
|
+
for manifest_path in manifest_candidates:
|
|
84
|
+
allowlist = _extract_tool_allowlist_from_manifest(manifest_path)
|
|
85
|
+
if allowlist:
|
|
86
|
+
return allowlist
|
|
87
|
+
return LEGACY_ALLOWLIST_TOOLS + X402_TOOLS
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _is_agent_wallet_extension_path(value: object) -> bool:
|
|
91
|
+
return "extensions/agent-wallet" in str(value).replace("\\", "/")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _normalize_load_paths(paths: list[object], extension_path_text: str) -> list[str]:
|
|
95
|
+
normalized: list[str] = []
|
|
96
|
+
seen: set[str] = set()
|
|
97
|
+
|
|
98
|
+
for item in paths:
|
|
99
|
+
item_text = str(item).strip()
|
|
100
|
+
if not item_text:
|
|
101
|
+
continue
|
|
102
|
+
if "extensions/pay-bridge" in item_text:
|
|
103
|
+
continue
|
|
104
|
+
if _is_agent_wallet_extension_path(item_text) and item_text != extension_path_text:
|
|
105
|
+
continue
|
|
106
|
+
if item_text in seen:
|
|
107
|
+
continue
|
|
108
|
+
normalized.append(item_text)
|
|
109
|
+
seen.add(item_text)
|
|
110
|
+
|
|
111
|
+
if extension_path_text not in seen:
|
|
112
|
+
normalized.append(extension_path_text)
|
|
113
|
+
return normalized
|
|
114
|
+
|
|
115
|
+
|
|
60
116
|
def _default_config_path() -> Path:
|
|
61
117
|
return Path(os.path.expanduser("~/.openclaw/openclaw.json"))
|
|
62
118
|
|
|
@@ -239,9 +295,7 @@ def main() -> None:
|
|
|
239
295
|
load = plugins.setdefault("load", {})
|
|
240
296
|
paths = load.setdefault("paths", [])
|
|
241
297
|
extension_path_text = str(Path(args.extension_path).expanduser().resolve())
|
|
242
|
-
|
|
243
|
-
paths.append(extension_path_text)
|
|
244
|
-
paths[:] = [item for item in paths if "extensions/pay-bridge" not in str(item)]
|
|
298
|
+
paths[:] = _normalize_load_paths(list(paths), extension_path_text)
|
|
245
299
|
|
|
246
300
|
entries = plugins.setdefault("entries", {})
|
|
247
301
|
effective_network = _normalize_network(args.backend, args.network)
|
|
@@ -306,7 +360,7 @@ def main() -> None:
|
|
|
306
360
|
"pay_api_request",
|
|
307
361
|
}
|
|
308
362
|
also_allow[:] = [tool_name for tool_name in also_allow if tool_name not in removed_pay_tools]
|
|
309
|
-
for tool_name in
|
|
363
|
+
for tool_name in _load_extension_tool_allowlist(Path(extension_path_text)):
|
|
310
364
|
if tool_name not in also_allow:
|
|
311
365
|
also_allow.append(tool_name)
|
|
312
366
|
|
|
@@ -5,16 +5,16 @@ description: Use when operating OpenClaw wallet tools: balances, transfers, swap
|
|
|
5
5
|
|
|
6
6
|
# Wallet Operator
|
|
7
7
|
|
|
8
|
-
Use this skill before calling OpenClaw wallet tools. It is the routing guide for wallet commands, providers, units, and
|
|
8
|
+
Use this skill before calling OpenClaw wallet tools. It is the routing guide for wallet commands, providers, units, and confirmation flow.
|
|
9
9
|
|
|
10
10
|
## Core Rules
|
|
11
11
|
|
|
12
12
|
1. Start with `get_wallet_capabilities` when the active chain, signing support, or available tools are unclear.
|
|
13
13
|
2. Use `get_wallet_address` before asking for deposits or confirming a recipient/source wallet.
|
|
14
14
|
3. Use `get_wallet_balance` before spending, swapping, bridging, staking, lending, or claiming.
|
|
15
|
-
4. Use `preview` first for every write action. Use `prepare` only after explicit user intent.
|
|
15
|
+
4. Use `preview` first for every write action. Use `prepare` only after explicit user intent. In OpenClaw, use `execute` only after the user explicitly confirms the shown summary in chat; do not ask the user for `/approve`, buttons, popups, or a manual token.
|
|
16
16
|
5. `prepare` returns an execution plan only; it must not return signed transaction bytes.
|
|
17
|
-
6. On mainnet, `execute
|
|
17
|
+
6. On mainnet, restate the network and material terms before `execute`; the OpenClaw plugin handles the internal execution authorization after chat confirmation.
|
|
18
18
|
7. If backend is `sign_only`, do not execute; use `prepare` and state that nothing was broadcast.
|
|
19
19
|
8. Never claim a transfer, swap, bridge, stake, claim, deposit, borrow, repay, or withdrawal happened unless the tool result says it was broadcast/confirmed.
|
|
20
20
|
9. Do not use Mayan. Direct Mayan paths were removed. Cross-chain swaps must go through LI.FI with Mayan denied.
|
|
@@ -63,7 +63,7 @@ Use this skill before calling OpenClaw wallet tools. It is the routing guide for
|
|
|
63
63
|
## Transfer Commands
|
|
64
64
|
|
|
65
65
|
- SOL transfer: `transfer_sol`
|
|
66
|
-
- Params: `recipient`, `amount` in SOL UI units, `mode`, `purpose`, optional `user_intent
|
|
66
|
+
- Params: `recipient`, `amount` in SOL UI units, `mode`, `purpose`, optional `user_intent`.
|
|
67
67
|
- SPL transfer: `transfer_spl_token`
|
|
68
68
|
- Params: `recipient`, `mint`, `amount` in UI units, optional `decimals`, `mode`, `purpose`.
|
|
69
69
|
- EVM native transfer: `transfer_evm_native`
|
|
@@ -118,7 +118,7 @@ Use this skill before calling OpenClaw wallet tools. It is the routing guide for
|
|
|
118
118
|
1. Call the write tool with `mode=preview` and a concrete `purpose`.
|
|
119
119
|
2. Show the user the important fields: chain, token, amount, destination, provider, estimated output/minimum output, fees, and route/tool when present.
|
|
120
120
|
3. For `prepare`, call same tool with `mode=prepare`, same params, `user_intent=true`.
|
|
121
|
-
4. For `execute`, use the same semantic params
|
|
121
|
+
4. For `execute`, use the same semantic params after the user's chat confirmation. Do not mutate amount, token, destination, network, slippage, or minimum output between preview and execute; do not ask the user for a token or out-of-chat approval action.
|
|
122
122
|
5. For cross-chain swaps, after execute, offer `get_lifi_transfer_status` using the source tx hash and bridge/tool if returned.
|
|
123
123
|
|
|
124
124
|
## Disabled Or Avoided Paths
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentlayer.tech/wallet",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.25",
|
|
4
4
|
"description": "NPM installer for the OpenClaw Agent Wallet local runtime.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
"url": "https://github.com/lopushok9/Agent-Layer/issues"
|
|
12
12
|
},
|
|
13
13
|
"homepage": "https://github.com/lopushok9/Agent-Layer#readme",
|
|
14
|
-
"bin":
|
|
14
|
+
"bin": {
|
|
15
|
+
"wallet": "./bin/openclaw-agent-wallet.mjs"
|
|
16
|
+
},
|
|
15
17
|
"scripts": {
|
|
16
18
|
"check": "node --check bin/openclaw-agent-wallet.mjs",
|
|
17
19
|
"build:openclaw-plugins": "node scripts/manage_openclaw_plugin_packages.mjs build",
|
|
@@ -72,4 +74,4 @@
|
|
|
72
74
|
"evm"
|
|
73
75
|
],
|
|
74
76
|
"license": "SEE LICENSE IN LICENSE"
|
|
75
|
-
}
|
|
77
|
+
}
|