@agentlayer.tech/wallet 0.1.32 → 0.1.34

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 (36) hide show
  1. package/.openclaw/extensions/agent-wallet/dist/index.js +2 -59
  2. package/.openclaw/extensions/agent-wallet/index.ts +2 -59
  3. package/.openclaw/extensions/agent-wallet/openclaw.plugin.json +1 -4
  4. package/.openclaw/extensions/agent-wallet/package.json +1 -1
  5. package/CHANGELOG.md +66 -0
  6. package/README.md +2 -5
  7. package/RELEASING.md +56 -29
  8. package/VERSION +1 -0
  9. package/agent-wallet/.env.example +0 -1
  10. package/agent-wallet/README.md +0 -8
  11. package/agent-wallet/agent_wallet/__init__.py +5 -0
  12. package/agent-wallet/agent_wallet/config.py +0 -1
  13. package/agent-wallet/agent_wallet/openclaw_adapter.py +25 -324
  14. package/agent-wallet/agent_wallet/openclaw_cli.py +0 -5
  15. package/agent-wallet/agent_wallet/providers/bags.py +1 -58
  16. package/agent-wallet/agent_wallet/providers/jupiter.py +1 -64
  17. package/agent-wallet/agent_wallet/update_check.py +191 -0
  18. package/agent-wallet/agent_wallet/wallet_layer/base.py +0 -44
  19. package/agent-wallet/agent_wallet/wallet_layer/solana.py +0 -236
  20. package/agent-wallet/openclaw.plugin.json +1 -5
  21. package/agent-wallet/pyproject.toml +1 -1
  22. package/agent-wallet/skills/wallet-operator/SKILL.md +2 -5
  23. package/bin/openclaw-agent-wallet.mjs +419 -33
  24. package/claude-code/plugins/agent-wallet/.claude-plugin/plugin.json +1 -1
  25. package/claude-code/plugins/agent-wallet/scripts/run_mcp.sh +14 -1
  26. package/codex/plugins/agent-wallet/.codex-plugin/plugin.json +1 -1
  27. package/codex/plugins/agent-wallet/scripts/run_mcp.sh +18 -0
  28. package/codex/plugins/agent-wallet/server.py +39 -5
  29. package/hermes/plugins/agent_wallet/plugin.yaml +1 -1
  30. package/package.json +5 -1
  31. package/scripts/check_release_version.mjs +50 -20
  32. package/scripts/version_targets.mjs +60 -0
  33. package/wdk-btc-wallet/package.json +1 -1
  34. package/wdk-evm-wallet/README.md +3 -3
  35. package/wdk-evm-wallet/package.json +1 -1
  36. package/wdk-evm-wallet/src/wdk_evm_wallet.js +17 -2
