@zkp2p/cash 0.4.7 → 0.4.8

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/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, CASH_RESTRICTED_PLATFORMS, errors, isCashError, CASH_ORDER_STATUSES, mapChainError, CashError, CASH_ACCESS_GROUP_IDS } from './chunk-SYE25ICW.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-SYE25ICW.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, CASH_ACCESS_GROUP_IDS, CASH_RESTRICTED_PLATFORMS } from './chunk-CSDSJVI7.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-CSDSJVI7.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';
@@ -461,7 +461,7 @@ function buildCapabilities(environment) {
461
461
  currencies: [...new Set(currencies2)].sort(),
462
462
  payeeHint: PAYEE_HINTS[platform] ?? "Your payment handle for this platform",
463
463
  requiresIdentityAttestation: IDENTITY_ATTESTATION_PLATFORMS.has(platform),
464
- requiresAtomicAccessPolicy: CASH_RESTRICTED_PLATFORMS.has(platform)
464
+ requiresAtomicAccessPolicy: false
465
465
  };
466
466
  }).filter((p) => p.currencies.length > 0).sort((a, b) => a.platform.localeCompare(b.platform));
467
467
  const currencies = [...new Set(platforms.flatMap((p) => p.currencies))].sort();
@@ -1296,6 +1296,11 @@ async function submitAndConfirm(client, verb, send) {
1296
1296
  function isKnownPreBroadcastFailure(mapped) {
1297
1297
  return mapped.code === "TRANSACTION_REJECTED" || mapped.code === "INSUFFICIENT_TOKEN_BALANCE" || mapped.code === "ALLOWANCE_NOT_VISIBLE" || mapped.code === "ESCROW_PAUSED";
1298
1298
  }
1299
+ function requiresCashoutAccessPolicy(depositInput) {
1300
+ return depositInput.payouts.some(
1301
+ (payout) => CASH_RESTRICTED_PLATFORMS.has(payout.processorName.toLowerCase())
1302
+ );
1303
+ }
1299
1304
  function depositOrderOptions(deposit) {
1300
1305
  const remaining = toBigIntOrUndefined(deposit.remainingDeposits);
1301
1306
  const outstanding = toBigIntOrUndefined(deposit.outstandingIntentAmount);
@@ -1427,12 +1432,6 @@ function createCashClient(options) {
1427
1432
  ...range ? { intentAmountRange: range } : {}
1428
1433
  };
1429
1434
  }
1430
- function assertGenericCashoutSupported(payoutInput) {
1431
- const restrictedPlatforms = payoutInput.payouts.map((payout) => payout.processorName.toLowerCase()).filter((platform) => CASH_RESTRICTED_PLATFORMS.has(platform));
1432
- if (restrictedPlatforms.length > 0) {
1433
- throw errors.atomicAccessPolicyRequired(restrictedPlatforms);
1434
- }
1435
- }
1436
1435
  function isCashPayoutSet(payouts) {
1437
1436
  return payouts.length > 0 && payouts.every((payout) => payout.pricing.marketRate && payout.pricing.spreadBps === 0);
1438
1437
  }
@@ -1672,7 +1671,7 @@ function createCashClient(options) {
1672
1671
  if (lastNonceError) throw lastNonceError;
1673
1672
  throw new Error(`Signer provider did not observe Relay nonce ${afterRelay - 1}`);
1674
1673
  }
1675
- function prepareCashoutAccess(depositId, client = readClient) {
1674
+ function prepareCashoutAccess(depositId, client = readClient, source) {
1676
1675
  const { compositeId, escrowAddress, onchainDepositId } = parseDepositId(depositId);
1677
1676
  const groupIds = CASH_ACCESS_GROUP_IDS[environment];
1678
1677
  try {
@@ -1691,9 +1690,50 @@ function createCashClient(options) {
1691
1690
  chainId: prepared.chainId
1692
1691
  };
1693
1692
  } catch (err) {
1694
- throw errors.accessPolicyConfigurationFailed(compositeId, groupIds, err);
1693
+ throw errors.accessPolicyConfigurationFailed(compositeId, groupIds, {
1694
+ cause: err,
1695
+ ...source ? { source } : {}
1696
+ });
1695
1697
  }
1696
1698
  }
1699
+ async function configureCashoutAccess(client, signer, depositInput, depositId, source) {
1700
+ if (!requiresCashoutAccessPolicy(depositInput)) return void 0;
1701
+ const groupIds = CASH_ACCESS_GROUP_IDS[environment];
1702
+ const prepared = prepareCashoutAccess(depositId, client, source);
1703
+ let hash;
1704
+ try {
1705
+ hash = await signer.sendTransaction({
1706
+ account: signer.account,
1707
+ chain: signer.chain,
1708
+ to: prepared.to,
1709
+ data: prepared.data,
1710
+ value: prepared.value
1711
+ });
1712
+ } catch (err) {
1713
+ throw errors.accessPolicyConfigurationFailed(depositId, groupIds, {
1714
+ cause: err,
1715
+ ...source ? { source } : {}
1716
+ });
1717
+ }
1718
+ let receipt;
1719
+ try {
1720
+ receipt = await client.publicClient.waitForTransactionReceipt({ hash });
1721
+ } catch (err) {
1722
+ throw errors.accessPolicyConfigurationFailed(depositId, groupIds, {
1723
+ cause: err,
1724
+ transactionHash: hash,
1725
+ ...source ? { source } : {}
1726
+ });
1727
+ }
1728
+ if (receipt.status === "reverted") {
1729
+ throw errors.accessPolicyConfigurationFailed(depositId, groupIds, {
1730
+ cause: errors.transactionFailed(hash),
1731
+ transactionHash: hash,
1732
+ ...source ? { source } : {}
1733
+ });
1734
+ }
1735
+ return hash;
1736
+ }
1697
1737
  return {
1698
1738
  capabilities,
1699
1739
  async sourceCapabilities() {
@@ -1731,7 +1771,6 @@ function createCashClient(options) {
1731
1771
  },
1732
1772
  async cashout(input, opts) {
1733
1773
  const payoutInput = validatePayout(input);
1734
- assertGenericCashoutSupported(payoutInput);
1735
1774
  const client = await signingClient("cashout", opts);
1736
1775
  const owner = opts.signer.account.address;
1737
1776
  let sourceResult;
@@ -1829,6 +1868,13 @@ function createCashClient(options) {
1829
1868
  const abi2 = client.escrowV2Abi ?? client.escrowAbi;
1830
1869
  const resolved2 = resolveCashDepositId({ logs: receipt2.logs, abi: abi2 });
1831
1870
  if (!resolved2) throw errors.depositResolutionFailed(hash2);
1871
+ const accessPolicyTxHash2 = await configureCashoutAccess(
1872
+ client,
1873
+ opts.signer,
1874
+ depositInput2,
1875
+ resolved2.compositeId,
1876
+ routedSource
1877
+ );
1832
1878
  const order2 = deriveCashOrder(resolved2.compositeId, [], {
1833
1879
  remainingAmount: depositInput2.amount,
1834
1880
  status: "ACTIVE"
@@ -1839,6 +1885,7 @@ function createCashClient(options) {
1839
1885
  escrowAddress: resolved2.escrowAddress,
1840
1886
  onchainDepositId: resolved2.onchainDepositId,
1841
1887
  order: order2,
1888
+ ...accessPolicyTxHash2 ? { accessPolicyTxHash: accessPolicyTxHash2 } : {},
1842
1889
  source: routedSource
1843
1890
  };
1844
1891
  }
@@ -1883,6 +1930,12 @@ function createCashClient(options) {
1883
1930
  const abi = client.escrowV2Abi ?? client.escrowAbi;
1884
1931
  const resolved = resolveCashDepositId({ logs: receipt.logs, abi });
1885
1932
  if (!resolved) throw errors.depositResolutionFailed(hash);
1933
+ const accessPolicyTxHash = await configureCashoutAccess(
1934
+ client,
1935
+ opts.signer,
1936
+ depositInput,
1937
+ resolved.compositeId
1938
+ );
1886
1939
  const order = deriveCashOrder(resolved.compositeId, [], {
1887
1940
  remainingAmount: depositInput.amount,
1888
1941
  status: "ACTIVE"
@@ -1893,13 +1946,13 @@ function createCashClient(options) {
1893
1946
  escrowAddress: resolved.escrowAddress,
1894
1947
  onchainDepositId: resolved.onchainDepositId,
1895
1948
  order,
1949
+ ...accessPolicyTxHash ? { accessPolicyTxHash } : {},
1896
1950
  ...sourceResult ? { source: sourceResult } : {}
1897
1951
  };
1898
1952
  },
1899
1953
  async prepare(input) {
1900
1954
  if (input.source) throw errors.sourceRouteUnsupportedInPrepare();
1901
1955
  const depositInput = validateDepositInput(input.amount, input);
1902
- assertGenericCashoutSupported(depositInput);
1903
1956
  const params = await buildDepositParams(readClient, depositInput);
1904
1957
  const { prepared } = await readClient.prepareCreateDeposit({
1905
1958
  ...params,
@@ -1932,7 +1985,7 @@ function createCashClient(options) {
1932
1985
  }
1933
1986
  ],
1934
1987
  register: { hashedOnchainIds },
1935
- accessPolicyRequired: false
1988
+ accessPolicyRequired: requiresCashoutAccessPolicy(depositInput)
1936
1989
  };
1937
1990
  },
1938
1991
  finalizePreparedCashout(receipt) {
@@ -2559,7 +2612,8 @@ var cashErrorRecoveryJsonSchema = z.discriminatedUnion("kind", [
2559
2612
  kind: z.literal("configure-cashout-access-policy"),
2560
2613
  depositId: z.string(),
2561
2614
  groupIds: z.array(z.string()),
2562
- transactionHash: z.string().optional()
2615
+ transactionHash: z.string().optional(),
2616
+ source: z.object(cashSourceRecoveryJsonShape).strict().optional()
2563
2617
  }).strict()
2564
2618
  ]);
2565
2619
  var cashErrorJsonSchema = z.object({
@@ -2887,6 +2941,10 @@ function topUpResultFromJson(json) {
2887
2941
  function capabilitiesToJson(caps) {
2888
2942
  return {
2889
2943
  ...caps,
2944
+ platforms: caps.platforms.map((platform) => ({
2945
+ ...platform,
2946
+ requiresAtomicAccessPolicy: false
2947
+ })),
2890
2948
  amount: {
2891
2949
  min: caps.amount.min.toString(),
2892
2950
  recommendedMin: caps.amount.recommendedMin.toString(),
@@ -2905,7 +2963,7 @@ function capabilitiesFromJson(json) {
2905
2963
  platforms: parsed.platforms.map((p) => ({
2906
2964
  ...p,
2907
2965
  currencies: p.currencies,
2908
- requiresAtomicAccessPolicy: p.requiresAtomicAccessPolicy ?? CASH_RESTRICTED_PLATFORMS.has(p.platform)
2966
+ requiresAtomicAccessPolicy: false
2909
2967
  })),
2910
2968
  currencies: parsed.currencies,
2911
2969
  amount: {
@@ -2939,7 +2997,15 @@ function cashErrorFromJson(json) {
2939
2997
  kind: parsed.recovery.kind,
2940
2998
  depositId: parsed.recovery.depositId,
2941
2999
  groupIds: parsed.recovery.groupIds,
2942
- ...parsed.recovery.transactionHash !== void 0 ? { transactionHash: parsed.recovery.transactionHash } : {}
3000
+ ...parsed.recovery.transactionHash !== void 0 ? { transactionHash: parsed.recovery.transactionHash } : {},
3001
+ ...parsed.recovery.source !== void 0 ? {
3002
+ source: {
3003
+ amount: parsed.recovery.source.amount,
3004
+ txHashes: parsed.recovery.source.txHashes,
3005
+ ...parsed.recovery.source.requestId !== void 0 ? { requestId: parsed.recovery.source.requestId } : {},
3006
+ ...parsed.recovery.source.transactions !== void 0 ? { transactions: parsed.recovery.source.transactions } : {}
3007
+ }
3008
+ } : {}
2943
3009
  };
2944
3010
  } else if (parsed.recovery.kind === "inspect-base-operation-submission") {
2945
3011
  recovery = {
package/dist/react.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { CurrencyType } from '@zkp2p/sdk';
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-CL1SCbqF.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-BJmz3v4_.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, 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-CL1SCbqF.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-BJmz3v4_.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-SYE25ICW.js';
1
+ import { isCashError, CASH_ORDER_POLL_INTERVAL_MS } from './chunk-CSDSJVI7.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.7"};
5
+ version: "0.4.8"};
6
6
 
7
7
  // src/tools/index.ts
8
8
  var bigintString = {
@@ -164,7 +164,7 @@ var builtInCashTools = [
164
164
  },
165
165
  {
166
166
  name: "cash_cashout",
167
- description: "Start an unrestricted-rail Base-USDC cash-out using the custody-separated prepare path. Returns UNSIGNED transactions plus same-index steps [approve, createDeposit]; signing and ordered submission stay host-side. Platforms marked requiresAtomicAccessPolicy fail closed because this tool cannot safely prepare them. For another source asset, complete cash_source_quote and cash_source_status first, then pass the guaranteed Base USDC output amount here.",
167
+ description: "Start a Base-USDC cash-out using the custody-separated prepare path. Returns UNSIGNED transactions plus same-index steps [approve, createDeposit]; signing and ordered submission stay host-side. For Venmo, Cash App, or PayPal, accessPolicyRequired is true: confirm createDeposit, finalize its receipt, then prepare and submit the access policy with the depositor. For another source asset, complete cash_source_quote and cash_source_status first, then pass the guaranteed Base USDC output amount here.",
168
168
  inputSchema: {
169
169
  type: "object",
170
170
  properties: {
package/dist/tools.d.cts CHANGED
@@ -145,7 +145,7 @@ declare const builtInCashTools: readonly [{
145
145
  };
146
146
  }, {
147
147
  readonly name: "cash_cashout";
148
- readonly description: "Start an unrestricted-rail Base-USDC cash-out using the custody-separated prepare path. Returns UNSIGNED transactions plus same-index steps [approve, createDeposit]; signing and ordered submission stay host-side. Platforms marked requiresAtomicAccessPolicy fail closed because this tool cannot safely prepare them. For another source asset, complete cash_source_quote and cash_source_status first, then pass the guaranteed Base USDC output amount here.";
148
+ readonly description: "Start a Base-USDC cash-out using the custody-separated prepare path. Returns UNSIGNED transactions plus same-index steps [approve, createDeposit]; signing and ordered submission stay host-side. For Venmo, Cash App, or PayPal, accessPolicyRequired is true: confirm createDeposit, finalize its receipt, then prepare and submit the access policy with the depositor. For another source asset, complete cash_source_quote and cash_source_status first, then pass the guaranteed Base USDC output amount here.";
149
149
  readonly inputSchema: {
150
150
  readonly type: "object";
151
151
  readonly properties: {
package/dist/tools.d.ts CHANGED
@@ -145,7 +145,7 @@ declare const builtInCashTools: readonly [{
145
145
  };
146
146
  }, {
147
147
  readonly name: "cash_cashout";
148
- readonly description: "Start an unrestricted-rail Base-USDC cash-out using the custody-separated prepare path. Returns UNSIGNED transactions plus same-index steps [approve, createDeposit]; signing and ordered submission stay host-side. Platforms marked requiresAtomicAccessPolicy fail closed because this tool cannot safely prepare them. For another source asset, complete cash_source_quote and cash_source_status first, then pass the guaranteed Base USDC output amount here.";
148
+ readonly description: "Start a Base-USDC cash-out using the custody-separated prepare path. Returns UNSIGNED transactions plus same-index steps [approve, createDeposit]; signing and ordered submission stay host-side. For Venmo, Cash App, or PayPal, accessPolicyRequired is true: confirm createDeposit, finalize its receipt, then prepare and submit the access policy with the depositor. For another source asset, complete cash_source_quote and cash_source_status first, then pass the guaranteed Base USDC output amount here.";
149
149
  readonly inputSchema: {
150
150
  readonly type: "object";
151
151
  readonly properties: {
package/dist/tools.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // package.json
2
2
  var package_default = {
3
- version: "0.4.7"};
3
+ version: "0.4.8"};
4
4
 
5
5
  // src/tools/index.ts
6
6
  var bigintString = {
@@ -162,7 +162,7 @@ var builtInCashTools = [
162
162
  },
163
163
  {
164
164
  name: "cash_cashout",
165
- description: "Start an unrestricted-rail Base-USDC cash-out using the custody-separated prepare path. Returns UNSIGNED transactions plus same-index steps [approve, createDeposit]; signing and ordered submission stay host-side. Platforms marked requiresAtomicAccessPolicy fail closed because this tool cannot safely prepare them. For another source asset, complete cash_source_quote and cash_source_status first, then pass the guaranteed Base USDC output amount here.",
165
+ description: "Start a Base-USDC cash-out using the custody-separated prepare path. Returns UNSIGNED transactions plus same-index steps [approve, createDeposit]; signing and ordered submission stay host-side. For Venmo, Cash App, or PayPal, accessPolicyRequired is true: confirm createDeposit, finalize its receipt, then prepare and submit the access policy with the depositor. For another source asset, complete cash_source_quote and cash_source_status first, then pass the guaranteed Base USDC output amount here.",
166
166
  inputSchema: {
167
167
  type: "object",
168
168
  properties: {
@@ -65,15 +65,16 @@ but the host or a signer-backed client must execute the route before
65
65
  transaction confirms, call `finalizePreparedCashout(receipt)` to decode it with
66
66
  the environment-correct escrow ABI and obtain the resumable `CashoutResult`.
67
67
 
68
- Venmo, Cash App, and PayPal require atomic deposit creation and access-policy
69
- configuration. The generic `cashout()` and `prepare()` paths reject these rails
70
- with `ATOMIC_ACCESS_POLICY_REQUIRED` before wallet access, Relay work, payee
71
- registration, allowance, or deposit submission. Peer web performs the required
72
- guard-before, create, guard-after, and policy configuration in one Curator-backed
73
- batch. A host must provide the same atomic guarantee to support these rails.
74
- Discovery marks them with `requiresAtomicAccessPolicy: true`.
75
- `prepareAccessPolicy(depositId)` is retained only to recover a restricted
76
- deposit already created by `0.4.4`; it is not a safe new-order sequence.
68
+ The deprecated `requiresAtomicAccessPolicy` capability is always `false`:
69
+ policy attachment is sequential, not atomic. Venmo, Cash App, and PayPal
70
+ cash-outs nevertheless attach Plus, Pro, Peer Makers, and Peer Pay groups by
71
+ default. Signed `cashout()` confirms the deposit before submitting and
72
+ confirming the policy with the same viem wallet, so a brief unprotected interval
73
+ exists. For `prepare()`, `accessPolicyRequired` marks whether the host must call
74
+ `prepareAccessPolicy(depositId)` after finalizing the confirmed deposit receipt.
75
+ Any viem `WalletClient`, including an EOA, can submit it; Privy is not required.
76
+ If the follow-up fails, the deposit already exists. Recover from
77
+ `ACCESS_POLICY_CONFIGURATION_FAILED` and never repeat the cash-out.
77
78
 
78
79
  There is no static chain/token allowlist in Peer Cash. Relay decides source
79
80
  support through its metadata and quote execution, filtered to the viem/EVM
@@ -301,7 +302,7 @@ explicit override.
301
302
  | `INVALID_PAYOUT_PLATFORMS` | no | The payout leg set is empty or repeats a platform. Pass one leg, or an array of legs using each platform at most once. |
302
303
  | `PAYEE_VERIFICATION_REQUIRED` | no | A new Wise/PayPal payee needs an attestation. Register it through Peer first; an existing registration can be reused. |
303
304
  | `PAYEE_REGISTRATION_FAILED` | yes | Curator rejected the handle or was unavailable. Check `payeeHint` and retry. |
304
- | `ATOMIC_ACCESS_POLICY_REQUIRED` | no | Venmo, Cash App, or PayPal needs atomic creation and group policy setup. Use Peer web or an equivalent atomic host; nothing was submitted. |
305
+ | `ATOMIC_ACCESS_POLICY_REQUIRED` | no | Deprecated compatibility code. Current SDK flows never emit it. |
305
306
  | `SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE` | no | `prepare()` accepts Base USDC only. Use signed source execution, or complete Relay first and then prepare the Base cashout. |
306
307
  | `SOURCE_RECIPIENT_MISMATCH` | no | Relay output recipient differs from the cashout depositor. Use the depositor address. |
307
308
  | `SOURCE_CAPABILITIES_FAILED` | yes | Relay source discovery failed. Retry or use Base USDC. |
@@ -319,7 +320,7 @@ explicit override.
319
320
  | `TRANSACTION_SUBMISSION_UNKNOWN` | no | A Base mutation returned no hash but may have broadcast. Inspect wallet/protocol state and its recovery action before any retry. |
320
321
  | `TRANSACTION_STATUS_UNKNOWN` | no | A transaction was submitted but its receipt is unknown. Inspect `recovery.transactionHash` before resubmitting. |
321
322
  | `DEPOSIT_RESOLUTION_FAILED` | no | Base tx succeeded but no `DepositReceived` was decoded. Inspect its logs and recover the composite id. |
322
- | `ACCESS_POLICY_CONFIGURATION_FAILED` | no | A `0.4.4` cash-out exists without confirmed group policy. Configure that existing deposit from recovery data; never create it again. |
323
+ | `ACCESS_POLICY_CONFIGURATION_FAILED` | no | Optional policy preparation failed. The cash-out remains valid; retry the opt-in with the same depositor if desired. |
323
324
  | `INVALID_DEPOSIT_ID` | no | The id is not `escrowAddress_onchainId`. A bare number cannot cold-hydrate; use the value returned by `cashout()`. |
324
325
  | `ORDER_NOT_FOUND` | yes | Unknown id or immediate indexer lag. Verify the id and retry shortly after creation. |
325
326
  | `INDEXER_LAG` | yes | Indexer trails the chain. Retry the read shortly. |
@@ -11,9 +11,9 @@
11
11
  * The curator validates supported handles against the live platform, so the
12
12
  * payee must be a real account. A new Wise/PayPal registration also needs the
13
13
  * identity attestation created by Peer; an existing registered handle can be
14
- * reused. Venmo, Cash App, and PayPal require Peer web or another host that
15
- * creates the deposit and access policy atomically, so this generic demo uses
16
- * Chime by default. Override the demo corridor with:
14
+ * reused. This private-key EOA works directly with every supported platform;
15
+ * no Privy wallet is required. Venmo, Cash App, and PayPal attach their access
16
+ * policy in a confirmed follow-up transaction. Override the demo corridor with:
17
17
  * CASH_PLATFORM=revolut CASH_CURRENCY=EUR CASH_PAYEE=your-revtag
18
18
  */
19
19
  import { createWalletClient, http } from 'viem';
@@ -28,9 +28,9 @@ const signer = createWalletClient({ account, chain: base, transport: http() });
28
28
  // One leg here; `receive` also accepts an array of legs to offer several
29
29
  // platforms on one order (each platform at most once, all at the oracle rate).
30
30
  const receive = {
31
- platform: process.env.CASH_PLATFORM ?? 'chime',
31
+ platform: process.env.CASH_PLATFORM ?? 'venmo',
32
32
  currency: (process.env.CASH_CURRENCY ?? 'USD') as CurrencyType,
33
- payee: { offchainId: process.env.CASH_PAYEE ?? '$your-chime-sign' },
33
+ payee: { offchainId: process.env.CASH_PAYEE ?? '@your-venmo' },
34
34
  };
35
35
 
36
36
  const cash = createCashClient({ environment: 'staging' });
@@ -51,6 +51,7 @@ console.log(
51
51
  // 2 - Cash out.
52
52
  const result = await cash.cashout({ amount: usdc(1), receive }, { signer });
53
53
  console.log(`deposit created: ${result.depositId} (tx ${result.txHash})`);
54
+ if (result.accessPolicyTxHash) console.log(`access policy attached: ${result.accessPolicyTxHash}`);
54
55
  // Persist this in YOUR system: userId → result.depositId
55
56
 
56
57
  // 3/5 - Track it. A real service would watch until terminal; the demo bails
package/llms.txt CHANGED
@@ -69,6 +69,10 @@ Key facts:
69
69
  `sourceSigner`.
70
70
  - Wise and PayPal require attestation for a new payee registration; a
71
71
  previously registered bare handle can be reused.
72
+ - Venmo, Cash App, and PayPal attach Plus, Pro, Peer Makers, and Peer Pay
73
+ groups after the deposit confirms. The follow-up is intentionally non-atomic;
74
+ `cashout()` submits it with the same viem wallet, while prepared hosts must
75
+ act when `accessPolicyRequired` is true. Any EOA works; Privy is not required.
72
76
  - Preproduction uses https://api-preprod.zkp2p.xyz by default; staging uses
73
77
  https://api-staging.zkp2p.xyz. curatorUrl can override either.
74
78
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zkp2p/cash",
3
- "version": "0.4.7",
3
+ "version": "0.4.8",
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)",