@rozoai/checkout 0.1.7 → 0.1.11

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.
@@ -153,6 +153,9 @@ function maskMemo(memo) {
153
153
  return `${s.slice(0, 4)}...${s.slice(-3)}`;
154
154
  }
155
155
 
156
+ // scripts/src/lib/api.mjs
157
+ import { createRequire } from "node:module";
158
+
156
159
  // scripts/src/lib/http.mjs
157
160
  var DEFAULT_TIMEOUT_MS = 2e4;
158
161
  var USER_AGENT = "rozo-checkout-skill/1.0";
@@ -222,7 +225,20 @@ function postJson(url, body, opts) {
222
225
  }
223
226
 
224
227
  // scripts/src/lib/api.mjs
228
+ var PKG_VERSION = (() => {
229
+ const requireFrom = createRequire(import.meta.url);
230
+ for (const candidate of ["../../package.json", "../../../package.json"]) {
231
+ try {
232
+ const pkg = requireFrom(candidate);
233
+ if (pkg?.name === "@rozoai/checkout" && pkg.version) return pkg.version;
234
+ } catch {
235
+ }
236
+ }
237
+ return "0.0.0";
238
+ })();
225
239
  var MPP_BASE = process.env.ROZO_CHECKOUT_MPP_BASE || "https://apiserver.mpprouter.dev/v1/services/rozo-agent-api";
240
+ var CLIENT_LABEL = `rozo-checkout-cli/${PKG_VERSION}`;
241
+ var ATTRIBUTION_CLIENT = `rozo-checkout-skill/${PKG_VERSION}`;
226
242
  var INTENTS_BASE = process.env.ROZO_CHECKOUT_INTENTS_BASE || "https://intentapiv4.rozo.ai/functions/v1/payment-api";
227
243
  async function quoteInvoice({ url, linkId }) {
228
244
  const body = url ? { url } : { payment_id: linkId };
@@ -232,7 +248,9 @@ async function createInvoice({ url, linkId, source, quoteReceipt }) {
232
248
  const body = {
233
249
  ...url ? { url } : { payment_id: linkId },
234
250
  source: { chainId: String(source.chainId), tokenSymbol: source.tokenSymbol },
235
- ...quoteReceipt ? { quoteReceipt } : {}
251
+ ...quoteReceipt ? { quoteReceipt } : {},
252
+ client: CLIENT_LABEL,
253
+ attribution: { client: ATTRIBUTION_CLIENT }
236
254
  };
237
255
  return postJson(`${MPP_BASE}/create-invoice`, body);
238
256
  }
@@ -133,6 +133,9 @@ function extractLinkId(urlOrId) {
133
133
  );
134
134
  }
135
135
 
136
+ // scripts/src/lib/api.mjs
137
+ import { createRequire } from "node:module";
138
+
136
139
  // scripts/src/lib/http.mjs
137
140
  var DEFAULT_TIMEOUT_MS = 2e4;
138
141
  var USER_AGENT = "rozo-checkout-skill/1.0";
@@ -199,7 +202,20 @@ function postJson(url, body, opts) {
199
202
  }
200
203
 
201
204
  // scripts/src/lib/api.mjs
205
+ var PKG_VERSION = (() => {
206
+ const requireFrom = createRequire(import.meta.url);
207
+ for (const candidate of ["../../package.json", "../../../package.json"]) {
208
+ try {
209
+ const pkg = requireFrom(candidate);
210
+ if (pkg?.name === "@rozoai/checkout" && pkg.version) return pkg.version;
211
+ } catch {
212
+ }
213
+ }
214
+ return "0.0.0";
215
+ })();
202
216
  var MPP_BASE = process.env.ROZO_CHECKOUT_MPP_BASE || "https://apiserver.mpprouter.dev/v1/services/rozo-agent-api";
217
+ var CLIENT_LABEL = `rozo-checkout-cli/${PKG_VERSION}`;
218
+ var ATTRIBUTION_CLIENT = `rozo-checkout-skill/${PKG_VERSION}`;
203
219
  var INTENTS_BASE = process.env.ROZO_CHECKOUT_INTENTS_BASE || "https://intentapiv4.rozo.ai/functions/v1/payment-api";
