@agentlayer.tech/wallet 0.1.64 → 0.1.66

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.
@@ -52,13 +52,27 @@ def resolve_user_wallet_path(user_id: str, network: str | None = None) -> Path:
52
52
  return user_dir / f"solana-{effective_network}-agent.json"
53
53
 
54
54
 
55
- def _user_wallet_metadata(user_id: str, address: str, network: str | None = None) -> dict[str, str]:
55
+ def _user_wallet_metadata(
56
+ user_id: str,
57
+ address: str,
58
+ network: str | None = None,
59
+ key_scope: str | None = None,
60
+ ) -> dict[str, str]:
56
61
  effective_network = normalize_solana_network(network or settings.solana_network)
57
- return {
62
+ metadata = {
58
63
  "address": address,
59
64
  "user_id": user_id,
60
65
  "network": effective_network,
61
66
  }
67
+ # Record which master-key scope encrypted this envelope so the loader can
68
+ # try the matching candidate first instead of paying a wasted KDF on the
69
+ # wrong one. Writes through _resolve_user_wallet_master_key follow
70
+ # use_per_user_key_derivation(), so that is the accurate default.
71
+ effective_scope = key_scope or (
72
+ "per-user-derived" if use_per_user_key_derivation() else "global-master"
73
+ )
74
+ metadata["key_scope"] = effective_scope
75
+ return metadata
62
76
 
63
77
 
64
78
  def _resolve_effective_network(network: str | None = None) -> str:
@@ -126,12 +140,25 @@ def _load_user_wallet_secret_material(
126
140
  if not is_encrypted_wallet_payload(raw_text):
127
141
  return raw_text, "plaintext", None
128
142
 
129
- last_exc: WalletBackendError | None = None
130
- for key_scope, candidate in _candidate_user_wallet_master_keys(
143
+ candidates = _candidate_user_wallet_master_keys(
131
144
  user_id,
132
145
  network,
133
146
  raw_master_key=raw_master_key,
134
- ):
147
+ )
148
+ # Try the scope recorded at encryption time first: a mismatched candidate
149
+ # costs a full (failed) KDF before the right one is attempted. Files
150
+ # without the marker keep the legacy order.
151
+ try:
152
+ import json as _json
153
+
154
+ recorded_scope = (_json.loads(raw_text).get("metadata") or {}).get("key_scope")
155
+ except Exception:
156
+ recorded_scope = None
157
+ if isinstance(recorded_scope, str) and recorded_scope:
158
+ candidates.sort(key=lambda item: item[0] != recorded_scope)
159
+
160
+ last_exc: WalletBackendError | None = None
161
+ for key_scope, candidate in candidates:
135
162
  try:
136
163
  return (
137
164
  decrypt_secret_material(raw_text, master_key=candidate),
@@ -147,6 +174,58 @@ def _load_user_wallet_secret_material(
147
174
  )
148
175
 
149
176
 
177
+ def _maybe_migrate_wallet_envelope_kdf(
178
+ path: Path,
179
+ secret_material: str,
180
+ *,
181
+ user_id: str,
182
+ network: str,
183
+ key_scope: str | None,
184
+ address: str,
185
+ ) -> None:
186
+ """Lazily rewrite an argon2id wallet envelope as hkdf-sha256.
187
+
188
+ Re-encrypts with the SAME key scope that just decrypted the file, so this
189
+ never performs a scope migration through the back door. Best-effort: any
190
+ failure leaves the (still readable) argon2id file untouched. Kill switch:
191
+ AGENT_WALLET_ENVELOPE_KDF_MIGRATION=0.
192
+ """
193
+ from agent_wallet.config import envelope_kdf_migration_enabled
194
+ from agent_wallet.encrypted_storage import (
195
+ KDF_ARGON2ID,
196
+ _default_write_kdf,
197
+ envelope_kdf,
198
+ )
199
+
200
+ try:
201
+ if not envelope_kdf_migration_enabled():
202
+ return
203
+ if _default_write_kdf() == KDF_ARGON2ID:
204
+ return # forced-argon2id installs must not rewrite in place forever
205
+ if key_scope not in {"per-user-derived", "global-master"}:
206
+ return
207
+ if envelope_kdf(path.read_text(encoding="utf-8")) != KDF_ARGON2ID:
208
+ return
209
+ if key_scope == "per-user-derived":
210
+ master_key = _derive_user_scoped_key(
211
+ resolve_wallet_master_key(), user_id=user_id, network=network
212
+ )
213
+ else:
214
+ master_key = resolve_wallet_master_key()
215
+ if not master_key.strip():
216
+ return
217
+ write_encrypted_wallet_file(
218
+ path,
219
+ secret_material,
220
+ master_key=master_key,
221
+ metadata=_user_wallet_metadata(
222
+ user_id, address, network=network, key_scope=key_scope
223
+ ),
224
+ )
225
+ except Exception:
226
+ pass
227
+
228
+
150
229
  def ensure_user_solana_wallet(
151
230
  user_id: str,
152
231
  network: str | None = None,
@@ -206,6 +285,15 @@ def ensure_user_solana_wallet(
206
285
  metadata=_user_wallet_metadata(user_id, signer.address, network=effective_network),
207
286
  )
208
287
  key_scope = "per-user-derived"
288
+ elif storage_format == "encrypted":
289
+ _maybe_migrate_wallet_envelope_kdf(
290
+ path,
291
+ secret_material,
292
+ user_id=user_id,
293
+ network=effective_network,
294
+ key_scope=key_scope,
295
+ address=signer.address,
296
+ )
209
297
  return {
210
298
  "user_id": user_id,
211
299
  "address": signer.address,
@@ -2,7 +2,7 @@
2
2
  "id": "agent-wallet",
3
3
  "name": "Agent Wallet",
4
4
  "description": "Plugin-friendly wallet backend for OpenClaw agents with safe wallet tools and runtime instructions across Solana, local BTC, and local EVM.",
5
- "version": "0.1.64",
5
+ "version": "0.1.66",
6
6
  "skills": ["skills/wallet-operator"],
7
7
  "configSchema": {
8
8
  "type": "object",
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "openclaw-agent-wallet"
7
- version = "0.1.64"
7
+ version = "0.1.66"
8
8
  description = "Plugin-friendly wallet backend for OpenClaw agents"
9
9
  requires-python = ">=3.10"
10
10
  dependencies = [
@@ -19,15 +19,23 @@ INCLUDED_ROOT_FILES = [
19
19
  "LICENSE",
20
20
  "README.md",
21
21
  "RELEASING.md",
22
+ "VERSION",
22
23
  "install-from-github.sh",
23
24
  "requirements.txt",
24
25
  "setup.sh",
25
26
  ]
27
+ # Must cover every setup.sh require_path and mirror the npm package `files`
28
+ # allowlist (RELEASING.md "What Ships") — the bundle is the same runtime users
29
+ # get from npx, just delivered as a GitHub Release asset.
26
30
  INCLUDED_TOP_LEVEL_DIRS = [
27
- "codex",
31
+ ".claude-plugin",
28
32
  ".openclaw",
29
- "agent-a2a-gateway",
30
33
  "agent-wallet",
34
+ "bin",
35
+ "claude-code",
36
+ "codex",
37
+ "hermes",
38
+ "scripts",
31
39
  "wdk-btc-wallet",
32
40
  "wdk-evm-wallet",
33
41
  ]
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: wallet-operator
3
- description: Use when operating OpenClaw wallet tools: balances, transfers, swaps, LI.FI cross-chain swaps, Jupiter swaps, Velora EVM swaps, BTC transfers, staking, Kamino lending, Bags launches, and wallet execution safety.
3
+ description: Use whenever the user's own funds are involved, even if they never say "wallet": balances, portfolio, transfers, swaps, LI.FI cross-chain swaps, Jupiter swaps, Velora EVM swaps, BTC transfers, staking, Kamino lending, Bags launches, and wallet execution safety.
4
4
  ---
5
5
 
6
6
  # Wallet Operator
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agent-wallet",
3
3
  "displayName": "Agent Wallet",
4
- "version": "0.1.64",
4
+ "version": "0.1.66",
5
5
  "description": "Claude Code bridge for the existing AgentLayer wallet runtime. Connects to Solana, Bitcoin, and EVM wallets without creating a new one.",
6
6
  "author": {
7
7
  "name": "AgentLayer"
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Use when the user asks Claude Code to interact with the local AgentLayer wallet runtime: check balances, transfer tokens, swap, DeFi operations, or x402 payments. Prefer wallet tools over shell commands. Preview writes first and execute only after explicit user confirmation."
2
+ description: "Use whenever the user's own funds or wallet are involved — balances, portfolio, transfers, swaps, bridging, staking, lending, or x402 payments — even if the user never says \"wallet\". Trigger phrases include \"my balance\", \"how much SOL/ETH/BTC/USDC do I have\", \"send/transfer X to\", \"swap\", \"bridge\", \"stake\", \"my portfolio\", \"pay for this API\", \"x402\". Prefer agent-wallet MCP tools over shell commands, raw RPC, or crypto data servers. Preview writes first and execute only after explicit user confirmation."
3
3
  ---
4
4
 
5
5
  # Agent Wallet Operator
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-wallet",
3
- "version": "0.1.64",
3
+ "version": "0.1.66",
4
4
  "description": "Codex plugin bridge for the AgentLayer wallet runtime.",
5
5
  "author": {
6
6
  "name": "AgentLayer"
@@ -78,6 +78,9 @@ APPROVAL_CONTEXT_MISSING_MESSAGE = (
78
78
  "operation again, wait for explicit user confirmation, then retry execute. Do not ask the "
79
79
  "user for a manual approval token."
80
80
  )
81
+ # Tools served by the long-lived resident read worker instead of a cold CLI
82
+ # subprocess. Seeded with the legacy floor; _build_tool_definitions() extends
83
+ # it with every adapter-declared read-only tool at server start.
81
84
  RESIDENT_READ_ONLY_TOOLS = {
82
85
  "get_wallet_balance",
83
86
  "get_wallet_portfolio",
@@ -270,6 +273,44 @@ def _cache_preview_for_approval(user_id: str, tool_name: str, payload: dict[str,
270
273
  }
271
274
 
272
275
 
276
+ X402_PREVIEW_REUSE_TTL_SECONDS = 300
277
+
278
+
279
+ def _cache_x402_preview_payload(user_id: str, payload: dict[str, Any]) -> None:
280
+ """Cache a paid-endpoint preview so x402_pay_request can skip its unpaid probe.
281
+
282
+ x402 previews run on the read-only resident-worker path, so they never reach
283
+ _cache_preview_for_approval (and preview-mode annotation strips
284
+ confirmation_summary anyway). Stored under the x402_preview_request key that
285
+ the pay alias resolves to. The wallet runtime revalidates the payload by
286
+ request fingerprint and falls back to a fresh probe on any mismatch, so a
287
+ stale or unrelated cached preview can never redirect a payment.
288
+ """
289
+ if not isinstance(payload, dict) or payload.get("ok") is False:
290
+ return
291
+ data = payload.get("data")
292
+ if not isinstance(data, dict):
293
+ return
294
+ if not data.get("payment_required") or not str(data.get("request_fingerprint") or "").strip():
295
+ return
296
+ with _approval_cache_lock:
297
+ _prune_approval_preview_cache()
298
+ approval_preview_cache[_approval_cache_key(user_id, "x402_preview_request")] = {
299
+ "digest": _preview_digest(data),
300
+ "expires_at": time.time() + X402_PREVIEW_REUSE_TTL_SECONDS,
301
+ "preview": data,
302
+ "summary": None,
303
+ }
304
+
305
+
306
+ def _attach_x402_approved_preview(tool_name: str, effective_params: dict[str, Any]) -> None:
307
+ if tool_name != "x402_pay_request" or "_approved_preview" in effective_params:
308
+ return
309
+ cached = _latest_cached_preview(_user_id(), tool_name)
310
+ if cached and isinstance(cached.get("preview"), dict):
311
+ effective_params["_approved_preview"] = cached["preview"]
312
+
313
+
273
314
  def _latest_cached_preview(user_id: str, tool_name: str) -> dict[str, Any] | None:
274
315
  with _approval_cache_lock:
275
316
  _prune_approval_preview_cache()
@@ -622,20 +663,31 @@ def _call_wallet_cli(command: str, extra_args: list[str]) -> dict[str, Any]:
622
663
  raise WalletCliError(f"agent-wallet CLI returned invalid JSON: {exc}") from exc
623
664
 
624
665
 
625
- def _invoke_tool(tool_name: str, arguments: dict[str, Any], config: dict[str, Any]) -> dict[str, Any]:
626
- return _call_wallet_cli(
627
- "invoke",
628
- [
629
- "--user-id",
630
- _user_id(),
631
- "--tool",
632
- tool_name,
633
- "--arguments-json",
634
- json.dumps(arguments),
635
- "--config-json",
636
- json.dumps(config),
637
- ],
638
- )
666
+ def _invoke_tool(
667
+ tool_name: str,
668
+ arguments: dict[str, Any],
669
+ config: dict[str, Any],
670
+ *,
671
+ approval_summary: dict[str, Any] | None = None,
672
+ approval_mainnet_confirmed: bool = False,
673
+ ) -> dict[str, Any]:
674
+ extra_args = [
675
+ "--user-id",
676
+ _user_id(),
677
+ "--tool",
678
+ tool_name,
679
+ "--arguments-json",
680
+ json.dumps(arguments),
681
+ "--config-json",
682
+ json.dumps(config),
683
+ ]
684
+ if approval_summary is not None:
685
+ # The invoke subprocess mints the approval token itself, so an execute
686
+ # costs one cold start instead of two (issue-approval + invoke).
687
+ extra_args.extend(["--approval-summary-json", json.dumps(approval_summary)])
688
+ if approval_mainnet_confirmed:
689
+ extra_args.append("--approval-mainnet-confirmed")
690
+ return _call_wallet_cli("invoke", extra_args)
639
691
 
640
692
 
641
693
  class _ResidentReadWorker:
@@ -943,33 +995,16 @@ def _prewarm_resident_read_worker() -> None:
943
995
  ).start()
944
996
 
945
997
 
946
- def _issue_approval_token(
947
- tool_name: str,
948
- config: dict[str, Any],
949
- preview_payload: dict[str, Any],
950
- ) -> str:
998
+ def _approval_summary_for_preview(tool_name: str, preview_payload: dict[str, Any]) -> dict[str, Any]:
999
+ """Build the digest-bound confirmation summary the invoke subprocess will
1000
+ mint an approval token from (in-process, replacing the old standalone
1001
+ issue-approval subprocess round trip)."""
951
1002
  summary = preview_payload.get("confirmation_summary")
952
1003
  if not isinstance(summary, dict):
953
1004
  raise RuntimeError(f"No confirmation_summary available for {tool_name}.")
954
1005
  summary_for_token = dict(summary)
955
1006
  summary_for_token["_preview_digest"] = _preview_digest(preview_payload)
956
- extra_args = [
957
- "--user-id",
958
- _user_id(),
959
- "--tool",
960
- tool_name,
961
- "--summary-json",
962
- json.dumps(summary_for_token),
963
- "--config-json",
964
- json.dumps(config),
965
- ]
966
- if preview_payload.get("is_mainnet") is True:
967
- extra_args.append("--mainnet-confirmed")
968
- payload = _call_wallet_cli("issue-approval", extra_args)
969
- token = str(payload.get("approval_token") or "").strip()
970
- if not token:
971
- raise RuntimeError(f"issue-approval did not return an approval_token for {tool_name}.")
972
- return token
1007
+ return summary_for_token
973
1008
 
974
1009
 
975
1010
  def _invoke_resident_read_tool(tool_name: str, arguments: dict[str, Any], config: dict[str, Any]) -> dict[str, Any]:
@@ -1041,10 +1076,17 @@ def _attach_approval_for_execute(
1041
1076
  tool_name: str,
1042
1077
  config: dict[str, Any],
1043
1078
  effective_params: dict[str, Any],
1044
- ) -> dict[str, Any] | None:
1079
+ ) -> tuple[dict[str, Any] | None, dict[str, Any] | None]:
1080
+ """Prepare approval context for an execute call.
1081
+
1082
+ Returns ``(used_cache, approval_args)``: ``used_cache`` is the consumed
1083
+ bridge-managed preview (if any); ``approval_args`` carries the
1084
+ digest-bound summary the invoke subprocess mints its own token from,
1085
+ so no separate issue-approval subprocess is spawned.
1086
+ """
1045
1087
  mode = str(effective_params.get("mode") or "")
1046
1088
  if mode not in {"execute", "intent_execute"}:
1047
- return None
1089
+ return None, None
1048
1090
  if tool_name == "swap_solana_tokens" and mode == "execute":
1049
1091
  raise RuntimeError(
1050
1092
  "Legacy exact-preview execute is disabled for Solana Jupiter swaps in Codex. "
@@ -1053,19 +1095,22 @@ def _attach_approval_for_execute(
1053
1095
  cached = _latest_cached_preview(_user_id(), tool_name)
1054
1096
  if cached and isinstance(cached.get("preview"), dict):
1055
1097
  preview = cached["preview"]
1056
- effective_params["approval_token"] = _issue_approval_token(tool_name, config, preview)
1098
+ approval_args = {
1099
+ "summary": _approval_summary_for_preview(tool_name, preview),
1100
+ "mainnet_confirmed": preview.get("is_mainnet") is True,
1101
+ }
1057
1102
  if _requires_approved_preview_payload(tool_name, effective_params):
1058
1103
  effective_params["_approved_preview"] = preview
1059
- return cached
1104
+ return cached, approval_args
1060
1105
  approval_token = str(effective_params.get("approval_token") or "").strip()
1061
1106
  if approval_token and _requires_approved_preview_payload(tool_name, effective_params):
1062
1107
  cached_preview = _cached_preview_for_token(_user_id(), tool_name, approval_token)
1063
1108
  if cached_preview is not None and "_approved_preview" not in effective_params:
1064
1109
  effective_params["_approved_preview"] = cached_preview
1065
1110
  if effective_params.get("approval_token"):
1066
- return None
1111
+ return None, None
1067
1112
  if _should_let_backend_authorize_autonomous_execution(tool_name, effective_params, config):
1068
- return None
1113
+ return None, None
1069
1114
  raise RuntimeError(APPROVAL_CONTEXT_MISSING_MESSAGE)
1070
1115
 
1071
1116
 
@@ -1242,6 +1287,13 @@ def _build_tool_definitions() -> list[dict[str, Any]]:
1242
1287
  merged.setdefault(spec["name"], spec)
1243
1288
  for spec in merged.values():
1244
1289
  spec["input_schema"] = _sanitize_schema(spec["input_schema"])
1290
+ if spec.get("read_only") is True:
1291
+ # Route every adapter-declared read-only tool through the resident
1292
+ # read worker: reads then cost one warm request instead of a cold
1293
+ # interpreter boot + onboarding per call. The worker enforces the
1294
+ # same read_only contract on its side, and transport failures fall
1295
+ # back to the cold subprocess path.
1296
+ RESIDENT_READ_ONLY_TOOLS.add(spec["name"])
1245
1297
  if spec.get("read_only") is False:
1246
1298
  spec["description"] = (
1247
1299
  f"{spec['description']} Preview first when supported. Execute reuses cached "
@@ -1388,11 +1440,22 @@ def _invoke_wallet_tool_blocking(
1388
1440
  call never freezes the MCP server (tools/list, read-only calls, and
1389
1441
  cancellation stay responsive).
1390
1442
  """
1391
- used_cache = _attach_approval_for_execute(tool_name, config, effective_params)
1443
+ used_cache, approval_args = _attach_approval_for_execute(tool_name, config, effective_params)
1444
+ _attach_x402_approved_preview(tool_name, effective_params)
1392
1445
  try:
1393
- payload = _invoke_tool(tool_name, effective_params, config)
1446
+ payload = _invoke_tool(
1447
+ tool_name,
1448
+ effective_params,
1449
+ config,
1450
+ approval_summary=(approval_args or {}).get("summary"),
1451
+ approval_mainnet_confirmed=bool((approval_args or {}).get("mainnet_confirmed")),
1452
+ )
1394
1453
  except Exception as exc:
1395
1454
  raise _normalize_approval_context_error(exc) from exc
1455
+ if tool_name == "x402_pay_request":
1456
+ # The cached x402 preview quote is single-use: whether the payment
1457
+ # succeeded or the endpoint re-priced, the next pay must re-preview.
1458
+ _consume_cached_preview(_user_id(), tool_name)
1396
1459
  _cache_preview_for_approval(_user_id(), tool_name, payload)
1397
1460
  # A bridge-managed preview that was just executed successfully is single-use:
1398
1461
  # drop it so a duplicate execute cannot silently re-run the operation.
@@ -1431,15 +1494,21 @@ async def _handle_wallet_tool(tool_name: str, params: dict[str, Any]) -> dict[st
1431
1494
  _invoke_wallet_tool_blocking, tool_name, config, effective_params
1432
1495
  )
1433
1496
 
1497
+ if tool_name == "x402_preview_request":
1498
+ _cache_x402_preview_payload(_user_id(), payload)
1434
1499
  if payload.get("ok") is False:
1435
1500
  raise RuntimeError(str(payload.get("error") or f"{tool_name} failed"))
1436
1501
  return payload.get("data", {})
1437
1502
 
1438
1503
 
1439
1504
  BASE_INSTRUCTIONS = (
1440
- "Use the local AgentLayer wallet runtime through explicit wallet tools. Keep wallet "
1441
- "secrets local. Preview writes first when supported, and execute only after explicit "
1442
- "user confirmation."
1505
+ "This server is the user's own local AgentLayer wallet (Solana, EVM, Bitcoin). Use its "
1506
+ "tools whenever the user asks about their balances, portfolio, addresses, transfers, "
1507
+ "swaps, bridging, staking, lending, or x402 payments — even when they never say the "
1508
+ "word 'wallet'. For anything touching the user's own funds, prefer these tools over "
1509
+ "shell commands, raw RPC calls, or other crypto data servers (those are for arbitrary "
1510
+ "addresses and market data, not the user's wallet). Keep wallet secrets local. Preview "
1511
+ "writes first when supported, and execute only after explicit user confirmation."
1443
1512
  )
1444
1513
 
1445
1514
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: "wallet-operator"
3
- description: "Use when the user asks Codex to interact with the local AgentLayer wallet runtime. Prefer wallet tools over shell commands, preview writes first, and keep approval/signing semantics intact."
3
+ description: "Use whenever the user's own funds or wallet are involved — balances, portfolio, transfers, swaps, bridging, staking, lending, or x402 payments — even if the user never says \"wallet\". Trigger phrases include \"my balance\", \"how much SOL/ETH/BTC/USDC do I have\", \"send/transfer X to\", \"swap\", \"bridge\", \"stake\", \"my portfolio\". Prefer wallet tools over shell commands, preview writes first, and keep approval/signing semantics intact."
4
4
  ---
5
5
 
6
6
  # Agent Wallet Operator
@@ -1,5 +1,5 @@
1
1
  name: agent-wallet
2
- version: 0.1.64
2
+ version: 0.1.66
3
3
  description: Thin Hermes Agent bridge to the existing AgentLayer/OpenClaw wallet backend
4
4
  provides_tools:
5
5
  - agent_wallet_tools
@@ -120,9 +120,15 @@ if [ -z "$SOURCE_ROOT" ] || [ ! -d "$SOURCE_ROOT" ]; then
120
120
  exit 1
121
121
  fi
122
122
 
123
+ # Pre-flight must be a superset of setup.sh's require_path list: everything is
124
+ # checked on the EXTRACTED temp tree, before the destructive swap below. A
125
+ # bundle that would fail setup.sh must never replace the user's runtime.
123
126
  require_path "$SOURCE_ROOT/setup.sh" "local setup entrypoint"
124
127
  require_path "$SOURCE_ROOT/agent-wallet" "agent-wallet package"
128
+ require_path "$SOURCE_ROOT/agent-wallet/scripts/install_agent_wallet.py" "Python installer"
125
129
  require_path "$SOURCE_ROOT/.openclaw/extensions/agent-wallet" "OpenClaw extension"
130
+ require_path "$SOURCE_ROOT/codex/plugins/agent-wallet/.codex-plugin/plugin.json" "Codex plugin"
131
+ require_path "$SOURCE_ROOT/claude-code/plugins/agent-wallet/.claude-plugin/plugin.json" "Claude Code plugin"
126
132
  require_path "$SOURCE_ROOT/wdk-btc-wallet/package.json" "wdk-btc-wallet runtime"
127
133
  require_path "$SOURCE_ROOT/wdk-evm-wallet/package.json" "wdk-evm-wallet runtime"
128
134
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentlayer.tech/wallet",
3
- "version": "0.1.64",
3
+ "version": "0.1.66",
4
4
  "description": "NPM installer for the OpenClaw Agent Wallet local runtime.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wdk-btc-wallet",
3
- "version": "0.1.64",
3
+ "version": "0.1.66",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "Separate BTC-only wallet service built on Tether WDK.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wdk-evm-wallet",
3
- "version": "0.1.64",
3
+ "version": "0.1.66",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "Separate EVM wallet service built on Tether WDK.",