@zkp2p/cash 0.4.8 → 0.4.10

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, 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';
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-4LPWKZMW.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-4LPWKZMW.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';
@@ -1773,8 +1773,6 @@ function createCashClient(options) {
1773
1773
  const payoutInput = validatePayout(input);
1774
1774
  const client = await signingClient("cashout", opts);
1775
1775
  const owner = opts.signer.account.address;
1776
- let sourceResult;
1777
- let cashoutAmount = input.amount;
1778
1776
  if (input.source) {
1779
1777
  const sourceSigner = opts.sourceSigner ?? (input.source.chainId === BASE_CHAIN_ID ? opts.signer : void 0);
1780
1778
  if (!sourceSigner?.account) throw errors.signerRequired("source cashout");
@@ -1795,7 +1793,7 @@ function createCashClient(options) {
1795
1793
  if (relayQuote.outputAmount < MIN_CASHOUT_AMOUNT) {
1796
1794
  throw errors.amountBelowMinimum(relayQuote.outputAmount, MIN_CASHOUT_AMOUNT);
1797
1795
  }
1798
- cashoutAmount = relayQuote.outputAmount;
1796
+ const cashoutAmount = relayQuote.outputAmount;
1799
1797
  const depositInput2 = validateDepositInput(cashoutAmount, input, payoutInput);
1800
1798
  const params2 = await buildDepositParams(client, depositInput2);
1801
1799
  const escrow2 = client.escrowV2Address ?? client.escrowAddress;
@@ -1812,7 +1810,6 @@ function createCashClient(options) {
1812
1810
  txHashes: executed.txHashes,
1813
1811
  ...executed.transactions ? { transactions: executed.transactions } : {}
1814
1812
  };
1815
- sourceResult = routedSource;
1816
1813
  try {
1817
1814
  await waitForBaseSignerAfterRelay(
1818
1815
  client,
@@ -1946,8 +1943,7 @@ function createCashClient(options) {
1946
1943
  escrowAddress: resolved.escrowAddress,
1947
1944
  onchainDepositId: resolved.onchainDepositId,
1948
1945
  order,
1949
- ...accessPolicyTxHash ? { accessPolicyTxHash } : {},
1950
- ...sourceResult ? { source: sourceResult } : {}
1946
+ ...accessPolicyTxHash ? { accessPolicyTxHash } : {}
1951
1947
  };
1952
1948
  },
1953
1949
  async prepare(input) {
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-BJmz3v4_.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-Br7uu4lQ.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-BJmz3v4_.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-Br7uu4lQ.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-CSDSJVI7.js';
1
+ import { isCashError, CASH_ORDER_POLL_INTERVAL_MS } from './chunk-4LPWKZMW.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.8"};
5
+ version: "0.4.10"};
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 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.",
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. If any payout leg is Venmo, Cash App, or PayPal, accessPolicyRequired is true: after createDeposit confirms, the host adapter must call CashClient.finalizePreparedCashout(receipt), then prepare and confirm CashClient.prepareAccessPolicy(depositId) with the depositor. These receipt/signing methods are not separate built-in tools. 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 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.";
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. If any payout leg is Venmo, Cash App, or PayPal, accessPolicyRequired is true: after createDeposit confirms, the host adapter must call CashClient.finalizePreparedCashout(receipt), then prepare and confirm CashClient.prepareAccessPolicy(depositId) with the depositor. These receipt/signing methods are not separate built-in tools. 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 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.";
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. If any payout leg is Venmo, Cash App, or PayPal, accessPolicyRequired is true: after createDeposit confirms, the host adapter must call CashClient.finalizePreparedCashout(receipt), then prepare and confirm CashClient.prepareAccessPolicy(depositId) with the depositor. These receipt/signing methods are not separate built-in tools. 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.8"};
3
+ version: "0.4.10"};
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 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.",
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. If any payout leg is Venmo, Cash App, or PayPal, accessPolicyRequired is true: after createDeposit confirms, the host adapter must call CashClient.finalizePreparedCashout(receipt), then prepare and confirm CashClient.prepareAccessPolicy(depositId) with the depositor. These receipt/signing methods are not separate built-in tools. 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: {
@@ -66,15 +66,18 @@ transaction confirms, call `finalizePreparedCashout(receipt)` to decode it with
66
66
  the environment-correct escrow ABI and obtain the resumable `CashoutResult`.
67
67
 
68
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
69
+ policy attachment is sequential, not atomic. If any payout leg uses Venmo,
70
+ Cash App, or PayPal, the cash-out nevertheless restricts intent signaling to
71
+ the Plus, Pro, Peer Makers, and Peer Pay groups by default. Signed `cashout()`
72
+ confirms the deposit before submitting and confirming the policy with the same
73
+ viem wallet, so a brief unprotected interval exists. For `prepare()`,
74
+ `accessPolicyRequired` marks whether the host must call
74
75
  `prepareAccessPolicy(depositId)` after finalizing the confirmed deposit receipt.
75
76
  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
+ If the follow-up fails, the deposit already exists. Never repeat the cash-out.
78
+ When `ACCESS_POLICY_CONFIGURATION_FAILED.recovery.transactionHash` is present,
79
+ inspect it before preparing another policy; resubmit only when that transaction
80
+ is absent or confirmed reverted.
78
81
 
79
82
  There is no static chain/token allowlist in Peer Cash. Relay decides source
80
83
  support through its metadata and quote execution, filtered to the viem/EVM
@@ -278,8 +281,10 @@ whole life. Two things to know for long-lived orders:
278
281
  the payee is re-registered. Format-only platforms (Zelle, Chime, …) are
279
282
  never re-checked.
280
283
  - **Wise and PayPal** require a signed identity attestation for a new payee
281
- registration. A previously registered handle can be reused with bare payee
282
- data. If the handle is new and no attestation is supplied, the SDK surfaces
284
+ registration. The SDK accepts the structured attestation but does not mint
285
+ it; first-party Peer web obtains it through the Peer TEE browser extension.
286
+ A previously registered handle can be reused with bare payee data. If the
287
+ handle is new and no attestation is supplied, the SDK surfaces
283
288
  `PAYEE_VERIFICATION_REQUIRED`; `capabilities()` flags these platforms with
284
289
  `requiresIdentityAttestation: true`.
285
290
 
@@ -300,7 +305,7 @@ explicit override.
300
305
  | `INVALID_INTENT_AMOUNT_RANGE` | no | Min/max is non-positive, inverted, or exceeds the deposit. Correct the range. |
301
306
  | `INVALID_PAYOUT_CURRENCIES` | no | The currency set is empty or contains duplicates. Pass a non-empty unique set from `capabilities()`. |
302
307
  | `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. |
303
- | `PAYEE_VERIFICATION_REQUIRED` | no | A new Wise/PayPal payee needs an attestation. Register it through Peer first; an existing registration can be reused. |
308
+ | `PAYEE_VERIFICATION_REQUIRED` | no | A new Wise/PayPal payee needs an attestation from Peer web and its TEE browser extension; an existing registration can be reused. |
304
309
  | `PAYEE_REGISTRATION_FAILED` | yes | Curator rejected the handle or was unavailable. Check `payeeHint` and retry. |
305
310
  | `ATOMIC_ACCESS_POLICY_REQUIRED` | no | Deprecated compatibility code. Current SDK flows never emit it. |
306
311
  | `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. |
@@ -320,7 +325,7 @@ explicit override.
320
325
  | `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. |
321
326
  | `TRANSACTION_STATUS_UNKNOWN` | no | A transaction was submitted but its receipt is unknown. Inspect `recovery.transactionHash` before resubmitting. |
322
327
  | `DEPOSIT_RESOLUTION_FAILED` | no | Base tx succeeded but no `DepositReceived` was decoded. Inspect its logs and recover the composite id. |
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. |
328
+ | `ACCESS_POLICY_CONFIGURATION_FAILED` | no | The deposit exists but its required policy was not confirmed. Inspect `transactionHash` if present; attach the policy if still needed. |
324
329
  | `INVALID_DEPOSIT_ID` | no | The id is not `escrowAddress_onchainId`. A bare number cannot cold-hydrate; use the value returned by `cashout()`. |
325
330
  | `ORDER_NOT_FOUND` | yes | Unknown id or immediate indexer lag. Verify the id and retry shortly after creation. |
326
331
  | `INDEXER_LAG` | yes | Indexer trails the chain. Retry the read shortly. |
@@ -54,7 +54,9 @@ async function executeTool(name: string, args: Record<string, unknown>): Promise
54
54
  case 'cash_cashout': {
55
55
  // Tool/prepare path: Base USDC only. cash_source_quote is read-only;
56
56
  // the host must execute and confirm Relay with its own signer/runtime,
57
- // then call this tool with the guaranteed Base USDC amount.
57
+ // then call this tool with the guaranteed Base USDC amount. Persist
58
+ // accessPolicyRequired: after createDeposit confirms, the host adapter
59
+ // calls finalizePreparedCashout(receipt), then prepareAccessPolicy().
58
60
  const input = {
59
61
  amount: BigInt(args.amount as string),
60
62
  receive: args.receive as never,
@@ -108,12 +110,16 @@ const caps = (await executeTool('cash_capabilities', {})) as {
108
110
  platform: string;
109
111
  currencies: string[];
110
112
  payeeHint: string;
113
+ requiresIdentityAttestation: boolean;
111
114
  requiresAtomicAccessPolicy: boolean;
112
115
  }[];
113
116
  };
114
117
  const venmo = caps.platforms.find((p) => p.platform === 'venmo');
115
118
  console.log(`agent sees ${caps.platforms.length} platforms; venmo capability:`);
116
- console.log(` hint="${venmo?.payeeHint}" atomic=${venmo?.requiresAtomicAccessPolicy}\n`);
119
+ console.log(
120
+ ` hint="${venmo?.payeeHint}" identityAttestation=${venmo?.requiresIdentityAttestation}`,
121
+ );
122
+ console.log(' sequential access policy is reported by cash_cashout.accessPolicyRequired\n');
117
123
 
118
124
  const est = await executeTool('cash_estimate', {
119
125
  amount: usdc(250).toString(),
@@ -10,8 +10,9 @@
10
10
  *
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
- * identity attestation created by Peer; an existing registered handle can be
14
- * reused. This private-key EOA works directly with every supported platform;
13
+ * identity attestation obtained by Peer web through the Peer TEE browser
14
+ * extension; an existing registered handle can be reused. This private-key EOA
15
+ * works directly with every supported platform;
15
16
  * no Privy wallet is required. Venmo, Cash App, and PayPal attach their access
16
17
  * policy in a confirmed follow-up transaction. Override the demo corridor with:
17
18
  * CASH_PLATFORM=revolut CASH_CURRENCY=EUR CASH_PAYEE=your-revtag
package/llms.txt CHANGED
@@ -40,7 +40,8 @@ Key facts:
40
40
  prepareWithdraw, prepareTopUp) for host-side signing; source-routed cashout
41
41
  needs signer-backed Relay execution first. prepare() and the cash_cashout tool
42
42
  are Base-USDC-only; cash_source_quote/status do not execute the route.
43
- @zkp2p/cash/tools ships a JSON-schema tool manifest.
43
+ @zkp2p/cash/tools ships a JSON-schema tool manifest. Receipt finalization
44
+ and policy preparation remain CashClient methods for the host adapter.
44
45
  - Errors are typed: { code, retryable, remediation, recovery? }. Completed
45
46
  Relay routes retain requestId, flat hashes, and origin/destination
46
47
  transactions. Retry Base-only after SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED;
@@ -67,12 +68,17 @@ Key facts:
67
68
  - Default path is same-chain Base USDC. Optional `source` on `cashout()` runs
68
69
  Relay source-to-Base-USDC first; non-Base source chains require
69
70
  `sourceSigner`.
70
- - Wise and PayPal require attestation for a new payee registration; a
71
- previously registered bare handle can be reused.
71
+ - Wise and PayPal require attestation for a new payee registration. The SDK
72
+ accepts but does not mint it; first-party Peer web obtains it through the
73
+ Peer TEE browser extension. A previously registered bare handle can be reused.
72
74
  - 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.
75
+ groups after the deposit confirms, restricting which takers can signal an
76
+ intent. If any payout leg uses one of these platforms, the follow-up is
77
+ intentionally non-atomic; `cashout()` submits it with the same viem wallet,
78
+ while prepared hosts must act when `accessPolicyRequired` is true. Any EOA
79
+ works; Privy is not required. On ACCESS_POLICY_CONFIGURATION_FAILED, never
80
+ repeat the cashout; inspect recovery.transactionHash before resubmitting a
81
+ policy.
76
82
  - Preproduction uses https://api-preprod.zkp2p.xyz by default; staging uses
77
83
  https://api-staging.zkp2p.xyz. curatorUrl can override either.
78
84
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zkp2p/cash",
3
- "version": "0.4.8",
3
+ "version": "0.4.10",
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)",
@@ -105,9 +105,9 @@
105
105
  "ci": "bun run typecheck && bun run lint && bun run format:check && bun run test && bun run audit && bun run build && bun run pack:check"
106
106
  },
107
107
  "dependencies": {
108
- "@relayprotocol/relay-sdk": "^6.1.3",
109
- "@zkp2p/sdk": "0.12.0",
110
- "zod": "^3.25.76"
108
+ "@relayprotocol/relay-sdk": "^7.0.1",
109
+ "@zkp2p/sdk": "0.12.1",
110
+ "zod": "^4.4.3"
111
111
  },
112
112
  "peerDependencies": {
113
113
  "react": ">=18",
@@ -119,19 +119,19 @@
119
119
  }
120
120
  },
121
121
  "devDependencies": {
122
- "@eslint/js": "^9.39.5",
122
+ "@eslint/js": "^10.0.1",
123
123
  "@types/node": "^22.20.1",
124
- "@types/react": "^19.2.17",
124
+ "@types/react": "^19.2.18",
125
125
  "@types/react-test-renderer": "19.1.0",
126
- "eslint": "^9.39.5",
127
- "eslint-config-prettier": "^9.1.2",
128
- "prettier": "^3.9.5",
129
- "react": "^19.2.7",
130
- "react-test-renderer": "19.2.7",
126
+ "eslint": "^10.8.1",
127
+ "eslint-config-prettier": "^10.1.8",
128
+ "prettier": "^3.9.6",
129
+ "react": "^19.2.8",
130
+ "react-test-renderer": "19.2.8",
131
131
  "tsup": "^8.5.1",
132
132
  "typescript": "^5.9.3",
133
- "typescript-eslint": "^8.63.0",
134
- "viem": "^2.55.1",
133
+ "typescript-eslint": "^8.67.0",
134
+ "viem": "^2.55.15",
135
135
  "vitest": "^4.1.10"
136
136
  }
137
137
  }
@@ -29,6 +29,10 @@ custodial off-ramp provider.
29
29
  - anything in your UI or agent output implying a locked rate is a bug.
30
30
  - **Custody story.** Funds are held by the protocol contract only. An unmatched
31
31
  deposit is withdrawable by the maker at any time. The SDK never holds keys.
32
+ - **Restricted intent signaling.** If any payout leg uses Venmo, Cash App, or
33
+ PayPal, the Plus, Pro, Peer Makers, and Peer Pay groups attach after the
34
+ deposit confirms. Signed `cashout()` handles the sequential follow-up with
35
+ the same viem wallet. Prepared hosts must finish it explicitly; any EOA works.
32
36
  - **Honest ETA.** Use `estimate().eta`: `{ seconds, label }` backed by rolling
33
37
  30-day indexer data from zero-spread (`spreadBps: 0`) market-rate deposits in
34
38
  the same payout corridor, measured from deposit creation to first fill. Do
@@ -67,7 +71,13 @@ const res = await cash.cashout(
67
71
  },
68
72
  { signer },
69
73
  );
70
- const { txs, steps } = await cash.prepare({/* same input */}); // 2b unsigned plan
74
+ const { txs, steps, accessPolicyRequired } = await cash.prepare({/* same input */}); // 2b unsigned plan
75
+ // Submit txs in order. After createDeposit confirms:
76
+ const prepared = cash.finalizePreparedCashout(createDepositReceipt);
77
+ if (accessPolicyRequired) {
78
+ const policyTx = cash.prepareAccessPolicy(prepared.depositId);
79
+ await hostSubmitAndConfirm(policyTx);
80
+ }
71
81
  const order = await cash.order(res.depositId); // 3 observe
72
82
  const mine = await cash.orders(ownerAddress, { inFlight: true }); // 4 list
73
83
  for await (const o of cash.watch(res.depositId)) {
@@ -107,7 +117,10 @@ counterparts. `prepare()` rejects `source`. Source-routed cashout runs Relay
107
117
  first; use signed `cashout({ source }, { signer, sourceSigner })`, or execute
108
118
  and confirm Relay in the host before preparing a Base-USDC cashout.
109
119
  `cash_source_quote` and `cash_source_status` are quote/read tools, not a
110
- host-side execution path.
120
+ host-side execution path. The built-in tool manifest also does not expose
121
+ receipt finalization or access-policy submission as separate tools; the host
122
+ adapter calls those `CashClient` methods after its signer confirms
123
+ `createDeposit`.
111
124
  Every protocol transaction carries ERC-8021 attribution. To receive the
112
125
  deposit-level integration share, copy the six-character code from your Peer
113
126
  mobile or web referral screen and configure it directly:
@@ -127,9 +140,11 @@ that deposit. Use one referral code per deposit. Renaming the displayed code
127
140
  later does not change the owner of an already-attributed open deposit.
128
141
 
129
142
  Wise and PayPal require an identity attestation for a new payee registration.
130
- Do not disable them outright: a previously registered handle can be reused
131
- with bare payee data. Handle `PAYEE_VERIFICATION_REQUIRED` when registration
132
- is still needed.
143
+ The SDK accepts the structured attestation but does not mint it; first-party
144
+ Peer web obtains it through the Peer TEE browser extension. Do not disable these
145
+ platforms outright: a previously registered handle can be reused with bare
146
+ payee data. Handle `PAYEE_VERIFICATION_REQUIRED` when registration is still
147
+ needed.
133
148
 
134
149
  ## 4. Order management - indexer-native
135
150
 
@@ -167,6 +182,10 @@ those, don't re-derive. The recovery boundaries that matter most in practice:
167
182
  - `TRANSACTION_SUBMISSION_UNKNOWN` = a Base mutation returned no hash but may
168
183
  have broadcast. Follow `error.recovery`, inspect Base wallet/protocol state,
169
184
  and do not retry until absence is proven.
185
+ - `ACCESS_POLICY_CONFIGURATION_FAILED` = the deposit exists but its required
186
+ policy was not confirmed. Never cash out again. Inspect
187
+ `error.recovery.transactionHash` when present; prepare another policy only
188
+ if that transaction is absent or confirmed reverted.
170
189
  - `INDEXER_UNAVAILABLE` / `ORACLE_READ_FAILED` = retry the read only. Do not
171
190
  repeat the transaction that produced the id or balance being inspected.
172
191
  - `SIGNER_CHAIN_MISMATCH` = switch to the required chain and obtain a fresh
@@ -183,7 +202,8 @@ Run against `environment: 'staging'` with a small funded wallet.
183
202
 
184
203
  Prove both routes without waiting for a buyer:
185
204
 
186
- 1. Create a real 1–2 USDC Base-USDC deposit; retain `depositId` and Base tx.
205
+ 1. Create a real 1–2 USDC Base-USDC deposit; retain `depositId`, the Base tx,
206
+ and `accessPolicyTxHash` when using Venmo, Cash App, or PayPal.
187
207
  2. Retry through indexer lag until `order(depositId)` is `awaiting-buyer`, and
188
208
  assert `orders(owner)` contains it.
189
209
  3. Withdraw it; assert `returned` and the Base USDC balance is restored minus