@zkp2p/cash 0.4.8 → 0.4.9
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 +22 -9
- package/README.md +113 -81
- package/dist/{chunk-CSDSJVI7.js → chunk-4LPWKZMW.js} +2 -2
- package/dist/{createCashClient-BJmz3v4_.d.cts → createCashClient-Br7uu4lQ.d.cts} +9 -5
- package/dist/{createCashClient-BJmz3v4_.d.ts → createCashClient-Br7uu4lQ.d.ts} +9 -5
- package/dist/index.cjs +4 -8
- package/dist/index.d.cts +276 -3167
- package/dist/index.d.ts +276 -3167
- package/dist/index.js +4 -8
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/tools.cjs +2 -2
- package/dist/tools.d.cts +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +2 -2
- package/docs/lifecycle-and-recovery.md +16 -11
- package/examples/agent-tool-use.ts +8 -2
- package/examples/node-cashout.ts +3 -2
- package/llms.txt +12 -6
- package/package.json +12 -12
- package/skills/peer-cash-integration/SKILL.md +26 -6
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
package/dist/tools.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// package.json
|
|
4
4
|
var package_default = {
|
|
5
|
-
version: "0.4.
|
|
5
|
+
version: "0.4.9"};
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
3
|
+
version: "0.4.9"};
|
|
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.
|
|
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.
|
|
70
|
-
|
|
71
|
-
default. Signed `cashout()`
|
|
72
|
-
|
|
73
|
-
exists. For `prepare()`,
|
|
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.
|
|
77
|
-
`ACCESS_POLICY_CONFIGURATION_FAILED`
|
|
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.
|
|
282
|
-
|
|
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
|
|
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 |
|
|
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(
|
|
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(),
|
package/examples/node-cashout.ts
CHANGED
|
@@ -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
|
|
14
|
-
* reused. This private-key EOA
|
|
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
|
|
71
|
-
|
|
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
|
|
74
|
-
|
|
75
|
-
|
|
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.
|
|
3
|
+
"version": "0.4.9",
|
|
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": "^
|
|
108
|
+
"@relayprotocol/relay-sdk": "^7.0.1",
|
|
109
109
|
"@zkp2p/sdk": "0.12.0",
|
|
110
|
-
"zod": "^
|
|
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": "^
|
|
122
|
+
"@eslint/js": "^10.0.1",
|
|
123
123
|
"@types/node": "^22.20.1",
|
|
124
|
-
"@types/react": "^19.2.
|
|
124
|
+
"@types/react": "^19.2.18",
|
|
125
125
|
"@types/react-test-renderer": "19.1.0",
|
|
126
|
-
"eslint": "^
|
|
127
|
-
"eslint-config-prettier": "^
|
|
128
|
-
"prettier": "^3.9.
|
|
129
|
-
"react": "^19.2.
|
|
130
|
-
"react-test-renderer": "19.2.
|
|
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.
|
|
134
|
-
"viem": "^2.55.
|
|
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
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
|
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
|