@usdctofiat/offramp 4.3.0 → 4.4.0

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/CHANGELOG.md CHANGED
@@ -5,18 +5,38 @@ All notable changes to `@usdctofiat/offramp` will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
+ ## [4.4.0] - 2026-06-24
9
+
10
+ ### Added
11
+
12
+ - Add Curator-backed taker tier helpers: `getTakerTier()`,
13
+ `findTakerPlatformLimit()`, and `resolveTakerPlatformLimit()`. Integrators can
14
+ now fetch the live `/v2/taker/tier` platform caps/cooldowns instead of relying
15
+ only on static advisory limits.
16
+ - Extend Peer extension seller-credential registration to every SAR-capable
17
+ seller platform supported by the current extension/service path: PayPal, Wise,
18
+ Venmo, and Cash App.
19
+
20
+ ## [4.3.1] - 2026-06-24
21
+
22
+ ### Fixed
23
+
24
+ - Align `@zkp2p/sdk` to `0.5.7`, restoring keyed curator quote requests for
25
+ internal quote modes such as `EXCLUSIVE_SAR` and private orderbooks. This
26
+ also picks up `@zkp2p/zkp2p-attestation` `1.6.3`, which binds browser and
27
+ extension default `fetch` calls to avoid receiver-sensitive fetch invocation
28
+ failures.
29
+
8
30
  ## [4.3.0] - 2026-06-23
9
31
 
10
32
  ### Changed
11
33
 
12
- - **Zelle generic hard cut.** New Zelle deposits now register the single generic
13
- `zelle` payment method (`keccak256("zelle")`) instead of the legacy
14
- `zelle-chase` / `zelle-citi` / `zelle-bofa` bank variants mirroring the
15
- zkp2p-clients generic-Zelle cutover. Bank selection is now a buyer-side
16
- capture detail, so one generic deposit accepts any supported bank.
17
- `getPaymentMethodHashes("zelle")` and `getPaymentMethodCreateEntries("zelle")`
18
- return the single generic method; legacy variant hashes remain recognized for
19
- reads/drain only.
34
+ - **Zelle curator-prod compatibility.** New Zelle deposits register the
35
+ bank-specific `zelle-chase` / `zelle-bofa` / `zelle-citi` methods again after
36
+ curator prod reverted generic-Zelle maker creation on 2026-06-23.
37
+ `getPaymentMethodHashes("zelle")` still recognizes the generic hash for
38
+ reads/taker compatibility, but `getPaymentMethodCreateEntries("zelle")`
39
+ returns the three bank-specific creation entries.
20
40
  - Align `@zkp2p/sdk` to `0.5.4` and `@zkp2p/contracts-v2` to `0.2.4` (attestation
21
41
  host-pin/retry fix, below-min buyer-attestation rejection, generic-Zelle
22
42
  fulfillment route).
package/README.md CHANGED
@@ -26,11 +26,20 @@ import { OFFRAMP_DEVELOPER_RESOURCES, getOfframpDeveloperResources } from "@usdc
26
26
  OFFRAMP_DEVELOPER_RESOURCES.delegation.required; // true
27
27
  OFFRAMP_DEVELOPER_RESOURCES.delegation.feeRateBps; // 10
28
28
  OFFRAMP_DEVELOPER_RESOURCES.links.agentSkill; // https://usdctofiat.xyz/skills/usdctofiat.md
29
+ OFFRAMP_DEVELOPER_RESOURCES.checklist.map((item) => item.title); // integration doctor
29
30
 
30
31
  const botPlaybook = getOfframpDeveloperResources("bot");
31
32
  // profile-specific steps + canonical docs/starters/webhook resources
32
33
  ```
33
34
 
35
+ For agent-built integrations, copy the same prompt the developer console uses:
36
+
37
+ ```typescript
38
+ import { getOfframpAgentPrompt } from "@usdctofiat/offramp";
39
+
40
+ const prompt = getOfframpAgentPrompt("bot");
41
+ ```
42
+
34
43
  ## Install
35
44
 
36
45
  ```bash
@@ -195,13 +204,14 @@ try {
195
204
  }
196
205
  ```
197
206
 
198
- ## Peer Extension Registration (PayPal, Wise)
207
+ ## Peer Extension Registration (PayPal, Wise, Venmo, Cash App)
199
208
 
200
- PayPal and Wise makers must register their handle inside the Peer (PeerAuth)
201
- browser extension before the first deposit. The SDK throws `OfframpError`
202
- with code `EXTENSION_REGISTRATION_REQUIRED` when curator rejects a maker for
203
- this reason. Drive install, connection approval, headless seller-credential capture,
204
- seller-credential upload, and retry via the React hook:
209
+ PayPal, Wise, Venmo, and Cash App makers may need to register their handle
210
+ inside the Peer (PeerAuth) browser extension before the first deposit. The SDK
211
+ throws `OfframpError` with code `EXTENSION_REGISTRATION_REQUIRED` when curator
212
+ rejects a maker for this reason. Drive install, connection approval, headless
213
+ seller-credential capture, seller-credential upload, and retry via the React
214
+ hook:
205
215
 
206
216
  ```tsx
207
217
  import { PLATFORMS, CURRENCIES, OFFRAMP_ERROR_CODES } from "@usdctofiat/offramp";
