@zkp2p/cash 0.1.1 → 0.1.2
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 +39 -30
- package/README.md +57 -26
- package/dist/{chunk-4DRZRWWS.js → chunk-FKVPZVFH.js} +14 -2
- package/dist/chunk-FKVPZVFH.js.map +1 -0
- package/dist/{createCashClient-DpAx9A1A.d.cts → createCashClient-iHuGgjH_.d.cts} +169 -6
- package/dist/{createCashClient-DpAx9A1A.d.ts → createCashClient-iHuGgjH_.d.ts} +169 -6
- package/dist/index.cjs +600 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +801 -55
- package/dist/index.d.ts +801 -55
- package/dist/index.js +592 -30
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +23 -5
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +11 -3
- package/dist/react.d.ts +11 -3
- package/dist/react.js +24 -6
- package/dist/react.js.map +1 -1
- package/dist/tools.cjs +103 -7
- package/dist/tools.cjs.map +1 -1
- package/dist/tools.d.cts +2 -2
- package/dist/tools.d.ts +2 -2
- package/dist/tools.js +103 -7
- package/dist/tools.js.map +1 -1
- package/llms.txt +22 -17
- package/package.json +5 -4
- package/skills/peer-cash-integration/SKILL.md +18 -8
- package/dist/chunk-4DRZRWWS.js.map +0 -1
|
@@ -5,9 +5,10 @@ description: Integrate Peer Cash (@zkp2p/cash) into any codebase - React app, No
|
|
|
5
5
|
|
|
6
6
|
# Peer Cash integration
|
|
7
7
|
|
|
8
|
-
Onboard this codebase to `@zkp2p/cash`: an offramp-only SDK that
|
|
9
|
-
|
|
10
|
-
with protocol-held funds and no
|
|
8
|
+
Onboard this codebase to `@zkp2p/cash`: an offramp-only SDK that routes any
|
|
9
|
+
Relay-supported EVM source asset into Base USDC, then cashes out Base USDC to fiat
|
|
10
|
+
at the live Chainlink market rate (0% spread), with protocol-held funds and no
|
|
11
|
+
custodial off-ramp provider.
|
|
11
12
|
|
|
12
13
|
## 1. Mental model (read before writing code)
|
|
13
14
|
|
|
@@ -15,14 +16,20 @@ with protocol-held funds and no custodial off-ramp provider.
|
|
|
15
16
|
a protocol-held deposit. A buyer (taker) pays them fiat and proves it
|
|
16
17
|
with TEE-TLS; the protocol releases the USDC. The protocol runs in its normal
|
|
17
18
|
direction - Peer Cash is a lens on it, not a fork of it.
|
|
19
|
+
- **Source routing.** Destination is always canonical Base USDC. Same-chain
|
|
20
|
+
Base USDC remains the default/minimal path. Other source chains/tokens come
|
|
21
|
+
from `@relayprotocol/relay-sdk` metadata and quote execution, filtered to
|
|
22
|
+
EVM chains this viem SDK can sign. Non-Base source chains require
|
|
23
|
+
`sourceSigner`.
|
|
18
24
|
- **Oracle-at-fill pricing. There is no quote.** The deposit carries
|
|
19
25
|
`oracleRateConfig { spreadBps: 0 }`; the binding rate is whatever the
|
|
20
26
|
Chainlink feed says when a buyer fills. `estimate()` is deliberately named
|
|
21
27
|
- anything in your UI or agent output implying a locked rate is a bug.
|
|
22
28
|
- **Custody story.** Funds are held by the protocol contract only. An unmatched
|
|
23
29
|
deposit is withdrawable by the maker at any time. The SDK never holds keys.
|
|
24
|
-
- **Honest ETA.**
|
|
25
|
-
|
|
30
|
+
- **Honest ETA.** Use `estimate().eta`: `{ seconds, label }` backed by rolling
|
|
31
|
+
7-day indexer data from deposit creation to first fill. Do not use
|
|
32
|
+
signal-to-fulfillment latency and never render it as a guarantee.
|
|
26
33
|
|
|
27
34
|
## 2. Decision tree - entry point by runtime
|
|
28
35
|
|
|
@@ -44,7 +51,8 @@ import { createCashClient, usdc } from '@zkp2p/cash';
|
|
|
44
51
|
const cash = createCashClient({ environment: 'staging' });
|
|
45
52
|
|
|
46
53
|
const caps = cash.capabilities(); // 0 discover (sync)
|
|
47
|
-
const
|
|
54
|
+
const relayCaps = await cash.capabilities({ includeRelaySources: true }); // 0b source discovery
|
|
55
|
+
const est = await cash.estimate({ amount: usdc(100), currency: 'USD' }); // 1 estimate + ETA
|
|
48
56
|
const res = await cash.cashout(
|
|
49
57
|
{
|
|
50
58
|
// 2 execute
|
|
@@ -64,8 +72,10 @@ await cash.withdraw(res.depositId, { signer }); // 6 unwind (amount: for partial
|
|
|
64
72
|
await cash.topUp(res.depositId, usdc(50), { signer }); // 7 top up a live order
|
|
65
73
|
```
|
|
66
74
|
|
|
67
|
-
|
|
68
|
-
|
|
75
|
+
Base-USDC cashout, withdraw, and top-up also have unsigned `prepare*`
|
|
76
|
+
counterparts. Source-routed cashout runs Relay first; use signed
|
|
77
|
+
`cashout({ source }, { signer, sourceSigner })` for non-Base sources, or bridge first and then use `prepare()`.
|
|
78
|
+
Every protocol transaction carries ERC-8021 attribution (`peer-cash` + your
|
|
69
79
|
`createCashClient({ referrer })` codes).
|
|
70
80
|
|
|
71
81
|
## 4. Order management - indexer-native
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/engine/constants.ts","../src/client/errors.ts"],"names":[],"mappings":"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","file":"chunk-4DRZRWWS.js","sourcesContent":["/**\n * Peer Cash - engine constants.\n *\n * Peer Cash is an async crypto→fiat offramp built on the maker/deposit side of\n * the protocol: the cashing-out user IS the maker. They create a deposit at the\n * live oracle/market rate (0% spread); a buyer (a standard taker) signals an\n * intent, pays fiat, and proves it via the standard TEE-TLS flow, releasing the\n * user's crypto. The protocol is reused in its existing direction - no proof\n * inversion, no sell-side quote.\n */\nimport type { IntentStatus } from '../sdk-types';\n\n/** Base chain id - Peer Cash settles in Base USDC. */\nexport const BASE_CHAIN_ID = 8453;\n\n/** Canonical USDC on Base (6 decimals). The deposit asset for every cash-out. */\nexport const BASE_USDC_ADDRESS = '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913' as const;\n\n/** USDC has 6 decimals. */\nexport const USDC_DECIMALS = 6;\n\n/**\n * Market rate = the live Chainlink oracle with **zero spread**. The user sets no\n * rate; selling at market is the fast-fill incentive (the deposit is the best\n * deal on the book, so buyers have reason to take it quickly).\n */\nexport const MARKET_SPREAD_BPS = 0;\n\n/**\n * EscrowV2 rejects a zero `minConversionRate` even when an oracle-backed rate\n * config is attached. Use the smallest non-zero sentinel so the oracle rate\n * still fully determines pricing while satisfying the on-chain invariant.\n */\nexport const ORACLE_MIN_CONVERSION_RATE_SENTINEL = 1n;\n\n/**\n * The full intent-status set a cash-out order can pass through. The indexer's\n * `getIntentsForDeposits` defaults to `['SIGNALED']` only - passing this\n * explicit set is REQUIRED, otherwise `delivered`/`returned` states are\n * silently filtered out.\n */\nexport const CASH_ORDER_STATUSES: IntentStatus[] = [\n 'SIGNALED',\n 'FULFILLED',\n 'PRUNED',\n 'MANUALLY_RELEASED',\n];\n\n/** Default polling cadence for an in-flight order (ms). Matches the protocol's active-intent polling. */\nexport const CASH_ORDER_POLL_INTERVAL_MS = 5_000;\n\n/**\n * Default deposit config for every Peer Cash deposit: a one-shot cash-out\n * cleans up when fully filled rather than lingering empty.\n */\nexport const CASH_RETAIN_ON_EMPTY = false;\n","/**\n * Typed errors - every failure carries a `code`, whether it is `retryable`,\n * and a `remediation` sentence so agents can self-drive recovery.\n */\nexport type CashErrorCode =\n | 'ORACLE_UNSUPPORTED_CURRENCY'\n | 'UNSUPPORTED_PLATFORM'\n | 'AMOUNT_BELOW_MINIMUM'\n | 'ACTIVE_INTENT_BLOCKS_WITHDRAWAL'\n | 'NOTHING_TO_WITHDRAW'\n | 'INSUFFICIENT_AVAILABLE_FUNDS'\n | 'ORDER_NOT_ACTIVE'\n | 'ESCROW_PAUSED'\n | 'INDEXER_LAG'\n | 'ORDER_NOT_FOUND'\n | 'PAYEE_REGISTRATION_FAILED'\n | 'PAYEE_VERIFICATION_REQUIRED'\n | 'DEPOSIT_RESOLUTION_FAILED'\n | 'ALLOWANCE_NOT_VISIBLE'\n | 'SIGNER_REQUIRED'\n | 'WATCH_TIMEOUT'\n | 'TRANSACTION_FAILED';\n\nexport interface CashErrorShape {\n code: CashErrorCode;\n message: string;\n retryable: boolean;\n remediation: string;\n}\n\nexport class CashError extends Error implements CashErrorShape {\n readonly code: CashErrorCode;\n readonly retryable: boolean;\n readonly remediation: string;\n\n constructor(shape: CashErrorShape, options?: { cause?: unknown }) {\n super(shape.message, options);\n this.name = 'CashError';\n this.code = shape.code;\n this.retryable = shape.retryable;\n this.remediation = shape.remediation;\n }\n\n /** Serializable view (for tool results and logs). */\n toJSON(): CashErrorShape {\n return {\n code: this.code,\n message: this.message,\n retryable: this.retryable,\n remediation: this.remediation,\n };\n }\n}\n\nexport function isCashError(value: unknown): value is CashError {\n return value instanceof CashError;\n}\n\n/** Factory helpers keep call sites one-liners and remediation copy consistent. */\nexport const errors = {\n oracleUnsupportedCurrency: (currency: string) =>\n new CashError({\n code: 'ORACLE_UNSUPPORTED_CURRENCY',\n message: `${currency} has no live Chainlink oracle feed; Peer Cash is market-rate only.`,\n retryable: false,\n remediation: `Pick a currency listed in capabilities() - each one is priced by a live oracle feed.`,\n }),\n unsupportedPlatform: (platform: string) =>\n new CashError({\n code: 'UNSUPPORTED_PLATFORM',\n message: `'${platform}' is not a supported payout platform in this environment.`,\n retryable: false,\n remediation: `Pick a platform listed in capabilities().`,\n }),\n amountBelowMinimum: (amount: bigint, min: bigint) =>\n new CashError({\n code: 'AMOUNT_BELOW_MINIMUM',\n message: `Amount ${amount} is below the minimum cash-out of ${min} USDC base units.`,\n retryable: false,\n remediation: `Increase the amount to at least ${min} base units (${Number(min) / 1e6} USDC).`,\n }),\n activeIntentBlocksWithdrawal: (depositId: string) =>\n new CashError({\n code: 'ACTIVE_INTENT_BLOCKS_WITHDRAWAL',\n message: `Order ${depositId} has a live buyer intent; escrow blocks withdrawal while a buyer may still deliver.`,\n retryable: true,\n remediation: `Wait for the buyer to complete or for their intent to expire, then call withdraw() again - it prunes expired intents automatically.`,\n }),\n insufficientAvailableFunds: (depositId: string, requested: bigint, available: bigint) =>\n new CashError({\n code: 'INSUFFICIENT_AVAILABLE_FUNDS',\n message: `Order ${depositId} has ${available} base units available; ${requested} requested.`,\n retryable: true,\n remediation: `Withdraw at most the available (unlocked) amount, or omit the amount to close the order fully once no buyer intent is live.`,\n }),\n orderNotActive: (depositId: string) =>\n new CashError({\n code: 'ORDER_NOT_ACTIVE',\n message: `Order ${depositId} is closed (delivered or returned); it cannot be topped up.`,\n retryable: false,\n remediation: `Start a new cash-out with cashout() instead.`,\n }),\n nothingToWithdraw: (depositId: string) =>\n new CashError({\n code: 'NOTHING_TO_WITHDRAW',\n message: `Order ${depositId} holds no withdrawable funds (already delivered or returned).`,\n retryable: false,\n remediation: `Check order(depositId).state - this order is terminal.`,\n }),\n indexerLag: (depositId: string) =>\n new CashError({\n code: 'INDEXER_LAG',\n message: `Order ${depositId} is not indexed yet (the deposit may be seconds old).`,\n retryable: true,\n remediation: `Retry in a few seconds; on-chain state is ahead of the indexer right after a transaction.`,\n }),\n orderNotFound: (depositId: string) =>\n new CashError({\n code: 'ORDER_NOT_FOUND',\n message: `No deposit found for id ${depositId}.`,\n retryable: true,\n remediation: `Verify the composite depositId (escrow_onchainId). If the deposit was created seconds ago this is indexer lag - retry shortly.`,\n }),\n payeeRegistrationFailed: (cause: unknown) =>\n new CashError(\n {\n code: 'PAYEE_REGISTRATION_FAILED',\n message: `Registering payee details with the curator failed.`,\n retryable: true,\n remediation: `Check the payee handle format for the platform (see capabilities() hints) and retry.`,\n },\n { cause },\n ),\n payeeVerificationRequired: (platform: string, cause?: unknown) =>\n new CashError(\n {\n code: 'PAYEE_VERIFICATION_REQUIRED',\n message: `${platform} requires a verified maker identity attestation to register a payee; a bare handle is not accepted.`,\n retryable: false,\n remediation: `Register this ${platform} payee through the ZKP2P app / extension (which produces the signed identity attestation) before cashing out. capabilities() flags such platforms with requiresIdentityAttestation: true.`,\n },\n { cause },\n ),\n allowanceNotVisible: (amount: bigint) =>\n new CashError({\n code: 'ALLOWANCE_NOT_VISIBLE',\n message: `USDC approval for ${amount} base units did not become visible on the read path in time.`,\n retryable: true,\n remediation: `The approve transaction mined but a load-balanced RPC is serving stale state. Retry the same call in a few seconds.`,\n }),\n depositResolutionFailed: (txHash: string) =>\n new CashError({\n code: 'DEPOSIT_RESOLUTION_FAILED',\n message: `Deposit transaction ${txHash} succeeded but no DepositReceived event was found in the receipt.`,\n retryable: false,\n remediation: `Inspect the transaction on Basescan; recover the depositId from the DepositReceived log manually, then resume with order(depositId).`,\n }),\n signerRequired: (verb: string) =>\n new CashError({\n code: 'SIGNER_REQUIRED',\n message: `${verb}() mutates on-chain state and needs a signer.`,\n retryable: false,\n remediation: `Pass { signer } (a viem WalletClient with an account), or use prepare() and submit the returned txs with your own signing infrastructure.`,\n }),\n watchTimeout: (depositId: string, timeoutMs: number) =>\n new CashError({\n code: 'WATCH_TIMEOUT',\n message: `watch(${depositId}) exceeded ${timeoutMs}ms without reaching a terminal state.`,\n retryable: true,\n remediation: `The order is still live - resume any time with watch(depositId) or order(depositId).`,\n }),\n transactionFailed: (txHash: string, cause?: unknown) =>\n new CashError(\n {\n code: 'TRANSACTION_FAILED',\n message: `Transaction ${txHash} reverted.`,\n retryable: false,\n remediation: `Inspect the transaction on Basescan; the deposit state is unchanged if the revert happened before escrow accepted funds.`,\n },\n { cause },\n ),\n escrowPaused: () =>\n new CashError({\n code: 'ESCROW_PAUSED',\n message: `The escrow contract is paused; deposits are temporarily disabled.`,\n retryable: true,\n remediation: `Wait for the protocol to unpause and retry. Existing funds remain withdrawable.`,\n }),\n /** Generic fallback for an on-chain call that failed for an unrecognized reason. */\n chainCallFailed: (verb: string, cause?: unknown) =>\n new CashError(\n {\n code: 'TRANSACTION_FAILED',\n message: `The on-chain ${verb} call failed.`,\n retryable: false,\n remediation: `Inspect the error cause and the wallet on Basescan. Deposit state is unchanged if the call reverted before escrow accepted funds.`,\n },\n { cause },\n ),\n};\n\n/**\n * Map a raw SDK/RPC/viem error from a mutating on-chain call to a typed\n * `CashError`, so the package's error contract holds even when the underlying\n * call reverts. Recognized reverts get specific codes; everything else falls\n * back to a wrapped `TRANSACTION_FAILED` (never a raw error to the consumer).\n */\nexport function mapChainError(verb: string, err: unknown): CashError {\n if (isCashError(err)) return err;\n const message = err instanceof Error ? err.message : String(err);\n if (/\\bpaused\\b/i.test(message)) return errors.escrowPaused();\n if (/exceeds allowance|insufficient allowance|transfer amount exceeds/i.test(message)) {\n return errors.allowanceNotVisible(0n);\n }\n return errors.chainCallFailed(verb, err);\n}\n"]}
|