@zkp2p/cash 0.4.0-rc.2 → 0.4.0-rc.3

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
@@ -87,6 +87,19 @@ const multiCurrency = await cash.cashout(
87
87
  { signer },
88
88
  );
89
89
 
90
+ // Widest reach: several platforms on one order (each platform at most once);
91
+ // the buyer picks the leg they can pay, every leg at the live oracle rate.
92
+ const multiPlatform = await cash.cashout(
93
+ {
94
+ amount: usdc(500),
95
+ receive: [
96
+ { platform: 'venmo', currency: 'USD', payee: '@handle' },
97
+ { platform: 'revolut', currencies: ['EUR', 'GBP'], payee: { offchainId: 'revtag' } },
98
+ ],
99
+ },
100
+ { signer },
101
+ );
102
+
90
103
  // 4. Persist depositId ↔ your user. That row is the entire integration state.
91
104
 
92
105
  // 5. Drive the lifecycle from nextActions - no heuristics.
package/README.md CHANGED
@@ -65,6 +65,19 @@ const fastFill = await cash.cashout(
65
65
  { signer },
66
66
  );
67
67
 
68
+ // One order can also offer several platforms (each at most once). The buyer
69
+ // picks the leg they can pay; every leg fills at the live oracle market rate.
70
+ const widestReach = await cash.cashout(
71
+ {
72
+ amount: usdc(1000),
73
+ receive: [
74
+ { platform: 'venmo', currency: 'USD', payee: '@you' },
75
+ { platform: 'revolut', currencies: ['EUR', 'GBP'], payee: { offchainId: 'revtag' } },
76
+ ],
77
+ },
78
+ { signer },
79
+ );
80
+
68
81
  for await (const order of cash.watch(depositId)) {
69
82
  console.log(order.state, order.explain());
70
83
  if (order.state === 'delivered') break;
@@ -87,6 +87,12 @@ var errors = {
87
87
  retryable: false,
88
88
  remediation: `Pass one or more unique currencies listed for ${platform} by capabilities().`
89
89
  }),
