@agentlayer.tech/wallet 0.1.92 → 0.1.94
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/dist/index.js +41 -0
- package/.openclaw/extensions/agent-wallet/index.ts +41 -0
- package/.openclaw/extensions/agent-wallet/openclaw.plugin.json +4 -1
- package/.openclaw/extensions/agent-wallet/package.json +1 -1
- package/CHANGELOG.md +35 -0
- package/VERSION +1 -1
- package/agent-wallet/agent_wallet/__init__.py +1 -1
- package/agent-wallet/agent_wallet/autonomous_permissions.py +1 -0
- package/agent-wallet/agent_wallet/openclaw_adapter.py +136 -0
- package/agent-wallet/agent_wallet/providers/wdk_evm_local.py +2 -0
- package/agent-wallet/agent_wallet/providers/x402.py +9 -1
- package/agent-wallet/agent_wallet/user_wallets.py +2 -0
- package/agent-wallet/agent_wallet/wallet_layer/base.py +18 -0
- package/agent-wallet/agent_wallet/wallet_layer/solana.py +2 -0
- package/agent-wallet/agent_wallet/wallet_layer/wdk_evm.py +97 -0
- 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/README.md +2 -0
- package/claude-code/plugins/agent-wallet/commands/cards.md +129 -0
- package/codex/plugins/agent-wallet/.codex-plugin/plugin.json +1 -1
- package/codex/plugins/agent-wallet/README.md +6 -2
- package/codex/plugins/agent-wallet/server.py +1 -0
- package/codex/plugins/agent-wallet/skills/cards/SKILL.md +119 -0
- 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/.env.example +3 -0
- package/wdk-evm-wallet/README.md +6 -0
- package/wdk-evm-wallet/package.json +1 -1
- package/wdk-evm-wallet/src/config.js +9 -0
- package/wdk-evm-wallet/src/server.js +12 -0
- package/wdk-evm-wallet/src/wdk_evm_wallet.js +345 -0
|
@@ -29,6 +29,7 @@ const AUTONOMOUS_DEFI_TOOLS = new Set([
|
|
|
29
29
|
"manage_evm_lido_withdrawal",
|
|
30
30
|
"manage_evm_morpho_market_position",
|
|
31
31
|
"manage_evm_morpho_vault_position",
|
|
32
|
+
"manage_evm_uniswap_liquidity",
|
|
32
33
|
]);
|
|
33
34
|
const approvalPreviewCache = new Map();
|
|
34
35
|
const WALLET_TOOL_ONLY_GUIDANCE =
|
|
@@ -1977,6 +1978,23 @@ const evmToolDefinitions = [
|
|
|
1977
1978
|
additionalProperties: false,
|
|
1978
1979
|
},
|
|
1979
1980
|
},
|
|
1981
|
+
{
|
|
1982
|
+
name: "search_uniswap_pairs",
|
|
1983
|
+
description: "Search read-only onchain Uniswap-tradeable pairs by name, ticker, or ERC-20 address. Verify any returned token address independently before quoting or trading.",
|
|
1984
|
+
parameters: {
|
|
1985
|
+
type: "object",
|
|
1986
|
+
properties: {
|
|
1987
|
+
query: { type: "string" },
|
|
1988
|
+
token_address: { type: "string" },
|
|
1989
|
+
chain: { type: "string" },
|
|
1990
|
+
dex_id: { type: "string" },
|
|
1991
|
+
all_chains: { type: "boolean" },
|
|
1992
|
+
limit: { type: "integer" },
|
|
1993
|
+
network: { type: "string", enum: EVM_CORE_NETWORKS },
|
|
1994
|
+
},
|
|
1995
|
+
additionalProperties: false,
|
|
1996
|
+
},
|
|
1997
|
+
},
|
|
1980
1998
|
{
|
|
1981
1999
|
name: "swap_evm_uniswap_tokens",
|
|
1982
2000
|
description: "Preview, prepare, or execute a supported Uniswap path on ethereum, base, or robinhood: CLASSIC, UniswapX orders, or canonical ETH↔WETH wrap/unwrap. ERC-20 paths may use Permit2 EIP-712 or an UniswapX order signature. Preview or prepare first. After the user explicitly confirms the shown summary in chat, call execute; the OpenClaw plugin handles the internal execution authorization automatically.",
|
|
@@ -1997,6 +2015,29 @@ const evmToolDefinitions = [
|
|
|
1997
2015
|
additionalProperties: false,
|
|
1998
2016
|
},
|
|
1999
2017
|
},
|
|
2018
|
+
{
|
|
2019
|
+
name: "manage_evm_uniswap_liquidity",
|
|
2020
|
+
description: "Preview, prepare, or execute a Uniswap V3/V4 liquidity action on ethereum, base, or robinhood. Supported actions are create, increase, decrease, and claim_fees. The official Liquidity API builds the transaction again immediately before signing, so confirmation is scoped to the LP intent rather than fragile ticks or calldata.",
|
|
2021
|
+
optional: true,
|
|
2022
|
+
parameters: {
|
|
2023
|
+
type: "object",
|
|
2024
|
+
properties: {
|
|
2025
|
+
action: { type: "string", enum: ["create", "increase", "decrease", "claim_fees"] },
|
|
2026
|
+
protocol: { type: "string", enum: ["V3", "V4"] },
|
|
2027
|
+
request: {
|
|
2028
|
+
type: "object",
|
|
2029
|
+
description: "Official Uniswap Liquidity API fields. walletAddress, chainId, protocol, simulateTransaction, and permit/signature fields are controlled by the wallet.",
|
|
2030
|
+
additionalProperties: true,
|
|
2031
|
+
},
|
|
2032
|
+
mode: { type: "string", enum: ["preview", "prepare", "execute"] },
|
|
2033
|
+
purpose: { type: "string" },
|
|
2034
|
+
user_intent: { type: "boolean" },
|
|
2035
|
+
network: { type: "string", enum: EVM_CORE_NETWORKS },
|
|
2036
|
+
},
|
|
2037
|
+
required: ["action", "protocol", "request", "mode", "purpose"],
|
|
2038
|
+
additionalProperties: false,
|
|
2039
|
+
},
|
|
2040
|
+
},
|
|
2000
2041
|
{
|
|
2001
2042
|
name: "swap_evm_lifi_cross_chain_tokens",
|
|
2002
2043
|
description: "Preview, prepare, or execute an EVM-origin cross-chain swap through LI.FI. This currently supports ethereum/base as the source network and ethereum/base/solana as the destination chain. Preview or prepare first. After the user explicitly confirms the shown summary in chat, call execute; the OpenClaw plugin handles the internal execution authorization automatically.",
|
|
@@ -29,6 +29,7 @@ const AUTONOMOUS_DEFI_TOOLS = new Set([
|
|
|
29
29
|
"manage_evm_lido_withdrawal",
|
|
30
30
|
"manage_evm_morpho_market_position",
|
|
31
31
|
"manage_evm_morpho_vault_position",
|
|
32
|
+
"manage_evm_uniswap_liquidity",
|
|
32
33
|
]);
|
|
33
34
|
const approvalPreviewCache = new Map();
|
|
34
35
|
const WALLET_TOOL_ONLY_GUIDANCE =
|
|
@@ -1977,6 +1978,23 @@ const evmToolDefinitions = [
|
|
|
1977
1978
|
additionalProperties: false,
|
|
1978
1979
|
},
|
|
1979
1980
|
},
|
|
1981
|
+
{
|
|
1982
|
+
name: "search_uniswap_pairs",
|
|
1983
|
+
description: "Search read-only onchain Uniswap-tradeable pairs by name, ticker, or ERC-20 address. Verify any returned token address independently before quoting or trading.",
|
|
1984
|
+
parameters: {
|
|
1985
|
+
type: "object",
|
|
1986
|
+
properties: {
|
|
1987
|
+
query: { type: "string" },
|
|
1988
|
+
token_address: { type: "string" },
|
|
1989
|
+
chain: { type: "string" },
|
|
1990
|
+
dex_id: { type: "string" },
|
|
1991
|
+
all_chains: { type: "boolean" },
|
|
1992
|
+
limit: { type: "integer" },
|
|
1993
|
+
network: { type: "string", enum: EVM_CORE_NETWORKS },
|
|
1994
|
+
},
|
|
1995
|
+
additionalProperties: false,
|
|
1996
|
+
},
|
|
1997
|
+
},
|
|
1980
1998
|
{
|
|
1981
1999
|
name: "swap_evm_uniswap_tokens",
|
|
1982
2000
|
description: "Preview, prepare, or execute a supported Uniswap path on ethereum, base, or robinhood: CLASSIC, UniswapX orders, or canonical ETH↔WETH wrap/unwrap. ERC-20 paths may use Permit2 EIP-712 or an UniswapX order signature. Preview or prepare first. After the user explicitly confirms the shown summary in chat, call execute; the OpenClaw plugin handles the internal execution authorization automatically.",
|
|
@@ -1997,6 +2015,29 @@ const evmToolDefinitions = [
|
|
|
1997
2015
|
additionalProperties: false,
|
|
1998
2016
|
},
|
|
1999
2017
|
},
|
|
2018
|
+
{
|
|
2019
|
+
name: "manage_evm_uniswap_liquidity",
|
|
2020
|
+
description: "Preview, prepare, or execute a Uniswap V3/V4 liquidity action on ethereum, base, or robinhood. Supported actions are create, increase, decrease, and claim_fees. The official Liquidity API builds the transaction again immediately before signing, so confirmation is scoped to the LP intent rather than fragile ticks or calldata.",
|
|
2021
|
+
optional: true,
|
|
2022
|
+
parameters: {
|
|
2023
|
+
type: "object",
|
|
2024
|
+
properties: {
|
|
2025
|
+
action: { type: "string", enum: ["create", "increase", "decrease", "claim_fees"] },
|
|
2026
|
+
protocol: { type: "string", enum: ["V3", "V4"] },
|
|
2027
|
+
request: {
|
|
2028
|
+
type: "object",
|
|
2029
|
+
description: "Official Uniswap Liquidity API fields. walletAddress, chainId, protocol, simulateTransaction, and permit/signature fields are controlled by the wallet.",
|
|
2030
|
+
additionalProperties: true,
|
|
2031
|
+
},
|
|
2032
|
+
mode: { type: "string", enum: ["preview", "prepare", "execute"] },
|
|
2033
|
+
purpose: { type: "string" },
|
|
2034
|
+
user_intent: { type: "boolean" },
|
|
2035
|
+
network: { type: "string", enum: EVM_CORE_NETWORKS },
|
|
2036
|
+
},
|
|
2037
|
+
required: ["action", "protocol", "request", "mode", "purpose"],
|
|
2038
|
+
additionalProperties: false,
|
|
2039
|
+
},
|
|
2040
|
+
},
|
|
2000
2041
|
{
|
|
2001
2042
|
name: "swap_evm_lifi_cross_chain_tokens",
|
|
2002
2043
|
description: "Preview, prepare, or execute an EVM-origin cross-chain swap through LI.FI. This currently supports ethereum/base as the source network and ethereum/base/solana as the destination chain. Preview or prepare first. After the user explicitly confirms the shown summary in chat, call execute; the OpenClaw plugin handles the internal execution authorization automatically.",
|
|
@@ -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.94",
|
|
6
6
|
"contracts": {
|
|
7
7
|
"tools": [
|
|
8
8
|
"agentlayer_autonomous_approve",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"get_evm_token_balance",
|
|
31
31
|
"get_evm_token_metadata",
|
|
32
32
|
"get_evm_transaction_receipt",
|
|
33
|
+
"get_uniswap_swap_quote",
|
|
33
34
|
"get_flash_trade_markets",
|
|
34
35
|
"get_flash_trade_positions",
|
|
35
36
|
"get_kamino_earn_positions",
|
|
@@ -61,11 +62,13 @@
|
|
|
61
62
|
"manage_evm_morpho_vault_position",
|
|
62
63
|
"manage_evm_lido_position",
|
|
63
64
|
"manage_evm_lido_withdrawal",
|
|
65
|
+
"manage_evm_uniswap_liquidity",
|
|
64
66
|
"search_uniswap_pairs",
|
|
65
67
|
"set_evm_network",
|
|
66
68
|
"set_wallet_backend",
|
|
67
69
|
"sign_wallet_message",
|
|
68
70
|
"swap_evm_lifi_cross_chain_tokens",
|
|
71
|
+
"swap_evm_uniswap_tokens",
|
|
69
72
|
"swap_evm_tokens",
|
|
70
73
|
"swap_solana_lifi_cross_chain_tokens",
|
|
71
74
|
"swap_solana_tokens",
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,41 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## v0.1.94 - 2026-08-13
|
|
6
|
+
|
|
7
|
+
- **Added Uniswap V3/V4 liquidity provisioning for Ethereum, Base, and
|
|
8
|
+
Robinhood Chain.** The EVM wallet now previews, prepares, and executes
|
|
9
|
+
create, increase, decrease, and fee-claim actions through Uniswap's
|
|
10
|
+
Liquidity API. Final LP calldata is refreshed and simulated immediately
|
|
11
|
+
before signing; executable transactions are accepted only for pinned
|
|
12
|
+
PositionManager deployments and matching wallet/network fields.
|
|
13
|
+
- **Added bounded LP approval handling and intent-safe confirmations.** Token
|
|
14
|
+
approvals are restricted to LP-request assets and approved spenders, while
|
|
15
|
+
confirmations bind the action, network, protocol, pool/position, and assets
|
|
16
|
+
rather than fast-expiring ticks or calldata. Single-sided concentrated
|
|
17
|
+
positions with a zero amount on one ERC-20 side no longer fail approval
|
|
18
|
+
discovery.
|
|
19
|
+
- **Exposed LP actions through the provider gateway, OpenClaw, and Codex.**
|
|
20
|
+
The provider gateway forwards the existing shared Uniswap API key to the
|
|
21
|
+
Liquidity API; OpenClaw's pair-search contract was restored and registered.
|
|
22
|
+
|
|
23
|
+
## v0.1.93 - 2026-08-10
|
|
24
|
+
|
|
25
|
+
- **Added `/cards` (Claude Code) and `cards` (Codex) for Laso Finance card
|
|
26
|
+
issuance.** Issue a US or international prepaid card, paid via x402 from
|
|
27
|
+
the wallet already connected in the session (Solana or Base/EVM). Both
|
|
28
|
+
files hardcode the `laso.finance` endpoints and never accept a URL
|
|
29
|
+
override from user input, search results, or page content; the flow
|
|
30
|
+
always previews the live payment terms and requires explicit confirmation
|
|
31
|
+
of the total debit (including any fee) before calling `x402_pay_request`.
|
|
32
|
+
- **Fixed a misleading Solana compatibility message in
|
|
33
|
+
`x402_preview_request`.** Preview runs through a read-only worker that
|
|
34
|
+
deliberately skips loading the Solana signer for speed; the compatibility
|
|
35
|
+
reason used to word this as "does not yet expose a supported x402 signer
|
|
36
|
+
path," which reads as unsupported. It now says the signer isn't loaded in
|
|
37
|
+
this read-only preview context by design, and that the real
|
|
38
|
+
`x402_pay_request` call can still succeed.
|
|
39
|
+
|
|
5
40
|
## v0.1.92 - 2026-07-29
|
|
6
41
|
|
|
7
42
|
- **EVM daemon restart after updates.** The installer now stops a verified
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.94
|
|
@@ -751,6 +751,28 @@ class OpenClawWalletAdapter:
|
|
|
751
751
|
"quote_fingerprint": provided_fingerprint,
|
|
752
752
|
}
|
|
753
753
|
|
|
754
|
+
if asset_type == "evm-uniswap-liquidity":
|
|
755
|
+
request = payload.get("request") if isinstance(payload.get("request"), dict) else {}
|
|
756
|
+
existing_pool = request.get("existingPool") if isinstance(request.get("existingPool"), dict) else {}
|
|
757
|
+
return {
|
|
758
|
+
"operation": action_label,
|
|
759
|
+
"network": str(payload.get("network") or getattr(self.backend, "network", "unknown")),
|
|
760
|
+
"from_address": payload.get("from_address"),
|
|
761
|
+
"protocol": payload.get("protocol"),
|
|
762
|
+
"liquidity_action": payload.get("liquidity_action"),
|
|
763
|
+
"liquidity_protocol": payload.get("liquidity_protocol"),
|
|
764
|
+
# Intent binds to the action and caller-provided LP scope, not a
|
|
765
|
+
# per-block transaction hash, adjusted ticks, or calculated amount.
|
|
766
|
+
"token0_address": request.get("token0Address") or existing_pool.get("token0Address"),
|
|
767
|
+
"token1_address": request.get("token1Address") or existing_pool.get("token1Address"),
|
|
768
|
+
"pool_reference": existing_pool.get("poolReference"),
|
|
769
|
+
"position_token_id": request.get("nftTokenId") or request.get("tokenId") or payload.get("position_token_id"),
|
|
770
|
+
"independent_token": request.get("independentToken"),
|
|
771
|
+
"liquidity_percentage_to_decrease": request.get("liquidityPercentageToDecrease"),
|
|
772
|
+
"slippage_tolerance": request.get("slippageTolerance"),
|
|
773
|
+
"position_manager": payload.get("position_manager"),
|
|
774
|
+
}
|
|
775
|
+
|
|
754
776
|
if asset_type == "evm-morpho-vault":
|
|
755
777
|
return {
|
|
756
778
|
"operation": action_label,
|
|
@@ -1722,6 +1744,35 @@ class OpenClawWalletAdapter:
|
|
|
1722
1744
|
risk_level="low",
|
|
1723
1745
|
),
|
|
1724
1746
|
)
|
|
1747
|
+
tools.insert(
|
|
1748
|
+
13,
|
|
1749
|
+
AgentToolSpec(
|
|
1750
|
+
name="manage_evm_uniswap_liquidity",
|
|
1751
|
+
description=(
|
|
1752
|
+
"Preview, prepare, or execute a Uniswap V3/V4 liquidity action on ethereum, base, or robinhood. "
|
|
1753
|
+
"Supported actions are create, increase, decrease, and claim_fees. The request is passed to the "
|
|
1754
|
+
"official Uniswap Liquidity API; execute refreshes the transaction immediately before signing."
|
|
1755
|
+
),
|
|
1756
|
+
input_schema={
|
|
1757
|
+
"type": "object",
|
|
1758
|
+
"properties": {
|
|
1759
|
+
"action": {"type": "string", "enum": ["create", "increase", "decrease", "claim_fees"]},
|
|
1760
|
+
"protocol": {"type": "string", "enum": ["V3", "V4"]},
|
|
1761
|
+
"request": {"type": "object", "description": "Uniswap LP API fields excluding walletAddress, chainId, protocol, and simulateTransaction; those are set from the active wallet.", "additionalProperties": True},
|
|
1762
|
+
"mode": {"type": "string", "enum": ["preview", "prepare", "execute"]},
|
|
1763
|
+
"purpose": {"type": "string"},
|
|
1764
|
+
"user_intent": {"type": "boolean"},
|
|
1765
|
+
"approval_token": {"type": "string"},
|
|
1766
|
+
"network": {"type": "string", "enum": ["ethereum", "base", "robinhood"]},
|
|
1767
|
+
},
|
|
1768
|
+
"required": ["action", "protocol", "request", "mode", "purpose"],
|
|
1769
|
+
"additionalProperties": False,
|
|
1770
|
+
},
|
|
1771
|
+
read_only=False,
|
|
1772
|
+
requires_explicit_user_intent=True,
|
|
1773
|
+
risk_level="high",
|
|
1774
|
+
),
|
|
1775
|
+
)
|
|
1725
1776
|
tools.insert(
|
|
1726
1777
|
14,
|
|
1727
1778
|
AgentToolSpec(
|
|
@@ -5757,6 +5808,91 @@ class OpenClawWalletAdapter:
|
|
|
5757
5808
|
),
|
|
5758
5809
|
)
|
|
5759
5810
|
|
|
5811
|
+
if tool_name == "manage_evm_uniswap_liquidity":
|
|
5812
|
+
action = args.get("action")
|
|
5813
|
+
protocol = args.get("protocol")
|
|
5814
|
+
request = args.get("request")
|
|
5815
|
+
mode = args.get("mode")
|
|
5816
|
+
purpose = args.get("purpose")
|
|
5817
|
+
user_intent = args.get("user_intent", False)
|
|
5818
|
+
approval_token = args.get("approval_token")
|
|
5819
|
+
if action not in {"create", "increase", "decrease", "claim_fees"}:
|
|
5820
|
+
raise WalletBackendError("action must be create, increase, decrease, or claim_fees.")
|
|
5821
|
+
if protocol not in {"V3", "V4"}:
|
|
5822
|
+
raise WalletBackendError("protocol must be V3 or V4.")
|
|
5823
|
+
if not isinstance(request, dict):
|
|
5824
|
+
raise WalletBackendError("request must be an object.")
|
|
5825
|
+
if mode not in {"preview", "prepare", "execute"}:
|
|
5826
|
+
raise WalletBackendError("mode must be 'preview', 'prepare' or 'execute'.")
|
|
5827
|
+
if not isinstance(purpose, str) or not purpose.strip():
|
|
5828
|
+
raise WalletBackendError("purpose is required.")
|
|
5829
|
+
# The caller must not override values that are derived from the
|
|
5830
|
+
# active wallet/network in the WDK layer.
|
|
5831
|
+
forbidden = {"walletAddress", "chainId", "protocol", "simulateTransaction", "signature", "batchPermitData", "v4BatchPermitData", "v3NftPermitData"}
|
|
5832
|
+
overlap = forbidden.intersection(request)
|
|
5833
|
+
if overlap:
|
|
5834
|
+
raise WalletBackendError(f"request must not set wallet-controlled fields: {', '.join(sorted(overlap))}.")
|
|
5835
|
+
preview_kwargs = {"action": action, "protocol": protocol, "request": dict(request)}
|
|
5836
|
+
if mode == "preview":
|
|
5837
|
+
preview = await active_backend.preview_uniswap_liquidity(**preview_kwargs)
|
|
5838
|
+
return AgentToolResult(tool=tool_name, ok=True, data=self._annotate_sensitive_payload(preview, action_label="Uniswap liquidity", mode="preview"))
|
|
5839
|
+
if mode == "prepare":
|
|
5840
|
+
self._require_prepare_intent(user_intent)
|
|
5841
|
+
preview = await active_backend.preview_uniswap_liquidity(**preview_kwargs)
|
|
5842
|
+
return AgentToolResult(tool=tool_name, ok=True, data=self._annotate_sensitive_payload(self._build_prepare_plan(preview_payload=preview, action_label="Uniswap liquidity"), action_label="Uniswap liquidity", mode="prepare"))
|
|
5843
|
+
if isinstance(approval_token, str) and approval_token.strip():
|
|
5844
|
+
approval_payload = inspect_approval_token(
|
|
5845
|
+
approval_token,
|
|
5846
|
+
tool_name=tool_name,
|
|
5847
|
+
network=str(getattr(active_backend, "network", "unknown")),
|
|
5848
|
+
require_mainnet_confirmation=self._is_mainnet_for_backend(active_backend),
|
|
5849
|
+
)
|
|
5850
|
+
approval_summary = approval_payload.get("binding", {}).get("summary")
|
|
5851
|
+
if not isinstance(approval_summary, dict):
|
|
5852
|
+
raise WalletBackendError("approval_token does not match the requested LP operation. Generate a new approval after prepare.")
|
|
5853
|
+
approval_summary_copy = dict(approval_summary)
|
|
5854
|
+
else:
|
|
5855
|
+
fresh_preview = await active_backend.preview_uniswap_liquidity(**preview_kwargs)
|
|
5856
|
+
approval_summary_copy = self._build_confirmation_summary(action_label="Uniswap liquidity", payload=fresh_preview)
|
|
5857
|
+
expected = {
|
|
5858
|
+
"operation": "Uniswap liquidity",
|
|
5859
|
+
"network": str(getattr(active_backend, "network", "unknown")),
|
|
5860
|
+
"liquidity_action": action,
|
|
5861
|
+
"liquidity_protocol": protocol,
|
|
5862
|
+
}
|
|
5863
|
+
for key, value in expected.items():
|
|
5864
|
+
if approval_summary_copy.get(key) != value:
|
|
5865
|
+
raise WalletBackendError("approval_token does not match the requested LP operation. Generate a new approval after prepare.")
|
|
5866
|
+
# An LP intent deliberately does not bind API-calculated ticks,
|
|
5867
|
+
# price, calldata, or quote amounts: those are regenerated just
|
|
5868
|
+
# before broadcast. It must still be scoped to the selected
|
|
5869
|
+
# assets/pool/position so an approval cannot be reused for a
|
|
5870
|
+
# different liquidity position.
|
|
5871
|
+
requested_scope = self._build_confirmation_summary(
|
|
5872
|
+
action_label="Uniswap liquidity",
|
|
5873
|
+
payload={
|
|
5874
|
+
"asset_type": "evm-uniswap-liquidity",
|
|
5875
|
+
"network": str(getattr(active_backend, "network", "unknown")),
|
|
5876
|
+
"protocol": "uniswap",
|
|
5877
|
+
"liquidity_action": action,
|
|
5878
|
+
"liquidity_protocol": protocol,
|
|
5879
|
+
"request": preview_kwargs["request"],
|
|
5880
|
+
},
|
|
5881
|
+
)
|
|
5882
|
+
for key in ("token0_address", "token1_address", "pool_reference", "position_token_id", "independent_token"):
|
|
5883
|
+
requested_value = requested_scope.get(key)
|
|
5884
|
+
if requested_value is not None and approval_summary_copy.get(key) != requested_value:
|
|
5885
|
+
raise WalletBackendError("approval_token does not match the requested LP assets or position. Generate a new approval after prepare.")
|
|
5886
|
+
self._require_execute_approval(
|
|
5887
|
+
approval_token=approval_token,
|
|
5888
|
+
tool_name=tool_name,
|
|
5889
|
+
summary=approval_summary_copy,
|
|
5890
|
+
action_label="Uniswap liquidity",
|
|
5891
|
+
backend=active_backend,
|
|
5892
|
+
)
|
|
5893
|
+
result = await active_backend.send_uniswap_liquidity(**preview_kwargs)
|
|
5894
|
+
return AgentToolResult(tool=tool_name, ok=True, data=self._annotate_sensitive_payload(result, action_label="Uniswap liquidity", mode="execute"))
|
|
5895
|
+
|
|
5760
5896
|
if tool_name == "issue_wallet_approval":
|
|
5761
5897
|
from agent_wallet.approval import issue_approval_token
|
|
5762
5898
|
|
|
@@ -40,6 +40,8 @@ LONG_RUNNING_POST_PATHS = {
|
|
|
40
40
|
"/v1/evm/swap/send",
|
|
41
41
|
"/v1/evm/uniswap/swap/quote",
|
|
42
42
|
"/v1/evm/uniswap/swap/send",
|
|
43
|
+
"/v1/evm/uniswap/liquidity/quote",
|
|
44
|
+
"/v1/evm/uniswap/liquidity/send",
|
|
43
45
|
"/v1/evm/lifi/quote",
|
|
44
46
|
"/v1/evm/lifi/send",
|
|
45
47
|
"/v1/evm/transfer/send",
|
|
@@ -504,7 +504,15 @@ def _requirement_compatibility(requirement: dict[str, Any], backend: AgentWallet
|
|
|
504
504
|
elif chain == "evm" and scheme == "upto" and not _evm_payment_requirement_supported(requirement):
|
|
505
505
|
reason = "This EVM upto payment is missing a facilitatorAddress in its extra data, so it cannot be signed."
|
|
506
506
|
elif planned_execution_supported and wallet_network_matches:
|
|
507
|
-
|
|
507
|
+
if chain == "solana" and getattr(backend, "read_only", False):
|
|
508
|
+
reason = (
|
|
509
|
+
"Signer not loaded in this read-only preview context by "
|
|
510
|
+
"design (avoids unnecessary key material access on cheap "
|
|
511
|
+
"preview calls) -- the real x402_pay_request call loads "
|
|
512
|
+
"the signer and can still succeed here."
|
|
513
|
+
)
|
|
514
|
+
else:
|
|
515
|
+
reason = "Wallet network matches, but this backend does not yet expose a supported x402 signer path."
|
|
508
516
|
elif planned_execution_supported:
|
|
509
517
|
reason = "Planned execution path exists, but the requirement targets a different network than the active wallet."
|
|
510
518
|
else:
|
|
@@ -528,6 +528,7 @@ def create_openclaw_solana_backend(
|
|
|
528
528
|
signer=signer,
|
|
529
529
|
address=resolved_address or None,
|
|
530
530
|
sign_only=effective_sign_only,
|
|
531
|
+
read_only=read_only,
|
|
531
532
|
rpc_provider_mode=str(rpc_config["mode"]),
|
|
532
533
|
rpc_provider=str(rpc_config["provider"]),
|
|
533
534
|
rpc_transport=str(rpc_config["transport"]),
|
|
@@ -554,6 +555,7 @@ def create_openclaw_solana_backend(
|
|
|
554
555
|
signer=None,
|
|
555
556
|
address=wallet_info["address"] or None,
|
|
556
557
|
sign_only=effective_sign_only,
|
|
558
|
+
read_only=read_only,
|
|
557
559
|
rpc_provider_mode=str(rpc_config["mode"]),
|
|
558
560
|
rpc_provider=str(rpc_config["provider"]),
|
|
559
561
|
rpc_transport=str(rpc_config["transport"]),
|
|
@@ -349,6 +349,24 @@ class AgentWalletBackend(ABC):
|
|
|
349
349
|
) -> dict[str, Any]:
|
|
350
350
|
raise WalletBackendError(f"{self.name} does not support Uniswap swaps.")
|
|
351
351
|
|
|
352
|
+
async def preview_uniswap_liquidity(
|
|
353
|
+
self,
|
|
354
|
+
*,
|
|
355
|
+
action: str,
|
|
356
|
+
protocol: str,
|
|
357
|
+
request: dict[str, Any],
|
|
358
|
+
) -> dict[str, Any]:
|
|
359
|
+
raise WalletBackendError(f"{self.name} does not support Uniswap liquidity previews.")
|
|
360
|
+
|
|
361
|
+
async def send_uniswap_liquidity(
|
|
362
|
+
self,
|
|
363
|
+
*,
|
|
364
|
+
action: str,
|
|
365
|
+
protocol: str,
|
|
366
|
+
request: dict[str, Any],
|
|
367
|
+
) -> dict[str, Any]:
|
|
368
|
+
raise WalletBackendError(f"{self.name} does not support Uniswap liquidity operations.")
|
|
369
|
+
|
|
352
370
|
async def preview_evm_native_transfer(
|
|
353
371
|
self,
|
|
354
372
|
*,
|
|
@@ -261,6 +261,7 @@ class SolanaWalletBackend(AgentWalletBackend):
|
|
|
261
261
|
signer: SolanaLocalKeypairSigner | None = None,
|
|
262
262
|
address: str | None = None,
|
|
263
263
|
sign_only: bool = True,
|
|
264
|
+
read_only: bool = False,
|
|
264
265
|
rpc_provider_mode: str | None = None,
|
|
265
266
|
rpc_provider: str | None = None,
|
|
266
267
|
rpc_transport: str | None = None,
|
|
@@ -281,6 +282,7 @@ class SolanaWalletBackend(AgentWalletBackend):
|
|
|
281
282
|
self.commitment = commitment
|
|
282
283
|
self.network = normalize_solana_network(network)
|
|
283
284
|
self.signer = signer
|
|
285
|
+
self.read_only = read_only
|
|
284
286
|
self.address = final_address
|
|
285
287
|
self.sign_only = sign_only
|
|
286
288
|
self.rpc_provider_mode = rpc_provider_mode
|
|
@@ -2028,6 +2028,103 @@ class WdkEvmLocalWalletBackend(AgentWalletBackend):
|
|
|
2028
2028
|
"source": str(data.get("source") or "wdk-evm-wallet"),
|
|
2029
2029
|
}
|
|
2030
2030
|
|
|
2031
|
+
def _normalize_uniswap_liquidity_payload(
|
|
2032
|
+
self,
|
|
2033
|
+
data: dict[str, Any],
|
|
2034
|
+
*,
|
|
2035
|
+
action: str,
|
|
2036
|
+
protocol: str,
|
|
2037
|
+
) -> dict[str, Any]:
|
|
2038
|
+
transaction = dict(data.get("transaction") or {})
|
|
2039
|
+
result = dict(data.get("result") or {})
|
|
2040
|
+
request = dict(data.get("request") or {})
|
|
2041
|
+
return {
|
|
2042
|
+
"chain": self.chain,
|
|
2043
|
+
"network": self.network,
|
|
2044
|
+
"asset_type": "evm-uniswap-liquidity",
|
|
2045
|
+
"protocol": str(data.get("protocol") or "uniswap"),
|
|
2046
|
+
"liquidity_action": str(data.get("liquidityAction") or action),
|
|
2047
|
+
"liquidity_protocol": str(data.get("liquidityProtocol") or protocol).upper(),
|
|
2048
|
+
"from_address": str(data.get("address") or "").strip() or None,
|
|
2049
|
+
"request": request,
|
|
2050
|
+
"request_id": str(data.get("requestId") or "").strip() or None,
|
|
2051
|
+
"token0": data.get("token0"),
|
|
2052
|
+
"token1": data.get("token1"),
|
|
2053
|
+
"tick_lower": data.get("tickLower"),
|
|
2054
|
+
"tick_upper": data.get("tickUpper"),
|
|
2055
|
+
"adjusted_min_price": data.get("adjustedMinPrice"),
|
|
2056
|
+
"adjusted_max_price": data.get("adjustedMaxPrice"),
|
|
2057
|
+
"position_token_id": str(data.get("positionTokenId") or "").strip() or None,
|
|
2058
|
+
"position_manager": str(data.get("positionManager") or "").strip() or None,
|
|
2059
|
+
"gas_fee": str(data.get("gasFee")) if data.get("gasFee") is not None else None,
|
|
2060
|
+
"approvals": list(data.get("approvals") or []),
|
|
2061
|
+
"approval_results": list(data.get("approvalResults") or []),
|
|
2062
|
+
"simulation": _normalize_swap_simulation(data.get("simulation")),
|
|
2063
|
+
"transaction": {
|
|
2064
|
+
"to": str(transaction.get("to") or "").strip() or None,
|
|
2065
|
+
"value": str(transaction.get("value") or "0"),
|
|
2066
|
+
"data_hash": str(transaction.get("dataHash") or "").strip() or None,
|
|
2067
|
+
},
|
|
2068
|
+
"hash": result.get("hash"),
|
|
2069
|
+
"result": result,
|
|
2070
|
+
"chain_id": int(data.get("chainId") or 0),
|
|
2071
|
+
"broadcasted": bool(result.get("hash")),
|
|
2072
|
+
"confirmed": bool(data.get("confirmed")),
|
|
2073
|
+
"source": str(data.get("source") or "wdk-evm-wallet"),
|
|
2074
|
+
}
|
|
2075
|
+
|
|
2076
|
+
async def preview_uniswap_liquidity(
|
|
2077
|
+
self,
|
|
2078
|
+
*,
|
|
2079
|
+
action: str,
|
|
2080
|
+
protocol: str,
|
|
2081
|
+
request: dict[str, Any],
|
|
2082
|
+
) -> dict[str, Any]:
|
|
2083
|
+
if not isinstance(request, dict):
|
|
2084
|
+
raise WalletBackendError("Uniswap liquidity request must be an object.")
|
|
2085
|
+
data = await self.client.post(
|
|
2086
|
+
"/v1/evm/uniswap/liquidity/quote",
|
|
2087
|
+
{
|
|
2088
|
+
"walletId": self.wallet_id,
|
|
2089
|
+
"address": await self.get_address(),
|
|
2090
|
+
"accountIndex": self.account_index,
|
|
2091
|
+
"network": self.network,
|
|
2092
|
+
"action": action,
|
|
2093
|
+
"protocol": protocol,
|
|
2094
|
+
"request": request,
|
|
2095
|
+
},
|
|
2096
|
+
)
|
|
2097
|
+
normalized = self._normalize_uniswap_liquidity_payload(data, action=action, protocol=protocol)
|
|
2098
|
+
normalized["from_address"] = await self.get_address()
|
|
2099
|
+
normalized["execution_supported"] = not self.sign_only
|
|
2100
|
+
return normalized
|
|
2101
|
+
|
|
2102
|
+
async def send_uniswap_liquidity(
|
|
2103
|
+
self,
|
|
2104
|
+
*,
|
|
2105
|
+
action: str,
|
|
2106
|
+
protocol: str,
|
|
2107
|
+
request: dict[str, Any],
|
|
2108
|
+
) -> dict[str, Any]:
|
|
2109
|
+
if self.sign_only:
|
|
2110
|
+
raise WalletBackendError("wdk_evm_local is configured as sign_only.")
|
|
2111
|
+
if not isinstance(request, dict):
|
|
2112
|
+
raise WalletBackendError("Uniswap liquidity request must be an object.")
|
|
2113
|
+
data = await self.client.post(
|
|
2114
|
+
"/v1/evm/uniswap/liquidity/send",
|
|
2115
|
+
{
|
|
2116
|
+
"walletId": self.wallet_id,
|
|
2117
|
+
"accountIndex": self.account_index,
|
|
2118
|
+
"network": self.network,
|
|
2119
|
+
"action": action,
|
|
2120
|
+
"protocol": protocol,
|
|
2121
|
+
"request": request,
|
|
2122
|
+
},
|
|
2123
|
+
)
|
|
2124
|
+
normalized = self._normalize_uniswap_liquidity_payload(data, action=action, protocol=protocol)
|
|
2125
|
+
normalized["from_address"] = await self.get_address()
|
|
2126
|
+
return normalized
|
|
2127
|
+
|
|
2031
2128
|
async def preview_evm_lifi_cross_chain_swap(
|
|
2032
2129
|
self,
|
|
2033
2130
|
*,
|
|
@@ -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.94",
|
|
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.94",
|
|
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"
|
|
@@ -58,6 +58,8 @@ no-op once the backend is healthy.
|
|
|
58
58
|
switch the session's active wallet backend to Base so follow-up wallet
|
|
59
59
|
requests default to it.
|
|
60
60
|
- `/wallet-ethereum` — print the Ethereum EVM wallet overview directly in chat.
|
|
61
|
+
- `/cards` -- issue a Laso Finance prepaid card (US or international), paid
|
|
62
|
+
via x402 from the connected wallet.
|
|
61
63
|
- `/agentlayer-autonomous-approve` — enable high-trust autonomous Base swaps
|
|
62
64
|
(`swap_evm_tokens` / `swap_evm_uniswap_tokens` on Base only) without
|
|
63
65
|
per-transaction approvals. In Claude Code this command now asks for an
|