204
220
  async function quoteInvoice({ url, linkId }) {
205
221
  const body = url ? { url } : { payment_id: linkId };
@@ -999,7 +999,7 @@ var init_size = __esm({
999
999
  var version2;
1000
1000
  var init_version2 = __esm({
1001
1001
  "node_modules/viem/_esm/errors/version.js"() {
1002
- version2 = "2.55.11";
1002
+ version2 = "2.55.13";
1003
1003
  }
1004
1004
  });
1005
1005
 
@@ -1759,10 +1759,10 @@ var init_u64 = __esm({
1759
1759
 
1760
1760
  // node_modules/@noble/hashes/esm/cryptoNode.js
1761
1761
  import * as nc from "node:crypto";
1762
- var crypto2;
1762
+ var crypto3;
1763
1763
  var init_cryptoNode = __esm({
1764
1764
  "node_modules/@noble/hashes/esm/cryptoNode.js"() {
1765
- crypto2 = nc && typeof nc === "object" && "webcrypto" in nc ? nc.webcrypto : nc && typeof nc === "object" && "randomBytes" in nc ? nc : void 0;
1765
+ crypto3 = nc && typeof nc === "object" && "webcrypto" in nc ? nc.webcrypto : nc && typeof nc === "object" && "randomBytes" in nc ? nc : void 0;
1766
1766
  }
1767
1767
  });
1768
1768
 
@@ -1857,11 +1857,11 @@ function createHasher(hashCons) {
1857
1857
  return hashC;
1858
1858
  }
1859
1859
  function randomBytes(bytesLength = 32) {
1860
- if (crypto2 && typeof crypto2.getRandomValues === "function") {
1861
- return crypto2.getRandomValues(new Uint8Array(bytesLength));
1860
+ if (crypto3 && typeof crypto3.getRandomValues === "function") {
1861
+ return crypto3.getRandomValues(new Uint8Array(bytesLength));
1862
1862
  }
1863
- if (crypto2 && typeof crypto2.randomBytes === "function") {
1864
- return Uint8Array.from(crypto2.randomBytes(bytesLength));
1863
+ if (crypto3 && typeof crypto3.randomBytes === "function") {
1864
+ return Uint8Array.from(crypto3.randomBytes(bytesLength));
1865
1865
  }
1866
1866
  throw new Error("crypto.getRandomValues must be defined");
1867
1867
  }
@@ -10214,43 +10214,148 @@ function chainFamily(chainId) {
10214
10214
  // scripts/src/lib/keys.mjs
10215
10215
  import fs from "node:fs";
10216
10216
  import path from "node:path";
10217
- import { execFileSync } from "node:child_process";
10218
- var ENV_FILE_RE = /^\.env(\..+)?$/;
10219
- var PUBLIC_ENV_RE = /^\.env\.(example|sample|template)$/;
10220
- function insideGitWorkTree(dir, whatFor) {
10217
+ import crypto2 from "node:crypto";
10218
+ function findGitRepo(dir) {
10219
+ for (const v of ["GIT_DIR", "GIT_WORK_TREE", "GIT_INDEX_FILE"]) {
10220
+ if (process.env[v]) {
10221
+ throw new SkillError(
10222
+ "TRACKED_DOTENV_UNVERIFIABLE",
10223
+ `${v} is set, so the repository layout cannot be resolved by reading the filesystem alone. Unset it (or run from a plain checkout) before using hot-wallet keys.`
10224
+ );
10225
+ }
10226
+ }
10227
+ let cur = path.resolve(dir);
10228
+ for (; ; ) {
10229
+ const dotGit = path.join(cur, ".git");
10230
+ let st = null;
10231
+ try {
10232
+ st = fs.statSync(dotGit);
10233
+ } catch (err) {
10234
+ if (err?.code !== "ENOENT" && err?.code !== "ENOTDIR") {
10235
+ throw new SkillError(
10236
+ "TRACKED_DOTENV_UNVERIFIABLE",
10237
+ `A .git entry here could not be inspected (${err?.code || "error"}), so tracked status cannot be proved. Refusing.`
10238
+ );
10239
+ }
10240
+ st = null;
10241
+ }
10242
+ if (st) {
10243
+ if (st.isDirectory()) return { root: cur, gitDir: dotGit };
10244
+ let text;
10245
+ try {
10246
+ text = fs.readFileSync(dotGit, "utf8");
10247
+ } catch {
10248
+ throw new SkillError(
10249
+ "TRACKED_DOTENV_UNVERIFIABLE",
10250
+ "A .git entry exists here but could not be read, so tracked status cannot be proved. Refusing."
10251
+ );
10252
+ }
10253
+ const m = /^gitdir:\s*(.+)\s*$/m.exec(text);
10254
+ if (!m) {
10255
+ throw new SkillError(
10256
+ "TRACKED_DOTENV_UNVERIFIABLE",
10257
+ "A .git file exists here but is not a recognised gitdir pointer. Refusing."
10258
+ );
10259
+ }
10260
+ return { root: cur, gitDir: path.resolve(cur, m[1]) };
10261
+ }
10262
+ const parent = path.dirname(cur);
10263
+ if (parent === cur) return null;
10264
+ cur = parent;
10265
+ }
10266
+ }
10267
+ function trackedPathsFromIndex(buf, { hashLen = 20 } = {}) {
10268
+ const fail2 = (why) => new SkillError(
10269
+ "TRACKED_DOTENV_UNVERIFIABLE",
10270
+ `The git index could not be interpreted (${why}), so tracked status cannot be proved. Refusing.`
10271
+ );
10272
+ if (buf.length < 12 + hashLen || buf.toString("latin1", 0, 4) !== "DIRC") throw fail2("bad header");
10273
+ const algo = hashLen === 32 ? "sha256" : "sha1";
10274
+ const expected = buf.subarray(buf.length - hashLen);
10275
+ const actual = crypto2.createHash(algo).update(buf.subarray(0, buf.length - hashLen)).digest();
10276
+ if (!actual.equals(expected)) throw fail2(`${algo} checksum mismatch`);
10277
+ const version4 = buf.readUInt32BE(4);
10278
+ if (version4 !== 2 && version4 !== 3) throw fail2(`unsupported index version ${version4}`);
10279
+ const count = buf.readUInt32BE(8);
10280
+ const paths = /* @__PURE__ */ new Set();
10281
+ const fixed = 40 + hashLen + 2;
10282
+ let off = 12;
10283
+ for (let i = 0; i < count; i++) {
10284
+ const entryStart = off;
10285
+ if (off + fixed > buf.length - hashLen) throw fail2("truncated entry");
10286
+ const flags = buf.readUInt16BE(off + fixed - 2);
10287
+ let nameOff = off + fixed;
10288
+ if (flags & 16384) {
10289
+ if (version4 < 3) throw fail2("extended flags in v2 index");
10290
+ nameOff += 2;
10291
+ }
10292
+ const nameLen = flags & 4095;
10293
+ let end;
10294
+ if (nameLen < 4095) {
10295
+ end = nameOff + nameLen;
10296
+ if (end > buf.length - hashLen) throw fail2("truncated path");
10297
+ } else {
10298
+ end = buf.indexOf(0, nameOff);
10299
+ if (end === -1 || end > buf.length - hashLen) throw fail2("unterminated path");
10300
+ }
10301
+ paths.add(buf.toString("utf8", nameOff, end));
10302
+ const entryLen = end - entryStart;
10303
+ off = entryStart + (Math.floor(entryLen / 8) + 1) * 8;
10304
+ }
10305
+ while (off < buf.length - hashLen) {
10306
+ if (off + 8 > buf.length - hashLen) throw fail2("truncated extension header");
10307
+ const extName = buf.toString("latin1", off, off + 4);
10308
+ const extSize = buf.readUInt32BE(off + 4);
10309
+ const first = extName.charCodeAt(0);
10310
+ if (first >= 97 && first <= 122) {
10311
+ throw fail2(`mandatory index extension "${extName}" (e.g. core.splitIndex) is not supported`);
10312
+ }
10313
+ off += 8 + extSize;
10314
+ if (off > buf.length - hashLen) throw fail2("truncated extension");
10315
+ }
10316
+ return paths;
10317
+ }
10318
+ function repoHashLen(gitDir) {
10319
+ let configDir = gitDir;
10221
10320
  try {
10222
- return execFileSync("git", ["rev-parse", "--is-inside-work-tree"], {
10223
- cwd: dir,
10224
- stdio: ["ignore", "pipe", "pipe"],
10225
- encoding: "utf8"
10226
- }).trim() === "true";
10321
+ const common = fs.readFileSync(path.join(gitDir, "commondir"), "utf8").trim();
10322
+ if (common) configDir = path.resolve(gitDir, common);
10323
+ } catch {
10324
+ }
10325
+ try {
10326
+ const cfg = fs.readFileSync(path.join(configDir, "config"), "utf8");
10327
+ if (/^\s*objectformat\s*=\s*sha256\s*$/im.test(cfg)) return 32;
10328
+ } catch {
10329
+ }
10330
+ return 20;
10331
+ }
10332
+ function trackedAmong(repo, files) {
10333
+ const indexPath = path.join(repo.gitDir, "index");
10334
+ let buf;
10335
+ try {
10336
+ buf = fs.readFileSync(indexPath);
10227
10337
  } catch (err) {
10228
- const stderr = String(err?.stderr || "");
10229
- if (/not a git repository|does not appear to be a git repository/i.test(stderr)) return false;
10338
+ if (err?.code === "ENOENT") return [];
10230
10339
  throw new SkillError(
10231
10340
  "TRACKED_DOTENV_UNVERIFIABLE",
10232
- `git could not be consulted (${err?.code || "unknown error"}), so it cannot be proved that ${whatFor} is untracked. Refusing rather than assuming it is safe.`
10341
+ "The git index exists but could not be read, so tracked status cannot be proved. Refusing."
10233
10342
  );
10234
10343
  }
10344
+ const tracked = trackedPathsFromIndex(buf, { hashLen: repoHashLen(repo.gitDir) });
10345
+ return files.filter((f) => {
10346
+ const rel = path.relative(repo.root, path.resolve(f)).split(path.sep).join("/");
10347
+ return tracked.has(rel);
10348
+ });
10235
10349
  }
10350
+ var ENV_FILE_RE = /^\.env(\..+)?$/;
10351
+ var PUBLIC_ENV_RE = /^\.env\.(example|sample|template)$/;
10236
10352
  function assertNotTrackedByGit(file) {
10237
10353
  const dir = path.dirname(path.resolve(file));
10238
- const base = path.basename(file);
10239
- if (!insideGitWorkTree(dir, "this key file")) return { checked: true, tracked: false };
10240
- let out;
10241
- try {
10242
- out = execFileSync("git", ["ls-files", "-z", "--", base], {
10243
- cwd: dir,
10244
- stdio: ["ignore", "pipe", "ignore"],
10245
- encoding: "utf8"
10246
- });
10247
- } catch {
10248
- throw new SkillError(
10249
- "TRACKED_DOTENV_UNVERIFIABLE",
10250
- "git could not report whether this key file is tracked. Refusing to use it."
10251
- );
10252
- }
10253
- if (out.split("\0").filter(Boolean).length) {
10354
+ const repo = findGitRepo(dir);
10355
+ if (!repo) return { checked: true, tracked: false };
10356
+ const hits = trackedAmong(repo, [file]);
10357
+ if (hits.length) {
10358
+ const base = path.basename(file);
10254
10359
  throw new SkillError(
10255
10360
  "TRACKED_KEYFILE",
10256
10361
  `${base} is tracked by git. A committed key is one push from being public \u2014 untrack it (git rm --cached ${base}) and gitignore it before using it to sign.`
@@ -10269,37 +10374,11 @@ function assertNoTrackedDotEnv(cwd = process.cwd()) {
10269
10374
  );
10270
10375
  }
10271
10376
  if (candidates.length === 0) return { checked: true, tracked: false, candidates: [] };
10272
- let insideRepo;
10273
- try {
10274
- insideRepo = execFileSync("git", ["rev-parse", "--is-inside-work-tree"], {
10275
- cwd,
10276
- stdio: ["ignore", "pipe", "pipe"],
10277
- encoding: "utf8"
10278
- }).trim() === "true";
10279
- } catch (err) {
10280
- const stderr = String(err?.stderr || "");
10281
- const notARepo = /not a git repository|does not appear to be a git repository/i.test(stderr);
10282
- if (notARepo) return { checked: true, tracked: false, candidates };
10283
- throw new SkillError(
10284
- "TRACKED_DOTENV_UNVERIFIABLE",
10285
- `Found ${candidates.length} .env file(s) here, but git could not be consulted (${err?.code || "unknown error"}), so it cannot be proved they are untracked. Refusing to use hot-wallet keys in this directory.`
10286
- );
10287
- }
10288
- if (!insideRepo) return { checked: true, tracked: false, candidates };
10289
- let out;
10290
- try {
10291
- out = execFileSync("git", ["ls-files", "-z", "--", ...candidates], {
10292
- cwd,
10293
- stdio: ["ignore", "pipe", "ignore"],
10294
- encoding: "utf8"
10295
- });
10296
- } catch {
10297
- throw new SkillError(
10298
- "TRACKED_DOTENV_UNVERIFIABLE",
10299
- "git could not report whether the .env file(s) in this directory are tracked. Refusing to use hot-wallet keys rather than assuming they are safe."
10300
- );
10301
- }
10302
- const tracked = out.split("\0").filter(Boolean);
10377
+ const repo = findGitRepo(cwd);
10378
+ if (!repo) return { checked: true, tracked: false, candidates };
10379
+ const tracked = trackedAmong(repo, candidates.map((f) => path.join(cwd, f))).map(
10380
+ (f) => path.basename(f)
10381
+ );
10303
10382
  if (tracked.length) {
10304
10383
  throw new SkillError(
10305
10384
  "TRACKED_DOTENV",
@@ -10313,7 +10392,7 @@ function assertNoTrackedDotEnv(cwd = process.cwd()) {
10313
10392
  import fs3 from "node:fs";
10314
10393
  import path3 from "node:path";
10315
10394
  import os2 from "node:os";
10316
- import crypto3 from "node:crypto";
10395
+ import crypto4 from "node:crypto";
10317
10396
 
10318
10397
  // node_modules/viem/_esm/utils/getAction.js
10319
10398
  function getAction(client, actionFn, name) {
@@ -11375,14 +11454,6 @@ async function prepareTransactionRequest(client, args) {
11375
11454
  }
11376
11455
  let account = account_ ? parseAccount(account_) : account_;
11377
11456
  let nonce = request2.nonce;
11378
- if (parameters.includes("nonce") && typeof nonce === "undefined" && account && nonceManager) {
11379
- const chainId2 = await getChainId2();
11380
- nonce = await nonceManager.consume({
11381
- address: account.address,
11382
- chainId: chainId2,
11383
- client
11384
- });
11385
- }
11386
11457
  if (prepareTransactionRequest2?.fn && prepareTransactionRequest2.runAt?.includes("beforeFillTransaction")) {
11387
11458
  request2 = await prepareTransactionRequest2.fn({ ...request2, chain }, {
11388
11459
  client,
@@ -11392,13 +11463,21 @@ async function prepareTransactionRequest(client, args) {
11392
11463
  const sender = request2.account ?? request2.from;
11393
11464
  account = sender ? parseAccount(sender) : void 0;
11394
11465
  }
11466
+ if (parameters.includes("nonce") && typeof nonce === "undefined" && account && nonceManager) {
11467
+ const chainId2 = await getChainId2();
11468
+ nonce = await nonceManager.consume({
11469
+ address: account.address,
11470
+ chainId: chainId2,
11471
+ client
11472
+ });
11473
+ }
11395
11474
  const attemptFill = (() => {
11396
11475
  if ((parameters.includes("blobVersionedHashes") || parameters.includes("sidecars")) && request2.kzg && request2.blobs)
11397
11476
  return false;
11398
- if (supportsFillTransaction.get(client.uid) === false)
11399
- return false;
11400
11477
  if (parameters.length > 0 && "feePayer" in request2 && request2.feePayer && !("feePayerSignature" in request2 && request2.feePayerSignature))
11401
11478
  return true;
11479
+ if (supportsFillTransaction.get(client.uid) === false)
11480
+ return false;
11402
11481
  const shouldAttempt = ["fees", "gas"].some((parameter) => parameters.includes(parameter));
11403
11482
  if (!shouldAttempt)
11404
11483
  return false;
@@ -12530,17 +12609,29 @@ async function sendTransaction(client, parameters) {
12530
12609
  }
12531
12610
  }
12532
12611
  if (account?.type === "local") {
12533
- if (account.nonceManager && typeof nonce === "undefined") {
12534
- const requestChainId = rest.chainId;
12535
- const chainId = await (async () => {
12536
- if (typeof requestChainId === "number")
12537
- return requestChainId;
12538
- if (chain)
12539
- return chain.id;
12540
- return getAction(client, getChainId, "getChainId")({});
12541
- })();
12542
- nonceManagerParameters = { address: account.address, chainId };
12543
- }
12612
+ const nonceManager = (() => {
12613
+ if (!account.nonceManager || typeof nonce !== "undefined")
12614
+ return account.nonceManager;
12615
+ const nonceManager2 = account.nonceManager;
12616
+ return {
12617
+ consume(parameters2) {
12618
+ nonceManagerParameters = {
12619
+ address: parameters2.address,
12620
+ chainId: parameters2.chainId
12621
+ };
12622
+ return nonceManager2.consume(parameters2);
12623
+ },
12624
+ get(parameters2) {
12625
+ return nonceManager2.get(parameters2);
12626
+ },
12627
+ increment(parameters2) {
12628
+ return nonceManager2.increment(parameters2);
12629
+ },
12630
+ reset(parameters2) {
12631
+ return nonceManager2.reset(parameters2);
12632
+ }
12633
+ };
12634
+ })();
12544
12635
  const request2 = await getAction(client, prepareTransactionRequest, "prepareTransactionRequest")({
12545
12636
  account,
12546
12637
  accessList,
@@ -12554,7 +12645,7 @@ async function sendTransaction(client, parameters) {
12554
12645
  maxFeePerGas,
12555
12646
  maxPriorityFeePerGas,
12556
12647
  nonce,
12557
- nonceManager: account.nonceManager,
12648
+ nonceManager,
12558
12649
  parameters: [...defaultParameters, "sidecars"],
12559
12650
  type,
12560
12651
  value,
@@ -13059,6 +13150,7 @@ function bindActionDecorators(client, action) {
13059
13150
  "estimateGas",
13060
13151
  "prepare",
13061
13152
  "prepareRecipient",
13153
+ "predict",
13062
13154
  "simulate"
13063
13155
  ])
13064
13156
  if (Object.hasOwn(action, key)) {
@@ -20454,17 +20546,29 @@ async function sendTransactionSync(client, parameters) {
20454
20546
  return receipt;
20455
20547
  }
20456
20548
  if (account?.type === "local") {
20457
- if (account.nonceManager && typeof nonce === "undefined") {
20458
- const requestChainId = rest.chainId;
20459
- const chainId = await (async () => {
20460
- if (typeof requestChainId === "number")
20461
- return requestChainId;
20462
- if (chain)
20463
- return chain.id;
20464
- return getAction(client, getChainId, "getChainId")({});
20465
- })();
20466
- nonceManagerParameters = { address: account.address, chainId };
20467
- }
20549
+ const nonceManager = (() => {
20550
+ if (!account.nonceManager || typeof nonce !== "undefined")
20551
+ return account.nonceManager;
20552
+ const nonceManager2 = account.nonceManager;
20553
+ return {
20554
+ consume(parameters2) {
20555
+ nonceManagerParameters = {
20556
+ address: parameters2.address,
20557
+ chainId: parameters2.chainId
20558
+ };
20559
+ return nonceManager2.consume(parameters2);
20560
+ },
20561
+ get(parameters2) {
20562
+ return nonceManager2.get(parameters2);
20563
+ },
20564
+ increment(parameters2) {
20565
+ return nonceManager2.increment(parameters2);
20566
+ },
20567
+ reset(parameters2) {
20568
+ return nonceManager2.reset(parameters2);
20569
+ }
20570
+ };
20571
+ })();
20468
20572
  const request2 = await getAction(client, prepareTransactionRequest, "prepareTransactionRequest")({
20469
20573
  account,
20470
20574
  accessList,
@@ -20478,7 +20582,7 @@ async function sendTransactionSync(client, parameters) {
20478
20582
  maxFeePerGas,
20479
20583
  maxPriorityFeePerGas,
20480
20584
  nonce,
20481
- nonceManager: account.nonceManager,
20585
+ nonceManager,
20482
20586
  parameters: [...defaultParameters, "sidecars"],
20483
20587
  type,
20484
20588
  value,
@@ -21504,7 +21608,7 @@ function decryptKeystoreV3(keystore, passphrase) {
21504
21608
  if (!n || !r || !p || !dklen || !salt) {
21505
21609
  throw new SkillError("BAD_KEYSTORE", "The keystore scrypt parameters are incomplete.");
21506
21610
  }
21507
- derived = crypto3.scryptSync(pass, Buffer.from(salt, "hex"), dklen, {
21611
+ derived = crypto4.scryptSync(pass, Buffer.from(salt, "hex"), dklen, {
21508
21612
  N: n,
21509
21613
  r,
21510
21614
  p,
@@ -21520,7 +21624,7 @@ function decryptKeystoreV3(keystore, passphrase) {
21520
21624
  if (!iterations || !dklen || !salt) {
21521
21625
  throw new SkillError("BAD_KEYSTORE", "The keystore pbkdf2 parameters are incomplete.");
21522
21626
  }
21523
- derived = crypto3.pbkdf2Sync(pass, Buffer.from(salt, "hex"), iterations, dklen, "sha256");
21627
+ derived = crypto4.pbkdf2Sync(pass, Buffer.from(salt, "hex"), iterations, dklen, "sha256");
21524
21628
  } else {
21525
21629
  throw new SkillError("BAD_KEYSTORE", `Unsupported keystore KDF "${c.kdf}".`);
21526
21630
  }
@@ -21535,7 +21639,7 @@ function decryptKeystoreV3(keystore, passphrase) {
21535
21639
  if (c.cipher !== "aes-128-ctr") {
21536
21640
  throw new SkillError("BAD_KEYSTORE", `Unsupported keystore cipher "${c.cipher}".`);
21537
21641
  }
21538
- const decipher = crypto3.createDecipheriv(
21642
+ const decipher = crypto4.createDecipheriv(
21539
21643
  "aes-128-ctr",
21540
21644
  derived.subarray(0, 16),
21541
21645
  Buffer.from(c.cipherparams.iv, "hex")
@@ -21557,7 +21661,7 @@ function timingSafeEqualHex(a, b) {
21557
21661
  const ab = Buffer.from(String(a).toLowerCase(), "hex");
21558
21662
  const bb = Buffer.from(String(b).toLowerCase(), "hex");
21559
21663
  if (ab.length === 0 || ab.length !== bb.length) return false;
21560
- return crypto3.timingSafeEqual(ab, bb);
21664
+ return crypto4.timingSafeEqual(ab, bb);
21561
21665
  }
21562
21666
  function looksLikeKeystore(text) {
21563
21667
  const t = String(text).trimStart();
@@ -21713,6 +21817,9 @@ function promptPassphrase(prompt = " Keystore passphrase: ") {
21713
21817
  });
21714
21818
  }
21715
21819
 
21820
+ // scripts/src/lib/api.mjs
21821
+ import { createRequire } from "node:module";
21822
+
21716
21823
  // scripts/src/lib/http.mjs
21717
21824
  var DEFAULT_TIMEOUT_MS = 2e4;
21718
21825
  var USER_AGENT = "rozo-checkout-skill/1.0";
@@ -21779,7 +21886,20 @@ function getJson(url, opts) {
21779
21886
  }
21780
21887
 
21781
21888
  // scripts/src/lib/api.mjs
21889
+ var PKG_VERSION = (() => {
21890
+ const requireFrom = createRequire(import.meta.url);
21891
+ for (const candidate of ["../../package.json", "../../../package.json"]) {
21892
+ try {
21893
+ const pkg = requireFrom(candidate);
21894
+ if (pkg?.name === "@rozoai/checkout" && pkg.version) return pkg.version;
21895
+ } catch {
21896
+ }
21897
+ }
21898
+ return "0.0.0";
21899
+ })();
21782
21900
  var MPP_BASE = process.env.ROZO_CHECKOUT_MPP_BASE || "https://apiserver.mpprouter.dev/v1/services/rozo-agent-api";
21901
+ var CLIENT_LABEL = `rozo-checkout-cli/${PKG_VERSION}`;
21902
+ var ATTRIBUTION_CLIENT = `rozo-checkout-skill/${PKG_VERSION}`;
21783
21903
  var INTENTS_BASE = process.env.ROZO_CHECKOUT_INTENTS_BASE || "https://intentapiv4.rozo.ai/functions/v1/payment-api";
21784
21904
  async function invoiceStatus({ linkId, rozoPaymentId }) {
21785
21905
  const qs = new URLSearchParams();
@@ -22107,7 +22227,7 @@ function checkExpiry({
22107
22227
  // scripts/src/lib/blacklist.mjs
22108
22228
  import fs4 from "node:fs";
22109
22229
  import path4 from "node:path";
22110
- import crypto4 from "node:crypto";
22230
+ import crypto5 from "node:crypto";
22111
22231
  import { fileURLToPath } from "node:url";
22112
22232
  var BlacklistError = class extends Error {
22113
22233
  constructor(code, message) {
@@ -22142,7 +22262,7 @@ function parseBlacklist(doc) {
22142
22262
  }
22143
22263
  addresses.push(e.address);
22144
22264
  }
22145
- const digest = crypto4.createHash("sha256").update(JSON.stringify(addresses), "utf8").digest("hex");
22265
+ const digest = crypto5.createHash("sha256").update(JSON.stringify(addresses), "utf8").digest("hex");
22146
22266
  if (typeof provenance.addressesSha256 !== "string" || !provenance.addressesSha256) {
22147
22267
  throw new BlacklistError("BLACKLIST_UNAVAILABLE", "Blacklist provenance digest is missing.");
22148
22268
  }
@@ -22231,7 +22351,7 @@ function assertNotBlacklisted(targets, blacklist) {
22231
22351
  import fs5 from "node:fs";
22232
22352
  import path5 from "node:path";
22233
22353
  import os3 from "node:os";
22234
- import crypto5 from "node:crypto";
22354
+ import crypto6 from "node:crypto";
22235
22355
  var LOCK_STALE_MS = 6e4;
22236
22356
  var LOCK_WAIT_MS = 1e4;
22237
22357
  var LOCK_POLL_MS = 25;
@@ -22261,7 +22381,7 @@ function withLock(fn) {
22261
22381
  try {
22262
22382
  const age = Date.now() - fs5.statSync(file).mtimeMs;
22263
22383
  if (age > LOCK_STALE_MS) {
22264
- const stolen = `${file}.stale.${crypto5.randomBytes(4).toString("hex")}`;
22384
+ const stolen = `${file}.stale.${crypto6.randomBytes(4).toString("hex")}`;
22265
22385
  try {
22266
22386
  fs5.renameSync(file, stolen);
22267
22387
  fs5.unlinkSync(stolen);
@@ -22302,7 +22422,7 @@ function statePath(rozoPaymentId) {
22302
22422
  function writeAtomic(file, data) {
22303
22423
  const dir = path5.dirname(file);
22304
22424
  fs5.mkdirSync(dir, { recursive: true, mode: 448 });
22305
- const tmp = path5.join(dir, `.${path5.basename(file)}.${crypto5.randomBytes(6).toString("hex")}.tmp`);
22425
+ const tmp = path5.join(dir, `.${path5.basename(file)}.${crypto6.randomBytes(6).toString("hex")}.tmp`);
22306
22426
  const fd = fs5.openSync(tmp, "wx", 384);
22307
22427
  try {
22308
22428
  fs5.writeFileSync(fd, JSON.stringify(data, null, 2) + "\n", "utf8");
@@ -22341,7 +22461,7 @@ function depositDigest(source) {
22341
22461
  amountUnit: source?.amountUnit ?? null,
22342
22462
  lnInvoice: source?.lnInvoice ?? null
22343
22463
  });
22344
- return crypto5.createHash("sha256").update(canonical, "utf8").digest("hex");
22464
+ return crypto6.createHash("sha256").update(canonical, "utf8").digest("hex");
22345
22465
  }
22346
22466
  function claimSend(rozoPaymentId, intent, { skipCaps = false } = {}) {
22347
22467
  return withLock(() => {