@usdctofiat/offramp 0.1.4 → 0.2.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/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # @usdctofiat/offramp
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@usdctofiat/offramp?color=8fb47d)](https://www.npmjs.com/package/@usdctofiat/offramp)
4
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/ADWilkinson/galleonlabs-zkp2p/blob/main/packages/offramp-sdk/LICENSE)
5
+
3
6
  USDC-to-fiat offramp SDK for Base. Create and manage delegated deposits in one function call.
4
7
 
5
8
  ## Install
@@ -11,14 +14,14 @@ npm install @usdctofiat/offramp
11
14
  ## Quick Start
12
15
 
13
16
  ```typescript
14
- import { Offramp } from "@usdctofiat/offramp";
17
+ import { Offramp, PAYMENT_PLATFORMS, CURRENCIES } from "@usdctofiat/offramp";
15
18
 
16
19
  const offramp = new Offramp();
17
20
 
18
21
  const result = await offramp.createDeposit(walletClient, {
19
22
  amount: "100",
20
- platform: "revolut",
21
- currency: "EUR",
23
+ platform: PAYMENT_PLATFORMS.REVOLUT,
24
+ currency: CURRENCIES.EUR,
22
25
  identifier: "alice",
23
26
  });
24
27
 
@@ -75,13 +78,25 @@ await offramp.createDeposit(walletClient, params, (progress) => {
75
78
  ## Discovery & Validation
76
79
 
77
80
  ```typescript
81
+ import { PAYMENT_PLATFORMS, CURRENCIES } from "@usdctofiat/offramp";
82
+
83
+ // Platforms with currencies, labels, and format requirements
78
84
  offramp.getPlatforms();
79
- // [{ id: "revolut", name: "Revolut", currencies: [...], identifierLabel, identifierPlaceholder, helperText }]
85
+ // [{ id: "revolut", name: "Revolut", currencies: ["USD","EUR",...], identifierLabel: "Revtag", helperText: "Revtag without @", ... }]
80
86
 
81
- offramp.getCurrencies("wise");
87
+ // Currencies for a platform
88
+ offramp.getCurrencies(PAYMENT_PLATFORMS.WISE);
82
89
  // ["USD", "EUR", "GBP", "AUD", ...]
83
90
 
84
- offramp.validateIdentifier("revolut", "@alice");
91
+ // Currency metadata for UI rendering
92
+ offramp.getCurrencyInfo(CURRENCIES.EUR);
93
+ // { code: "EUR", name: "Euro", symbol: "€", countryCode: "eu" }
94
+
95
+ offramp.getAllCurrencies();
96
+ // [{ code: "AED", name: "UAE Dirham", symbol: "د.إ", countryCode: "ae" }, ...]
97
+
98
+ // Validate and normalize identifiers (strips @, $, validates format)
99
+ offramp.validateIdentifier(PAYMENT_PLATFORMS.REVOLUT, "@alice");
85
100
  // { valid: true, normalized: "alice" }
