@agentlayer.tech/wallet 0.1.18 → 0.1.20

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 (27) hide show
  1. package/.openclaw/AGENTS.md +0 -7
  2. package/.openclaw/extensions/agent-wallet/README.md +3 -2
  3. package/.openclaw/extensions/agent-wallet/package.json +1 -1
  4. package/README.md +111 -3
  5. package/RELEASING.md +5 -15
  6. package/agent-wallet/README.md +3 -0
  7. package/agent-wallet/agent_wallet/config.py +11 -0
  8. package/agent-wallet/agent_wallet/evm_user_wallets.py +310 -2
  9. package/agent-wallet/agent_wallet/openclaw_runtime.py +10 -41
  10. package/agent-wallet/agent_wallet/providers/wdk_evm_local.py +52 -0
  11. package/agent-wallet/pyproject.toml +1 -1
  12. package/agent-wallet/scripts/build_release_bundle.py +1 -0
  13. package/agent-wallet/scripts/flash-sdk-bridge/bridge.mjs +21 -11
  14. package/agent-wallet/scripts/install_agent_wallet.py +250 -14
  15. package/agent-wallet/scripts/install_openclaw_local_config.py +20 -51
  16. package/agent-wallet/scripts/install_openclaw_sealed_keys.py +9 -1
  17. package/bin/openclaw-agent-wallet.mjs +282 -24
  18. package/package.json +1 -2
  19. package/.openclaw/extensions/pay-bridge/README.md +0 -38
  20. package/.openclaw/extensions/pay-bridge/core.mjs +0 -287
  21. package/.openclaw/extensions/pay-bridge/dist/core.mjs +0 -287
  22. package/.openclaw/extensions/pay-bridge/dist/index.js +0 -196
  23. package/.openclaw/extensions/pay-bridge/index.ts +0 -196
  24. package/.openclaw/extensions/pay-bridge/openclaw.plugin.json +0 -34
  25. package/.openclaw/extensions/pay-bridge/package.json +0 -49
  26. package/.openclaw/extensions/pay-bridge/skills/pay-operator/SKILL.md +0 -20
  27. package/.openclaw/extensions/pay-bridge/smoke_pay_bridge.mjs +0 -38