@@ -306,13 +316,30 @@ if (state === "needs_install" || !isPeerExtensionMetadataBridgeAvailable()) {
306
316
  The captured metadata passed to `completePeerExtensionRegistration(...)` must
307
317
  include `sarCredentialCapture.credentialBundle`. Completion validates the
308
318
  captured `offchainId` against your identifier and validates the payee hash in
309
- the credential bundle. PayPal first registers the normalized handle through
310
- `/v2/makers/create` to resolve `hashedOnchainId`; Wise uses
311
- `credentialBundle.payeeIdHash` directly. Both paths upload the seller credential
312
- bundle to `/v2/makers/<processor>/<payeeHash>/seller-credential` and return
319
+ the credential bundle. Wise uses `credentialBundle.payeeIdHash` directly;
320
+ PayPal, Venmo, and Cash App register the normalized handle through
321
+ `/v2/makers/create` before upload. All paths upload the seller credential bundle
322
+ to `/v2/makers/<processor>/<payeeHash>/seller-credential` and return
313
323
  `sellerCredentialResponse` plus `sellerCredentialStatus`. After that succeeds,
314
324
  call `offramp()` again with the same handle.
315
325
 
326
+ ## Dynamic Taker Tiers
327
+
328
+ Curator computes taker caps and platform locks dynamically. Use
329
+ `getTakerTier()` plus `findTakerPlatformLimit()` when a take-side UI needs the
330
+ current limit for a wallet/payment rail:
331
+
332
+ ```typescript
333
+ import { findTakerPlatformLimit, getTakerTier } from "@usdctofiat/offramp";
334
+
335
+ const tier = await getTakerTier({ owner: takerAddress });
336
+ const paypalLimit = findTakerPlatformLimit(tier, { platform: "paypal" });
337
+
338
+ if (paypalLimit?.isLocked) {
339
+ console.log(`PayPal unlocks at ${paypalLimit.minTierRequired} tier`);
340
+ }
341
+ ```
342
+
316
343
  ## How It Works
317
344
 
318
345
  Every deposit is automatically delegated to the Delegate vault for oracle-based rate management (which charges a 0.10% manager fee — see [Fees](#fees)), auto-closes when filled, and is attributed to Galleon Labs via ERC-8021.
@@ -1,6 +1,6 @@
1
1
  // src/config.ts
2
2
  import { getContracts, getGatingServiceAddress } from "@zkp2p/sdk";
3
- var SDK_VERSION = "4.3.0";
3
+ var SDK_VERSION = "4.4.0";
4
4
  var BASE_CHAIN_ID = 8453;
5
5
  var RUNTIME_ENV = "production";
6
6
  var API_BASE_URL = "https://api.zkp2p.xyz";
@@ -140,9 +140,7 @@ var FALLBACK_CURRENCIES = {
140
140
  mercadopago: ["ARS"],
141
141
  zelle: ["USD"],
142
142
  paypal: ["USD", "EUR", "GBP", "SGD", "NZD", "AUD", "CAD"],
143
- monzo: ["GBP"],
144
- n26: ["EUR"],
145
- luxon: ["USD", "EUR", "GBP"]
143
+ monzo: ["GBP"]
146
144
  };
147
145
  function gatherCatalogHashes(platform) {
148
146
  if (platform === "zelle") {
@@ -185,21 +183,6 @@ function normalizePaypalMeUsername(value) {
185
183
  }
186
184
  return trimmed.replace(/^@+/, "").toLowerCase();
187
185
  }
188
- function isValidIBAN(iban) {
189
- const upper = iban.toUpperCase();
190
- if (!/^[A-Z]{2}[0-9]{2}[A-Z0-9]{11,30}$/.test(upper)) return false;
191
- const rearranged = upper.slice(4) + upper.slice(0, 4);
192
- const numeric = rearranged.split("").map((ch) => {
193
- const code = ch.charCodeAt(0);
194
- return code >= 65 && code <= 90 ? (code - 55).toString() : ch;
195
- }).join("");
196
- let remainder = numeric;
197
- while (remainder.length > 2) {
198
- const block = remainder.slice(0, 9);
199
- remainder = (parseInt(block, 10) % 97).toString() + remainder.slice(block.length);
200
- }
201
- return parseInt(remainder, 10) % 97 === 1;
202
- }
203
186
  var BLUEPRINTS = {
204
187
  venmo: {
205
188
  id: "venmo",
@@ -208,7 +191,12 @@ var BLUEPRINTS = {
208
191
  placeholder: "venmo username (no @)",
209
192
  helperText: "Username without @ (publicly discoverable)",
210
193
  validation: z.string().min(1).regex(/^[a-zA-Z0-9_-]+$/),
211
- transform: (v) => v.replace(/^@+/, "")
194
+ transform: (v) => v.replace(/^@+/, ""),
195
+ extensionRegistration: {
196
+ providerId: "venmo",
197
+ requiredPrompt: "This Venmo username is not registered yet. Register it with PeerAuth, then retry with the same Venmo username.",
198
+ ctaLabel: "Register Venmo Username"
199
+ }
212
200
  },
213
201
  cashapp: {
214
202
  id: "cashapp",
@@ -217,7 +205,12 @@ var BLUEPRINTS = {
217
205
  placeholder: "cashtag (no $)",
218
206
  helperText: "Cashtag without $ (publicly discoverable)",
219
207
  validation: z.string().min(1).regex(/^[a-zA-Z0-9]+$/),
220
- transform: (v) => v.replace(/^\$+/, "")
208
+ transform: (v) => v.replace(/^\$+/, ""),
209
+ extensionRegistration: {
210
+ providerId: "cashapp",
211
+ requiredPrompt: "This Cash App cashtag is not registered yet. Register it with PeerAuth, then retry with the same cashtag.",
212
+ ctaLabel: "Register Cash App Cashtag"
213
+ }
221
214
  },
222
215
  chime: {
223
216
  id: "chime",
@@ -299,27 +292,6 @@ var BLUEPRINTS = {
299
292
  placeholder: "monzo.me username",
300
293
  helperText: "Your Monzo.me username",
301
294
  validation: z.string().min(1).regex(/^[a-zA-Z0-9_-]+$/)
302
- },
303
- n26: {
304
- id: "n26",
305
- name: "N26",
306
- identifierLabel: "IBAN",
307
- placeholder: "IBAN (e.g. DE89...)",
308
- helperText: "Your IBAN (spaces will be removed)",
309
- // transform runs before validation, so the schema sees a spaceless,
310
- // uppercased IBAN. The MOD-97 refine mirrors curator's N26Processor so a
311
- // typo'd-but-well-formed IBAN fails here, not after USDC approval + gas.
312
- validation: 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"),
313
- transform: (v) => v.replace(/\s/g, "").toUpperCase()
314
- },
315
- luxon: {
316
- id: "luxon",
317
- name: "Luxon",
318
- identifierLabel: "Email",
319
- placeholder: "your-luxon-email@example.com",
320
- helperText: "Email address registered with Luxon",
321
- validation: z.string().email(),
322
- transform: (v) => v.trim()
323
295
  }
324
296
  };
325
297
  function buildPlatformEntry(bp) {
@@ -357,13 +329,10 @@ var PLATFORMS = {
357
329
  MERCADO_PAGO: buildPlatformEntry(BLUEPRINTS.mercadopago),
358
330
  ZELLE: buildPlatformEntry(BLUEPRINTS.zelle),
359
331
  PAYPAL: buildPlatformEntry(BLUEPRINTS.paypal),
360
- MONZO: buildPlatformEntry(BLUEPRINTS.monzo),
361
- N26: buildPlatformEntry(BLUEPRINTS.n26),
362
- LUXON: buildPlatformEntry(BLUEPRINTS.luxon)
332
+ MONZO: buildPlatformEntry(BLUEPRINTS.monzo)
363
333
  };
364
334
  var PLATFORM_LIMITS = {
365
335
  venmo: { platformCapUsd: 5e3 },
366
- n26: { platformCapUsd: 1e4 },
367
336
  paypal: { minTier: "PLUS" }
368
337
  };
369
338
  function getPlatformLimits(platform) {
@@ -382,16 +351,26 @@ function normalizePaymentMethodLookupName(platform) {
382
351
  const ids = Object.values(PLATFORMS).map((p) => p.id);
383
352
  return ids.includes(normalized) ? normalized : null;
384
353
  }
354
+ var ZELLE_CREATE_LOOKUP_NAMES = ["zelle-chase", "zelle-bofa", "zelle-citi"];
385
355
  var GENERIC_ZELLE_METHOD_HASH = resolvePaymentMethodHash("zelle") ?? null;
386
- function resolveCanonicalZelleHash() {
356
+ function resolveGenericZelleHash() {
387
357
  return GENERIC_ZELLE_METHOD_HASH;
388
358
  }
359
+ function getZelleCreateEntries() {
360
+ const entries = [];
361
+ for (const name of ZELLE_CREATE_LOOKUP_NAMES) {
362
+ const hash = getPaymentMethodHash(name);
363
+ if (hash) entries.push({ name, hash });
364
+ }
365
+ return entries;
366
+ }
389
367
  function getPaymentMethodHash(platform) {
390
368
  const name = normalizePaymentMethodLookupName(platform);
391
369
  if (!name) return null;
392
370
  const catalogEntry = PAYMENT_CATALOG[name];
393
371
  if (catalogEntry?.paymentMethodHash) return catalogEntry.paymentMethodHash;
394
- if (name === "zelle" || name.startsWith("zelle-")) return resolveCanonicalZelleHash();
372
+ if (name === "zelle") return resolveGenericZelleHash();
373
+ if (name.startsWith("zelle-")) return resolvePaymentMethodHash(name);
395
374
  const sdkHash = resolvePaymentMethodHash(name);
396
375
  return sdkHash ? sdkHash : null;
397
376
  }
@@ -400,16 +379,16 @@ function getPaymentMethodHashes(platform) {
400
379
  const hash = getPaymentMethodHash(platform);
401
380
  return hash ? [hash] : [];
402
381
  }
403
- const generic = resolveCanonicalZelleHash();
404
- return generic ? [generic] : [];
382
+ const hashes = getZelleCreateEntries().map((entry) => entry.hash);
383
+ const generic = resolveGenericZelleHash();
384
+ return generic ? [...hashes, generic] : hashes;
405
385
  }
406
386
  function getPaymentMethodCreateEntries(platform) {
407
387
  if (platform !== "zelle") {
408
388
  const hash = getPaymentMethodHash(platform);
409
389
  return hash ? [{ name: platform, hash }] : [];
410
390
  }
411
- const generic = resolveCanonicalZelleHash();
412
- return generic ? [{ name: "zelle", hash: generic }] : [];
391
+ return getZelleCreateEntries();
413
392
  }
414
393
  function buildDepositData(platform, identifier, telegramUsername = "") {
415
394
  const offchainId = platform === "chime" ? identifier.toLowerCase() : identifier;
@@ -434,7 +413,7 @@ function getPeerExtensionRegistrationAuthParams(platform, options = {}) {
434
413
  }
435
414
  function resolveRegistrationProcessor(platform) {
436
415
  const info = getPeerExtensionRegistrationInfo(platform.id);
437
- if (info?.providerId === "paypal" || info?.providerId === "wise") {
416
+ if (info?.providerId === "paypal" || info?.providerId === "wise" || info?.providerId === "venmo" || info?.providerId === "cashapp") {
438
417
  return info.providerId;
439
418
  }
440
419
  throw new Error(`${platform.name} does not require Peer extension registration.`);
@@ -1652,15 +1631,17 @@ var peerExtensionSdk = createPeerExtensionSdk();
1652
1631
 
1653
1632
  export {
1654
1633
  SDK_VERSION,
1634
+ BASE_CHAIN_ID,
1635
+ API_BASE_URL,
1655
1636
  ESCROW_ADDRESS,
1656
1637
  DELEGATE_RATE_MANAGER_ID,
1657
1638
  RATE_MANAGER_REGISTRY_ADDRESS,
1658
1639
  DELEGATE_MANAGER_FEE_BPS,
1659
1640
  REFERRER,
1641
+ PAYEE_REGISTRATION_TIMEOUT_MS,
1660
1642
  MakersCreateError,
1661
1643
  OfframpError,
1662
1644
  normalizePaypalMeUsername,
1663
- isValidIBAN,
1664
1645
  PLATFORMS,
1665
1646
  PLATFORM_LIMITS,
1666
1647
  getPlatformLimits,
@@ -1692,4 +1673,4 @@ export {
1692
1673
  createPeerExtensionSdk,
1693
1674
  peerExtensionSdk
1694
1675
  };
1695
- //# sourceMappingURL=chunk-XKWPLBG3.js.map
1676
+ //# sourceMappingURL=chunk-CPTVCTLU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts","../src/errors.ts","../src/platforms.ts","../src/otc.ts","../src/sdk-client.ts","../src/queries.ts","../src/telemetry.ts","../src/deposit.ts","../src/currencies.ts","../src/offramp.ts","../src/extension.ts"],"sourcesContent":["import { getContracts, getGatingServiceAddress } from \"@zkp2p/sdk\";\n\n// Keep in sync with package.json — enforced by scripts/check-version.mjs on prepublish.\nexport const SDK_VERSION = \"4.4.0\";\nexport const BASE_CHAIN_ID = 8453;\nexport const RUNTIME_ENV = \"production\" as const;\nexport const API_BASE_URL = \"https://api.zkp2p.xyz\";\nexport const ATTESTATION_SERVICE_URL = \"https://attestation-service.zkp2p.xyz\";\nexport const BASE_RPC_URL = \"https://mainnet.base.org\";\n\n/**\n * Resolve the curator REST base URL for maker registration/validation calls.\n *\n * Returns `API_BASE_URL` unchanged when no override is supplied, so default\n * behavior is byte-for-byte identical. A non-empty override is trimmed and has\n * any trailing slash stripped (mirrors `@peerlytics/sdk`). Only the curator\n * REST surface is overridable — the indexer and Base RPC always target mainnet.\n */\nexport function resolveApiBaseUrl(override?: string): string {\n const trimmed = override?.trim();\n return (trimmed && trimmed.length > 0 ? trimmed : API_BASE_URL).replace(/\\/$/, \"\");\n}\n\nconst contracts = getContracts(BASE_CHAIN_ID, RUNTIME_ENV);\nconst addresses = contracts.addresses;\n\nconst addrs = addresses as unknown as Record<string, string>;\nexport const USDC_ADDRESS = (addrs.token ||\n \"0x833589fcd6edb6e08f4c7c32d4f71b54bda02913\") as `0x${string}`;\nexport const ESCROW_ADDRESS = (addrs.escrowV2 || addrs.escrow || \"\") as `0x${string}`;\nexport const GATING_SERVICE_ADDRESS = getGatingServiceAddress(\n BASE_CHAIN_ID,\n RUNTIME_ENV,\n) as `0x${string}`;\n\nexport const DELEGATE_RATE_MANAGER_ID =\n \"0x8666d6fb0f6797c56e95339fd7ca82fdd348b9db200e10a4c4aa0a0b879fc41c\" as `0x${string}`;\nexport const RATE_MANAGER_REGISTRY_ADDRESS =\n \"0xeed7db23e724ac4590d6db6f78fda6db203535f3\" as `0x${string}`;\nexport const DELEGATE_MANAGER_FEE_BPS = 10;\n\n// Mirrors `DEFAULT_INTENT_GUARDIAN_ADDRESS` from zkp2p-clients\n// (`packages/core/src/constants/index.ts`) so SDK-created deposits share the\n// canonical guardian instead of falling back to ZERO_ADDRESS at the contract.\nexport const DEFAULT_INTENT_GUARDIAN_ADDRESS =\n \"0xe29a5BD4D0CEbA6C125A0361E7D20ab4eA275C2f\" as `0x${string}`;\n\nexport const REFERRER = \"galleonlabs\";\n\nexport const MIN_DEPOSIT_USDC = 1;\nexport const MIN_ORDER_USDC = 1;\nexport const MAX_ORDER_USDC = 2500;\n\nexport const INDEXER_MAX_ATTEMPTS = 12;\nexport const INDEXER_INITIAL_DELAY_MS = 1000;\nexport const INDEXER_MAX_DELAY_MS = 10_000;\n\nexport const PAYEE_REGISTRATION_TIMEOUT_MS = 8000;\n","import type { OfframpErrorCode, OfframpStep } from \"./types\";\n\n/**\n * Error thrown when curator's `/v2/makers/create` returns a non-success\n * response. Preserves the HTTP status so callers can distinguish a\n * \"needs Peer-extension registration\" 400 from a transient server error.\n *\n * `offramp()` re-raises this as an {@link OfframpError} with code\n * `EXTENSION_REGISTRATION_REQUIRED` (for PayPal/Wise 400s) or\n * `REGISTRATION_FAILED` (for any other curator error); `MakersCreateError`\n * is attached as the `cause`.\n */\nexport class MakersCreateError extends Error {\n readonly status: number | null;\n readonly body: string;\n\n constructor(message: string, status: number | null, body: string) {\n super(message);\n this.name = \"MakersCreateError\";\n this.status = status;\n this.body = body;\n }\n}\n\nexport class OfframpError extends Error {\n readonly code: OfframpErrorCode;\n readonly step?: OfframpStep;\n readonly cause?: unknown;\n readonly txHash?: string;\n readonly depositId?: string;\n\n constructor(\n message: string,\n code: OfframpErrorCode,\n step?: OfframpStep,\n cause?: unknown,\n details?: { txHash?: string; depositId?: string },\n ) {\n super(message);\n this.name = \"OfframpError\";\n this.code = code;\n this.step = step;\n this.cause = cause;\n this.txHash = details?.txHash;\n this.depositId = details?.depositId;\n }\n}\n\nexport function isUserCancellation(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n const msg = error.message.toLowerCase();\n return (\n msg.includes(\"user rejected\") ||\n msg.includes(\"user denied\") ||\n msg.includes(\"user cancelled\") ||\n msg.includes(\"rejected the request\") ||\n msg.includes(\"action_rejected\")\n );\n}\n","import {\n apiUploadSellerCredentialBundle,\n type CuratorSellerCredentialUploadResponse,\n type UploadSellerCredentialBundleParams,\n currencyInfo,\n getCurrencyInfoFromHash,\n getPaymentMethodsCatalog,\n resolvePaymentMethodHash,\n} from \"@zkp2p/sdk\";\nimport { z } from \"zod\";\nimport { API_BASE_URL, BASE_CHAIN_ID, PAYEE_REGISTRATION_TIMEOUT_MS, RUNTIME_ENV } from \"./config\";\nimport { MakersCreateError } from \"./errors\";\nimport type {\n PeerAuthenticateParams,\n PeerMetadataMessage,\n PeerSarCredentialBundle,\n PeerSarCredentialCapture,\n} from \"./extension\";\n\n/* ── Internal types ───────────────────────────────────────────────── */\n\ntype CatalogEntry = { currencies?: string[]; paymentMethodHash?: `0x${string}` };\nconst PAYMENT_CATALOG = getPaymentMethodsCatalog(BASE_CHAIN_ID, RUNTIME_ENV) as Record<\n string,\n CatalogEntry\n>;\n\ntype CurrencyCode = keyof typeof currencyInfo;\n\nconst ZELLE_HASH_LOOKUP_NAMES = [\"zelle\", \"zelle-bofa\", \"zelle-chase\", \"zelle-citi\"] as const;\ntype PaymentMethodLookupName = PlatformId | (typeof ZELLE_HASH_LOOKUP_NAMES)[number];\n\ntype PlatformId =\n | \"venmo\"\n | \"cashapp\"\n | \"chime\"\n | \"revolut\"\n | \"wise\"\n | \"mercadopago\"\n | \"zelle\"\n | \"paypal\"\n | \"monzo\";\ntype SellerCredentialProcessor = \"paypal\" | \"wise\" | \"venmo\" | \"cashapp\";\n\n/* ── Platform entry type ──────────────────────────────────────────── */\n\n/**\n * Extension pre-registration requirement for a platform. When present,\n * curator's `/v2/makers/create` rejects the maker until the user has\n * registered their handle with PeerAuth.\n */\nexport interface PeerExtensionRegistrationInfo {\n /** Peer extension provider id. */\n readonly providerId: string;\n /** Message shown to the user when curator rejects the maker. */\n readonly requiredPrompt: string;\n /** Label for the registration CTA. */\n readonly ctaLabel: string;\n /** Optional subtext (e.g. PayPal Business disclaimer). */\n readonly ctaSubtext?: string;\n}\n\nexport interface PlatformEntry {\n readonly id: PlatformId;\n readonly name: string;\n readonly currencies: readonly string[];\n readonly identifier: {\n readonly label: string;\n readonly placeholder: string;\n readonly help: string;\n };\n /** Set for platforms that require Peer extension registration (PayPal, Wise). */\n readonly extensionRegistration?: PeerExtensionRegistrationInfo;\n validate(input: string): { valid: boolean; normalized: string; error?: string };\n}\n\n/* ── Currency resolution ──────────────────────────────────────────── */\n\nconst FALLBACK_CURRENCIES: Record<PlatformId, string[]> = {\n venmo: [\"USD\"],\n cashapp: [\"USD\"],\n chime: [\"USD\"],\n revolut: [\n \"USD\",\n \"EUR\",\n \"GBP\",\n \"SGD\",\n \"NZD\",\n \"AUD\",\n \"CAD\",\n \"HKD\",\n \"MXN\",\n \"SAR\",\n \"AED\",\n \"THB\",\n \"TRY\",\n \"PLN\",\n \"CHF\",\n \"ZAR\",\n \"CZK\",\n \"CNY\",\n \"DKK\",\n \"HUF\",\n \"NOK\",\n \"RON\",\n \"SEK\",\n ],\n wise: [\n \"USD\",\n \"CNY\",\n \"EUR\",\n \"GBP\",\n \"AUD\",\n \"NZD\",\n \"CAD\",\n \"AED\",\n \"CHF\",\n \"ZAR\",\n \"SGD\",\n \"ILS\",\n \"HKD\",\n \"JPY\",\n \"PLN\",\n \"TRY\",\n \"IDR\",\n \"KES\",\n \"MYR\",\n \"MXN\",\n \"THB\",\n \"VND\",\n \"UGX\",\n \"CZK\",\n \"DKK\",\n \"HUF\",\n \"INR\",\n \"NOK\",\n \"PHP\",\n \"RON\",\n \"SEK\",\n ],\n mercadopago: [\"ARS\"],\n zelle: [\"USD\"],\n paypal: [\"USD\", \"EUR\", \"GBP\", \"SGD\", \"NZD\", \"AUD\", \"CAD\"],\n monzo: [\"GBP\"],\n};\n\nfunction gatherCatalogHashes(platform: PlatformId): string[] {\n if (platform === \"zelle\") {\n return Object.entries(PAYMENT_CATALOG)\n .filter(([key]) => key.startsWith(\"zelle\"))\n .flatMap(([, entry]) => entry.currencies ?? []);\n }\n return PAYMENT_CATALOG[platform]?.currencies ?? [];\n}\n\nfunction resolveSupportedCurrencies(platform: PlatformId): string[] {\n const codes = new Set<string>();\n for (const hash of gatherCatalogHashes(platform)) {\n const info = getCurrencyInfoFromHash(hash);\n if (info?.currencyCode && currencyInfo[info.currencyCode as CurrencyCode]) {\n codes.add(info.currencyCode);\n }\n }\n if (!codes.size) {\n for (const code of FALLBACK_CURRENCIES[platform] ?? []) codes.add(code);\n }\n return Array.from(codes).sort();\n}\n\n/* ── PayPal.me username normalizer ────────────────────────────────── */\n\n/**\n * Extracts the bare PayPal.me username from any accepted input shape\n * (`paypal.me/user`, `https://paypal.me/user`, `@user`, `user`). Mirrors the\n * upstream zkp2p-clients normalizer so our offchainId hashes identically.\n */\nexport function normalizePaypalMeUsername(value: string): string {\n const trimmed = value.trim();\n if (!trimmed) return \"\";\n const withoutProtocol = trimmed.replace(/^https?:\\/\\//i, \"\");\n const [pathWithoutQuery] = withoutProtocol.split(/[?#]/, 1);\n const sanitizedPath = pathWithoutQuery.replace(/^\\/+/, \"\");\n const [host = \"\", ...pathSegments] = sanitizedPath.split(\"/\");\n const normalizedHost = host.toLowerCase().replace(/^www\\./i, \"\");\n\n if (normalizedHost === \"paypal.me\") {\n const [username = \"\"] = pathSegments;\n return username.replace(/^@+/, \"\").trim().toLowerCase();\n }\n\n if (normalizedHost === \"paypal.com\") {\n const [paypalMePath = \"\", username = \"\"] = pathSegments;\n if (paypalMePath.toLowerCase() !== \"paypalme\") return \"\";\n return username.replace(/^@+/, \"\").trim().toLowerCase();\n }\n\n if (/^https?:\\/\\//i.test(trimmed) || trimmed.includes(\"/\")) {\n return trimmed;\n }\n\n return trimmed.replace(/^@+/, \"\").toLowerCase();\n}\n\n/* ── Validation schemas ───────────────────────────────────────────── */\n\ninterface PlatformBlueprint {\n id: PlatformId;\n name: string;\n identifierLabel: string;\n placeholder: string;\n helperText: string;\n validation: z.ZodType<string>;\n transform?: (value: string) => string;\n extensionRegistration?: PeerExtensionRegistrationInfo;\n}\n\nconst BLUEPRINTS: Record<PlatformId, PlatformBlueprint> = {\n venmo: {\n id: \"venmo\",\n name: \"Venmo\",\n identifierLabel: \"Username\",\n placeholder: \"venmo username (no @)\",\n helperText: \"Username without @ (publicly discoverable)\",\n validation: z\n .string()\n .min(1)\n .regex(/^[a-zA-Z0-9_-]+$/),\n transform: (v) => v.replace(/^@+/, \"\"),\n extensionRegistration: {\n providerId: \"venmo\",\n requiredPrompt:\n \"This Venmo username is not registered yet. Register it with PeerAuth, then retry with the same Venmo username.\",\n ctaLabel: \"Register Venmo Username\",\n },\n },\n cashapp: {\n id: \"cashapp\",\n name: \"Cash App\",\n identifierLabel: \"Cashtag\",\n placeholder: \"cashtag (no $)\",\n helperText: \"Cashtag without $ (publicly discoverable)\",\n validation: z\n .string()\n .min(1)\n .regex(/^[a-zA-Z0-9]+$/),\n transform: (v) => v.replace(/^\\$+/, \"\"),\n extensionRegistration: {\n providerId: \"cashapp\",\n requiredPrompt:\n \"This Cash App cashtag is not registered yet. Register it with PeerAuth, then retry with the same cashtag.\",\n ctaLabel: \"Register Cash App Cashtag\",\n },\n },\n chime: {\n id: \"chime\",\n name: \"Chime\",\n identifierLabel: \"ChimeSign\",\n placeholder: \"$chimesign\",\n helperText: \"ChimeSign with $ (must be discoverable)\",\n validation: z\n .string()\n .min(2)\n .regex(/^\\$[a-zA-Z0-9]+$/),\n transform: (v) => {\n const t = v.trim().toLowerCase();\n return t.startsWith(\"$\") ? t : `$${t}`;\n },\n },\n revolut: {\n id: \"revolut\",\n name: \"Revolut\",\n identifierLabel: \"Revtag\",\n placeholder: \"revtag (no @)\",\n helperText: \"Revtag without @ (must be public)\",\n validation: z\n .string()\n .min(1)\n .regex(/^[a-zA-Z0-9]+$/),\n transform: (v) => v.replace(/^@+/, \"\").trim(),\n },\n wise: {\n id: \"wise\",\n name: \"Wise\",\n identifierLabel: \"Wisetag\",\n placeholder: \"wisetag (no @)\",\n helperText: \"Your Wise @wisetag (no @)\",\n validation: z\n .string()\n .min(1)\n .regex(/^[a-zA-Z0-9_-]+$/),\n transform: (v) => v.replace(/^@+/, \"\").trim(),\n extensionRegistration: {\n providerId: \"wise\",\n requiredPrompt:\n \"This Wisetag is not registered yet. Register it with PeerAuth, then retry with the same Wisetag.\",\n ctaLabel: \"Register Wisetag\",\n },\n },\n mercadopago: {\n id: \"mercadopago\",\n name: \"Mercado Pago\",\n identifierLabel: \"CVU\",\n placeholder: \"22-digit CVU\",\n helperText: \"CVU must be exactly 22 digits\",\n validation: z\n .string()\n .length(22)\n .regex(/^\\d{22}$/),\n },\n zelle: {\n id: \"zelle\",\n name: \"Zelle\",\n identifierLabel: \"Email\",\n placeholder: \"email\",\n helperText: \"Registered Zelle email\",\n // Curator's ZelleProcessor rejects any non-lowercase email outright, so\n // canonicalize to lowercase here rather than letting /v2/makers/create\n // reject after the maker has already approved USDC + paid gas.\n validation: z.string().email(),\n transform: (v) => v.trim().toLowerCase(),\n },\n paypal: {\n id: \"paypal\",\n name: \"PayPal\",\n identifierLabel: \"PayPal.me Username\",\n placeholder: \"paypal.me/your-username\",\n helperText: \"Your PayPal.me username, not your email\",\n validation: z\n .string()\n .min(1, \"PayPal.me username is required\")\n .regex(\n /^[a-z0-9._-]+$/i,\n \"Use your PayPal.me username or paypal.me link, not a shortened URL.\",\n ),\n transform: normalizePaypalMeUsername,\n extensionRegistration: {\n providerId: \"paypal\",\n requiredPrompt:\n \"This PayPal username is not registered yet. Register it with PeerAuth, then retry with the same PayPal username.\",\n ctaLabel: \"Register PayPal Username\",\n ctaSubtext: \"PayPal Business accounts are not supported at this time.\",\n },\n },\n monzo: {\n id: \"monzo\",\n name: \"Monzo\",\n identifierLabel: \"Username\",\n placeholder: \"monzo.me username\",\n helperText: \"Your Monzo.me username\",\n validation: z\n .string()\n .min(1)\n .regex(/^[a-zA-Z0-9_-]+$/),\n },\n};\n\n/* ── Build PLATFORMS const ────────────────────────────────────────── */\n\nfunction buildPlatformEntry(bp: PlatformBlueprint): PlatformEntry {\n const currencies = resolveSupportedCurrencies(bp.id);\n return {\n id: bp.id,\n name: bp.name,\n currencies,\n identifier: {\n label: bp.identifierLabel,\n placeholder: bp.placeholder,\n help: bp.helperText,\n },\n ...(bp.extensionRegistration ? { extensionRegistration: bp.extensionRegistration } : {}),\n validate(input: string) {\n const transformed = bp.transform ? bp.transform(input) : input;\n const result = bp.validation.safeParse(transformed);\n if (!result.success) {\n return {\n valid: false,\n normalized: transformed,\n error: result.error.issues[0]?.message || \"Invalid input\",\n };\n }\n return { valid: true, normalized: transformed };\n },\n };\n}\n\n/** All supported payment platforms. Access via `PLATFORMS.REVOLUT`, `PLATFORMS.WISE`, etc. */\nexport const PLATFORMS = {\n VENMO: buildPlatformEntry(BLUEPRINTS.venmo),\n CASHAPP: buildPlatformEntry(BLUEPRINTS.cashapp),\n CHIME: buildPlatformEntry(BLUEPRINTS.chime),\n REVOLUT: buildPlatformEntry(BLUEPRINTS.revolut),\n WISE: buildPlatformEntry(BLUEPRINTS.wise),\n MERCADO_PAGO: buildPlatformEntry(BLUEPRINTS.mercadopago),\n ZELLE: buildPlatformEntry(BLUEPRINTS.zelle),\n PAYPAL: buildPlatformEntry(BLUEPRINTS.paypal),\n MONZO: buildPlatformEntry(BLUEPRINTS.monzo),\n} as const;\n\n/** Platform key type for PLATFORMS constant. */\nexport type PlatformKey = keyof typeof PLATFORMS;\n\n/* ── Per-platform constraints (mirrored from curator) ─────────────── */\n\n/** Taker account tiers curator gates fills behind, lowest → highest. */\nexport type PlatformTier = \"PEASANT\" | \"PEER\" | \"PLUS\" | \"PRO\" | \"PLATINUM\";\n\nexport interface PlatformLimits {\n /**\n * Hard per-platform max fill (USD) curator enforces regardless of taker\n * tier. Omitted when a platform has no absolute cap — its effective limit is\n * `capMultiplier × tierCap`, which depends on the taker's tier and so can't\n * be known when a maker creates a deposit.\n */\n readonly platformCapUsd?: number;\n /**\n * Minimum taker account tier curator requires to fill on this platform.\n * Omitted when any tier may fill.\n */\n readonly minTier?: PlatformTier;\n}\n\n/**\n * Per-platform constraints mirrored from curator's `PLATFORM_RISK_CONFIG`\n * (curator `platformRisk.ts`). ONLY the absolute, tier-independent rules are\n * mirrored: PayPal's PLUS-tier gate and the hard Venmo cap. Per-tier\n * effective caps are intentionally excluded — they're `capMultiplier × tierCap`\n * and depend on the taker, not the maker. Curator exposes no public \"list\n * limits\" endpoint, so this static mirror can drift if a PeerHQ admin changes\n * a value; treat as an advisory hint, never as enforcement — curator remains\n * the source of truth at intent-signing time.\n */\nexport const PLATFORM_LIMITS: Partial<Record<PlatformId, PlatformLimits>> = {\n venmo: { platformCapUsd: 5_000 },\n paypal: { minTier: \"PLUS\" },\n};\n\n/** Returns curator's constraints for a platform id, or null if unconstrained. */\nexport function getPlatformLimits(platform: string): PlatformLimits | null {\n const id = platform.trim().toLowerCase() as PlatformId;\n return PLATFORM_LIMITS[id] ?? null;\n}\n\n/* ── Internal helpers (used by deposit.ts) ─────────────────────────── */\n\nexport function getPlatformById(id: string): PlatformEntry | null {\n return Object.values(PLATFORMS).find((p) => p.id === id) ?? null;\n}\n\nfunction normalizePaymentMethodLookupName(platform: string): PaymentMethodLookupName | null {\n const normalized = platform.trim().toLowerCase();\n if (!normalized) return null;\n if (ZELLE_HASH_LOOKUP_NAMES.includes(normalized as (typeof ZELLE_HASH_LOOKUP_NAMES)[number])) {\n return normalized as PaymentMethodLookupName;\n }\n const ids: readonly string[] = Object.values(PLATFORMS).map((p) => p.id);\n return ids.includes(normalized) ? (normalized as PlatformId) : null;\n}\n\nconst ZELLE_CREATE_LOOKUP_NAMES = [\"zelle-chase\", \"zelle-bofa\", \"zelle-citi\"] as const;\n\n/**\n * Generic Zelle payment-method hash, keccak256(\"zelle\"). Some upstream\n * surfaces can resolve it, but curator prod reverted generic-Zelle maker\n * creation on 2026-06-23. Keep recognizing it for reads/taker handoff while\n * registering new maker deposits with bank-specific variants.\n */\nexport const GENERIC_ZELLE_METHOD_HASH = (resolvePaymentMethodHash(\"zelle\") ?? null) as\n | `0x${string}`\n | null;\n\nfunction resolveGenericZelleHash(): `0x${string}` | null {\n return GENERIC_ZELLE_METHOD_HASH;\n}\n\nfunction getZelleCreateEntries(): Array<{ name: string; hash: `0x${string}` }> {\n const entries: Array<{ name: string; hash: `0x${string}` }> = [];\n for (const name of ZELLE_CREATE_LOOKUP_NAMES) {\n const hash = getPaymentMethodHash(name);\n if (hash) entries.push({ name, hash });\n }\n return entries;\n}\n\nexport function getPaymentMethodHash(platform: string): `0x${string}` | null {\n const name = normalizePaymentMethodLookupName(platform);\n if (!name) return null;\n const catalogEntry = PAYMENT_CATALOG[name];\n if (catalogEntry?.paymentMethodHash) return catalogEntry.paymentMethodHash;\n if (name === \"zelle\") return resolveGenericZelleHash();\n if (name.startsWith(\"zelle-\")) return resolvePaymentMethodHash(name) as `0x${string}` | null;\n const sdkHash = resolvePaymentMethodHash(name);\n return sdkHash ? (sdkHash as `0x${string}`) : null;\n}\n\nexport function getPaymentMethodHashes(platform: string): `0x${string}`[] {\n if (platform !== \"zelle\") {\n const hash = getPaymentMethodHash(platform);\n return hash ? [hash] : [];\n }\n const hashes = getZelleCreateEntries().map((entry) => entry.hash);\n const generic = resolveGenericZelleHash();\n return generic ? [...hashes, generic] : hashes;\n}\n\nexport function getPaymentMethodCreateEntries(\n platform: string,\n): Array<{ name: string; hash: `0x${string}` }> {\n if (platform !== \"zelle\") {\n const hash = getPaymentMethodHash(platform);\n return hash ? [{ name: platform, hash }] : [];\n }\n return getZelleCreateEntries();\n}\n\n/** Flat payload accepted by `POST /v2/makers/create`. */\nexport interface PayeeDepositData {\n offchainId: string;\n telegramUsername?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface CompletePeerExtensionRegistrationInput {\n readonly platform: PlatformEntry;\n readonly identifier: string;\n readonly capturedMetadata: PeerMetadataMessage;\n}\n\nexport interface CompletePeerExtensionRegistrationResult {\n readonly processorName: SellerCredentialProcessor;\n readonly offchainId: string;\n readonly hashedOnchainId: string;\n readonly sellerCredentialResponse: CuratorSellerCredentialUploadResponse;\n readonly sellerCredentialStatus: CuratorSellerCredentialUploadResponse[\"responseObject\"];\n}\n\ntype PayPalSellerCredentialBundleParams = {\n platform: \"paypal\";\n offchainId: string;\n bundle: PeerSarCredentialBundle;\n};\n\n/**\n * Build the payee payload for `/v2/makers/create`. Chime lowercases its\n * chimesign; PayPal identifiers should already be normalized via\n * `PLATFORMS.PAYPAL.validate()`.\n */\nexport function buildDepositData(\n platform: string,\n identifier: string,\n telegramUsername = \"\",\n): PayeeDepositData {\n const offchainId = platform === \"chime\" ? identifier.toLowerCase() : identifier;\n return telegramUsername ? { offchainId, telegramUsername } : { offchainId };\n}\n\n/* ── Peer extension helpers ──────────────────────────────────────── */\n\n/**\n * Returns the extension-registration metadata for a platform, or `null` if\n * the platform does not require Peer-extension pre-registration. Use this to\n * decide whether to surface an \"Install / Connect Peer Extension\" CTA in\n * your UI before calling `offramp()` for PayPal or Wise.\n */\nexport function getPeerExtensionRegistrationInfo(\n platform: string,\n): PeerExtensionRegistrationInfo | null {\n const entry = getPlatformById(platform);\n return entry?.extensionRegistration ?? null;\n}\n\nexport function getPeerExtensionRegistrationAuthParams(\n platform: string,\n options: { attestationServiceUrl?: string | null } = {},\n): PeerAuthenticateParams | null {\n const info = getPeerExtensionRegistrationInfo(platform);\n if (!info) return null;\n const params: PeerAuthenticateParams = {\n actionType: `transfer_${info.providerId}`,\n captureMode: \"sellerCredential\",\n platform: info.providerId,\n };\n if (options.attestationServiceUrl) {\n params.attestationServiceUrl = options.attestationServiceUrl;\n }\n return params;\n}\n\nfunction resolveRegistrationProcessor(platform: PlatformEntry): SellerCredentialProcessor {\n const info = getPeerExtensionRegistrationInfo(platform.id);\n if (\n info?.providerId === \"paypal\" ||\n info?.providerId === \"wise\" ||\n info?.providerId === \"venmo\" ||\n info?.providerId === \"cashapp\"\n ) {\n return info.providerId;\n }\n throw new Error(`${platform.name} does not require Peer extension registration.`);\n}\n\n/**\n * POST a maker to curator's `/v2/makers/create` and return the\n * `hashedOnchainId`. Shared by the deposit flow (standard processors) and the\n * Peer-extension registration flow (PayPal/Wise/Venmo/Cash App). Throws `MakersCreateError`\n * preserving curator's HTTP status so callers can apply the\n * extension-registration heuristic.\n */\nexport async function postMakerCreate(\n processorName: string,\n payload: PayeeDepositData,\n apiBaseUrl: string = API_BASE_URL,\n): Promise<string> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), PAYEE_REGISTRATION_TIMEOUT_MS);\n try {\n const res = await fetch(`${apiBaseUrl}/v2/makers/create`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ processorName, ...payload }),\n signal: controller.signal,\n });\n if (!res.ok) {\n const txt = await res.text().catch(() => \"\");\n // Prefer curator's JSON `message` so the extension-registration heuristic\n // can match on the \"creating the maker\" phrasing.\n let detail = txt || res.statusText;\n try {\n const parsed = JSON.parse(txt) as { message?: unknown };\n if (typeof parsed.message === \"string\" && parsed.message.trim()) {\n detail = parsed.message;\n }\n } catch {\n // fall through\n }\n throw new MakersCreateError(\n `makers/create failed (${res.status}): ${detail}`,\n res.status,\n txt,\n );\n }\n const json = (await res.json()) as {\n success: boolean;\n message: string;\n statusCode?: number;\n responseObject?: { hashedOnchainId: string };\n };\n if (!json.success || !json.responseObject?.hashedOnchainId) {\n throw new MakersCreateError(\n json.message || \"makers/create returned no hashedOnchainId\",\n json.statusCode ?? null,\n \"\",\n );\n }\n return json.responseObject.hashedOnchainId;\n } finally {\n clearTimeout(timeout);\n }\n}\n\nfunction requireSarCredentialCapture(\n capturedMetadata: PeerMetadataMessage,\n): PeerSarCredentialCapture {\n const capture = capturedMetadata.sarCredentialCapture;\n if (!capture?.credentialBundle) {\n throw new Error(\"Peer metadata did not include a seller credential bundle.\");\n }\n if (!capture.offchainId) {\n throw new Error(\"Peer metadata did not include seller credential offchainId.\");\n }\n return capture;\n}\n\nasync function uploadSellerCredentialBundle(\n processorName: SellerCredentialProcessor,\n offchainId: string,\n bundle: PeerSarCredentialBundle,\n): Promise<CuratorSellerCredentialUploadResponse> {\n const params: UploadSellerCredentialBundleParams | PayPalSellerCredentialBundleParams =\n processorName === \"wise\"\n ? { platform: \"wise\", bundle }\n : { platform: processorName, offchainId, bundle };\n // @zkp2p/sdk's public bundle-upload type covers venmo/cashapp/wise. PayPal\n // remains a curator-compatible runtime path, so keep the cast for that one\n // legacy route while letting the first-class SAR platforms pass through.\n //\n // Older @zkp2p/sdk releases narrowed the public type to venmo/cashapp/wise, but the\n // runtime helper still supports the curator's PayPal bundle route by\n // registering `{ processorName: \"paypal\", offchainId }` before upload. Keep\n // that path here so existing PayPal maker recovery keeps working.\n return apiUploadSellerCredentialBundle(\n params as unknown as UploadSellerCredentialBundleParams,\n API_BASE_URL,\n PAYEE_REGISTRATION_TIMEOUT_MS,\n );\n}\n\nexport async function completePeerExtensionRegistration(\n input: CompletePeerExtensionRegistrationInput,\n): Promise<CompletePeerExtensionRegistrationResult> {\n const processorName = resolveRegistrationProcessor(input.platform);\n if (input.capturedMetadata.platform !== processorName) {\n throw new Error(\n `Peer metadata is for ${input.capturedMetadata.platform}, not ${processorName}.`,\n );\n }\n\n const sarCredentialCapture = requireSarCredentialCapture(input.capturedMetadata);\n const bundle = sarCredentialCapture.credentialBundle;\n if (bundle.platform.toLowerCase() !== processorName) {\n throw new Error(\"Seller credential bundle platform does not match registration platform.\");\n }\n\n const validation = input.platform.validate(input.identifier);\n if (!validation.valid) {\n throw new Error(validation.error || \"Invalid identifier\");\n }\n\n const payload = buildDepositData(processorName, sarCredentialCapture.offchainId);\n if (payload.offchainId !== validation.normalized) {\n throw new Error(\"Seller credential offchainId does not match registration identifier.\");\n }\n const hashedOnchainId = bundle.payeeIdHash;\n\n const sellerCredentialResponse = await uploadSellerCredentialBundle(\n processorName,\n payload.offchainId,\n bundle,\n );\n\n return {\n processorName,\n offchainId: payload.offchainId,\n hashedOnchainId,\n sellerCredentialResponse,\n sellerCredentialStatus: sellerCredentialResponse.responseObject,\n };\n}\n\n// Phrases curator emits when the maker is not yet registered in the Peer\n// extension. Matched case-insensitively alongside the 400 heuristic.\nconst EXTENSION_REGISTRATION_ERROR_PATTERNS = [\"creating the maker\", \"create the maker\"] as const;\n\n/**\n * True when a failed `/v2/makers/create` response should be treated as\n * \"maker needs to register in the Peer extension first\". Platforms without\n * an `extensionRegistration` config always return false. A 400 on a\n * registration-required platform is treated as registration required, and\n * so is any response whose message contains curator's phrasing.\n */\nexport function isPeerExtensionRegistrationError(\n platform: string,\n message?: string | null,\n statusCode?: number | null,\n): boolean {\n const info = getPeerExtensionRegistrationInfo(platform);\n if (!info) return false;\n if (statusCode === 400) return true;\n const normalized = (message ?? \"\").trim();\n if (!normalized) return false;\n const lower = normalized.toLowerCase();\n return EXTENSION_REGISTRATION_ERROR_PATTERNS.some((p) => lower.includes(p));\n}\n","import type { WalletClient } from \"viem\";\nimport { createPublicClient, http, isAddress, zeroAddress, type Address } from \"viem\";\nimport { base } from \"viem/chains\";\nimport WhitelistPreIntentHookABI from \"@zkp2p/contracts-v2/abis/base/WhitelistPreIntentHook.json\";\n\nimport { createSdkClient } from \"./sdk-client\";\nimport { BASE_RPC_URL, ESCROW_ADDRESS, REFERRER } from \"./config\";\nimport { OfframpError, isUserCancellation } from \"./errors\";\n\nconst WHITELIST_HOOK_ADDRESS = \"0xda023Ea0d789A41BcF5866F7B6BBd2CaDF9b79B8\" as const;\n\nconst OTC_BASE_URL = \"https://otc.usdctofiat.xyz\";\n\nexport interface EnableOtcResult {\n depositId: string;\n takerAddress: string;\n otcLink: string;\n}\n\n/**\n * Make a deposit private so only one taker wallet can trade against it.\n *\n * Sets the WhitelistPreIntentHook on the deposit and whitelists the taker.\n * The hook stores its whitelist as a membership-only mapping with no\n * enumeration, so a taker that was previously whitelisted is NOT removed when\n * a new one is added — both stay whitelisted. To switch to a single new taker,\n * remove the prior one explicitly (or `disableOtc` first) before calling this.\n *\n * @param walletClient - viem WalletClient with the deposit owner's account\n * @param depositId - The numeric deposit ID (from `OfframpResult.depositId`)\n * @param takerAddress - The Ethereum address allowed to take this order\n * @param escrowAddress - Optional escrow override (defaults to current V3 escrow)\n */\nexport async function enableOtc(\n walletClient: WalletClient,\n depositId: string,\n takerAddress: string,\n escrowAddress?: string,\n): Promise<EnableOtcResult> {\n if (!isAddress(takerAddress)) {\n throw new OfframpError(\"Invalid taker address\", \"VALIDATION\");\n }\n\n const escrow = (escrowAddress || ESCROW_ADDRESS) as Address;\n const taker = takerAddress as Address;\n const depositIdBig = BigInt(depositId);\n const client = createSdkClient(walletClient);\n const txOverrides = { referrer: [REFERRER] };\n\n try {\n // Check current hook state\n const currentHook = (await client.getDepositWhitelistHook(depositIdBig, {\n escrowAddress: escrow,\n })) as Address;\n\n // If the hook is already set and this taker is already whitelisted, no-op.\n if (currentHook !== zeroAddress) {\n const isAlready = (await readIsWhitelisted(escrow, depositIdBig, taker)) as boolean;\n\n if (isAlready) {\n return {\n depositId,\n takerAddress: taker,\n otcLink: getOtcLink(depositId, escrow),\n };\n }\n }\n\n // Add taker to whitelist\n await writeContract(walletClient, \"addToWhitelist\", [escrow, depositIdBig, [taker]]);\n\n // Set hook if not already set\n if (currentHook === zeroAddress) {\n await client.setDepositWhitelistHook({\n depositId: depositIdBig,\n whitelistHook: WHITELIST_HOOK_ADDRESS,\n escrowAddress: escrow,\n txOverrides,\n });\n }\n\n return {\n depositId,\n takerAddress: taker,\n otcLink: getOtcLink(depositId, escrow),\n };\n } catch (err) {\n if (err instanceof OfframpError) throw err;\n if (isUserCancellation(err)) {\n throw new OfframpError(\"User cancelled\", \"USER_CANCELLED\", undefined, err, { depositId });\n }\n const detail = err instanceof Error ? err.message : String(err);\n throw new OfframpError(`Failed to enable OTC: ${detail}`, \"DEPOSIT_FAILED\", undefined, err, {\n depositId,\n });\n }\n}\n\n/**\n * Remove the OTC restriction and make the deposit public again.\n *\n * @param walletClient - viem WalletClient with the deposit owner's account\n * @param depositId - The numeric deposit ID\n * @param escrowAddress - Optional escrow override (defaults to current V3 escrow)\n */\nexport async function disableOtc(\n walletClient: WalletClient,\n depositId: string,\n escrowAddress?: string,\n): Promise<void> {\n const escrow = (escrowAddress || ESCROW_ADDRESS) as Address;\n const client = createSdkClient(walletClient);\n const txOverrides = { referrer: [REFERRER] };\n\n try {\n await client.setDepositWhitelistHook({\n depositId: BigInt(depositId),\n whitelistHook: zeroAddress,\n escrowAddress: escrow,\n txOverrides,\n });\n } catch (err) {\n if (isUserCancellation(err)) {\n throw new OfframpError(\"User cancelled\", \"USER_CANCELLED\", undefined, err, { depositId });\n }\n const detail = err instanceof Error ? err.message : String(err);\n throw new OfframpError(`Failed to disable OTC: ${detail}`, \"DEPOSIT_FAILED\", undefined, err, {\n depositId,\n });\n }\n}\n\n/**\n * Get the OTC deposit link that a taker opens to fill the order.\n *\n * @param depositId - The numeric deposit ID\n * @param escrowAddress - Optional escrow override (defaults to current V3 escrow)\n */\nexport function getOtcLink(depositId: string, escrowAddress?: string): string {\n const escrow = escrowAddress || ESCROW_ADDRESS;\n return `${OTC_BASE_URL}/d/${escrow}/${depositId}`;\n}\n\n/* ── Internal helpers ──────────────────────────────────────────────── */\n\nasync function writeContract(\n walletClient: WalletClient,\n functionName: string,\n args: unknown[],\n): Promise<void> {\n const wc = walletClient as unknown as {\n writeContract: (req: {\n address: Address;\n abi: unknown;\n functionName: string;\n args: unknown[];\n }) => Promise<string>;\n };\n if (typeof wc.writeContract !== \"function\") {\n throw new OfframpError(\"Wallet client does not support writeContract\", \"VALIDATION\");\n }\n await wc.writeContract({\n address: WHITELIST_HOOK_ADDRESS,\n abi: WhitelistPreIntentHookABI,\n functionName,\n args,\n });\n}\n\nasync function readIsWhitelisted(\n escrow: Address,\n depositId: bigint,\n taker: Address,\n): Promise<unknown> {\n const publicClient = createPublicClient({ chain: base, transport: http(BASE_RPC_URL) });\n return publicClient.readContract({\n address: WHITELIST_HOOK_ADDRESS,\n abi: WhitelistPreIntentHookABI,\n functionName: \"isWhitelisted\",\n args: [escrow, depositId, taker],\n });\n}\n","/**\n * SDK client factory.\n *\n * Extracted from `./deposit.ts` so both `otc.ts` and `queries.ts` can import\n * `createSdkClient` without closing a cycle back through `deposit.ts`.\n */\n\nimport type { WalletClient } from \"viem\";\nimport { OfframpClient } from \"@zkp2p/sdk\";\n\nimport { API_BASE_URL, BASE_CHAIN_ID, BASE_RPC_URL, RUNTIME_ENV } from \"./config\";\n\nexport function createSdkClient(\n walletClient: WalletClient,\n apiBaseUrl: string = API_BASE_URL,\n): OfframpClient {\n return new OfframpClient({\n walletClient: walletClient as any,\n chainId: BASE_CHAIN_ID,\n runtimeEnv: RUNTIME_ENV,\n rpcUrl: BASE_RPC_URL,\n baseApiUrl: apiBaseUrl,\n });\n}\n","import type { Hex, WalletClient } from \"viem\";\nimport { concatHex, createPublicClient, encodeFunctionData, formatUnits, http } from \"viem\";\nimport { base } from \"viem/chains\";\nimport {\n classifyDelegationState,\n defaultIndexerEndpoint,\n getAttributionDataSuffix,\n getCurrencyInfoFromHash,\n IndexerClient,\n IndexerDepositService,\n} from \"@zkp2p/sdk\";\n\nimport type { DepositInfo, DepositStatus } from \"./types\";\nimport { createSdkClient } from \"./sdk-client\";\nimport { PLATFORMS, getPaymentMethodHashes } from \"./platforms\";\nimport {\n BASE_RPC_URL,\n DELEGATE_RATE_MANAGER_ID,\n ESCROW_ADDRESS,\n RATE_MANAGER_REGISTRY_ADDRESS,\n REFERRER,\n} from \"./config\";\n\n/* ── Indexer singleton ────────────────────────────────────────────── */\n\nlet indexerService: IndexerDepositService | null = null;\n\nexport function getIndexerService(): IndexerDepositService {\n if (!indexerService) {\n const endpoint = defaultIndexerEndpoint(\"PRODUCTION\");\n const client = new IndexerClient(endpoint);\n indexerService = new IndexerDepositService(client);\n }\n return indexerService;\n}\n\n/* ── Helpers ──────────────────────────────────────────────────────── */\n\ntype IndexerDeposit = {\n id: string;\n depositId: string;\n txHash?: string;\n status: string;\n remainingDeposits: string | null;\n outstandingIntentAmount: string | null;\n totalAmountTaken: string | null;\n fulfilledIntents: number | null;\n escrowAddress: string;\n rateManagerId?: string | null;\n rateManagerAddress?: string | null;\n paymentMethods: Array<{ paymentMethodHash: string }>;\n currencies: Array<{ currencyCode: string; rateSource?: string | null }>;\n};\n\nfunction toBigInt(value: string | null | undefined): bigint {\n try {\n return BigInt(value || \"0\");\n } catch {\n return 0n;\n }\n}\n\nfunction toUsdc(value: string | null | undefined): number {\n return Number(formatUnits(toBigInt(value), 6));\n}\n\nfunction resolveStatus(deposit: IndexerDeposit): DepositStatus {\n if (deposit.status === \"CLOSED\") return \"closed\";\n if (toBigInt(deposit.remainingDeposits) === 0n) return \"empty\";\n return \"active\";\n}\n\nfunction resolveMethodNames(hashes: Array<{ paymentMethodHash: string }>): string[] {\n const names = new Set<string>();\n for (const { paymentMethodHash } of hashes) {\n const normalized = paymentMethodHash.toLowerCase();\n for (const platform of Object.values(PLATFORMS)) {\n const platformHashes = getPaymentMethodHashes(platform.id);\n if (platformHashes.some((h) => h.toLowerCase() === normalized)) {\n names.add(platform.name);\n break;\n }\n }\n }\n return Array.from(names);\n}\n\nfunction mapDeposit(d: IndexerDeposit): DepositInfo {\n const delegationState = classifyDelegationState(\n d.rateManagerId ?? undefined,\n d.rateManagerAddress ?? undefined,\n DELEGATE_RATE_MANAGER_ID,\n RATE_MANAGER_REGISTRY_ADDRESS,\n );\n return {\n depositId: d.depositId,\n compositeId: d.id,\n txHash: d.txHash,\n status: resolveStatus(d),\n remainingUsdc: toUsdc(d.remainingDeposits),\n outstandingUsdc: toUsdc(d.outstandingIntentAmount),\n totalTakenUsdc: toUsdc(d.totalAmountTaken),\n fulfilledIntents: d.fulfilledIntents ?? 0,\n paymentMethods: resolveMethodNames(d.paymentMethods),\n currencies: d.currencies.map((c) => {\n const info = getCurrencyInfoFromHash(c.currencyCode);\n return info?.currencyCode ?? c.currencyCode;\n }),\n rateSource: d.currencies[0]?.rateSource || \"unknown\",\n delegated: delegationState === \"delegated_here\",\n escrowAddress: d.escrowAddress,\n };\n}\n\nfunction extractTxHash(result: unknown): string {\n if (typeof result === \"string\") return result;\n if (result && typeof result === \"object\" && \"hash\" in result)\n return (result as { hash: string }).hash;\n if (result && typeof result === \"object\" && \"transactionHash\" in result)\n return (result as { transactionHash: string }).transactionHash;\n throw new Error(\"Unexpected transaction result format\");\n}\n\nconst ESCROW_V2_ABI = [\n {\n name: \"clearRateManager\",\n type: \"function\",\n stateMutability: \"nonpayable\",\n inputs: [{ name: \"depositId\", type: \"uint256\" }],\n outputs: [],\n },\n] as const;\n\nfunction appendReferrerAttribution(calldata: Hex): Hex {\n return concatHex([calldata, getAttributionDataSuffix([REFERRER])]);\n}\n\n/* ── Public functions ─────────────────────────────────────────────── */\n\n/**\n * List all deposits for a wallet address. Read-only, no wallet needed.\n * Returns active deposits first, then empty, then closed.\n */\nexport async function deposits(walletAddress: string): Promise<DepositInfo[]> {\n const service = getIndexerService();\n const raw = (await service.fetchDepositsWithRelations(\n { depositor: walletAddress as `0x${string}` },\n { limit: 100 },\n )) as IndexerDeposit[];\n\n const statusOrder: Record<DepositStatus, number> = { active: 0, empty: 1, closed: 2 };\n\n return (raw || []).map(mapDeposit).sort((a, b) => {\n const diff = statusOrder[a.status] - statusOrder[b.status];\n if (diff !== 0) return diff;\n return Number(BigInt(b.depositId) - BigInt(a.depositId));\n });\n}\n\n/**\n * Withdraw remaining USDC and close a deposit.\n *\n * @param walletClient - viem WalletClient with the deposit owner's account\n * @param depositId - The numeric deposit ID (from `DepositInfo.depositId`)\n */\nexport async function close(\n walletClient: WalletClient,\n depositId: string,\n escrowAddress?: string,\n): Promise<string> {\n const client = createSdkClient(walletClient);\n const result = await client.withdrawDeposit({\n depositId: BigInt(depositId),\n escrowAddress: (escrowAddress || ESCROW_ADDRESS) as `0x${string}`,\n txOverrides: { referrer: [REFERRER] },\n });\n return extractTxHash(result);\n}\n\n/**\n * Delegate a deposit to the configured Delegate vault.\n *\n * @param walletClient - viem WalletClient with the deposit owner's account\n * @param depositId - The numeric deposit ID (from `DepositInfo.depositId`)\n */\nexport async function delegate(\n walletClient: WalletClient,\n depositId: string,\n escrowAddress?: string,\n): Promise<string> {\n const client = createSdkClient(walletClient);\n const result = await client.setRateManager({\n depositId: BigInt(depositId),\n rateManagerAddress: RATE_MANAGER_REGISTRY_ADDRESS,\n rateManagerId: DELEGATE_RATE_MANAGER_ID,\n escrowAddress: (escrowAddress || ESCROW_ADDRESS) as `0x${string}`,\n txOverrides: { referrer: [REFERRER] },\n });\n return extractTxHash(result);\n}\n\n/**\n * Remove Delegate rate management from a deposit.\n *\n * @param walletClient - viem WalletClient with the deposit owner's account\n * @param depositId - The numeric deposit ID (from `DepositInfo.depositId`)\n */\nexport async function undelegate(\n walletClient: WalletClient,\n depositId: string,\n escrowAddress?: string,\n): Promise<string> {\n const account = walletClient.account;\n if (!account) {\n throw new Error(\"Wallet client has no account. Connect a wallet first.\");\n }\n\n const data = appendReferrerAttribution(\n encodeFunctionData({\n abi: ESCROW_V2_ABI,\n functionName: \"clearRateManager\",\n args: [BigInt(depositId)],\n }),\n );\n\n const hash = await walletClient.sendTransaction({\n account,\n chain: base,\n data,\n to: (escrowAddress || ESCROW_ADDRESS) as `0x${string}`,\n });\n\n const publicClient = createPublicClient({\n chain: base,\n transport: http(BASE_RPC_URL),\n });\n\n try {\n const receipt = await publicClient.waitForTransactionReceipt({\n hash,\n confirmations: 1,\n timeout: 120_000,\n pollingInterval: 4_000,\n });\n\n if (receipt.status !== \"success\") {\n throw new Error(\"Undelegation transaction failed\");\n }\n } catch (err) {\n const isTimeout = err instanceof Error && err.message.toLowerCase().includes(\"timed out\");\n\n if (!isTimeout) {\n throw err;\n }\n }\n\n return hash;\n}\n","const SDK_EVENTS_ENDPOINT = \"https://usdctofiat.xyz/api/sdk-events\";\nconst MAX_BATCH_SIZE = 50;\nconst FLUSH_DELAY_MS = 180;\nconst TELEMETRY_TIMEOUT_MS = 2_000;\n\nexport type TelemetryEventName =\n | \"sdk.init\"\n | \"sdk.createDeposit.start\"\n | \"sdk.createDeposit.progress\"\n | \"sdk.createDeposit.success\"\n | \"sdk.createDeposit.error\";\n\nexport interface TelemetryEvent {\n name: TelemetryEventName;\n payload?: Record<string, unknown>;\n ts: number;\n}\n\nexport interface TelemetryContext {\n readonly enabled: boolean;\n readonly sdkVersion: string;\n readonly integratorId?: string;\n readonly referralId?: string;\n emit: (name: TelemetryEventName, payload?: Record<string, unknown>) => void;\n}\n\nexport interface CreateTelemetryContextOptions {\n sdkVersion: string;\n telemetry?: boolean;\n integratorId?: string;\n referralId?: string;\n}\n\nlet queuedEvents: TelemetryEvent[] = [];\nlet flushTimer: ReturnType<typeof setTimeout> | null = null;\nlet flushInFlight = false;\n\nexport function sanitizeAttributionId(raw: unknown): string | undefined {\n if (typeof raw !== \"string\") return undefined;\n const stripped = raw.trim().replace(/[^a-zA-Z0-9_-]/g, \"\");\n if (!stripped) return undefined;\n if (stripped.length > 64) return undefined;\n return stripped;\n}\n\nfunction scheduleFlush(): void {\n if (flushTimer != null) return;\n flushTimer = setTimeout(() => {\n flushTimer = null;\n void flushQueue();\n }, FLUSH_DELAY_MS);\n}\n\nasync function postBatch(batch: TelemetryEvent[]): Promise<void> {\n if (!batch.length) return;\n\n const body = JSON.stringify(batch);\n try {\n if (typeof navigator !== \"undefined\" && typeof navigator.sendBeacon === \"function\") {\n const blob = new Blob([body], { type: \"application/json\" });\n const accepted = navigator.sendBeacon(SDK_EVENTS_ENDPOINT, blob);\n if (accepted) return;\n }\n } catch {\n // noop: fall back to fetch\n }\n\n try {\n const controller =\n typeof AbortController !== \"undefined\"\n ? new AbortController()\n : (null as AbortController | null);\n const timeout = controller ? setTimeout(() => controller.abort(), TELEMETRY_TIMEOUT_MS) : null;\n await fetch(SDK_EVENTS_ENDPOINT, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n keepalive: true,\n signal: controller?.signal,\n }).catch(() => {});\n if (timeout) clearTimeout(timeout);\n } catch {\n // noop: best effort\n }\n}\n\nasync function flushQueue(): Promise<void> {\n if (flushInFlight) return;\n if (!queuedEvents.length) return;\n flushInFlight = true;\n try {\n while (queuedEvents.length > 0) {\n const batch = queuedEvents.slice(0, MAX_BATCH_SIZE);\n queuedEvents = queuedEvents.slice(batch.length);\n await postBatch(batch);\n }\n } finally {\n flushInFlight = false;\n }\n}\n\nexport function emitEvent(name: TelemetryEventName, payload?: Record<string, unknown>): void {\n try {\n queuedEvents.push({\n name,\n payload,\n ts: Date.now(),\n });\n if (queuedEvents.length >= MAX_BATCH_SIZE) {\n void flushQueue();\n return;\n }\n scheduleFlush();\n } catch {\n // noop\n }\n}\n\nexport function sendTelemetryEvent(\n name: TelemetryEventName,\n payload?: Record<string, unknown>,\n): void {\n emitEvent(name, payload);\n}\n\nexport function createTelemetryContext(options: CreateTelemetryContextOptions): TelemetryContext {\n const integratorId = sanitizeAttributionId(options.integratorId);\n const referralId = sanitizeAttributionId(options.referralId);\n const enabled = options.telemetry !== false;\n const sdkVersion = options.sdkVersion;\n\n return {\n enabled,\n sdkVersion,\n integratorId,\n referralId,\n emit(name, payload = {}) {\n if (!enabled) return;\n emitEvent(name, {\n sdkVersion,\n integratorId,\n referralId,\n ...payload,\n });\n },\n };\n}\n","import type { WalletClient } from \"viem\";\nimport { createPublicClient, decodeEventLog, formatUnits, http, parseUnits, type Hex } from \"viem\";\nimport { base } from \"viem/chains\";\nimport {\n getSpreadOracleConfig,\n mapConversionRatesToOnchainMinRate,\n type CurrencyType,\n} from \"@zkp2p/sdk\";\n\nimport {\n API_BASE_URL,\n BASE_RPC_URL,\n DEFAULT_INTENT_GUARDIAN_ADDRESS,\n DELEGATE_RATE_MANAGER_ID,\n ESCROW_ADDRESS,\n GATING_SERVICE_ADDRESS,\n INDEXER_INITIAL_DELAY_MS,\n INDEXER_MAX_ATTEMPTS,\n INDEXER_MAX_DELAY_MS,\n MAX_ORDER_USDC,\n MIN_DEPOSIT_USDC,\n MIN_ORDER_USDC,\n PAYEE_REGISTRATION_TIMEOUT_MS,\n RATE_MANAGER_REGISTRY_ADDRESS,\n REFERRER,\n resolveApiBaseUrl,\n SDK_VERSION,\n USDC_ADDRESS,\n} from \"./config\";\nimport {\n buildDepositData,\n getPaymentMethodCreateEntries,\n getPeerExtensionRegistrationInfo,\n isPeerExtensionRegistrationError,\n postMakerCreate,\n} from \"./platforms\";\nimport { MakersCreateError, OfframpError, isUserCancellation } from \"./errors\";\nimport { enableOtc } from \"./otc\";\nimport { getIndexerService } from \"./queries\";\nimport { createSdkClient } from \"./sdk-client\";\nimport { createTelemetryContext, type TelemetryContext } from \"./telemetry\";\nimport type { OfframpParams, OfframpResult, OnProgress } from \"./types\";\n\nexport { createSdkClient };\n\n/* ── Helpers ──────────────────────────────────────────────────────── */\n\nfunction usdcToUnits(amount: string): bigint {\n return parseUnits(amount, 6);\n}\n\nconst DEPOSIT_RECEIVED_ABI = [\n {\n type: \"event\" as const,\n name: \"DepositReceived\" as const,\n inputs: [\n { indexed: true, name: \"depositId\", type: \"uint256\" },\n { indexed: true, name: \"depositor\", type: \"address\" },\n { indexed: true, name: \"token\", type: \"address\" },\n { indexed: false, name: \"amount\", type: \"uint256\" },\n {\n indexed: false,\n name: \"intentAmountRange\",\n type: \"tuple\",\n components: [\n { name: \"min\", type: \"uint256\" },\n { name: \"max\", type: \"uint256\" },\n ],\n },\n { indexed: false, name: \"delegate\", type: \"address\" },\n { indexed: false, name: \"intentGuardian\", type: \"address\" },\n ],\n },\n] as const;\n\nfunction extractDepositIdFromLogs(logs: Array<{ topics?: Hex[]; data?: Hex }>): string | null {\n for (const log of logs) {\n if (!log?.topics?.length || !log.data) continue;\n try {\n const decoded = decodeEventLog({\n abi: DEPOSIT_RECEIVED_ABI,\n data: log.data,\n topics: log.topics as [Hex, ...Hex[]],\n });\n if (decoded.eventName !== \"DepositReceived\") continue;\n const args = decoded.args as { depositId?: bigint };\n if (typeof args.depositId === \"bigint\") return args.depositId.toString();\n } catch {\n continue;\n }\n }\n return null;\n}\n\ntype ValidateOutcome = \"valid\" | \"invalid\" | \"unknown\";\n\n/**\n * Pre-checks a payee handle against curator's `/v2/makers/validate` before the\n * maker spends gas. Curator runs the same processor checks `/v2/makers/create`\n * does (format, live existence lookup for Venmo/Revolut, lowercase for Zelle)\n * with zero on-chain side effects, returning the verdict as a `responseObject`\n * boolean on an HTTP 200.\n *\n * Fails OPEN: only an explicit `false` verdict returns `\"invalid\"`. Curator\n * downtime, a non-200, a network error, or an unexpected body all return\n * `\"unknown\"` so the deposit still proceeds and `/v2/makers/create` stays the\n * authoritative gate — the pre-check can never be the reason a valid maker is\n * blocked.\n */\nasync function validatePayeeDetails(\n processorName: string,\n offchainId: string,\n apiBaseUrl: string = API_BASE_URL,\n): Promise<ValidateOutcome> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), PAYEE_REGISTRATION_TIMEOUT_MS);\n try {\n const res = await fetch(`${apiBaseUrl}/v2/makers/validate`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ processorName, offchainId }),\n signal: controller.signal,\n });\n if (!res.ok) return \"unknown\";\n const json = (await res.json()) as { responseObject?: unknown };\n if (typeof json.responseObject === \"boolean\") {\n return json.responseObject ? \"valid\" : \"invalid\";\n }\n return \"unknown\";\n } catch {\n return \"unknown\";\n } finally {\n clearTimeout(timeout);\n }\n}\n\ntype OnchainCurrencyEntry = {\n code: `0x${string}`;\n minConversionRate: bigint;\n oracleRateConfig?: {\n adapter: `0x${string}`;\n adapterConfig: `0x${string}`;\n spreadBps: number;\n maxStaleness: number;\n };\n};\n\nfunction attachOracleConfig(\n entries: Array<Array<{ code: `0x${string}`; minConversionRate: bigint }>>,\n conversionRates: Array<Array<{ currency: CurrencyType; conversionRate: string }>>,\n): OnchainCurrencyEntry[][] {\n return entries.map((group, gi) =>\n group.map((entry, ci) => {\n const currency = conversionRates[gi]?.[ci]?.currency;\n if (!currency) return entry;\n const oracleConfig = getSpreadOracleConfig(currency);\n if (!oracleConfig) return entry;\n return {\n ...entry,\n oracleRateConfig: {\n adapter: oracleConfig.adapter,\n adapterConfig: oracleConfig.adapterConfig,\n spreadBps: 0,\n maxStaleness: oracleConfig.maxStaleness,\n },\n };\n }),\n );\n}\n\nfunction extractTxHash(result: unknown): string {\n if (typeof result === \"string\") return result;\n if (result && typeof result === \"object\" && \"hash\" in result)\n return (result as { hash: string }).hash;\n if (result && typeof result === \"object\" && \"transactionHash\" in result)\n return (result as { transactionHash: string }).transactionHash;\n throw new Error(\"Unexpected transaction result format\");\n}\n\n/* ── Resume check ─────────────────────────────────────────────────── */\n\ntype IndexerDeposit = {\n depositId: string;\n txHash?: string;\n status: string;\n remainingDeposits: string | null;\n escrowAddress: string;\n rateManagerId?: string | null;\n rateManagerAddress?: string | null;\n};\n\nasync function findUndelegatedDeposit(walletAddress: string): Promise<IndexerDeposit | null> {\n try {\n const service = getIndexerService();\n const raw = (await service.fetchDepositsWithRelations(\n { depositor: walletAddress as `0x${string}` },\n { limit: 50 },\n )) as IndexerDeposit[];\n\n const escrowLower = ESCROW_ADDRESS.toLowerCase();\n const delegateIdLower = DELEGATE_RATE_MANAGER_ID.toLowerCase();\n const undelegated = (raw || []).filter((d) => {\n if (d.status === \"CLOSED\") return false;\n if (d.escrowAddress.toLowerCase() !== escrowLower) return false;\n const remaining = (() => {\n try {\n return BigInt(d.remainingDeposits || \"0\");\n } catch {\n return 0n;\n }\n })();\n if (remaining === 0n) return false;\n return (d.rateManagerId ?? \"\").toLowerCase() !== delegateIdLower;\n });\n // Most recent first\n undelegated.sort((a, b) => {\n const left = BigInt(a.depositId);\n const right = BigInt(b.depositId);\n if (left === right) return 0;\n return left > right ? -1 : 1;\n });\n return undelegated[0] ?? null;\n } catch {\n return null;\n }\n}\n\n/* ── Main offramp flow ────────────────────────────────────────────── */\n\n/**\n * Create a USDC-to-fiat offramp deposit and delegate it to the vault.\n *\n * **Resumable**: if an existing undelegated deposit is found for this wallet,\n * the flow skips directly to delegation instead of creating a new deposit.\n */\nexport async function offramp(\n walletClient: WalletClient,\n params: OfframpParams,\n onProgress?: OnProgress,\n telemetryContext?: TelemetryContext,\n apiBaseUrl?: string,\n): Promise<OfframpResult> {\n const { amount, platform, currency, identifier } = params;\n const platformId = platform.id;\n const currencyCode = currency.code;\n // Resolves to the production curator REST base unless an override is passed.\n // Only the curator REST surface is overridable (indexer + RPC stay mainnet).\n const resolvedApiBaseUrl = resolveApiBaseUrl(apiBaseUrl);\n const telemetry =\n telemetryContext ??\n createTelemetryContext({\n sdkVersion: SDK_VERSION,\n telemetry: true,\n integratorId: params.integratorId,\n referralId: params.referralId,\n });\n const flowStartMs = Date.now();\n const emitProgress = (progress: Parameters<NonNullable<typeof onProgress>>[0]) => {\n onProgress?.(progress);\n telemetry.emit(\"sdk.createDeposit.progress\", {\n step: progress.step,\n txHash: progress.txHash,\n });\n };\n\n try {\n // 1. Validate\n if (!walletClient.account?.address) {\n throw new OfframpError(\"Wallet client has no account. Connect a wallet first.\", \"VALIDATION\");\n }\n const walletAddress = walletClient.account.address.toLowerCase() as `0x${string}`;\n telemetry.emit(\"sdk.createDeposit.start\", {\n platform: platformId,\n currency: currencyCode,\n amount,\n wallet: walletAddress,\n });\n\n const amt = parseFloat(amount);\n if (!Number.isFinite(amt) || amt < MIN_DEPOSIT_USDC) {\n throw new OfframpError(`Minimum deposit is ${MIN_DEPOSIT_USDC} USDC`, \"VALIDATION\");\n }\n\n if (!platform.currencies.includes(currencyCode)) {\n throw new OfframpError(`${currencyCode} is not supported on ${platform.name}`, \"UNSUPPORTED\");\n }\n\n const validation = platform.validate(identifier);\n if (!validation.valid) {\n throw new OfframpError(validation.error || \"Invalid identifier\", \"VALIDATION\");\n }\n const normalizedIdentifier = validation.normalized;\n\n const paymentMethodEntries = getPaymentMethodCreateEntries(platformId);\n if (paymentMethodEntries.length === 0) {\n throw new OfframpError(`${platform.name} is not currently supported`, \"UNSUPPORTED\");\n }\n\n // 2. Check for existing undelegated deposit (resume path)\n const existing = await findUndelegatedDeposit(walletAddress);\n if (existing) {\n emitProgress({ step: \"resuming\", depositId: existing.depositId });\n\n const client = createSdkClient(walletClient, resolvedApiBaseUrl);\n const txOverrides = { referrer: [REFERRER] };\n\n try {\n const result = await client.setRateManager({\n depositId: BigInt(existing.depositId),\n rateManagerAddress: RATE_MANAGER_REGISTRY_ADDRESS,\n rateManagerId: DELEGATE_RATE_MANAGER_ID,\n escrowAddress: existing.escrowAddress as `0x${string}`,\n txOverrides,\n });\n const txHash = extractTxHash(result);\n emitProgress({ step: \"done\", txHash, depositId: existing.depositId });\n const resumedResult = { depositId: existing.depositId, txHash, resumed: true };\n telemetry.emit(\"sdk.createDeposit.success\", {\n depositId: resumedResult.depositId,\n txHash: resumedResult.txHash,\n wallet: walletAddress,\n resumed: true,\n wallDurationMs: Date.now() - flowStartMs,\n });\n return resumedResult;\n } catch (err) {\n if (isUserCancellation(err))\n throw new OfframpError(\"User cancelled\", \"USER_CANCELLED\", \"resuming\", err);\n throw new OfframpError(\n \"Found undelegated deposit but delegation failed. Try again.\",\n \"DELEGATION_FAILED\",\n \"resuming\",\n err,\n { depositId: existing.depositId, txHash: existing.txHash },\n );\n }\n }\n\n // 3. Full flow — no existing deposit to resume\n const truncatedAmount = amt.toFixed(6).replace(/\\.?0+$/, \"\");\n const amountUnits = usdcToUnits(truncatedAmount);\n const minUnits = usdcToUnits(String(MIN_ORDER_USDC));\n const maxUnits = usdcToUnits(String(Math.min(amt, MAX_ORDER_USDC)));\n\n // Pre-flight balance check\n try {\n const publicClient = createPublicClient({ chain: base, transport: http(BASE_RPC_URL) });\n const balance = await publicClient.readContract({\n address: USDC_ADDRESS,\n abi: [\n {\n name: \"balanceOf\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"account\", type: \"address\" }],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n ] as const,\n functionName: \"balanceOf\",\n args: [walletAddress],\n });\n if (balance < amountUnits) {\n const available = Number(formatUnits(balance, 6));\n throw new OfframpError(\n `Insufficient USDC balance. Have ${available.toFixed(2)}, need ${truncatedAmount}.`,\n \"VALIDATION\",\n );\n }\n } catch (err) {\n if (err instanceof OfframpError) throw err;\n }\n\n // All Zelle variants register under the base \"zelle\" processor.\n const canonicalName = platformId.startsWith(\"zelle\") ? \"zelle\" : platformId;\n\n // Fail fast on a bad/nonexistent handle BEFORE the maker approves USDC and\n // pays deposit gas. Skipped for extension-gated platforms (PayPal, Wise):\n // their validate path doesn't assert Peer-extension registration, and\n // `/v2/makers/create` already owns the EXTENSION_REGISTRATION_REQUIRED\n // recovery flow, so a pre-check there would add no signal and risk masking\n // it. For every other platform this catches typo'd IBANs, non-existent\n // Venmo/Revolut handles, etc. that curator would reject after gas is spent.\n if (!getPeerExtensionRegistrationInfo(platformId)) {\n const outcome = await validatePayeeDetails(\n canonicalName,\n normalizedIdentifier,\n resolvedApiBaseUrl,\n );\n if (outcome === \"invalid\") {\n throw new OfframpError(\n `Couldn't verify that ${platform.name} ${platform.identifier.label.toLowerCase()}. Double-check it and try again.`,\n \"VALIDATION\",\n \"registering\",\n );\n }\n }\n\n const client = createSdkClient(walletClient, resolvedApiBaseUrl);\n const txOverrides = { referrer: [REFERRER] };\n\n // Approve\n emitProgress({ step: \"approving\" });\n try {\n await client.ensureAllowance({\n token: USDC_ADDRESS,\n amount: amountUnits,\n escrowAddress: ESCROW_ADDRESS,\n maxApprove: false,\n txOverrides,\n });\n } catch (err) {\n if (isUserCancellation(err))\n throw new OfframpError(\"User cancelled\", \"USER_CANCELLED\", \"approving\", err);\n const detail = err instanceof Error ? err.message : String(err);\n throw new OfframpError(\n `USDC approval failed: ${detail}`,\n \"APPROVAL_FAILED\",\n \"approving\",\n err,\n );\n }\n\n // Register payee\n emitProgress({ step: \"registering\" });\n let hashedOnchainId: string;\n try {\n const payeePayload = buildDepositData(canonicalName, normalizedIdentifier);\n hashedOnchainId = await postMakerCreate(canonicalName, payeePayload, resolvedApiBaseUrl);\n } catch (err) {\n // Curator requires SAR-capable makers to register their handle in the\n // Peer extension first. A 400 or \"creating the maker\" message on those\n // platforms means the integrator needs to launch the headless Peer\n // metadata-capture flow before retrying.\n const status = err instanceof MakersCreateError ? err.status : null;\n const message = err instanceof Error ? err.message : String(err);\n if (isPeerExtensionRegistrationError(canonicalName, message, status)) {\n throw new OfframpError(\n `${platform.name} maker is not yet registered in the Peer extension. Register this handle with Peer, then retry.`,\n \"EXTENSION_REGISTRATION_REQUIRED\",\n \"registering\",\n err,\n );\n }\n throw new OfframpError(\n \"Payee registration failed\",\n \"REGISTRATION_FAILED\",\n \"registering\",\n err,\n );\n }\n\n // Create deposit\n emitProgress({ step: \"depositing\" });\n\n const conversionRates: Array<Array<{ currency: CurrencyType; conversionRate: string }>> =\n paymentMethodEntries.map(() => [\n { currency: currencyCode as CurrencyType, conversionRate: \"1\" },\n ]);\n\n const baseCurrenciesOverride = mapConversionRatesToOnchainMinRate(\n conversionRates,\n paymentMethodEntries.length,\n );\n const currenciesOverride = attachOracleConfig(baseCurrenciesOverride, conversionRates);\n const paymentMethodHashes = paymentMethodEntries.map((entry) => entry.hash);\n const payeeDetailsHashes = paymentMethodEntries.map(() => hashedOnchainId);\n\n let hash: `0x${string}`;\n try {\n const result = await client.createDeposit({\n token: USDC_ADDRESS,\n amount: amountUnits,\n retainOnEmpty: false,\n intentAmountRange: { min: minUnits, max: maxUnits },\n processorNames: paymentMethodEntries.map((entry) => entry.name),\n conversionRates,\n payeeDetailsHashes,\n paymentMethodsOverride: paymentMethodHashes,\n paymentMethodDataOverride: payeeDetailsHashes.map((payeeDetails) => ({\n intentGatingService: GATING_SERVICE_ADDRESS,\n payeeDetails: payeeDetails as `0x${string}`,\n data: \"0x\" as `0x${string}`,\n })),\n currenciesOverride,\n intentGuardian: DEFAULT_INTENT_GUARDIAN_ADDRESS,\n escrowAddress: ESCROW_ADDRESS,\n txOverrides,\n });\n if (!result?.hash) throw new Error(\"No transaction hash returned\");\n hash = result.hash;\n } catch (err) {\n if (isUserCancellation(err))\n throw new OfframpError(\"User cancelled\", \"USER_CANCELLED\", \"depositing\", err);\n const detail = err instanceof Error ? err.message : String(err);\n throw new OfframpError(\n `Deposit transaction failed: ${detail}`,\n \"DEPOSIT_FAILED\",\n \"depositing\",\n err,\n );\n }\n\n // Confirm\n emitProgress({ step: \"confirming\", txHash: hash });\n let depositId = \"\";\n\n const receiptClient = client as {\n waitForTransactionReceipt?: (p: {\n hash: `0x${string}`;\n confirmations?: number;\n }) => Promise<{ logs: Array<{ topics?: Hex[]; data?: Hex }> }>;\n };\n if (typeof receiptClient.waitForTransactionReceipt === \"function\") {\n try {\n const receipt = await receiptClient.waitForTransactionReceipt({ hash, confirmations: 1 });\n depositId = extractDepositIdFromLogs(receipt.logs) || \"\";\n } catch {\n /* fall through to indexer */\n }\n }\n\n if (!depositId) {\n let delay = INDEXER_INITIAL_DELAY_MS;\n for (let attempt = 0; attempt < INDEXER_MAX_ATTEMPTS && !depositId; attempt++) {\n try {\n const deps = (await client.indexer.getDepositsWithRelations(\n { depositor: walletAddress },\n { limit: 25 },\n )) as Array<{ txHash?: string; depositId: string }>;\n const hit = deps.find((d) => (d?.txHash || \"\").toLowerCase() === hash.toLowerCase());\n if (hit) {\n depositId = String(hit.depositId);\n break;\n }\n } catch {\n /* continue */\n }\n await new Promise((r) => setTimeout(r, delay));\n delay = Math.min(INDEXER_MAX_DELAY_MS, Math.floor(delay * 1.7));\n }\n }\n\n if (!depositId) {\n throw new OfframpError(\n \"Deposit created on-chain but could not confirm deposit ID. Your funds are safe. Call offramp() again to resume delegation.\",\n \"CONFIRMATION_FAILED\",\n \"confirming\",\n undefined,\n { txHash: hash },\n );\n }\n\n // Delegate\n emitProgress({ step: \"delegating\", txHash: hash, depositId });\n try {\n await client.setRateManager({\n depositId: BigInt(depositId),\n rateManagerAddress: RATE_MANAGER_REGISTRY_ADDRESS,\n rateManagerId: DELEGATE_RATE_MANAGER_ID,\n escrowAddress: ESCROW_ADDRESS,\n txOverrides,\n });\n } catch (delegationError) {\n if (isUserCancellation(delegationError)) {\n throw new OfframpError(\n \"User cancelled delegation\",\n \"USER_CANCELLED\",\n \"delegating\",\n delegationError,\n { txHash: hash, depositId },\n );\n }\n throw new OfframpError(\n \"Deposit created but delegation failed. Call offramp() again to resume delegation.\",\n \"DELEGATION_FAILED\",\n \"delegating\",\n delegationError,\n { txHash: hash, depositId },\n );\n }\n\n // OTC restriction (optional)\n let otcLink: string | undefined;\n if (params.otcTaker) {\n emitProgress({ step: \"restricting\", txHash: hash, depositId });\n try {\n const otcResult = await enableOtc(walletClient, depositId, params.otcTaker);\n otcLink = otcResult.otcLink;\n } catch (otcError) {\n if (isUserCancellation(otcError)) {\n throw new OfframpError(\n \"User cancelled OTC restriction\",\n \"USER_CANCELLED\",\n \"restricting\",\n otcError,\n {\n txHash: hash,\n depositId,\n },\n );\n }\n throw new OfframpError(\n \"Deposit created and delegated but OTC restriction failed. Use enableOtc() to retry.\",\n \"DEPOSIT_FAILED\",\n \"restricting\",\n otcError,\n { txHash: hash, depositId },\n );\n }\n }\n\n emitProgress({ step: \"done\", txHash: hash, depositId });\n const result = { depositId, txHash: hash, resumed: false, otcLink };\n telemetry.emit(\"sdk.createDeposit.success\", {\n depositId: result.depositId,\n txHash: result.txHash,\n wallet: walletAddress,\n resumed: false,\n wallDurationMs: Date.now() - flowStartMs,\n });\n return result;\n } catch (error) {\n const known = error instanceof OfframpError ? error : null;\n telemetry.emit(\"sdk.createDeposit.error\", {\n code: known?.code ?? \"DEPOSIT_FAILED\",\n step: known?.step ?? \"unknown\",\n });\n throw error;\n }\n}\n","import { currencyInfo } from \"@zkp2p/sdk\";\n\nexport interface CurrencyEntry {\n readonly code: string;\n readonly name: string;\n readonly symbol: string;\n readonly countryCode: string;\n}\n\ntype CurrencyMap = { readonly [K in keyof typeof currencyInfo]: CurrencyEntry };\n\nfunction buildCurrencies(): CurrencyMap {\n const entries: Record<string, CurrencyEntry> = {};\n for (const [code, info] of Object.entries(\n currencyInfo as Record<\n string,\n {\n currencyCode?: string;\n currencyName?: string;\n currencySymbol?: string;\n countryCode?: string;\n }\n >,\n )) {\n entries[code] = {\n code: info.currencyCode ?? code,\n name: info.currencyName ?? code,\n symbol: info.currencySymbol ?? code,\n countryCode: info.countryCode ?? \"\",\n };\n }\n return entries as CurrencyMap;\n}\n\n/** All supported currencies with metadata. Access via `CURRENCIES.EUR.symbol` etc. */\nexport const CURRENCIES = buildCurrencies();\n","import type { WalletClient } from \"viem\";\n\nimport {\n DELEGATE_RATE_MANAGER_ID,\n DELEGATE_MANAGER_FEE_BPS,\n ESCROW_ADDRESS,\n RATE_MANAGER_REGISTRY_ADDRESS,\n SDK_VERSION,\n} from \"./config\";\nimport { CURRENCIES, type CurrencyEntry } from \"./currencies\";\nimport { offramp as createDepositFlow } from \"./deposit\";\nimport { OfframpError } from \"./errors\";\nimport { PLATFORMS, type PlatformEntry } from \"./platforms\";\nimport { createTelemetryContext, sanitizeAttributionId, type TelemetryContext } from \"./telemetry\";\nimport type {\n OfframpCreateOptions,\n OfframpParams,\n OfframpQuote,\n OfframpQuoteInput,\n OfframpResult,\n OfframpVaultStatus,\n OnProgress,\n} from \"./types\";\n\nconst IDEMPOTENCY_TTL_MS = 10 * 60 * 1000;\nconst IDEMPOTENCY_STORAGE_PREFIX = \"offramp:idempotency:\";\n\ninterface IdempotencyRecord {\n result: OfframpResult;\n expiresAt: number;\n}\n\n// The idempotency cache is backed by `sessionStorage`, so it is a no-op in\n// Node/worker runtimes. Warn server-side integrators exactly once per process\n// the first time they pass an `idempotencyKey` without a backing store, so they\n// learn at runtime instead of via duplicate deposits.\nlet warnedIdempotencyUnavailable = false;\n\nfunction warnIdempotencyUnavailableOnce(): void {\n if (warnedIdempotencyUnavailable) return;\n warnedIdempotencyUnavailable = true;\n console.warn(\n \"[offramp] idempotencyKey was provided but sessionStorage is unavailable \" +\n \"(Node/worker runtime). The idempotency cache is browser-only and no-ops here, \" +\n \"so retries can create duplicate deposits. For server-side dedup, call \" +\n \"deposits(walletAddress) and reuse an existing open deposit before creating one.\",\n );\n}\n\nfunction getWalletAddress(walletClient: WalletClient): string {\n const address = walletClient.account?.address;\n if (!address) {\n throw new OfframpError(\"Wallet client has no account. Connect a wallet first.\", \"VALIDATION\");\n }\n return address.toLowerCase();\n}\n\nfunction getIdempotencyStorageKey(walletAddress: string, idempotencyKey: string): string {\n return `${IDEMPOTENCY_STORAGE_PREFIX}${walletAddress}:${idempotencyKey}`;\n}\n\nfunction readIdempotencyResult(storageKey: string): OfframpResult | null {\n if (typeof sessionStorage === \"undefined\") return null;\n try {\n const raw = sessionStorage.getItem(storageKey);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as Partial<IdempotencyRecord>;\n const expiresAt =\n typeof parsed.expiresAt === \"number\" && Number.isFinite(parsed.expiresAt)\n ? parsed.expiresAt\n : 0;\n if (expiresAt <= Date.now()) {\n sessionStorage.removeItem(storageKey);\n return null;\n }\n const result = parsed.result;\n if (!result?.depositId || !result.txHash) {\n sessionStorage.removeItem(storageKey);\n return null;\n }\n return result;\n } catch {\n return null;\n }\n}\n\nfunction writeIdempotencyResult(storageKey: string, result: OfframpResult): void {\n if (typeof sessionStorage === \"undefined\") return;\n try {\n const record: IdempotencyRecord = {\n result,\n expiresAt: Date.now() + IDEMPOTENCY_TTL_MS,\n };\n sessionStorage.setItem(storageKey, JSON.stringify(record));\n } catch {\n // noop\n }\n}\n\nfunction createPerFlowTelemetry(\n base: TelemetryContext,\n integratorId?: string,\n referralId?: string,\n): TelemetryContext {\n return createTelemetryContext({\n sdkVersion: base.sdkVersion,\n telemetry: base.enabled,\n integratorId: sanitizeAttributionId(integratorId) ?? base.integratorId,\n referralId: sanitizeAttributionId(referralId) ?? base.referralId,\n });\n}\n\nfunction normalizeCurrencyEntry(code: string): CurrencyEntry {\n const fromCatalog = CURRENCIES[code as keyof typeof CURRENCIES];\n if (fromCatalog) return fromCatalog;\n return {\n code,\n name: code,\n symbol: code,\n countryCode: \"\",\n };\n}\n\nfunction buildCurrencyGroups(): Record<PlatformEntry[\"id\"], CurrencyEntry[]> {\n const grouped = {} as Record<PlatformEntry[\"id\"], CurrencyEntry[]>;\n for (const platform of Object.values(PLATFORMS)) {\n grouped[platform.id] = platform.currencies.map(normalizeCurrencyEntry);\n }\n return grouped;\n}\n\nexport interface OfframpConstructorOptions extends OfframpCreateOptions {\n walletClient: WalletClient;\n}\n\nexport class Offramp {\n private readonly walletClient: WalletClient;\n private readonly telemetry: TelemetryContext;\n private readonly apiBaseUrl?: string;\n\n constructor(options: OfframpConstructorOptions) {\n this.walletClient = options.walletClient;\n this.apiBaseUrl = options.apiBaseUrl;\n this.telemetry = createTelemetryContext({\n sdkVersion: SDK_VERSION,\n telemetry: options.telemetry,\n integratorId: options.integratorId,\n referralId: options.referralId,\n });\n\n this.telemetry.emit(\"sdk.init\", {\n userAgent: typeof navigator !== \"undefined\" ? navigator.userAgent : \"unknown\",\n });\n }\n\n async createDeposit(params: OfframpParams, onProgress?: OnProgress): Promise<OfframpResult> {\n const flowTelemetry = createPerFlowTelemetry(\n this.telemetry,\n params.integratorId,\n params.referralId,\n );\n const sanitizedParams: OfframpParams = {\n ...params,\n integratorId: flowTelemetry.integratorId,\n referralId: flowTelemetry.referralId,\n };\n\n const sanitizedKey = sanitizeAttributionId(params.idempotencyKey);\n if (sanitizedKey && typeof sessionStorage === \"undefined\") {\n warnIdempotencyUnavailableOnce();\n }\n const walletAddress = sanitizedKey ? getWalletAddress(this.walletClient) : null;\n const storageKey =\n walletAddress && sanitizedKey ? getIdempotencyStorageKey(walletAddress, sanitizedKey) : null;\n\n if (storageKey) {\n const existing = readIdempotencyResult(storageKey);\n if (existing) return existing;\n }\n\n const result = await createDepositFlow(\n this.walletClient,\n sanitizedParams,\n onProgress,\n flowTelemetry,\n this.apiBaseUrl,\n );\n\n if (storageKey) {\n writeIdempotencyResult(storageKey, result);\n }\n return result;\n }\n\n getQuote(input: OfframpQuoteInput): OfframpQuote {\n const amountUsdc = Number(input.amount);\n if (!Number.isFinite(amountUsdc) || amountUsdc <= 0) {\n throw new OfframpError(\"Amount must be a positive number\", \"VALIDATION\");\n }\n if (!input.platform.currencies.includes(input.currency.code)) {\n throw new OfframpError(\n `${input.currency.code} is not supported on ${input.platform.name}`,\n \"UNSUPPORTED\",\n );\n }\n\n const vaultSpreadBps = 0;\n const spreadFactor = Math.max(0, 1 - vaultSpreadBps / 10_000);\n const expectedFiat = amountUsdc * spreadFactor;\n const effectiveRate = amountUsdc === 0 ? 0 : expectedFiat / amountUsdc;\n\n return {\n amountUsdc,\n expectedFiat,\n effectiveRate,\n vaultSpreadBps,\n };\n }\n\n getVaultStatus(): OfframpVaultStatus {\n return {\n rateManagerId: DELEGATE_RATE_MANAGER_ID,\n rateManagerAddress: RATE_MANAGER_REGISTRY_ADDRESS,\n feeRateBps: DELEGATE_MANAGER_FEE_BPS,\n escrow: ESCROW_ADDRESS,\n isActive: true,\n };\n }\n\n listCurrencies(): Record<PlatformEntry[\"id\"], CurrencyEntry[]> {\n return buildCurrencyGroups();\n }\n}\n\nexport function createOfframp(options: OfframpConstructorOptions): Offramp {\n return new Offramp(options);\n}\n","/**\n * Peer browser-extension surface for SAR-capable makers. Drive the\n * headless metadata bridge via `usePeerExtensionRegistration` in\n * `@usdctofiat/offramp/react`, or manually:\n *\n * ```ts\n * import {\n * completePeerExtensionRegistration,\n * isPeerExtensionMetadataBridgeAvailable,\n * peerExtensionSdk,\n * } from \"@usdctofiat/offramp\";\n *\n * const state = await peerExtensionSdk.getState();\n * if (state === \"needs_install\" || !isPeerExtensionMetadataBridgeAvailable()) {\n * peerExtensionSdk.openInstallPage();\n * } else if (state === \"needs_connection\") {\n * await peerExtensionSdk.requestConnection();\n * } else {\n * peerExtensionSdk.authenticate({\n * actionType: \"transfer_paypal\",\n * captureMode: \"sellerCredential\",\n * platform: \"paypal\",\n * });\n * // Pass the captured metadata to completePeerExtensionRegistration(...), then retry.\n * }\n * ```\n */\nimport {\n PEER_EXTENSION_CHROME_URL,\n createPeerExtensionSdk as createSdkPeerExtensionSdk,\n} from \"@zkp2p/sdk\";\nimport type {\n PeerAuthenticateParams,\n PeerBuyerTeePaymentCapture,\n PeerBuyerTeePaymentParams,\n PeerConnectionStatus,\n PeerExtensionSdkOptions as SdkPeerExtensionSdkOptions,\n PeerMetadataCaptureMode,\n PeerMetadataMessage,\n PeerMetadataMessageCallback,\n PeerMetadataProviderConfig,\n PeerMetadataRow,\n PeerSarCredentialCapture,\n SellerCredentialBundle,\n} from \"@zkp2p/sdk\";\n\nexport { PEER_EXTENSION_CHROME_URL };\nexport type {\n PeerAuthenticateParams,\n PeerBuyerTeePaymentCapture,\n PeerBuyerTeePaymentParams,\n PeerConnectionStatus,\n PeerMetadataCaptureMode,\n PeerMetadataMessage,\n PeerMetadataMessageCallback,\n PeerMetadataProviderConfig,\n PeerMetadataRow,\n PeerSarCredentialCapture,\n};\n\nexport type PeerSarCredentialBundle = SellerCredentialBundle;\n\nexport type PeerExtensionApi = {\n requestConnection(): Promise<boolean>;\n checkConnectionStatus(): Promise<PeerConnectionStatus>;\n getVersion(): Promise<string>;\n authenticate?: (params: PeerAuthenticateParams) => void;\n onMetadataMessage?: (callback: PeerMetadataMessageCallback) => () => void;\n};\n\nexport type PeerExtensionWindow = Window & {\n peer?: PeerExtensionApi;\n};\n\nexport type PeerExtensionSdkOptions = {\n window?: PeerExtensionWindow;\n /**\n * Chrome Web Store listing opened by `openInstallPage()`. Defaults to the\n * USDCtoFiat Verify listing; pass `PEER_EXTENSION_CHROME_URL` (re-exported\n * from `@zkp2p/sdk`) to target the legacy PeerAuth listing, or any custom\n * branded-extension listing.\n */\n installUrl?: string;\n};\n\n/**\n * Default install target: the USDCtoFiat Verify extension (branded fork of\n * PeerAuth implementing the same window.peer interface).\n */\nexport const DEFAULT_EXTENSION_INSTALL_URL =\n \"https://chromewebstore.google.com/detail/usdctofiat-verify/lfkmdfifolhcfjmhklmckigfngghmpdf\";\n\nexport type PeerExtensionSdk = {\n requestConnection(): Promise<boolean>;\n checkConnectionStatus(): Promise<PeerConnectionStatus>;\n getVersion(): Promise<string>;\n authenticate(params: PeerAuthenticateParams): void;\n onMetadataMessage(callback: PeerMetadataMessageCallback): () => void;\n isAvailable(): boolean;\n openInstallPage(): void;\n getState(): Promise<PeerExtensionState>;\n};\n\nexport type PeerExtensionState = \"needs_install\" | \"needs_connection\" | \"ready\";\n\nconst resolveWindow = (options?: PeerExtensionSdkOptions): PeerExtensionWindow | undefined => {\n if (options?.window) {\n return options.window;\n }\n\n if (typeof window === \"undefined\") {\n return undefined;\n }\n\n return window as PeerExtensionWindow;\n};\n\nconst requirePeer = (options?: PeerExtensionSdkOptions): PeerExtensionApi => {\n const resolvedWindow = resolveWindow(options);\n if (!resolvedWindow) {\n throw new Error(\"Peer extension SDK requires a browser window.\");\n }\n\n if (!resolvedWindow.peer) {\n throw new Error(\"Peer extension not available. Install or enable the Peer extension.\");\n }\n\n return resolvedWindow.peer;\n};\n\nexport const isPeerExtensionAvailable = (options?: PeerExtensionSdkOptions): boolean => {\n const resolvedWindow = resolveWindow(options);\n return Boolean(resolvedWindow?.peer);\n};\n\nconst hasHeadlessMetadataBridge = (peer: PeerExtensionApi): boolean =>\n typeof peer.authenticate === \"function\" && typeof peer.onMetadataMessage === \"function\";\n\nconst requirePeerMetadataBridge = (\n options?: PeerExtensionSdkOptions,\n): PeerExtensionApi & Required<Pick<PeerExtensionApi, \"authenticate\" | \"onMetadataMessage\">> => {\n const peer = requirePeer(options);\n if (!hasHeadlessMetadataBridge(peer)) {\n throw new Error(\"Peer extension metadata bridge unavailable. Install or update Peer.\");\n }\n return peer as PeerExtensionApi &\n Required<Pick<PeerExtensionApi, \"authenticate\" | \"onMetadataMessage\">>;\n};\n\nexport const isPeerExtensionMetadataBridgeAvailable = (\n options?: PeerExtensionSdkOptions,\n): boolean => {\n const resolvedWindow = resolveWindow(options);\n return Boolean(resolvedWindow?.peer && hasHeadlessMetadataBridge(resolvedWindow.peer));\n};\n\nexport const openPeerExtensionInstallPage = (options?: PeerExtensionSdkOptions): void => {\n const resolvedWindow = resolveWindow(options);\n if (!resolvedWindow) {\n throw new Error(\"Peer extension SDK requires a browser window.\");\n }\n\n const installUrl = options?.installUrl ?? DEFAULT_EXTENSION_INSTALL_URL;\n resolvedWindow.open(installUrl, \"_blank\", \"noopener,noreferrer\");\n};\n\nexport const getPeerExtensionState = async (\n options?: PeerExtensionSdkOptions,\n): Promise<PeerExtensionState> => {\n if (!isPeerExtensionAvailable(options)) {\n return \"needs_install\";\n }\n\n try {\n const status = await requirePeer(options).checkConnectionStatus();\n return status === \"connected\" ? \"ready\" : \"needs_connection\";\n } catch {\n return \"needs_connection\";\n }\n};\n\nexport const createPeerExtensionSdk = (options: PeerExtensionSdkOptions = {}): PeerExtensionSdk => {\n const sdk = createSdkPeerExtensionSdk(options as unknown as SdkPeerExtensionSdkOptions);\n\n return {\n isAvailable: () => isPeerExtensionAvailable(options),\n requestConnection: () => requirePeer(options).requestConnection(),\n checkConnectionStatus: () => requirePeer(options).checkConnectionStatus(),\n getVersion: () => requirePeer(options).getVersion(),\n authenticate: (params: PeerAuthenticateParams) =>\n requirePeerMetadataBridge(options).authenticate(params),\n onMetadataMessage: (callback: PeerMetadataMessageCallback) =>\n requirePeerMetadataBridge(options).onMetadataMessage(callback),\n openInstallPage: () => openPeerExtensionInstallPage(options),\n getState: () => sdk.getState(),\n };\n};\n\nexport const peerExtensionSdk = createPeerExtensionSdk();\n"],"mappings":"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","names":["createPublicClient","http","base","getCurrencyInfoFromHash","getCurrencyInfoFromHash","base","createPublicClient","http","createPublicClient","formatUnits","http","base","extractTxHash","client","txOverrides","result","createPublicClient","base","http","formatUnits","currencyInfo","base"]}