@agentlayer.tech/wallet 0.1.17 → 0.1.18
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 +105 -7
- package/.openclaw/extensions/agent-wallet/index.ts +105 -7
- package/.openclaw/extensions/agent-wallet/openclaw.plugin.json +5 -1
- package/.openclaw/extensions/agent-wallet/package.json +1 -1
- package/.openclaw/extensions/pay-bridge/package.json +1 -1
- package/CHANGELOG.md +24 -0
- package/agent-wallet/README.md +4 -0
- package/agent-wallet/agent_wallet/openclaw_adapter.py +303 -1
- package/agent-wallet/agent_wallet/providers/x402.py +1323 -0
- package/agent-wallet/agent_wallet/wallet_layer/wdk_evm.py +30 -0
- package/agent-wallet/pyproject.toml +2 -1
- package/agent-wallet/scripts/install_openclaw_local_config.py +8 -1
- package/package.json +1 -1
- package/wdk-evm-wallet/src/server.js +6 -0
- package/wdk-evm-wallet/src/wdk_evm_wallet.js +108 -0
|
@@ -25,6 +25,9 @@ const approvalPreviewCache = new Map();
|
|
|
25
25
|
const privateSwapOrderCache = new Map();
|
|
26
26
|
const WALLET_TOOL_ONLY_GUIDANCE =
|
|
27
27
|
"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.";
|
|
28
|
+
const APPROVAL_PREVIEW_TOOL_ALIASES = new Map([
|
|
29
|
+
["x402_pay_request", "x402_preview_request"],
|
|
30
|
+
]);
|
|
28
31
|
|
|
29
32
|
function canonicalJsonText(payload) {
|
|
30
33
|
const normalize = (value) => {
|
|
@@ -51,6 +54,11 @@ function approvalCacheKey(userId, toolName) {
|
|
|
51
54
|
return `${userId}::${toolName}`;
|
|
52
55
|
}
|
|
53
56
|
|
|
57
|
+
function approvalPreviewToolName(toolName) {
|
|
58
|
+
const normalized = typeof toolName === "string" ? toolName.trim() : "";
|
|
59
|
+
return APPROVAL_PREVIEW_TOOL_ALIASES.get(normalized) || normalized;
|
|
60
|
+
}
|
|
61
|
+
|
|
54
62
|
function pruneApprovalPreviewCache() {
|
|
55
63
|
const now = Date.now();
|
|
56
64
|
for (const [key, value] of approvalPreviewCache.entries()) {
|
|
@@ -61,29 +69,30 @@ function pruneApprovalPreviewCache() {
|
|
|
61
69
|
}
|
|
62
70
|
|
|
63
71
|
function cachePreviewForApproval(userId, toolName, payload) {
|
|
72
|
+
const cacheToolName = approvalPreviewToolName(toolName);
|
|
64
73
|
if (!payload || payload.ok !== true || !payload.data || typeof payload.data !== "object") return;
|
|
65
74
|
const preview = payload.data;
|
|
66
75
|
if (preview.mode !== "preview") return;
|
|
67
76
|
if (!preview.confirmation_summary || typeof preview.confirmation_summary !== "object") return;
|
|
68
77
|
pruneApprovalPreviewCache();
|
|
69
78
|
const digest = previewDigest(preview);
|
|
70
|
-
approvalPreviewCache.set(approvalCacheKey(userId,
|
|
79
|
+
approvalPreviewCache.set(approvalCacheKey(userId, cacheToolName), {
|
|
71
80
|
digest,
|
|
72
81
|
expiresAt:
|
|
73
|
-
|
|
82
|
+
cacheToolName === "swap_solana_privately"
|
|
74
83
|
? Date.now() + PRIVATE_SWAP_CACHE_TTL_MS
|
|
75
84
|
: Date.now() + PREVIEW_CACHE_TTL_MS,
|
|
76
85
|
preview,
|
|
77
86
|
summary: preview.confirmation_summary,
|
|
78
87
|
});
|
|
79
|
-
if (
|
|
80
|
-
privateSwapOrderCache.delete(approvalCacheKey(userId,
|
|
88
|
+
if (cacheToolName === "swap_solana_privately") {
|
|
89
|
+
privateSwapOrderCache.delete(approvalCacheKey(userId, cacheToolName));
|
|
81
90
|
}
|
|
82
91
|
}
|
|
83
92
|
|
|
84
93
|
function latestCachedPreview(userId, toolName) {
|
|
85
94
|
pruneApprovalPreviewCache();
|
|
86
|
-
return approvalPreviewCache.get(approvalCacheKey(userId, toolName)) || null;
|
|
95
|
+
return approvalPreviewCache.get(approvalCacheKey(userId, approvalPreviewToolName(toolName))) || null;
|
|
87
96
|
}
|
|
88
97
|
|
|
89
98
|
function approvalTokenPreviewDigest(token) {
|
|
@@ -498,8 +507,9 @@ async function issueApprovalToken(api, config, userId, toolName, previewPayload)
|
|
|
498
507
|
if (!summary || typeof summary !== "object") {
|
|
499
508
|
throw new Error(`No confirmation_summary available for ${toolName}.`);
|
|
500
509
|
}
|
|
501
|
-
const
|
|
502
|
-
|
|
510
|
+
const summaryForToken = PREVIEW_BOUND_SWAP_TOOLS.has(toolName)
|
|
511
|
+
? { ...summary, _preview_digest: previewDigest(previewPayload) }
|
|
512
|
+
: { ...summary };
|
|
503
513
|
const extraArgs = [
|
|
504
514
|
"--tool",
|
|
505
515
|
toolName,
|
|
@@ -819,6 +829,94 @@ const walletSessionToolDefinitions = [
|
|
|
819
829
|
additionalProperties: false,
|
|
820
830
|
},
|
|
821
831
|
},
|
|
832
|
+
{
|
|
833
|
+
name: "x402_search_services",
|
|
834
|
+
description:
|
|
835
|
+
"Search x402-paid services through CDP Bazaar or Agentic Market. This is read-only discovery and does not spend funds.",
|
|
836
|
+
parameters: {
|
|
837
|
+
type: "object",
|
|
838
|
+
properties: {
|
|
839
|
+
query: { type: "string" },
|
|
840
|
+
discovery_provider: {
|
|
841
|
+
type: "string",
|
|
842
|
+
enum: ["auto", "cdp_bazaar", "agentic_market"],
|
|
843
|
+
},
|
|
844
|
+
network: { type: "string" },
|
|
845
|
+
asset: { type: "string" },
|
|
846
|
+
scheme: { type: "string" },
|
|
847
|
+
max_usd_price: { type: "string" },
|
|
848
|
+
limit: { type: "integer" },
|
|
849
|
+
},
|
|
850
|
+
additionalProperties: false,
|
|
851
|
+
},
|
|
852
|
+
},
|
|
853
|
+
{
|
|
854
|
+
name: "x402_get_service_details",
|
|
855
|
+
description:
|
|
856
|
+
"Resolve one x402 service or resource into a normalized details payload. Use a resource URL for CDP Bazaar or a domain/service id for Agentic Market.",
|
|
857
|
+
parameters: {
|
|
858
|
+
type: "object",
|
|
859
|
+
properties: {
|
|
860
|
+
reference: { type: "string" },
|
|
861
|
+
discovery_provider: {
|
|
862
|
+
type: "string",
|
|
863
|
+
enum: ["auto", "cdp_bazaar", "agentic_market"],
|
|
864
|
+
},
|
|
865
|
+
},
|
|
866
|
+
required: ["reference"],
|
|
867
|
+
additionalProperties: false,
|
|
868
|
+
},
|
|
869
|
+
},
|
|
870
|
+
{
|
|
871
|
+
name: "x402_preview_request",
|
|
872
|
+
description:
|
|
873
|
+
"Make an unpaid HTTP request to an x402 endpoint, detect HTTP 402, parse PAYMENT-REQUIRED, and summarize the payment options. This does not pay or execute.",
|
|
874
|
+
parameters: {
|
|
875
|
+
type: "object",
|
|
876
|
+
properties: {
|
|
877
|
+
url: { type: "string" },
|
|
878
|
+
method: { type: "string" },
|
|
879
|
+
headers: { type: "object", additionalProperties: { type: "string" } },
|
|
880
|
+
query: { type: "object", additionalProperties: true },
|
|
881
|
+
json_body: {},
|
|
882
|
+
text_body: { type: "string" },
|
|
883
|
+
},
|
|
884
|
+
required: ["url"],
|
|
885
|
+
additionalProperties: false,
|
|
886
|
+
},
|
|
887
|
+
},
|
|
888
|
+
{
|
|
889
|
+
name: "x402_pay_request",
|
|
890
|
+
description:
|
|
891
|
+
"Prepare or execute an x402 paid request using the active wallet backend. This milestone executes the Solana exact buyer flow and keeps EVM as prepare-only.",
|
|
892
|
+
parameters: {
|
|
893
|
+
type: "object",
|
|
894
|
+
properties: {
|
|
895
|
+
url: { type: "string" },
|
|
896
|
+
method: { type: "string" },
|
|
897
|
+
headers: { type: "object", additionalProperties: { type: "string" } },
|
|
898
|
+
query: { type: "object", additionalProperties: true },
|
|
899
|
+
json_body: {},
|
|
900
|
+
text_body: { type: "string" },
|
|
901
|
+
mode: {
|
|
902
|
+
type: "string",
|
|
903
|
+
enum: ["prepare", "execute"],
|
|
904
|
+
description: "prepare validates the payment plan; execute sends the paid retry.",
|
|
905
|
+
},
|
|
906
|
+
purpose: { type: "string" },
|
|
907
|
+
user_intent: {
|
|
908
|
+
type: "boolean",
|
|
909
|
+
description: "Must be true for prepare mode.",
|
|
910
|
+
},
|
|
911
|
+
approval_token: {
|
|
912
|
+
type: "string",
|
|
913
|
+
description: "Required for execute mode and must be issued against the exact x402 payment summary.",
|
|
914
|
+
},
|
|
915
|
+
},
|
|
916
|
+
required: ["url", "mode", "purpose"],
|
|
917
|
+
additionalProperties: false,
|
|
918
|
+
},
|
|
919
|
+
},
|
|
822
920
|
{
|
|
823
921
|
name: "get_active_wallet_backend",
|
|
824
922
|
description: "Show which wallet backend is active in this OpenClaw plugin session and whether it differs from the startup plugin config.",
|
|
@@ -25,6 +25,9 @@ const approvalPreviewCache = new Map();
|
|
|
25
25
|
const privateSwapOrderCache = new Map();
|
|
26
26
|
const WALLET_TOOL_ONLY_GUIDANCE =
|
|
27
27
|
"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.";
|
|
28
|
+
const APPROVAL_PREVIEW_TOOL_ALIASES = new Map([
|
|
29
|
+
["x402_pay_request", "x402_preview_request"],
|
|
30
|
+
]);
|
|
28
31
|
|
|
29
32
|
function canonicalJsonText(payload) {
|
|
30
33
|
const normalize = (value) => {
|
|
@@ -51,6 +54,11 @@ function approvalCacheKey(userId, toolName) {
|
|
|
51
54
|
return `${userId}::${toolName}`;
|
|
52
55
|
}
|
|
53
56
|
|
|
57
|
+
function approvalPreviewToolName(toolName) {
|
|
58
|
+
const normalized = typeof toolName === "string" ? toolName.trim() : "";
|
|
59
|
+
return APPROVAL_PREVIEW_TOOL_ALIASES.get(normalized) || normalized;
|
|
60
|
+
}
|
|
61
|
+
|
|
54
62
|
function pruneApprovalPreviewCache() {
|
|
55
63
|
const now = Date.now();
|
|
56
64
|
for (const [key, value] of approvalPreviewCache.entries()) {
|
|
@@ -61,29 +69,30 @@ function pruneApprovalPreviewCache() {
|
|
|
61
69
|
}
|
|
62
70
|
|
|
63
71
|
function cachePreviewForApproval(userId, toolName, payload) {
|
|
72
|
+
const cacheToolName = approvalPreviewToolName(toolName);
|
|
64
73
|
if (!payload || payload.ok !== true || !payload.data || typeof payload.data !== "object") return;
|
|
65
74
|
const preview = payload.data;
|
|
66
75
|
if (preview.mode !== "preview") return;
|
|
67
76
|
if (!preview.confirmation_summary || typeof preview.confirmation_summary !== "object") return;
|
|
68
77
|
pruneApprovalPreviewCache();
|
|
69
78
|
const digest = previewDigest(preview);
|
|
70
|
-
approvalPreviewCache.set(approvalCacheKey(userId,
|
|
79
|
+
approvalPreviewCache.set(approvalCacheKey(userId, cacheToolName), {
|
|
71
80
|
digest,
|
|
72
81
|
expiresAt:
|
|
73
|
-
|
|
82
|
+
cacheToolName === "swap_solana_privately"
|
|
74
83
|
? Date.now() + PRIVATE_SWAP_CACHE_TTL_MS
|
|
75
84
|
: Date.now() + PREVIEW_CACHE_TTL_MS,
|
|
76
85
|
preview,
|
|
77
86
|
summary: preview.confirmation_summary,
|
|
78
87
|
});
|
|
79
|
-
if (
|
|
80
|
-
privateSwapOrderCache.delete(approvalCacheKey(userId,
|
|
88
|
+
if (cacheToolName === "swap_solana_privately") {
|
|
89
|
+
privateSwapOrderCache.delete(approvalCacheKey(userId, cacheToolName));
|
|
81
90
|
}
|
|
82
91
|
}
|
|
83
92
|
|
|
84
93
|
function latestCachedPreview(userId, toolName) {
|
|
85
94
|
pruneApprovalPreviewCache();
|
|
86
|
-
return approvalPreviewCache.get(approvalCacheKey(userId, toolName)) || null;
|
|
95
|
+
return approvalPreviewCache.get(approvalCacheKey(userId, approvalPreviewToolName(toolName))) || null;
|
|
87
96
|
}
|
|
88
97
|
|
|
89
98
|
function approvalTokenPreviewDigest(token) {
|
|
@@ -498,8 +507,9 @@ async function issueApprovalToken(api, config, userId, toolName, previewPayload)
|
|
|
498
507
|
if (!summary || typeof summary !== "object") {
|
|
499
508
|
throw new Error(`No confirmation_summary available for ${toolName}.`);
|
|
500
509
|
}
|
|
501
|
-
const
|
|
502
|
-
|
|
510
|
+
const summaryForToken = PREVIEW_BOUND_SWAP_TOOLS.has(toolName)
|
|
511
|
+
? { ...summary, _preview_digest: previewDigest(previewPayload) }
|
|
512
|
+
: { ...summary };
|
|
503
513
|
const extraArgs = [
|
|
504
514
|
"--tool",
|
|
505
515
|
toolName,
|
|
@@ -819,6 +829,94 @@ const walletSessionToolDefinitions = [
|
|
|
819
829
|
additionalProperties: false,
|
|
820
830
|
},
|
|
821
831
|
},
|
|
832
|
+
{
|
|
833
|
+
name: "x402_search_services",
|
|
834
|
+
description:
|
|
835
|
+
"Search x402-paid services through CDP Bazaar or Agentic Market. This is read-only discovery and does not spend funds.",
|
|
836
|
+
parameters: {
|
|
837
|
+
type: "object",
|
|
838
|
+
properties: {
|
|
839
|
+
query: { type: "string" },
|
|
840
|
+
discovery_provider: {
|
|
841
|
+
type: "string",
|
|
842
|
+
enum: ["auto", "cdp_bazaar", "agentic_market"],
|
|
843
|
+
},
|
|
844
|
+
network: { type: "string" },
|
|
845
|
+
asset: { type: "string" },
|
|
846
|
+
scheme: { type: "string" },
|
|
847
|
+
max_usd_price: { type: "string" },
|
|
848
|
+
limit: { type: "integer" },
|
|
849
|
+
},
|
|
850
|
+
additionalProperties: false,
|
|
851
|
+
},
|
|
852
|
+
},
|
|
853
|
+
{
|
|
854
|
+
name: "x402_get_service_details",
|
|
855
|
+
description:
|
|
856
|
+
"Resolve one x402 service or resource into a normalized details payload. Use a resource URL for CDP Bazaar or a domain/service id for Agentic Market.",
|
|
857
|
+
parameters: {
|
|
858
|
+
type: "object",
|
|
859
|
+
properties: {
|
|
860
|
+
reference: { type: "string" },
|
|
861
|
+
discovery_provider: {
|
|
862
|
+
type: "string",
|
|
863
|
+
enum: ["auto", "cdp_bazaar", "agentic_market"],
|
|
864
|
+
},
|
|
865
|
+
},
|
|
866
|
+
required: ["reference"],
|
|
867
|
+
additionalProperties: false,
|
|
868
|
+
},
|
|
869
|
+
},
|
|
870
|
+
{
|
|
871
|
+
name: "x402_preview_request",
|
|
872
|
+
description:
|
|
873
|
+
"Make an unpaid HTTP request to an x402 endpoint, detect HTTP 402, parse PAYMENT-REQUIRED, and summarize the payment options. This does not pay or execute.",
|
|
874
|
+
parameters: {
|
|
875
|
+
type: "object",
|
|
876
|
+
properties: {
|
|
877
|
+
url: { type: "string" },
|
|
878
|
+
method: { type: "string" },
|
|
879
|
+
headers: { type: "object", additionalProperties: { type: "string" } },
|
|
880
|
+
query: { type: "object", additionalProperties: true },
|
|
881
|
+
json_body: {},
|
|
882
|
+
text_body: { type: "string" },
|
|
883
|
+
},
|
|
884
|
+
required: ["url"],
|
|
885
|
+
additionalProperties: false,
|
|
886
|
+
},
|
|
887
|
+
},
|
|
888
|
+
{
|
|
889
|
+
name: "x402_pay_request",
|
|
890
|
+
description:
|
|
891
|
+
"Prepare or execute an x402 paid request using the active wallet backend. This milestone executes the Solana exact buyer flow and keeps EVM as prepare-only.",
|
|
892
|
+
parameters: {
|
|
893
|
+
type: "object",
|
|
894
|
+
properties: {
|
|
895
|
+
url: { type: "string" },
|
|
896
|
+
method: { type: "string" },
|
|
897
|
+
headers: { type: "object", additionalProperties: { type: "string" } },
|
|
898
|
+
query: { type: "object", additionalProperties: true },
|
|
899
|
+
json_body: {},
|
|
900
|
+
text_body: { type: "string" },
|
|
901
|
+
mode: {
|
|
902
|
+
type: "string",
|
|
903
|
+
enum: ["prepare", "execute"],
|
|
904
|
+
description: "prepare validates the payment plan; execute sends the paid retry.",
|
|
905
|
+
},
|
|
906
|
+
purpose: { type: "string" },
|
|
907
|
+
user_intent: {
|
|
908
|
+
type: "boolean",
|
|
909
|
+
description: "Must be true for prepare mode.",
|
|
910
|
+
},
|
|
911
|
+
approval_token: {
|
|
912
|
+
type: "string",
|
|
913
|
+
description: "Required for execute mode and must be issued against the exact x402 payment summary.",
|
|
914
|
+
},
|
|
915
|
+
},
|
|
916
|
+
required: ["url", "mode", "purpose"],
|
|
917
|
+
additionalProperties: false,
|
|
918
|
+
},
|
|
919
|
+
},
|
|
822
920
|
{
|
|
823
921
|
name: "get_active_wallet_backend",
|
|
824
922
|
description: "Show which wallet backend is active in this OpenClaw plugin session and whether it differs from the startup plugin config.",
|
|
@@ -70,7 +70,11 @@
|
|
|
70
70
|
"transfer_evm_native",
|
|
71
71
|
"transfer_evm_token",
|
|
72
72
|
"transfer_sol",
|
|
73
|
-
"transfer_spl_token"
|
|
73
|
+
"transfer_spl_token",
|
|
74
|
+
"x402_get_service_details",
|
|
75
|
+
"x402_pay_request",
|
|
76
|
+
"x402_preview_request",
|
|
77
|
+
"x402_search_services"
|
|
74
78
|
]
|
|
75
79
|
},
|
|
76
80
|
"skills": ["skills/wallet-operator"],
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## v0.1.18 - 2026-05-19
|
|
6
|
+
|
|
7
|
+
- Started the native x402 buyer integration inside `agent-wallet` instead of
|
|
8
|
+
the separate `pay-bridge` wallet path.
|
|
9
|
+
- Added read-only x402 discovery helpers for `CDP Bazaar` and
|
|
10
|
+
`Agentic Market`, including normalized service/resource search results.
|
|
11
|
+
- Added `x402_preview_request`, which performs an unpaid request, parses
|
|
12
|
+
`PAYMENT-REQUIRED`, and summarizes accepted payment options without spending
|
|
13
|
+
funds.
|
|
14
|
+
- Added `x402_pay_request` with `prepare` and `execute` flow for exact buyer
|
|
15
|
+
payments from the native wallet on Solana, Base, and Base Sepolia.
|
|
16
|
+
- Added buyer-side x402 signing support to the local EVM runtime so Base
|
|
17
|
+
payments execute without requiring a separate wallet product.
|
|
18
|
+
- Fixed x402 Solana execution against hosted RPC routing by deriving an
|
|
19
|
+
SDK-compatible direct Solana RPC URL for the x402 SVM client.
|
|
20
|
+
- Fixed x402 payment requirement selection so SDK model objects survive through
|
|
21
|
+
prepare and execute without crashing on plain dict access.
|
|
22
|
+
- Added automatic host approval-token issuance for `x402_pay_request` from the
|
|
23
|
+
cached `x402_preview_request` summary in the OpenClaw bridge.
|
|
24
|
+
- Fixed x402 approval-token binding so execute validates against the exact
|
|
25
|
+
`confirmation_summary` used by the Python wallet policy gate.
|
|
26
|
+
- Synced the OpenClaw coding profile allowlist and runtime bundle so the new
|
|
27
|
+
x402 tools are exposed correctly in packaged installs.
|
|
28
|
+
|
|
5
29
|
## v0.1.17 - 2026-05-17
|
|
6
30
|
|
|
7
31
|
- Added Flash Trade collateral-aware perp opens so the Solana wallet flow can
|
package/agent-wallet/README.md
CHANGED
|
@@ -108,6 +108,10 @@ Current safe tools:
|
|
|
108
108
|
- `deactivate_solana_stake`
|
|
109
109
|
- `withdraw_solana_stake`
|
|
110
110
|
- `request_devnet_airdrop`
|
|
111
|
+
- `x402_search_services`
|
|
112
|
+
- `x402_get_service_details`
|
|
113
|
+
- `x402_preview_request`
|
|
114
|
+
- `x402_pay_request`
|
|
111
115
|
|
|
112
116
|
Temporarily disabled but kept in the codebase for later re-enable:
|
|
113
117
|
|