86
101
  ```
87
102
 
@@ -131,3 +146,9 @@ Every deposit created through this SDK is automatically:
131
146
  - Base network (chain ID 8453)
132
147
  - viem `WalletClient` with an account
133
148
  - USDC balance on Base
149
+
150
+ ## Links
151
+
152
+ [usdctofiat.xyz](https://usdctofiat.xyz) · [delegate.usdctofiat.xyz](https://delegate.usdctofiat.xyz) · [peerlytics.xyz](https://peerlytics.xyz) · [orderbook.peerlytics.xyz](https://orderbook.peerlytics.xyz)
153
+
154
+ [Examples & agent skills](https://github.com/ADWilkinson/usdctofiat-peerlytics-starters) · [@usdctofiat](https://x.com/usdctofiat) · [@davyjones0x](https://x.com/davyjones0x)
@@ -131,7 +131,7 @@ function isUserCancellation(error) {
131
131
 
132
132
  // src/client.ts
133
133
  import { formatUnits as formatUnits2 } from "viem";
134
- import { classifyDelegationState, currencyInfo as currencyInfo2, getCurrencyInfoFromHash as getCurrencyInfoFromHash2 } from "@zkp2p/sdk";
134
+ import { classifyDelegationState, currencyInfo as currencyInfo2, getCurrencyInfoFromHash as getCurrencyInfoFromHash2, IndexerClient, IndexerDepositService } from "@zkp2p/sdk";
135
135
 
136
136
  // src/deposit.ts
137
137
  import { createPublicClient, decodeEventLog, formatUnits, http, parseUnits } from "viem";
@@ -662,6 +662,14 @@ async function createOfframpDeposit(walletClient, params, onProgress) {
662
662
  }
663
663
 
664
664
  // src/client.ts
665
+ var indexerClient = null;
666
+ function getIndexerService() {
667
+ if (!indexerClient) {
668
+ const client = new IndexerClient(`${API_BASE_URL.replace(/\/+$/, "")}`);
669
+ indexerClient = new IndexerDepositService(client);
670
+ }
671
+ return indexerClient;
672
+ }
665
673
  function toBigInt(value) {
666
674
  try {
667
675
  return BigInt(value || "0");
@@ -681,7 +689,7 @@ function resolveMethodNames(hashes) {
681
689
  const names = /* @__PURE__ */ new Set();
682
690
  for (const { paymentMethodHash } of hashes) {
683
691
  const normalized = paymentMethodHash.toLowerCase();
684
- for (const platform of ["venmo", "cashapp", "chime", "revolut", "wise", "mercadopago", "zelle", "paypal", "monzo", "n26"]) {
692
+ for (const platform of PLATFORMS) {
685
693
  const platformHashes = getPaymentMethodHashes(platform);
686
694
  if (platformHashes.some((h) => h.toLowerCase() === normalized)) {
687
695
  names.add(getPlatformConfig(platform).name);
@@ -691,60 +699,104 @@ function resolveMethodNames(hashes) {
691
699
  }
692
700
  return Array.from(names);
693
701
  }
702
+ function mapDeposit(d) {
703
+ const delegationState = classifyDelegationState(
704
+ d.rateManagerId ?? void 0,
705
+ d.rateManagerAddress ?? void 0,
706
+ DELEGATE_RATE_MANAGER_ID,
707
+ RATE_MANAGER_REGISTRY_ADDRESS
708
+ );
709
+ return {
710
+ depositId: d.depositId,
711
+ compositeId: d.id,
712
+ txHash: d.txHash,
713
+ status: resolveStatus(d),
714
+ remainingUsdc: toUsdc(d.remainingDeposits),
715
+ outstandingUsdc: toUsdc(d.outstandingIntentAmount),
716
+ totalTakenUsdc: toUsdc(d.totalAmountTaken),
717
+ fulfilledIntents: d.fulfilledIntents ?? 0,
718
+ paymentMethods: resolveMethodNames(d.paymentMethods),
719
+ currencies: d.currencies.map((c) => {
720
+ const info = getCurrencyInfoFromHash2(c.currencyCode);
721
+ return info?.currencyCode ?? c.currencyCode;
722
+ }),
723
+ rateSource: d.currencies[0]?.rateSource || "unknown",
724
+ delegated: delegationState === "delegated_here",
725
+ escrowAddress: d.escrowAddress
726
+ };
727
+ }
728
+ function extractTxHash(result) {
729
+ if (typeof result === "string") return result;
730
+ if (result && typeof result === "object" && "hash" in result) return result.hash;
731
+ if (result && typeof result === "object" && "transactionHash" in result) return result.transactionHash;
732
+ throw new Error("Unexpected transaction result format");
733
+ }
694
734
  var Offramp = class {
695
735
  /**
696
736
  * Create an offramp deposit: approve USDC, register payee, create deposit,
697
737
  * confirm on-chain, and delegate to the vault. All in one call.
738
+ *
739
+ * @param walletClient - viem WalletClient with an account
740
+ * @param params - Deposit parameters (amount, platform, currency, identifier)
741
+ * @param onProgress - Optional callback for step-by-step progress updates
698
742
  */
699
743
  async createDeposit(walletClient, params, onProgress) {
700
744
  return createOfframpDeposit(walletClient, params, onProgress);
701
745
  }
702
746
  /**
703
- * Fetch deposits for a wallet address. Returns active, empty, and closed deposits
704
- * sorted by status (active first) then recency.
747
+ * Fetch all deposits for a wallet address. Read-only, no wallet needed.
748
+ * Returns active, empty, and closed deposits sorted by status then recency.
705
749
  */
706
750
  async getDeposits(walletAddress) {
707
- const client = createSdkClient(
708
- // Read-only client -- no wallet needed for indexer queries
709
- { account: void 0, chain: void 0, transport: void 0 }
710
- );
711
- const raw = await client.indexer.getDepositsWithRelations(
751
+ const service = getIndexerService();
752
+ const raw = await service.fetchDepositsWithRelations(
712
753
  { depositor: walletAddress },
713
754
  { limit: 100 }
714
755
  );
715
756
  const statusOrder = { active: 0, empty: 1, closed: 2 };
716
- return (raw || []).map((d) => {
717
- const delegationState = classifyDelegationState(
718
- d.rateManagerId ?? void 0,
719
- d.rateManagerAddress ?? void 0,
720
- DELEGATE_RATE_MANAGER_ID,
721
- RATE_MANAGER_REGISTRY_ADDRESS
722
- );
723
- return {
724
- depositId: d.depositId,
725
- compositeId: d.id,
726
- status: resolveStatus(d),
727
- remainingUsdc: toUsdc(d.remainingDeposits),
728
- outstandingUsdc: toUsdc(d.outstandingIntentAmount),
729
- totalTakenUsdc: toUsdc(d.totalAmountTaken),
730
- fulfilledIntents: d.fulfilledIntents ?? 0,
731
- paymentMethods: resolveMethodNames(d.paymentMethods),
732
- currencies: d.currencies.map((c) => {
733
- const info = getCurrencyInfoFromHash2(c.currencyCode);
734
- return info?.currencyCode ?? c.currencyCode;
735
- }),
736
- rateSource: d.currencies[0]?.rateSource || "unknown",
737
- delegated: delegationState === "delegated_here",
738
- escrowAddress: d.escrowAddress
739
- };
740
- }).sort((a, b) => {
757
+ return (raw || []).map(mapDeposit).sort((a, b) => {
741
758
  const diff = statusOrder[a.status] - statusOrder[b.status];
742
759
  if (diff !== 0) return diff;
743
760
  return Number(BigInt(b.depositId) - BigInt(a.depositId));
744
761
  });
745
762
  }
746
763
  /**
747
- * Withdraw and close a deposit, returning remaining USDC to the wallet.
764
+ * Find a deposit by its transaction hash. Useful for recovering from
765
+ * CONFIRMATION_FAILED errors where you have a txHash but no depositId.
766
+ *
767
+ * @param walletAddress - The depositor's wallet address
768
+ * @param txHash - The transaction hash from createDeposit
769
+ */
770
+ async getDepositByTxHash(walletAddress, txHash) {
771
+ const deposits = await this.getDeposits(walletAddress);
772
+ const normalized = txHash.toLowerCase();
773
+ return deposits.find((d) => d.txHash?.toLowerCase() === normalized) ?? null;
774
+ }
775
+ /**
776
+ * Delegate an existing deposit to the Delegate vault. Use this to:
777
+ * - Retry after a DELEGATION_FAILED error
778
+ * - Delegate a deposit created outside the SDK
779
+ * - Delegate a deposit created via usdctofiat.xyz
780
+ *
781
+ * @param walletClient - viem WalletClient with the deposit owner's account
782
+ * @param depositId - The numeric deposit ID (not the composite escrow_id format)
783
+ */
784
+ async delegateDeposit(walletClient, depositId, escrowAddress) {
785
+ const client = createSdkClient(walletClient);
786
+ const result = await client.setRateManager({
787
+ depositId: BigInt(depositId),
788
+ rateManagerAddress: RATE_MANAGER_REGISTRY_ADDRESS,
789
+ rateManagerId: DELEGATE_RATE_MANAGER_ID,
790
+ escrowAddress: escrowAddress || ESCROW_ADDRESS,
791
+ txOverrides: { referrer: [REFERRER] }
792
+ });
793
+ return extractTxHash(result);
794
+ }
795
+ /**
796
+ * Withdraw remaining USDC and close a deposit.
797
+ *
798
+ * @param walletClient - viem WalletClient with the deposit owner's account
799
+ * @param depositId - The numeric deposit ID (not the composite escrow_id format)
748
800
  */
749
801
  async withdrawDeposit(walletClient, depositId, escrowAddress) {
750
802
  const client = createSdkClient(walletClient);
@@ -753,9 +805,9 @@ var Offramp = class {
753
805
  escrowAddress: escrowAddress || ESCROW_ADDRESS,
754
806
  txOverrides: { referrer: [REFERRER] }
755
807
  });
756
- return typeof result === "string" ? result : result.hash;
808
+ return extractTxHash(result);
757
809
  }
758
- /** List available payment platforms and their supported currencies. */
810
+ /** List available payment platforms with currencies, labels, and format requirements. */
759
811
  getPlatforms() {
760
812
  return getPlatforms();
761
813
  }
@@ -763,7 +815,10 @@ var Offramp = class {
763
815
  getCurrencies(platform) {
764
816
  return getCurrencies(platform);
765
817
  }
766
- /** Get currency metadata (symbol, name, country code) for a currency code. */
818
+ /**
819
+ * Get currency metadata for UI rendering.
820
+ * @returns Symbol (€), full name (Euro), and country code (eu), or null if unsupported.
821
+ */
767
822
  getCurrencyInfo(code) {
768
823
  const info = currencyInfo2[code];
769
824
  if (!info) return null;
@@ -780,7 +835,10 @@ var Offramp = class {
780
835
  return this.getCurrencyInfo(code);
781
836
  }).filter(Boolean);
782
837
  }
783
- /** Validate a payment identifier for a platform without creating a deposit. */
838
+ /**
839
+ * Validate and normalize a payment identifier for a platform.
840
+ * Strips leading @/$ characters, validates format (email, IBAN, etc).
841
+ */
784
842
  validateIdentifier(platform, identifier) {
785
843
  return validateIdentifier(platform, identifier);
786
844
  }
@@ -797,4 +855,4 @@ export {
797
855
  createOfframpDeposit,
798
856
  Offramp
799
857
  };
800
- //# sourceMappingURL=chunk-BJNSLI3D.js.map
858
+ //# sourceMappingURL=chunk-E4AJU3FA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/errors.ts","../src/client.ts","../src/deposit.ts","../src/config.ts","../src/platforms.ts"],"sourcesContent":["export const PLATFORMS = [\n \"venmo\", \"cashapp\", \"chime\", \"revolut\", \"wise\",\n \"mercadopago\", \"zelle\", \"paypal\", \"monzo\", \"n26\",\n] as const;\n\nexport type Platform = (typeof PLATFORMS)[number];\n\n/** Constant map for platform autocomplete: `PAYMENT_PLATFORMS.REVOLUT` */\nexport const PAYMENT_PLATFORMS = {\n VENMO: \"venmo\",\n CASHAPP: \"cashapp\",\n CHIME: \"chime\",\n REVOLUT: \"revolut\",\n WISE: \"wise\",\n MERCADO_PAGO: \"mercadopago\",\n ZELLE: \"zelle\",\n PAYPAL: \"paypal\",\n MONZO: \"monzo\",\n N26: \"n26\",\n} as const satisfies Record<string, Platform>;\n\nexport const SUPPORTED_CURRENCIES = [\n \"AED\", \"ARS\", \"AUD\", \"BRL\", \"CAD\", \"CHF\", \"CLP\", \"CNY\", \"COP\",\n \"CZK\", \"DKK\", \"EUR\", \"GBP\", \"HKD\", \"HUF\", \"IDR\", \"ILS\", \"INR\",\n \"JPY\", \"KES\", \"KRW\", \"MXN\", \"MYR\", \"NOK\", \"NZD\", \"PEN\", \"PHP\",\n \"PLN\", \"RON\", \"SAR\", \"SEK\", \"SGD\", \"THB\", \"TRY\", \"TWD\", \"UGX\",\n \"USD\", \"VND\", \"ZAR\",\n] as const;\n\nexport type Currency = (typeof SUPPORTED_CURRENCIES)[number];\n\n/** Constant map for currency autocomplete: `CURRENCIES.EUR` */\nexport const CURRENCIES = {\n AED: \"AED\", ARS: \"ARS\", AUD: \"AUD\", BRL: \"BRL\", CAD: \"CAD\",\n CHF: \"CHF\", CLP: \"CLP\", CNY: \"CNY\", COP: \"COP\", CZK: \"CZK\",\n DKK: \"DKK\", EUR: \"EUR\", GBP: \"GBP\", HKD: \"HKD\", HUF: \"HUF\",\n IDR: \"IDR\", ILS: \"ILS\", INR: \"INR\", JPY: \"JPY\", KES: \"KES\",\n KRW: \"KRW\", MXN: \"MXN\", MYR: \"MYR\", NOK: \"NOK\", NZD: \"NZD\",\n PEN: \"PEN\", PHP: \"PHP\", PLN: \"PLN\", RON: \"RON\", SAR: \"SAR\",\n SEK: \"SEK\", SGD: \"SGD\", THB: \"THB\", TRY: \"TRY\", TWD: \"TWD\",\n UGX: \"UGX\", USD: \"USD\", VND: \"VND\", ZAR: \"ZAR\",\n} as const satisfies Record<string, Currency>;\n\nexport interface OfframpParams {\n amount: string;\n platform: Platform;\n currency: Currency;\n identifier: string;\n}\n\nexport interface OfframpResult {\n depositId: string;\n txHash: string;\n}\n\nexport type OfframpStep =\n | \"approving\"\n | \"registering\"\n | \"depositing\"\n | \"confirming\"\n | \"delegating\"\n | \"done\";\n\nexport interface OfframpProgress {\n step: OfframpStep;\n txHash?: string;\n depositId?: string;\n}\n\nexport type OnProgress = (progress: OfframpProgress) => void;\n\nexport interface PlatformInfo {\n id: Platform;\n name: string;\n currencies: Currency[];\n identifierLabel: string;\n identifierPlaceholder: string;\n helperText: string;\n}\n\nexport interface CurrencyInfo {\n code: string;\n name: string;\n symbol: string;\n countryCode: string;\n}\n\nexport type DepositStatus = \"active\" | \"empty\" | \"closed\";\n\nexport interface DepositInfo {\n /** Numeric deposit ID. Pass this to delegateDeposit/withdrawDeposit. */\n depositId: string;\n /** Composite ID (escrowAddress_depositId). For indexer queries. */\n compositeId: string;\n /** Transaction hash of the deposit creation. */\n txHash?: string;\n status: DepositStatus;\n remainingUsdc: number;\n outstandingUsdc: number;\n totalTakenUsdc: number;\n fulfilledIntents: number;\n paymentMethods: string[];\n currencies: string[];\n rateSource: string;\n delegated: boolean;\n escrowAddress: string;\n}\n","import type { OfframpStep } from \"./types\";\n\nexport type OfframpErrorCode =\n | \"VALIDATION\"\n | \"APPROVAL_FAILED\"\n | \"REGISTRATION_FAILED\"\n | \"DEPOSIT_FAILED\"\n | \"CONFIRMATION_FAILED\"\n | \"DELEGATION_FAILED\"\n | \"USER_CANCELLED\"\n | \"UNSUPPORTED\";\n\nexport class OfframpError extends Error {\n readonly code: OfframpErrorCode;\n readonly step?: OfframpStep;\n override 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 type { WalletClient } from \"viem\";\nimport { formatUnits } from \"viem\";\nimport { classifyDelegationState, currencyInfo, getCurrencyInfoFromHash, IndexerClient, IndexerDepositService } from \"@zkp2p/sdk\";\n\nimport { PLATFORMS } from \"./types\";\nimport type {\n OfframpParams,\n OfframpResult,\n OnProgress,\n PlatformInfo,\n Platform,\n CurrencyInfo,\n DepositInfo,\n DepositStatus,\n} from \"./types\";\nimport { createOfframpDeposit, createSdkClient } from \"./deposit\";\nimport {\n getPlatforms as getPlatformList,\n getCurrencies as getCurrencyList,\n validateIdentifier as validateId,\n getPaymentMethodHashes as getPaymentMethodHashesForPlatform,\n getPlatformConfig,\n} from \"./platforms\";\nimport {\n API_BASE_URL,\n DELEGATE_RATE_MANAGER_ID,\n ESCROW_ADDRESS,\n RATE_MANAGER_REGISTRY_ADDRESS,\n REFERRER,\n} from \"./config\";\n\n/* ── Indexer client (read-only, no wallet needed) ─────────────────── */\n\nlet indexerClient: IndexerDepositService | null = null;\n\nfunction getIndexerService(): IndexerDepositService {\n if (!indexerClient) {\n const client = new IndexerClient(`${API_BASE_URL.replace(/\\/+$/, \"\")}`);\n indexerClient = new IndexerDepositService(client);\n }\n return indexerClient;\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 { return BigInt(value || \"0\"); } catch { return 0n; }\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(\n hashes: Array<{ paymentMethodHash: string }>,\n): string[] {\n const names = new Set<string>();\n for (const { paymentMethodHash } of hashes) {\n const normalized = paymentMethodHash.toLowerCase();\n for (const platform of PLATFORMS) {\n const platformHashes = getPaymentMethodHashesForPlatform(platform);\n if (platformHashes.some((h) => h.toLowerCase() === normalized)) {\n names.add(getPlatformConfig(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) return (result as { hash: string }).hash;\n if (result && typeof result === \"object\" && \"transactionHash\" in result) return (result as { transactionHash: string }).transactionHash;\n throw new Error(\"Unexpected transaction result format\");\n}\n\n/* ── Offramp class ────────────────────────────────────────────────── */\n\nexport class Offramp {\n /**\n * Create an offramp deposit: approve USDC, register payee, create deposit,\n * confirm on-chain, and delegate to the vault. All in one call.\n *\n * @param walletClient - viem WalletClient with an account\n * @param params - Deposit parameters (amount, platform, currency, identifier)\n * @param onProgress - Optional callback for step-by-step progress updates\n */\n async createDeposit(\n walletClient: WalletClient,\n params: OfframpParams,\n onProgress?: OnProgress,\n ): Promise<OfframpResult> {\n return createOfframpDeposit(walletClient, params, onProgress);\n }\n\n /**\n * Fetch all deposits for a wallet address. Read-only, no wallet needed.\n * Returns active, empty, and closed deposits sorted by status then recency.\n */\n async getDeposits(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 || [])\n .map(mapDeposit)\n .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 * Find a deposit by its transaction hash. Useful for recovering from\n * CONFIRMATION_FAILED errors where you have a txHash but no depositId.\n *\n * @param walletAddress - The depositor's wallet address\n * @param txHash - The transaction hash from createDeposit\n */\n async getDepositByTxHash(walletAddress: string, txHash: string): Promise<DepositInfo | null> {\n const deposits = await this.getDeposits(walletAddress);\n const normalized = txHash.toLowerCase();\n return deposits.find((d) => d.txHash?.toLowerCase() === normalized) ?? null;\n }\n\n /**\n * Delegate an existing deposit to the Delegate vault. Use this to:\n * - Retry after a DELEGATION_FAILED error\n * - Delegate a deposit created outside the SDK\n * - Delegate a deposit created via usdctofiat.xyz\n *\n * @param walletClient - viem WalletClient with the deposit owner's account\n * @param depositId - The numeric deposit ID (not the composite escrow_id format)\n */\n async delegateDeposit(\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 * 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 (not the composite escrow_id format)\n */\n async withdrawDeposit(\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 /** List available payment platforms with currencies, labels, and format requirements. */\n getPlatforms(): PlatformInfo[] {\n return getPlatformList();\n }\n\n /** Get supported currencies for a specific platform. */\n getCurrencies(platform: Platform): string[] {\n return getCurrencyList(platform);\n }\n\n /**\n * Get currency metadata for UI rendering.\n * @returns Symbol (€), full name (Euro), and country code (eu), or null if unsupported.\n */\n getCurrencyInfo(code: string): CurrencyInfo | null {\n const info = (currencyInfo as Record<string, { currencyCode?: string; currencyName?: string; currencySymbol?: string; countryCode?: string }>)[code];\n if (!info) return null;\n return {\n code: info.currencyCode ?? code,\n name: info.currencyName ?? code,\n symbol: info.currencySymbol ?? code,\n countryCode: info.countryCode ?? \"\",\n };\n }\n\n /** Get all supported currencies with metadata. */\n getAllCurrencies(): CurrencyInfo[] {\n return Object.keys(currencyInfo as Record<string, unknown>).map((code) => {\n return this.getCurrencyInfo(code)!;\n }).filter(Boolean);\n }\n\n /**\n * Validate and normalize a payment identifier for a platform.\n * Strips leading @/$ characters, validates format (email, IBAN, etc).\n */\n validateIdentifier(platform: Platform, identifier: string): {\n valid: boolean;\n normalized: string;\n error?: string;\n } {\n return validateId(platform, identifier);\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 OfframpClient,\n getSpreadOracleConfig,\n mapConversionRatesToOnchainMinRate,\n type CurrencyType,\n} from \"@zkp2p/sdk\";\n\nimport {\n API_BASE_URL,\n BASE_CHAIN_ID,\n BASE_RPC_URL,\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 MIN_DEPOSIT_USDC,\n MIN_ORDER_USDC,\n PAYEE_REGISTRATION_TIMEOUT_MS,\n RATE_MANAGER_REGISTRY_ADDRESS,\n REFERRER,\n RUNTIME_ENV,\n USDC_ADDRESS,\n} from \"./config\";\nimport {\n buildDepositData,\n getPaymentMethodHash,\n isSupportedCurrency,\n validateIdentifier,\n} from \"./platforms\";\nimport { OfframpError, isUserCancellation } from \"./errors\";\nimport type { OfframpParams, OfframpResult, OnProgress } from \"./types\";\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 { indexed: false, name: \"intentAmountRange\", type: \"tuple\", components: [\n { name: \"min\", type: \"uint256\" }, { name: \"max\", type: \"uint256\" },\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 { continue; }\n }\n return null;\n}\n\nasync function registerPayeeDetails(\n processorName: string,\n depositData: Record<string, string>,\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(`${API_BASE_URL}/v1/makers/create`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ processorName, depositData }),\n signal: controller.signal,\n });\n if (!res.ok) {\n const txt = await res.text().catch(() => \"\");\n throw new Error(`makers/create failed (${res.status}): ${txt || res.statusText}`);\n }\n const json = await res.json() as { success: boolean; message: string; responseObject?: { hashedOnchainId: string } };\n if (!json.success || !json.responseObject?.hashedOnchainId) {\n throw new Error(json.message || \"makers/create returned no hashedOnchainId\");\n }\n return json.responseObject.hashedOnchainId;\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\n/* ── SDK client factory ───────────────────────────────────────────── */\n\nexport function createSdkClient(walletClient: WalletClient): OfframpClient {\n return new OfframpClient({\n walletClient,\n chainId: BASE_CHAIN_ID,\n runtimeEnv: RUNTIME_ENV,\n rpcUrl: BASE_RPC_URL,\n baseApiUrl: API_BASE_URL,\n });\n}\n\n/* ── Main deposit flow ────────────────────────────────────────────── */\n\nexport async function createOfframpDeposit(\n walletClient: WalletClient,\n params: OfframpParams,\n onProgress?: OnProgress,\n): Promise<OfframpResult> {\n const { amount, platform, currency, identifier } = params;\n\n // 1. Validate\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 (!isSupportedCurrency(platform, currency)) {\n throw new OfframpError(`${currency} is not supported on ${platform}`, \"UNSUPPORTED\");\n }\n\n const validation = validateIdentifier(platform, identifier);\n if (!validation.valid) {\n throw new OfframpError(validation.error || \"Invalid identifier\", \"VALIDATION\");\n }\n const normalizedIdentifier = validation.normalized;\n\n const methodHash = getPaymentMethodHash(platform);\n if (!methodHash) {\n throw new OfframpError(`${platform} is not currently supported`, \"UNSUPPORTED\");\n }\n\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;\n\n // Truncate to 6 decimals (USDC precision)\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, 2500)));\n\n // Pre-flight: check USDC balance\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: [{ name: \"balanceOf\", type: \"function\", stateMutability: \"view\", inputs: [{ name: \"account\", type: \"address\" }], outputs: [{ name: \"\", type: \"uint256\" }] }] 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 // If balance check fails (RPC issue), proceed anyway -- the tx will revert if insufficient\n }\n\n const client = createSdkClient(walletClient);\n const txOverrides = { referrer: [REFERRER] };\n\n // 2. Approve\n onProgress?.({ 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)) throw new OfframpError(\"User cancelled\", \"USER_CANCELLED\", \"approving\", err);\n const detail = err instanceof Error ? err.message : String(err);\n throw new OfframpError(`USDC approval failed: ${detail}`, \"APPROVAL_FAILED\", \"approving\", err);\n }\n\n // 3. Register payee\n onProgress?.({ step: \"registering\" });\n let hashedOnchainId: string;\n try {\n const canonicalName = platform.startsWith(\"zelle\") ? \"zelle\" : platform;\n const depositData = buildDepositData(platform, normalizedIdentifier);\n hashedOnchainId = await registerPayeeDetails(canonicalName, depositData);\n } catch (err) {\n throw new OfframpError(\"Payee registration failed\", \"REGISTRATION_FAILED\", \"registering\", err);\n }\n\n // 4. Create deposit\n onProgress?.({ step: \"depositing\" });\n\n // 1 wei floor -- vault manages actual rates via oracle\n const conversionRates: Array<Array<{ currency: CurrencyType; conversionRate: string }>> = [\n [{ currency: currency as CurrencyType, conversionRate: \"1\" }],\n ];\n\n const baseCurrenciesOverride = mapConversionRatesToOnchainMinRate(conversionRates, 1);\n const currenciesOverride = attachOracleConfig(baseCurrenciesOverride, conversionRates);\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: [platform],\n depositData: [buildDepositData(platform, normalizedIdentifier)],\n conversionRates,\n paymentMethodsOverride: [methodHash],\n paymentMethodDataOverride: [{\n intentGatingService: GATING_SERVICE_ADDRESS,\n payeeDetails: hashedOnchainId as `0x${string}`,\n data: \"0x\" as `0x${string}`,\n }],\n currenciesOverride,\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)) throw new OfframpError(\"User cancelled\", \"USER_CANCELLED\", \"depositing\", err);\n const detail = err instanceof Error ? err.message : String(err);\n throw new OfframpError(`Deposit transaction failed: ${detail}`, \"DEPOSIT_FAILED\", \"depositing\", err);\n }\n\n // 5. Confirm\n onProgress?.({ step: \"confirming\", txHash: hash });\n let depositId = \"\";\n\n const receiptClient = client as { waitForTransactionReceipt?: (p: { hash: `0x${string}`; confirmations?: number }) => Promise<{ logs: Array<{ topics?: Hex[]; data?: Hex }> }> };\n if (typeof receiptClient.waitForTransactionReceipt === \"function\") {\n try {\n const receipt = await receiptClient.waitForTransactionReceipt({ hash, confirmations: 1 });\n depositId = extractDepositIdFromLogs(receipt.logs) || \"\";\n } catch { /* fall through to indexer */ }\n }\n\n if (!depositId) {\n {\n let delay = INDEXER_INITIAL_DELAY_MS;\n for (let attempt = 0; attempt < INDEXER_MAX_ATTEMPTS && !depositId; attempt++) {\n try {\n const deposits = await client.indexer.getDepositsWithRelations(\n { depositor: walletAddress },\n { limit: 25 },\n ) as Array<{ txHash?: string; depositId: string }>;\n const hit = deposits.find((d) => (d?.txHash || \"\").toLowerCase() === hash.toLowerCase());\n if (hit) {\n depositId = String(hit.depositId);\n break;\n }\n } catch { /* continue */ }\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\n if (!depositId) {\n throw new OfframpError(\n \"Deposit created on-chain but could not confirm deposit ID. Your funds are safe. Use the transaction hash to locate your deposit.\",\n \"CONFIRMATION_FAILED\",\n \"confirming\",\n undefined,\n { txHash: hash },\n );\n }\n\n // 6. Delegate\n onProgress?.({ 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(\"User cancelled delegation\", \"USER_CANCELLED\", \"delegating\", delegationError, { txHash: hash, depositId });\n }\n throw new OfframpError(\n \"Deposit created but delegation failed. Visit usdctofiat.xyz to manage your deposit manually.\",\n \"DELEGATION_FAILED\",\n \"delegating\",\n delegationError,\n { txHash: hash, depositId },\n );\n }\n\n onProgress?.({ step: \"done\", txHash: hash, depositId });\n return { depositId, txHash: hash };\n}\n","import { getContracts, getGatingServiceAddress } from \"@zkp2p/sdk\";\n\nexport const BASE_CHAIN_ID = 8453;\nexport const RUNTIME_ENV = \"production\" as const;\nexport const API_BASE_URL = \"https://api.zkp2p.xyz\";\nexport const BASE_RPC_URL = \"https://mainnet.base.org\";\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 || \"0x833589fcd6edb6e08f4c7c32d4f71b54bda02913\") as `0x${string}`;\nexport const ESCROW_ADDRESS = (addrs.escrowV2 || addrs.escrow || \"\") as `0x${string}`;\nexport const GATING_SERVICE_ADDRESS = getGatingServiceAddress(BASE_CHAIN_ID, RUNTIME_ENV) 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}`;\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 {\n currencyInfo,\n getCurrencyInfoFromHash,\n getPaymentMethodsCatalog,\n resolvePaymentMethodHash,\n} from \"@zkp2p/sdk\";\nimport { z } from \"zod\";\nimport { BASE_CHAIN_ID, RUNTIME_ENV } from \"./config\";\nimport type { Currency, Platform, PlatformInfo } from \"./types\";\nimport { PLATFORMS } from \"./types\";\n\ntype CurrencyCode = keyof typeof currencyInfo;\n\nconst ZELLE_HASH_LOOKUP_NAMES = [\"zelle\", \"zelle-bofa\", \"zelle-chase\", \"zelle-citi\"] as const;\ntype PaymentMethodLookupName = Platform | (typeof ZELLE_HASH_LOOKUP_NAMES)[number];\n\ninterface PlatformConfig {\n id: Platform;\n name: string;\n identifierLabel: string;\n placeholder: string;\n helperText: string;\n currencies: string[];\n validation: z.ZodType<string>;\n transform?: (value: string) => string;\n}\n\ntype CatalogEntry = { currencies?: string[]; paymentMethodHash?: `0x${string}` };\nconst PAYMENT_CATALOG = getPaymentMethodsCatalog(BASE_CHAIN_ID, RUNTIME_ENV) as Record<string, CatalogEntry>;\n\nconst FALLBACK_CURRENCIES: Record<Platform, string[]> = {\n venmo: [\"USD\"],\n cashapp: [\"USD\"],\n chime: [\"USD\"],\n revolut: [\"USD\", \"EUR\", \"GBP\", \"SGD\", \"NZD\", \"AUD\", \"CAD\", \"HKD\", \"MXN\", \"SAR\", \"AED\", \"THB\", \"TRY\", \"PLN\", \"CHF\", \"ZAR\", \"CZK\", \"CNY\", \"DKK\", \"HUF\", \"NOK\", \"RON\", \"SEK\"],\n wise: [\"USD\", \"CNY\", \"EUR\", \"GBP\", \"AUD\", \"NZD\", \"CAD\", \"AED\", \"CHF\", \"ZAR\", \"SGD\", \"ILS\", \"HKD\", \"JPY\", \"PLN\", \"TRY\", \"IDR\", \"KES\", \"MYR\", \"MXN\", \"THB\", \"VND\", \"UGX\", \"CZK\", \"DKK\", \"HUF\", \"INR\", \"NOK\", \"PHP\", \"RON\", \"SEK\"],\n mercadopago: [\"ARS\"],\n zelle: [\"USD\"],\n paypal: [\"USD\", \"EUR\", \"GBP\", \"SGD\", \"NZD\", \"AUD\", \"CAD\"],\n monzo: [\"GBP\"],\n n26: [\"EUR\"],\n};\n\nfunction gatherCatalogHashes(platform: Platform): 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: Platform): 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\nconst BLUEPRINT: Record<Platform, Omit<PlatformConfig, \"currencies\">> = {\n venmo: {\n id: \"venmo\", name: \"Venmo\", identifierLabel: \"Username\", placeholder: \"venmo username (no @)\",\n helperText: \"Username without @ (publicly discoverable)\",\n validation: z.string().min(1).regex(/^[a-zA-Z0-9_-]+$/),\n transform: (v) => v.replace(/^@+/, \"\"),\n },\n cashapp: {\n id: \"cashapp\", name: \"Cash App\", identifierLabel: \"Cashtag\", placeholder: \"cashtag (no $)\",\n helperText: \"Cashtag without $ (publicly discoverable)\",\n validation: z.string().min(1).regex(/^[a-zA-Z0-9]+$/),\n transform: (v) => v.replace(/^\\$+/, \"\"),\n },\n chime: {\n id: \"chime\", name: \"Chime\", identifierLabel: \"ChimeSign\", placeholder: \"$chimesign\",\n helperText: \"ChimeSign with $ (must be discoverable)\",\n validation: z.string().min(2).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\", name: \"Revolut\", identifierLabel: \"Revtag\", placeholder: \"revtag (no @)\",\n helperText: \"Revtag without @ (must be public)\",\n validation: z.string().min(1).regex(/^[a-zA-Z0-9]+$/),\n transform: (v) => v.replace(/^@+/, \"\").trim(),\n },\n wise: {\n id: \"wise\", name: \"Wise\", identifierLabel: \"Wisetag\", placeholder: \"wisetag (no @)\",\n helperText: \"Your Wise @wisetag (no @)\",\n validation: z.string().min(1).regex(/^[a-zA-Z0-9_-]+$/),\n transform: (v) => v.replace(/^@+/, \"\").trim(),\n },\n mercadopago: {\n id: \"mercadopago\", name: \"Mercado Pago\", identifierLabel: \"CVU\", placeholder: \"22-digit CVU\",\n helperText: \"CVU must be exactly 22 digits\",\n validation: z.string().length(22).regex(/^\\d{22}$/),\n },\n zelle: {\n id: \"zelle\", name: \"Zelle\", identifierLabel: \"Email\", placeholder: \"email\",\n helperText: \"Registered Zelle email\",\n validation: z.string().email(),\n },\n paypal: {\n id: \"paypal\", name: \"PayPal\", identifierLabel: \"Email\", placeholder: \"email\",\n helperText: \"Email linked to PayPal account\",\n validation: z.string().email(),\n },\n monzo: {\n id: \"monzo\", name: \"Monzo\", identifierLabel: \"Username\", placeholder: \"monzo.me username\",\n helperText: \"Your Monzo.me username\",\n validation: z.string().min(1).regex(/^[a-zA-Z0-9_-]+$/),\n },\n n26: {\n id: \"n26\", name: \"N26\", identifierLabel: \"IBAN\", placeholder: \"IBAN (e.g. DE89...)\",\n helperText: \"Your IBAN (spaces will be removed)\",\n validation: z.string().min(15).max(34).regex(/^[A-Z]{2}[0-9]{2}[A-Z0-9]+$/i),\n transform: (v) => v.replace(/\\s/g, \"\").toUpperCase(),\n },\n};\n\nconst CONFIGS: Record<Platform, PlatformConfig> = Object.fromEntries(\n Object.entries(BLUEPRINT).map(([p, bp]) => {\n const key = p as Platform;\n return [key, { ...bp, currencies: resolveSupportedCurrencies(key) }];\n }),\n) as Record<Platform, PlatformConfig>;\n\nexport function getPlatformConfig(platform: Platform): PlatformConfig {\n return CONFIGS[platform];\n}\n\nexport function getPlatforms(): PlatformInfo[] {\n return PLATFORMS.map((id) => {\n const cfg = CONFIGS[id];\n return {\n id,\n name: cfg.name,\n currencies: cfg.currencies as Currency[],\n identifierLabel: cfg.identifierLabel,\n identifierPlaceholder: cfg.placeholder,\n helperText: cfg.helperText,\n };\n });\n}\n\nexport function getCurrencies(platform: Platform): string[] {\n return CONFIGS[platform]?.currencies ?? [];\n}\n\nexport function validateIdentifier(\n platform: Platform,\n value: string,\n): { valid: boolean; normalized: string; error?: string } {\n const cfg = CONFIGS[platform];\n if (!cfg) return { valid: false, normalized: value, error: \"Unsupported platform\" };\n const transformed = cfg.transform ? cfg.transform(value) : value;\n const result = cfg.validation.safeParse(transformed);\n if (!result.success) {\n return { valid: false, normalized: transformed, error: result.error.issues[0]?.message || \"Invalid input\" };\n }\n return { valid: true, normalized: transformed };\n}\n\nexport function isSupportedCurrency(platform: Platform, currency: string): boolean {\n return CONFIGS[platform]?.currencies.includes(currency) ?? false;\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 return PLATFORMS.includes(normalized as Platform) ? (normalized as Platform) : null;\n}\n\nfunction resolveCanonicalZelleHash(): `0x${string}` | null {\n const direct = PAYMENT_CATALOG.zelle?.paymentMethodHash;\n if (direct) return direct;\n const variant = Object.entries(PAYMENT_CATALOG).find(\n ([name, entry]) => name.startsWith(\"zelle\") && Boolean(entry.paymentMethodHash),\n );\n return variant?.[1]?.paymentMethodHash ?? null;\n}\n\nexport function getPaymentMethodHash(platform: Platform): `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\" || name.startsWith(\"zelle-\")) return resolveCanonicalZelleHash();\n const sdkHash = resolvePaymentMethodHash(name);\n return sdkHash ? (sdkHash as `0x${string}`) : null;\n}\n\nexport function getPaymentMethodHashes(platform: Platform): `0x${string}`[] {\n if (platform !== \"zelle\") {\n const hash = getPaymentMethodHash(platform);\n return hash ? [hash] : [];\n }\n const hashes = new Set<`0x${string}`>();\n const generic = resolvePaymentMethodHash(\"zelle\") as `0x${string}` | undefined;\n if (generic) hashes.add(generic);\n const canonical = resolveCanonicalZelleHash();\n if (canonical) hashes.add(canonical);\n for (const [name, entry] of Object.entries(PAYMENT_CATALOG)) {\n if (name.startsWith(\"zelle\") && entry.paymentMethodHash) {\n hashes.add(entry.paymentMethodHash);\n }\n }\n return Array.from(hashes);\n}\n\nexport function buildDepositData(\n platform: Platform,\n identifier: string,\n): Record<string, string> {\n switch (platform) {\n case \"venmo\": return { venmoUsername: identifier, telegramUsername: \"\" };\n case \"cashapp\": return { cashtag: identifier, telegramUsername: \"\" };\n case \"chime\": return { chimesign: identifier.toLowerCase(), telegramUsername: \"\" };\n case \"revolut\": return { revolutUsername: identifier, telegramUsername: \"\" };\n case \"wise\": return { wisetag: identifier, telegramUsername: \"\" };\n case \"mercadopago\": return { cvu: identifier, telegramUsername: \"\" };\n case \"zelle\": return { zelleEmail: identifier, telegramUsername: \"\" };\n case \"paypal\": return { paypalEmail: identifier, telegramUsername: \"\" };\n case \"monzo\": return { monzoMeUsername: identifier, telegramUsername: \"\" };\n case \"n26\": return { iban: identifier, telegramUsername: \"\" };\n default: return { identifier, telegramUsername: \"\" };\n }\n}\n"],"mappings":"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","names":["formatUnits","currencyInfo","getCurrencyInfoFromHash","formatUnits","getCurrencyInfoFromHash","currencyInfo"]}
@@ -90,8 +90,12 @@ interface CurrencyInfo {
90
90
  }
