@rozoai/checkout 0.1.17 → 0.1.19
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/README.md +15 -2
- package/llms.txt +38 -2
- package/package.json +1 -1
- package/scripts/dist/cli.js +1073 -70
- package/scripts/dist/create-order.js +106 -34
- package/scripts/dist/quote.js +100 -33
- package/scripts/dist/receipt.js +100 -33
- package/scripts/dist/resume.js +100 -33
- package/scripts/dist/send-evm.js +100 -33
- package/scripts/dist/send-sol.js +100 -33
- package/scripts/dist/status.js +119 -35
package/scripts/dist/resume.js
CHANGED
|
@@ -13,6 +13,8 @@ var SUPPORT = Object.freeze({
|
|
|
13
13
|
discord: "https://discord.gg/EfWejgTbuU"
|
|
14
14
|
});
|
|
15
15
|
var SUPPORT_TEXT = `Need help? Email ${SUPPORT.email}, or reach ROZO on X ${SUPPORT.x} or Discord ${SUPPORT.discord}.`;
|
|
16
|
+
var BULK_DOCS_URL = "https://docs.rozo.ai/products/checkout/bulk-and-agents";
|
|
17
|
+
var BULK_HINT_TEXT = `Buying regularly or for others? ${BULK_DOCS_URL}`;
|
|
16
18
|
|
|
17
19
|
// scripts/src/lib/output.mjs
|
|
18
20
|
var PUBLIC_SUPPORT_URLS = /* @__PURE__ */ new Set([SUPPORT.x, SUPPORT.discord]);
|
|
@@ -34,6 +36,7 @@ function redact(text) {
|
|
|
34
36
|
return `${scheme}://${host}${hadMore ? "/<redacted>" : ""}`;
|
|
35
37
|
});
|
|
36
38
|
s = s.replace(/\b(bearer)\s+[A-Za-z0-9._~+/=-]{8,}/gi, "$1 <redacted>");
|
|
39
|
+
s = s.replace(/\bak_[A-Za-z0-9_-]{8,}/g, "ak_<redacted>");
|
|
37
40
|
s = s.replace(
|
|
38
41
|
/\b(api[-_]?key|apikey|access[-_]?token|auth[-_]?token|secret|token|password|passwd|pwd)\b(\s*[:=]\s*)("?)[A-Za-z0-9._~+/=-]{6,}\3/gi,
|
|
39
42
|
"$1$2<redacted>"
|
|
@@ -160,18 +163,66 @@ function maskMemo(memo) {
|
|
|
160
163
|
return `${s.slice(0, 4)}...${s.slice(-3)}`;
|
|
161
164
|
}
|
|
162
165
|
|
|
163
|
-
// scripts/src/lib/
|
|
166
|
+
// scripts/src/lib/version.mjs
|
|
164
167
|
import { createRequire } from "node:module";
|
|
168
|
+
var PKG_VERSION = (() => {
|
|
169
|
+
const requireFrom = createRequire(import.meta.url);
|
|
170
|
+
for (const candidate of ["../../package.json", "../../../package.json"]) {
|
|
171
|
+
try {
|
|
172
|
+
const pkg = requireFrom(candidate);
|
|
173
|
+
if (pkg?.name === "@rozoai/checkout" && pkg.version) return pkg.version;
|
|
174
|
+
} catch {
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return "0.0.0";
|
|
178
|
+
})();
|
|
165
179
|
|
|
166
180
|
// scripts/src/lib/http.mjs
|
|
167
181
|
var DEFAULT_TIMEOUT_MS = 2e4;
|
|
168
|
-
var USER_AGENT =
|
|
169
|
-
|
|
182
|
+
var USER_AGENT = `rozo-checkout-skill/${PKG_VERSION}`;
|
|
183
|
+
var MAX_RETRIES = 3;
|
|
184
|
+
var MAX_TOTAL_WAIT_MS = 12e4;
|
|
185
|
+
var FALLBACK_BACKOFF_MS = [2e3, 4e3, 8e3];
|
|
186
|
+
var defaultSleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
187
|
+
function parseRetryAfter(value, now = Date.now()) {
|
|
188
|
+
if (value === null || value === void 0) return null;
|
|
189
|
+
const s = String(value).trim();
|
|
190
|
+
if (!s) return null;
|
|
191
|
+
if (/^\d+(\.\d+)?$/.test(s)) return Math.round(Number(s) * 1e3);
|
|
192
|
+
const at = Date.parse(s);
|
|
193
|
+
if (!Number.isFinite(at)) return null;
|
|
194
|
+
return Math.max(0, at - now);
|
|
195
|
+
}
|
|
196
|
+
function bodyRetryAfterMs(json) {
|
|
197
|
+
const raw = json?.retryAfterSeconds ?? json?.error?.retryAfterSeconds;
|
|
198
|
+
if (raw === null || raw === void 0 || raw === "") return null;
|
|
199
|
+
const n = Number(raw);
|
|
200
|
+
return Number.isFinite(n) && n >= 0 ? Math.round(n * 1e3) : null;
|
|
201
|
+
}
|
|
202
|
+
function rateLimitInfo(res) {
|
|
203
|
+
const pick = (name) => res.headers?.get?.(name) ?? null;
|
|
204
|
+
const info = {
|
|
205
|
+
limit: pick("x-ratelimit-limit"),
|
|
206
|
+
remaining: pick("x-ratelimit-remaining"),
|
|
207
|
+
tier: pick("x-ratelimit-tier"),
|
|
208
|
+
scope: pick("x-ratelimit-scope")
|
|
209
|
+
};
|
|
210
|
+
const present = Object.fromEntries(Object.entries(info).filter(([, v]) => v !== null));
|
|
211
|
+
return Object.keys(present).length ? present : null;
|
|
212
|
+
}
|
|
213
|
+
function parseBody(text) {
|
|
214
|
+
if (!text) return null;
|
|
215
|
+
try {
|
|
216
|
+
return JSON.parse(text);
|
|
217
|
+
} catch {
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
async function fetchOnce(method, url, body, timeoutMs) {
|
|
170
222
|
const controller = new AbortController();
|
|
171
223
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
172
|
-
let res;
|
|
173
224
|
try {
|
|
174
|
-
res = await fetch(url, {
|
|
225
|
+
const res = await fetch(url, {
|
|
175
226
|
method,
|
|
176
227
|
headers: {
|
|
177
228
|
accept: "application/json",
|
|
@@ -181,6 +232,8 @@ async function request(method, url, { body, timeoutMs = DEFAULT_TIMEOUT_MS } = {
|
|
|
181
232
|
body: body !== void 0 ? JSON.stringify(body) : void 0,
|
|
182
233
|
signal: controller.signal
|
|
183
234
|
});
|
|
235
|
+
const text = await res.text();
|
|
236
|
+
return { res, text };
|
|
184
237
|
} catch (err) {
|
|
185
238
|
throw new SkillError(
|
|
186
239
|
err?.name === "AbortError" ? "HTTP_TIMEOUT" : "HTTP_UNREACHABLE",
|
|
@@ -190,31 +243,54 @@ async function request(method, url, { body, timeoutMs = DEFAULT_TIMEOUT_MS } = {
|
|
|
190
243
|
} finally {
|
|
191
244
|
clearTimeout(timer);
|
|
192
245
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
246
|
+
}
|
|
247
|
+
async function request(method, url, {
|
|
248
|
+
body,
|
|
249
|
+
timeoutMs = DEFAULT_TIMEOUT_MS,
|
|
250
|
+
sleep = defaultSleep,
|
|
251
|
+
now = Date.now,
|
|
252
|
+
maxTotalWaitMs = MAX_TOTAL_WAIT_MS
|
|
253
|
+
} = {}) {
|
|
254
|
+
let waitedMs = 0;
|
|
255
|
+
let retries = 0;
|
|
256
|
+
for (; ; ) {
|
|
257
|
+
const { res, text } = await fetchOnce(method, url, body, timeoutMs);
|
|
258
|
+
const json = parseBody(text);
|
|
259
|
+
if (res.ok) {
|
|
260
|
+
if (json === null) {
|
|
261
|
+
throw new SkillError("HTTP_BAD_JSON", "Endpoint returned a non-JSON body.", {
|
|
262
|
+
url: redactUrl(url),
|
|
263
|
+
snippet: redact(text).slice(0, 400)
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
return json;
|
|
267
|
+
}
|
|
268
|
+
const headerWaitMs = parseRetryAfter(res.headers?.get?.("retry-after"), now());
|
|
269
|
+
const hintMs = headerWaitMs ?? bodyRetryAfterMs(json);
|
|
270
|
+
const retryable = res.status === 429 || res.status === 503 && hintMs !== null;
|
|
271
|
+
if (retryable && retries < MAX_RETRIES) {
|
|
272
|
+
const waitMs = hintMs ?? FALLBACK_BACKOFF_MS[retries];
|
|
273
|
+
if (waitedMs + waitMs <= Math.min(maxTotalWaitMs, MAX_TOTAL_WAIT_MS)) {
|
|
274
|
+
retries += 1;
|
|
275
|
+
waitedMs += waitMs;
|
|
276
|
+
await sleep(waitMs);
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
200
279
|
}
|
|
201
|
-
}
|
|
202
|
-
if (!res.ok) {
|
|
203
280
|
const code = json?.code || json?.error?.code || (typeof json?.error === "string" && /^[A-Z][A-Z0-9_]+$/.test(json.error) ? json.error : null) || `HTTP_${res.status}`;
|
|
204
281
|
const message = json?.message || (typeof json?.error === "string" ? json.error : json?.error?.message) || `HTTP ${res.status}`;
|
|
282
|
+
const rateLimit = rateLimitInfo(res);
|
|
205
283
|
throw new SkillError(code, redact(String(message)), {
|
|
206
284
|
httpStatus: res.status,
|
|
207
285
|
url: redactUrl(url),
|
|
208
|
-
body: json ?? redact(text).slice(0, 800)
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
snippet: redact(text).slice(0, 400)
|
|
286
|
+
body: json ?? redact(text).slice(0, 800),
|
|
287
|
+
...retryable ? {
|
|
288
|
+
retries,
|
|
289
|
+
retryAfterSeconds: hintMs === null ? null : Math.ceil(hintMs / 1e3)
|
|
290
|
+
} : {},
|
|
291
|
+
...rateLimit ? { rateLimit } : {}
|
|
215
292
|
});
|
|
216
293
|
}
|
|
217
|
-
return json;
|
|
218
294
|
}
|
|
219
295
|
function redactUrl(url) {
|
|
220
296
|
try {
|
|
@@ -280,17 +356,6 @@ function findByLinkId(linkId) {
|
|
|
280
356
|
}
|
|
281
357
|
|
|
282
358
|
// scripts/src/lib/api.mjs
|
|
283
|
-
var PKG_VERSION = (() => {
|
|
284
|
-
const requireFrom = createRequire(import.meta.url);
|
|
285
|
-
for (const candidate of ["../../package.json", "../../../package.json"]) {
|
|
286
|
-
try {
|
|
287
|
-
const pkg = requireFrom(candidate);
|
|
288
|
-
if (pkg?.name === "@rozoai/checkout" && pkg.version) return pkg.version;
|
|
289
|
-
} catch {
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
return "0.0.0";
|
|
293
|
-
})();
|
|
294
359
|
var MPP_BASE = process.env.ROZO_CHECKOUT_MPP_BASE || "https://apiserver.mpprouter.dev/v1/services/rozo-agent-api";
|
|
295
360
|
var CLIENT_LABEL = `rozo-checkout-cli/${PKG_VERSION}`;
|
|
296
361
|
var ATTRIBUTION_CLIENT = `rozo-checkout-skill/${PKG_VERSION}`;
|
|
@@ -895,6 +960,8 @@ var MARGINS_MS = {
|
|
|
895
960
|
};
|
|
896
961
|
var BOLT11_MIN_VALIDITY_MS = 10 * MINUTE;
|
|
897
962
|
var DEFAULT_MARGIN_MS = 10 * MINUTE;
|
|
963
|
+
var DEFAULT_WATCH_MS = 10 * MINUTE;
|
|
964
|
+
var LIGHTNING_WATCH_CAP_MS = 60 * MINUTE;
|
|
898
965
|
function formatRemaining(ms) {
|
|
899
966
|
if (!Number.isFinite(ms)) return "unknown";
|
|
900
967
|
if (ms <= 0) return "expired";
|
package/scripts/dist/send-evm.js
CHANGED
|
@@ -9982,6 +9982,8 @@ var SUPPORT = Object.freeze({
|
|
|
9982
9982
|
discord: "https://discord.gg/EfWejgTbuU"
|
|
9983
9983
|
});
|
|
9984
9984
|
var SUPPORT_TEXT = `Need help? Email ${SUPPORT.email}, or reach ROZO on X ${SUPPORT.x} or Discord ${SUPPORT.discord}.`;
|
|
9985
|
+
var BULK_DOCS_URL = "https://docs.rozo.ai/products/checkout/bulk-and-agents";
|
|
9986
|
+
var BULK_HINT_TEXT = `Buying regularly or for others? ${BULK_DOCS_URL}`;
|
|
9985
9987
|
|
|
9986
9988
|
// scripts/src/lib/output.mjs
|
|
9987
9989
|
var PUBLIC_SUPPORT_URLS = /* @__PURE__ */ new Set([SUPPORT.x, SUPPORT.discord]);
|
|
@@ -10003,6 +10005,7 @@ function redact(text) {
|
|
|
10003
10005
|
return `${scheme}://${host}${hadMore ? "/<redacted>" : ""}`;
|
|
10004
10006
|
});
|
|
10005
10007
|
s = s.replace(/\b(bearer)\s+[A-Za-z0-9._~+/=-]{8,}/gi, "$1 <redacted>");
|
|
10008
|
+
s = s.replace(/\bak_[A-Za-z0-9_-]{8,}/g, "ak_<redacted>");
|
|
10006
10009
|
s = s.replace(
|
|
10007
10010
|
/\b(api[-_]?key|apikey|access[-_]?token|auth[-_]?token|secret|token|password|passwd|pwd)\b(\s*[:=]\s*)("?)[A-Za-z0-9._~+/=-]{6,}\3/gi,
|
|
10008
10011
|
"$1$2<redacted>"
|
|
@@ -21849,18 +21852,66 @@ function promptPassphrase(prompt = " Keystore passphrase: ") {
|
|
|
21849
21852
|
});
|
|
21850
21853
|
}
|
|
21851
21854
|
|
|
21852
|
-
// scripts/src/lib/
|
|
21855
|
+
// scripts/src/lib/version.mjs
|
|
21853
21856
|
import { createRequire } from "node:module";
|
|
21857
|
+
var PKG_VERSION = (() => {
|
|
21858
|
+
const requireFrom = createRequire(import.meta.url);
|
|
21859
|
+
for (const candidate of ["../../package.json", "../../../package.json"]) {
|
|
21860
|
+
try {
|
|
21861
|
+
const pkg = requireFrom(candidate);
|
|
21862
|
+
if (pkg?.name === "@rozoai/checkout" && pkg.version) return pkg.version;
|
|
21863
|
+
} catch {
|
|
21864
|
+
}
|
|
21865
|
+
}
|
|
21866
|
+
return "0.0.0";
|
|
21867
|
+
})();
|
|
21854
21868
|
|
|
21855
21869
|
// scripts/src/lib/http.mjs
|
|
21856
21870
|
var DEFAULT_TIMEOUT_MS = 2e4;
|
|
21857
|
-
var USER_AGENT =
|
|
21858
|
-
|
|
21871
|
+
var USER_AGENT = `rozo-checkout-skill/${PKG_VERSION}`;
|
|
21872
|
+
var MAX_RETRIES = 3;
|
|
21873
|
+
var MAX_TOTAL_WAIT_MS = 12e4;
|
|
21874
|
+
var FALLBACK_BACKOFF_MS = [2e3, 4e3, 8e3];
|
|
21875
|
+
var defaultSleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
21876
|
+
function parseRetryAfter(value, now = Date.now()) {
|
|
21877
|
+
if (value === null || value === void 0) return null;
|
|
21878
|
+
const s = String(value).trim();
|
|
21879
|
+
if (!s) return null;
|
|
21880
|
+
if (/^\d+(\.\d+)?$/.test(s)) return Math.round(Number(s) * 1e3);
|
|
21881
|
+
const at = Date.parse(s);
|
|
21882
|
+
if (!Number.isFinite(at)) return null;
|
|
21883
|
+
return Math.max(0, at - now);
|
|
21884
|
+
}
|
|
21885
|
+
function bodyRetryAfterMs(json) {
|
|
21886
|
+
const raw = json?.retryAfterSeconds ?? json?.error?.retryAfterSeconds;
|
|
21887
|
+
if (raw === null || raw === void 0 || raw === "") return null;
|
|
21888
|
+
const n = Number(raw);
|
|
21889
|
+
return Number.isFinite(n) && n >= 0 ? Math.round(n * 1e3) : null;
|
|
21890
|
+
}
|
|
21891
|
+
function rateLimitInfo(res) {
|
|
21892
|
+
const pick = (name) => res.headers?.get?.(name) ?? null;
|
|
21893
|
+
const info = {
|
|
21894
|
+
limit: pick("x-ratelimit-limit"),
|
|
21895
|
+
remaining: pick("x-ratelimit-remaining"),
|
|
21896
|
+
tier: pick("x-ratelimit-tier"),
|
|
21897
|
+
scope: pick("x-ratelimit-scope")
|
|
21898
|
+
};
|
|
21899
|
+
const present = Object.fromEntries(Object.entries(info).filter(([, v]) => v !== null));
|
|
21900
|
+
return Object.keys(present).length ? present : null;
|
|
21901
|
+
}
|
|
21902
|
+
function parseBody(text) {
|
|
21903
|
+
if (!text) return null;
|
|
21904
|
+
try {
|
|
21905
|
+
return JSON.parse(text);
|
|
21906
|
+
} catch {
|
|
21907
|
+
return null;
|
|
21908
|
+
}
|
|
21909
|
+
}
|
|
21910
|
+
async function fetchOnce(method, url, body, timeoutMs) {
|
|
21859
21911
|
const controller = new AbortController();
|
|
21860
21912
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
21861
|
-
let res;
|
|
21862
21913
|
try {
|
|
21863
|
-
res = await fetch(url, {
|
|
21914
|
+
const res = await fetch(url, {
|
|
21864
21915
|
method,
|
|
21865
21916
|
headers: {
|
|
21866
21917
|
accept: "application/json",
|
|
@@ -21870,6 +21921,8 @@ async function request(method, url, { body, timeoutMs = DEFAULT_TIMEOUT_MS } = {
|
|
|
21870
21921
|
body: body !== void 0 ? JSON.stringify(body) : void 0,
|
|
21871
21922
|
signal: controller.signal
|
|
21872
21923
|
});
|
|
21924
|
+
const text = await res.text();
|
|
21925
|
+
return { res, text };
|
|
21873
21926
|
} catch (err) {
|
|
21874
21927
|
throw new SkillError(
|
|
21875
21928
|
err?.name === "AbortError" ? "HTTP_TIMEOUT" : "HTTP_UNREACHABLE",
|
|
@@ -21879,31 +21932,54 @@ async function request(method, url, { body, timeoutMs = DEFAULT_TIMEOUT_MS } = {
|
|
|
21879
21932
|
} finally {
|
|
21880
21933
|
clearTimeout(timer);
|
|
21881
21934
|
}
|
|
21882
|
-
|
|
21883
|
-
|
|
21884
|
-
|
|
21885
|
-
|
|
21886
|
-
|
|
21887
|
-
|
|
21888
|
-
|
|
21935
|
+
}
|
|
21936
|
+
async function request(method, url, {
|
|
21937
|
+
body,
|
|
21938
|
+
timeoutMs = DEFAULT_TIMEOUT_MS,
|
|
21939
|
+
sleep = defaultSleep,
|
|
21940
|
+
now = Date.now,
|
|
21941
|
+
maxTotalWaitMs = MAX_TOTAL_WAIT_MS
|
|
21942
|
+
} = {}) {
|
|
21943
|
+
let waitedMs = 0;
|
|
21944
|
+
let retries = 0;
|
|
21945
|
+
for (; ; ) {
|
|
21946
|
+
const { res, text } = await fetchOnce(method, url, body, timeoutMs);
|
|
21947
|
+
const json = parseBody(text);
|
|
21948
|
+
if (res.ok) {
|
|
21949
|
+
if (json === null) {
|
|
21950
|
+
throw new SkillError("HTTP_BAD_JSON", "Endpoint returned a non-JSON body.", {
|
|
21951
|
+
url: redactUrl(url),
|
|
21952
|
+
snippet: redact(text).slice(0, 400)
|
|
21953
|
+
});
|
|
21954
|
+
}
|
|
21955
|
+
return json;
|
|
21956
|
+
}
|
|
21957
|
+
const headerWaitMs = parseRetryAfter(res.headers?.get?.("retry-after"), now());
|
|
21958
|
+
const hintMs = headerWaitMs ?? bodyRetryAfterMs(json);
|
|
21959
|
+
const retryable = res.status === 429 || res.status === 503 && hintMs !== null;
|
|
21960
|
+
if (retryable && retries < MAX_RETRIES) {
|
|
21961
|
+
const waitMs = hintMs ?? FALLBACK_BACKOFF_MS[retries];
|
|
21962
|
+
if (waitedMs + waitMs <= Math.min(maxTotalWaitMs, MAX_TOTAL_WAIT_MS)) {
|
|
21963
|
+
retries += 1;
|
|
21964
|
+
waitedMs += waitMs;
|
|
21965
|
+
await sleep(waitMs);
|
|
21966
|
+
continue;
|
|
21967
|
+
}
|
|
21889
21968
|
}
|
|
21890
|
-
}
|
|
21891
|
-
if (!res.ok) {
|
|
21892
21969
|
const code = json?.code || json?.error?.code || (typeof json?.error === "string" && /^[A-Z][A-Z0-9_]+$/.test(json.error) ? json.error : null) || `HTTP_${res.status}`;
|
|
21893
21970
|
const message = json?.message || (typeof json?.error === "string" ? json.error : json?.error?.message) || `HTTP ${res.status}`;
|
|
21971
|
+
const rateLimit = rateLimitInfo(res);
|
|
21894
21972
|
throw new SkillError(code, redact(String(message)), {
|
|
21895
21973
|
httpStatus: res.status,
|
|
21896
21974
|
url: redactUrl(url),
|
|
21897
|
-
body: json ?? redact(text).slice(0, 800)
|
|
21898
|
-
|
|
21899
|
-
|
|
21900
|
-
|
|
21901
|
-
|
|
21902
|
-
|
|
21903
|
-
snippet: redact(text).slice(0, 400)
|
|
21975
|
+
body: json ?? redact(text).slice(0, 800),
|
|
21976
|
+
...retryable ? {
|
|
21977
|
+
retries,
|
|
21978
|
+
retryAfterSeconds: hintMs === null ? null : Math.ceil(hintMs / 1e3)
|
|
21979
|
+
} : {},
|
|
21980
|
+
...rateLimit ? { rateLimit } : {}
|
|
21904
21981
|
});
|
|
21905
21982
|
}
|
|
21906
|
-
return json;
|
|
21907
21983
|
}
|
|
21908
21984
|
function redactUrl(url) {
|
|
21909
21985
|
try {
|
|
@@ -22111,17 +22187,6 @@ function assertPaymentLimit(invoiceUsd) {
|
|
|
22111
22187
|
}
|
|
22112
22188
|
|
|
22113
22189
|
// scripts/src/lib/api.mjs
|
|
22114
|
-
var PKG_VERSION = (() => {
|
|
22115
|
-
const requireFrom = createRequire(import.meta.url);
|
|
22116
|
-
for (const candidate of ["../../package.json", "../../../package.json"]) {
|
|
22117
|
-
try {
|
|
22118
|
-
const pkg = requireFrom(candidate);
|
|
22119
|
-
if (pkg?.name === "@rozoai/checkout" && pkg.version) return pkg.version;
|
|
22120
|
-
} catch {
|
|
22121
|
-
}
|
|
22122
|
-
}
|
|
22123
|
-
return "0.0.0";
|
|
22124
|
-
})();
|
|
22125
22190
|
var MPP_BASE = process.env.ROZO_CHECKOUT_MPP_BASE || "https://apiserver.mpprouter.dev/v1/services/rozo-agent-api";
|
|
22126
22191
|
var CLIENT_LABEL = `rozo-checkout-cli/${PKG_VERSION}`;
|
|
22127
22192
|
var ATTRIBUTION_CLIENT = `rozo-checkout-skill/${PKG_VERSION}`;
|
|
@@ -22359,6 +22424,8 @@ var MARGINS_MS = {
|
|
|
22359
22424
|
};
|
|
22360
22425
|
var BOLT11_MIN_VALIDITY_MS = 10 * MINUTE;
|
|
22361
22426
|
var DEFAULT_MARGIN_MS = 10 * MINUTE;
|
|
22427
|
+
var DEFAULT_WATCH_MS = 10 * MINUTE;
|
|
22428
|
+
var LIGHTNING_WATCH_CAP_MS = 60 * MINUTE;
|
|
22362
22429
|
function marginFor(chainId) {
|
|
22363
22430
|
const key = String(chainId);
|
|
22364
22431
|
return MARGINS_MS[key] ?? MARGINS_MS[chainId] ?? DEFAULT_MARGIN_MS;
|
package/scripts/dist/send-sol.js
CHANGED
|
@@ -32150,6 +32150,8 @@ var SUPPORT = Object.freeze({
|
|
|
32150
32150
|
discord: "https://discord.gg/EfWejgTbuU"
|
|
32151
32151
|
});
|
|
32152
32152
|
var SUPPORT_TEXT = `Need help? Email ${SUPPORT.email}, or reach ROZO on X ${SUPPORT.x} or Discord ${SUPPORT.discord}.`;
|
|
32153
|
+
var BULK_DOCS_URL = "https://docs.rozo.ai/products/checkout/bulk-and-agents";
|
|
32154
|
+
var BULK_HINT_TEXT = `Buying regularly or for others? ${BULK_DOCS_URL}`;
|
|
32153
32155
|
|
|
32154
32156
|
// scripts/src/lib/output.mjs
|
|
32155
32157
|
var PUBLIC_SUPPORT_URLS = /* @__PURE__ */ new Set([SUPPORT.x, SUPPORT.discord]);
|
|
@@ -32171,6 +32173,7 @@ function redact(text) {
|
|
|
32171
32173
|
return `${scheme}://${host}${hadMore ? "/<redacted>" : ""}`;
|
|
32172
32174
|
});
|
|
32173
32175
|
s = s.replace(/\b(bearer)\s+[A-Za-z0-9._~+/=-]{8,}/gi, "$1 <redacted>");
|
|
32176
|
+
s = s.replace(/\bak_[A-Za-z0-9_-]{8,}/g, "ak_<redacted>");
|
|
32174
32177
|
s = s.replace(
|
|
32175
32178
|
/\b(api[-_]?key|apikey|access[-_]?token|auth[-_]?token|secret|token|password|passwd|pwd)\b(\s*[:=]\s*)("?)[A-Za-z0-9._~+/=-]{6,}\3/gi,
|
|
32176
32179
|
"$1$2<redacted>"
|
|
@@ -33026,18 +33029,66 @@ function promptPassphrase(prompt = " Keystore passphrase: ") {
|
|
|
33026
33029
|
});
|
|
33027
33030
|
}
|
|
33028
33031
|
|
|
33029
|
-
// scripts/src/lib/
|
|
33032
|
+
// scripts/src/lib/version.mjs
|
|
33030
33033
|
import { createRequire } from "node:module";
|
|
33034
|
+
var PKG_VERSION = (() => {
|
|
33035
|
+
const requireFrom = createRequire(import.meta.url);
|
|
33036
|
+
for (const candidate of ["../../package.json", "../../../package.json"]) {
|
|
33037
|
+
try {
|
|
33038
|
+
const pkg = requireFrom(candidate);
|
|
33039
|
+
if (pkg?.name === "@rozoai/checkout" && pkg.version) return pkg.version;
|
|
33040
|
+
} catch {
|
|
33041
|
+
}
|
|
33042
|
+
}
|
|
33043
|
+
return "0.0.0";
|
|
33044
|
+
})();
|
|
33031
33045
|
|
|
33032
33046
|
// scripts/src/lib/http.mjs
|
|
33033
33047
|
var DEFAULT_TIMEOUT_MS = 2e4;
|
|
33034
|
-
var USER_AGENT =
|
|
33035
|
-
|
|
33048
|
+
var USER_AGENT = `rozo-checkout-skill/${PKG_VERSION}`;
|
|
33049
|
+
var MAX_RETRIES = 3;
|
|
33050
|
+
var MAX_TOTAL_WAIT_MS = 12e4;
|
|
33051
|
+
var FALLBACK_BACKOFF_MS = [2e3, 4e3, 8e3];
|
|
33052
|
+
var defaultSleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
33053
|
+
function parseRetryAfter(value, now = Date.now()) {
|
|
33054
|
+
if (value === null || value === void 0) return null;
|
|
33055
|
+
const s = String(value).trim();
|
|
33056
|
+
if (!s) return null;
|
|
33057
|
+
if (/^\d+(\.\d+)?$/.test(s)) return Math.round(Number(s) * 1e3);
|
|
33058
|
+
const at = Date.parse(s);
|
|
33059
|
+
if (!Number.isFinite(at)) return null;
|
|
33060
|
+
return Math.max(0, at - now);
|
|
33061
|
+
}
|
|
33062
|
+
function bodyRetryAfterMs(json) {
|
|
33063
|
+
const raw = json?.retryAfterSeconds ?? json?.error?.retryAfterSeconds;
|
|
33064
|
+
if (raw === null || raw === void 0 || raw === "") return null;
|
|
33065
|
+
const n = Number(raw);
|
|
33066
|
+
return Number.isFinite(n) && n >= 0 ? Math.round(n * 1e3) : null;
|
|
33067
|
+
}
|
|
33068
|
+
function rateLimitInfo(res) {
|
|
33069
|
+
const pick = (name) => res.headers?.get?.(name) ?? null;
|
|
33070
|
+
const info = {
|
|
33071
|
+
limit: pick("x-ratelimit-limit"),
|
|
33072
|
+
remaining: pick("x-ratelimit-remaining"),
|
|
33073
|
+
tier: pick("x-ratelimit-tier"),
|
|
33074
|
+
scope: pick("x-ratelimit-scope")
|
|
33075
|
+
};
|
|
33076
|
+
const present = Object.fromEntries(Object.entries(info).filter(([, v]) => v !== null));
|
|
33077
|
+
return Object.keys(present).length ? present : null;
|
|
33078
|
+
}
|
|
33079
|
+
function parseBody(text) {
|
|
33080
|
+
if (!text) return null;
|
|
33081
|
+
try {
|
|
33082
|
+
return JSON.parse(text);
|
|
33083
|
+
} catch {
|
|
33084
|
+
return null;
|
|
33085
|
+
}
|
|
33086
|
+
}
|
|
33087
|
+
async function fetchOnce(method, url, body, timeoutMs) {
|
|
33036
33088
|
const controller = new AbortController();
|
|
33037
33089
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
33038
|
-
let res;
|
|
33039
33090
|
try {
|
|
33040
|
-
res = await fetch(url, {
|
|
33091
|
+
const res = await fetch(url, {
|
|
33041
33092
|
method,
|
|
33042
33093
|
headers: {
|
|
33043
33094
|
accept: "application/json",
|
|
@@ -33047,6 +33098,8 @@ async function request(method, url, { body, timeoutMs = DEFAULT_TIMEOUT_MS } = {
|
|
|
33047
33098
|
body: body !== void 0 ? JSON.stringify(body) : void 0,
|
|
33048
33099
|
signal: controller.signal
|
|
33049
33100
|
});
|
|
33101
|
+
const text = await res.text();
|
|
33102
|
+
return { res, text };
|
|
33050
33103
|
} catch (err) {
|
|
33051
33104
|
throw new SkillError(
|
|
33052
33105
|
err?.name === "AbortError" ? "HTTP_TIMEOUT" : "HTTP_UNREACHABLE",
|
|
@@ -33056,31 +33109,54 @@ async function request(method, url, { body, timeoutMs = DEFAULT_TIMEOUT_MS } = {
|
|
|
33056
33109
|
} finally {
|
|
33057
33110
|
clearTimeout(timer);
|
|
33058
33111
|
}
|
|
33059
|
-
|
|
33060
|
-
|
|
33061
|
-
|
|
33062
|
-
|
|
33063
|
-
|
|
33064
|
-
|
|
33065
|
-
|
|
33112
|
+
}
|
|
33113
|
+
async function request(method, url, {
|
|
33114
|
+
body,
|
|
33115
|
+
timeoutMs = DEFAULT_TIMEOUT_MS,
|
|
33116
|
+
sleep = defaultSleep,
|
|
33117
|
+
now = Date.now,
|
|
33118
|
+
maxTotalWaitMs = MAX_TOTAL_WAIT_MS
|
|
33119
|
+
} = {}) {
|
|
33120
|
+
let waitedMs = 0;
|
|
33121
|
+
let retries = 0;
|
|
33122
|
+
for (; ; ) {
|
|
33123
|
+
const { res, text } = await fetchOnce(method, url, body, timeoutMs);
|
|
33124
|
+
const json = parseBody(text);
|
|
33125
|
+
if (res.ok) {
|
|
33126
|
+
if (json === null) {
|
|
33127
|
+
throw new SkillError("HTTP_BAD_JSON", "Endpoint returned a non-JSON body.", {
|
|
33128
|
+
url: redactUrl(url),
|
|
33129
|
+
snippet: redact(text).slice(0, 400)
|
|
33130
|
+
});
|
|
33131
|
+
}
|
|
33132
|
+
return json;
|
|
33133
|
+
}
|
|
33134
|
+
const headerWaitMs = parseRetryAfter(res.headers?.get?.("retry-after"), now());
|
|
33135
|
+
const hintMs = headerWaitMs ?? bodyRetryAfterMs(json);
|
|
33136
|
+
const retryable = res.status === 429 || res.status === 503 && hintMs !== null;
|
|
33137
|
+
if (retryable && retries < MAX_RETRIES) {
|
|
33138
|
+
const waitMs = hintMs ?? FALLBACK_BACKOFF_MS[retries];
|
|
33139
|
+
if (waitedMs + waitMs <= Math.min(maxTotalWaitMs, MAX_TOTAL_WAIT_MS)) {
|
|
33140
|
+
retries += 1;
|
|
33141
|
+
waitedMs += waitMs;
|
|
33142
|
+
await sleep(waitMs);
|
|
33143
|
+
continue;
|
|
33144
|
+
}
|
|
33066
33145
|
}
|
|
33067
|
-
}
|
|
33068
|
-
if (!res.ok) {
|
|
33069
33146
|
const code = json?.code || json?.error?.code || (typeof json?.error === "string" && /^[A-Z][A-Z0-9_]+$/.test(json.error) ? json.error : null) || `HTTP_${res.status}`;
|
|
33070
33147
|
const message = json?.message || (typeof json?.error === "string" ? json.error : json?.error?.message) || `HTTP ${res.status}`;
|
|
33148
|
+
const rateLimit = rateLimitInfo(res);
|
|
33071
33149
|
throw new SkillError(code, redact(String(message)), {
|
|
33072
33150
|
httpStatus: res.status,
|
|
33073
33151
|
url: redactUrl(url),
|
|
33074
|
-
body: json ?? redact(text).slice(0, 800)
|
|
33075
|
-
|
|
33076
|
-
|
|
33077
|
-
|
|
33078
|
-
|
|
33079
|
-
|
|
33080
|
-
snippet: redact(text).slice(0, 400)
|
|
33152
|
+
body: json ?? redact(text).slice(0, 800),
|
|
33153
|
+
...retryable ? {
|
|
33154
|
+
retries,
|
|
33155
|
+
retryAfterSeconds: hintMs === null ? null : Math.ceil(hintMs / 1e3)
|
|
33156
|
+
} : {},
|
|
33157
|
+
...rateLimit ? { rateLimit } : {}
|
|
33081
33158
|
});
|
|
33082
33159
|
}
|
|
33083
|
-
return json;
|
|
33084
33160
|
}
|
|
33085
33161
|
function redactUrl(url) {
|
|
33086
33162
|
try {
|
|
@@ -33288,17 +33364,6 @@ function assertPaymentLimit(invoiceUsd) {
|
|
|
33288
33364
|
}
|
|
33289
33365
|
|
|
33290
33366
|
// scripts/src/lib/api.mjs
|
|
33291
|
-
var PKG_VERSION = (() => {
|
|
33292
|
-
const requireFrom = createRequire(import.meta.url);
|
|
33293
|
-
for (const candidate of ["../../package.json", "../../../package.json"]) {
|
|
33294
|
-
try {
|
|
33295
|
-
const pkg = requireFrom(candidate);
|
|
33296
|
-
if (pkg?.name === "@rozoai/checkout" && pkg.version) return pkg.version;
|
|
33297
|
-
} catch {
|
|
33298
|
-
}
|
|
33299
|
-
}
|
|
33300
|
-
return "0.0.0";
|
|
33301
|
-
})();
|
|
33302
33367
|
var MPP_BASE = process.env.ROZO_CHECKOUT_MPP_BASE || "https://apiserver.mpprouter.dev/v1/services/rozo-agent-api";
|
|
33303
33368
|
var CLIENT_LABEL = `rozo-checkout-cli/${PKG_VERSION}`;
|
|
33304
33369
|
var ATTRIBUTION_CLIENT = `rozo-checkout-skill/${PKG_VERSION}`;
|
|
@@ -33536,6 +33601,8 @@ var MARGINS_MS = {
|
|
|
33536
33601
|
};
|
|
33537
33602
|
var BOLT11_MIN_VALIDITY_MS = 10 * MINUTE;
|
|
33538
33603
|
var DEFAULT_MARGIN_MS = 10 * MINUTE;
|
|
33604
|
+
var DEFAULT_WATCH_MS = 10 * MINUTE;
|
|
33605
|
+
var LIGHTNING_WATCH_CAP_MS = 60 * MINUTE;
|
|
33539
33606
|
function marginFor(chainId) {
|
|
33540
33607
|
const key = String(chainId);
|
|
33541
33608
|
return MARGINS_MS[key] ?? MARGINS_MS[chainId] ?? DEFAULT_MARGIN_MS;
|