@usdctofiat/offramp 4.3.0 → 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,
@@ -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,16 +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
  }
421
+ var ZELLE_CREATE_LOOKUP_NAMES = ["zelle-chase", "zelle-bofa", "zelle-citi"];
461
422
  var GENERIC_ZELLE_METHOD_HASH = (0, import_sdk2.resolvePaymentMethodHash)("zelle") ?? null;
462
- function resolveCanonicalZelleHash() {
423
+ function resolveGenericZelleHash() {
463
424
  return GENERIC_ZELLE_METHOD_HASH;
464
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;
433
+ }
465
434
  function getPaymentMethodHash(platform) {
466
435
  const name = normalizePaymentMethodLookupName(platform);
467
436
  if (!name) return null;
468
437
  const catalogEntry = PAYMENT_CATALOG[name];
469
438
  if (catalogEntry?.paymentMethodHash) return catalogEntry.paymentMethodHash;
470
- 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);
471
441
  const sdkHash = (0, import_sdk2.resolvePaymentMethodHash)(name);
472
442
  return sdkHash ? sdkHash : null;
473
443
  }
@@ -476,16 +446,16 @@ function getPaymentMethodHashes(platform) {
476
446
  const hash = getPaymentMethodHash(platform);
477
447
  return hash ? [hash] : [];
478
448
  }
479
- const generic = resolveCanonicalZelleHash();
480
- return generic ? [generic] : [];
449
+ const hashes = getZelleCreateEntries().map((entry) => entry.hash);
450
+ const generic = resolveGenericZelleHash();
451
+ return generic ? [...hashes, generic] : hashes;
481
452
  }
482
453
  function getPaymentMethodCreateEntries(platform) {
483
454
  if (platform !== "zelle") {
484
455
  const hash = getPaymentMethodHash(platform);
485
456
  return hash ? [{ name: platform, hash }] : [];
486
457
  }
487
- const generic = resolveCanonicalZelleHash();
488
- return generic ? [{ name: "zelle", hash: generic }] : [];
458
+ return getZelleCreateEntries();
489
459
  }
490
460
  function buildDepositData(platform, identifier, telegramUsername = "") {
491
461
  const offchainId = platform === "chime" ? identifier.toLowerCase() : identifier;
@@ -1971,6 +1941,33 @@ var OFFRAMP_INTEGRATION_PLAYBOOKS = [
1971
1941
  ]
1972
1942
  }
1973
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
+ ];
1974
1971
  var OFFRAMP_DEVELOPER_RESOURCES = {
1975
1972
  packageName: "@usdctofiat/offramp",
1976
1973
  sdkVersion: SDK_VERSION,
@@ -2001,7 +1998,8 @@ var OFFRAMP_DEVELOPER_RESOURCES = {
2001
1998
  peerlyticsPricing: OFFRAMP_RESOURCE_LINKS.peerlyticsPricing,
2002
1999
  npm: OFFRAMP_RESOURCE_LINKS.npm
2003
2000
  },
2004
- playbooks: OFFRAMP_INTEGRATION_PLAYBOOKS
2001
+ playbooks: OFFRAMP_INTEGRATION_PLAYBOOKS,
2002
+ checklist: OFFRAMP_INTEGRATION_CHECKLIST
2005
2003
  };
2006
2004
  function getOfframpDeveloperResources(profile) {
2007
2005
  if (!profile) return OFFRAMP_DEVELOPER_RESOURCES;
@@ -2009,6 +2007,22 @@ function getOfframpDeveloperResources(profile) {
2009
2007
  if (!playbook) return OFFRAMP_DEVELOPER_RESOURCES;
2010
2008
  return playbook;
2011
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
+ }
2012
2026
  // Annotate the CommonJS export names for ESM import in node:
2013
2027
  0 && (module.exports = {
2014
2028
  CURRENCIES,
@@ -2017,6 +2031,7 @@ function getOfframpDeveloperResources(profile) {
2017
2031
  MakersCreateError,
2018
2032
  OFFRAMP_DEVELOPER_RESOURCES,
2019
2033
  OFFRAMP_ERROR_CODES,
2034
+ OFFRAMP_INTEGRATION_CHECKLIST,
2020
2035
  OFFRAMP_INTEGRATION_PLAYBOOKS,
2021
2036
  OFFRAMP_RESOURCE_LINKS,
2022
2037
  Offramp,
@@ -2034,6 +2049,7 @@ function getOfframpDeveloperResources(profile) {
2034
2049
  disableOtc,
2035
2050
  emitEvent,
2036
2051
  enableOtc,
2052
+ getOfframpAgentPrompt,
2037
2053
  getOfframpDeveloperResources,
2038
2054
  getOtcLink,
2039
2055
  getPeerExtensionRegistrationAuthParams,
@@ -2043,7 +2059,6 @@ function getOfframpDeveloperResources(profile) {
2043
2059
  isPeerExtensionAvailable,
2044
2060
  isPeerExtensionMetadataBridgeAvailable,
2045
2061
  isPeerExtensionRegistrationError,
2046
- isValidIBAN,
2047
2062
  normalizePaypalMeUsername,
2048
2063
  offramp,
2049
2064
  openPeerExtensionInstallPage,