@zkp2p/cash 0.5.4-rc.1 → 0.6.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -8,7 +8,7 @@ You are integrating Peer Cash: an offramp that routes Relay-supported EVM
8
8
  assets or NEAR Intents 1Click external deposits into Base USDC, then converts
9
9
  Base USDC to fiat (Venmo, Revolut, Wise, Alipay, Zelle, ...) at a zero-spread
10
10
  Chainlink market rate. Existing corridors bind at intent signal; Alipay/CNY
11
- fixes a fresh Ethereum Chainlink snapshot during deposit preparation. The user whose USDC you
11
+ fixes a fresh Ethereum Chainlink snapshot during deposit preparation; UPI/INR uses Polygon Chainlink. The user whose USDC you
12
12
  manage is the **maker**; a buyer pays them fiat and proves it with TEE-TLS; the
13
13
  protocol releases the USDC. Funds are held by the protocol, and only the maker
14
14
  can withdraw an unmatched deposit.
@@ -70,10 +70,9 @@ deposit-level integration share instead of applying maker L1/L2.
70
70
  - **Venmo, Revolut, Cash App, Monzo** validate the handle against the live
71
71
  platform at registration - the account must exist. The rest (Zelle, Chime,
72
72
  etc.) are format-checked only. Match handles to the `payeeHint`.
73
- - **UPI is staging-only and opt-in.** Construct the client with
74
- `features: { upi: true }`. Any valid UPI ID from any bank can receive; there
73
+ - **UPI is available in every environment without a rollout flag.** Any valid UPI ID from any bank can receive; there
75
74
  is no seller bank login, extension, identity attestation, or prior
76
- registration flow. Buyers currently prove from HDFC Bank through Gmail.
75
+ registration flow. Buyers pay and verify through Amazon Pay using standard UPI.
77
76
 
78
77
  ## The loop
79
78
 
