@agentlayer.tech/wallet 0.1.49 → 0.1.52

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.
@@ -2,7 +2,7 @@
2
2
  "id": "agent-wallet",
3
3
  "name": "Agent Wallet",
4
4
  "description": "Official OpenClaw plugin bridge for the agent-wallet backends, including Solana, local BTC, and local EVM.",
5
- "version": "0.1.49",
5
+ "version": "0.1.52",
6
6
  "contracts": {
7
7
  "tools": [
8
8
  "agentlayer_autonomous_approve",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentlayertech/agent-wallet-plugin",
3
- "version": "0.1.49",
3
+ "version": "0.1.52",
4
4
  "description": "OpenClaw plugin bridge for the AgentLayer wallet runtime.",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN ../../../LICENSE",
package/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## v0.1.52 - 2026-06-26
6
+
7
+ - Fixed Morpho vault and market quote (preview) requests timing out under the
8
+ default 10 s HTTP budget. The Morpho SDK fetches vault state from
9
+ `api.morpho.org/graphql` and runs on-chain simulation before returning a
10
+ quote, which regularly exceeds 10 s. Added all six quote paths
11
+ (`/v1/evm/morpho/vault/{supply,withdraw}/quote` and
12
+ `/v1/evm/morpho/market/{supply_collateral,borrow,repay,withdraw_collateral}/quote`)
13
+ to `LONG_RUNNING_POST_PATHS` so they share the 120 s budget already applied
14
+ to the corresponding send paths.
15
+ - `agent-wallet/agent_wallet/providers/wdk_evm_local.py`
16
+ - Extended the high-trust autonomous permission mode beyond Base swaps and made
17
+ it a single combined permission group. `/agentlayer-autonomous-approve`
18
+ enables both Base Velora/Uniswap swaps and supported EVM DeFi write tools
19
+ (Aave, Morpho vault/market, and Lido staking/withdrawal) on Ethereum/Base;
20
+ `/agentlayer-autonomous-revoke` disables both together. Covered execute calls
21
+ use the same fresh-preview/internal-approval path while retaining exact
22
+ summary and quote-fingerprint binding. Transfers, bridges, Solana swaps, and
23
+ generic contract calls remain outside this standing permission.
24
+
5
25
  ## v0.1.47 - 2026-06-16
6
26
 
7
27
  - Fixed Solana swaps of Token-2022 tokens with complex extensions (e.g. Backpack
package/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.49
1
+ 0.1.52
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Keep in sync with package.json, pyproject.toml, and the npm installer version.
4
4
  # scripts/check_release_version.mjs enforces this on release.
5
- __version__ = "0.1.49"
5
+ __version__ = "0.1.52"
6
6
 
7
7
  __all__ = [
8
8
  "config",
@@ -18,11 +18,17 @@ LONG_RUNNING_POST_PATHS = {
18
18
  "/v1/evm/aave/withdraw/send",
19
19
  "/v1/evm/aave/borrow/send",
20
20
  "/v1/evm/aave/repay/send",
21
+ "/v1/evm/morpho/vault/supply/quote",
21
22
  "/v1/evm/morpho/vault/supply/send",
23
+ "/v1/evm/morpho/vault/withdraw/quote",
22
24
  "/v1/evm/morpho/vault/withdraw/send",
25
+ "/v1/evm/morpho/market/supply_collateral/quote",
23
26
  "/v1/evm/morpho/market/supply_collateral/send",
27
+ "/v1/evm/morpho/market/borrow/quote",
24
28
  "/v1/evm/morpho/market/borrow/send",
29
+ "/v1/evm/morpho/market/repay/quote",
25
30
  "/v1/evm/morpho/market/repay/send",
31
+ "/v1/evm/morpho/market/withdraw_collateral/quote",
26
32
  "/v1/evm/morpho/market/withdraw_collateral/send",
27
33
  "/v1/evm/lido/stake_eth_for_wsteth/send",
28
34
  "/v1/evm/lido/wrap_steth/send",
@@ -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.49",
5
+ "version": "0.1.52",
6
6
  "skills": ["skills/wallet-operator"],
7
7
  "configSchema": {
8
8
  "type": "object",
@@ -4,13 +4,13 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "openclaw-agent-wallet"
7
- version = "0.1.49"
7
+ version = "0.1.52"
8
8
  description = "Plugin-friendly wallet backend for OpenClaw agents"
9
9
  requires-python = ">=3.10"
10
10
  dependencies = [
11
11
  "fastmcp>=2.0.0",
12
12
  "httpx>=0.27.0",
13
- "pydantic>=2.0.0",
13
+ "pydantic>=2.0.0,<2.13.0",
14
14
  "pydantic-settings>=2.0.0",
15
15
  "pynacl>=1.5.0",
16
16
  "python-dotenv>=1.0.0",
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { spawnSync } from "node:child_process";
3
+ import { spawn, spawnSync } from "node:child_process";
4
4
  import crypto from "node:crypto";
5
5
  import fs from "node:fs";
6
6
  import os from "node:os";
@@ -15,6 +15,14 @@ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
15
15
  const packageVersion = packageJson.version;
16
16
  const UPDATE_CLI_PATH_ENV = "OPENCLAW_AGENT_WALLET_UPDATE_CLI_PATH";
17
17
  const UPDATE_PACKAGE_SPEC_ENV = "OPENCLAW_AGENT_WALLET_UPDATE_PACKAGE_SPEC";
18
+ const DEFAULT_PROVIDER_GATEWAY_URL = "https://agent-layer-production.up.railway.app";
19
+ const TELEMETRY_SPOOL_NAME = "telemetry_spool.jsonl";
20
+ const TELEMETRY_ID_NAME = "telemetry_id";
21
+ const TELEMETRY_LAST_FLUSH_NAME = "telemetry_last_flush";
22
+ const TELEMETRY_FLUSH_THROTTLE_SECONDS = 20;
23
+ const TELEMETRY_FORCE_LINES = 25;
24
+ const TELEMETRY_MAX_EVENTS_PER_FLUSH = 100;
25
+ const TELEMETRY_HTTP_TIMEOUT_MS = 1500;
18
26
 
19
27
  function printHelp() {
20
28
  console.log(`openclaw-agent-wallet
@@ -100,6 +108,211 @@ function updateCheckDisabled(env = process.env) {
100
108
  return ["1", "true", "yes", "on"].includes(raw);
101
109
  }
102
110
 
111
+ function telemetryDisabled(env = process.env) {
112
+ const raw = String(env.AGENT_WALLET_NO_TELEMETRY || "").trim().toLowerCase();
113
+ return ["1", "true", "yes", "on"].includes(raw);
114
+ }
115
+
116
+ function telemetryPath(name, env = process.env) {
117
+ return path.join(resolveOpenclawHome(env), name);
118
+ }
119
+
120
+ function telemetryInstallId(env = process.env) {
121
+ const idPath = telemetryPath(TELEMETRY_ID_NAME, env);
122
+ try {
123
+ const existing = fs.readFileSync(idPath, "utf8").trim();
124
+ if (existing) return existing;
125
+ } catch {
126
+ // Create below.
127
+ }
128
+ const next = crypto.randomUUID ? crypto.randomUUID().replaceAll("-", "") : crypto.randomBytes(16).toString("hex");
129
+ try {
130
+ fs.mkdirSync(path.dirname(idPath), { recursive: true });
131
+ fs.writeFileSync(idPath, next, { mode: 0o600 });
132
+ } catch {
133
+ // Telemetry must not affect install flow.
134
+ }
135
+ return next;
136
+ }
137
+
138
+ function telemetryHost(host = "", env = process.env) {
139
+ const raw = String(host || env.AGENT_WALLET_HOST || "").trim().toLowerCase();
140
+ return ["claude-code", "codex", "hermes", "openclaw"].includes(raw) ? raw : "unknown";
141
+ }
142
+
143
+ function telemetrySource(env = process.env) {
144
+ const explicit = String(env.AGENT_WALLET_INSTALL_SOURCE || "").trim().toLowerCase();
145
+ if (explicit) return explicit.replace(/[^a-z0-9_]/g, "_").slice(0, 48);
146
+ return env.npm_execpath || String(env.npm_config_user_agent || "").includes("npm")
147
+ ? "npx"
148
+ : "global_cli";
149
+ }
150
+
151
+ function telemetryGatewayUrl(env = process.env) {
152
+ return String(env.PROVIDER_GATEWAY_URL || DEFAULT_PROVIDER_GATEWAY_URL).trim().replace(/\/+$/, "");
153
+ }
154
+
155
+ function telemetryAppend(payload, env = process.env) {
156
+ const spool = telemetryPath(TELEMETRY_SPOOL_NAME, env);
157
+ fs.mkdirSync(path.dirname(spool), { recursive: true });
158
+ fs.appendFileSync(spool, `${JSON.stringify(payload)}\n`, { encoding: "utf8" });
159
+ }
160
+
161
+ function telemetrySpoolLineCount(env = process.env) {
162
+ try {
163
+ const spool = telemetryPath(TELEMETRY_SPOOL_NAME, env);
164
+ return fs.readFileSync(spool, "utf8").split(/\r?\n/).filter(Boolean).length;
165
+ } catch {
166
+ return 0;
167
+ }
168
+ }
169
+
170
+ function telemetryShouldFlush(env = process.env) {
171
+ const count = telemetrySpoolLineCount(env);
172
+ if (count === 0) return false;
173
+ if (count >= TELEMETRY_FORCE_LINES) return true;
174
+ try {
175
+ const last = Number(fs.readFileSync(telemetryPath(TELEMETRY_LAST_FLUSH_NAME, env), "utf8").trim() || "0");
176
+ return Date.now() / 1000 - last >= TELEMETRY_FLUSH_THROTTLE_SECONDS;
177
+ } catch {
178
+ return true;
179
+ }
180
+ }
181
+
182
+ function telemetryMarkFlush(env = process.env) {
183
+ try {
184
+ fs.writeFileSync(telemetryPath(TELEMETRY_LAST_FLUSH_NAME, env), String(Date.now() / 1000));
185
+ } catch {
186
+ // ignored
187
+ }
188
+ }
189
+
190
+ function telemetrySpawnFlush(env = process.env, force = false) {
191
+ if (!force && !telemetryShouldFlush(env)) return;
192
+ telemetryMarkFlush(env);
193
+ try {
194
+ const child = spawn(process.execPath, [cliPath, "--telemetry-flush"], {
195
+ detached: true,
196
+ stdio: "ignore",
197
+ env,
198
+ });
199
+ child.unref();
200
+ } catch {
201
+ // ignored
202
+ }
203
+ }
204
+
205
+ function recordCliTelemetry(event, { commandName, host = "", ok = true, args = [], flush = true } = {}) {
206
+ try {
207
+ if (telemetryDisabled()) return;
208
+ if (args && hasFlag(args, "--dry-run")) return;
209
+ const payload = {
210
+ event,
211
+ install_id: telemetryInstallId(),
212
+ host: telemetryHost(host),
213
+ tool: "",
214
+ backend: "",
215
+ plugin_version: packageVersion,
216
+ ok: Boolean(ok),
217
+ ts: Math.floor(Date.now() / 1000),
218
+ source: telemetrySource(),
219
+ command: String(commandName || "").trim().toLowerCase().replace(/-/g, "_").slice(0, 48),
220
+ };
221
+ telemetryAppend(payload);
222
+ if (flush) telemetrySpawnFlush(process.env, true);
223
+ } catch {
224
+ // Telemetry must never affect CLI behavior.
225
+ }
226
+ }
227
+
228
+ async function telemetryPost(url, line) {
229
+ const controller = new AbortController();
230
+ const timer = setTimeout(() => controller.abort(), TELEMETRY_HTTP_TIMEOUT_MS);
231
+ try {
232
+ const response = await fetch(url, {
233
+ method: "POST",
234
+ body: line,
235
+ headers: { "Content-Type": "application/json" },
236
+ signal: controller.signal,
237
+ });
238
+ return response.ok;
239
+ } catch {
240
+ return false;
241
+ } finally {
242
+ clearTimeout(timer);
243
+ }
244
+ }
245
+
246
+ async function telemetryFlushMain(env = process.env) {
247
+ if (telemetryDisabled(env)) return 0;
248
+ const spool = telemetryPath(TELEMETRY_SPOOL_NAME, env);
249
+ const claim = `${spool}.flushing.${process.pid}`;
250
+ try {
251
+ fs.renameSync(spool, claim);
252
+ } catch {
253
+ return 0;
254
+ }
255
+
256
+ let lines = [];
257
+ try {
258
+ lines = fs.readFileSync(claim, "utf8").split(/\r?\n/).filter(Boolean);
259
+ } catch {
260
+ lines = [];
261
+ }
262
+
263
+ const url = `${telemetryGatewayUrl(env)}/v1/telemetry`;
264
+ const failed = [];
265
+ let sent = 0;
266
+ for (const line of lines) {
267
+ if (sent >= TELEMETRY_MAX_EVENTS_PER_FLUSH) {
268
+ failed.push(line);
269
+ continue;
270
+ }
271
+ if (await telemetryPost(url, line)) {
272
+ sent += 1;
273
+ } else {
274
+ failed.push(line);
275
+ }
276
+ }
277
+
278
+ if (failed.length) {
279
+ try {
280
+ fs.appendFileSync(spool, `${failed.join("\n")}\n`, { encoding: "utf8" });
281
+ } catch {
282
+ // ignored
283
+ }
284
+ }
285
+ try {
286
+ fs.unlinkSync(claim);
287
+ } catch {
288
+ // ignored
289
+ }
290
+ return 0;
291
+ }
292
+
293
+ function runWithCliTelemetry(fn, { startEvent, successEvent, failedEvent, commandName, host = "", args = [] }) {
294
+ recordCliTelemetry(startEvent, { commandName, host, ok: true, args, flush: false });
295
+ let code;
296
+ try {
297
+ code = fn();
298
+ } catch (error) {
299
+ recordCliTelemetry(failedEvent, {
300
+ commandName,
301
+ host,
302
+ ok: false,
303
+ args,
304
+ });
305
+ throw error;
306
+ }
307
+ recordCliTelemetry(code === 0 ? successEvent : failedEvent, {
308
+ commandName,
309
+ host,
310
+ ok: code === 0,
311
+ args,
312
+ });
313
+ return code;
314
+ }
315
+
103
316
  // Shared with the Python runtime (agent_wallet/update_check.py): the cache lives
104
317
  // under OPENCLAW_HOME/agent-wallet-runtime regardless of OPENCLAW_INSTALL_ROOT.
105
318
  function updateCheckCachePath(env = process.env) {
@@ -1802,6 +2015,10 @@ function runClaudeCodeInstall(args) {
1802
2015
  const args = process.argv.slice(2);
1803
2016
  const command = args[0] || "install";
1804
2017
 
2018
+ if (command === "--telemetry-flush") {
2019
+ process.exit(await telemetryFlushMain());
2020
+ }
2021
+
1805
2022
  if (command === "--help" || command === "-h" || command === "help") {
1806
2023
  printHelp();
1807
2024
  process.exit(0);
@@ -1830,11 +2047,35 @@ if (command === "status") {
1830
2047
  }
1831
2048
 
1832
2049
  if (command === "install" || command === "setup") {
1833
- process.exit(runInstall(args.slice(1), { commandName: "install" }));
2050
+ const commandArgs = args.slice(1);
2051
+ process.exit(
2052
+ runWithCliTelemetry(
2053
+ () => runInstall(commandArgs, { commandName: "install" }),
2054
+ {
2055
+ startEvent: "install_start",
2056
+ successEvent: "install_success",
2057
+ failedEvent: "install_failed",
2058
+ commandName: "install",
2059
+ args: commandArgs,
2060
+ },
2061
+ ),
2062
+ );
1834
2063
  }
1835
2064
 
1836
2065
  if (command === "update") {
1837
- process.exit(runUpdate(args.slice(1)));
2066
+ const commandArgs = args.slice(1);
2067
+ process.exit(
2068
+ runWithCliTelemetry(
2069
+ () => runUpdate(commandArgs),
2070
+ {
2071
+ startEvent: "update_start",
2072
+ successEvent: "update_success",
2073
+ failedEvent: "update_failed",
2074
+ commandName: "update",
2075
+ args: commandArgs,
2076
+ },
2077
+ ),
2078
+ );
1838
2079
  }
1839
2080
 
1840
2081
  if (command === "rollback") {
@@ -1844,7 +2085,20 @@ if (command === "rollback") {
1844
2085
  if (command === "hermes") {
1845
2086
  const subcommand = args[1] || "install";
1846
2087
  if (subcommand === "install" || subcommand === "setup") {
1847
- process.exit(runHermesInstall(args.slice(2)));
2088
+ const commandArgs = args.slice(2);
2089
+ process.exit(
2090
+ runWithCliTelemetry(
2091
+ () => runHermesInstall(commandArgs),
2092
+ {
2093
+ startEvent: "plugin_install_start",
2094
+ successEvent: "plugin_install_success",
2095
+ failedEvent: "plugin_install_failed",
2096
+ commandName: "hermes_install",
2097
+ host: "hermes",
2098
+ args: commandArgs,
2099
+ },
2100
+ ),
2101
+ );
1848
2102
  }
1849
2103
  console.error(`Unknown hermes command: ${subcommand}`);
1850
2104
  console.error("Run `openclaw-agent-wallet hermes install --yes` to connect Hermes Agent.");
@@ -1854,7 +2108,20 @@ if (command === "hermes") {
1854
2108
  if (command === "codex") {
1855
2109
  const subcommand = args[1] || "install";
1856
2110
  if (subcommand === "install" || subcommand === "setup") {
1857
- process.exit(runCodexInstall(args.slice(2)));
2111
+ const commandArgs = args.slice(2);
2112
+ process.exit(
2113
+ runWithCliTelemetry(
2114
+ () => runCodexInstall(commandArgs),
2115
+ {
2116
+ startEvent: "plugin_install_start",
2117
+ successEvent: "plugin_install_success",
2118
+ failedEvent: "plugin_install_failed",
2119
+ commandName: "codex_install",
2120
+ host: "codex",
2121
+ args: commandArgs,
2122
+ },
2123
+ ),
2124
+ );
1858
2125
  }
1859
2126
  console.error(`Unknown codex command: ${subcommand}`);
1860
2127
  console.error("Run `openclaw-agent-wallet codex install --yes` to connect Codex.");
@@ -1864,7 +2131,20 @@ if (command === "codex") {
1864
2131
  if (command === "claude-code") {
1865
2132
  const subcommand = args[1] || "install";
1866
2133
  if (subcommand === "install" || subcommand === "setup") {
1867
- process.exit(runClaudeCodeInstall(args.slice(2)));
2134
+ const commandArgs = args.slice(2);
2135
+ process.exit(
2136
+ runWithCliTelemetry(
2137
+ () => runClaudeCodeInstall(commandArgs),
2138
+ {
2139
+ startEvent: "plugin_install_start",
2140
+ successEvent: "plugin_install_success",
2141
+ failedEvent: "plugin_install_failed",
2142
+ commandName: "claude_code_install",
2143
+ host: "claude-code",
2144
+ args: commandArgs,
2145
+ },
2146
+ ),
2147
+ );
1868
2148
  }
1869
2149
  console.error(`Unknown claude-code command: ${subcommand}`);
1870
2150
  console.error("Run `openclaw-agent-wallet claude-code install --yes` to connect Claude Code.");
@@ -1872,7 +2152,18 @@ if (command === "claude-code") {
1872
2152
  }
1873
2153
 
1874
2154
  if (command.startsWith("-")) {
1875
- process.exit(runInstall(args, { commandName: "install" }));
2155
+ process.exit(
2156
+ runWithCliTelemetry(
2157
+ () => runInstall(args, { commandName: "install" }),
2158
+ {
2159
+ startEvent: "install_start",
2160
+ successEvent: "install_success",
2161
+ failedEvent: "install_failed",
2162
+ commandName: "install",
2163
+ args,
2164
+ },
2165
+ ),
2166
+ );
1876
2167
  }
1877
2168
 
1878
2169
  console.error(`Unknown command: ${command}`);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agent-wallet",
3
3
  "displayName": "Agent Wallet",
4
- "version": "0.1.49",
4
+ "version": "0.1.52",
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"
@@ -113,7 +113,7 @@ fi
113
113
 
114
114
  log "Installing the AgentLayer wallet backend runtime via npm (this may take a minute)…"
115
115
  log " -> npx $PACKAGE_SPEC install --yes"
116
- if ! npx -y "$PACKAGE_SPEC" install --yes; then
116
+ if ! AGENT_WALLET_INSTALL_SOURCE=claude_marketplace_bootstrap npx -y "$PACKAGE_SPEC" install --yes; then
117
117
  log "Backend install failed. Ensure Node.js 18+ and Python >= 3.10 (with venv) are installed, then re-run /wallet-setup."
118
118
  exit 1
119
119
  fi
@@ -123,7 +123,7 @@ fi
123
123
  # --skip-enable: the plugin is already registered via the marketplace, so we only
124
124
  # want the file pinning, not another `claude plugin install`.
125
125
  log "Wiring the Claude Code bridge to the installed runtime…"
126
- npx -y "$PACKAGE_SPEC" claude-code install --yes --skip-enable || \
126
+ AGENT_WALLET_INSTALL_SOURCE=claude_marketplace_bootstrap npx -y "$PACKAGE_SPEC" claude-code install --yes --skip-enable || \
127
127
  log "Note: could not re-pin the Claude Code bridge automatically; it will still resolve the default runtime."
128
128
 
129
129
  if backend_ready; then
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-wallet",
3
- "version": "0.1.49",
3
+ "version": "0.1.52",
4
4
  "description": "Codex plugin bridge for the AgentLayer wallet runtime.",
5
5
  "author": {
6
6
  "name": "AgentLayer"
@@ -1,5 +1,5 @@
1
1
  name: agent-wallet
2
- version: 0.1.49
2
+ version: 0.1.52
3
3
  description: Thin Hermes Agent bridge to the existing AgentLayer/OpenClaw wallet backend
4
4
  provides_tools:
5
5
  - agent_wallet_tools
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentlayer.tech/wallet",
3
- "version": "0.1.49",
3
+ "version": "0.1.52",
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.49",
3
+ "version": "0.1.52",
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.49",
3
+ "version": "0.1.52",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "Separate EVM wallet service built on Tether WDK.",