@agentlayer.tech/wallet 0.1.24 → 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.
@@ -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",
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "openclaw-agent-wallet"
7
- version = "0.1.24"
7
+ version = "0.1.25"
8
8
  description = "Plugin-friendly wallet backend for OpenClaw agents"
9
9
  requires-python = ">=3.10"
10
10
  dependencies = [
@@ -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
- OPTIONAL_TOOLS = [
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
- if extension_path_text not in paths:
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 OPTIONAL_TOOLS + X402_TOOLS:
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 approval flow.
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. Use `execute` only with a host-issued `approval_token`.
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` requires approval that includes explicit mainnet confirmation.
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`, `approval_token`.
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 and pass the `approval_token`. Do not mutate amount, token, destination, network, slippage, or minimum output between preview and execute.
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.24",
3
+ "version": "0.1.25",
4
4
  "description": "NPM installer for the OpenClaw Agent Wallet local runtime.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -74,4 +74,4 @@
74
74
  "evm"
75
75
  ],
76
76
  "license": "SEE LICENSE IN LICENSE"
77
- }
77
+ }