@usdctofiat/offramp 0.2.1 → 1.0.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/platforms.ts","../src/config.ts","../src/errors.ts","../src/queries.ts","../src/deposit.ts"],"sourcesContent":["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\";\n\n/* ── Internal types ───────────────────────────────────────────────── */\n\ntype CatalogEntry = { currencies?: string[]; paymentMethodHash?: `0x${string}` };\nconst PAYMENT_CATALOG = getPaymentMethodsCatalog(BASE_CHAIN_ID, RUNTIME_ENV) as Record<string, CatalogEntry>;\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 = \"venmo\" | \"cashapp\" | \"chime\" | \"revolut\" | \"wise\" | \"mercadopago\" | \"zelle\" | \"paypal\" | \"monzo\" | \"n26\";\n\n/* ── Platform entry type ──────────────────────────────────────────── */\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 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: [\"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: 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/* ── 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}\n\nconst BLUEPRINTS: Record<PlatformId, PlatformBlueprint> = {\n venmo: { id: \"venmo\", name: \"Venmo\", identifierLabel: \"Username\", placeholder: \"venmo username (no @)\", helperText: \"Username without @ (publicly discoverable)\", validation: z.string().min(1).regex(/^[a-zA-Z0-9_-]+$/), transform: (v) => v.replace(/^@+/, \"\") },\n cashapp: { id: \"cashapp\", name: \"Cash App\", identifierLabel: \"Cashtag\", placeholder: \"cashtag (no $)\", helperText: \"Cashtag without $ (publicly discoverable)\", validation: z.string().min(1).regex(/^[a-zA-Z0-9]+$/), transform: (v) => v.replace(/^\\$+/, \"\") },\n chime: { id: \"chime\", name: \"Chime\", identifierLabel: \"ChimeSign\", placeholder: \"$chimesign\", helperText: \"ChimeSign with $ (must be discoverable)\", validation: z.string().min(2).regex(/^\\$[a-zA-Z0-9]+$/), transform: (v) => { const t = v.trim().toLowerCase(); return t.startsWith(\"$\") ? t : `$${t}`; } },\n revolut: { id: \"revolut\", name: \"Revolut\", identifierLabel: \"Revtag\", placeholder: \"revtag (no @)\", helperText: \"Revtag without @ (must be public)\", validation: z.string().min(1).regex(/^[a-zA-Z0-9]+$/), transform: (v) => v.replace(/^@+/, \"\").trim() },\n wise: { id: \"wise\", name: \"Wise\", identifierLabel: \"Wisetag\", placeholder: \"wisetag (no @)\", helperText: \"Your Wise @wisetag (no @)\", validation: z.string().min(1).regex(/^[a-zA-Z0-9_-]+$/), transform: (v) => v.replace(/^@+/, \"\").trim() },\n mercadopago: { id: \"mercadopago\", name: \"Mercado Pago\", identifierLabel: \"CVU\", placeholder: \"22-digit CVU\", helperText: \"CVU must be exactly 22 digits\", validation: z.string().length(22).regex(/^\\d{22}$/) },\n zelle: { id: \"zelle\", name: \"Zelle\", identifierLabel: \"Email\", placeholder: \"email\", helperText: \"Registered Zelle email\", validation: z.string().email() },\n paypal: { id: \"paypal\", name: \"PayPal\", identifierLabel: \"Email\", placeholder: \"email\", helperText: \"Email linked to PayPal account\", validation: z.string().email() },\n monzo: { id: \"monzo\", name: \"Monzo\", identifierLabel: \"Username\", placeholder: \"monzo.me username\", helperText: \"Your Monzo.me username\", validation: z.string().min(1).regex(/^[a-zA-Z0-9_-]+$/) },\n n26: { id: \"n26\", name: \"N26\", identifierLabel: \"IBAN\", placeholder: \"IBAN (e.g. DE89...)\", helperText: \"Your IBAN (spaces will be removed)\", validation: z.string().min(15).max(34).regex(/^[A-Z]{2}[0-9]{2}[A-Z0-9]+$/i), transform: (v) => v.replace(/\\s/g, \"\").toUpperCase() },\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 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 { valid: false, normalized: transformed, error: result.error.issues[0]?.message || \"Invalid input\" };\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 N26: buildPlatformEntry(BLUEPRINTS.n26),\n} as const;\n\n/** Platform key type for PLATFORMS constant. */\nexport type PlatformKey = keyof typeof PLATFORMS;\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\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: 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\" || name.startsWith(\"zelle-\")) return resolveCanonicalZelleHash();\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 = 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(platform: string, identifier: string): 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","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 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, defaultIndexerEndpoint, getCurrencyInfoFromHash, IndexerClient, IndexerDepositService } from \"@zkp2p/sdk\";\n\nimport type { DepositInfo, DepositStatus } from \"./types\";\nimport { createSdkClient } from \"./deposit\";\nimport { PLATFORMS, getPaymentMethodHashes } from \"./platforms\";\nimport {\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 { 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(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) 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/* ── 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 || [])\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 * 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","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} from \"./platforms\";\nimport { OfframpError, isUserCancellation } from \"./errors\";\nimport { getIndexerService } from \"./queries\";\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\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/* ── 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/* ── 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 return (raw || []).find((d) => {\n if (d.status === \"CLOSED\") return false;\n if (d.escrowAddress.toLowerCase() !== escrowLower) return false;\n const remaining = (() => { try { return BigInt(d.remainingDeposits || \"0\"); } catch { return 0n; } })();\n if (remaining === 0n) return false;\n // Undelegated = no rate manager set, or not our vault\n const hasOurVault = d.rateManagerId === DELEGATE_RATE_MANAGER_ID;\n return !hasOurVault;\n }) ?? 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): Promise<OfframpResult> {\n const { amount, platform, currency, identifier } = params;\n const platformId = platform.id;\n const currencyCode = currency.code;\n\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;\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 methodHash = getPaymentMethodHash(platformId);\n if (!methodHash) {\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 onProgress?.({ step: \"resuming\", depositId: existing.depositId });\n\n const client = createSdkClient(walletClient);\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 onProgress?.({ step: \"done\", txHash, depositId: existing.depositId });\n return { depositId: existing.depositId, txHash, resumed: true };\n } catch (err) {\n if (isUserCancellation(err)) 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\", \"resuming\", 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, 2500)));\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: [{ 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(`Insufficient USDC balance. Have ${available.toFixed(2)}, need ${truncatedAmount}.`, \"VALIDATION\");\n }\n } catch (err) {\n if (err instanceof OfframpError) throw err;\n }\n\n const client = createSdkClient(walletClient);\n const txOverrides = { referrer: [REFERRER] };\n\n // 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 // Register payee\n onProgress?.({ step: \"registering\" });\n let hashedOnchainId: string;\n try {\n const canonicalName = platformId.startsWith(\"zelle\") ? \"zelle\" : platformId;\n const depositData = buildDepositData(platformId, normalizedIdentifier);\n hashedOnchainId = await registerPayeeDetails(canonicalName, depositData);\n } catch (err) {\n throw new OfframpError(\"Payee registration failed\", \"REGISTRATION_FAILED\", \"registering\", err);\n }\n\n // Create deposit\n onProgress?.({ step: \"depositing\" });\n\n const conversionRates: Array<Array<{ currency: CurrencyType; conversionRate: string }>> = [\n [{ currency: currencyCode 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: [platformId],\n depositData: [buildDepositData(platformId, 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 // 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 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 { /* 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 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\", \"confirming\", undefined, { txHash: hash },\n );\n }\n\n // 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. Call offramp() again to resume delegation.\",\n \"DELEGATION_FAILED\", \"delegating\", delegationError, { txHash: hash, depositId },\n );\n }\n\n onProgress?.({ step: \"done\", txHash: hash, depositId });\n return { depositId, txHash: hash, resumed: false };\n}\n"],"mappings":"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","names":["formatUnits","getCurrencyInfoFromHash","client","txOverrides","formatUnits","getCurrencyInfoFromHash","extractTxHash"]}
@@ -0,0 +1,101 @@
1
+ import { currencyInfo } from '@zkp2p/sdk';
2
+
3
+ type PlatformId = "venmo" | "cashapp" | "chime" | "revolut" | "wise" | "mercadopago" | "zelle" | "paypal" | "monzo" | "n26";
4
+ interface PlatformEntry {
5
+ readonly id: PlatformId;
6
+ readonly name: string;
7
+ readonly currencies: readonly string[];
8
+ readonly identifier: {
9
+ readonly label: string;
10
+ readonly placeholder: string;
11
+ readonly help: string;
12
+ };
13
+ validate(input: string): {
14
+ valid: boolean;
15
+ normalized: string;
16
+ error?: string;
17
+ };
18
+ }
19
+ /** All supported payment platforms. Access via `PLATFORMS.REVOLUT`, `PLATFORMS.WISE`, etc. */
20
+ declare const PLATFORMS: {
21
+ readonly VENMO: PlatformEntry;
22
+ readonly CASHAPP: PlatformEntry;
23
+ readonly CHIME: PlatformEntry;
24
+ readonly REVOLUT: PlatformEntry;
25
+ readonly WISE: PlatformEntry;
26
+ readonly MERCADO_PAGO: PlatformEntry;
27
+ readonly ZELLE: PlatformEntry;
28
+ readonly PAYPAL: PlatformEntry;
29
+ readonly MONZO: PlatformEntry;
30
+ readonly N26: PlatformEntry;
31
+ };
32
+
33
+ interface CurrencyEntry {
34
+ readonly code: string;
35
+ readonly name: string;
36
+ readonly symbol: string;
37
+ readonly countryCode: string;
38
+ }
39
+ type CurrencyMap = {
40
+ readonly [K in keyof typeof currencyInfo]: CurrencyEntry;
41
+ };
42
+ /** All supported currencies with metadata. Access via `CURRENCIES.EUR.symbol` etc. */
43
+ declare const CURRENCIES: CurrencyMap;
44
+
45
+ interface OfframpParams {
46
+ /** USDC amount as decimal string, min 1. */
47
+ amount: string;
48
+ /** Payment platform — use `PLATFORMS.REVOLUT` etc. */
49
+ platform: PlatformEntry;
50
+ /** Fiat currency — use `CURRENCIES.EUR` etc. */
51
+ currency: CurrencyEntry;
52
+ /** Platform-specific identifier (username, email, IBAN). */
53
+ identifier: string;
54
+ }
55
+ interface OfframpResult {
56
+ depositId: string;
57
+ txHash: string;
58
+ /** Whether an existing undelegated deposit was resumed. */
59
+ resumed: boolean;
60
+ }
61
+ type OfframpStep = "approving" | "registering" | "depositing" | "confirming" | "delegating" | "resuming" | "done";
62
+ interface OfframpProgress {
63
+ step: OfframpStep;
64
+ txHash?: string;
65
+ depositId?: string;
66
+ }
67
+ type OnProgress = (progress: OfframpProgress) => void;
68
+ type DepositStatus = "active" | "empty" | "closed";
69
+ interface DepositInfo {
70
+ /** Numeric deposit ID. Pass this to `close()`. */
71
+ depositId: string;
72
+ /** Composite ID (escrowAddress_depositId). */
73
+ compositeId: string;
74
+ /** Creation transaction hash. */
75
+ txHash?: string;
76
+ status: DepositStatus;
77
+ remainingUsdc: number;
78
+ outstandingUsdc: number;
79
+ totalTakenUsdc: number;
80
+ fulfilledIntents: number;
81
+ paymentMethods: string[];
82
+ currencies: string[];
83
+ rateSource: string;
84
+ delegated: boolean;
85
+ escrowAddress: string;
86
+ }
87
+
88
+ type OfframpErrorCode = "VALIDATION" | "APPROVAL_FAILED" | "REGISTRATION_FAILED" | "DEPOSIT_FAILED" | "CONFIRMATION_FAILED" | "DELEGATION_FAILED" | "USER_CANCELLED" | "UNSUPPORTED";
89
+ declare class OfframpError extends Error {
90
+ readonly code: OfframpErrorCode;
91
+ readonly step?: OfframpStep;
92
+ readonly cause?: unknown;
93
+ readonly txHash?: string;
94
+ readonly depositId?: string;
95
+ constructor(message: string, code: OfframpErrorCode, step?: OfframpStep, cause?: unknown, details?: {
96
+ txHash?: string;
97
+ depositId?: string;
98
+ });
99
+ }
100
+
101
+ export { CURRENCIES as C, type DepositInfo as D, type OfframpParams as O, PLATFORMS as P, type OnProgress as a, type OfframpResult as b, type CurrencyEntry as c, type DepositStatus as d, OfframpError as e, type OfframpErrorCode as f, type OfframpProgress as g, type OfframpStep as h, type PlatformEntry as i };
@@ -0,0 +1,101 @@
1
+ import { currencyInfo } from '@zkp2p/sdk';
2
+
3
+ type PlatformId = "venmo" | "cashapp" | "chime" | "revolut" | "wise" | "mercadopago" | "zelle" | "paypal" | "monzo" | "n26";
4
+ interface PlatformEntry {
5
+ readonly id: PlatformId;
6
+ readonly name: string;
7
+ readonly currencies: readonly string[];
8
+ readonly identifier: {
9
+ readonly label: string;
10
+ readonly placeholder: string;
11
+ readonly help: string;
12
+ };
13
+ validate(input: string): {
14
+ valid: boolean;
15
+ normalized: string;
16
+ error?: string;
17
+ };
18
+ }
19
+ /** All supported payment platforms. Access via `PLATFORMS.REVOLUT`, `PLATFORMS.WISE`, etc. */
20
+ declare const PLATFORMS: {
21
+ readonly VENMO: PlatformEntry;
22
+ readonly CASHAPP: PlatformEntry;
23
+ readonly CHIME: PlatformEntry;
24
+ readonly REVOLUT: PlatformEntry;
25
+ readonly WISE: PlatformEntry;
26
+ readonly MERCADO_PAGO: PlatformEntry;
27
+ readonly ZELLE: PlatformEntry;
28
+ readonly PAYPAL: PlatformEntry;
29
+ readonly MONZO: PlatformEntry;
30
+ readonly N26: PlatformEntry;
31
+ };
32
+
33
+ interface CurrencyEntry {
34
+ readonly code: string;
35
+ readonly name: string;
36
+ readonly symbol: string;
37
+ readonly countryCode: string;
38
+ }
39
+ type CurrencyMap = {
40
+ readonly [K in keyof typeof currencyInfo]: CurrencyEntry;
41
+ };
42
+ /** All supported currencies with metadata. Access via `CURRENCIES.EUR.symbol` etc. */
43
+ declare const CURRENCIES: CurrencyMap;
44
+
45
+ interface OfframpParams {
46
+ /** USDC amount as decimal string, min 1. */
47
+ amount: string;
48
+ /** Payment platform — use `PLATFORMS.REVOLUT` etc. */
49
+ platform: PlatformEntry;
50
+ /** Fiat currency — use `CURRENCIES.EUR` etc. */
51
+ currency: CurrencyEntry;
52
+ /** Platform-specific identifier (username, email, IBAN). */
53
+ identifier: string;
54
+ }
55
+ interface OfframpResult {
56
+ depositId: string;
57
+ txHash: string;
58
+ /** Whether an existing undelegated deposit was resumed. */
59
+ resumed: boolean;
60
+ }
61
+ type OfframpStep = "approving" | "registering" | "depositing" | "confirming" | "delegating" | "resuming" | "done";
62
+ interface OfframpProgress {
63
+ step: OfframpStep;
64
+ txHash?: string;
65
+ depositId?: string;
66
+ }
67
+ type OnProgress = (progress: OfframpProgress) => void;
68
+ type DepositStatus = "active" | "empty" | "closed";
69
+ interface DepositInfo {
70
+ /** Numeric deposit ID. Pass this to `close()`. */
71
+ depositId: string;
72
+ /** Composite ID (escrowAddress_depositId). */
73
+ compositeId: string;
74
+ /** Creation transaction hash. */
75
+ txHash?: string;
76
+ status: DepositStatus;
77
+ remainingUsdc: number;
78
+ outstandingUsdc: number;
79
+ totalTakenUsdc: number;
80
+ fulfilledIntents: number;
81
+ paymentMethods: string[];
82
+ currencies: string[];
83
+ rateSource: string;
84
+ delegated: boolean;
85
+ escrowAddress: string;
86
+ }
87
+
88
+ type OfframpErrorCode = "VALIDATION" | "APPROVAL_FAILED" | "REGISTRATION_FAILED" | "DEPOSIT_FAILED" | "CONFIRMATION_FAILED" | "DELEGATION_FAILED" | "USER_CANCELLED" | "UNSUPPORTED";
89
+ declare class OfframpError extends Error {
90
+ readonly code: OfframpErrorCode;
91
+ readonly step?: OfframpStep;
92
+ readonly cause?: unknown;
93
+ readonly txHash?: string;
94
+ readonly depositId?: string;
95
+ constructor(message: string, code: OfframpErrorCode, step?: OfframpStep, cause?: unknown, details?: {
96
+ txHash?: string;
97
+ depositId?: string;
98
+ });
99
+ }
100
+
101
+ export { CURRENCIES as C, type DepositInfo as D, type OfframpParams as O, PLATFORMS as P, type OnProgress as a, type OfframpResult as b, type CurrencyEntry as c, type DepositStatus as d, OfframpError as e, type OfframpErrorCode as f, type OfframpProgress as g, type OfframpStep as h, type PlatformEntry as i };