@@ -1,287 +0,0 @@
1
- import { execFile } from "node:child_process";
2
- import { promisify } from "node:util";
3
-
4
- const execFileAsync = promisify(execFile);
5
- const ANSI_RE = /\u001b\[[0-9;]*m/g;
6
-
7
- function stripAnsi(text) {
8
- return String(text || "").replace(ANSI_RE, "");
9
- }
10
-
11
- function nonEmptyLines(text) {
12
- return stripAnsi(text)
13
- .split(/\r?\n/)
14
- .map((line) => line.trim())
15
- .filter(Boolean);
16
- }
17
-
18
- function extractLastJsonValue(text) {
19
- const lines = nonEmptyLines(text);
20
- for (let i = lines.length - 1; i >= 0; i -= 1) {
21
- const candidate = lines[i];
22
- if (!candidate.startsWith("{") && !candidate.startsWith("[")) continue;
23
- try {
24
- return JSON.parse(candidate);
25
- } catch {
26
- continue;
27
- }
28
- }
29
- return null;
30
- }
31
-
32
- function collectStringLeaves(value, acc = new Set()) {
33
- if (typeof value === "string") {
34
- acc.add(value);
35
- return acc;
36
- }
37
- if (Array.isArray(value)) {
38
- for (const item of value) collectStringLeaves(item, acc);
39
- return acc;
40
- }
41
- if (value && typeof value === "object") {
42
- for (const item of Object.values(value)) collectStringLeaves(item, acc);
43
- }
44
- return acc;
45
- }
46
-
47
- function withAccountArgs(args, account) {
48
- if (!account) return args;
49
- return [...args, "--account", account];
50
- }
51
-
52
- export function resolvePayBinary(config = {}) {
53
- return (
54
- config.payBinary ||
55
- process.env.OPENCLAW_PAY_BINARY ||
56
- "pay"
57
- );
58
- }
59
-
60
- export async function runPayCommand(payBinary, args, options = {}) {
61
- const { cwd, input = null } = options;
62
- let stdout = "";
63
- let stderr = "";
64
- try {
65
- const result = await execFileAsync(payBinary, args, {
66
- cwd,
67
- env: { ...process.env },
68
- input,
69
- maxBuffer: 1024 * 1024 * 8,
70
- });
71
- stdout = result.stdout ?? "";
72
- stderr = result.stderr ?? "";
73
- } catch (error) {
74
- stdout = typeof error?.stdout === "string" ? error.stdout : "";
75
- stderr = typeof error?.stderr === "string" ? error.stderr : "";
76
- const payload = extractLastJsonValue(stdout) || extractLastJsonValue(stderr);
77
- const message =
78
- payload?.error?.message ||
79
- payload?.message ||
80
- stripAnsi(stderr || stdout || error?.message || "pay command failed").trim() ||
81
- "pay command failed";
82
- const wrapped = new Error(message);
83
- wrapped.stdout = stdout;
84
- wrapped.stderr = stderr;
85
- wrapped.details = payload && typeof payload === "object" ? payload : null;
86
- throw wrapped;
87
- }
88
- return { stdout, stderr };
89
- }
90
-
91
- export function parseWhoamiOutput(stdout) {
92
- const lines = nonEmptyLines(stdout);
93
- const systemUser = lines[0] || null;
94
- const noAccount = lines.some((line) => /no mainnet account/i.test(line));
95
- return {
96
- system_user: systemUser,
97
- has_mainnet_account: !noAccount,
98
- raw_lines: lines,
99
- };
100
- }
101
-
102
- export function parseAccountListOutput(stdout) {
103
- const lines = nonEmptyLines(stdout);
104
- const noAccounts = lines.some((line) => /no accounts found/i.test(line));
105
- return {
106
- has_accounts: !noAccounts,
107
- raw_lines: lines,
108
- };
109
- }
110
-
111
- export async function getPayStatus(config = {}, options = {}) {
112
- const payBinary = resolvePayBinary(config);
113
- const versionResult = await runPayCommand(payBinary, ["--version"], options);
114
- const whoamiResult = await runPayCommand(
115
- payBinary,
116
- withAccountArgs(["whoami"], config.defaultAccount),
117
- options
118
- );
119
- const accountListResult = await runPayCommand(payBinary, ["account", "list"], options);
120
- return {
121
- installed: true,
122
- pay_binary: payBinary,
123
- version: stripAnsi(versionResult.stdout).trim() || null,
124
- account_configured: parseWhoamiOutput(whoamiResult.stdout).has_mainnet_account,
125
- has_any_accounts: parseAccountListOutput(accountListResult.stdout).has_accounts,
126
- whoami: parseWhoamiOutput(whoamiResult.stdout),
127
- accounts: parseAccountListOutput(accountListResult.stdout),
128
- };
129
- }
130
-
131
- export async function getPayWalletInfo(config = {}, options = {}) {
132
- const payBinary = resolvePayBinary(config);
133
- const whoamiResult = await runPayCommand(
134
- payBinary,
135
- withAccountArgs(["whoami"], config.defaultAccount),
136
- options
137
- );
138
- const accountListResult = await runPayCommand(payBinary, ["account", "list"], options);
139
- return {
140
- pay_binary: payBinary,
141
- default_account: config.defaultAccount || null,
142
- whoami: parseWhoamiOutput(whoamiResult.stdout),
143
- accounts: parseAccountListOutput(accountListResult.stdout),
144
- notes: [
145
- "This wallet is managed by pay.sh and is separate from the AgentLayer execution wallet.",
146
- ],
147
- };
148
- }
149
-
150
- export async function searchPayServices(config = {}, params = {}, options = {}) {
151
- const payBinary = resolvePayBinary(config);
152
- const args = ["skills", "search"];
153
- if (params.query) args.push(String(params.query));
154
- if (params.category) args.push("--category", String(params.category));
155
- args.push("--json");
156
- const { stdout, stderr } = await runPayCommand(
157
- payBinary,
158
- withAccountArgs(args, params.account || config.defaultAccount),
159
- options
160
- );
161
- const parsed = JSON.parse(stdout.trim() || "{}");
162
- return {
163
- query: params.query || "",
164
- category: params.category || null,
165
- results: parsed,
166
- warnings: nonEmptyLines(stderr),
167
- };
168
- }
169
-
170
- export async function getPayServiceEndpoints(config = {}, params = {}, options = {}) {
171
- const payBinary = resolvePayBinary(config);
172
- const args = [
173
- "skills",
174
- "endpoints",
175
- String(params.service_fqn),
176
- String(params.resource),
177
- "--json",
178
- ];
179
- const { stdout, stderr } = await runPayCommand(
180
- payBinary,
181
- withAccountArgs(args, params.account || config.defaultAccount),
182
- options
183
- );
184
- const parsed = JSON.parse(stdout.trim() || "{}");
185
- return {
186
- service_fqn: String(params.service_fqn),
187
- resource: String(params.resource),
188
- endpoints: parsed,
189
- warnings: nonEmptyLines(stderr),
190
- };
191
- }
192
-
193
- function ensureHttps(url, requireHttps = true) {
194
- if (!requireHttps) return;
195
- const parsed = new URL(url);
196
- if (parsed.protocol !== "https:") {
197
- throw new Error("pay_api_request only allows https URLs.");
198
- }
199
- }
200
-
201
- function appendQuery(url, query) {
202
- const parsed = new URL(url);
203
- if (query && typeof query === "object") {
204
- for (const [key, value] of Object.entries(query)) {
205
- if (value === undefined || value === null) continue;
206
- parsed.searchParams.set(key, String(value));
207
- }
208
- }
209
- return parsed.toString();
210
- }
211
-
212
- export function endpointPayloadContainsUrl(endpointPayload, url) {
213
- const strings = collectStringLeaves(endpointPayload);
214
- return strings.has(url);
215
- }
216
-
217
- export async function executePayApiRequest(config = {}, params = {}, options = {}) {
218
- if (params.user_confirmed !== true) {
219
- throw new Error("pay_api_request requires user_confirmed=true.");
220
- }
221
- if (!params.purpose || !String(params.purpose).trim()) {
222
- throw new Error("pay_api_request requires a non-empty purpose.");
223
- }
224
- if (!params.service_fqn || !params.resource || !params.url) {
225
- throw new Error("pay_api_request requires service_fqn, resource, and url.");
226
- }
227
- if (params.json_body !== undefined && params.text_body !== undefined) {
228
- throw new Error("Provide either json_body or text_body, not both.");
229
- }
230
-
231
- const endpointData = await getPayServiceEndpoints(config, {
232
- account: params.account,
233
- resource: params.resource,
234
- service_fqn: params.service_fqn,
235
- }, options);
236
-
237
- const finalUrl = appendQuery(String(params.url), params.query);
238
- ensureHttps(finalUrl, config.requireHttps !== false);
239
- if (!endpointPayloadContainsUrl(endpointData.endpoints, String(params.url))) {
240
- throw new Error("The requested URL is not present in pay_get_service_endpoints for this service/resource.");
241
- }
242
-
243
- const payBinary = resolvePayBinary(config);
244
- const method = String(params.method || "GET").toUpperCase();
245
- const args = ["curl"];
246
- if (params.account || config.defaultAccount) {
247
- args.push("--account", String(params.account || config.defaultAccount));
248
- }
249
- args.push("--request", method);
250
-
251
- const headers = params.headers && typeof params.headers === "object" ? params.headers : {};
252
- for (const [key, value] of Object.entries(headers)) {
253
- args.push("--header", `${key}: ${String(value)}`);
254
- }
255
-
256
- if (params.json_body !== undefined) {
257
- const hasContentType = Object.keys(headers).some((key) => key.toLowerCase() === "content-type");
258
- if (!hasContentType) {
259
- args.push("--header", "content-type: application/json");
260
- }
261
- args.push("--data", JSON.stringify(params.json_body));
262
- } else if (params.text_body !== undefined) {
263
- args.push("--data", String(params.text_body));
264
- }
265
-
266
- args.push(finalUrl);
267
- const { stdout, stderr } = await runPayCommand(payBinary, args, options);
268
- const trimmed = stdout.trim();
269
- let responseBody = trimmed;
270
- if (params.parse_json_response !== false) {
271
- try {
272
- responseBody = JSON.parse(trimmed);
273
- } catch {
274
- responseBody = trimmed;
275
- }
276
- }
277
- return {
278
- method,
279
- purpose: String(params.purpose),
280
- request_url: finalUrl,
281
- service_fqn: String(params.service_fqn),
282
- resource: String(params.resource),
283
- response: responseBody,
284
- raw_response_text: trimmed,
285
- warnings: nonEmptyLines(stderr),
286
- };
287
- }
@@ -1,287 +0,0 @@
1
- import { execFile } from "node:child_process";
2
- import { promisify } from "node:util";
3
-
4
- const execFileAsync = promisify(execFile);
5
- const ANSI_RE = /\u001b\[[0-9;]*m/g;
6
-
7
- function stripAnsi(text) {
8
- return String(text || "").replace(ANSI_RE, "");
9
- }
10
-
11
- function nonEmptyLines(text) {
12
- return stripAnsi(text)
13
- .split(/\r?\n/)
14
- .map((line) => line.trim())
15
- .filter(Boolean);
16
- }
17
-
18
- function extractLastJsonValue(text) {
19
- const lines = nonEmptyLines(text);
20
- for (let i = lines.length - 1; i >= 0; i -= 1) {
21
- const candidate = lines[i];
22
- if (!candidate.startsWith("{") && !candidate.startsWith("[")) continue;
23
- try {
24
- return JSON.parse(candidate);
25
- } catch {
26
- continue;
27
- }
28
- }
29
- return null;
30
- }
31
-
32
- function collectStringLeaves(value, acc = new Set()) {
33
- if (typeof value === "string") {
34
- acc.add(value);
35
- return acc;
36
- }
37
- if (Array.isArray(value)) {
38
- for (const item of value) collectStringLeaves(item, acc);
39
- return acc;
40
- }
41
- if (value && typeof value === "object") {
42
- for (const item of Object.values(value)) collectStringLeaves(item, acc);
43
- }
44
- return acc;
45
- }
46
-
47
- function withAccountArgs(args, account) {
48
- if (!account) return args;
49
- return [...args, "--account", account];
50
- }
51
-
52
- export function resolvePayBinary(config = {}) {
53
- return (
54
- config.payBinary ||
55
- process.env.OPENCLAW_PAY_BINARY ||
56
- "pay"
57
- );
58
- }
59
-
60
- export async function runPayCommand(payBinary, args, options = {}) {
61
- const { cwd, input = null } = options;
62
- let stdout = "";
63
- let stderr = "";
64
- try {
65
- const result = await execFileAsync(payBinary, args, {
66
- cwd,
67
- env: { ...process.env },
68
- input,
69
- maxBuffer: 1024 * 1024 * 8,
70
- });
71
- stdout = result.stdout ?? "";
72
- stderr = result.stderr ?? "";
73
- } catch (error) {
74
- stdout = typeof error?.stdout === "string" ? error.stdout : "";
75
- stderr = typeof error?.stderr === "string" ? error.stderr : "";
76
- const payload = extractLastJsonValue(stdout) || extractLastJsonValue(stderr);
77
- const message =
78
- payload?.error?.message ||
79
- payload?.message ||
80
- stripAnsi(stderr || stdout || error?.message || "pay command failed").trim() ||
81
- "pay command failed";
82
- const wrapped = new Error(message);
83
- wrapped.stdout = stdout;
84
- wrapped.stderr = stderr;
85
- wrapped.details = payload && typeof payload === "object" ? payload : null;
86
- throw wrapped;
87
- }
88
- return { stdout, stderr };
89
- }
90
-
91
- export function parseWhoamiOutput(stdout) {
92
- const lines = nonEmptyLines(stdout);
93
- const systemUser = lines[0] || null;
94
- const noAccount = lines.some((line) => /no mainnet account/i.test(line));
95
- return {
96
- system_user: systemUser,
97
- has_mainnet_account: !noAccount,
98
- raw_lines: lines,
99
- };
100
- }
101
-
102
- export function parseAccountListOutput(stdout) {
103
- const lines = nonEmptyLines(stdout);
104
- const noAccounts = lines.some((line) => /no accounts found/i.test(line));
105
- return {
106
- has_accounts: !noAccounts,
107
- raw_lines: lines,
108
- };
109
- }
110
-
111
- export async function getPayStatus(config = {}, options = {}) {
112
- const payBinary = resolvePayBinary(config);
113
- const versionResult = await runPayCommand(payBinary, ["--version"], options);
114
- const whoamiResult = await runPayCommand(
115
- payBinary,
116
- withAccountArgs(["whoami"], config.defaultAccount),
117
- options
118
- );
119
- const accountListResult = await runPayCommand(payBinary, ["account", "list"], options);
120
- return {
121
- installed: true,
122
- pay_binary: payBinary,
123
- version: stripAnsi(versionResult.stdout).trim() || null,
124
- account_configured: parseWhoamiOutput(whoamiResult.stdout).has_mainnet_account,
125
- has_any_accounts: parseAccountListOutput(accountListResult.stdout).has_accounts,
126
- whoami: parseWhoamiOutput(whoamiResult.stdout),
127
- accounts: parseAccountListOutput(accountListResult.stdout),
128
- };
129
- }
130
-
131
- export async function getPayWalletInfo(config = {}, options = {}) {
132
- const payBinary = resolvePayBinary(config);
133
- const whoamiResult = await runPayCommand(
134
- payBinary,
135
- withAccountArgs(["whoami"], config.defaultAccount),
136
- options
137
- );
138
- const accountListResult = await runPayCommand(payBinary, ["account", "list"], options);
139
- return {
140
- pay_binary: payBinary,
141
- default_account: config.defaultAccount || null,
142
- whoami: parseWhoamiOutput(whoamiResult.stdout),
143
- accounts: parseAccountListOutput(accountListResult.stdout),
144
- notes: [
145
- "This wallet is managed by pay.sh and is separate from the AgentLayer execution wallet.",
146
- ],
147
- };
148
- }
149
-
150
- export async function searchPayServices(config = {}, params = {}, options = {}) {
151
- const payBinary = resolvePayBinary(config);
152
- const args = ["skills", "search"];
153
- if (params.query) args.push(String(params.query));
154
- if (params.category) args.push("--category", String(params.category));
155
- args.push("--json");
156
- const { stdout, stderr } = await runPayCommand(
157
- payBinary,
158
- withAccountArgs(args, params.account || config.defaultAccount),
159
- options
160
- );
161
- const parsed = JSON.parse(stdout.trim() || "{}");
162
- return {
163
- query: params.query || "",
164
- category: params.category || null,
165
- results: parsed,
166
- warnings: nonEmptyLines(stderr),
167
- };
168
- }
169
-
170
- export async function getPayServiceEndpoints(config = {}, params = {}, options = {}) {
171
- const payBinary = resolvePayBinary(config);
172
- const args = [
173
- "skills",
174
- "endpoints",
175
- String(params.service_fqn),
176
- String(params.resource),
177
- "--json",
178
- ];
179
- const { stdout, stderr } = await runPayCommand(
180
- payBinary,
181
- withAccountArgs(args, params.account || config.defaultAccount),
182
- options
183
- );
184
- const parsed = JSON.parse(stdout.trim() || "{}");
185
- return {
186
- service_fqn: String(params.service_fqn),
187
- resource: String(params.resource),
188
- endpoints: parsed,
189
- warnings: nonEmptyLines(stderr),
190
- };
191
- }
192
-
193
- function ensureHttps(url, requireHttps = true) {
194
- if (!requireHttps) return;
195
- const parsed = new URL(url);
196
- if (parsed.protocol !== "https:") {
197
- throw new Error("pay_api_request only allows https URLs.");
198
- }
199
- }
200
-
201
- function appendQuery(url, query) {
202
- const parsed = new URL(url);
203
- if (query && typeof query === "object") {
204
- for (const [key, value] of Object.entries(query)) {
205
- if (value === undefined || value === null) continue;
206
- parsed.searchParams.set(key, String(value));
207
- }
208
- }
209
- return parsed.toString();
210
- }
211
-
212
- export function endpointPayloadContainsUrl(endpointPayload, url) {
213
- const strings = collectStringLeaves(endpointPayload);
214
- return strings.has(url);
215
- }
216
-
217
- export async function executePayApiRequest(config = {}, params = {}, options = {}) {
218
- if (params.user_confirmed !== true) {
219
- throw new Error("pay_api_request requires user_confirmed=true.");
220
- }
221
- if (!params.purpose || !String(params.purpose).trim()) {
222
- throw new Error("pay_api_request requires a non-empty purpose.");
223
- }
224
- if (!params.service_fqn || !params.resource || !params.url) {
225
- throw new Error("pay_api_request requires service_fqn, resource, and url.");
226
- }
227
- if (params.json_body !== undefined && params.text_body !== undefined) {
228
- throw new Error("Provide either json_body or text_body, not both.");
229
- }
230
-
231
- const endpointData = await getPayServiceEndpoints(config, {
232
- account: params.account,
233
- resource: params.resource,
234
- service_fqn: params.service_fqn,
235
- }, options);
236
-
237
- const finalUrl = appendQuery(String(params.url), params.query);
238
- ensureHttps(finalUrl, config.requireHttps !== false);
239
- if (!endpointPayloadContainsUrl(endpointData.endpoints, String(params.url))) {
240
- throw new Error("The requested URL is not present in pay_get_service_endpoints for this service/resource.");
241
- }
242
-
243
- const payBinary = resolvePayBinary(config);
244
- const method = String(params.method || "GET").toUpperCase();
245
- const args = ["curl"];
246
- if (params.account || config.defaultAccount) {
247
- args.push("--account", String(params.account || config.defaultAccount));
248
- }
249
- args.push("--request", method);
250
-
251
- const headers = params.headers && typeof params.headers === "object" ? params.headers : {};
252
- for (const [key, value] of Object.entries(headers)) {
253
- args.push("--header", `${key}: ${String(value)}`);
254
- }
255
-
256
- if (params.json_body !== undefined) {
257
- const hasContentType = Object.keys(headers).some((key) => key.toLowerCase() === "content-type");
258
- if (!hasContentType) {
259
- args.push("--header", "content-type: application/json");
260
- }
261
- args.push("--data", JSON.stringify(params.json_body));
262
- } else if (params.text_body !== undefined) {
263
- args.push("--data", String(params.text_body));
264
- }
265
-
266
- args.push(finalUrl);
267
- const { stdout, stderr } = await runPayCommand(payBinary, args, options);
268
- const trimmed = stdout.trim();
269
- let responseBody = trimmed;
270
- if (params.parse_json_response !== false) {
271
- try {
272
- responseBody = JSON.parse(trimmed);
273
- } catch {
274
- responseBody = trimmed;
275
- }
276
- }
277
- return {
278
- method,
279
- purpose: String(params.purpose),
280
- request_url: finalUrl,
281
- service_fqn: String(params.service_fqn),
282
- resource: String(params.resource),
283
- response: responseBody,
284
- raw_response_text: trimmed,
285
- warnings: nonEmptyLines(stderr),
286
- };
287
- }