91
91
  type DepositStatus = "active" | "empty" | "closed";
92
92
  interface DepositInfo {
93
+ /** Numeric deposit ID. Pass this to delegateDeposit/withdrawDeposit. */
93
94
  depositId: string;
95
+ /** Composite ID (escrowAddress_depositId). For indexer queries. */
94
96
  compositeId: string;
97
+ /** Transaction hash of the deposit creation. */
98
+ txHash?: string;
95
99
  status: DepositStatus;
96
100
  remainingUsdc: number;
97
101
  outstandingUsdc: number;
@@ -104,4 +108,17 @@ interface DepositInfo {
104
108
  escrowAddress: string;
105
109
  }
106
110
 
107
- export { type CurrencyInfo as C, type DepositInfo as D, type OfframpParams as O, type PlatformInfo as P, SUPPORTED_CURRENCIES as S, type OnProgress as a, type OfframpResult as b, type Platform as c, type OfframpStep as d, CURRENCIES as e, type Currency as f, type DepositStatus as g, type OfframpProgress as h, PAYMENT_PLATFORMS as i };
111
+ type OfframpErrorCode = "VALIDATION" | "APPROVAL_FAILED" | "REGISTRATION_FAILED" | "DEPOSIT_FAILED" | "CONFIRMATION_FAILED" | "DELEGATION_FAILED" | "USER_CANCELLED" | "UNSUPPORTED";
112
+ declare class OfframpError extends Error {
113
+ readonly code: OfframpErrorCode;
114
+ readonly step?: OfframpStep;
115
+ readonly cause?: unknown;
116
+ readonly txHash?: string;
117
+ readonly depositId?: string;
118
+ constructor(message: string, code: OfframpErrorCode, step?: OfframpStep, cause?: unknown, details?: {
119
+ txHash?: string;
120
+ depositId?: string;
121
+ });
122
+ }
123
+
124
+ export { type CurrencyInfo as C, type DepositInfo as D, type OfframpParams as O, type PlatformInfo as P, SUPPORTED_CURRENCIES as S, type OnProgress as a, type OfframpResult as b, type Platform as c, CURRENCIES as d, type Currency as e, type DepositStatus as f, OfframpError as g, type OfframpErrorCode as h, type OfframpProgress as i, type OfframpStep as j, PAYMENT_PLATFORMS as k };
@@ -90,8 +90,12 @@ interface CurrencyInfo {
90
90
  }
91
91
  type DepositStatus = "active" | "empty" | "closed";
92
92
  interface DepositInfo {
93
+ /** Numeric deposit ID. Pass this to delegateDeposit/withdrawDeposit. */
93
94
  depositId: string;
95
+ /** Composite ID (escrowAddress_depositId). For indexer queries. */
94
96
  compositeId: string;
97
+ /** Transaction hash of the deposit creation. */
98
+ txHash?: string;
95
99
  status: DepositStatus;
96
100
  remainingUsdc: number;
97
101
  outstandingUsdc: number;
@@ -104,4 +108,17 @@ interface DepositInfo {
104
108
  escrowAddress: string;
105
109
  }
106
110
 
107
- export { type CurrencyInfo as C, type DepositInfo as D, type OfframpParams as O, type PlatformInfo as P, SUPPORTED_CURRENCIES as S, type OnProgress as a, type OfframpResult as b, type Platform as c, type OfframpStep as d, CURRENCIES as e, type Currency as f, type DepositStatus as g, type OfframpProgress as h, PAYMENT_PLATFORMS as i };
111
+ type OfframpErrorCode = "VALIDATION" | "APPROVAL_FAILED" | "REGISTRATION_FAILED" | "DEPOSIT_FAILED" | "CONFIRMATION_FAILED" | "DELEGATION_FAILED" | "USER_CANCELLED" | "UNSUPPORTED";
112
+ declare class OfframpError extends Error {
113
+ readonly code: OfframpErrorCode;
114
+ readonly step?: OfframpStep;
115
+ readonly cause?: unknown;
116
+ readonly txHash?: string;
117
+ readonly depositId?: string;
118
+ constructor(message: string, code: OfframpErrorCode, step?: OfframpStep, cause?: unknown, details?: {
119
+ txHash?: string;
120
+ depositId?: string;
121
+ });
122
+ }
123
+
124
+ export { type CurrencyInfo as C, type DepositInfo as D, type OfframpParams as O, type PlatformInfo as P, SUPPORTED_CURRENCIES as S, type OnProgress as a, type OfframpResult as b, type Platform as c, CURRENCIES as d, type Currency as e, type DepositStatus as f, OfframpError as g, type OfframpErrorCode as h, type OfframpProgress as i, type OfframpStep as j, PAYMENT_PLATFORMS as k };