# @zkp2p/cash - Peer Cash > Offramp-only SDK for the ZKP2P protocol: route Relay-supported EVM assets or > NEAR Intents 1Click external deposits to Base USDC, then cash out to fiat > (Venmo, Revolut, Wise, Alipay, Zelle, ...) > at a zero-spread Chainlink market rate with no centralized > off-ramp provider. The user is the maker, a buyer pays them fiat and proves > the payment, and the SDK exposes readable order state. > Base-USDC flows are serializable through prepare paths; source-routed cashout > uses Relay execution first. React apps, Node services, and agent hosts use the > same typed surface. Key facts: - Optional Venmo receipt linking: prepareVenmoGmailConnect(handle) registers the selected handle and returns { payeeDetails, url }. From a separate click, openVenmoGmailConnect(payeeDetails) opens the environment's hosted flow. isVenmoGmailConnected(payeeDetails) checks for an active Google credential; lookup errors reject. Cashout and prepare never call or require these steps. Mobile may open a tab; check status on return or ambiguous popup closure. Google-hosted school/custom domains are supported; actual receipt failures use VenmoGmailConnectError.code, including venmo_google_oauth_receipt_not_found. Partner apps receive neither emails nor Google tokens. Re-prepare when the handle changes; persist payee hash with environment and user account. - The cashing-out user is the MAKER: their USDC becomes a protocol-held order; a buyer pays fiat and proves it with TEE-TLS; the protocol releases the USDC. - Destination is always Base USDC. Relay sources come from live SDK metadata; NEAR Intents sources come from live 1Click token discovery. - High-level source cashout uses EXACT_INPUT: amount is source-token base units. source.amount is Relay's guaranteed minimum Base USDC output and the exact order deposit amount, not the route's actual output. - NEAR Intents is an external-deposit flow: persist the signed quote, deposit address/memo, and deadline; send once with the origin wallet; optionally submit that existing hash; poll status to SUCCESS; reconcile Base evidence; then cash out Base-only. Use EXACT_OUTPUT when the order amount must be fixed. - estimate() reports its binding point. Existing corridors bind the on-chain oracle when an intent is signaled; Alipay/CNY fixes a fresh Ethereum Chainlink snapshot during deposit preparation; UPI/INR uses a fresh Polygon Chainlink snapshot. ETA is `{ seconds, label }` from the same rolling 30-day, intent-attributed pair sampler as fillStats(), not a guarantee. - fillStats() returns raw `{ fills, medianFillSeconds? }` evidence keyed by `platform:currency` or a sorted set such as `revolut:EUR+GBP+USD`. Set medians measure time to the first fill in any offered currency. Recommended consumer gate: fills >= 10 and median <= 48h; fail open to capabilities() if unavailable or filtering empties it. Its raw environment snapshot is cached for 15 minutes. - Progressive UIs can call estimate(input, { includeEta: false }) so the oracle rate is not blocked by indexer history, then load the exact pair from fillStats() separately. - capabilities() exposes one Zelle platform. A zelle cashout attaches only the generic Zelle payment method to the on-chain deposit. - UPI/INR is available without feature flags. For example, use `createCashClient({ environment: 'preproduction' })`. Any valid UPI ID from any bank can receive without a seller login, extension, identity attestation, or prior registration flow. Buyers pay and verify through Amazon Pay using standard UPI. - Resume any order from its depositId alone (composite escrow_onchainId). - One unwind verb: withdraw(depositId) - prunes expired intents automatically; pass amount for a partial withdrawal of the unlocked balance. - topUp(depositId, amount) adds USDC to a live order (same payee, same rate). - Base-USDC mutating verbs have unsigned counterparts (prepare, prepareWithdraw, prepareTopUp) for host-side signing; source-routed cashout needs signer-backed Relay execution first. prepare() and the cash_cashout tool are Base-USDC-only; cash_source_quote/status do not execute Relay, and the cash_near_intents_* tools never sign or broadcast the origin transfer. @zkp2p/cash/tools ships a JSON-schema tool manifest. Receipt finalization and policy preparation remain CashClient methods for the host adapter. - Errors are typed: { code, retryable, remediation, recovery? }. Completed Relay routes retain requestId, flat hashes, and origin/destination transactions. Retry Base-only after SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED; inspect Base activity/orders after SOURCE_CASHOUT_SUBMISSION_UNKNOWN; inspect depositTxHash before any action after SOURCE_CASHOUT_STATUS_UNKNOWN. Treat TRANSACTION_SUBMISSION_UNKNOWN as potentially broadcast. Retry INDEXER_UNAVAILABLE and ORACLE_READ_FAILED reads without repeating a transaction; fix SIGNER_CHAIN_MISMATCH or SIGNER_CHAIN_UNAVAILABLE before quoting or submitting. TRANSACTION_STATUS_UNKNOWN carries the submitted hash in recovery.transactionHash. - Everything is decoded to human units: platform ids and currency codes from their on-chain hashes, plain-number rates from 1e18 precision. - Fills are receipts: locked rate + fiat owed at signal; verified fiat paid, payment id, released USDC, and fill latency after the proof. - `receive` takes one payout leg or an array of legs across different platforms (each platform at most once); read each capability's pricing entry for its binding semantics. - Orders carry their payout legs (platform, currency, payee hash) plus indexed pricing evidence for either signal-time oracle or fixed-at-creation pricing. - Order reads fail closed when any deposit method is absent from the active catalog; mixed historical deposits are never partially reclassified. - buyer(address) aggregates a buyer's track record (fulfilled/pruned/success rate) from their full intent history. - Default path is same-chain Base USDC. Optional `source` on `cashout()` runs Relay source-to-Base-USDC first; non-Base source chains require `sourceSigner`. - `capabilities({ includeNearIntentsSources: true })`, `quoteNearIntentsSource()`, `submitNearIntentsDeposit()`, and `nearIntentsStatus()` support 1Click routes including non-EVM origins. A browser uses the same-origin proxy transport so the JWT stays server-side. - Wise, PayPal, and Alipay require attestation for a new payee registration. The SDK accepts but does not mint it; first-party Peer web obtains it through the Peer TEE browser extension. A previously registered bare handle can be reused. - Venmo and PayPal attach a method-scoped Peer Pay merchant policy after the deposit confirms, restricting which takers can signal an intent. The follow-ups are intentionally non-atomic; `cashout()` submits each with the same viem wallet, while prepared hosts iterate `accessPolicyPaymentMethods`. Method-scoped dispute protection is already default-on, so Cash does not readiness-gate creation or submit an explicit enable transaction. Cash App is non-chargebackable, stays public, and does not require dispute-protection stake. Any EOA works; Privy is not required. On ACCESS_POLICY_CONFIGURATION_FAILED, never repeat the cashout; inspect recovery.transactionHash before resubmitting a policy. - Preproduction uses https://api-preprod.zkp2p.xyz by default; staging uses https://api-staging.zkp2p.xyz. curatorUrl can override either. ## Links - npm: https://www.npmjs.com/package/@zkp2p/cash - Source: https://github.com/zkp2p/peer-cash ## Docs - [README](README.md): quickstart, verb table, lifecycle diagram - [AGENTS.md](AGENTS.md): agent integration manual - decision tree, prepare-path patterns, error → remediation table - [Lifecycle and recovery](docs/lifecycle-and-recovery.md): source routing, states, partial fills, ETA principle, unwind, resumability, failure table - [Partner integration patterns](docs/partner-integrations.md): custody choices, MPP settlement separation, agent-host setup, durable production state - [Integration skill](skills/peer-cash-integration/SKILL.md): step-by-step onboarding for coding agents, with the staging verification checklist ## Source - [Engine](src/engine/): pure order-state derivation and deposit-param construction (no I/O) - [Client](src/client/createCashClient.ts): the verb facade - Deposit integration referrals: pass the six-character Peer app code as `createCashClient({ referralCode })`; the SDK emits `peer-ref-XXXXXX` and no API key or referral-enrollment transaction is required. - [Tools manifest](src/tools/index.ts): JSON-schema definitions of the verbs - [Codecs](src/codecs/): zod schemas + lossless JSON round-trips UPI/INR reads the live Chainlink Polygon mainnet proxy `0xDA0F8Df6F5dB15b346f4B8D1156722027E194E60` (chain 137), inverts USD per INR, and rounds the creation-time maker floor up. Configure its read-only RPC with `upiCreationRateRpcUrl` or `upiCreationRateTransport`. Alipay/CNY retains the Ethereum registry and `creationRateRpcUrl` / `creationRateTransport`. UPI rejects the wrong chain, invalid rounds, and observations older than 24 hours; market closures do not bypass freshness. UPI is available in production, preproduction, and staging without a feature flag.