@usdctofiat/offramp 4.2.1 → 4.3.1

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/dist/index.cjs CHANGED
@@ -36,6 +36,7 @@ __export(index_exports, {
36
36
  MakersCreateError: () => MakersCreateError,
37
37
  OFFRAMP_DEVELOPER_RESOURCES: () => OFFRAMP_DEVELOPER_RESOURCES,
38
38
  OFFRAMP_ERROR_CODES: () => OFFRAMP_ERROR_CODES,
39
+ OFFRAMP_INTEGRATION_CHECKLIST: () => OFFRAMP_INTEGRATION_CHECKLIST,
39
40
  OFFRAMP_INTEGRATION_PLAYBOOKS: () => OFFRAMP_INTEGRATION_PLAYBOOKS,
40
41
  OFFRAMP_RESOURCE_LINKS: () => OFFRAMP_RESOURCE_LINKS,
41
42
  Offramp: () => Offramp,
@@ -53,6 +54,7 @@ __export(index_exports, {
53
54
  disableOtc: () => disableOtc,
54
55
  emitEvent: () => emitEvent,
55
56
  enableOtc: () => enableOtc,
57
+ getOfframpAgentPrompt: () => getOfframpAgentPrompt,
56
58
  getOfframpDeveloperResources: () => getOfframpDeveloperResources,
57
59
  getOtcLink: () => getOtcLink,
58
60
  getPeerExtensionRegistrationAuthParams: () => getPeerExtensionRegistrationAuthParams,
@@ -62,7 +64,6 @@ __export(index_exports, {
62
64
  isPeerExtensionAvailable: () => isPeerExtensionAvailable,
63
65
  isPeerExtensionMetadataBridgeAvailable: () => isPeerExtensionMetadataBridgeAvailable,
64
66
  isPeerExtensionRegistrationError: () => isPeerExtensionRegistrationError,
65
- isValidIBAN: () => isValidIBAN,
66
67
  normalizePaypalMeUsername: () => normalizePaypalMeUsername,
67
68
  offramp: () => offramp,
68
69
  openPeerExtensionInstallPage: () => openPeerExtensionInstallPage,
@@ -80,7 +81,7 @@ var import_sdk5 = require("@zkp2p/sdk");
80
81
 
81
82
  // src/config.ts
82
83
  var import_sdk = require("@zkp2p/sdk");
83
- var SDK_VERSION = "4.2.1";
84
+ var SDK_VERSION = "4.3.0";
84
85
  var BASE_CHAIN_ID = 8453;
85
86
  var RUNTIME_ENV = "production";
86
87
  var API_BASE_URL = "https://api.zkp2p.xyz";
@@ -216,9 +217,7 @@ var FALLBACK_CURRENCIES = {
216
217
  mercadopago: ["ARS"],
217
218
  zelle: ["USD"],
218
219
  paypal: ["USD", "EUR", "GBP", "SGD", "NZD", "AUD", "CAD"],
219
- monzo: ["GBP"],
220
- n26: ["EUR"],
221
- luxon: ["USD", "EUR", "GBP"]
220
+ monzo: ["GBP"]
222
221
  };
223
222
  function gatherCatalogHashes(platform) {
224
223
  if (platform === "zelle") {
@@ -261,21 +260,6 @@ function normalizePaypalMeUsername(value) {
261
260
  }
262
261
  return trimmed.replace(/^@+/, "").toLowerCase();
263
262
  }
264
- function isValidIBAN(iban) {
265
- const upper = iban.toUpperCase();
266
- if (!/^[A-Z]{2}[0-9]{2}[A-Z0-9]{11,30}$/.test(upper)) return false;
267
- const rearranged = upper.slice(4) + upper.slice(0, 4);
268
- const numeric = rearranged.split("").map((ch) => {
269
- const code = ch.charCodeAt(0);
270
- return code >= 65 && code <= 90 ? (code - 55).toString() : ch;
271
- }).join("");
272
- let remainder = numeric;
273
- while (remainder.length > 2) {
274
- const block = remainder.slice(0, 9);
275
- remainder = (parseInt(block, 10) % 97).toString() + remainder.slice(block.length);
276
- }
277
- return parseInt(remainder, 10) % 97 === 1;
278
- }
279
263
  var BLUEPRINTS = {
280
264
  venmo: {
281
265
  id: "venmo",
@@ -375,27 +359,6 @@ var BLUEPRINTS = {
375
359
  placeholder: "monzo.me username",
376
360
  helperText: "Your Monzo.me username",
377
361
  validation: import_zod.z.string().min(1).regex(/^[a-zA-Z0-9_-]+$/)
378
- },
379
- n26: {
380
- id: "n26",
381
- name: "N26",
382
- identifierLabel: "IBAN",
383
- placeholder: "IBAN (e.g. DE89...)",
384
- helperText: "Your IBAN (spaces will be removed)",
385
- // transform runs before validation, so the schema sees a spaceless,
386
- // uppercased IBAN. The MOD-97 refine mirrors curator's N26Processor so a
387
- // typo'd-but-well-formed IBAN fails here, not after USDC approval + gas.
388
- validation: import_zod.z.string().regex(/^[A-Z]{2}[0-9]{2}[A-Z0-9]{11,30}$/, "Enter a valid IBAN").refine(isValidIBAN, "That IBAN looks wrong \u2014 its checksum doesn't match"),
389
- transform: (v) => v.replace(/\s/g, "").toUpperCase()
390
- },
391
- luxon: {
392
- id: "luxon",
393
- name: "Luxon",
394
- identifierLabel: "Email",
395
- placeholder: "your-luxon-email@example.com",
396
- helperText: "Email address registered with Luxon",
397
- validation: import_zod.z.string().email(),
398
- transform: (v) => v.trim()
399
362
  }
400
363
  };
401
364
  function buildPlatformEntry(bp) {
@@ -433,13 +396,10 @@ var PLATFORMS = {
433
396
  MERCADO_PAGO: buildPlatformEntry(BLUEPRINTS.mercadopago),
434
397
  ZELLE: buildPlatformEntry(BLUEPRINTS.zelle),
435
398
  PAYPAL: buildPlatformEntry(BLUEPRINTS.paypal),
436
- MONZO: buildPlatformEntry(BLUEPRINTS.monzo),
437
- N26: buildPlatformEntry(BLUEPRINTS.n26),
438
- LUXON: buildPlatformEntry(BLUEPRINTS.luxon)
399
+ MONZO: buildPlatformEntry(BLUEPRINTS.monzo)
439
400
  };
440
401
  var PLATFORM_LIMITS = {
441
402
  venmo: { platformCapUsd: 5e3 },
442
- n26: { platformCapUsd: 1e4 },
443
403
  paypal: { minTier: "PLUS" }
444
404
  };
445
405
  function getPlatformLimits(platform) {
@@ -458,20 +418,26 @@ function normalizePaymentMethodLookupName(platform) {
458
418
  const ids = Object.values(PLATFORMS).map((p) => p.id);
459
419
  return ids.includes(normalized) ? normalized : null;
460
420
  }
461
- function resolveCanonicalZelleHash() {
462
- const direct = PAYMENT_CATALOG.zelle?.paymentMethodHash;
463
- if (direct) return direct;
464
- const variant = Object.entries(PAYMENT_CATALOG).find(
465
- ([name, entry]) => name.startsWith("zelle") && Boolean(entry.paymentMethodHash)
466
- );
467
- return variant?.[1]?.paymentMethodHash ?? null;
421
+ var ZELLE_CREATE_LOOKUP_NAMES = ["zelle-chase", "zelle-bofa", "zelle-citi"];
422
+ var GENERIC_ZELLE_METHOD_HASH = (0, import_sdk2.resolvePaymentMethodHash)("zelle") ?? null;
423
+ function resolveGenericZelleHash() {
424
+ return GENERIC_ZELLE_METHOD_HASH;
425
+ }
426
+ function getZelleCreateEntries() {
427
+ const entries = [];
428
+ for (const name of ZELLE_CREATE_LOOKUP_NAMES) {
429
+ const hash = getPaymentMethodHash(name);
430
+ if (hash) entries.push({ name, hash });
431
+ }
432
+ return entries;
468
433
  }
469
434
  function getPaymentMethodHash(platform) {
470
435
  const name = normalizePaymentMethodLookupName(platform);
471
436
  if (!name) return null;
472
437
  const catalogEntry = PAYMENT_CATALOG[name];
473
438
  if (catalogEntry?.paymentMethodHash) return catalogEntry.paymentMethodHash;
474
- if (name === "zelle" || name.startsWith("zelle-")) return resolveCanonicalZelleHash();
439
+ if (name === "zelle") return resolveGenericZelleHash();
440
+ if (name.startsWith("zelle-")) return (0, import_sdk2.resolvePaymentMethodHash)(name);
475
441
  const sdkHash = (0, import_sdk2.resolvePaymentMethodHash)(name);
476
442
  return sdkHash ? sdkHash : null;
477
443
  }
@@ -480,24 +446,16 @@ function getPaymentMethodHashes(platform) {
480
446
  const hash = getPaymentMethodHash(platform);
481
447
  return hash ? [hash] : [];
482
448
  }
483
- const hashes = /* @__PURE__ */ new Set();
484
- const generic = (0, import_sdk2.resolvePaymentMethodHash)("zelle");
485
- if (generic) hashes.add(generic);
486
- const canonical = resolveCanonicalZelleHash();
487
- if (canonical) hashes.add(canonical);
488
- for (const [name, entry] of Object.entries(PAYMENT_CATALOG)) {
489
- if (name.startsWith("zelle") && entry.paymentMethodHash) {
490
- hashes.add(entry.paymentMethodHash);
491
- }
492
- }
493
- return Array.from(hashes);
449
+ const hashes = getZelleCreateEntries().map((entry) => entry.hash);
450
+ const generic = resolveGenericZelleHash();
451
+ return generic ? [...hashes, generic] : hashes;
494
452
  }
495
453
  function getPaymentMethodCreateEntries(platform) {
496
454
  if (platform !== "zelle") {
497
455
  const hash = getPaymentMethodHash(platform);
498
456
  return hash ? [{ name: platform, hash }] : [];
499
457
  }
500
- return Object.entries(PAYMENT_CATALOG).filter(([name, entry]) => name.startsWith("zelle") && Boolean(entry.paymentMethodHash)).sort(([a], [b]) => a.localeCompare(b)).map(([name, entry]) => ({ name, hash: entry.paymentMethodHash }));
458
+ return getZelleCreateEntries();
501
459
  }
502
460
  function buildDepositData(platform, identifier, telegramUsername = "") {
503
461
  const offchainId = platform === "chime" ? identifier.toLowerCase() : identifier;
@@ -1952,15 +1910,15 @@ var OFFRAMP_INTEGRATION_PLAYBOOKS = [
1952
1910
  },
1953
1911
  {
1954
1912
  profile: "peerlytics",
1955
- title: "Peerlytics expansion",
1956
- summary: "Add market data, explorer reads, analytics, and credit-backed API access.",
1913
+ title: "Peerlytics API",
1914
+ summary: "Add market data, explorer reads, analytics, and API-credit-backed access.",
1957
1915
  steps: [
1958
1916
  {
1959
1917
  title: "Start with deposits",
1960
1918
  detail: "@usdctofiat/offramp creates delegated seller inventory without an API key."
1961
1919
  },
1962
1920
  {
1963
- title: "Add the paid API",
1921
+ title: "Add the Peerlytics API",
1964
1922
  detail: "Use @peerlytics/sdk when the product needs orderbook, analytics, and webhooks."
1965
1923
  },
1966
1924
  {
@@ -1971,7 +1929,7 @@ var OFFRAMP_INTEGRATION_PLAYBOOKS = [
1971
1929
  resources: [
1972
1930
  ...sharedResources,
1973
1931
  {
1974
- label: "Peerlytics expansion guide",
1932
+ label: "Peerlytics API guide",
1975
1933
  href: OFFRAMP_RESOURCE_LINKS.peerlyticsGuide,
1976
1934
  description: "When to add the paid protocol API alongside the free deposit SDK."
1977
1935
  },
@@ -1983,6 +1941,33 @@ var OFFRAMP_INTEGRATION_PLAYBOOKS = [
1983
1941
  ]
1984
1942
  }
1985
1943
  ];
1944
+ var OFFRAMP_INTEGRATION_CHECKLIST = [
1945
+ {
1946
+ title: "Base mainnet wallet client",
1947
+ detail: "Use a viem WalletClient on chain 8453. The SDK has no public sandbox mode.",
1948
+ required: true
1949
+ },
1950
+ {
1951
+ title: "Delegate-vault pricing",
1952
+ detail: "Every SDK-created deposit must delegate pricing to the managed Delegate vault.",
1953
+ required: true
1954
+ },
1955
+ {
1956
+ title: "PayPal/Wise recovery path",
1957
+ detail: "Catch EXTENSION_REGISTRATION_REQUIRED and drive Peer extension seller registration.",
1958
+ required: true
1959
+ },
1960
+ {
1961
+ title: "Server-side duplicate prevention",
1962
+ detail: "Bots and workers must call deposits(address) and use their own order database; idempotencyKey is browser-session scoped and the standalone offramp() helper ignores it.",
1963
+ required: true
1964
+ },
1965
+ {
1966
+ title: "Raw-body webhook verification",
1967
+ detail: "Verify timestamp.rawBody with HMAC-SHA256 before parsing JSON.",
1968
+ required: true
1969
+ }
1970
+ ];
1986
1971
  var OFFRAMP_DEVELOPER_RESOURCES = {
1987
1972
  packageName: "@usdctofiat/offramp",
1988
1973
  sdkVersion: SDK_VERSION,
@@ -2013,7 +1998,8 @@ var OFFRAMP_DEVELOPER_RESOURCES = {
2013
1998
  peerlyticsPricing: OFFRAMP_RESOURCE_LINKS.peerlyticsPricing,
2014
1999
  npm: OFFRAMP_RESOURCE_LINKS.npm
2015
2000
  },
2016
- playbooks: OFFRAMP_INTEGRATION_PLAYBOOKS
2001
+ playbooks: OFFRAMP_INTEGRATION_PLAYBOOKS,
2002
+ checklist: OFFRAMP_INTEGRATION_CHECKLIST
2017
2003
  };
2018
2004
  function getOfframpDeveloperResources(profile) {
2019
2005
  if (!profile) return OFFRAMP_DEVELOPER_RESOURCES;
@@ -2021,6 +2007,22 @@ function getOfframpDeveloperResources(profile) {
2021
2007
  if (!playbook) return OFFRAMP_DEVELOPER_RESOURCES;
2022
2008
  return playbook;
2023
2009
  }
2010
+ function getOfframpAgentPrompt(profile = "app") {
2011
+ const playbook = getOfframpDeveloperResources(profile);
2012
+ const resource = "profile" in playbook ? playbook : OFFRAMP_INTEGRATION_PLAYBOOKS.find((entry) => entry.profile === "app");
2013
+ const steps = resource?.steps.map((step, index) => `${index + 1}. ${step.title}: ${step.detail}`);
2014
+ return [
2015
+ "Build a USDC-to-fiat integration with @usdctofiat/offramp.",
2016
+ `Profile: ${profile}.`,
2017
+ "Before coding, read https://usdctofiat.xyz/skills/usdctofiat.md and https://usdctofiat.xyz/llms.txt.",
2018
+ "Use Base mainnet chainId 8453 and a viem WalletClient; do not invent a sandbox.",
2019
+ "Do not add manual rate controls; SDK-created deposits must delegate to the Delegate vault.",
2020
+ "For PayPal and Wise, recover EXTENSION_REGISTRATION_REQUIRED through the Peer extension registration flow.",
2021
+ "For bots/workers, deduplicate with deposits(address) plus your own order database; do not rely on idempotencyKey.",
2022
+ "For webhooks, verify the raw request body before parsing JSON.",
2023
+ ...steps ?? []
2024
+ ].join("\n");
2025
+ }
2024
2026
  // Annotate the CommonJS export names for ESM import in node:
2025
2027
  0 && (module.exports = {
2026
2028
  CURRENCIES,
@@ -2029,6 +2031,7 @@ function getOfframpDeveloperResources(profile) {
2029
2031
  MakersCreateError,
2030
2032
  OFFRAMP_DEVELOPER_RESOURCES,
2031
2033
  OFFRAMP_ERROR_CODES,
2034
+ OFFRAMP_INTEGRATION_CHECKLIST,
2032
2035
  OFFRAMP_INTEGRATION_PLAYBOOKS,
2033
2036
  OFFRAMP_RESOURCE_LINKS,
2034
2037
  Offramp,
@@ -2046,6 +2049,7 @@ function getOfframpDeveloperResources(profile) {
2046
2049
  disableOtc,
2047
2050
  emitEvent,
2048
2051
  enableOtc,
2052
+ getOfframpAgentPrompt,
2049
2053
  getOfframpDeveloperResources,
2050
2054
  getOtcLink,
2051
2055
  getPeerExtensionRegistrationAuthParams,
@@ -2055,7 +2059,6 @@ function getOfframpDeveloperResources(profile) {
2055
2059
  isPeerExtensionAvailable,
2056
2060
  isPeerExtensionMetadataBridgeAvailable,
2057
2061
  isPeerExtensionRegistrationError,
2058
- isValidIBAN,
2059
2062
  normalizePaypalMeUsername,
2060
2063
  offramp,
2061
2064
  openPeerExtensionInstallPage,