90
+ invalidPayoutPlatforms: (reason) => new CashError({
91
+ code: "INVALID_PAYOUT_PLATFORMS",
92
+ message: `The payout platform set is invalid: ${reason}.`,
93
+ retryable: false,
94
+ remediation: `Pass one payout leg, or an array of legs using each platform from capabilities() at most once.`
95
+ }),
90
96
  invalidReferralCode: () => new CashError({
91
97
  code: "INVALID_REFERRAL_CODE",
92
98
  message: `The Peer referral code must be exactly six letters or numbers.`,
@@ -515,6 +515,8 @@ interface CashMultiCurrencyLeg {
515
515
  payee: CashPayeeInput;
516
516
  currency?: never;
517
517
  }
518
+ /** One payout leg of a cash-out - single-currency or multi-currency. */
519
+ type CashReceiveLeg = CashLeg | CashMultiCurrencyLeg;
518
520
  interface CashoutInput {
519
521
  /**
520
522
  * Amount to cash out. Without `source`, this is Base USDC base units. With
@@ -529,8 +531,12 @@ interface CashoutInput {
529
531
  /** Relay amount mode. Omit for the recommended exact source-input flow. */
530
532
  tradeType?: 'EXACT_INPUT' | 'EXACT_OUTPUT' | 'EXPECTED_OUTPUT';
531
533
  };
532
- /** Where the fiat should arrive. One method may offer multiple currencies. */
533
- receive: CashLeg | CashMultiCurrencyLeg;
534
+ /**
535
+ * Where the fiat should arrive. One leg, or an array of legs to offer the
536
+ * buyer several payout platforms (each platform at most once). One method
537
+ * may offer multiple currencies; every leg fills at the live oracle rate.
538
+ */
539
+ receive: CashReceiveLeg | readonly [CashReceiveLeg, ...CashReceiveLeg[]];
534
540
  /** Per-order min/max override (USDC base units). */
535
541
  intentAmountRange?: {
536
542
  min: bigint;
@@ -702,4 +708,4 @@ interface CashClient {
702
708
  }
703
709
  declare function createCashClient(options: CashClientOptions): CashClient;
704
710
 
705
- export { buildCapabilities as $, type CashPayeeInput as A, type CashPayout as B, type CashPayoutInfo as C, type CashPayoutPricing as D, type CashPlatformCapability as E, type CashPreparedStepKind as F, type CashoutInput as G, type CashoutOptions as H, type IntentStatus as I, type CuratorPayeeDataInput as J, type EstimateInput as K, type EstimateOptions as L, MIN_CASHOUT_AMOUNT as M, type PreparedCashoutReceipt as N, type OrdersOptions as O, type PrepareResult as P, RECOMMENDED_MIN_CASHOUT_AMOUNT as Q, type RelayExecutionResult as R, type RelayOptions as S, type TopUpResult as T, type RelayQuoteInput as U, type RelaySourceInput as V, type WithdrawResult as W, type RelayTransaction as X, type SignerOptions as Y, type WatchOptions as Z, type WithdrawOptions as _, type IntentEntity as a, createCashClient as a0, normalizeCashPayee as a1, toCashReferralAttributionCode as a2, type CashBuyerProfile as b, type CashDepositInput 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 CashPreparedStep as k, type RelayQuote as l, type RelayStatus as m, type CashSourceCapabilities as n, CASH_ATTRIBUTION_CODE as o, CASH_REFERRAL_ATTRIBUTION_PREFIX as p, type CashAsset as q, type CashChain as r, type CashClient as s, type CashClientOptions as t, type CashFillEta as u, type CashLeg as v, type CashMultiCurrencyLeg as w, type CashNextAction as x, type CashOrderState as y, type CashPairFillStats as z };
711
+ export { type WithdrawOptions as $, type CashPayeeInput as A, type CashPayout as B, type CashPayoutInfo as C, type CashPayoutPricing as D, type CashPlatformCapability as E, type CashPreparedStepKind as F, type CashReceiveLeg as G, type CashoutInput as H, type IntentStatus as I, type CashoutOptions as J, type CuratorPayeeDataInput as K, type EstimateInput as L, type EstimateOptions as M, MIN_CASHOUT_AMOUNT as N, type OrdersOptions as O, type PrepareResult as P, type PreparedCashoutReceipt as Q, type RelayExecutionResult as R, RECOMMENDED_MIN_CASHOUT_AMOUNT as S, type TopUpResult as T, type RelayOptions as U, type RelayQuoteInput as V, type WithdrawResult as W, type RelaySourceInput as X, type RelayTransaction as Y, type SignerOptions as Z, type WatchOptions as _, type IntentEntity as a, buildCapabilities as a0, createCashClient as a1, normalizeCashPayee as a2, toCashReferralAttributionCode as a3, type CashBuyerProfile as b, type CashDepositInput 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 CashPreparedStep as k, type RelayQuote as l, type RelayStatus as m, type CashSourceCapabilities as n, CASH_ATTRIBUTION_CODE as o, CASH_REFERRAL_ATTRIBUTION_PREFIX as p, type CashAsset as q, type CashChain as r, type CashClient as s, type CashClientOptions as t, type CashFillEta as u, type CashLeg as v, type CashMultiCurrencyLeg as w, type CashNextAction as x, type CashOrderState as y, type CashPairFillStats as z };
@@ -515,6 +515,8 @@ interface CashMultiCurrencyLeg {
515
515
  payee: CashPayeeInput;
516
516
  currency?: never;
517
517
  }
518
+ /** One payout leg of a cash-out - single-currency or multi-currency. */
519
+ type CashReceiveLeg = CashLeg | CashMultiCurrencyLeg;
518
520
  interface CashoutInput {
519
521
  /**
520
522
  * Amount to cash out. Without `source`, this is Base USDC base units. With
@@ -529,8 +531,12 @@ interface CashoutInput {
529
531
  /** Relay amount mode. Omit for the recommended exact source-input flow. */
530
532
  tradeType?: 'EXACT_INPUT' | 'EXACT_OUTPUT' | 'EXPECTED_OUTPUT';
531
533
  };
532
- /** Where the fiat should arrive. One method may offer multiple currencies. */
533
- receive: CashLeg | CashMultiCurrencyLeg;
534
+ /**
535
+ * Where the fiat should arrive. One leg, or an array of legs to offer the
536
+ * buyer several payout platforms (each platform at most once). One method
537
+ * may offer multiple currencies; every leg fills at the live oracle rate.
538
+ */
539
+ receive: CashReceiveLeg | readonly [CashReceiveLeg, ...CashReceiveLeg[]];
534
540
  /** Per-order min/max override (USDC base units). */
535
541
  intentAmountRange?: {
536
542
  min: bigint;
@@ -702,4 +708,4 @@ interface CashClient {
702
708
  }
703
709
  declare function createCashClient(options: CashClientOptions): CashClient;
704
710
 
705
- export { buildCapabilities as $, type CashPayeeInput as A, type CashPayout as B, type CashPayoutInfo as C, type CashPayoutPricing as D, type CashPlatformCapability as E, type CashPreparedStepKind as F, type CashoutInput as G, type CashoutOptions as H, type IntentStatus as I, type CuratorPayeeDataInput as J, type EstimateInput as K, type EstimateOptions as L, MIN_CASHOUT_AMOUNT as M, type PreparedCashoutReceipt as N, type OrdersOptions as O, type PrepareResult as P, RECOMMENDED_MIN_CASHOUT_AMOUNT as Q, type RelayExecutionResult as R, type RelayOptions as S, type TopUpResult as T, type RelayQuoteInput as U, type RelaySourceInput as V, type WithdrawResult as W, type RelayTransaction as X, type SignerOptions as Y, type WatchOptions as Z, type WithdrawOptions as _, type IntentEntity as a, createCashClient as a0, normalizeCashPayee as a1, toCashReferralAttributionCode as a2, type CashBuyerProfile as b, type CashDepositInput 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 CashPreparedStep as k, type RelayQuote as l, type RelayStatus as m, type CashSourceCapabilities as n, CASH_ATTRIBUTION_CODE as o, CASH_REFERRAL_ATTRIBUTION_PREFIX as p, type CashAsset as q, type CashChain as r, type CashClient as s, type CashClientOptions as t, type CashFillEta as u, type CashLeg as v, type CashMultiCurrencyLeg as w, type CashNextAction as x, type CashOrderState as y, type CashPairFillStats as z };
711
+ export { type WithdrawOptions as $, type CashPayeeInput as A, type CashPayout as B, type CashPayoutInfo as C, type CashPayoutPricing as D, type CashPlatformCapability as E, type CashPreparedStepKind as F, type CashReceiveLeg as G, type CashoutInput as H, type IntentStatus as I, type CashoutOptions as J, type CuratorPayeeDataInput as K, type EstimateInput as L, type EstimateOptions as M, MIN_CASHOUT_AMOUNT as N, type OrdersOptions as O, type PrepareResult as P, type PreparedCashoutReceipt as Q, type RelayExecutionResult as R, RECOMMENDED_MIN_CASHOUT_AMOUNT as S, type TopUpResult as T, type RelayOptions as U, type RelayQuoteInput as V, type WithdrawResult as W, type RelaySourceInput as X, type RelayTransaction as Y, type SignerOptions as Z, type WatchOptions as _, type IntentEntity as a, buildCapabilities as a0, createCashClient as a1, normalizeCashPayee as a2, toCashReferralAttributionCode as a3, type CashBuyerProfile as b, type CashDepositInput 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 CashPreparedStep as k, type RelayQuote as l, type RelayStatus as m, type CashSourceCapabilities as n, CASH_ATTRIBUTION_CODE as o, CASH_REFERRAL_ATTRIBUTION_PREFIX as p, type CashAsset as q, type CashChain as r, type CashClient as s, type CashClientOptions as t, type CashFillEta as u, type CashLeg as v, type CashMultiCurrencyLeg as w, type CashNextAction as x, type CashOrderState as y, type CashPairFillStats as z };
package/dist/index.cjs CHANGED
@@ -463,6 +463,9 @@ var PAYEE_HINTS = {
463
463
  n26: "MoneyBeam email or phone number"
464
464
  };
465
465
  var IDENTITY_ATTESTATION_PLATFORMS = /* @__PURE__ */ new Set(["wise", "paypal"]);
466
+ function platformRequiresIdentityAttestation(platform) {
467
+ return IDENTITY_ATTESTATION_PLATFORMS.has(platform);
468
+ }
466
469
  function buildCapabilities(environment) {
467
470
  const catalog = sdk.getPaymentMethodsCatalog(BASE_CHAIN_ID, environment);
468
471
  const platforms = Object.entries(catalog).map(([platform, entry]) => {
@@ -565,6 +568,12 @@ var errors = {
565
568
  retryable: false,
566
569
  remediation: `Pass one or more unique currencies listed for ${platform} by capabilities().`
567
570
  }),
571
+ invalidPayoutPlatforms: (reason) => new CashError({
572
+ code: "INVALID_PAYOUT_PLATFORMS",
573
+ message: `The payout platform set is invalid: ${reason}.`,
574
+ retryable: false,
575
+ remediation: `Pass one payout leg, or an array of legs using each platform from capabilities() at most once.`
576
+ }),
568
577
  invalidReferralCode: () => new CashError({
569
578
  code: "INVALID_REFERRAL_CODE",
570
579
  message: `The Peer referral code must be exactly six letters or numbers.`,
@@ -1805,41 +1814,51 @@ function createCashClient(options) {
1805
1814
  return client;
1806
1815
  }
1807
1816
  function validatePayout(input) {
1808
- const { receive } = input;
1809
- const platform = buildCapabilities(environment).platforms.find(
1810
- (capability) => capability.platform === receive.platform
1811
- );
1812
- if (!platform) throw errors.unsupportedPlatform(receive.platform);
1813
- if (receive.currency === void 0 === (receive.currencies === void 0)) {
1814
- throw errors.invalidPayoutCurrencies(
1815
- receive.platform,
1816
- "pass exactly one of currency or currencies"
1817
- );
1818
- }
1819
- const currencies = receive.currencies !== void 0 ? [...receive.currencies] : [receive.currency];
1820
- if (currencies.length === 0) {
1821
- throw errors.invalidPayoutCurrencies(receive.platform, "at least one currency is required");
1817
+ const legs = Array.isArray(input.receive) ? input.receive : [input.receive];
1818
+ if (legs.length === 0) {
1819
+ throw errors.invalidPayoutPlatforms("at least one payout leg is required");
1822
1820
  }
1823
- if (new Set(currencies).size !== currencies.length) {
1824
- throw errors.invalidPayoutCurrencies(receive.platform, "currencies must be unique");
1825
- }
1826
- for (const currency of currencies) {
1827
- if (!isMarketRateSupported(currency)) {
1828
- throw errors.oracleUnsupportedCurrency(currency);
1821
+ const capabilities2 = buildCapabilities(environment);
1822
+ const seenPlatforms = /* @__PURE__ */ new Set();
1823
+ const payouts = legs.map((leg) => {
1824
+ const platform = capabilities2.platforms.find(
1825
+ (capability) => capability.platform === leg.platform
1826
+ );
1827
+ if (!platform) throw errors.unsupportedPlatform(leg.platform);
1828
+ if (seenPlatforms.has(leg.platform)) {
1829
+ throw errors.invalidPayoutPlatforms(
1830
+ `${leg.platform} appears more than once - each platform may carry one leg`
1831
+ );
1829
1832
  }
1830
- if (!platform.currencies.includes(currency)) {
1831
- throw errors.unsupportedPlatformCurrency(receive.platform, currency);
1833
+ seenPlatforms.add(leg.platform);
1834
+ if (leg.currency === void 0 === (leg.currencies === void 0)) {
1835
+ throw errors.invalidPayoutCurrencies(
1836
+ leg.platform,
1837
+ "pass exactly one of currency or currencies"
1838
+ );
1832
1839
  }
1833
- }
1834
- return {
1835
- payouts: [
1836
- {
1837
- processorName: receive.platform,
1838
- ...currencies.length === 1 ? { currency: currencies[0] } : { currencies },
1839
- payeeData: normalizeCashPayee(receive.platform, receive.payee)
1840
+ const currencies = leg.currencies !== void 0 ? [...leg.currencies] : [leg.currency];
1841
+ if (currencies.length === 0) {
1842
+ throw errors.invalidPayoutCurrencies(leg.platform, "at least one currency is required");
1843
+ }
1844
+ if (new Set(currencies).size !== currencies.length) {
1845
+ throw errors.invalidPayoutCurrencies(leg.platform, "currencies must be unique");
1846
+ }
1847
+ for (const currency of currencies) {
1848
+ if (!isMarketRateSupported(currency)) {
1849
+ throw errors.oracleUnsupportedCurrency(currency);
1840
1850
  }
1841
- ]
1842
- };
1851
+ if (!platform.currencies.includes(currency)) {
1852
+ throw errors.unsupportedPlatformCurrency(leg.platform, currency);
1853
+ }
1854
+ }
1855
+ return {
1856
+ processorName: leg.platform,
1857
+ ...currencies.length === 1 ? { currency: currencies[0] } : { currencies },
1858
+ payeeData: normalizeCashPayee(leg.platform, leg.payee)
1859
+ };
1860
+ });
1861
+ return { payouts };
1843
1862
  }
1844
1863
  function validateDepositInput(amount, input, payoutInput = validatePayout(input)) {
1845
1864
  if (amount < MIN_CASHOUT_AMOUNT) {
@@ -1856,12 +1875,7 @@ function createCashClient(options) {
1856
1875
  };
1857
1876
  }
1858
1877
  function isCashPayoutSet(payouts) {
1859
- const first = payouts[0];
1860
- return Boolean(
1861
- first && payouts.every(
1862
- (payout) => payout.platformHash.toLowerCase() === first.platformHash.toLowerCase() && payout.payeeHash.toLowerCase() === first.payeeHash.toLowerCase() && payout.pricing.marketRate && payout.pricing.spreadBps === 0
1863
- )
1864
- );
1878
+ return payouts.length > 0 && payouts.every((payout) => payout.pricing.marketRate && payout.pricing.spreadBps === 0);
1865
1879
  }
1866
1880
  async function buildDepositParams(client, depositInput) {
1867
1881
  try {
@@ -1870,7 +1884,8 @@ function createCashClient(options) {
1870
1884
  if (isCashError(err)) throw err;
1871
1885
  const message = err instanceof Error ? err.message : String(err);
1872
1886
  if (/identityAttestation is required|identity attestation/i.test(message)) {
1873
- const platform = depositInput.payouts[0]?.processorName ?? "this platform";
1887
+ const platforms = depositInput.payouts.map((payout) => payout.processorName);
1888
+ const platform = platforms.find(platformRequiresIdentityAttestation) ?? platforms[0] ?? "this platform";
1874
1889
  throw errors.payeeVerificationRequired(platform, err);
1875
1890
  }
1876
1891
  throw errors.payeeRegistrationFailed(err);
@@ -2879,6 +2894,7 @@ var CASH_ERROR_CODES = defineCashErrorCodes([
2879
2894
  "AMOUNT_BELOW_MINIMUM",
2880
2895
  "INVALID_INTENT_AMOUNT_RANGE",
2881
2896
  "INVALID_PAYOUT_CURRENCIES",
2897
+ "INVALID_PAYOUT_PLATFORMS",
2882
2898
  "INVALID_REFERRAL_CODE",
2883
2899
  "ACTIVE_INTENT_BLOCKS_WITHDRAWAL",
2884
2900
  "NOTHING_TO_WITHDRAW",
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { I as IntentStatus, C as CashPayoutInfo, a as IntentEntity, b as CashBuyerProfile, c as CashDepositInput, d as CreateDepositParamsArg, e as CashOrder, f as CashFill, g as CashCapabilities, h as CashoutResult, i as CashEstimate, j as CashFillStats, P as PrepareResult, k as CashPreparedStep, R as RelayExecutionResult, l as RelayQuote, m as RelayStatus, n as CashSourceCapabilities, T as TopUpResult, W as WithdrawResult } from './createCashClient-D8gw-Hhv.cjs';
2
- export { o as CASH_ATTRIBUTION_CODE, p as CASH_REFERRAL_ATTRIBUTION_PREFIX, q as CashAsset, r as CashChain, s as CashClient, t as CashClientOptions, u as CashFillEta, v as CashLeg, w as CashMultiCurrencyLeg, x as CashNextAction, y as CashOrderState, z as CashPairFillStats, A as CashPayeeInput, B as CashPayout, D as CashPayoutPricing, E as CashPlatformCapability, F as CashPreparedStepKind, G as CashoutInput, H as CashoutOptions, J as CuratorPayeeDataInput, K as EstimateInput, L as EstimateOptions, M as MIN_CASHOUT_AMOUNT, O as OrdersOptions, N as PreparedCashoutReceipt, Q as RECOMMENDED_MIN_CASHOUT_AMOUNT, S as RelayOptions, U as RelayQuoteInput, V as RelaySourceInput, X as RelayTransaction, Y as SignerOptions, Z as WatchOptions, _ as WithdrawOptions, $ as buildCapabilities, a0 as createCashClient, a1 as normalizeCashPayee, a2 as toCashReferralAttributionCode } from './createCashClient-D8gw-Hhv.cjs';
1
+ import { I as IntentStatus, C as CashPayoutInfo, a as IntentEntity, b as CashBuyerProfile, c as CashDepositInput, d as CreateDepositParamsArg, e as CashOrder, f as CashFill, g as CashCapabilities, h as CashoutResult, i as CashEstimate, j as CashFillStats, P as PrepareResult, k as CashPreparedStep, R as RelayExecutionResult, l as RelayQuote, m as RelayStatus, n as CashSourceCapabilities, T as TopUpResult, W as WithdrawResult } from './createCashClient-CYSM84-K.cjs';
2
+ export { o as CASH_ATTRIBUTION_CODE, p as CASH_REFERRAL_ATTRIBUTION_PREFIX, q as CashAsset, r as CashChain, s as CashClient, t as CashClientOptions, u as CashFillEta, v as CashLeg, w as CashMultiCurrencyLeg, x as CashNextAction, y as CashOrderState, z as CashPairFillStats, A as CashPayeeInput, B as CashPayout, D as CashPayoutPricing, E as CashPlatformCapability, F as CashPreparedStepKind, G as CashReceiveLeg, H as CashoutInput, J as CashoutOptions, K as CuratorPayeeDataInput, L as EstimateInput, M as EstimateOptions, N as MIN_CASHOUT_AMOUNT, O as OrdersOptions, Q as PreparedCashoutReceipt, S as RECOMMENDED_MIN_CASHOUT_AMOUNT, U as RelayOptions, V as RelayQuoteInput, X as RelaySourceInput, Y as RelayTransaction, Z as SignerOptions, _ as WatchOptions, $ as WithdrawOptions, a0 as buildCapabilities, a1 as createCashClient, a2 as normalizeCashPayee, a3 as toCashReferralAttributionCode } from './createCashClient-CYSM84-K.cjs';
3
3
  import { PaymentMethodCatalog, CurrencyType, OracleAdapterOverrides, OnchainCurrency, Zkp2pClient, PreparedTransaction } from '@zkp2p/sdk';
4
4
  export { CurrencyType, PreparedTransaction, RuntimeEnv } from '@zkp2p/sdk';
5
5
  import { Log, Abi } from 'viem';
@@ -10,7 +10,7 @@ import '@relayprotocol/relay-sdk';
10
10
  * Typed errors - every failure carries a `code`, whether it is `retryable`,
11
11
  * and a `remediation` sentence so agents can self-drive recovery.
12
12
  */
13
- type CashErrorCode = 'ORACLE_UNSUPPORTED_CURRENCY' | 'ORACLE_READ_FAILED' | 'UNSUPPORTED_PLATFORM' | 'UNSUPPORTED_PLATFORM_CURRENCY' | 'AMOUNT_BELOW_MINIMUM' | 'INVALID_INTENT_AMOUNT_RANGE' | 'INVALID_PAYOUT_CURRENCIES' | 'INVALID_REFERRAL_CODE' | 'ACTIVE_INTENT_BLOCKS_WITHDRAWAL' | 'NOTHING_TO_WITHDRAW' | 'INSUFFICIENT_AVAILABLE_FUNDS' | 'INSUFFICIENT_TOKEN_BALANCE' | 'ORDER_NOT_ACTIVE' | 'INVALID_DEPOSIT_ID' | 'ESCROW_PAUSED' | 'INDEXER_LAG' | 'INDEXER_UNAVAILABLE' | 'ORDER_NOT_FOUND' | 'PAYEE_REGISTRATION_FAILED' | 'PAYEE_VERIFICATION_REQUIRED' | 'SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE' | 'SOURCE_RECIPIENT_MISMATCH' | 'SOURCE_CAPABILITIES_FAILED' | 'SOURCE_QUOTE_FAILED' | 'SOURCE_NONCE_MANAGER_REQUIRED' | 'SOURCE_EXECUTION_FAILED' | 'SOURCE_STATUS_FAILED' | 'SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED' | 'SOURCE_CASHOUT_SUBMISSION_UNKNOWN' | 'SOURCE_CASHOUT_STATUS_UNKNOWN' | 'DEPOSIT_RESOLUTION_FAILED' | 'ALLOWANCE_NOT_VISIBLE' | 'SIGNER_REQUIRED' | 'SIGNER_CHAIN_MISMATCH' | 'SIGNER_CHAIN_UNAVAILABLE' | 'WATCH_TIMEOUT' | 'TRANSACTION_REJECTED' | 'TRANSACTION_FAILED' | 'TRANSACTION_SUBMISSION_UNKNOWN' | 'TRANSACTION_STATUS_UNKNOWN';
13
+ type CashErrorCode = 'ORACLE_UNSUPPORTED_CURRENCY' | 'ORACLE_READ_FAILED' | 'UNSUPPORTED_PLATFORM' | 'UNSUPPORTED_PLATFORM_CURRENCY' | 'AMOUNT_BELOW_MINIMUM' | 'INVALID_INTENT_AMOUNT_RANGE' | 'INVALID_PAYOUT_CURRENCIES' | 'INVALID_PAYOUT_PLATFORMS' | 'INVALID_REFERRAL_CODE' | 'ACTIVE_INTENT_BLOCKS_WITHDRAWAL' | 'NOTHING_TO_WITHDRAW' | 'INSUFFICIENT_AVAILABLE_FUNDS' | 'INSUFFICIENT_TOKEN_BALANCE' | 'ORDER_NOT_ACTIVE' | 'INVALID_DEPOSIT_ID' | 'ESCROW_PAUSED' | 'INDEXER_LAG' | 'INDEXER_UNAVAILABLE' | 'ORDER_NOT_FOUND' | 'PAYEE_REGISTRATION_FAILED' | 'PAYEE_VERIFICATION_REQUIRED' | 'SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE' | 'SOURCE_RECIPIENT_MISMATCH' | 'SOURCE_CAPABILITIES_FAILED' | 'SOURCE_QUOTE_FAILED' | 'SOURCE_NONCE_MANAGER_REQUIRED' | 'SOURCE_EXECUTION_FAILED' | 'SOURCE_STATUS_FAILED' | 'SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED' | 'SOURCE_CASHOUT_SUBMISSION_UNKNOWN' | 'SOURCE_CASHOUT_STATUS_UNKNOWN' | 'DEPOSIT_RESOLUTION_FAILED' | 'ALLOWANCE_NOT_VISIBLE' | 'SIGNER_REQUIRED' | 'SIGNER_CHAIN_MISMATCH' | 'SIGNER_CHAIN_UNAVAILABLE' | 'WATCH_TIMEOUT' | 'TRANSACTION_REJECTED' | 'TRANSACTION_FAILED' | 'TRANSACTION_SUBMISSION_UNKNOWN' | 'TRANSACTION_STATUS_UNKNOWN';
14
14
  interface CashErrorShape {
15
15
  code: CashErrorCode;
16
16
  message: string;
@@ -78,6 +78,7 @@ declare const errors: {
78
78
  amountBelowMinimum: (amount: bigint, min: bigint) => CashError;
79
79
  invalidIntentAmountRange: (amount: bigint, min: bigint, max: bigint) => CashError;
80
80
  invalidPayoutCurrencies: (platform: string, reason: string) => CashError;
81
+ invalidPayoutPlatforms: (reason: string) => CashError;
81
82
  invalidReferralCode: () => CashError;
82
83
  activeIntentBlocksWithdrawal: (depositId: string) => CashError;
83
84
  insufficientAvailableFunds: (depositId: string, requested: bigint, available: bigint) => CashError;
@@ -224,9 +225,9 @@ interface MethodCurrencyLike {
224
225
  /**
225
226
  * Decode a deposit's payment methods + currency tuples into payout legs.
226
227
  * Pure - the environment arrives via the catalog. One leg per
227
- * (method, currency) pair; cash orders create exactly one in v1. If any
228
- * method is absent from the active catalog, reject the whole set instead of
229
- * partially reclassifying a mixed historical deposit.
228
+ * (method, currency) pair; a cash order carries one or several platforms. If
229
+ * any method is absent from the active catalog, reject the whole set instead
230
+ * of partially reclassifying a mixed historical deposit.
230
231
  */
231
232
  declare function derivePayouts(paymentMethods: ReadonlyArray<PaymentMethodLike>, currencies: ReadonlyArray<MethodCurrencyLike>, catalog: PaymentMethodCatalog): CashPayoutInfo[];
232
233
 
@@ -3185,7 +3186,7 @@ declare const cashErrorRecoveryJsonSchema: z.ZodDiscriminatedUnion<"kind", [z.Zo
3185
3186
  operation: string;
3186
3187
  }>]>;
3187
3188
  declare const cashErrorJsonSchema: z.ZodObject<{
3188
- code: z.ZodEnum<["ORACLE_UNSUPPORTED_CURRENCY", "ORACLE_READ_FAILED", "UNSUPPORTED_PLATFORM", "UNSUPPORTED_PLATFORM_CURRENCY", "AMOUNT_BELOW_MINIMUM", "INVALID_INTENT_AMOUNT_RANGE", "INVALID_PAYOUT_CURRENCIES", "INVALID_REFERRAL_CODE", "ACTIVE_INTENT_BLOCKS_WITHDRAWAL", "NOTHING_TO_WITHDRAW", "INSUFFICIENT_AVAILABLE_FUNDS", "INSUFFICIENT_TOKEN_BALANCE", "ORDER_NOT_ACTIVE", "INVALID_DEPOSIT_ID", "ESCROW_PAUSED", "INDEXER_LAG", "INDEXER_UNAVAILABLE", "ORDER_NOT_FOUND", "PAYEE_REGISTRATION_FAILED", "PAYEE_VERIFICATION_REQUIRED", "SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE", "SOURCE_RECIPIENT_MISMATCH", "SOURCE_CAPABILITIES_FAILED", "SOURCE_QUOTE_FAILED", "SOURCE_NONCE_MANAGER_REQUIRED", "SOURCE_EXECUTION_FAILED", "SOURCE_STATUS_FAILED", "SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED", "SOURCE_CASHOUT_SUBMISSION_UNKNOWN", "SOURCE_CASHOUT_STATUS_UNKNOWN", "DEPOSIT_RESOLUTION_FAILED", "ALLOWANCE_NOT_VISIBLE", "SIGNER_REQUIRED", "SIGNER_CHAIN_MISMATCH", "SIGNER_CHAIN_UNAVAILABLE", "WATCH_TIMEOUT", "TRANSACTION_REJECTED", "TRANSACTION_FAILED", "TRANSACTION_SUBMISSION_UNKNOWN", "TRANSACTION_STATUS_UNKNOWN"]>;
3189
+ code: z.ZodEnum<["ORACLE_UNSUPPORTED_CURRENCY", "ORACLE_READ_FAILED", "UNSUPPORTED_PLATFORM", "UNSUPPORTED_PLATFORM_CURRENCY", "AMOUNT_BELOW_MINIMUM", "INVALID_INTENT_AMOUNT_RANGE", "INVALID_PAYOUT_CURRENCIES", "INVALID_PAYOUT_PLATFORMS", "INVALID_REFERRAL_CODE", "ACTIVE_INTENT_BLOCKS_WITHDRAWAL", "NOTHING_TO_WITHDRAW", "INSUFFICIENT_AVAILABLE_FUNDS", "INSUFFICIENT_TOKEN_BALANCE", "ORDER_NOT_ACTIVE", "INVALID_DEPOSIT_ID", "ESCROW_PAUSED", "INDEXER_LAG", "INDEXER_UNAVAILABLE", "ORDER_NOT_FOUND", "PAYEE_REGISTRATION_FAILED", "PAYEE_VERIFICATION_REQUIRED", "SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE", "SOURCE_RECIPIENT_MISMATCH", "SOURCE_CAPABILITIES_FAILED", "SOURCE_QUOTE_FAILED", "SOURCE_NONCE_MANAGER_REQUIRED", "SOURCE_EXECUTION_FAILED", "SOURCE_STATUS_FAILED", "SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED", "SOURCE_CASHOUT_SUBMISSION_UNKNOWN", "SOURCE_CASHOUT_STATUS_UNKNOWN", "DEPOSIT_RESOLUTION_FAILED", "ALLOWANCE_NOT_VISIBLE", "SIGNER_REQUIRED", "SIGNER_CHAIN_MISMATCH", "SIGNER_CHAIN_UNAVAILABLE", "WATCH_TIMEOUT", "TRANSACTION_REJECTED", "TRANSACTION_FAILED", "TRANSACTION_SUBMISSION_UNKNOWN", "TRANSACTION_STATUS_UNKNOWN"]>;
3189
3190
  message: z.ZodString;
3190
3191
  retryable: z.ZodBoolean;
3191
3192
  remediation: z.ZodString;
@@ -3572,7 +3573,7 @@ declare const cashErrorJsonSchema: z.ZodObject<{
3572
3573
  }>]>>;
3573
3574
  }, "strict", z.ZodTypeAny, {
3574
3575
  message: string;
3575
- code: "ORACLE_UNSUPPORTED_CURRENCY" | "ORACLE_READ_FAILED" | "UNSUPPORTED_PLATFORM" | "UNSUPPORTED_PLATFORM_CURRENCY" | "AMOUNT_BELOW_MINIMUM" | "INVALID_INTENT_AMOUNT_RANGE" | "INVALID_PAYOUT_CURRENCIES" | "INVALID_REFERRAL_CODE" | "ACTIVE_INTENT_BLOCKS_WITHDRAWAL" | "NOTHING_TO_WITHDRAW" | "INSUFFICIENT_AVAILABLE_FUNDS" | "INSUFFICIENT_TOKEN_BALANCE" | "ORDER_NOT_ACTIVE" | "INVALID_DEPOSIT_ID" | "ESCROW_PAUSED" | "INDEXER_LAG" | "INDEXER_UNAVAILABLE" | "ORDER_NOT_FOUND" | "PAYEE_REGISTRATION_FAILED" | "PAYEE_VERIFICATION_REQUIRED" | "SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE" | "SOURCE_RECIPIENT_MISMATCH" | "SOURCE_CAPABILITIES_FAILED" | "SOURCE_QUOTE_FAILED" | "SOURCE_NONCE_MANAGER_REQUIRED" | "SOURCE_EXECUTION_FAILED" | "SOURCE_STATUS_FAILED" | "SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED" | "SOURCE_CASHOUT_SUBMISSION_UNKNOWN" | "SOURCE_CASHOUT_STATUS_UNKNOWN" | "DEPOSIT_RESOLUTION_FAILED" | "ALLOWANCE_NOT_VISIBLE" | "SIGNER_REQUIRED" | "SIGNER_CHAIN_MISMATCH" | "SIGNER_CHAIN_UNAVAILABLE" | "WATCH_TIMEOUT" | "TRANSACTION_REJECTED" | "TRANSACTION_FAILED" | "TRANSACTION_SUBMISSION_UNKNOWN" | "TRANSACTION_STATUS_UNKNOWN";
3576
+ code: "ORACLE_UNSUPPORTED_CURRENCY" | "ORACLE_READ_FAILED" | "UNSUPPORTED_PLATFORM" | "UNSUPPORTED_PLATFORM_CURRENCY" | "AMOUNT_BELOW_MINIMUM" | "INVALID_INTENT_AMOUNT_RANGE" | "INVALID_PAYOUT_CURRENCIES" | "INVALID_PAYOUT_PLATFORMS" | "INVALID_REFERRAL_CODE" | "ACTIVE_INTENT_BLOCKS_WITHDRAWAL" | "NOTHING_TO_WITHDRAW" | "INSUFFICIENT_AVAILABLE_FUNDS" | "INSUFFICIENT_TOKEN_BALANCE" | "ORDER_NOT_ACTIVE" | "INVALID_DEPOSIT_ID" | "ESCROW_PAUSED" | "INDEXER_LAG" | "INDEXER_UNAVAILABLE" | "ORDER_NOT_FOUND" | "PAYEE_REGISTRATION_FAILED" | "PAYEE_VERIFICATION_REQUIRED" | "SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE" | "SOURCE_RECIPIENT_MISMATCH" | "SOURCE_CAPABILITIES_FAILED" | "SOURCE_QUOTE_FAILED" | "SOURCE_NONCE_MANAGER_REQUIRED" | "SOURCE_EXECUTION_FAILED" | "SOURCE_STATUS_FAILED" | "SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED" | "SOURCE_CASHOUT_SUBMISSION_UNKNOWN" | "SOURCE_CASHOUT_STATUS_UNKNOWN" | "DEPOSIT_RESOLUTION_FAILED" | "ALLOWANCE_NOT_VISIBLE" | "SIGNER_REQUIRED" | "SIGNER_CHAIN_MISMATCH" | "SIGNER_CHAIN_UNAVAILABLE" | "WATCH_TIMEOUT" | "TRANSACTION_REJECTED" | "TRANSACTION_FAILED" | "TRANSACTION_SUBMISSION_UNKNOWN" | "TRANSACTION_STATUS_UNKNOWN";
3576
3577
  retryable: boolean;
3577
3578
  remediation: string;
3578
3579
  recovery?: {
@@ -3654,7 +3655,7 @@ declare const cashErrorJsonSchema: z.ZodObject<{
3654
3655
  } | undefined;
3655
3656
  }, {
3656
3657
  message: string;
3657
- code: "ORACLE_UNSUPPORTED_CURRENCY" | "ORACLE_READ_FAILED" | "UNSUPPORTED_PLATFORM" | "UNSUPPORTED_PLATFORM_CURRENCY" | "AMOUNT_BELOW_MINIMUM" | "INVALID_INTENT_AMOUNT_RANGE" | "INVALID_PAYOUT_CURRENCIES" | "INVALID_REFERRAL_CODE" | "ACTIVE_INTENT_BLOCKS_WITHDRAWAL" | "NOTHING_TO_WITHDRAW" | "INSUFFICIENT_AVAILABLE_FUNDS" | "INSUFFICIENT_TOKEN_BALANCE" | "ORDER_NOT_ACTIVE" | "INVALID_DEPOSIT_ID" | "ESCROW_PAUSED" | "INDEXER_LAG" | "INDEXER_UNAVAILABLE" | "ORDER_NOT_FOUND" | "PAYEE_REGISTRATION_FAILED" | "PAYEE_VERIFICATION_REQUIRED" | "SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE" | "SOURCE_RECIPIENT_MISMATCH" | "SOURCE_CAPABILITIES_FAILED" | "SOURCE_QUOTE_FAILED" | "SOURCE_NONCE_MANAGER_REQUIRED" | "SOURCE_EXECUTION_FAILED" | "SOURCE_STATUS_FAILED" | "SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED" | "SOURCE_CASHOUT_SUBMISSION_UNKNOWN" | "SOURCE_CASHOUT_STATUS_UNKNOWN" | "DEPOSIT_RESOLUTION_FAILED" | "ALLOWANCE_NOT_VISIBLE" | "SIGNER_REQUIRED" | "SIGNER_CHAIN_MISMATCH" | "SIGNER_CHAIN_UNAVAILABLE" | "WATCH_TIMEOUT" | "TRANSACTION_REJECTED" | "TRANSACTION_FAILED" | "TRANSACTION_SUBMISSION_UNKNOWN" | "TRANSACTION_STATUS_UNKNOWN";
3658
+ code: "ORACLE_UNSUPPORTED_CURRENCY" | "ORACLE_READ_FAILED" | "UNSUPPORTED_PLATFORM" | "UNSUPPORTED_PLATFORM_CURRENCY" | "AMOUNT_BELOW_MINIMUM" | "INVALID_INTENT_AMOUNT_RANGE" | "INVALID_PAYOUT_CURRENCIES" | "INVALID_PAYOUT_PLATFORMS" | "INVALID_REFERRAL_CODE" | "ACTIVE_INTENT_BLOCKS_WITHDRAWAL" | "NOTHING_TO_WITHDRAW" | "INSUFFICIENT_AVAILABLE_FUNDS" | "INSUFFICIENT_TOKEN_BALANCE" | "ORDER_NOT_ACTIVE" | "INVALID_DEPOSIT_ID" | "ESCROW_PAUSED" | "INDEXER_LAG" | "INDEXER_UNAVAILABLE" | "ORDER_NOT_FOUND" | "PAYEE_REGISTRATION_FAILED" | "PAYEE_VERIFICATION_REQUIRED" | "SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE" | "SOURCE_RECIPIENT_MISMATCH" | "SOURCE_CAPABILITIES_FAILED" | "SOURCE_QUOTE_FAILED" | "SOURCE_NONCE_MANAGER_REQUIRED" | "SOURCE_EXECUTION_FAILED" | "SOURCE_STATUS_FAILED" | "SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED" | "SOURCE_CASHOUT_SUBMISSION_UNKNOWN" | "SOURCE_CASHOUT_STATUS_UNKNOWN" | "DEPOSIT_RESOLUTION_FAILED" | "ALLOWANCE_NOT_VISIBLE" | "SIGNER_REQUIRED" | "SIGNER_CHAIN_MISMATCH" | "SIGNER_CHAIN_UNAVAILABLE" | "WATCH_TIMEOUT" | "TRANSACTION_REJECTED" | "TRANSACTION_FAILED" | "TRANSACTION_SUBMISSION_UNKNOWN" | "TRANSACTION_STATUS_UNKNOWN";
3658
3659
  retryable: boolean;
3659
3660
  remediation: string;
3660
3661
  recovery?: {
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { I as IntentStatus, C as CashPayoutInfo, a as IntentEntity, b as CashBuyerProfile, c as CashDepositInput, d as CreateDepositParamsArg, e as CashOrder, f as CashFill, g as CashCapabilities, h as CashoutResult, i as CashEstimate, j as CashFillStats, P as PrepareResult, k as CashPreparedStep, R as RelayExecutionResult, l as RelayQuote, m as RelayStatus, n as CashSourceCapabilities, T as TopUpResult, W as WithdrawResult } from './createCashClient-D8gw-Hhv.js';
2
- export { o as CASH_ATTRIBUTION_CODE, p as CASH_REFERRAL_ATTRIBUTION_PREFIX, q as CashAsset, r as CashChain, s as CashClient, t as CashClientOptions, u as CashFillEta, v as CashLeg, w as CashMultiCurrencyLeg, x as CashNextAction, y as CashOrderState, z as CashPairFillStats, A as CashPayeeInput, B as CashPayout, D as CashPayoutPricing, E as CashPlatformCapability, F as CashPreparedStepKind, G as CashoutInput, H as CashoutOptions, J as CuratorPayeeDataInput, K as EstimateInput, L as EstimateOptions, M as MIN_CASHOUT_AMOUNT, O as OrdersOptions, N as PreparedCashoutReceipt, Q as RECOMMENDED_MIN_CASHOUT_AMOUNT, S as RelayOptions, U as RelayQuoteInput, V as RelaySourceInput, X as RelayTransaction, Y as SignerOptions, Z as WatchOptions, _ as WithdrawOptions, $ as buildCapabilities, a0 as createCashClient, a1 as normalizeCashPayee, a2 as toCashReferralAttributionCode } from './createCashClient-D8gw-Hhv.js';
1
+ import { I as IntentStatus, C as CashPayoutInfo, a as IntentEntity, b as CashBuyerProfile, c as CashDepositInput, d as CreateDepositParamsArg, e as CashOrder, f as CashFill, g as CashCapabilities, h as CashoutResult, i as CashEstimate, j as CashFillStats, P as PrepareResult, k as CashPreparedStep, R as RelayExecutionResult, l as RelayQuote, m as RelayStatus, n as CashSourceCapabilities, T as TopUpResult, W as WithdrawResult } from './createCashClient-CYSM84-K.js';
2
+ export { o as CASH_ATTRIBUTION_CODE, p as CASH_REFERRAL_ATTRIBUTION_PREFIX, q as CashAsset, r as CashChain, s as CashClient, t as CashClientOptions, u as CashFillEta, v as CashLeg, w as CashMultiCurrencyLeg, x as CashNextAction, y as CashOrderState, z as CashPairFillStats, A as CashPayeeInput, B as CashPayout, D as CashPayoutPricing, E as CashPlatformCapability, F as CashPreparedStepKind, G as CashReceiveLeg, H as CashoutInput, J as CashoutOptions, K as CuratorPayeeDataInput, L as EstimateInput, M as EstimateOptions, N as MIN_CASHOUT_AMOUNT, O as OrdersOptions, Q as PreparedCashoutReceipt, S as RECOMMENDED_MIN_CASHOUT_AMOUNT, U as RelayOptions, V as RelayQuoteInput, X as RelaySourceInput, Y as RelayTransaction, Z as SignerOptions, _ as WatchOptions, $ as WithdrawOptions, a0 as buildCapabilities, a1 as createCashClient, a2 as normalizeCashPayee, a3 as toCashReferralAttributionCode } from './createCashClient-CYSM84-K.js';
3
3
  import { PaymentMethodCatalog, CurrencyType, OracleAdapterOverrides, OnchainCurrency, Zkp2pClient, PreparedTransaction } from '@zkp2p/sdk';
4
4
  export { CurrencyType, PreparedTransaction, RuntimeEnv } from '@zkp2p/sdk';
5
5
  import { Log, Abi } from 'viem';
@@ -10,7 +10,7 @@ import '@relayprotocol/relay-sdk';
10
10
  * Typed errors - every failure carries a `code`, whether it is `retryable`,
11
11
  * and a `remediation` sentence so agents can self-drive recovery.
12
12
  */
13
- type CashErrorCode = 'ORACLE_UNSUPPORTED_CURRENCY' | 'ORACLE_READ_FAILED' | 'UNSUPPORTED_PLATFORM' | 'UNSUPPORTED_PLATFORM_CURRENCY' | 'AMOUNT_BELOW_MINIMUM' | 'INVALID_INTENT_AMOUNT_RANGE' | 'INVALID_PAYOUT_CURRENCIES' | 'INVALID_REFERRAL_CODE' | 'ACTIVE_INTENT_BLOCKS_WITHDRAWAL' | 'NOTHING_TO_WITHDRAW' | 'INSUFFICIENT_AVAILABLE_FUNDS' | 'INSUFFICIENT_TOKEN_BALANCE' | 'ORDER_NOT_ACTIVE' | 'INVALID_DEPOSIT_ID' | 'ESCROW_PAUSED' | 'INDEXER_LAG' | 'INDEXER_UNAVAILABLE' | 'ORDER_NOT_FOUND' | 'PAYEE_REGISTRATION_FAILED' | 'PAYEE_VERIFICATION_REQUIRED' | 'SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE' | 'SOURCE_RECIPIENT_MISMATCH' | 'SOURCE_CAPABILITIES_FAILED' | 'SOURCE_QUOTE_FAILED' | 'SOURCE_NONCE_MANAGER_REQUIRED' | 'SOURCE_EXECUTION_FAILED' | 'SOURCE_STATUS_FAILED' | 'SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED' | 'SOURCE_CASHOUT_SUBMISSION_UNKNOWN' | 'SOURCE_CASHOUT_STATUS_UNKNOWN' | 'DEPOSIT_RESOLUTION_FAILED' | 'ALLOWANCE_NOT_VISIBLE' | 'SIGNER_REQUIRED' | 'SIGNER_CHAIN_MISMATCH' | 'SIGNER_CHAIN_UNAVAILABLE' | 'WATCH_TIMEOUT' | 'TRANSACTION_REJECTED' | 'TRANSACTION_FAILED' | 'TRANSACTION_SUBMISSION_UNKNOWN' | 'TRANSACTION_STATUS_UNKNOWN';
13
+ type CashErrorCode = 'ORACLE_UNSUPPORTED_CURRENCY' | 'ORACLE_READ_FAILED' | 'UNSUPPORTED_PLATFORM' | 'UNSUPPORTED_PLATFORM_CURRENCY' | 'AMOUNT_BELOW_MINIMUM' | 'INVALID_INTENT_AMOUNT_RANGE' | 'INVALID_PAYOUT_CURRENCIES' | 'INVALID_PAYOUT_PLATFORMS' | 'INVALID_REFERRAL_CODE' | 'ACTIVE_INTENT_BLOCKS_WITHDRAWAL' | 'NOTHING_TO_WITHDRAW' | 'INSUFFICIENT_AVAILABLE_FUNDS' | 'INSUFFICIENT_TOKEN_BALANCE' | 'ORDER_NOT_ACTIVE' | 'INVALID_DEPOSIT_ID' | 'ESCROW_PAUSED' | 'INDEXER_LAG' | 'INDEXER_UNAVAILABLE' | 'ORDER_NOT_FOUND' | 'PAYEE_REGISTRATION_FAILED' | 'PAYEE_VERIFICATION_REQUIRED' | 'SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE' | 'SOURCE_RECIPIENT_MISMATCH' | 'SOURCE_CAPABILITIES_FAILED' | 'SOURCE_QUOTE_FAILED' | 'SOURCE_NONCE_MANAGER_REQUIRED' | 'SOURCE_EXECUTION_FAILED' | 'SOURCE_STATUS_FAILED' | 'SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED' | 'SOURCE_CASHOUT_SUBMISSION_UNKNOWN' | 'SOURCE_CASHOUT_STATUS_UNKNOWN' | 'DEPOSIT_RESOLUTION_FAILED' | 'ALLOWANCE_NOT_VISIBLE' | 'SIGNER_REQUIRED' | 'SIGNER_CHAIN_MISMATCH' | 'SIGNER_CHAIN_UNAVAILABLE' | 'WATCH_TIMEOUT' | 'TRANSACTION_REJECTED' | 'TRANSACTION_FAILED' | 'TRANSACTION_SUBMISSION_UNKNOWN' | 'TRANSACTION_STATUS_UNKNOWN';
14
14
  interface CashErrorShape {
15
15
  code: CashErrorCode;
16
16
  message: string;
@@ -78,6 +78,7 @@ declare const errors: {
78
78
  amountBelowMinimum: (amount: bigint, min: bigint) => CashError;
79
79
  invalidIntentAmountRange: (amount: bigint, min: bigint, max: bigint) => CashError;
80
80
  invalidPayoutCurrencies: (platform: string, reason: string) => CashError;
81
+ invalidPayoutPlatforms: (reason: string) => CashError;
81
82
  invalidReferralCode: () => CashError;
82
83
  activeIntentBlocksWithdrawal: (depositId: string) => CashError;
83
84
  insufficientAvailableFunds: (depositId: string, requested: bigint, available: bigint) => CashError;
@@ -224,9 +225,9 @@ interface MethodCurrencyLike {
224
225
  /**
225
226
  * Decode a deposit's payment methods + currency tuples into payout legs.
226
227
  * Pure - the environment arrives via the catalog. One leg per
227
- * (method, currency) pair; cash orders create exactly one in v1. If any
228
- * method is absent from the active catalog, reject the whole set instead of
229
- * partially reclassifying a mixed historical deposit.
228
+ * (method, currency) pair; a cash order carries one or several platforms. If
229
+ * any method is absent from the active catalog, reject the whole set instead
230
+ * of partially reclassifying a mixed historical deposit.
230
231
  */
231
232
  declare function derivePayouts(paymentMethods: ReadonlyArray<PaymentMethodLike>, currencies: ReadonlyArray<MethodCurrencyLike>, catalog: PaymentMethodCatalog): CashPayoutInfo[];
232
233
 
@@ -3185,7 +3186,7 @@ declare const cashErrorRecoveryJsonSchema: z.ZodDiscriminatedUnion<"kind", [z.Zo
3185
3186
  operation: string;
3186
3187
  }>]>;
3187
3188
  declare const cashErrorJsonSchema: z.ZodObject<{
3188
- code: z.ZodEnum<["ORACLE_UNSUPPORTED_CURRENCY", "ORACLE_READ_FAILED", "UNSUPPORTED_PLATFORM", "UNSUPPORTED_PLATFORM_CURRENCY", "AMOUNT_BELOW_MINIMUM", "INVALID_INTENT_AMOUNT_RANGE", "INVALID_PAYOUT_CURRENCIES", "INVALID_REFERRAL_CODE", "ACTIVE_INTENT_BLOCKS_WITHDRAWAL", "NOTHING_TO_WITHDRAW", "INSUFFICIENT_AVAILABLE_FUNDS", "INSUFFICIENT_TOKEN_BALANCE", "ORDER_NOT_ACTIVE", "INVALID_DEPOSIT_ID", "ESCROW_PAUSED", "INDEXER_LAG", "INDEXER_UNAVAILABLE", "ORDER_NOT_FOUND", "PAYEE_REGISTRATION_FAILED", "PAYEE_VERIFICATION_REQUIRED", "SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE", "SOURCE_RECIPIENT_MISMATCH", "SOURCE_CAPABILITIES_FAILED", "SOURCE_QUOTE_FAILED", "SOURCE_NONCE_MANAGER_REQUIRED", "SOURCE_EXECUTION_FAILED", "SOURCE_STATUS_FAILED", "SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED", "SOURCE_CASHOUT_SUBMISSION_UNKNOWN", "SOURCE_CASHOUT_STATUS_UNKNOWN", "DEPOSIT_RESOLUTION_FAILED", "ALLOWANCE_NOT_VISIBLE", "SIGNER_REQUIRED", "SIGNER_CHAIN_MISMATCH", "SIGNER_CHAIN_UNAVAILABLE", "WATCH_TIMEOUT", "TRANSACTION_REJECTED", "TRANSACTION_FAILED", "TRANSACTION_SUBMISSION_UNKNOWN", "TRANSACTION_STATUS_UNKNOWN"]>;
3189
+ code: z.ZodEnum<["ORACLE_UNSUPPORTED_CURRENCY", "ORACLE_READ_FAILED", "UNSUPPORTED_PLATFORM", "UNSUPPORTED_PLATFORM_CURRENCY", "AMOUNT_BELOW_MINIMUM", "INVALID_INTENT_AMOUNT_RANGE", "INVALID_PAYOUT_CURRENCIES", "INVALID_PAYOUT_PLATFORMS", "INVALID_REFERRAL_CODE", "ACTIVE_INTENT_BLOCKS_WITHDRAWAL", "NOTHING_TO_WITHDRAW", "INSUFFICIENT_AVAILABLE_FUNDS", "INSUFFICIENT_TOKEN_BALANCE", "ORDER_NOT_ACTIVE", "INVALID_DEPOSIT_ID", "ESCROW_PAUSED", "INDEXER_LAG", "INDEXER_UNAVAILABLE", "ORDER_NOT_FOUND", "PAYEE_REGISTRATION_FAILED", "PAYEE_VERIFICATION_REQUIRED", "SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE", "SOURCE_RECIPIENT_MISMATCH", "SOURCE_CAPABILITIES_FAILED", "SOURCE_QUOTE_FAILED", "SOURCE_NONCE_MANAGER_REQUIRED", "SOURCE_EXECUTION_FAILED", "SOURCE_STATUS_FAILED", "SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED", "SOURCE_CASHOUT_SUBMISSION_UNKNOWN", "SOURCE_CASHOUT_STATUS_UNKNOWN", "DEPOSIT_RESOLUTION_FAILED", "ALLOWANCE_NOT_VISIBLE", "SIGNER_REQUIRED", "SIGNER_CHAIN_MISMATCH", "SIGNER_CHAIN_UNAVAILABLE", "WATCH_TIMEOUT", "TRANSACTION_REJECTED", "TRANSACTION_FAILED", "TRANSACTION_SUBMISSION_UNKNOWN", "TRANSACTION_STATUS_UNKNOWN"]>;
3189
3190
  message: z.ZodString;
3190
3191
  retryable: z.ZodBoolean;
3191
3192
  remediation: z.ZodString;
@@ -3572,7 +3573,7 @@ declare const cashErrorJsonSchema: z.ZodObject<{
3572
3573
  }>]>>;
3573
3574
  }, "strict", z.ZodTypeAny, {
3574
3575
  message: string;
3575
- code: "ORACLE_UNSUPPORTED_CURRENCY" | "ORACLE_READ_FAILED" | "UNSUPPORTED_PLATFORM" | "UNSUPPORTED_PLATFORM_CURRENCY" | "AMOUNT_BELOW_MINIMUM" | "INVALID_INTENT_AMOUNT_RANGE" | "INVALID_PAYOUT_CURRENCIES" | "INVALID_REFERRAL_CODE" | "ACTIVE_INTENT_BLOCKS_WITHDRAWAL" | "NOTHING_TO_WITHDRAW" | "INSUFFICIENT_AVAILABLE_FUNDS" | "INSUFFICIENT_TOKEN_BALANCE" | "ORDER_NOT_ACTIVE" | "INVALID_DEPOSIT_ID" | "ESCROW_PAUSED" | "INDEXER_LAG" | "INDEXER_UNAVAILABLE" | "ORDER_NOT_FOUND" | "PAYEE_REGISTRATION_FAILED" | "PAYEE_VERIFICATION_REQUIRED" | "SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE" | "SOURCE_RECIPIENT_MISMATCH" | "SOURCE_CAPABILITIES_FAILED" | "SOURCE_QUOTE_FAILED" | "SOURCE_NONCE_MANAGER_REQUIRED" | "SOURCE_EXECUTION_FAILED" | "SOURCE_STATUS_FAILED" | "SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED" | "SOURCE_CASHOUT_SUBMISSION_UNKNOWN" | "SOURCE_CASHOUT_STATUS_UNKNOWN" | "DEPOSIT_RESOLUTION_FAILED" | "ALLOWANCE_NOT_VISIBLE" | "SIGNER_REQUIRED" | "SIGNER_CHAIN_MISMATCH" | "SIGNER_CHAIN_UNAVAILABLE" | "WATCH_TIMEOUT" | "TRANSACTION_REJECTED" | "TRANSACTION_FAILED" | "TRANSACTION_SUBMISSION_UNKNOWN" | "TRANSACTION_STATUS_UNKNOWN";
3576
+ code: "ORACLE_UNSUPPORTED_CURRENCY" | "ORACLE_READ_FAILED" | "UNSUPPORTED_PLATFORM" | "UNSUPPORTED_PLATFORM_CURRENCY" | "AMOUNT_BELOW_MINIMUM" | "INVALID_INTENT_AMOUNT_RANGE" | "INVALID_PAYOUT_CURRENCIES" | "INVALID_PAYOUT_PLATFORMS" | "INVALID_REFERRAL_CODE" | "ACTIVE_INTENT_BLOCKS_WITHDRAWAL" | "NOTHING_TO_WITHDRAW" | "INSUFFICIENT_AVAILABLE_FUNDS" | "INSUFFICIENT_TOKEN_BALANCE" | "ORDER_NOT_ACTIVE" | "INVALID_DEPOSIT_ID" | "ESCROW_PAUSED" | "INDEXER_LAG" | "INDEXER_UNAVAILABLE" | "ORDER_NOT_FOUND" | "PAYEE_REGISTRATION_FAILED" | "PAYEE_VERIFICATION_REQUIRED" | "SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE" | "SOURCE_RECIPIENT_MISMATCH" | "SOURCE_CAPABILITIES_FAILED" | "SOURCE_QUOTE_FAILED" | "SOURCE_NONCE_MANAGER_REQUIRED" | "SOURCE_EXECUTION_FAILED" | "SOURCE_STATUS_FAILED" | "SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED" | "SOURCE_CASHOUT_SUBMISSION_UNKNOWN" | "SOURCE_CASHOUT_STATUS_UNKNOWN" | "DEPOSIT_RESOLUTION_FAILED" | "ALLOWANCE_NOT_VISIBLE" | "SIGNER_REQUIRED" | "SIGNER_CHAIN_MISMATCH" | "SIGNER_CHAIN_UNAVAILABLE" | "WATCH_TIMEOUT" | "TRANSACTION_REJECTED" | "TRANSACTION_FAILED" | "TRANSACTION_SUBMISSION_UNKNOWN" | "TRANSACTION_STATUS_UNKNOWN";
3576
3577
  retryable: boolean;
3577
3578
  remediation: string;
3578
3579
  recovery?: {
@@ -3654,7 +3655,7 @@ declare const cashErrorJsonSchema: z.ZodObject<{
3654
3655
  } | undefined;
3655
3656
  }, {
3656
3657
  message: string;
3657
- code: "ORACLE_UNSUPPORTED_CURRENCY" | "ORACLE_READ_FAILED" | "UNSUPPORTED_PLATFORM" | "UNSUPPORTED_PLATFORM_CURRENCY" | "AMOUNT_BELOW_MINIMUM" | "INVALID_INTENT_AMOUNT_RANGE" | "INVALID_PAYOUT_CURRENCIES" | "INVALID_REFERRAL_CODE" | "ACTIVE_INTENT_BLOCKS_WITHDRAWAL" | "NOTHING_TO_WITHDRAW" | "INSUFFICIENT_AVAILABLE_FUNDS" | "INSUFFICIENT_TOKEN_BALANCE" | "ORDER_NOT_ACTIVE" | "INVALID_DEPOSIT_ID" | "ESCROW_PAUSED" | "INDEXER_LAG" | "INDEXER_UNAVAILABLE" | "ORDER_NOT_FOUND" | "PAYEE_REGISTRATION_FAILED" | "PAYEE_VERIFICATION_REQUIRED" | "SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE" | "SOURCE_RECIPIENT_MISMATCH" | "SOURCE_CAPABILITIES_FAILED" | "SOURCE_QUOTE_FAILED" | "SOURCE_NONCE_MANAGER_REQUIRED" | "SOURCE_EXECUTION_FAILED" | "SOURCE_STATUS_FAILED" | "SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED" | "SOURCE_CASHOUT_SUBMISSION_UNKNOWN" | "SOURCE_CASHOUT_STATUS_UNKNOWN" | "DEPOSIT_RESOLUTION_FAILED" | "ALLOWANCE_NOT_VISIBLE" | "SIGNER_REQUIRED" | "SIGNER_CHAIN_MISMATCH" | "SIGNER_CHAIN_UNAVAILABLE" | "WATCH_TIMEOUT" | "TRANSACTION_REJECTED" | "TRANSACTION_FAILED" | "TRANSACTION_SUBMISSION_UNKNOWN" | "TRANSACTION_STATUS_UNKNOWN";
3658
+ code: "ORACLE_UNSUPPORTED_CURRENCY" | "ORACLE_READ_FAILED" | "UNSUPPORTED_PLATFORM" | "UNSUPPORTED_PLATFORM_CURRENCY" | "AMOUNT_BELOW_MINIMUM" | "INVALID_INTENT_AMOUNT_RANGE" | "INVALID_PAYOUT_CURRENCIES" | "INVALID_PAYOUT_PLATFORMS" | "INVALID_REFERRAL_CODE" | "ACTIVE_INTENT_BLOCKS_WITHDRAWAL" | "NOTHING_TO_WITHDRAW" | "INSUFFICIENT_AVAILABLE_FUNDS" | "INSUFFICIENT_TOKEN_BALANCE" | "ORDER_NOT_ACTIVE" | "INVALID_DEPOSIT_ID" | "ESCROW_PAUSED" | "INDEXER_LAG" | "INDEXER_UNAVAILABLE" | "ORDER_NOT_FOUND" | "PAYEE_REGISTRATION_FAILED" | "PAYEE_VERIFICATION_REQUIRED" | "SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE" | "SOURCE_RECIPIENT_MISMATCH" | "SOURCE_CAPABILITIES_FAILED" | "SOURCE_QUOTE_FAILED" | "SOURCE_NONCE_MANAGER_REQUIRED" | "SOURCE_EXECUTION_FAILED" | "SOURCE_STATUS_FAILED" | "SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED" | "SOURCE_CASHOUT_SUBMISSION_UNKNOWN" | "SOURCE_CASHOUT_STATUS_UNKNOWN" | "DEPOSIT_RESOLUTION_FAILED" | "ALLOWANCE_NOT_VISIBLE" | "SIGNER_REQUIRED" | "SIGNER_CHAIN_MISMATCH" | "SIGNER_CHAIN_UNAVAILABLE" | "WATCH_TIMEOUT" | "TRANSACTION_REJECTED" | "TRANSACTION_FAILED" | "TRANSACTION_SUBMISSION_UNKNOWN" | "TRANSACTION_STATUS_UNKNOWN";
3658
3659
  retryable: boolean;
3659
3660
  remediation: string;
3660
3661
  recovery?: {
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { MARKET_SPREAD_BPS, ORACLE_MIN_CONVERSION_RATE_SENTINEL, CASH_RETAIN_ON_EMPTY, BASE_USDC_ADDRESS, USDC_DECIMALS, BASE_CHAIN_ID, errors, isCashError, CASH_ORDER_STATUSES, mapChainError, CashError } from './chunk-QCRY4XPA.js';
2
- export { BASE_CHAIN_ID, BASE_USDC_ADDRESS, CASH_ORDER_POLL_INTERVAL_MS, CASH_ORDER_STATUSES, CASH_RETAIN_ON_EMPTY, CashError, MARKET_SPREAD_BPS, ORACLE_MIN_CONVERSION_RATE_SENTINEL, USDC_DECIMALS, errors, isCashError, isUserRejectedError } from './chunk-QCRY4XPA.js';
1
+ import { MARKET_SPREAD_BPS, ORACLE_MIN_CONVERSION_RATE_SENTINEL, CASH_RETAIN_ON_EMPTY, BASE_USDC_ADDRESS, USDC_DECIMALS, BASE_CHAIN_ID, errors, isCashError, CASH_ORDER_STATUSES, mapChainError, CashError } from './chunk-EIEGWWNX.js';
2
+ export { BASE_CHAIN_ID, BASE_USDC_ADDRESS, CASH_ORDER_POLL_INTERVAL_MS, CASH_ORDER_STATUSES, CASH_RETAIN_ON_EMPTY, CashError, MARKET_SPREAD_BPS, ORACLE_MIN_CONVERSION_RATE_SENTINEL, USDC_DECIMALS, errors, isCashError, isUserRejectedError } from './chunk-EIEGWWNX.js';
3
3
  import { parseAbi, parseEventLogs, isAddress, http, createWalletClient, encodeFunctionData } from 'viem';
4
4
  import { base } from 'viem/chains';
5
5
  import { getSpreadOracleConfig, currencyInfo, getPaymentMethodsCatalog, getGatingServiceAddress, resolvePaymentMethodHashFromCatalog, resolvePaymentMethodNameFromHash, getCurrencyCodeFromHash, createCompositeDepositId, appendAttributionToCalldata, Zkp2pClient, CHAINLINK_ORACLE_FEEDS } from '@zkp2p/sdk';
@@ -447,6 +447,9 @@ var PAYEE_HINTS = {
447
447
  n26: "MoneyBeam email or phone number"
448
448
  };
449
449
  var IDENTITY_ATTESTATION_PLATFORMS = /* @__PURE__ */ new Set(["wise", "paypal"]);
450
+ function platformRequiresIdentityAttestation(platform) {
451
+ return IDENTITY_ATTESTATION_PLATFORMS.has(platform);
452
+ }
450
453
  function buildCapabilities(environment) {
451
454
  const catalog = getPaymentMethodsCatalog(BASE_CHAIN_ID, environment);
452
455
  const platforms = Object.entries(catalog).map(([platform, entry]) => {
@@ -1363,41 +1366,51 @@ function createCashClient(options) {
1363
1366
  return client;
1364
1367
  }
1365
1368
  function validatePayout(input) {
1366
- const { receive } = input;
1367
- const platform = buildCapabilities(environment).platforms.find(
1368
- (capability) => capability.platform === receive.platform
1369
- );
1370
- if (!platform) throw errors.unsupportedPlatform(receive.platform);
1371
- if (receive.currency === void 0 === (receive.currencies === void 0)) {
1372
- throw errors.invalidPayoutCurrencies(
1373
- receive.platform,
1374
- "pass exactly one of currency or currencies"
1375
- );
1369
+ const legs = Array.isArray(input.receive) ? input.receive : [input.receive];
1370
+ if (legs.length === 0) {
1371
+ throw errors.invalidPayoutPlatforms("at least one payout leg is required");
1376
1372
  }
1377
- const currencies = receive.currencies !== void 0 ? [...receive.currencies] : [receive.currency];
1378
- if (currencies.length === 0) {
1379
- throw errors.invalidPayoutCurrencies(receive.platform, "at least one currency is required");
1380
- }
1381
- if (new Set(currencies).size !== currencies.length) {
1382
- throw errors.invalidPayoutCurrencies(receive.platform, "currencies must be unique");
1383
- }
1384
- for (const currency of currencies) {
1385
- if (!isMarketRateSupported(currency)) {
1386
- throw errors.oracleUnsupportedCurrency(currency);
1373
+ const capabilities2 = buildCapabilities(environment);
1374
+ const seenPlatforms = /* @__PURE__ */ new Set();
1375
+ const payouts = legs.map((leg) => {
1376
+ const platform = capabilities2.platforms.find(
1377
+ (capability) => capability.platform === leg.platform
1378
+ );
1379
+ if (!platform) throw errors.unsupportedPlatform(leg.platform);
1380
+ if (seenPlatforms.has(leg.platform)) {
1381
+ throw errors.invalidPayoutPlatforms(
1382
+ `${leg.platform} appears more than once - each platform may carry one leg`
1383
+ );
1387
1384
  }
1388
- if (!platform.currencies.includes(currency)) {
1389
- throw errors.unsupportedPlatformCurrency(receive.platform, currency);
1385
+ seenPlatforms.add(leg.platform);
1386
+ if (leg.currency === void 0 === (leg.currencies === void 0)) {
1387
+ throw errors.invalidPayoutCurrencies(
1388
+ leg.platform,
1389
+ "pass exactly one of currency or currencies"
1390
+ );
1390
1391
  }
1391
- }
1392
- return {
1393
- payouts: [
1394
- {
1395
- processorName: receive.platform,
1396
- ...currencies.length === 1 ? { currency: currencies[0] } : { currencies },
1397
- payeeData: normalizeCashPayee(receive.platform, receive.payee)
1392
+ const currencies = leg.currencies !== void 0 ? [...leg.currencies] : [leg.currency];
1393
+ if (currencies.length === 0) {
1394
+ throw errors.invalidPayoutCurrencies(leg.platform, "at least one currency is required");
1395
+ }
1396
+ if (new Set(currencies).size !== currencies.length) {
1397
+ throw errors.invalidPayoutCurrencies(leg.platform, "currencies must be unique");
1398
+ }
1399
+ for (const currency of currencies) {
1400
+ if (!isMarketRateSupported(currency)) {
1401
+ throw errors.oracleUnsupportedCurrency(currency);
1398
1402
  }
1399
- ]
1400
- };
1403
+ if (!platform.currencies.includes(currency)) {
1404
+ throw errors.unsupportedPlatformCurrency(leg.platform, currency);
1405
+ }
1406
+ }
1407
+ return {
1408
+ processorName: leg.platform,
1409
+ ...currencies.length === 1 ? { currency: currencies[0] } : { currencies },
1410
+ payeeData: normalizeCashPayee(leg.platform, leg.payee)
1411
+ };
1412
+ });
1413
+ return { payouts };
1401
1414
  }
1402
1415
  function validateDepositInput(amount, input, payoutInput = validatePayout(input)) {
1403
1416
  if (amount < MIN_CASHOUT_AMOUNT) {
@@ -1414,12 +1427,7 @@ function createCashClient(options) {
1414
1427
  };
1415
1428
  }
1416
1429
  function isCashPayoutSet(payouts) {
1417
- const first = payouts[0];
1418
- return Boolean(
1419
- first && payouts.every(
1420
- (payout) => payout.platformHash.toLowerCase() === first.platformHash.toLowerCase() && payout.payeeHash.toLowerCase() === first.payeeHash.toLowerCase() && payout.pricing.marketRate && payout.pricing.spreadBps === 0
1421
- )
1422
- );
1430
+ return payouts.length > 0 && payouts.every((payout) => payout.pricing.marketRate && payout.pricing.spreadBps === 0);
1423
1431
  }
1424
1432
  async function buildDepositParams(client, depositInput) {
1425
1433
  try {
@@ -1428,7 +1436,8 @@ function createCashClient(options) {
1428
1436
  if (isCashError(err)) throw err;
1429
1437
  const message = err instanceof Error ? err.message : String(err);
1430
1438
  if (/identityAttestation is required|identity attestation/i.test(message)) {
1431
- const platform = depositInput.payouts[0]?.processorName ?? "this platform";
1439
+ const platforms = depositInput.payouts.map((payout) => payout.processorName);
1440
+ const platform = platforms.find(platformRequiresIdentityAttestation) ?? platforms[0] ?? "this platform";
1432
1441
  throw errors.payeeVerificationRequired(platform, err);
1433
1442
  }
1434
1443
  throw errors.payeeRegistrationFailed(err);
@@ -2437,6 +2446,7 @@ var CASH_ERROR_CODES = defineCashErrorCodes([
2437
2446
  "AMOUNT_BELOW_MINIMUM",
2438
2447
  "INVALID_INTENT_AMOUNT_RANGE",
2439
2448
  "INVALID_PAYOUT_CURRENCIES",
2449
+ "INVALID_PAYOUT_PLATFORMS",
2440
2450
  "INVALID_REFERRAL_CODE",
2441
2451
  "ACTIVE_INTENT_BLOCKS_WITHDRAWAL",
2442
2452
  "NOTHING_TO_WITHDRAW",
package/dist/react.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { CurrencyType } from '@zkp2p/sdk';
2
- import { s as CashClient, K as EstimateInput, i as CashEstimate, H as CashoutOptions, h as CashoutResult, G as CashoutInput, T as TopUpResult, W as WithdrawResult, e as CashOrder } from './createCashClient-D8gw-Hhv.cjs';
2
+ import { s as CashClient, L as EstimateInput, i as CashEstimate, J as CashoutOptions, h as CashoutResult, H as CashoutInput, T as TopUpResult, W as WithdrawResult, e as CashOrder } from './createCashClient-CYSM84-K.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 { s as CashClient, K as EstimateInput, i as CashEstimate, H as CashoutOptions, h as CashoutResult, G as CashoutInput, T as TopUpResult, W as WithdrawResult, e as CashOrder } from './createCashClient-D8gw-Hhv.js';
2
+ import { s as CashClient, L as EstimateInput, i as CashEstimate, J as CashoutOptions, h as CashoutResult, H as CashoutInput, T as TopUpResult, W as WithdrawResult, e as CashOrder } from './createCashClient-CYSM84-K.js';
3
3
  import { WalletClient } from 'viem';
4
4
  import '@relayprotocol/relay-sdk';
5
5
 
package/dist/react.js CHANGED
@@ -1,4 +1,4 @@
1
- import { isCashError, CASH_ORDER_POLL_INTERVAL_MS } from './chunk-QCRY4XPA.js';
1
+ import { isCashError, CASH_ORDER_POLL_INTERVAL_MS } from './chunk-EIEGWWNX.js';
2
2
  import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
3
3
 
4
4
  function useEstimate({
package/dist/tools.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // package.json
4
4
  var package_default = {
5
- version: "0.4.0-rc.2"};
5
+ version: "0.4.0-rc.3"};
6
6
 
7
7
  // src/tools/index.ts
8
8
  var bigintString = {
@@ -24,6 +24,47 @@ var chainId = {
24
24
  minimum: 1,
25
25
  maximum: Number.MAX_SAFE_INTEGER
26
26
  };
27
+ var receiveLeg = {
28
+ type: "object",
29
+ description: "One payout leg: platform + currency choice + payee",
30
+ properties: {
31
+ platform: {
32
+ type: "string",
33
+ description: 'Platform id from cash_capabilities, e.g. "venmo"'
34
+ },
35
+ currency: { type: "string", description: 'Fiat currency code, e.g. "USD"' },
36
+ currencies: {
37
+ type: "array",
38
+ minItems: 1,
39
+ uniqueItems: true,
40
+ items: { type: "string" },
41
+ description: 'Fiat currency choices for one payment method, e.g. ["EUR", "GBP"]'
42
+ },
43
+ payee: {
44
+ description: "Raw payee handle or structured curator payee data",
45
+ oneOf: [
46
+ {
47
+ type: "string",
48
+ description: 'User-entered handle, e.g. "@andrew" for Venmo; Peer Cash normalizes it for the selected platform'
49
+ },
50
+ {
51
+ type: "object",
52
+ properties: {
53
+ offchainId: {
54
+ type: "string",
55
+ description: "Already-normalized handle for the platform"
56
+ }
57
+ },
58
+ required: ["offchainId"],
59
+ additionalProperties: true
60
+ }
61
+ ]
62
+ }
63
+ },
64
+ required: ["platform", "payee"],
65
+ oneOf: [{ required: ["currency"] }, { required: ["currencies"] }],
66
+ additionalProperties: false
67
+ };
27
68
  var builtInCashTools = [
28
69
  {
29
70
  name: "cash_capabilities",
@@ -129,45 +170,16 @@ var builtInCashTools = [
129
170
  properties: {
130
171
  amount: bigintString,
131
172
  receive: {
132
- type: "object",
133
- description: "Where the fiat should arrive",
134
- properties: {
135
- platform: {
136
- type: "string",
137
- description: 'Platform id from cash_capabilities, e.g. "venmo"'
138
- },
139
- currency: { type: "string", description: 'Fiat currency code, e.g. "USD"' },
140
- currencies: {
173
+ description: "Where the fiat should arrive: one payout leg, or an array of legs to offer several platforms (each platform at most once; every leg fills at the live oracle market rate)",
174
+ oneOf: [
175
+ receiveLeg,
176
+ {
141
177
  type: "array",
142
178
  minItems: 1,
143
- uniqueItems: true,
144
- items: { type: "string" },
145
- description: 'Fiat currency choices for one payment method, e.g. ["EUR", "GBP"]'
146
- },
147
- payee: {
148
- description: "Raw payee handle or structured curator payee data",
149
- oneOf: [
150
- {
151
- type: "string",
152
- description: 'User-entered handle, e.g. "@andrew" for Venmo; Peer Cash normalizes it for the selected platform'
153
- },
154
- {
155
- type: "object",
156
- properties: {
157
- offchainId: {
158
- type: "string",
159
- description: "Already-normalized handle for the platform"
160
- }
161
- },
162
- required: ["offchainId"],
163
- additionalProperties: true
164
- }
165
- ]
179
+ items: receiveLeg,
180
+ description: "Multiple payout legs across different platforms"
166
181
  }
167
- },
168
- required: ["platform", "payee"],
169
- oneOf: [{ required: ["currency"] }, { required: ["currencies"] }],
170
- additionalProperties: false
182
+ ]
171
183
  }
172
184
  },
173
185
  required: ["amount", "receive"],
package/dist/tools.d.cts CHANGED
@@ -155,51 +155,105 @@ declare const builtInCashTools: readonly [{
155
155
  readonly description: "Base units as a decimal string. For the default path this is USDC 6 decimals; with source it is source-token base units.";
156
156
  };
157
157
  readonly receive: {
158
- readonly type: "object";
159
- readonly description: "Where the fiat should arrive";
160
- readonly properties: {
161
- readonly platform: {
162
- readonly type: "string";
163
- readonly description: "Platform id from cash_capabilities, e.g. \"venmo\"";
164
- };
165
- readonly currency: {
166
- readonly type: "string";
167
- readonly description: "Fiat currency code, e.g. \"USD\"";
168
- };
169
- readonly currencies: {
170
- readonly type: "array";
171
- readonly minItems: 1;
172
- readonly uniqueItems: true;
173
- readonly items: {
158
+ readonly description: "Where the fiat should arrive: one payout leg, or an array of legs to offer several platforms (each platform at most once; every leg fills at the live oracle market rate)";
159
+ readonly oneOf: readonly [{
160
+ readonly type: "object";
161
+ readonly description: "One payout leg: platform + currency choice + payee";
162
+ readonly properties: {
163
+ readonly platform: {
174
164
  readonly type: "string";
165
+ readonly description: "Platform id from cash_capabilities, e.g. \"venmo\"";
175
166
  };
176
- readonly description: "Fiat currency choices for one payment method, e.g. [\"EUR\", \"GBP\"]";
177
- };
178
- readonly payee: {
179
- readonly description: "Raw payee handle or structured curator payee data";
180
- readonly oneOf: readonly [{
167
+ readonly currency: {
181
168
  readonly type: "string";
182
- readonly description: "User-entered handle, e.g. \"@andrew\" for Venmo; Peer Cash normalizes it for the selected platform";
183
- }, {
184
- readonly type: "object";
185
- readonly properties: {
186
- readonly offchainId: {
169
+ readonly description: "Fiat currency code, e.g. \"USD\"";
170
+ };
171
+ readonly currencies: {
172
+ readonly type: "array";
173
+ readonly minItems: 1;
174
+ readonly uniqueItems: true;
175
+ readonly items: {
176
+ readonly type: "string";
177
+ };
178
+ readonly description: "Fiat currency choices for one payment method, e.g. [\"EUR\", \"GBP\"]";
179
+ };
180
+ readonly payee: {
181
+ readonly description: "Raw payee handle or structured curator payee data";
182
+ readonly oneOf: readonly [{
183
+ readonly type: "string";
184
+ readonly description: "User-entered handle, e.g. \"@andrew\" for Venmo; Peer Cash normalizes it for the selected platform";
185
+ }, {
186
+ readonly type: "object";
187
+ readonly properties: {
188
+ readonly offchainId: {
189
+ readonly type: "string";
190
+ readonly description: "Already-normalized handle for the platform";
191
+ };
192
+ };
193
+ readonly required: readonly ["offchainId"];
194
+ readonly additionalProperties: true;
195
+ }];
196
+ };
197
+ };
198
+ readonly required: readonly ["platform", "payee"];
199
+ readonly oneOf: readonly [{
200
+ readonly required: readonly ["currency"];
201
+ }, {
202
+ readonly required: readonly ["currencies"];
203
+ }];
204
+ readonly additionalProperties: false;
205
+ }, {
206
+ readonly type: "array";
207
+ readonly minItems: 1;
208
+ readonly items: {
209
+ readonly type: "object";
210
+ readonly description: "One payout leg: platform + currency choice + payee";
211
+ readonly properties: {
212
+ readonly platform: {
213
+ readonly type: "string";
214
+ readonly description: "Platform id from cash_capabilities, e.g. \"venmo\"";
215
+ };
216
+ readonly currency: {
217
+ readonly type: "string";
218
+ readonly description: "Fiat currency code, e.g. \"USD\"";
219
+ };
220
+ readonly currencies: {
221
+ readonly type: "array";
222
+ readonly minItems: 1;
223
+ readonly uniqueItems: true;
224
+ readonly items: {
187
225
  readonly type: "string";
188
- readonly description: "Already-normalized handle for the platform";
189
226
  };
227
+ readonly description: "Fiat currency choices for one payment method, e.g. [\"EUR\", \"GBP\"]";
228
+ };
229
+ readonly payee: {
230
+ readonly description: "Raw payee handle or structured curator payee data";
231
+ readonly oneOf: readonly [{
232
+ readonly type: "string";
233
+ readonly description: "User-entered handle, e.g. \"@andrew\" for Venmo; Peer Cash normalizes it for the selected platform";
234
+ }, {
235
+ readonly type: "object";
236
+ readonly properties: {
237
+ readonly offchainId: {
238
+ readonly type: "string";
239
+ readonly description: "Already-normalized handle for the platform";
240
+ };
241
+ };
242
+ readonly required: readonly ["offchainId"];
243
+ readonly additionalProperties: true;
244
+ }];
190
245
  };
191
- readonly required: readonly ["offchainId"];
192
- readonly additionalProperties: true;
246
+ };
247
+ readonly required: readonly ["platform", "payee"];
248
+ readonly oneOf: readonly [{
249
+ readonly required: readonly ["currency"];
250
+ }, {
251
+ readonly required: readonly ["currencies"];
193
252
  }];
253
+ readonly additionalProperties: false;
194
254
  };
195
- };
196
- readonly required: readonly ["platform", "payee"];
197
- readonly oneOf: readonly [{
198
- readonly required: readonly ["currency"];
199
- }, {
200
- readonly required: readonly ["currencies"];
255
+ readonly description: "Multiple payout legs across different platforms";
201
256
  }];
202
- readonly additionalProperties: false;
203
257
  };
204
258
  };
205
259
  readonly required: readonly ["amount", "receive"];
package/dist/tools.d.ts CHANGED
@@ -155,51 +155,105 @@ declare const builtInCashTools: readonly [{
155
155
  readonly description: "Base units as a decimal string. For the default path this is USDC 6 decimals; with source it is source-token base units.";
156
156
  };
157
157
  readonly receive: {
158
- readonly type: "object";
159
- readonly description: "Where the fiat should arrive";
160
- readonly properties: {
161
- readonly platform: {
162
- readonly type: "string";
163
- readonly description: "Platform id from cash_capabilities, e.g. \"venmo\"";
164
- };
165
- readonly currency: {
166
- readonly type: "string";
167
- readonly description: "Fiat currency code, e.g. \"USD\"";
168
- };
169
- readonly currencies: {
170
- readonly type: "array";
171
- readonly minItems: 1;
172
- readonly uniqueItems: true;
173
- readonly items: {
158
+ readonly description: "Where the fiat should arrive: one payout leg, or an array of legs to offer several platforms (each platform at most once; every leg fills at the live oracle market rate)";
159
+ readonly oneOf: readonly [{
160
+ readonly type: "object";
161
+ readonly description: "One payout leg: platform + currency choice + payee";
162
+ readonly properties: {
163
+ readonly platform: {
174
164
  readonly type: "string";
165
+ readonly description: "Platform id from cash_capabilities, e.g. \"venmo\"";
175
166
  };
176
- readonly description: "Fiat currency choices for one payment method, e.g. [\"EUR\", \"GBP\"]";
177
- };
178
- readonly payee: {
179
- readonly description: "Raw payee handle or structured curator payee data";
180
- readonly oneOf: readonly [{
167
+ readonly currency: {
181
168
  readonly type: "string";
182
- readonly description: "User-entered handle, e.g. \"@andrew\" for Venmo; Peer Cash normalizes it for the selected platform";
183
- }, {
184
- readonly type: "object";
185
- readonly properties: {
186
- readonly offchainId: {
169
+ readonly description: "Fiat currency code, e.g. \"USD\"";
170
+ };
171
+ readonly currencies: {
172
+ readonly type: "array";
173
+ readonly minItems: 1;
174
+ readonly uniqueItems: true;
175
+ readonly items: {
176
+ readonly type: "string";
177
+ };
178
+ readonly description: "Fiat currency choices for one payment method, e.g. [\"EUR\", \"GBP\"]";
179
+ };
180
+ readonly payee: {
181
+ readonly description: "Raw payee handle or structured curator payee data";
182
+ readonly oneOf: readonly [{
183
+ readonly type: "string";
184
+ readonly description: "User-entered handle, e.g. \"@andrew\" for Venmo; Peer Cash normalizes it for the selected platform";
185
+ }, {
186
+ readonly type: "object";
187
+ readonly properties: {
188
+ readonly offchainId: {
189
+ readonly type: "string";
190
+ readonly description: "Already-normalized handle for the platform";
191
+ };
192
+ };
193
+ readonly required: readonly ["offchainId"];
194
+ readonly additionalProperties: true;
195
+ }];
196
+ };
197
+ };
198
+ readonly required: readonly ["platform", "payee"];
199
+ readonly oneOf: readonly [{
200
+ readonly required: readonly ["currency"];
201
+ }, {
202
+ readonly required: readonly ["currencies"];
203
+ }];
204
+ readonly additionalProperties: false;
205
+ }, {
206
+ readonly type: "array";
207
+ readonly minItems: 1;
208
+ readonly items: {
209
+ readonly type: "object";
210
+ readonly description: "One payout leg: platform + currency choice + payee";
211
+ readonly properties: {
212
+ readonly platform: {
213
+ readonly type: "string";
214
+ readonly description: "Platform id from cash_capabilities, e.g. \"venmo\"";
215
+ };
216
+ readonly currency: {
217
+ readonly type: "string";
218
+ readonly description: "Fiat currency code, e.g. \"USD\"";
219
+ };
220
+ readonly currencies: {
221
+ readonly type: "array";
222
+ readonly minItems: 1;
223
+ readonly uniqueItems: true;
224
+ readonly items: {
187
225
  readonly type: "string";
188
- readonly description: "Already-normalized handle for the platform";
189
226
  };
227
+ readonly description: "Fiat currency choices for one payment method, e.g. [\"EUR\", \"GBP\"]";
228
+ };
229
+ readonly payee: {
230
+ readonly description: "Raw payee handle or structured curator payee data";
231
+ readonly oneOf: readonly [{
232
+ readonly type: "string";
233
+ readonly description: "User-entered handle, e.g. \"@andrew\" for Venmo; Peer Cash normalizes it for the selected platform";
234
+ }, {
235
+ readonly type: "object";
236
+ readonly properties: {
237
+ readonly offchainId: {
238
+ readonly type: "string";
239
+ readonly description: "Already-normalized handle for the platform";
240
+ };
241
+ };
242
+ readonly required: readonly ["offchainId"];
243
+ readonly additionalProperties: true;
244
+ }];
190
245
  };
191
- readonly required: readonly ["offchainId"];
192
- readonly additionalProperties: true;
246
+ };
247
+ readonly required: readonly ["platform", "payee"];
248
+ readonly oneOf: readonly [{
249
+ readonly required: readonly ["currency"];
250
+ }, {
251
+ readonly required: readonly ["currencies"];
193
252
  }];
253
+ readonly additionalProperties: false;
194
254
  };
195
- };
196
- readonly required: readonly ["platform", "payee"];
197
- readonly oneOf: readonly [{
198
- readonly required: readonly ["currency"];
199
- }, {
200
- readonly required: readonly ["currencies"];
255
+ readonly description: "Multiple payout legs across different platforms";
201
256
  }];
202
- readonly additionalProperties: false;
203
257
  };
204
258
  };
205
259
  readonly required: readonly ["amount", "receive"];
package/dist/tools.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // package.json
2
2
  var package_default = {
3
- version: "0.4.0-rc.2"};
3
+ version: "0.4.0-rc.3"};
4
4
 
5
5
  // src/tools/index.ts
6
6
  var bigintString = {
@@ -22,6 +22,47 @@ var chainId = {
22
22
  minimum: 1,
23
23
  maximum: Number.MAX_SAFE_INTEGER
24
24
  };
25
+ var receiveLeg = {
26
+ type: "object",
27
+ description: "One payout leg: platform + currency choice + payee",
28
+ properties: {
29
+ platform: {
30
+ type: "string",
31
+ description: 'Platform id from cash_capabilities, e.g. "venmo"'
32
+ },
33
+ currency: { type: "string", description: 'Fiat currency code, e.g. "USD"' },
34
+ currencies: {
35
+ type: "array",
36
+ minItems: 1,
37
+ uniqueItems: true,
38
+ items: { type: "string" },
39
+ description: 'Fiat currency choices for one payment method, e.g. ["EUR", "GBP"]'
40
+ },
41
+ payee: {
42
+ description: "Raw payee handle or structured curator payee data",
43
+ oneOf: [
44
+ {
45
+ type: "string",
46
+ description: 'User-entered handle, e.g. "@andrew" for Venmo; Peer Cash normalizes it for the selected platform'
47
+ },
48
+ {
49
+ type: "object",
50
+ properties: {
51
+ offchainId: {
52
+ type: "string",
53
+ description: "Already-normalized handle for the platform"
54
+ }
55
+ },
56
+ required: ["offchainId"],
57
+ additionalProperties: true
58
+ }
59
+ ]
60
+ }
61
+ },
62
+ required: ["platform", "payee"],
63
+ oneOf: [{ required: ["currency"] }, { required: ["currencies"] }],
64
+ additionalProperties: false
65
+ };
25
66
  var builtInCashTools = [
26
67
  {
27
68
  name: "cash_capabilities",
@@ -127,45 +168,16 @@ var builtInCashTools = [
127
168
  properties: {
128
169
  amount: bigintString,
129
170
  receive: {
130
- type: "object",
131
- description: "Where the fiat should arrive",
132
- properties: {
133
- platform: {
134
- type: "string",
135
- description: 'Platform id from cash_capabilities, e.g. "venmo"'
136
- },
137
- currency: { type: "string", description: 'Fiat currency code, e.g. "USD"' },
138
- currencies: {
171
+ description: "Where the fiat should arrive: one payout leg, or an array of legs to offer several platforms (each platform at most once; every leg fills at the live oracle market rate)",
172
+ oneOf: [
173
+ receiveLeg,
174
+ {
139
175
  type: "array",
140
176
  minItems: 1,
141
- uniqueItems: true,
142
- items: { type: "string" },
143
- description: 'Fiat currency choices for one payment method, e.g. ["EUR", "GBP"]'
144
- },
145
- payee: {
146
- description: "Raw payee handle or structured curator payee data",
147
- oneOf: [
148
- {
149
- type: "string",
150
- description: 'User-entered handle, e.g. "@andrew" for Venmo; Peer Cash normalizes it for the selected platform'
151
- },
152
- {
153
- type: "object",
154
- properties: {
155
- offchainId: {
156
- type: "string",
157
- description: "Already-normalized handle for the platform"
158
- }
159
- },
160
- required: ["offchainId"],
161
- additionalProperties: true
162
- }
163
- ]
177
+ items: receiveLeg,
178
+ description: "Multiple payout legs across different platforms"
164
179
  }
165
- },
166
- required: ["platform", "payee"],
167
- oneOf: [{ required: ["currency"] }, { required: ["currencies"] }],
168
- additionalProperties: false
180
+ ]
169
181
  }
170
182
  },
171
183
  required: ["amount", "receive"],
package/llms.txt CHANGED
@@ -55,6 +55,9 @@ Key facts:
55
55
  their on-chain hashes, plain-number rates from 1e18 precision.
56
56
  - Fills are receipts: locked rate + fiat owed at signal; verified fiat paid,
57
57
  payment id, released USDC, and fill latency after the proof.
58
+ - `receive` takes one payout leg or an array of legs across different
59
+ platforms (each platform at most once); every leg fills at the live oracle
60
+ market rate.
58
61
  - Orders carry their payout legs (platform, currency, payee hash) plus a
59
62
  verifiable pricing proof (spreadBps: 0, oracle kind) from indexed data.
60
63
  - Order reads fail closed when any deposit method is absent from the active
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zkp2p/cash",
3
- "version": "0.4.0-rc.2",
3
+ "version": "0.4.0-rc.3",
4
4
  "description": "Peer Cash - offramp-only SDK for routing crypto to Base USDC, then cashing out to fiat at the live oracle market rate.",
5
5
  "license": "MIT",
6
6
  "author": "Peer (https://peer.xyz)",
@@ -61,6 +61,8 @@ const res = await cash.cashout(
61
61
  {
62
62
  // 2 execute
63
63
  amount: usdc(100),
64
+ // or an array of legs to offer several platforms on one order:
65
+ // receive: [{ platform: 'venmo', ... }, { platform: 'revolut', ... }]
64
66
  receive: { platform: 'venmo', currency: 'USD', payee: { offchainId: '@handle' } },
65
67
  },
66
68
  { signer },