@agentlayer.tech/wallet 0.1.50 → 0.1.53
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 +154 -0
- package/.openclaw/extensions/agent-wallet/index.ts +19 -9
- package/.openclaw/extensions/agent-wallet/openclaw.plugin.json +1 -1
- package/.openclaw/extensions/agent-wallet/package.json +1 -1
- package/CHANGELOG.md +20 -0
- package/VERSION +1 -1
- package/agent-wallet/agent_wallet/__init__.py +1 -1
- package/agent-wallet/agent_wallet/autonomous_permissions.py +110 -17
- package/agent-wallet/agent_wallet/openclaw_adapter.py +221 -109
- package/agent-wallet/agent_wallet/openclaw_cli.py +6 -5
- package/agent-wallet/agent_wallet/providers/wdk_evm_local.py +6 -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/commands/agentlayer-autonomous-approve.md +7 -6
- package/claude-code/plugins/agent-wallet/commands/agentlayer-autonomous-revoke.md +3 -3
- package/codex/plugins/agent-wallet/.codex-plugin/plugin.json +1 -1
- package/codex/plugins/agent-wallet/server.py +15 -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
|
@@ -18,6 +18,17 @@ const PREVIEW_BOUND_SWAP_TOOLS = new Set([
|
|
|
18
18
|
"flash_trade_open_position",
|
|
19
19
|
"flash_trade_close_position",
|
|
20
20
|
]);
|
|
21
|
+
const AUTONOMOUS_BASE_SWAP_TOOLS = new Set([
|
|
22
|
+
"swap_evm_tokens",
|
|
23
|
+
"swap_evm_uniswap_tokens",
|
|
24
|
+
]);
|
|
25
|
+
const AUTONOMOUS_DEFI_TOOLS = new Set([
|
|
26
|
+
"manage_evm_aave_position",
|
|
27
|
+
"manage_evm_lido_position",
|
|
28
|
+
"manage_evm_lido_withdrawal",
|
|
29
|
+
"manage_evm_morpho_market_position",
|
|
30
|
+
"manage_evm_morpho_vault_position",
|
|
31
|
+
]);
|
|
21
32
|
const approvalPreviewCache = new Map();
|
|
22
33
|
const WALLET_TOOL_ONLY_GUIDANCE =
|
|
23
34
|
"Use this wallet tool instead of shelling out to solana CLI, spl-token CLI, curl, or exec. If it fails, surface the wallet-tool error and stop rather than falling back to terminal commands.";
|
|
@@ -127,6 +138,17 @@ function requiresApprovedPreviewPayload(toolName, params = null) {
|
|
|
127
138
|
return PREVIEW_BOUND_SWAP_TOOLS.has(toolName);
|
|
128
139
|
}
|
|
129
140
|
|
|
141
|
+
function shouldLetBackendAuthorizeAutonomousExecution(toolName, params, config) {
|
|
142
|
+
const isBaseSwapTool = AUTONOMOUS_BASE_SWAP_TOOLS.has(toolName);
|
|
143
|
+
const isDefiTool = AUTONOMOUS_DEFI_TOOLS.has(toolName);
|
|
144
|
+
if (!isBaseSwapTool && !isDefiTool) return false;
|
|
145
|
+
if (String(params?.mode || "") !== "execute") return false;
|
|
146
|
+
if (typeof params?.approval_token === "string" && params.approval_token.trim()) return false;
|
|
147
|
+
const network = String(params?.network || config?.network || selectedEvmNetwork || "").trim().toLowerCase();
|
|
148
|
+
if (isBaseSwapTool) return network === "base";
|
|
149
|
+
return network === "base" || network === "ethereum";
|
|
150
|
+
}
|
|
151
|
+
|
|
130
152
|
function looksLikeApprovalContextError(message) {
|
|
131
153
|
const text = String(message || "").toLowerCase();
|
|
132
154
|
return (
|
|
@@ -516,6 +538,7 @@ async function attachApprovalForExecute(api, config, userId, toolName, effective
|
|
|
516
538
|
}
|
|
517
539
|
|
|
518
540
|
if (effectiveParams.approval_token) return null;
|
|
541
|
+
if (shouldLetBackendAuthorizeAutonomousExecution(toolName, effectiveParams, config)) return null;
|
|
519
542
|
|
|
520
543
|
throw new Error(APPROVAL_CONTEXT_MISSING_MESSAGE);
|
|
521
544
|
}
|
|
@@ -697,6 +720,38 @@ const walletSessionToolDefinitions = [
|
|
|
697
720
|
additionalProperties: false,
|
|
698
721
|
},
|
|
699
722
|
},
|
|
723
|
+
{
|
|
724
|
+
name: "agentlayer_autonomous_status",
|
|
725
|
+
description: "Return AgentLayer high-trust autonomous permission status for the combined base_swaps + defi_tools permission group.",
|
|
726
|
+
parameters: { type: "object", properties: {}, additionalProperties: false },
|
|
727
|
+
},
|
|
728
|
+
{
|
|
729
|
+
name: "agentlayer_autonomous_approve",
|
|
730
|
+
description:
|
|
731
|
+
"Enable high-trust autonomous execution for the combined permission group. The scope parameter is kept for compatibility; choosing base_swaps or defi_tools enables both Base Velora/Uniswap swaps and supported EVM DeFi management tools until revoked. This does not cover transfers, bridges, Solana swaps, or generic contract calls.",
|
|
732
|
+
parameters: {
|
|
733
|
+
type: "object",
|
|
734
|
+
properties: {
|
|
735
|
+
scope: { type: "string", enum: ["base_swaps", "defi_tools"], description: "Compatibility scope; either value enables the full autonomous permission group." },
|
|
736
|
+
purpose: { type: "string" },
|
|
737
|
+
user_intent: { type: "boolean" },
|
|
738
|
+
},
|
|
739
|
+
required: ["scope", "purpose", "user_intent"],
|
|
740
|
+
additionalProperties: false,
|
|
741
|
+
},
|
|
742
|
+
},
|
|
743
|
+
{
|
|
744
|
+
name: "agentlayer_autonomous_revoke",
|
|
745
|
+
description: "Disable the full high-trust autonomous permission group. The scope parameter is kept for compatibility; either value revokes base_swaps and defi_tools together.",
|
|
746
|
+
parameters: {
|
|
747
|
+
type: "object",
|
|
748
|
+
properties: {
|
|
749
|
+
scope: { type: "string", enum: ["base_swaps", "defi_tools"], description: "Compatibility scope; either value revokes the full autonomous permission group." },
|
|
750
|
+
},
|
|
751
|
+
required: ["scope"],
|
|
752
|
+
additionalProperties: false,
|
|
753
|
+
},
|
|
754
|
+
},
|
|
700
755
|
{
|
|
701
756
|
name: "x402_search_services",
|
|
702
757
|
description:
|
|
@@ -1689,6 +1744,105 @@ const evmToolDefinitions = [
|
|
|
1689
1744
|
additionalProperties: false,
|
|
1690
1745
|
},
|
|
1691
1746
|
},
|
|
1747
|
+
{
|
|
1748
|
+
name: "get_evm_morpho_vaults",
|
|
1749
|
+
description: "Get read-only Morpho vault discovery and detail data for the configured EVM network on supported mainnet chains. When listing, results are ordered (default: largest TVL first) and can be filtered by underlying asset.",
|
|
1750
|
+
parameters: {
|
|
1751
|
+
type: "object",
|
|
1752
|
+
properties: {
|
|
1753
|
+
vault_address: { type: "string", description: "Optional explicit vault address for a single-vault lookup." },
|
|
1754
|
+
limit: { type: "integer", minimum: 1, maximum: 500 },
|
|
1755
|
+
listed_only: { type: "boolean", description: "Filter to listed vaults only. Defaults to true." },
|
|
1756
|
+
asset_address: { type: "string", description: "Optional underlying asset address filter (e.g. only USDC vaults)." },
|
|
1757
|
+
order_by: {
|
|
1758
|
+
type: "string",
|
|
1759
|
+
enum: ["TotalAssetsUsd", "TotalAssets", "TotalSupply", "Liquidity", "LiquidityUsd", "Apy", "NetApy", "Address"],
|
|
1760
|
+
description: "Sort field when listing. Defaults to TotalAssetsUsd.",
|
|
1761
|
+
},
|
|
1762
|
+
order_direction: { type: "string", enum: ["asc", "desc"], description: "Sort direction. Defaults to desc." },
|
|
1763
|
+
network: { type: "string", enum: ["ethereum", "base"] },
|
|
1764
|
+
},
|
|
1765
|
+
additionalProperties: false,
|
|
1766
|
+
},
|
|
1767
|
+
},
|
|
1768
|
+
{
|
|
1769
|
+
name: "get_evm_morpho_markets",
|
|
1770
|
+
description: "Get read-only Morpho market discovery and detail data for the configured EVM network on supported mainnet chains. When listing, results are ordered (default: largest supply first) and can be filtered by free-text search or by collateral/loan asset.",
|
|
1771
|
+
parameters: {
|
|
1772
|
+
type: "object",
|
|
1773
|
+
properties: {
|
|
1774
|
+
market_id: { type: "string", description: "Optional explicit market id (32-byte hex) for a single-market lookup." },
|
|
1775
|
+
limit: { type: "integer", minimum: 1, maximum: 500 },
|
|
1776
|
+
listed_only: { type: "boolean", description: "Filter to listed markets only. Defaults to true." },
|
|
1777
|
+
search: { type: "string", description: "Optional free-text search over market/asset symbols (e.g. 'wstETH')." },
|
|
1778
|
+
collateral_asset_address: { type: "string", description: "Optional collateral asset address filter." },
|
|
1779
|
+
loan_asset_address: { type: "string", description: "Optional loan asset address filter." },
|
|
1780
|
+
order_by: {
|
|
1781
|
+
type: "string",
|
|
1782
|
+
enum: ["SupplyAssetsUsd", "BorrowAssetsUsd", "SupplyApy", "NetSupplyApy", "BorrowApy", "NetBorrowApy", "Utilization", "TotalLiquidityUsd", "Lltv"],
|
|
1783
|
+
description: "Sort field when listing. Defaults to SupplyAssetsUsd.",
|
|
1784
|
+
},
|
|
1785
|
+
order_direction: { type: "string", enum: ["asc", "desc"], description: "Sort direction. Defaults to desc." },
|
|
1786
|
+
network: { type: "string", enum: ["ethereum", "base"] },
|
|
1787
|
+
},
|
|
1788
|
+
additionalProperties: false,
|
|
1789
|
+
},
|
|
1790
|
+
},
|
|
1791
|
+
{
|
|
1792
|
+
name: "get_evm_morpho_positions",
|
|
1793
|
+
description: "Get read-only Morpho vault and market positions for the configured EVM wallet on supported mainnet chains.",
|
|
1794
|
+
parameters: {
|
|
1795
|
+
type: "object",
|
|
1796
|
+
properties: {
|
|
1797
|
+
network: { type: "string", enum: ["ethereum", "base"] },
|
|
1798
|
+
},
|
|
1799
|
+
additionalProperties: false,
|
|
1800
|
+
},
|
|
1801
|
+
},
|
|
1802
|
+
{
|
|
1803
|
+
name: "manage_evm_morpho_vault_position",
|
|
1804
|
+
description: "Preview, prepare, or execute a narrow Morpho vault operation on supported EVM mainnet networks. Supported operations are supply and withdraw. 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.",
|
|
1805
|
+
optional: true,
|
|
1806
|
+
parameters: {
|
|
1807
|
+
type: "object",
|
|
1808
|
+
properties: {
|
|
1809
|
+
operation: { type: "string", enum: ["supply", "withdraw"] },
|
|
1810
|
+
token_address: { type: "string" },
|
|
1811
|
+
vault_address: { type: "string" },
|
|
1812
|
+
vault_preset: { type: "string" },
|
|
1813
|
+
amount_raw: { type: "string" },
|
|
1814
|
+
native_amount_raw: { type: "string" },
|
|
1815
|
+
mode: { type: "string", enum: ["preview", "prepare", "execute"] },
|
|
1816
|
+
purpose: { type: "string" },
|
|
1817
|
+
user_intent: { type: "boolean" },
|
|
1818
|
+
network: { type: "string", enum: ["ethereum", "base"] },
|
|
1819
|
+
},
|
|
1820
|
+
required: ["operation", "token_address", "mode", "purpose"],
|
|
1821
|
+
additionalProperties: false,
|
|
1822
|
+
},
|
|
1823
|
+
},
|
|
1824
|
+
{
|
|
1825
|
+
name: "manage_evm_morpho_market_position",
|
|
1826
|
+
description: "Preview, prepare, or execute a narrow Morpho market operation on supported EVM mainnet networks. Supported operations are supply_collateral, borrow, repay, and withdraw_collateral. 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.",
|
|
1827
|
+
optional: true,
|
|
1828
|
+
parameters: {
|
|
1829
|
+
type: "object",
|
|
1830
|
+
properties: {
|
|
1831
|
+
operation: { type: "string", enum: ["supply_collateral", "borrow", "repay", "withdraw_collateral"] },
|
|
1832
|
+
token_address: { type: "string" },
|
|
1833
|
+
market_id: { type: "string" },
|
|
1834
|
+
market_preset: { type: "string" },
|
|
1835
|
+
amount_raw: { type: "string" },
|
|
1836
|
+
native_amount_raw: { type: "string" },
|
|
1837
|
+
mode: { type: "string", enum: ["preview", "prepare", "execute"] },
|
|
1838
|
+
purpose: { type: "string" },
|
|
1839
|
+
user_intent: { type: "boolean" },
|
|
1840
|
+
network: { type: "string", enum: ["ethereum", "base"] },
|
|
1841
|
+
},
|
|
1842
|
+
required: ["operation", "token_address", "mode", "purpose"],
|
|
1843
|
+
additionalProperties: false,
|
|
1844
|
+
},
|
|
1845
|
+
},
|
|
1692
1846
|
{
|
|
1693
1847
|
name: "get_evm_swap_quote",
|
|
1694
1848
|
description: "Get a read-only Velora quote for an ERC-20 or native ETH swap on supported EVM mainnet networks. This does not approve or execute a swap.",
|
|
@@ -22,6 +22,13 @@ const AUTONOMOUS_BASE_SWAP_TOOLS = new Set([
|
|
|
22
22
|
"swap_evm_tokens",
|
|
23
23
|
"swap_evm_uniswap_tokens",
|
|
24
24
|
]);
|
|
25
|
+
const AUTONOMOUS_DEFI_TOOLS = new Set([
|
|
26
|
+
"manage_evm_aave_position",
|
|
27
|
+
"manage_evm_lido_position",
|
|
28
|
+
"manage_evm_lido_withdrawal",
|
|
29
|
+
"manage_evm_morpho_market_position",
|
|
30
|
+
"manage_evm_morpho_vault_position",
|
|
31
|
+
]);
|
|
25
32
|
const approvalPreviewCache = new Map();
|
|
26
33
|
const WALLET_TOOL_ONLY_GUIDANCE =
|
|
27
34
|
"Use this wallet tool instead of shelling out to solana CLI, spl-token CLI, curl, or exec. If it fails, surface the wallet-tool error and stop rather than falling back to terminal commands.";
|
|
@@ -131,12 +138,15 @@ function requiresApprovedPreviewPayload(toolName, params = null) {
|
|
|
131
138
|
return PREVIEW_BOUND_SWAP_TOOLS.has(toolName);
|
|
132
139
|
}
|
|
133
140
|
|
|
134
|
-
function
|
|
135
|
-
|
|
141
|
+
function shouldLetBackendAuthorizeAutonomousExecution(toolName, params, config) {
|
|
142
|
+
const isBaseSwapTool = AUTONOMOUS_BASE_SWAP_TOOLS.has(toolName);
|
|
143
|
+
const isDefiTool = AUTONOMOUS_DEFI_TOOLS.has(toolName);
|
|
144
|
+
if (!isBaseSwapTool && !isDefiTool) return false;
|
|
136
145
|
if (String(params?.mode || "") !== "execute") return false;
|
|
137
146
|
if (typeof params?.approval_token === "string" && params.approval_token.trim()) return false;
|
|
138
147
|
const network = String(params?.network || config?.network || selectedEvmNetwork || "").trim().toLowerCase();
|
|
139
|
-
return network === "base";
|
|
148
|
+
if (isBaseSwapTool) return network === "base";
|
|
149
|
+
return network === "base" || network === "ethereum";
|
|
140
150
|
}
|
|
141
151
|
|
|
142
152
|
function looksLikeApprovalContextError(message) {
|
|
@@ -528,7 +538,7 @@ async function attachApprovalForExecute(api, config, userId, toolName, effective
|
|
|
528
538
|
}
|
|
529
539
|
|
|
530
540
|
if (effectiveParams.approval_token) return null;
|
|
531
|
-
if (
|
|
541
|
+
if (shouldLetBackendAuthorizeAutonomousExecution(toolName, effectiveParams, config)) return null;
|
|
532
542
|
|
|
533
543
|
throw new Error(APPROVAL_CONTEXT_MISSING_MESSAGE);
|
|
534
544
|
}
|
|
@@ -712,17 +722,17 @@ const walletSessionToolDefinitions = [
|
|
|
712
722
|
},
|
|
713
723
|
{
|
|
714
724
|
name: "agentlayer_autonomous_status",
|
|
715
|
-
description: "Return AgentLayer high-trust autonomous permission status
|
|
725
|
+
description: "Return AgentLayer high-trust autonomous permission status for the combined base_swaps + defi_tools permission group.",
|
|
716
726
|
parameters: { type: "object", properties: {}, additionalProperties: false },
|
|
717
727
|
},
|
|
718
728
|
{
|
|
719
729
|
name: "agentlayer_autonomous_approve",
|
|
720
730
|
description:
|
|
721
|
-
"Enable high-trust autonomous
|
|
731
|
+
"Enable high-trust autonomous execution for the combined permission group. The scope parameter is kept for compatibility; choosing base_swaps or defi_tools enables both Base Velora/Uniswap swaps and supported EVM DeFi management tools until revoked. This does not cover transfers, bridges, Solana swaps, or generic contract calls.",
|
|
722
732
|
parameters: {
|
|
723
733
|
type: "object",
|
|
724
734
|
properties: {
|
|
725
|
-
scope: { type: "string", enum: ["base_swaps"] },
|
|
735
|
+
scope: { type: "string", enum: ["base_swaps", "defi_tools"], description: "Compatibility scope; either value enables the full autonomous permission group." },
|
|
726
736
|
purpose: { type: "string" },
|
|
727
737
|
user_intent: { type: "boolean" },
|
|
728
738
|
},
|
|
@@ -732,11 +742,11 @@ const walletSessionToolDefinitions = [
|
|
|
732
742
|
},
|
|
733
743
|
{
|
|
734
744
|
name: "agentlayer_autonomous_revoke",
|
|
735
|
-
description: "Disable high-trust autonomous
|
|
745
|
+
description: "Disable the full high-trust autonomous permission group. The scope parameter is kept for compatibility; either value revokes base_swaps and defi_tools together.",
|
|
736
746
|
parameters: {
|
|
737
747
|
type: "object",
|
|
738
748
|
properties: {
|
|
739
|
-
scope: { type: "string", enum: ["base_swaps"] },
|
|
749
|
+
scope: { type: "string", enum: ["base_swaps", "defi_tools"], description: "Compatibility scope; either value revokes the full autonomous permission group." },
|
|
740
750
|
},
|
|
741
751
|
required: ["scope"],
|
|
742
752
|
additionalProperties: false,
|
|
@@ -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.53",
|
|
6
6
|
"contracts": {
|
|
7
7
|
"tools": [
|
|
8
8
|
"agentlayer_autonomous_approve",
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## v0.1.53 - 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.
|
|
1
|
+
0.1.53
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This module is intentionally narrower than ``autonomous_session``. It models
|
|
4
4
|
the "CLI permissions" UX where a user grants a standing capability, not a
|
|
5
|
-
budgeted policy envelope.
|
|
5
|
+
budgeted policy envelope.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
@@ -22,6 +22,19 @@ BASE_SWAP_SCOPE = "base_swaps"
|
|
|
22
22
|
BASE_SWAP_NETWORK = "base"
|
|
23
23
|
BASE_SWAP_TOOLS = frozenset({"swap_evm_tokens", "swap_evm_uniswap_tokens"})
|
|
24
24
|
BASE_SWAP_ISSUER = "autonomous-permission:base-swaps"
|
|
25
|
+
DEFI_TOOLS_SCOPE = "defi_tools"
|
|
26
|
+
DEFI_TOOLS_NETWORKS = frozenset({"base", "ethereum"})
|
|
27
|
+
DEFI_TOOLS = frozenset(
|
|
28
|
+
{
|
|
29
|
+
"manage_evm_aave_position",
|
|
30
|
+
"manage_evm_lido_position",
|
|
31
|
+
"manage_evm_lido_withdrawal",
|
|
32
|
+
"manage_evm_morpho_market_position",
|
|
33
|
+
"manage_evm_morpho_vault_position",
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
DEFI_TOOLS_ISSUER = "autonomous-permission:defi-tools"
|
|
37
|
+
SUPPORTED_SCOPES = frozenset({BASE_SWAP_SCOPE, DEFI_TOOLS_SCOPE})
|
|
25
38
|
_PERMISSIONS_FILENAME = "autonomous_permissions.json"
|
|
26
39
|
|
|
27
40
|
|
|
@@ -68,6 +81,7 @@ def _scope_status(record: dict[str, Any], scope: str) -> dict[str, Any]:
|
|
|
68
81
|
"approved_at": raw.get("approved_at"),
|
|
69
82
|
"approved_by": raw.get("approved_by"),
|
|
70
83
|
"network": raw.get("network"),
|
|
84
|
+
"networks": raw.get("networks") or ([raw.get("network")] if raw.get("network") else []),
|
|
71
85
|
"tools": raw.get("tools") or [],
|
|
72
86
|
"warning": raw.get("warning"),
|
|
73
87
|
}
|
|
@@ -77,17 +91,16 @@ def status() -> dict[str, Any]:
|
|
|
77
91
|
"""Return current high-trust autonomous permission status."""
|
|
78
92
|
record = _load_record()
|
|
79
93
|
base_swaps = _scope_status(record, BASE_SWAP_SCOPE)
|
|
94
|
+
defi_tools = _scope_status(record, DEFI_TOOLS_SCOPE)
|
|
95
|
+
group_enabled = all(bool(scope.get("enabled")) for scope in (base_swaps, defi_tools))
|
|
80
96
|
return {
|
|
81
|
-
"active":
|
|
82
|
-
"scopes": {BASE_SWAP_SCOPE: base_swaps},
|
|
97
|
+
"active": group_enabled,
|
|
98
|
+
"scopes": {BASE_SWAP_SCOPE: base_swaps, DEFI_TOOLS_SCOPE: defi_tools},
|
|
83
99
|
"permission_file": str(_permissions_path()),
|
|
84
100
|
}
|
|
85
101
|
|
|
86
102
|
|
|
87
|
-
def
|
|
88
|
-
"""Enable unattended Base swap execution for supported EVM swap tools."""
|
|
89
|
-
record = _load_record()
|
|
90
|
-
scopes = record.setdefault("scopes", {})
|
|
103
|
+
def _set_base_swap_scope(scopes: dict[str, Any], *, approved_by: str) -> None:
|
|
91
104
|
scopes[BASE_SWAP_SCOPE] = {
|
|
92
105
|
"enabled": True,
|
|
93
106
|
"approved_at": _now(),
|
|
@@ -99,26 +112,81 @@ def approve_base_swaps(*, approved_by: str = "user") -> dict[str, Any]:
|
|
|
99
112
|
"per-transaction human approval until revoked."
|
|
100
113
|
),
|
|
101
114
|
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _set_defi_tools_scope(scopes: dict[str, Any], *, approved_by: str) -> None:
|
|
118
|
+
scopes[DEFI_TOOLS_SCOPE] = {
|
|
119
|
+
"enabled": True,
|
|
120
|
+
"approved_at": _now(),
|
|
121
|
+
"approved_by": str(approved_by or "user"),
|
|
122
|
+
"networks": sorted(DEFI_TOOLS_NETWORKS),
|
|
123
|
+
"tools": sorted(DEFI_TOOLS),
|
|
124
|
+
"warning": (
|
|
125
|
+
"High-trust permission: supported EVM DeFi execute calls can run "
|
|
126
|
+
"without per-transaction human approval until revoked."
|
|
127
|
+
),
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def approve_all(*, approved_by: str = "user") -> dict[str, Any]:
|
|
132
|
+
"""Enable all high-trust autonomous permission scopes as one group."""
|
|
133
|
+
record = _load_record()
|
|
134
|
+
scopes = record.setdefault("scopes", {})
|
|
135
|
+
normalized_approved_by = str(approved_by or "user")
|
|
136
|
+
_set_base_swap_scope(scopes, approved_by=normalized_approved_by)
|
|
137
|
+
_set_defi_tools_scope(scopes, approved_by=normalized_approved_by)
|
|
102
138
|
_write_record(record)
|
|
103
139
|
return status()
|
|
104
140
|
|
|
105
141
|
|
|
142
|
+
def approve_base_swaps(*, approved_by: str = "user") -> dict[str, Any]:
|
|
143
|
+
"""Enable all autonomous permissions; base_swaps is kept as a compatibility scope."""
|
|
144
|
+
return approve_all(approved_by=approved_by)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def approve_defi_tools(*, approved_by: str = "user") -> dict[str, Any]:
|
|
148
|
+
"""Enable all autonomous permissions; defi_tools is kept as a compatibility scope."""
|
|
149
|
+
return approve_all(approved_by=approved_by)
|
|
150
|
+
|
|
151
|
+
|
|
106
152
|
def revoke_base_swaps() -> dict[str, Any]:
|
|
107
|
-
"""Disable
|
|
153
|
+
"""Disable all autonomous permissions; base_swaps is kept as a compatibility scope."""
|
|
154
|
+
return revoke_all()
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def revoke_defi_tools() -> dict[str, Any]:
|
|
158
|
+
"""Disable all autonomous permissions; defi_tools is kept as a compatibility scope."""
|
|
159
|
+
return revoke_all()
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def revoke_all() -> dict[str, Any]:
|
|
163
|
+
"""Disable every high-trust autonomous permission scope as one group."""
|
|
108
164
|
record = _load_record()
|
|
109
165
|
scopes = record.setdefault("scopes", {})
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
existing
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
166
|
+
for supported_scope in sorted(SUPPORTED_SCOPES):
|
|
167
|
+
existing = scopes.get(supported_scope)
|
|
168
|
+
if isinstance(existing, dict):
|
|
169
|
+
existing["enabled"] = False
|
|
170
|
+
existing["revoked_at"] = _now()
|
|
171
|
+
else:
|
|
172
|
+
scopes[supported_scope] = {"enabled": False, "revoked_at": _now()}
|
|
116
173
|
_write_record(record)
|
|
117
174
|
return status()
|
|
118
175
|
|
|
119
176
|
|
|
177
|
+
def revoke_scope(scope: str) -> dict[str, Any]:
|
|
178
|
+
normalized_scope = str(scope or "").strip()
|
|
179
|
+
if normalized_scope not in SUPPORTED_SCOPES:
|
|
180
|
+
raise WalletBackendError("Unsupported autonomous permission scope.")
|
|
181
|
+
return revoke_all()
|
|
182
|
+
|
|
183
|
+
|
|
120
184
|
def is_base_swap_approved() -> bool:
|
|
121
|
-
return bool(status()["
|
|
185
|
+
return bool(status()["active"])
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def is_defi_tools_approved() -> bool:
|
|
189
|
+
return bool(status()["active"])
|
|
122
190
|
|
|
123
191
|
|
|
124
192
|
def authorize_base_swap(*, tool_name: str, network: str, summary: dict[str, Any]) -> str:
|
|
@@ -129,8 +197,8 @@ def authorize_base_swap(*, tool_name: str, network: str, summary: dict[str, Any]
|
|
|
129
197
|
raise WalletBackendError("Autonomous Base swap permission only applies on network=base.")
|
|
130
198
|
if not is_base_swap_approved():
|
|
131
199
|
raise WalletBackendError(
|
|
132
|
-
"Autonomous
|
|
133
|
-
"agentlayer_autonomous_approve
|
|
200
|
+
"Autonomous execution is not enabled. Ask the user to run "
|
|
201
|
+
"agentlayer_autonomous_approve first."
|
|
134
202
|
)
|
|
135
203
|
summary_network = str((summary or {}).get("network") or "").strip().lower()
|
|
136
204
|
if summary_network and summary_network != BASE_SWAP_NETWORK:
|
|
@@ -143,3 +211,28 @@ def authorize_base_swap(*, tool_name: str, network: str, summary: dict[str, Any]
|
|
|
143
211
|
ttl_seconds=120,
|
|
144
212
|
issued_by=BASE_SWAP_ISSUER,
|
|
145
213
|
)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def authorize_defi_tool(*, tool_name: str, network: str, summary: dict[str, Any]) -> str:
|
|
217
|
+
"""Issue an internal approval token for one exact EVM DeFi operation."""
|
|
218
|
+
normalized_network = str(network or "").strip().lower()
|
|
219
|
+
if str(tool_name) not in DEFI_TOOLS:
|
|
220
|
+
raise WalletBackendError("Autonomous DeFi permission only covers supported EVM DeFi tools.")
|
|
221
|
+
if normalized_network not in DEFI_TOOLS_NETWORKS:
|
|
222
|
+
raise WalletBackendError("Autonomous DeFi permission only applies on ethereum or base.")
|
|
223
|
+
if not is_defi_tools_approved():
|
|
224
|
+
raise WalletBackendError(
|
|
225
|
+
"Autonomous execution is not enabled. Ask the user to run "
|
|
226
|
+
"agentlayer_autonomous_approve first."
|
|
227
|
+
)
|
|
228
|
+
summary_network = str((summary or {}).get("network") or "").strip().lower()
|
|
229
|
+
if summary_network and summary_network != normalized_network:
|
|
230
|
+
raise WalletBackendError("Autonomous DeFi summary is not bound to the active network.")
|
|
231
|
+
return issue_approval_token(
|
|
232
|
+
tool_name=tool_name,
|
|
233
|
+
network=normalized_network,
|
|
234
|
+
summary=summary,
|
|
235
|
+
mainnet_confirmed=True,
|
|
236
|
+
ttl_seconds=120,
|
|
237
|
+
issued_by=DEFI_TOOLS_ISSUER,
|
|
238
|
+
)
|