@agentlayer.tech/wallet 0.1.99 → 0.1.101
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/openclaw.plugin.json +1 -1
- package/.openclaw/extensions/agent-wallet/package.json +1 -1
- package/VERSION +1 -1
- package/agent-wallet/agent_wallet/__init__.py +1 -1
- package/agent-wallet/agent_wallet/providers/solana_rpc.py +1 -1
- package/agent-wallet/agent_wallet/providers/wdk_btc_local.py +7 -4
- package/agent-wallet/agent_wallet/providers/wdk_evm_local.py +7 -2
- package/agent-wallet/agent_wallet/wallet_layer/solana.py +1 -1
- package/agent-wallet/openclaw.plugin.json +1 -1
- package/agent-wallet/pyproject.toml +1 -1
- package/claude-code/plugins/agent-wallet/.claude-plugin/plugin.json +1 -1
- package/claude-code/plugins/agent-wallet/commands/x402.md +12 -12
- package/codex/plugins/agent-wallet/.codex-plugin/plugin.json +1 -1
- package/codex/plugins/agent-wallet/server.py +13 -4
- package/codex/plugins/agent-wallet/skills/x402/SKILL.md +4 -4
- package/hermes/plugins/agent_wallet/plugin.yaml +1 -1
- package/package.json +1 -1
- package/wdk-btc-wallet/package.json +1 -1
- package/wdk-evm-wallet/package.json +1 -1
|
@@ -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.
|
|
5
|
+
"version": "0.1.101",
|
|
6
6
|
"contracts": {
|
|
7
7
|
"tools": [
|
|
8
8
|
"agentlayer_autonomous_approve",
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.101
|
|
@@ -430,7 +430,7 @@ async def get_signature_status(
|
|
|
430
430
|
async def wait_for_confirmation(
|
|
431
431
|
signature: str,
|
|
432
432
|
rpc_url: str,
|
|
433
|
-
timeout_seconds: float =
|
|
433
|
+
timeout_seconds: float = 60.0,
|
|
434
434
|
poll_interval_seconds: float = 1.0,
|
|
435
435
|
) -> dict[str, Any] | None:
|
|
436
436
|
"""Poll signature status until confirmed/finalized or timeout."""
|
|
@@ -13,6 +13,9 @@ from agent_wallet.config import resolve_btc_wallet_password, resolve_openclaw_ho
|
|
|
13
13
|
from agent_wallet.wallet_layer.base import WalletBackendError
|
|
14
14
|
|
|
15
15
|
LOCAL_WDK_BTC_HOSTS = {"127.0.0.1", "localhost", "::1"}
|
|
16
|
+
# Local wallet calls can decrypt the sealed vault and wait for upstream Bitcoin
|
|
17
|
+
# RPC. Keep their operation timeout aligned with the local EVM wallet client.
|
|
18
|
+
LOCAL_WDK_BTC_TIMEOUT_SECONDS = 60.0
|
|
16
19
|
|
|
17
20
|
|
|
18
21
|
def _normalize_base_url(value: str) -> str:
|
|
@@ -99,7 +102,7 @@ class WdkBtcLocalClient:
|
|
|
99
102
|
|
|
100
103
|
async def post(self, path: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
101
104
|
async with httpx.AsyncClient(
|
|
102
|
-
timeout=
|
|
105
|
+
timeout=LOCAL_WDK_BTC_TIMEOUT_SECONDS,
|
|
103
106
|
headers=self._headers,
|
|
104
107
|
follow_redirects=False,
|
|
105
108
|
trust_env=False,
|
|
@@ -111,7 +114,7 @@ class WdkBtcLocalClient:
|
|
|
111
114
|
|
|
112
115
|
async def get(self, path: str) -> dict[str, Any]:
|
|
113
116
|
async with httpx.AsyncClient(
|
|
114
|
-
timeout=
|
|
117
|
+
timeout=LOCAL_WDK_BTC_TIMEOUT_SECONDS,
|
|
115
118
|
headers=self._headers,
|
|
116
119
|
follow_redirects=False,
|
|
117
120
|
trust_env=False,
|
|
@@ -121,7 +124,7 @@ class WdkBtcLocalClient:
|
|
|
121
124
|
|
|
122
125
|
def post_sync(self, path: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
123
126
|
with httpx.Client(
|
|
124
|
-
timeout=
|
|
127
|
+
timeout=LOCAL_WDK_BTC_TIMEOUT_SECONDS,
|
|
125
128
|
headers=self._headers,
|
|
126
129
|
follow_redirects=False,
|
|
127
130
|
trust_env=False,
|
|
@@ -133,7 +136,7 @@ class WdkBtcLocalClient:
|
|
|
133
136
|
|
|
134
137
|
def get_sync(self, path: str) -> dict[str, Any]:
|
|
135
138
|
with httpx.Client(
|
|
136
|
-
timeout=
|
|
139
|
+
timeout=LOCAL_WDK_BTC_TIMEOUT_SECONDS,
|
|
137
140
|
headers=self._headers,
|
|
138
141
|
follow_redirects=False,
|
|
139
142
|
trust_env=False,
|
|
@@ -13,6 +13,11 @@ from agent_wallet.config import resolve_evm_wallet_password, resolve_openclaw_ho
|
|
|
13
13
|
from agent_wallet.wallet_layer.base import WalletBackendError
|
|
14
14
|
|
|
15
15
|
LOCAL_WDK_EVM_HOSTS = {"127.0.0.1", "localhost", "::1"}
|
|
16
|
+
# The local service may decrypt the sealed vault and make several upstream RPC
|
|
17
|
+
# calls for a single wallet operation (for example, token metadata plus a gas
|
|
18
|
+
# quote). The global HTTP default is deliberately short for ordinary external
|
|
19
|
+
# providers, but it is too short for this local wallet boundary.
|
|
20
|
+
MIN_LOCAL_WDK_EVM_TIMEOUT_SECONDS = 60.0
|
|
16
21
|
LONG_RUNNING_POST_PATHS = {
|
|
17
22
|
"/v1/evm/aave/supply/send",
|
|
18
23
|
"/v1/evm/aave/withdraw/send",
|
|
@@ -89,7 +94,7 @@ def _load_local_token() -> str:
|
|
|
89
94
|
|
|
90
95
|
def _timeout_for_path(path: str) -> float:
|
|
91
96
|
normalized = str(path or "").strip()
|
|
92
|
-
base_timeout = float(settings.http_timeout)
|
|
97
|
+
base_timeout = max(float(settings.http_timeout), MIN_LOCAL_WDK_EVM_TIMEOUT_SECONDS)
|
|
93
98
|
if normalized in LONG_RUNNING_POST_PATHS:
|
|
94
99
|
return max(base_timeout, LONG_RUNNING_SEND_TIMEOUT_SECONDS)
|
|
95
100
|
return base_timeout
|
|
@@ -288,7 +293,7 @@ class WdkEvmLocalClient:
|
|
|
288
293
|
def list_wallets_sync(self) -> list[dict[str, Any]]:
|
|
289
294
|
try:
|
|
290
295
|
with httpx.Client(
|
|
291
|
-
timeout=
|
|
296
|
+
timeout=_timeout_for_path("/v1/evm/wallets"),
|
|
292
297
|
headers=self._headers,
|
|
293
298
|
follow_redirects=False,
|
|
294
299
|
trust_env=False,
|
|
@@ -3470,7 +3470,7 @@ class SolanaWalletBackend(AgentWalletBackend):
|
|
|
3470
3470
|
status = await solana_rpc.wait_for_confirmation(
|
|
3471
3471
|
signature=signature,
|
|
3472
3472
|
rpc_url=self.rpc_urls,
|
|
3473
|
-
timeout_seconds=60.0
|
|
3473
|
+
timeout_seconds=60.0,
|
|
3474
3474
|
poll_interval_seconds=2.0 if source == "kamino" else 1.0,
|
|
3475
3475
|
)
|
|
3476
3476
|
confirmed = status is not None
|
|
@@ -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.
|
|
5
|
+
"version": "0.1.101",
|
|
6
6
|
"skills": ["skills/wallet-operator"],
|
|
7
7
|
"configSchema": {
|
|
8
8
|
"type": "object",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-wallet",
|
|
3
3
|
"displayName": "Agent Wallet",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.101",
|
|
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"
|
|
@@ -34,23 +34,23 @@ wants only to ignore what they already typed. If it is empty (a bare
|
|
|
34
34
|
Agentic Market was named explicitly — `auto` searches CDP Bazaar first.
|
|
35
35
|
- Only if no inline text was given at all, ask the user what they want to
|
|
36
36
|
find or pay for before calling any tool.
|
|
37
|
-
- Present the top
|
|
38
|
-
asking anything, columns `Service | Price
|
|
37
|
+
- Present the top 6 returned `items` as a compact Markdown table before
|
|
38
|
+
asking anything, columns `Service | Price`:
|
|
39
39
|
- Service — CDP Bazaar: `description` (fall back to `resource`'s host +
|
|
40
40
|
path); Agentic Market: `service_name` (fall back to `domain`).
|
|
41
41
|
- Price — CDP Bazaar: `accepts[].amount_display`; Agentic Market:
|
|
42
42
|
`endpoints[].pricing`.
|
|
43
|
-
-
|
|
44
|
-
|
|
45
|
-
- Cap at 4 rows to match the menu in the next step; if `count` is higher,
|
|
46
|
-
say so below the table ("12 total matches, showing the top 4 — ask me
|
|
47
|
-
to narrow the search for more").
|
|
43
|
+
- Cap at 6 rows; if `count` is higher, say so below the table ("12 total
|
|
44
|
+
matches, showing the top 6 — ask me to narrow the search for more").
|
|
48
45
|
- Immediately after the table, call `AskUserQuestion` — header `Service`,
|
|
49
|
-
one option per table
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
one option per the table's first 4 rows (label: service name,
|
|
47
|
+
description: price from that row). `AskUserQuestion` hard-caps at 4
|
|
48
|
+
options, so it can't cover all 6 table rows as buttons — its built-in
|
|
49
|
+
"Other" choice is how the user reaches rows 5-6 (or refines the search):
|
|
50
|
+
they can type a service name or row text from the table, and it should
|
|
51
|
+
be matched back to that row rather than treated as a brand new search
|
|
52
|
+
query. Network and provider still surface naturally in Step 2's preview
|
|
53
|
+
and Step 3's confirm — they're just not repeated in this first table.
|
|
54
54
|
- If the chosen item doesn't already carry a directly-callable URL (CDP
|
|
55
55
|
Bazaar's `resource`, or an Agentic Market `endpoints[].url`), call
|
|
56
56
|
`x402_get_service_details` with that item's reference to resolve one.
|
|
@@ -1004,14 +1004,23 @@ def _prewarm_resident_read_worker() -> None:
|
|
|
1004
1004
|
|
|
1005
1005
|
|
|
1006
1006
|
def _approval_summary_for_preview(tool_name: str, preview_payload: dict[str, Any]) -> dict[str, Any]:
|
|
1007
|
-
"""Build the
|
|
1008
|
-
|
|
1009
|
-
|
|
1007
|
+
"""Build the confirmation summary the invoke subprocess mints a token from.
|
|
1008
|
+
|
|
1009
|
+
Only exact-preview tools validate ``_preview_digest`` in the wallet
|
|
1010
|
+
adapter. Adding that private binding to ordinary transfers and EVM swaps
|
|
1011
|
+
makes their approval token differ from the adapter's execution summary,
|
|
1012
|
+
causing a valid user confirmation to be rejected.
|
|
1013
|
+
"""
|
|
1010
1014
|
summary = preview_payload.get("confirmation_summary")
|
|
1011
1015
|
if not isinstance(summary, dict):
|
|
1012
1016
|
raise RuntimeError(f"No confirmation_summary available for {tool_name}.")
|
|
1013
1017
|
summary_for_token = dict(summary)
|
|
1014
|
-
|
|
1018
|
+
is_solana_swap_intent = (
|
|
1019
|
+
tool_name == "swap_solana_tokens"
|
|
1020
|
+
and str(preview_payload.get("mode") or "") == "intent_preview"
|
|
1021
|
+
)
|
|
1022
|
+
if tool_name in PREVIEW_BOUND_SWAP_TOOLS and not is_solana_swap_intent:
|
|
1023
|
+
summary_for_token["_preview_digest"] = _preview_digest(preview_payload)
|
|
1015
1024
|
return summary_for_token
|
|
1016
1025
|
|
|
1017
1026
|
|
|
@@ -36,16 +36,16 @@ wants only to ignore what they already typed.
|
|
|
36
36
|
bare `$x402`), ask the user what they want to find or pay for before
|
|
37
37
|
calling any tool.
|
|
38
38
|
- Present the top ~10 returned `items` as a compact Markdown table with a
|
|
39
|
-
leading `#` column, columns `# | Service | Price
|
|
39
|
+
leading `#` column, columns `# | Service | Price`:
|
|
40
40
|
- Service — CDP Bazaar: `description` (fall back to `resource`'s host +
|
|
41
41
|
path); Agentic Market: `service_name` (fall back to `domain`).
|
|
42
42
|
- Price — CDP Bazaar: `accepts[].amount_display`; Agentic Market:
|
|
43
43
|
`endpoints[].pricing`.
|
|
44
|
-
- Network — the matching `accepts[]`/`endpoints[].pricing` network.
|
|
45
|
-
- Provider — `discovery_provider` (`cdp_bazaar` / `agentic_market`).
|
|
46
44
|
- If `count` is higher than what's shown, say so below the table ("14
|
|
47
45
|
total matches, showing the top 10 — ask me to narrow the search for
|
|
48
|
-
more").
|
|
46
|
+
more"). Network and provider still surface naturally in Step 2's
|
|
47
|
+
preview and Step 3's confirm — they're just not repeated in this first
|
|
48
|
+
table.
|
|
49
49
|
- Wait for the user's reply with a row number, or a request to refine the
|
|
50
50
|
search if none fit.
|
|
51
51
|
- If the chosen item doesn't already carry a directly-callable URL (CDP
|
package/package.json
CHANGED