@@ -196,8 +195,8 @@ const route = await cash.nearIntentsStatus({
196
195
 
197
196
  - **Respect the declared binding point.** `estimate()` is
198
197
  `kind: 'oracle-estimate'`. Its `binding` is `intent-signal` for existing
199
- on-chain oracle corridors and `deposit-creation` for Alipay/CNY. Do not call
200
- an estimate locked before that point. Once Alipay/CNY is prepared, its fresh
198
+ on-chain oracle corridors and `deposit-creation` for Alipay/CNY and UPI/INR. Do not call
199
+ an estimate locked before that point. Once a creation-time corridor is prepared, its fresh
201
200
  Chainlink snapshot is the on-chain maker floor.
202
201
  - **Do not invent an ETA.** Use `estimate().eta`: `{ seconds, label }` backed
203
202
  by the same rolling 30-day, intent-attributed pair sample as `fillStats()`,
@@ -342,4 +341,4 @@ read-only RPC with `upiCreationRateRpcUrl` or `upiCreationRateTransport`.
342
341
  Alipay/CNY retains the Ethereum registry and `creationRateRpcUrl` /
343
342
  `creationRateTransport`. UPI rejects the wrong chain, invalid rounds, and
344
343
  observations older than 24 hours; market closures do not bypass freshness.
345
- This does not change the staging-only UPI opt-in gate.
344
+ UPI is available in production, preproduction, and staging without a feature flag.
package/README.md CHANGED
@@ -4,8 +4,8 @@ Route Relay-supported EVM assets or NEAR Intents 1Click external deposits into
4
4
  Base USDC, then cash out to fiat on Venmo, Revolut, Wise, Alipay, Zelle, and
5
5
  more at a zero-spread Chainlink market rate with no centralized off-ramp
6
6
  provider. Existing corridors bind the live oracle when a buyer signals;
7
- Alipay/CNY fixes a fresh Ethereum Chainlink snapshot when the SDK prepares the
8
- deposit.
7
+ Alipay/CNY and UPI/INR fix fresh Chainlink snapshots when the SDK prepares
8
+ the deposit (Ethereum for CNY; Polygon for INR).
9
9
 
10
10
  Peer Cash is an **offramp-only** SDK for the [ZKP2P](https://peer.xyz)
11
11
  protocol. The cashing-out user is the maker: their USDC becomes a deposit in
@@ -94,17 +94,17 @@ for await (const order of cash.watch(depositId)) {
94
94
  }
95
95
  ```
96
96
 
97
- ### Staging UPI cash-out
97
+ ### Staging and preproduction UPI cash-out
98
98
 
99
- UPI is an opt-in staging corridor until the payment method exists in production
100
- contracts. Any valid UPI ID from any bank can receive a cash-out. The seller
99
+ UPI requires the canonical UPI/INR catalog from `@zkp2p/sdk` 0.14.2-rc.1
100
+ or its approved successor; a missing catalog entry keeps the corridor disabled.
101
+ UPI is available in every environment without an opt-in. Any valid UPI ID from any bank can receive a cash-out. The seller
101
102
  does not connect a bank account, install an extension, or complete a separate
102
103
  registration flow:
103
104
 
104
105
  ```ts
105
106
  const cash = createCashClient({
106
- environment: 'staging',
107
- features: { upi: true },
107
+ environment: 'preproduction',
108
108
  });
109
109
 
110
110
  await cash.cashout(
@@ -116,18 +116,25 @@ await cash.cashout(
116
116
  );
117
117
  ```
118
118
 
119
- Buyers currently prove UPI payments from HDFC Bank through one-shot, read-only
120
- Gmail access. That buyer limitation does not restrict which bank issued the
121
- seller's UPI ID.
119
+ Buyers pay and verify through Amazon Pay using standard UPI. UPI Lite and
120
+ merchant payments are unsupported. The seller may receive at a valid UPI ID
121
+ from any bank.
122
+
123
+ INR pricing uses the [Chainlink Polygon INR/USD feed](https://data.chain.link/feeds/polygon/mainnet/inr-usd),
124
+ inverted into INR per USDC and fixed at deposit preparation. The SDK rejects
125
+ invalid rounds and readings older than 24 hours, including market-hour gaps.
126
+ Only oracle reads use Polygon; funds and transactions stay on Base. Override
127
+ the Polygon reader with `upiCreationRateTransport` or `upiCreationRateRpcUrl`.
128
+ The existing `creationRateTransport`/`creationRateRpcUrl` options remain Ethereum-only for CNY.
122
129
 
123
130
  ## Pick the right SDK
124
131
 
125
132
  Peer Cash and the general ZKP2P SDK serve different integration depths:
126
133
 
127
- | Package | Use it when | Boundary |
128
- | ------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
129
- | `@zkp2p/cash` | Cash-out is the product | Offramp only. The user is always the maker, the destination is Base USDC, pricing is zero-spread Chainlink (signal-time by default; creation-time for Alipay/CNY), and the SDK owns the resumable order lifecycle. |
130
- | `@zkp2p/sdk` | You are composing directly with the Peer protocol | General maker and taker operations, deposits, intents, proofs, quotes, vaults, rate managers, referrals, hooks, and API helpers. Your application owns the workflow and protocol choices. |
134
+ | Package | Use it when | Boundary |
135
+ | ------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
136
+ | `@zkp2p/cash` | Cash-out is the product | Offramp only. The user is always the maker, the destination is Base USDC, pricing is zero-spread Chainlink (signal-time by default; creation-time for Alipay/CNY and UPI/INR), and the SDK owns the resumable order lifecycle. |
137
+ | `@zkp2p/sdk` | You are composing directly with the Peer protocol | General maker and taker operations, deposits, intents, proofs, quotes, vaults, rate managers, referrals, hooks, and API helpers. Your application owns the workflow and protocol choices. |
131
138
 
132
139
  Peer Cash is a narrow facade over `@zkp2p/sdk`, not a replacement for it. It
133
140
  cannot express custom spreads, buyer-side proof flows, vaults, disputes, or
@@ -183,7 +190,7 @@ mixed historical deposit.
183
190
  | PayPal | Same method-scoped Peer Pay follow-up | Requires a Peer TEE browser-extension identity attestation |
184
191
  | Cash App | No access-policy follow-up; non-chargebackable and no stake required | Curator validates the live handle |
185
192
  | Wise | No access-policy follow-up | Requires a Peer TEE browser-extension identity attestation |
186
- | UPI (staging opt-in) | No access-policy follow-up | Any valid UPI ID; no account connection or identity attestation |
193
+ | UPI | No access-policy follow-up | Any valid UPI ID; no account connection or identity attestation |
187
194
  | Other supported rails | No access-policy follow-up; use `capabilities()` for currencies and format | Follow the `payeeHint`; live-validation behavior is described in the integration guide |
188
195
 
189
196
  No platform requires an atomic access-policy flow. `cashout()` and `prepare()`
@@ -380,7 +387,7 @@ awaiting-buyer ──────────► matched ───────
380
387
  resulting CNY-per-USDC maker floor when it prepares the deposit. A buyer may
381
388
  signal at that floor or a better rate for the maker.
382
389
  - **Read `binding`.** `estimate().binding` is `intent-signal` by default and
383
- `deposit-creation` for Alipay/CNY. An estimate remains approximate until its
390
+ `deposit-creation` for Alipay/CNY and UPI/INR. An estimate remains approximate until its
384
391
  stated binding point.
385
392
  - **ETA is historical.** `estimate().eta` is just `{ seconds, label }`, backed
386
393
  by the same rolling 30-day, intent-attributed pair sampler as `fillStats()`,
@@ -474,7 +481,7 @@ is the default source and the only destination asset for cashout orders.
474
481
  Runnable first-party examples in [`examples/`](examples):
475
482
 
476
483
  - [`node-cashout.ts`](examples/node-cashout.ts) - server-side cash-out with a private-key signer, plus order tracking.
477
- - [`upi-staging-cashout.ts`](examples/upi-staging-cashout.ts) - opt-in UPI/INR cash-out to any valid UPI ID on staging.
484
+ - [`upi-staging-cashout.ts`](examples/upi-staging-cashout.ts) - UPI/INR cash-out to any valid UPI ID on staging or preproduction.
478
485
  - [`agent-tool-use.ts`](examples/agent-tool-use.ts) - wiring the verbs into an agent tool-use loop with host-side signing.
479
486
  - [`carpe-diem-provider-cashout`](examples/carpe-diem-provider-cashout) - cash out confirmed Carpe Diem provider DIEM revenue through the connected Base wallet.
480
487
  - [`mpp-merchant-cashout`](examples/mpp-merchant-cashout) - turn confirmed MPP merchant revenue into an unsigned Peer Cash plan while the merchant keeps custody and signing.
@@ -498,12 +505,3 @@ the package, not the contributor entry point.
498
505
  ## License
499
506
 
500
507
  MIT
501
-
502
- UPI/INR reads the live Chainlink Polygon mainnet proxy
503
- `0xDA0F8Df6F5dB15b346f4B8D1156722027E194E60` (chain 137), inverts
504
- USD per INR, and rounds the creation-time maker floor up. Configure its
505
- read-only RPC with `upiCreationRateRpcUrl` or `upiCreationRateTransport`.
506
- Alipay/CNY retains the Ethereum registry and `creationRateRpcUrl` /
507
- `creationRateTransport`. UPI rejects the wrong chain, invalid rounds, and
508
- observations older than 24 hours; market closures do not bypass freshness.
509
- This does not change the staging-only UPI opt-in gate.
@@ -468,16 +468,10 @@ declare function quoteNearIntentsToBaseUsdc(input: NearIntentsQuoteInput, option
468
468
  declare function submitNearIntentsDeposit(input: NearIntentsDepositInput, options?: NearIntentsOptions): Promise<NearIntentsStatus>;
469
469
  declare function readNearIntentsStatus(input: NearIntentsStatusInput, options?: NearIntentsOptions): Promise<NearIntentsStatus>;
470
470
 
471
- interface CashCatalogFeatures {
472
- upi?: boolean;
473
- }
474
-
475
471
  /** Hard floor: below one cent a deposit is dust and can never fill. */
476
472
  declare const MIN_CASHOUT_AMOUNT = 10000n;
477
473
  /** Recommended floor: sub-1-USDC deposits force min==max fills and starve matching. */
478
474
  declare const RECOMMENDED_MIN_CASHOUT_AMOUNT = 1000000n;
479
- /** Opt-in product surfaces that are not yet available on production contracts. */
480
- type CashFeatureFlags = CashCatalogFeatures;
481
475
  type CashCorridorPricing = {
482
476
  kind: 'oracle-at-intent-signal';
483
477
  spreadBps: 0;
@@ -560,7 +554,7 @@ interface CashCapabilities {
560
554
  spreadBps: 0;
561
555
  };
562
556
  }
563
- declare function buildCapabilities(environment: RuntimeEnv, features?: CashFeatureFlags): CashCapabilities;
557
+ declare function buildCapabilities(environment: RuntimeEnv): CashCapabilities;
564
558
 
565
559
  interface CashPairFillStats {
566
560
  /** Fulfilled intents through this pair or currency set inside the rolling 30-day window. */
@@ -674,8 +668,6 @@ declare function toCashReferralAttributionCode(rawCode: string): string;
674
668
  interface CashClientOptions {
675
669
  /** `'production' | 'preproduction' | 'staging'` - selects contracts, curator, and indexer. */
676
670
  environment: RuntimeEnv;
677
- /** Fail-closed opt-ins for corridors that are not deployed to production. */
678
- features?: CashFeatureFlags;
679
671
  /** viem transport for RPC reads; defaults to the public Base RPC. */
680
672
  transport?: Transport;
681
673
  /** Convenience alternative to `transport`. */
@@ -949,4 +941,4 @@ interface CashClient {
949
941
  }
950
942
  declare function createCashClient(options: CashClientOptions): CashClient;
951
943
 
952
- export { type CuratorPayeeDataInput as $, type CashChain as A, BASE_CHAIN_ID as B, type CashPayoutInfo as C, type CashClient as D, type CashClientOptions as E, type CashCorridorPricing as F, type CashFeatureFlags as G, type CashFillEta as H, type IntentEntity as I, type CashLeg as J, type CashMultiCurrencyLeg as K, type CashNextAction as L, type CashOrderState as M, type NearIntentsSourceCapabilities as N, type CashPairFillStats as O, type PrepareResult as P, type CashPayeeInput as Q, type RelayExecutionResult as R, type CashPayout as S, type TopUpResult as T, type CashPayoutPricing as U, type CashPlatformCapability as V, type WithdrawResult as W, type CashPreparedStepKind as X, type CashReceiveLeg as Y, type CashoutInput as Z, type CashoutOptions as _, type CashBuyerProfile as a, type EstimateInput as a0, type EstimateOptions as a1, MARKET_SPREAD_BPS as a2, MIN_CASHOUT_AMOUNT as a3, NEAR_INTENTS_API_URL as a4, NEAR_INTENTS_BASE_USDC_ASSET_ID as a5, NEAR_INTENTS_DEFAULT_SLIPPAGE_BPS as a6, NEAR_INTENTS_STATUSES as a7, type NearIntentsClient as a8, type NearIntentsOptions as a9, type NearIntentsQuoteRequest as aa, type NearIntentsStatusCode as ab, type NearIntentsToken as ac, type NearIntentsTradeType as ad, type NearIntentsTransaction as ae, ORACLE_MIN_CONVERSION_RATE_SENTINEL as af, type OrdersOptions as ag, type PreparedCashoutReceipt as ah, RECOMMENDED_MIN_CASHOUT_AMOUNT as ai, type RelayOptions as aj, type RelayQuoteInput as ak, type RelaySourceInput as al, type RelayTransaction as am, type SignerOptions as an, USDC_DECIMALS as ao, type WatchOptions as ap, type WithdrawOptions as aq, buildCapabilities as ar, createCashClient as as, createNearIntentsClient as at, normalizeCashPayee as au, quoteNearIntentsToBaseUsdc as av, readNearIntentsSourceCapabilities as aw, readNearIntentsStatus as ax, submitNearIntentsDeposit as ay, toCashReferralAttributionCode as az, type CashDepositInput as b, type CashCatalogFeatures as c, type CreateDepositParamsArg as d, type CashOrder as e, type CashFill as f, type CashCapabilities as g, type CashoutResult as h, type CashEstimate as i, type CashFillStats as j, type NearIntentsDepositInput as k, type NearIntentsQuote as l, type NearIntentsQuoteInput as m, type NearIntentsStatus as n, type NearIntentsStatusInput as o, type CashPreparedStep as p, type RelayQuote as q, type RelayStatus as r, type CashSourceCapabilities as s, BASE_USDC_ADDRESS as t, CASH_ATTRIBUTION_CODE as u, CASH_ORDER_POLL_INTERVAL_MS as v, CASH_ORDER_STATUSES as w, CASH_REFERRAL_ATTRIBUTION_PREFIX as x, CASH_RETAIN_ON_EMPTY as y, type CashAsset as z };
944
+ export { type EstimateOptions as $, type CashClient as A, BASE_CHAIN_ID as B, type CashPayoutInfo as C, type CashClientOptions as D, type CashCorridorPricing as E, type CashFillEta as F, type CashLeg as G, type CashMultiCurrencyLeg as H, type IntentEntity as I, type CashNextAction as J, type CashOrderState as K, type CashPairFillStats as L, type CashPayeeInput as M, type NearIntentsSourceCapabilities as N, type CashPayout as O, type PrepareResult as P, type CashPayoutPricing as Q, type RelayExecutionResult as R, type CashPlatformCapability as S, type TopUpResult as T, type CashPreparedStepKind as U, type CashReceiveLeg as V, type WithdrawResult as W, type CashoutInput as X, type CashoutOptions as Y, type CuratorPayeeDataInput as Z, type EstimateInput as _, type CashBuyerProfile as a, MARKET_SPREAD_BPS as a0, MIN_CASHOUT_AMOUNT as a1, NEAR_INTENTS_API_URL as a2, NEAR_INTENTS_BASE_USDC_ASSET_ID as a3, NEAR_INTENTS_DEFAULT_SLIPPAGE_BPS as a4, NEAR_INTENTS_STATUSES as a5, type NearIntentsClient as a6, type NearIntentsOptions as a7, type NearIntentsQuoteRequest as a8, type NearIntentsStatusCode as a9, type NearIntentsToken as aa, type NearIntentsTradeType as ab, type NearIntentsTransaction as ac, ORACLE_MIN_CONVERSION_RATE_SENTINEL as ad, type OrdersOptions as ae, type PreparedCashoutReceipt as af, RECOMMENDED_MIN_CASHOUT_AMOUNT as ag, type RelayOptions as ah, type RelayQuoteInput as ai, type RelaySourceInput as aj, type RelayTransaction as ak, type SignerOptions as al, USDC_DECIMALS as am, type WatchOptions as an, type WithdrawOptions as ao, buildCapabilities as ap, createCashClient as aq, createNearIntentsClient as ar, normalizeCashPayee as as, quoteNearIntentsToBaseUsdc as at, readNearIntentsSourceCapabilities as au, readNearIntentsStatus as av, submitNearIntentsDeposit as aw, toCashReferralAttributionCode as ax, type CashDepositInput as b, type CreateDepositParamsArg as c, type CashOrder as d, type CashFill as e, type CashCapabilities as f, type CashoutResult as g, type CashEstimate as h, type CashFillStats as i, type NearIntentsDepositInput as j, type NearIntentsQuote as k, type NearIntentsQuoteInput as l, type NearIntentsStatus as m, type NearIntentsStatusInput as n, type CashPreparedStep as o, type RelayQuote as p, type RelayStatus as q, type CashSourceCapabilities as r, BASE_USDC_ADDRESS as s, CASH_ATTRIBUTION_CODE as t, CASH_ORDER_POLL_INTERVAL_MS as u, CASH_ORDER_STATUSES as v, CASH_REFERRAL_ATTRIBUTION_PREFIX as w, CASH_RETAIN_ON_EMPTY as x, type CashAsset as y, type CashChain as z };
@@ -468,16 +468,10 @@ declare function quoteNearIntentsToBaseUsdc(input: NearIntentsQuoteInput, option
468
468
  declare function submitNearIntentsDeposit(input: NearIntentsDepositInput, options?: NearIntentsOptions): Promise<NearIntentsStatus>;
469
469
  declare function readNearIntentsStatus(input: NearIntentsStatusInput, options?: NearIntentsOptions): Promise<NearIntentsStatus>;
470
470
 
471
- interface CashCatalogFeatures {
472
- upi?: boolean;
473
- }
474
-
475
471
  /** Hard floor: below one cent a deposit is dust and can never fill. */
476
472
  declare const MIN_CASHOUT_AMOUNT = 10000n;
477
473
  /** Recommended floor: sub-1-USDC deposits force min==max fills and starve matching. */
478
474
  declare const RECOMMENDED_MIN_CASHOUT_AMOUNT = 1000000n;
479
- /** Opt-in product surfaces that are not yet available on production contracts. */
480
- type CashFeatureFlags = CashCatalogFeatures;
481
475
  type CashCorridorPricing = {
482
476
  kind: 'oracle-at-intent-signal';
483
477
  spreadBps: 0;
@@ -560,7 +554,7 @@ interface CashCapabilities {
560
554
  spreadBps: 0;
561
555
  };
562
556
  }
563
- declare function buildCapabilities(environment: RuntimeEnv, features?: CashFeatureFlags): CashCapabilities;
557
+ declare function buildCapabilities(environment: RuntimeEnv): CashCapabilities;
564
558
 
565
559
  interface CashPairFillStats {
566
560
  /** Fulfilled intents through this pair or currency set inside the rolling 30-day window. */
@@ -674,8 +668,6 @@ declare function toCashReferralAttributionCode(rawCode: string): string;
674
668
  interface CashClientOptions {
675
669
  /** `'production' | 'preproduction' | 'staging'` - selects contracts, curator, and indexer. */
676
670
  environment: RuntimeEnv;
677
- /** Fail-closed opt-ins for corridors that are not deployed to production. */
678
- features?: CashFeatureFlags;
679
671
  /** viem transport for RPC reads; defaults to the public Base RPC. */
680
672
  transport?: Transport;
681
673
  /** Convenience alternative to `transport`. */
@@ -949,4 +941,4 @@ interface CashClient {
949
941
  }
950
942
  declare function createCashClient(options: CashClientOptions): CashClient;
951
943
 
952
- export { type CuratorPayeeDataInput as $, type CashChain as A, BASE_CHAIN_ID as B, type CashPayoutInfo as C, type CashClient as D, type CashClientOptions as E, type CashCorridorPricing as F, type CashFeatureFlags as G, type CashFillEta as H, type IntentEntity as I, type CashLeg as J, type CashMultiCurrencyLeg as K, type CashNextAction as L, type CashOrderState as M, type NearIntentsSourceCapabilities as N, type CashPairFillStats as O, type PrepareResult as P, type CashPayeeInput as Q, type RelayExecutionResult as R, type CashPayout as S, type TopUpResult as T, type CashPayoutPricing as U, type CashPlatformCapability as V, type WithdrawResult as W, type CashPreparedStepKind as X, type CashReceiveLeg as Y, type CashoutInput as Z, type CashoutOptions as _, type CashBuyerProfile as a, type EstimateInput as a0, type EstimateOptions as a1, MARKET_SPREAD_BPS as a2, MIN_CASHOUT_AMOUNT as a3, NEAR_INTENTS_API_URL as a4, NEAR_INTENTS_BASE_USDC_ASSET_ID as a5, NEAR_INTENTS_DEFAULT_SLIPPAGE_BPS as a6, NEAR_INTENTS_STATUSES as a7, type NearIntentsClient as a8, type NearIntentsOptions as a9, type NearIntentsQuoteRequest as aa, type NearIntentsStatusCode as ab, type NearIntentsToken as ac, type NearIntentsTradeType as ad, type NearIntentsTransaction as ae, ORACLE_MIN_CONVERSION_RATE_SENTINEL as af, type OrdersOptions as ag, type PreparedCashoutReceipt as ah, RECOMMENDED_MIN_CASHOUT_AMOUNT as ai, type RelayOptions as aj, type RelayQuoteInput as ak, type RelaySourceInput as al, type RelayTransaction as am, type SignerOptions as an, USDC_DECIMALS as ao, type WatchOptions as ap, type WithdrawOptions as aq, buildCapabilities as ar, createCashClient as as, createNearIntentsClient as at, normalizeCashPayee as au, quoteNearIntentsToBaseUsdc as av, readNearIntentsSourceCapabilities as aw, readNearIntentsStatus as ax, submitNearIntentsDeposit as ay, toCashReferralAttributionCode as az, type CashDepositInput as b, type CashCatalogFeatures as c, type CreateDepositParamsArg as d, type CashOrder as e, type CashFill as f, type CashCapabilities as g, type CashoutResult as h, type CashEstimate as i, type CashFillStats as j, type NearIntentsDepositInput as k, type NearIntentsQuote as l, type NearIntentsQuoteInput as m, type NearIntentsStatus as n, type NearIntentsStatusInput as o, type CashPreparedStep as p, type RelayQuote as q, type RelayStatus as r, type CashSourceCapabilities as s, BASE_USDC_ADDRESS as t, CASH_ATTRIBUTION_CODE as u, CASH_ORDER_POLL_INTERVAL_MS as v, CASH_ORDER_STATUSES as w, CASH_REFERRAL_ATTRIBUTION_PREFIX as x, CASH_RETAIN_ON_EMPTY as y, type CashAsset as z };
944
+ export { type EstimateOptions as $, type CashClient as A, BASE_CHAIN_ID as B, type CashPayoutInfo as C, type CashClientOptions as D, type CashCorridorPricing as E, type CashFillEta as F, type CashLeg as G, type CashMultiCurrencyLeg as H, type IntentEntity as I, type CashNextAction as J, type CashOrderState as K, type CashPairFillStats as L, type CashPayeeInput as M, type NearIntentsSourceCapabilities as N, type CashPayout as O, type PrepareResult as P, type CashPayoutPricing as Q, type RelayExecutionResult as R, type CashPlatformCapability as S, type TopUpResult as T, type CashPreparedStepKind as U, type CashReceiveLeg as V, type WithdrawResult as W, type CashoutInput as X, type CashoutOptions as Y, type CuratorPayeeDataInput as Z, type EstimateInput as _, type CashBuyerProfile as a, MARKET_SPREAD_BPS as a0, MIN_CASHOUT_AMOUNT as a1, NEAR_INTENTS_API_URL as a2, NEAR_INTENTS_BASE_USDC_ASSET_ID as a3, NEAR_INTENTS_DEFAULT_SLIPPAGE_BPS as a4, NEAR_INTENTS_STATUSES as a5, type NearIntentsClient as a6, type NearIntentsOptions as a7, type NearIntentsQuoteRequest as a8, type NearIntentsStatusCode as a9, type NearIntentsToken as aa, type NearIntentsTradeType as ab, type NearIntentsTransaction as ac, ORACLE_MIN_CONVERSION_RATE_SENTINEL as ad, type OrdersOptions as ae, type PreparedCashoutReceipt as af, RECOMMENDED_MIN_CASHOUT_AMOUNT as ag, type RelayOptions as ah, type RelayQuoteInput as ai, type RelaySourceInput as aj, type RelayTransaction as ak, type SignerOptions as al, USDC_DECIMALS as am, type WatchOptions as an, type WithdrawOptions as ao, buildCapabilities as ap, createCashClient as aq, createNearIntentsClient as ar, normalizeCashPayee as as, quoteNearIntentsToBaseUsdc as at, readNearIntentsSourceCapabilities as au, readNearIntentsStatus as av, submitNearIntentsDeposit as aw, toCashReferralAttributionCode as ax, type CashDepositInput as b, type CreateDepositParamsArg as c, type CashOrder as d, type CashFill as e, type CashCapabilities as f, type CashoutResult as g, type CashEstimate as h, type CashFillStats as i, type NearIntentsDepositInput as j, type NearIntentsQuote as k, type NearIntentsQuoteInput as l, type NearIntentsStatus as m, type NearIntentsStatusInput as n, type CashPreparedStep as o, type RelayQuote as p, type RelayStatus as q, type CashSourceCapabilities as r, BASE_USDC_ADDRESS as s, CASH_ATTRIBUTION_CODE as t, CASH_ORDER_POLL_INTERVAL_MS as u, CASH_ORDER_STATUSES as v, CASH_REFERRAL_ATTRIBUTION_PREFIX as w, CASH_RETAIN_ON_EMPTY as x, type CashAsset as y, type CashChain as z };
package/dist/index.cjs CHANGED
@@ -142,26 +142,12 @@ async function readCashCreationRate(publicClient, platform, currency, nowSeconds
142
142
  async function readAlipayCnyCreationRate(publicClient, nowSeconds = Math.floor(Date.now() / 1e3)) {
143
143
  return readCashCreationRate(publicClient, "alipay", "CNY", nowSeconds);
144
144
  }
145
- var UPI_STAGING_PAYMENT_METHOD_HASH = "0xe99a5081226cbbff9440a63da5caa04fa30f210c12c4dd9976132ac075054cd9";
146
- function getCashPaymentMethodsCatalog(environment, features = {}) {
147
- const catalog = sdk.getPaymentMethodsCatalog(8453, environment);
148
- if (environment !== "staging" || features.upi !== true || catalog.upi) {
149
- return catalog;
150
- }
151
- return {
152
- ...catalog,
153
- upi: {
154
- paymentMethodHash: UPI_STAGING_PAYMENT_METHOD_HASH,
155
- currencies: [sdk.currencyInfo.INR.currencyCodeHash],
156
- timestampBuffer: 30,
157
- providerHashes: []
158
- }
159
- };
145
+ function getCashPaymentMethodsCatalog(environment) {
146
+ return sdk.getPaymentMethodsCatalog(8453, environment);
160
147
  }
161
148
  function resolveCashPaymentMethodHash(processorName, catalog) {
162
- const normalized = processorName.trim().toLowerCase();
163
- if (normalized === "upi" && catalog.upi) {
164
- return catalog.upi.paymentMethodHash;
149
+ if (processorName.trim().toLowerCase() === "upi" && !catalog.upi) {
150
+ throw new Error("UPI is not enabled in this environment catalog");
165
151
  }
166
152
  return sdk.resolvePaymentMethodHashFromCatalog(processorName, catalog);
167
153
  }
@@ -200,12 +186,12 @@ function buildIntentAmountRange(amount) {
200
186
  const min = amount < DEFAULT_MIN_ORDER_FLOOR ? amount : DEFAULT_MIN_ORDER_FLOOR;
201
187
  return { min, max: amount };
202
188
  }
203
- async function prepareCashDepositParams(client, input, adapters, creationRateReader, features) {
189
+ async function prepareCashDepositParams(client, input, adapters, creationRateReader) {
204
190
  const { payouts } = input;
205
191
  if (!payouts.length) throw new Error("At least one payout is required");
206
192
  const chainId = client.chainId;
207
193
  const runtimeEnv = client.runtimeEnv;
208
- const catalog = getCashPaymentMethodsCatalog(runtimeEnv, features);
194
+ const catalog = getCashPaymentMethodsCatalog(runtimeEnv);
209
195
  const intentGatingService = sdk.getGatingServiceAddress(chainId, runtimeEnv);
210
196
  const processorNames = payouts.map((p) => p.processorName);
211
197
  const paymentMethodsOverride = processorNames.map(
@@ -641,8 +627,8 @@ var IDENTITY_ATTESTATION_PLATFORMS = /* @__PURE__ */ new Set(["wise", "paypal",
641
627
  function platformRequiresIdentityAttestation(platform) {
642
628
  return IDENTITY_ATTESTATION_PLATFORMS.has(platform.toLowerCase());
643
629
  }
644
- function buildCapabilities(environment, features = {}) {
645
- const catalog = getCashPaymentMethodsCatalog(environment, features);
630
+ function buildCapabilities(environment) {
631
+ const catalog = getCashPaymentMethodsCatalog(environment);
646
632
  const platforms = Object.entries(catalog).map(([platform, entry]) => {
647
633
  const currencies2 = (entry.currencies ?? []).map((hash) => sdk.getCurrencyCodeFromHash(hash)).filter(
648
634
  (code) => code != null && (isMarketRateSupported(code) || isCreationRateCorridor(platform, code))
@@ -665,9 +651,7 @@ function buildCapabilities(environment, features = {}) {
665
651
  requiresIdentityAttestation: IDENTITY_ATTESTATION_PLATFORMS.has(platform),
666
652
  requiresAtomicAccessPolicy: false
667
653
  };
668
- }).filter(
669
- (p) => p.currencies.length > 0 && (p.platform !== "upi" || environment === "staging" && features.upi === true)
670
- ).sort((a, b) => a.platform.localeCompare(b.platform));
654
+ }).filter((p) => p.currencies.length > 0).sort((a, b) => a.platform.localeCompare(b.platform));
671
655
  const currencies = [...new Set(platforms.flatMap((p) => p.currencies))].sort();
672
656
  const baseUsdc = { address: BASE_USDC_ADDRESS, symbol: "USDC", decimals: USDC_DECIMALS };
673
657
  return {
@@ -2923,8 +2907,8 @@ async function submitAndConfirm(client, verb, send) {
2923
2907
  function isKnownPreBroadcastFailure(mapped) {
2924
2908
  return mapped.code === "TRANSACTION_REJECTED" || mapped.code === "INSUFFICIENT_TOKEN_BALANCE" || mapped.code === "ALLOWANCE_NOT_VISIBLE" || mapped.code === "ESCROW_PAUSED";
2925
2909
  }
2926
- function cashoutAccessPolicyPaymentMethods(depositInput, environment, features) {
2927
- const catalog = getCashPaymentMethodsCatalog(environment, features);
2910
+ function cashoutAccessPolicyPaymentMethods(depositInput, environment) {
2911
+ const catalog = getCashPaymentMethodsCatalog(environment);
2928
2912
  return [
2929
2913
  ...new Set(
2930
2914
  depositInput.payouts.filter((payout) => CASH_RESTRICTED_PLATFORMS.has(payout.processorName.toLowerCase())).map((payout) => resolveCashPaymentMethodHash(payout.processorName, catalog))
@@ -3021,7 +3005,7 @@ function createCashClient(options) {
3021
3005
  if (legs.length === 0) {
3022
3006
  throw errors.invalidPayoutPlatforms("at least one payout leg is required");
3023
3007
  }
3024
- const capabilities2 = buildCapabilities(environment, options.features);
3008
+ const capabilities2 = buildCapabilities(environment);
3025
3009
  const seenPlatforms = /* @__PURE__ */ new Set();
3026
3010
  const payouts = legs.map((leg) => {
3027
3011
  const platform = capabilities2.platforms.find(
@@ -3102,8 +3086,7 @@ function createCashClient(options) {
3102
3086
  } catch (err) {
3103
3087
  throw errors.oracleReadFailed(currency, err);
3104
3088
  }
3105
- },
3106
- options.features
3089
+ }
3107
3090
  );
3108
3091
  } catch (err) {
3109
3092
  if (isCashError(err)) throw err;
@@ -3155,7 +3138,7 @@ function createCashClient(options) {
3155
3138
  const payouts = derivePayouts(
3156
3139
  deposit.paymentMethods ?? [],
3157
3140
  deposit.currencies ?? [],
3158
- getCashPaymentMethodsCatalog(environment, options.features)
3141
+ getCashPaymentMethodsCatalog(environment)
3159
3142
  );
3160
3143
  let attributedToCash = false;
3161
3144
  if (!isCashPayoutSet(payouts)) {
@@ -3213,7 +3196,7 @@ function createCashClient(options) {
3213
3196
  return escrowContext(depositId);
3214
3197
  }
3215
3198
  function capabilities(capabilityOptions) {
3216
- const baseCapabilities = buildCapabilities(environment, options.features);
3199
+ const baseCapabilities = buildCapabilities(environment);
3217
3200
  if (!capabilityOptions?.includeRelaySources && !capabilityOptions?.includeNearIntentsSources) {
3218
3201
  return baseCapabilities;
3219
3202
  }
@@ -3391,11 +3374,7 @@ function createCashClient(options) {
3391
3374
  }
3392
3375
  async function configureCashoutAccess(client, signer, depositInput, depositId, source) {
3393
3376
  const groupIds = CASH_ACCESS_GROUP_IDS[environment];
3394
- const paymentMethods = cashoutAccessPolicyPaymentMethods(
3395
- depositInput,
3396
- environment,
3397
- options.features
3398
- );
3377
+ const paymentMethods = cashoutAccessPolicyPaymentMethods(depositInput, environment);
3399
3378
  const hashes = [];
3400
3379
  for (const paymentMethod of paymentMethods) {
3401
3380
  const prepared = prepareCashoutAccess(depositId, paymentMethod, client, source);
@@ -3701,8 +3680,7 @@ function createCashClient(options) {
3701
3680
  const hashedOnchainIds = (params.paymentMethodDataOverride ?? []).map((d) => d.payeeDetails);
3702
3681
  const accessPolicyPaymentMethods = cashoutAccessPolicyPaymentMethods(
3703
3682
  depositInput,
3704
- environment,
3705
- options.features
3683
+ environment
3706
3684
  );
3707
3685
  return {
3708
3686
  txs: [approve, prepared],
@@ -3773,7 +3751,7 @@ function createCashClient(options) {
3773
3751
  } catch (err) {
3774
3752
  throw errors.indexerUnavailable("orders", err);
3775
3753
  }
3776
- const catalog = getCashPaymentMethodsCatalog(environment, options.features);
3754
+ const catalog = getCashPaymentMethodsCatalog(environment);
3777
3755
  let attributedCashDeposits = /* @__PURE__ */ new Set();
3778
3756
  const fixedRateCandidates = deposits.filter((deposit) => {
3779
3757
  const payouts = derivePayouts(
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as CashPayoutInfo, I as IntentEntity, a as CashBuyerProfile, b as CashDepositInput, c as CashCatalogFeatures, d as CreateDepositParamsArg, e as CashOrder, f as CashFill, g as CashCapabilities, h as CashoutResult, i as CashEstimate, j as CashFillStats, N as NearIntentsSourceCapabilities, k as NearIntentsDepositInput, l as NearIntentsQuote, m as NearIntentsQuoteInput, n as NearIntentsStatus, o as NearIntentsStatusInput, P as PrepareResult, p as CashPreparedStep, R as RelayExecutionResult, q as RelayQuote, r as RelayStatus, s as CashSourceCapabilities, T as TopUpResult, W as WithdrawResult } from './createCashClient-ECL3HN5H.cjs';
2
- export { B as BASE_CHAIN_ID, t as BASE_USDC_ADDRESS, u as CASH_ATTRIBUTION_CODE, v as CASH_ORDER_POLL_INTERVAL_MS, w as CASH_ORDER_STATUSES, x as CASH_REFERRAL_ATTRIBUTION_PREFIX, y as CASH_RETAIN_ON_EMPTY, z as CashAsset, A as CashChain, D as CashClient, E as CashClientOptions, F as CashCorridorPricing, G as CashFeatureFlags, H as CashFillEta, J as CashLeg, K as CashMultiCurrencyLeg, L as CashNextAction, M as CashOrderState, O as CashPairFillStats, Q as CashPayeeInput, S as CashPayout, U as CashPayoutPricing, V as CashPlatformCapability, X as CashPreparedStepKind, Y as CashReceiveLeg, Z as CashoutInput, _ as CashoutOptions, $ as CuratorPayeeDataInput, a0 as EstimateInput, a1 as EstimateOptions, a2 as MARKET_SPREAD_BPS, a3 as MIN_CASHOUT_AMOUNT, a4 as NEAR_INTENTS_API_URL, a5 as NEAR_INTENTS_BASE_USDC_ASSET_ID, a6 as NEAR_INTENTS_DEFAULT_SLIPPAGE_BPS, a7 as NEAR_INTENTS_STATUSES, a8 as NearIntentsClient, a9 as NearIntentsOptions, aa as NearIntentsQuoteRequest, ab as NearIntentsStatusCode, ac as NearIntentsToken, ad as NearIntentsTradeType, ae as NearIntentsTransaction, af as ORACLE_MIN_CONVERSION_RATE_SENTINEL, ag as OrdersOptions, ah as PreparedCashoutReceipt, ai as RECOMMENDED_MIN_CASHOUT_AMOUNT, aj as RelayOptions, ak as RelayQuoteInput, al as RelaySourceInput, am as RelayTransaction, an as SignerOptions, ao as USDC_DECIMALS, ap as WatchOptions, aq as WithdrawOptions, ar as buildCapabilities, as as createCashClient, at as createNearIntentsClient, au as normalizeCashPayee, av as quoteNearIntentsToBaseUsdc, aw as readNearIntentsSourceCapabilities, ax as readNearIntentsStatus, ay as submitNearIntentsDeposit, az as toCashReferralAttributionCode } from './createCashClient-ECL3HN5H.cjs';
1
+ import { C as CashPayoutInfo, I as IntentEntity, a as CashBuyerProfile, b as CashDepositInput, c as CreateDepositParamsArg, d as CashOrder, e as CashFill, f as CashCapabilities, g as CashoutResult, h as CashEstimate, i as CashFillStats, N as NearIntentsSourceCapabilities, j as NearIntentsDepositInput, k as NearIntentsQuote, l as NearIntentsQuoteInput, m as NearIntentsStatus, n as NearIntentsStatusInput, P as PrepareResult, o as CashPreparedStep, R as RelayExecutionResult, p as RelayQuote, q as RelayStatus, r as CashSourceCapabilities, T as TopUpResult, W as WithdrawResult } from './createCashClient-94tPE0dH.cjs';
2
+ export { B as BASE_CHAIN_ID, s as BASE_USDC_ADDRESS, t as CASH_ATTRIBUTION_CODE, u as CASH_ORDER_POLL_INTERVAL_MS, v as CASH_ORDER_STATUSES, w as CASH_REFERRAL_ATTRIBUTION_PREFIX, x as CASH_RETAIN_ON_EMPTY, y as CashAsset, z as CashChain, A as CashClient, D as CashClientOptions, E as CashCorridorPricing, F as CashFillEta, G as CashLeg, H as CashMultiCurrencyLeg, J as CashNextAction, K as CashOrderState, L as CashPairFillStats, M as CashPayeeInput, O as CashPayout, Q as CashPayoutPricing, S as CashPlatformCapability, U as CashPreparedStepKind, V as CashReceiveLeg, X as CashoutInput, Y as CashoutOptions, Z as CuratorPayeeDataInput, _ as EstimateInput, $ as EstimateOptions, a0 as MARKET_SPREAD_BPS, a1 as MIN_CASHOUT_AMOUNT, a2 as NEAR_INTENTS_API_URL, a3 as NEAR_INTENTS_BASE_USDC_ASSET_ID, a4 as NEAR_INTENTS_DEFAULT_SLIPPAGE_BPS, a5 as NEAR_INTENTS_STATUSES, a6 as NearIntentsClient, a7 as NearIntentsOptions, a8 as NearIntentsQuoteRequest, a9 as NearIntentsStatusCode, aa as NearIntentsToken, ab as NearIntentsTradeType, ac as NearIntentsTransaction, ad as ORACLE_MIN_CONVERSION_RATE_SENTINEL, ae as OrdersOptions, af as PreparedCashoutReceipt, ag as RECOMMENDED_MIN_CASHOUT_AMOUNT, ah as RelayOptions, ai as RelayQuoteInput, aj as RelaySourceInput, ak as RelayTransaction, al as SignerOptions, am as USDC_DECIMALS, an as WatchOptions, ao as WithdrawOptions, ap as buildCapabilities, aq as createCashClient, ar as createNearIntentsClient, as as normalizeCashPayee, at as quoteNearIntentsToBaseUsdc, au as readNearIntentsSourceCapabilities, av as readNearIntentsStatus, aw as submitNearIntentsDeposit, ax as toCashReferralAttributionCode } from './createCashClient-94tPE0dH.cjs';
3
3
  import { PublicClient, Log, Abi } from 'viem';
4
4
  import { PaymentMethodCatalog, CurrencyType, OracleAdapterOverrides, OnchainCurrency, Zkp2pClient, PreparedTransaction } from '@zkp2p/sdk';
5
5
  export { CurrencyType, PreparedTransaction, RuntimeEnv } from '@zkp2p/sdk';
@@ -255,11 +255,10 @@ declare function buildIntentAmountRange(amount: bigint): {
255
255
  *
256
256
  * Registers payee details with the curator (no auth), resolves payment-method
257
257
  * hashes + the gating service from the catalog, and assembles the override
258
- * arrays with signal-time oracle configs. Alipay/CNY is the explicit exception:
259
- * it fixes a fresh Chainlink Ethereum snapshot as the maker floor because Base
260
- * has no CNY oracle adapter.
258
+ * arrays with signal-time oracle configs. Alipay/CNY and UPI/INR instead fix
259
+ * fresh Chainlink snapshots from Ethereum and Polygon as their maker floors.
261
260
  */
262
- declare function prepareCashDepositParams(client: Zkp2pClient, input: CashDepositInput, adapters?: OracleAdapterOverrides, creationRateReader?: CreationRateReader, features?: CashCatalogFeatures): Promise<CreateDepositParamsArg>;
261
+ declare function prepareCashDepositParams(client: Zkp2pClient, input: CashDepositInput, adapters?: OracleAdapterOverrides, creationRateReader?: CreationRateReader): Promise<CreateDepositParamsArg>;
263
262
 
264
263
  /**
265
264
  * Whether a signaled fill can still be completed by its buyer. Uses the
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as CashPayoutInfo, I as IntentEntity, a as CashBuyerProfile, b as CashDepositInput, c as CashCatalogFeatures, d as CreateDepositParamsArg, e as CashOrder, f as CashFill, g as CashCapabilities, h as CashoutResult, i as CashEstimate, j as CashFillStats, N as NearIntentsSourceCapabilities, k as NearIntentsDepositInput, l as NearIntentsQuote, m as NearIntentsQuoteInput, n as NearIntentsStatus, o as NearIntentsStatusInput, P as PrepareResult, p as CashPreparedStep, R as RelayExecutionResult, q as RelayQuote, r as RelayStatus, s as CashSourceCapabilities, T as TopUpResult, W as WithdrawResult } from './createCashClient-ECL3HN5H.js';
2
- export { B as BASE_CHAIN_ID, t as BASE_USDC_ADDRESS, u as CASH_ATTRIBUTION_CODE, v as CASH_ORDER_POLL_INTERVAL_MS, w as CASH_ORDER_STATUSES, x as CASH_REFERRAL_ATTRIBUTION_PREFIX, y as CASH_RETAIN_ON_EMPTY, z as CashAsset, A as CashChain, D as CashClient, E as CashClientOptions, F as CashCorridorPricing, G as CashFeatureFlags, H as CashFillEta, J as CashLeg, K as CashMultiCurrencyLeg, L as CashNextAction, M as CashOrderState, O as CashPairFillStats, Q as CashPayeeInput, S as CashPayout, U as CashPayoutPricing, V as CashPlatformCapability, X as CashPreparedStepKind, Y as CashReceiveLeg, Z as CashoutInput, _ as CashoutOptions, $ as CuratorPayeeDataInput, a0 as EstimateInput, a1 as EstimateOptions, a2 as MARKET_SPREAD_BPS, a3 as MIN_CASHOUT_AMOUNT, a4 as NEAR_INTENTS_API_URL, a5 as NEAR_INTENTS_BASE_USDC_ASSET_ID, a6 as NEAR_INTENTS_DEFAULT_SLIPPAGE_BPS, a7 as NEAR_INTENTS_STATUSES, a8 as NearIntentsClient, a9 as NearIntentsOptions, aa as NearIntentsQuoteRequest, ab as NearIntentsStatusCode, ac as NearIntentsToken, ad as NearIntentsTradeType, ae as NearIntentsTransaction, af as ORACLE_MIN_CONVERSION_RATE_SENTINEL, ag as OrdersOptions, ah as PreparedCashoutReceipt, ai as RECOMMENDED_MIN_CASHOUT_AMOUNT, aj as RelayOptions, ak as RelayQuoteInput, al as RelaySourceInput, am as RelayTransaction, an as SignerOptions, ao as USDC_DECIMALS, ap as WatchOptions, aq as WithdrawOptions, ar as buildCapabilities, as as createCashClient, at as createNearIntentsClient, au as normalizeCashPayee, av as quoteNearIntentsToBaseUsdc, aw as readNearIntentsSourceCapabilities, ax as readNearIntentsStatus, ay as submitNearIntentsDeposit, az as toCashReferralAttributionCode } from './createCashClient-ECL3HN5H.js';
1
+ import { C as CashPayoutInfo, I as IntentEntity, a as CashBuyerProfile, b as CashDepositInput, c as CreateDepositParamsArg, d as CashOrder, e as CashFill, f as CashCapabilities, g as CashoutResult, h as CashEstimate, i as CashFillStats, N as NearIntentsSourceCapabilities, j as NearIntentsDepositInput, k as NearIntentsQuote, l as NearIntentsQuoteInput, m as NearIntentsStatus, n as NearIntentsStatusInput, P as PrepareResult, o as CashPreparedStep, R as RelayExecutionResult, p as RelayQuote, q as RelayStatus, r as CashSourceCapabilities, T as TopUpResult, W as WithdrawResult } from './createCashClient-94tPE0dH.js';
2
+ export { B as BASE_CHAIN_ID, s as BASE_USDC_ADDRESS, t as CASH_ATTRIBUTION_CODE, u as CASH_ORDER_POLL_INTERVAL_MS, v as CASH_ORDER_STATUSES, w as CASH_REFERRAL_ATTRIBUTION_PREFIX, x as CASH_RETAIN_ON_EMPTY, y as CashAsset, z as CashChain, A as CashClient, D as CashClientOptions, E as CashCorridorPricing, F as CashFillEta, G as CashLeg, H as CashMultiCurrencyLeg, J as CashNextAction, K as CashOrderState, L as CashPairFillStats, M as CashPayeeInput, O as CashPayout, Q as CashPayoutPricing, S as CashPlatformCapability, U as CashPreparedStepKind, V as CashReceiveLeg, X as CashoutInput, Y as CashoutOptions, Z as CuratorPayeeDataInput, _ as EstimateInput, $ as EstimateOptions, a0 as MARKET_SPREAD_BPS, a1 as MIN_CASHOUT_AMOUNT, a2 as NEAR_INTENTS_API_URL, a3 as NEAR_INTENTS_BASE_USDC_ASSET_ID, a4 as NEAR_INTENTS_DEFAULT_SLIPPAGE_BPS, a5 as NEAR_INTENTS_STATUSES, a6 as NearIntentsClient, a7 as NearIntentsOptions, a8 as NearIntentsQuoteRequest, a9 as NearIntentsStatusCode, aa as NearIntentsToken, ab as NearIntentsTradeType, ac as NearIntentsTransaction, ad as ORACLE_MIN_CONVERSION_RATE_SENTINEL, ae as OrdersOptions, af as PreparedCashoutReceipt, ag as RECOMMENDED_MIN_CASHOUT_AMOUNT, ah as RelayOptions, ai as RelayQuoteInput, aj as RelaySourceInput, ak as RelayTransaction, al as SignerOptions, am as USDC_DECIMALS, an as WatchOptions, ao as WithdrawOptions, ap as buildCapabilities, aq as createCashClient, ar as createNearIntentsClient, as as normalizeCashPayee, at as quoteNearIntentsToBaseUsdc, au as readNearIntentsSourceCapabilities, av as readNearIntentsStatus, aw as submitNearIntentsDeposit, ax as toCashReferralAttributionCode } from './createCashClient-94tPE0dH.js';
3
3
  import { PublicClient, Log, Abi } from 'viem';
4
4
  import { PaymentMethodCatalog, CurrencyType, OracleAdapterOverrides, OnchainCurrency, Zkp2pClient, PreparedTransaction } from '@zkp2p/sdk';
5
5
  export { CurrencyType, PreparedTransaction, RuntimeEnv } from '@zkp2p/sdk';
@@ -255,11 +255,10 @@ declare function buildIntentAmountRange(amount: bigint): {
255
255
  *
256
256
  * Registers payee details with the curator (no auth), resolves payment-method
257
257
  * hashes + the gating service from the catalog, and assembles the override
258
- * arrays with signal-time oracle configs. Alipay/CNY is the explicit exception:
259
- * it fixes a fresh Chainlink Ethereum snapshot as the maker floor because Base
260
- * has no CNY oracle adapter.
258
+ * arrays with signal-time oracle configs. Alipay/CNY and UPI/INR instead fix
259
+ * fresh Chainlink snapshots from Ethereum and Polygon as their maker floors.
261
260
  */
262
- declare function prepareCashDepositParams(client: Zkp2pClient, input: CashDepositInput, adapters?: OracleAdapterOverrides, creationRateReader?: CreationRateReader, features?: CashCatalogFeatures): Promise<CreateDepositParamsArg>;
261
+ declare function prepareCashDepositParams(client: Zkp2pClient, input: CashDepositInput, adapters?: OracleAdapterOverrides, creationRateReader?: CreationRateReader): Promise<CreateDepositParamsArg>;
263
262
 
264
263
  /**
265
264
  * Whether a signaled fill can still be completed by its buyer. Uses the
package/dist/index.js CHANGED
@@ -120,26 +120,12 @@ async function readCashCreationRate(publicClient, platform, currency, nowSeconds
120
120
  async function readAlipayCnyCreationRate(publicClient, nowSeconds = Math.floor(Date.now() / 1e3)) {
121
121
  return readCashCreationRate(publicClient, "alipay", "CNY", nowSeconds);
122
122
  }
123
- var UPI_STAGING_PAYMENT_METHOD_HASH = "0xe99a5081226cbbff9440a63da5caa04fa30f210c12c4dd9976132ac075054cd9";
124
- function getCashPaymentMethodsCatalog(environment, features = {}) {
125
- const catalog = getPaymentMethodsCatalog(8453, environment);
126
- if (environment !== "staging" || features.upi !== true || catalog.upi) {
127
- return catalog;
128
- }
129
- return {
130
- ...catalog,
131
- upi: {
132
- paymentMethodHash: UPI_STAGING_PAYMENT_METHOD_HASH,
133
- currencies: [currencyInfo.INR.currencyCodeHash],
134
- timestampBuffer: 30,
135
- providerHashes: []
136
- }
137
- };
123
+ function getCashPaymentMethodsCatalog(environment) {
124
+ return getPaymentMethodsCatalog(8453, environment);
138
125
  }
139
126
  function resolveCashPaymentMethodHash(processorName, catalog) {
140
- const normalized = processorName.trim().toLowerCase();
141
- if (normalized === "upi" && catalog.upi) {
142
- return catalog.upi.paymentMethodHash;
127
+ if (processorName.trim().toLowerCase() === "upi" && !catalog.upi) {
128
+ throw new Error("UPI is not enabled in this environment catalog");
143
129
  }
144
130
  return resolvePaymentMethodHashFromCatalog(processorName, catalog);
145
131
  }
@@ -178,12 +164,12 @@ function buildIntentAmountRange(amount) {
178
164
  const min = amount < DEFAULT_MIN_ORDER_FLOOR ? amount : DEFAULT_MIN_ORDER_FLOOR;
179
165
  return { min, max: amount };
180
166
  }
181
- async function prepareCashDepositParams(client, input, adapters, creationRateReader, features) {
167
+ async function prepareCashDepositParams(client, input, adapters, creationRateReader) {
182
168
  const { payouts } = input;
183
169
  if (!payouts.length) throw new Error("At least one payout is required");
184
170
  const chainId = client.chainId;
185
171
  const runtimeEnv = client.runtimeEnv;
186
- const catalog = getCashPaymentMethodsCatalog(runtimeEnv, features);
172
+ const catalog = getCashPaymentMethodsCatalog(runtimeEnv);
187
173
  const intentGatingService = getGatingServiceAddress(chainId, runtimeEnv);
188
174
  const processorNames = payouts.map((p) => p.processorName);
189
175
  const paymentMethodsOverride = processorNames.map(
@@ -619,8 +605,8 @@ var IDENTITY_ATTESTATION_PLATFORMS = /* @__PURE__ */ new Set(["wise", "paypal",
619
605
  function platformRequiresIdentityAttestation(platform) {
620
606
  return IDENTITY_ATTESTATION_PLATFORMS.has(platform.toLowerCase());
621
607
  }
622
- function buildCapabilities(environment, features = {}) {
623
- const catalog = getCashPaymentMethodsCatalog(environment, features);
608
+ function buildCapabilities(environment) {
609
+ const catalog = getCashPaymentMethodsCatalog(environment);
624
610
  const platforms = Object.entries(catalog).map(([platform, entry]) => {
625
611
  const currencies2 = (entry.currencies ?? []).map((hash) => getCurrencyCodeFromHash(hash)).filter(
626
612
  (code) => code != null && (isMarketRateSupported(code) || isCreationRateCorridor(platform, code))
@@ -643,9 +629,7 @@ function buildCapabilities(environment, features = {}) {
643
629
  requiresIdentityAttestation: IDENTITY_ATTESTATION_PLATFORMS.has(platform),
644
630
  requiresAtomicAccessPolicy: false
645
631
  };
646
- }).filter(
647
- (p) => p.currencies.length > 0 && (p.platform !== "upi" || environment === "staging" && features.upi === true)
648
- ).sort((a, b) => a.platform.localeCompare(b.platform));
632
+ }).filter((p) => p.currencies.length > 0).sort((a, b) => a.platform.localeCompare(b.platform));
649
633
  const currencies = [...new Set(platforms.flatMap((p) => p.currencies))].sort();
650
634
  const baseUsdc = { address: BASE_USDC_ADDRESS, symbol: "USDC", decimals: USDC_DECIMALS };
651
635
  return {
@@ -2429,8 +2413,8 @@ async function submitAndConfirm(client, verb, send) {
2429
2413
  function isKnownPreBroadcastFailure(mapped) {
2430
2414
  return mapped.code === "TRANSACTION_REJECTED" || mapped.code === "INSUFFICIENT_TOKEN_BALANCE" || mapped.code === "ALLOWANCE_NOT_VISIBLE" || mapped.code === "ESCROW_PAUSED";
2431
2415
  }
2432
- function cashoutAccessPolicyPaymentMethods(depositInput, environment, features) {
2433
- const catalog = getCashPaymentMethodsCatalog(environment, features);
2416
+ function cashoutAccessPolicyPaymentMethods(depositInput, environment) {
2417
+ const catalog = getCashPaymentMethodsCatalog(environment);
2434
2418
  return [
2435
2419
  ...new Set(
2436
2420
  depositInput.payouts.filter((payout) => CASH_RESTRICTED_PLATFORMS.has(payout.processorName.toLowerCase())).map((payout) => resolveCashPaymentMethodHash(payout.processorName, catalog))
@@ -2527,7 +2511,7 @@ function createCashClient(options) {
2527
2511
  if (legs.length === 0) {
2528
2512
  throw errors.invalidPayoutPlatforms("at least one payout leg is required");
2529
2513
  }
2530
- const capabilities2 = buildCapabilities(environment, options.features);
2514
+ const capabilities2 = buildCapabilities(environment);
2531
2515
  const seenPlatforms = /* @__PURE__ */ new Set();
2532
2516
  const payouts = legs.map((leg) => {
2533
2517
  const platform = capabilities2.platforms.find(
@@ -2608,8 +2592,7 @@ function createCashClient(options) {
2608
2592
  } catch (err) {
2609
2593
  throw errors.oracleReadFailed(currency, err);
2610
2594
  }
2611
- },
2612
- options.features
2595
+ }
2613
2596
  );
2614
2597
  } catch (err) {
2615
2598
  if (isCashError(err)) throw err;
@@ -2661,7 +2644,7 @@ function createCashClient(options) {
2661
2644
  const payouts = derivePayouts(
2662
2645
  deposit.paymentMethods ?? [],
2663
2646
  deposit.currencies ?? [],
2664
- getCashPaymentMethodsCatalog(environment, options.features)
2647
+ getCashPaymentMethodsCatalog(environment)
2665
2648
  );
2666
2649
  let attributedToCash = false;
2667
2650
  if (!isCashPayoutSet(payouts)) {
@@ -2719,7 +2702,7 @@ function createCashClient(options) {
2719
2702
  return escrowContext(depositId);
2720
2703
  }
2721
2704
  function capabilities(capabilityOptions) {
2722
- const baseCapabilities = buildCapabilities(environment, options.features);
2705
+ const baseCapabilities = buildCapabilities(environment);
2723
2706
  if (!capabilityOptions?.includeRelaySources && !capabilityOptions?.includeNearIntentsSources) {
2724
2707
  return baseCapabilities;
2725
2708
  }
@@ -2897,11 +2880,7 @@ function createCashClient(options) {
2897
2880
  }
2898
2881
  async function configureCashoutAccess(client, signer, depositInput, depositId, source) {
2899
2882
  const groupIds = CASH_ACCESS_GROUP_IDS[environment];
2900
- const paymentMethods = cashoutAccessPolicyPaymentMethods(
2901
- depositInput,
2902
- environment,
2903
- options.features
2904
- );
2883
+ const paymentMethods = cashoutAccessPolicyPaymentMethods(depositInput, environment);
2905
2884
  const hashes = [];
2906
2885
  for (const paymentMethod of paymentMethods) {
2907
2886
  const prepared = prepareCashoutAccess(depositId, paymentMethod, client, source);
@@ -3207,8 +3186,7 @@ function createCashClient(options) {
3207
3186
  const hashedOnchainIds = (params.paymentMethodDataOverride ?? []).map((d) => d.payeeDetails);
3208
3187
  const accessPolicyPaymentMethods = cashoutAccessPolicyPaymentMethods(
3209
3188
  depositInput,
3210
- environment,
3211
- options.features
3189
+ environment
3212
3190
  );
3213
3191
  return {
3214
3192
  txs: [approve, prepared],
@@ -3279,7 +3257,7 @@ function createCashClient(options) {
3279
3257
  } catch (err) {
3280
3258
  throw errors.indexerUnavailable("orders", err);
3281
3259
  }
3282
- const catalog = getCashPaymentMethodsCatalog(environment, options.features);
3260
+ const catalog = getCashPaymentMethodsCatalog(environment);
3283
3261
  let attributedCashDeposits = /* @__PURE__ */ new Set();
3284
3262
  const fixedRateCandidates = deposits.filter((deposit) => {
3285
3263
  const payouts = derivePayouts(
package/dist/react.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { CurrencyType } from '@zkp2p/sdk';
2
- import { D as CashClient, a0 as EstimateInput, i as CashEstimate, _ as CashoutOptions, h as CashoutResult, Z as CashoutInput, T as TopUpResult, W as WithdrawResult, e as CashOrder } from './createCashClient-ECL3HN5H.cjs';
2
+ import { A as CashClient, _ as EstimateInput, h as CashEstimate, Y as CashoutOptions, g as CashoutResult, X as CashoutInput, T as TopUpResult, W as WithdrawResult, d as CashOrder } from './createCashClient-94tPE0dH.cjs';
3
3
  import { WalletClient } from 'viem';
4
4
  import '@relayprotocol/relay-sdk';
5
5
 
package/dist/react.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { CurrencyType } from '@zkp2p/sdk';
2
- import { D as CashClient, a0 as EstimateInput, i as CashEstimate, _ as CashoutOptions, h as CashoutResult, Z as CashoutInput, T as TopUpResult, W as WithdrawResult, e as CashOrder } from './createCashClient-ECL3HN5H.js';
2
+ import { A as CashClient, _ as EstimateInput, h as CashEstimate, Y as CashoutOptions, g as CashoutResult, X as CashoutInput, T as TopUpResult, W as WithdrawResult, d as CashOrder } from './createCashClient-94tPE0dH.js';
3
3
  import { WalletClient } from 'viem';
4
4
  import '@relayprotocol/relay-sdk';
5
5
 
package/dist/tools.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // package.json
4
4
  var package_default = {
5
- version: "0.5.4-rc.1"};
5
+ version: "0.6.0-rc.1"};
6
6
 
7
7
  // src/tools/index.ts
8
8
  var bigintString = {
package/dist/tools.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // package.json
2
2
  var package_default = {
3
- version: "0.5.4-rc.1"};
3
+ version: "0.6.0-rc.1"};
4
4
 
5
5
  // src/tools/index.ts
6
6
  var bigintString = {
@@ -2,15 +2,18 @@
2
2
  import { createCashClient, usdc } from '@zkp2p/cash';
3
3
  import type { WalletClient } from 'viem';
4
4
 
5
- export async function cashOutToUpi(signer: WalletClient, upiId: string) {
5
+ export async function cashOutToUpi(
6
+ signer: WalletClient,
7
+ upiId: string,
8
+ environment: 'staging' | 'preproduction' = 'staging',
9
+ ) {
6
10
  const cash = createCashClient({
7
- environment: 'staging',
8
- features: { upi: true },
11
+ environment,
9
12
  });
10
13
 
11
14
  const upi = cash.capabilities().platforms.find(({ platform }) => platform === 'upi');
12
15
  if (!upi?.currencies.includes('INR')) {
13
- throw new Error('UPI is not enabled in this staging SDK build.');
16
+ throw new Error('UPI is not enabled in this environment.');
14
17
  }
15
18
 
16
19
  return cash.cashout(
package/llms.txt CHANGED
@@ -25,7 +25,7 @@ Key facts:
25
25
  then cash out Base-only. Use EXACT_OUTPUT when the order amount must be fixed.
26
26
  - estimate() reports its binding point. Existing corridors bind the on-chain
27
27
  oracle when an intent is signaled; Alipay/CNY fixes a fresh Ethereum
28
- Chainlink snapshot during deposit preparation. ETA is `{ seconds, label }` from the same rolling
28
+ Chainlink snapshot during deposit preparation; UPI/INR uses a fresh Polygon Chainlink snapshot. ETA is `{ seconds, label }` from the same rolling
29
29
  30-day, intent-attributed pair sampler as fillStats(), not a guarantee.
30
30
  - fillStats() returns raw `{ fills, medianFillSeconds? }` evidence keyed by
31
31
  `platform:currency` or a sorted set such as `revolut:EUR+GBP+USD`. Set
@@ -38,11 +38,11 @@ Key facts:
38
38
  fillStats() separately.
39
39
  - capabilities() exposes one Zelle platform. A zelle cashout attaches only the
40
40
  generic Zelle payment method to the on-chain deposit.
41
- - UPI/INR is staging-only and fail-closed. Enable it with
42
- `createCashClient({ environment: 'staging', features: { upi: true } })`.
41
+ - UPI/INR is available without feature flags. For example, use
42
+ `createCashClient({ environment: 'preproduction' })`.
43
43
  Any valid UPI ID from any bank can receive without a seller login,
44
44
  extension, identity attestation, or prior registration flow. Buyers
45
- currently prove HDFC Bank payments through Gmail.
45
+ pay and verify through Amazon Pay using standard UPI.
46
46
  - Resume any order from its depositId alone (composite escrow_onchainId).
47
47
  - One unwind verb: withdraw(depositId) - prunes expired intents automatically;
48
48
  pass amount for a partial withdrawal of the unlocked balance.
@@ -136,4 +136,4 @@ read-only RPC with `upiCreationRateRpcUrl` or `upiCreationRateTransport`.
136
136
  Alipay/CNY retains the Ethereum registry and `creationRateRpcUrl` /
137
137
  `creationRateTransport`. UPI rejects the wrong chain, invalid rounds, and
138
138
  observations older than 24 hours; market closures do not bypass freshness.
139
- This does not change the staging-only UPI opt-in gate.
139
+ UPI is available in production, preproduction, and staging without a feature flag.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zkp2p/cash",
3
- "version": "0.5.4-rc.1",
3
+ "version": "0.6.0-rc.1",
4
4
  "description": "Peer Cash - offramp-only SDK for routing Relay or NEAR Intents assets to Base USDC, then cashing out to fiat at zero-spread Chainlink market rates.",
5
5
  "license": "MIT",
6
6
  "author": "Peer (https://peer.xyz)",
@@ -32,7 +32,7 @@ protocol-held funds and no custodial off-ramp provider.
32
32
  `oracleRateConfig { spreadBps: 0 }`; the binding rate is the Chainlink rate
33
33
  when a buyer signals. Alipay/CNY is the exception: because Base has no CNY
34
34
  oracle adapter, the SDK reads Chainlink CNY/USD on Ethereum and fixes that
35
- fresh snapshot as the maker floor during deposit preparation. Read
35
+ fresh snapshot as the maker floor during deposit preparation. UPI/INR does the same using the direct Polygon INR/USD feed, rejecting wrong-chain, stale and invalid data. Read
36
36
  `estimate().binding` and `capabilities().platforms[].pricing`.
37
37
  - **Custody story.** Funds are held by the protocol contract only. An unmatched
38
38
  deposit is withdrawable by the maker at any time. The SDK never holds keys.
@@ -183,11 +183,10 @@ platforms outright: a previously registered handle can be reused with bare
183
183
  payee data. Handle `PAYEE_VERIFICATION_REQUIRED` when registration is still
184
184
  needed.
185
185
 
186
- UPI is a staging-only opt-in until production contracts support it. Enable it
187
- with `features: { upi: true }` on a staging client. Accept any locally valid
186
+ UPI is available on production, preproduction, and staging clients without feature flags. Accept any locally valid
188
187
  UPI ID from any bank; do not add a seller bank-login, extension, identity
189
- attestation, or pre-registration step. Buyers currently prove HDFC Bank UPI
190
- payments through Gmail.
188
+ attestation, or pre-registration step. Buyers pay and verify through Amazon Pay using standard UPI; UPI Lite and
189
+ merchant payments are unsupported.
191
190
 
192
191
  ## 4. Order management - indexer-native
193
192
 
@@ -264,6 +263,8 @@ Prove both routes without waiting for a buyer:
264
263
  If withdrawal fails with funds stuck: stop, do not retry blindly, escalate to
265
264
  a human with the `depositId` and tx hashes.
266
265
 
266
+ ## UPI oracle checks
267
+
267
268
  UPI/INR reads the live Chainlink Polygon mainnet proxy
268
269
  `0xDA0F8Df6F5dB15b346f4B8D1156722027E194E60` (chain 137), inverts
269
270
  USD per INR, and rounds the creation-time maker floor up. Configure its
@@ -271,7 +272,7 @@ read-only RPC with `upiCreationRateRpcUrl` or `upiCreationRateTransport`.
271
272
  Alipay/CNY retains the Ethereum registry and `creationRateRpcUrl` /
272
273
  `creationRateTransport`. UPI rejects the wrong chain, invalid rounds, and
273
274
  observations older than 24 hours; market closures do not bypass freshness.
274
- This does not change the staging-only UPI opt-in gate.
275
+ UPI is available in production, preproduction, and staging without a feature flag.
275
276
 
276
277
  Before a funded UPI QA run, call
277
278
  `cash.estimate({ amount: 1000000n, platform: 'upi', currency: 'INR' }, { includeEta: false })`
@@ -0,0 +1,96 @@
1
+ ---
2
+ name: upi-preprod-qa
3
+ description: Verify the Cash SDK Amazon Pay UPI corridor on preproduction, including catalog gates, a small maker deposit, indexing, and cleanup.
4
+ ---
5
+
6
+ # UPI preproduction QA
7
+
8
+ Use the exact published Cash candidate and record its SDK/contracts versions.
9
+ Require `createCashClient({ environment: 'preproduction' })` to advertise UPI/INR.
10
+ UPI is available without feature flags in every environment.
11
+ The canonical contracts catalog must contain the live UPI method and INR currency;
12
+ never invent a catalog entry when the package or registry omits one.
13
+
14
+ From a clean consumer of the candidate, run this catalog check before creating
15
+ any transaction:
16
+
17
+ ```ts
18
+ import { createCashClient } from '@zkp2p/cash';
19
+
20
+ for (const environment of ['staging', 'preproduction', 'production'] as const) {
21
+ const client = createCashClient({ environment });
22
+ const method = client.capabilities().platforms.find((item) => item.platform === 'upi');
23
+ if (!method?.currencies.includes('INR')) {
24
+ throw new Error(`Missing UPI catalog for ${environment}`);
25
+ }
26
+ }
27
+ ```
28
+
29
+ Use an explicitly authorized low-value wallet and verified recipient UPI ID.
30
+ Keep the identity and operation ledger in ignored private storage, outside this skill.
31
+ `cashout` accepts any valid VPA; no seller bank login or identity attestation is required.
32
+ Verify INR pricing is a fresh Polygon Chainlink snapshot fixed at deposit creation.
33
+ The official [INR/USD feed](https://data.chain.link/feeds/polygon/mainnet/inr-usd)
34
+ is proxy `0xDA0F8Df6F5dB15b346f4B8D1156722027E194E60` on chain 137;
35
+ it is not registered in Ethereum's Feed Registry. Before funding, call
36
+ `cash.estimate({ amount: 5_000_000n, platform: 'upi', currency: 'INR' }, { includeEta: false })`
37
+ against the live default or explicitly configured Polygon RPC. Confirm a positive
38
+ rate, fresh `oracleUpdatedAt`, and `binding: 'deposit-creation'`. Do not accept
39
+ mocked-rate unit tests as proof of a functioning live corridor. The reader must
40
+ reject the wrong chain, invalid/incomplete rounds, future timestamps and data
41
+ older than 86,400 seconds. Forex market-hour gaps must fail closed; do not
42
+ substitute a static price or relax freshness to make QA pass.
43
+
44
+ With bounded task authorization, create one small Base-USDC deposit, recording
45
+ transaction hash and deposit ID before any retry. Confirm the receipt, then
46
+ `order`/`orders` and the matching preproduction indexer's MethodCurrency and
47
+ QuoteCandidate. Check exact UPI/INR hashes, payee hash, amounts, and rate. Share
48
+ this one fixture with authorized buyer QA instead of funding duplicate deposits.
49
+ Keep quotes within the maker minimum and available liquidity.
50
+
51
+ Use `examples/upi-staging-cashout.ts` with its explicit `preproduction`
52
+ environment argument as the maker API example. Use the supported Cash client
53
+ methods for signing and finalization; never copy an old escrow address or
54
+ transaction payload. For GraphQL, filter `MethodCurrency` and `QuoteCandidate`
55
+ by the recorded `depositId`, `paymentMethodHash`, and `currencyCode`. Require
56
+ exactly one matching tuple, Base USDC, a positive matching conversion rate,
57
+ `isActive: true`, `hasMinLiquidity: true`, and enough available liquidity.
58
+ Inspect `disputeProtectionRequiresStake` before buyer QA so stake admission is
59
+ not mistaken for a payment-proof failure.
60
+
61
+ Buyer QA belongs to the client and attestation repositories. Amazon Pay is the
62
+ sole client flow: no HDFC/Gmail selector or fallback copy. Pay with standard UPI
63
+ to a person, then verify from the same Amazon account. Exclude UPI Lite, merchant
64
+ payments and incoming transactions. Keep session evidence encrypted. A real
65
+ intent requires the exact payment identity, allowed payment-time window, and an
66
+ unused payment nullifier. Report maker deposit, buyer signal, evidence proof,
67
+ and settlement as separate checkpoints. Backend HDFC support is retained until
68
+ a separately authorized retirement; do not remove its server routes here.
69
+
70
+ After buyer intents are cancelled or otherwise terminal, call the supported
71
+ `withdraw` path and verify the receipt and returned order state. If a transaction
72
+ has an unknown result, inspect its receipt and existing deposit before retrying.
73
+ Stop further spending on an unexplained balance or identity mismatch.
74
+
75
+ Run `bun run ci` for SDK changes. Keep private VPA, cookies, raw receipts, keys, and request
76
+ bodies out of committed evidence; publish only redacted checkpoint results.
77
+
78
+ ## Live order reconstruction regression
79
+
80
+ After the exact UPI fixture is indexed, require both `cash.order(depositId)` and `cash.orders(owner)` to return it. Fixed UPI/INR creation-rate deposits must have positive fixed-rate evidence and the indexed `peer-cash` attribution marker. Do not classify unrelated Advanced Sell deposits as Cash orders. A quoteable indexer row alone is insufficient: run order lookup, partial-fill observation and withdrawal checks too. Keep the method/currency pair explicit; UPI/CNY must be rejected.
81
+
82
+ ## Small-fixture visibility and dust reconciliation
83
+
84
+ The web orderbook hides deposits below USD 5 by default. Enable its low-liquidity
85
+ filter before diagnosing an active small fixture as missing. Selector liquidity
86
+ can include a deposit that the orderbook display hides. A verified read-only
87
+ Express `getQuote` accepted INR 10 against a 1 USDC fixture; quoteability still
88
+ depends on the current maker minimum, available liquidity and rate. This does
89
+ not authorize a payment or another fixture, and a quote is not a settlement.
90
+
91
+ The verified contract dust threshold is 0.1 USDC. A remaining amount below that
92
+ threshold may be collected as protocol dust rather than refunded to the maker.
93
+ Reconcile `DustCollected` events and actual token transfers with the successful
94
+ receipt, buyer proceeds, fees and maker balance. Do not interpret Cash
95
+ `returnedAmount` alone as a maker refund. Confirm the deployed threshold again
96
+ if the contract version changes, and retain exact amounts in private receipts.