@@ -906,17 +906,51 @@ async def _handle_wallet_tool(tool_name: str, params: dict[str, Any]) -> dict[st
906
906
  return payload.get("data", {})
907
907
 
908
908
 
909
+ BASE_INSTRUCTIONS = (
910
+ "Use the local AgentLayer wallet runtime through explicit wallet tools. Keep wallet "
911
+ "secrets local. Preview writes first when supported, and execute only after explicit "
912
+ "user confirmation."
913
+ )
914
+
915
+
916
+ def _update_notice_instructions(base: str) -> str:
917
+ """Append a one-time update notice to ``base`` when a newer version exists.
918
+
919
+ Fully fail-open: any error (package not importable, malformed cache, etc.)
920
+ returns ``base`` unchanged so the server always starts. The network refresh
921
+ runs in a background daemon thread and only affects the *next* start; the
922
+ notice itself is decided synchronously from the cache.
923
+ """
924
+ try:
925
+ package_root_text = str(_resolve_package_root())
926
+ inserted = package_root_text not in sys.path
927
+ if inserted:
928
+ sys.path.insert(0, package_root_text)
929
+ try:
930
+ from agent_wallet import update_check
931
+
932
+ update_check.maybe_refresh_in_background()
933
+ notice = update_check.pending_notice(mark_shown=True)
934
+ finally:
935
+ if inserted:
936
+ try:
937
+ sys.path.remove(package_root_text)
938
+ except ValueError:
939
+ pass
940
+ if notice:
941
+ return f"{base}\n\n⚠️ UPDATE AVAILABLE: {notice}"
942
+ except Exception:
943
+ pass
944
+ return base
945
+
946
+
909
947
  def build_server():
910
948
  from fastmcp import FastMCP
911
949
  from fastmcp.tools import FunctionTool
912
950
 
913
951
  mcp = FastMCP(
914
952
  "Agent Wallet",
915
- instructions=(
916
- "Use the local AgentLayer wallet runtime through explicit wallet tools. Keep wallet "
917
- "secrets local. Preview writes first when supported, and execute only after explicit "
918
- "user confirmation."
919
- ),
953
+ instructions=_update_notice_instructions(BASE_INSTRUCTIONS),
920
954
  )
921
955
 
922
956
  async def _dispatch(tool_name: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
@@ -1,5 +1,5 @@
1
1
  name: agent-wallet
2
- version: 0.1.0
2
+ version: 0.1.34
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.32",
3
+ "version": "0.1.34",
4
4
  "description": "NPM installer for the OpenClaw Agent Wallet local runtime.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -19,12 +19,16 @@
19
19
  "build:openclaw-plugins": "node scripts/manage_openclaw_plugin_packages.mjs build",
20
20
  "check:openclaw-plugins": "node scripts/manage_openclaw_plugin_packages.mjs check",
21
21
  "check:release-version": "node scripts/check_release_version.mjs",
22
+ "version:sync": "node scripts/sync_version.mjs",
23
+ "release:local": "node scripts/release_local.mjs",
22
24
  "test:npm-installer": "python3 agent-wallet/tests/smoke_npm_installer.py",
23
25
  "pack:dry-run": "npm pack --dry-run"
24
26
  },
25
27
  "files": [
26
28
  "bin/",
29
+ "VERSION",
27
30
  "scripts/check_release_version.mjs",
31
+ "scripts/version_targets.mjs",
28
32
  "setup.sh",
29
33
  "install-from-github.sh",
30
34
  "README.md",
@@ -1,26 +1,59 @@
1
1
  #!/usr/bin/env node
2
+ // Verify the project version is consistent across every framework manifest and,
3
+ // when run on a release tag, that the tag matches the canonical VERSION.
4
+ //
5
+ // Canonical source: the root VERSION file. All derived manifests (see
6
+ // scripts/version_targets.mjs) must equal it — stamp them with
7
+ // scripts/sync_version.mjs if this fails. Emits the resolved version and npm
8
+ // dist-tag for the publish workflow.
2
9
 
3
10
  import fs from "node:fs";
4
11
 
5
- const packageJson = JSON.parse(fs.readFileSync("package.json", "utf8"));
6
- const pyproject = fs.readFileSync("agent-wallet/pyproject.toml", "utf8");
7
- const pyVersion = pyproject.match(/^version\s*=\s*"([^"]+)"/m)?.[1] || "";
8
- const packageVersion = packageJson.version;
9
- const refName = process.env.GITHUB_REF_NAME || process.argv[2] || "";
10
- const expectedFromTag = refName.startsWith("v") ? refName.slice(1) : "";
12
+ import {
13
+ TARGETS,
14
+ VERSION_FILE,
15
+ npmTagFor,
16
+ readCanonicalVersion,
17
+ readTargetVersion,
18
+ } from "./version_targets.mjs";
19
+
20
+ const root = process.cwd();
11
21
  const errors = [];
12
22
 
13
- if (!packageVersion) {
14
- errors.push("package.json version is missing");
23
+ let canonical = "";
24
+ try {
25
+ canonical = readCanonicalVersion(root);
26
+ } catch {
27
+ errors.push(`${VERSION_FILE} is missing`);
15
28
  }
16
- if (!pyVersion) {
17
- errors.push("agent-wallet/pyproject.toml version is missing");
29
+ if (canonical === "") {
30
+ errors.push(`${VERSION_FILE} is empty`);
18
31
  }
19
- if (packageVersion && pyVersion && packageVersion !== pyVersion) {
20
- errors.push(`version mismatch: package.json=${packageVersion}, pyproject=${pyVersion}`);
32
+
33
+ if (canonical) {
34
+ for (const target of TARGETS) {
35
+ let actual = null;
36
+ try {
37
+ actual = readTargetVersion(root, target);
38
+ } catch {
39
+ errors.push(`${target.file} is missing`);
40
+ continue;
41
+ }
42
+ if (!actual) {
43
+ errors.push(`${target.file}: version field not found`);
44
+ } else if (actual !== canonical) {
45
+ errors.push(
46
+ `version mismatch: ${target.file}=${actual}, ${VERSION_FILE}=${canonical} ` +
47
+ `(run: npm run version:sync)`,
48
+ );
49
+ }
50
+ }
21
51
  }
22
- if (expectedFromTag && packageVersion !== expectedFromTag) {
23
- errors.push(`tag/version mismatch: tag=${refName}, package.json=${packageVersion}`);
52
+
53
+ const refName = process.env.GITHUB_REF_NAME || process.argv[2] || "";
54
+ const expectedFromTag = refName.startsWith("v") ? refName.slice(1) : "";
55
+ if (expectedFromTag && canonical && canonical !== expectedFromTag) {
56
+ errors.push(`tag/version mismatch: tag=${refName}, ${VERSION_FILE}=${canonical}`);
24
57
  }
25
58
 
26
59
  if (errors.length > 0) {
@@ -30,13 +63,10 @@ if (errors.length > 0) {
30
63
  process.exit(1);
31
64
  }
32
65
 
33
- const npmTag = packageVersion.includes("-") ? "beta" : "latest";
34
- console.log(`release_version=${packageVersion}`);
66
+ const npmTag = npmTagFor(canonical);
67
+ console.log(`release_version=${canonical}`);
35
68
  console.log(`npm_tag=${npmTag}`);
36
69
 
37
70
  if (process.env.GITHUB_OUTPUT) {
38
- fs.appendFileSync(
39
- process.env.GITHUB_OUTPUT,
40
- `release_version=${packageVersion}\nnpm_tag=${npmTag}\n`,
41
- );
71
+ fs.appendFileSync(process.env.GITHUB_OUTPUT, `release_version=${canonical}\nnpm_tag=${npmTag}\n`);
42
72
  }
@@ -0,0 +1,60 @@
1
+ // Single source of truth for the project version.
2
+ //
3
+ // The root VERSION file is canonical. Every other manifest below is a *derived*
4
+ // target that must carry the exact same version. These targets are stamped by
5
+ // scripts/sync_version.mjs and verified by scripts/check_release_version.mjs, so
6
+ // they should never be edited by hand.
7
+
8
+ import fs from "node:fs";
9
+ import path from "node:path";
10
+
11
+ export const VERSION_FILE = "VERSION";
12
+
13
+ // kind -> regex capturing (prefix)(version)(suffix). Non-global on purpose: we
14
+ // only ever replace the first (top-level) occurrence in each file.
15
+ const PATTERNS = {
16
+ json: /("version"\s*:\s*")([^"]*)(")/,
17
+ toml: /^(version\s*=\s*")([^"]*)(")/m,
18
+ pyinit: /^(__version__\s*=\s*")([^"]*)(")/m,
19
+ yaml: /^(version:\s*)(\S+)(.*)$/m,
20
+ };
21
+
22
+ // Every place the version lives, across all agent frameworks and packages.
23
+ export const TARGETS = [
24
+ { file: "package.json", kind: "json" },
25
+ { file: "agent-wallet/pyproject.toml", kind: "toml" },
26
+ { file: "agent-wallet/agent_wallet/__init__.py", kind: "pyinit" },
27
+ { file: ".openclaw/extensions/agent-wallet/package.json", kind: "json" },
28
+ { file: "agent-wallet/openclaw.plugin.json", kind: "json" },
29
+ { file: ".openclaw/extensions/agent-wallet/openclaw.plugin.json", kind: "json" },
30
+ { file: "codex/plugins/agent-wallet/.codex-plugin/plugin.json", kind: "json" },
31
+ { file: "claude-code/plugins/agent-wallet/.claude-plugin/plugin.json", kind: "json" },
32
+ { file: "hermes/plugins/agent_wallet/plugin.yaml", kind: "yaml" },
33
+ { file: "wdk-btc-wallet/package.json", kind: "json" },
34
+ { file: "wdk-evm-wallet/package.json", kind: "json" },
35
+ ];
36
+
37
+ export function readCanonicalVersion(root) {
38
+ return fs.readFileSync(path.join(root, VERSION_FILE), "utf8").trim();
39
+ }
40
+
41
+ export function readTargetVersion(root, target) {
42
+ const content = fs.readFileSync(path.join(root, target.file), "utf8");
43
+ const match = content.match(PATTERNS[target.kind]);
44
+ return match ? match[2] : null;
45
+ }
46
+
47
+ export function stampTarget(root, target, version) {
48
+ const filePath = path.join(root, target.file);
49
+ const content = fs.readFileSync(filePath, "utf8");
50
+ const pattern = PATTERNS[target.kind];
51
+ if (!pattern.test(content)) {
52
+ throw new Error(`No version field found in ${target.file}`);
53
+ }
54
+ const updated = content.replace(pattern, (_m, prefix, _old, suffix) => `${prefix}${version}${suffix}`);
55
+ fs.writeFileSync(filePath, updated);
56
+ }
57
+
58
+ export function npmTagFor(version) {
59
+ return version.includes("-") ? "beta" : "latest";
60
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wdk-btc-wallet",
3
- "version": "0.1.0",
3
+ "version": "0.1.34",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "Separate BTC-only wallet service built on Tether WDK.",
@@ -18,8 +18,8 @@ Current scope:
18
18
  - fetch ERC-20 balances
19
19
  - fetch ERC-20 token metadata (`name`, `symbol`, `decimals`)
20
20
  - fetch fee-rate suggestions
21
- - fetch read-only Velora swap quotes for supported mainnet ERC-20 pairs
22
- - execute Velora ERC-20 swaps on supported mainnet networks through the local wallet account
21
+ - fetch read-only Velora swap quotes for supported mainnet ERC-20 and native ETH pairs
22
+ - execute Velora ERC-20 and native ETH swaps on supported mainnet networks through the local wallet account
23
23
  - fetch Aave V3 account data on supported mainnet networks
24
24
  - fetch Aave V3 reserve catalog on supported mainnet networks
25
25
  - fetch Aave V3 per-reserve user positions on supported mainnet networks
@@ -177,7 +177,7 @@ Local security note:
177
177
  - unlocked seed phrases live only in memory
178
178
  - explicit `lock` or process restart clears the in-memory unlocked state
179
179
  - seed reveal is password-gated and separate from normal agent operations
180
- - Velora swap support is currently limited to `ethereum` and `base` ERC-20 pairs
180
+ - Velora swap support is currently limited to `ethereum` and `base` ERC-20 and native ETH pairs
181
181
  - the underlying WDK Velora package is still beta; test swap execution carefully before relying on it
182
182
  - Aave V3 support is currently limited to `ethereum` and `base`
183
183
  - Aave `supply` and `repay` may perform pool-scoped ERC-20 approvals; if a send fails after approval, the service attempts to restore the original allowance
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wdk-evm-wallet",
3
- "version": "0.1.0",
3
+ "version": "0.1.34",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "Separate EVM wallet service built on Tether WDK.",
@@ -246,6 +246,21 @@ function normalizeEvmTokenAddressAllowingNative(value, fieldName) {
246
246
  return normalizeAddress(address, fieldName).toLowerCase();
247
247
  }
248
248
 
249
+ function normalizeVeloraTokenAddress(value, fieldName) {
250
+ const raw = assertNonEmptyString(value, fieldName);
251
+ const alias = raw.toLowerCase();
252
+ if (
253
+ alias === "native" ||
254
+ alias === "eth" ||
255
+ alias === "ethereum" ||
256
+ isZeroAddress(raw) ||
257
+ isVeloraNativeTokenAddress(raw)
258
+ ) {
259
+ return VELORA_NATIVE_TOKEN_ADDRESS;
260
+ }
261
+ return normalizeAddress(raw, fieldName);
262
+ }
263
+
249
264
  function normalizeLifiOutputTokenAddress(value, destinationChainId, fieldName) {
250
265
  const raw = assertNonEmptyString(value, fieldName);
251
266
  const alias = raw.toLowerCase();
@@ -380,8 +395,8 @@ function normalizeX402ExactTypedData({ domain, types, primaryType, message }, ru
380
395
 
381
396
  function buildSwapRequest({ tokenIn, tokenOut, tokenInAmount }) {
382
397
  const swapRequest = {
383
- tokenIn: normalizeAddress(tokenIn, "tokenIn"),
384
- tokenOut: normalizeAddress(tokenOut, "tokenOut"),
398
+ tokenIn: normalizeVeloraTokenAddress(tokenIn, "tokenIn"),
399
+ tokenOut: normalizeVeloraTokenAddress(tokenOut, "tokenOut"),
385
400
  tokenInAmount: assertPositiveBigIntString(tokenInAmount, "tokenInAmount"),
386
401
  };
387
402
  assertDistinctAddresses(swapRequest.tokenIn, "tokenIn", swapRequest.tokenOut, "tokenOut");