@zkp2p/cash 0.1.2 → 0.1.4
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 +92 -28
- package/README.md +69 -25
- package/dist/chunk-P3KYZ2FX.js +373 -0
- package/dist/{createCashClient-iHuGgjH_.d.cts → createCashClient-BbkfxILl.d.cts} +37 -8
- package/dist/{createCashClient-iHuGgjH_.d.ts → createCashClient-BbkfxILl.d.ts} +37 -8
- package/dist/index.cjs +1099 -254
- package/dist/index.d.cts +1554 -74
- package/dist/index.d.ts +1554 -74
- package/dist/index.js +886 -248
- package/dist/react.cjs +239 -59
- package/dist/react.d.cts +6 -4
- package/dist/react.d.ts +6 -4
- package/dist/react.js +236 -59
- package/dist/tools.cjs +36 -36
- package/dist/tools.d.cts +282 -3
- package/dist/tools.d.ts +282 -3
- package/dist/tools.js +36 -36
- package/docs/lifecycle-and-recovery.md +278 -0
- package/examples/agent-tool-use.ts +122 -0
- package/examples/node-cashout.ts +79 -0
- package/llms.txt +23 -5
- package/package.json +51 -21
- package/skills/peer-cash-integration/SKILL.md +82 -19
- package/dist/chunk-FKVPZVFH.js +0 -188
- package/dist/chunk-FKVPZVFH.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/react.cjs.map +0 -1
- package/dist/react.js.map +0 -1
- package/dist/tools.cjs.map +0 -1
- package/dist/tools.js.map +0 -1
package/llms.txt
CHANGED
|
@@ -15,18 +15,32 @@ Key facts:
|
|
|
15
15
|
a buyer pays fiat and proves it with TEE-TLS; the protocol releases the USDC.
|
|
16
16
|
- Destination is always Base USDC. Source chains/tokens come from Relay SDK
|
|
17
17
|
metadata and quote execution, filtered to EVM chains this SDK can sign.
|
|
18
|
+
- High-level source cashout uses EXACT_INPUT: amount is source-token base units.
|
|
19
|
+
source.amount is Relay's guaranteed minimum Base USDC output and the exact
|
|
20
|
+
order deposit amount, not the route's actual output.
|
|
18
21
|
- There is NO locked fiat quote. estimate() reads the oracle; the binding rate
|
|
19
|
-
resolves at fill time. ETA is `{ seconds, label }` from
|
|
20
|
-
not a
|
|
22
|
+
resolves at fill time. ETA is `{ seconds, label }` from rolling 30-day,
|
|
23
|
+
zero-spread market-rate deposits in the same payout corridor, not a
|
|
24
|
+
guarantee.
|
|
21
25
|
- Resume any order from its depositId alone (composite escrow_onchainId).
|
|
22
26
|
- One unwind verb: withdraw(depositId) - prunes expired intents automatically;
|
|
23
27
|
pass amount for a partial withdrawal of the unlocked balance.
|
|
24
28
|
- topUp(depositId, amount) adds USDC to a live order (same payee, same rate).
|
|
25
29
|
- Base-USDC mutating verbs have unsigned counterparts (prepare,
|
|
26
30
|
prepareWithdraw, prepareTopUp) for host-side signing; source-routed cashout
|
|
27
|
-
needs Relay execution first.
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
needs signer-backed Relay execution first. prepare() and the cash_cashout tool
|
|
32
|
+
are Base-USDC-only; cash_source_quote/status do not execute the route.
|
|
33
|
+
@zkp2p/cash/tools ships a JSON-schema tool manifest.
|
|
34
|
+
- Errors are typed: { code, retryable, remediation, recovery? }. Completed
|
|
35
|
+
Relay routes retain requestId, flat hashes, and origin/destination
|
|
36
|
+
transactions. Retry Base-only after SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED;
|
|
37
|
+
inspect Base activity/orders after SOURCE_CASHOUT_SUBMISSION_UNKNOWN; inspect
|
|
38
|
+
depositTxHash before any action after SOURCE_CASHOUT_STATUS_UNKNOWN. Treat
|
|
39
|
+
TRANSACTION_SUBMISSION_UNKNOWN as potentially broadcast. Retry
|
|
40
|
+
INDEXER_UNAVAILABLE and ORACLE_READ_FAILED reads without repeating a
|
|
41
|
+
transaction; fix SIGNER_CHAIN_MISMATCH or SIGNER_CHAIN_UNAVAILABLE before
|
|
42
|
+
quoting or submitting. TRANSACTION_STATUS_UNKNOWN carries the submitted
|
|
43
|
+
hash in recovery.transactionHash.
|
|
30
44
|
- Everything is decoded to human units: platform ids and currency codes from
|
|
31
45
|
their on-chain hashes, plain-number rates from 1e18 precision.
|
|
32
46
|
- Fills are receipts: locked rate + fiat owed at signal; verified fiat paid,
|
|
@@ -38,6 +52,10 @@ Key facts:
|
|
|
38
52
|
- Default path is same-chain Base USDC. Optional `source` on `cashout()` runs
|
|
39
53
|
Relay source-to-Base-USDC first; non-Base source chains require
|
|
40
54
|
`sourceSigner`.
|
|
55
|
+
- Wise and PayPal require attestation for a new payee registration; a
|
|
56
|
+
previously registered bare handle can be reused.
|
|
57
|
+
- Preproduction uses https://api-preprod.zkp2p.xyz by default; staging uses
|
|
58
|
+
https://api-staging.zkp2p.xyz. curatorUrl can override either.
|
|
41
59
|
|
|
42
60
|
## Links
|
|
43
61
|
|
package/package.json
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zkp2p/cash",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
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)",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"sideEffects": false,
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=22"
|
|
11
|
+
},
|
|
9
12
|
"publishConfig": {
|
|
10
13
|
"access": "public"
|
|
11
14
|
},
|
|
12
|
-
"
|
|
13
|
-
"type": "git",
|
|
14
|
-
"url": "git+https://github.com/zkp2p/peer-cash.git"
|
|
15
|
-
},
|
|
16
|
-
"homepage": "https://github.com/zkp2p/peer-cash#readme",
|
|
17
|
-
"bugs": "https://github.com/zkp2p/peer-cash/issues",
|
|
15
|
+
"homepage": "https://peer.xyz/cash",
|
|
18
16
|
"keywords": [
|
|
19
17
|
"zkp2p",
|
|
20
18
|
"peer",
|
|
@@ -32,25 +30,52 @@
|
|
|
32
30
|
"main": "./dist/index.cjs",
|
|
33
31
|
"module": "./dist/index.js",
|
|
34
32
|
"types": "./dist/index.d.ts",
|
|
33
|
+
"typesVersions": {
|
|
34
|
+
"*": {
|
|
35
|
+
"react": [
|
|
36
|
+
"./dist/react.d.ts"
|
|
37
|
+
],
|
|
38
|
+
"tools": [
|
|
39
|
+
"./dist/tools.d.ts"
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
},
|
|
35
43
|
"exports": {
|
|
36
44
|
".": {
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
"import": {
|
|
46
|
+
"types": "./dist/index.d.ts",
|
|
47
|
+
"default": "./dist/index.js"
|
|
48
|
+
},
|
|
49
|
+
"require": {
|
|
50
|
+
"types": "./dist/index.d.cts",
|
|
51
|
+
"default": "./dist/index.cjs"
|
|
52
|
+
}
|
|
40
53
|
},
|
|
41
54
|
"./react": {
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
55
|
+
"import": {
|
|
56
|
+
"types": "./dist/react.d.ts",
|
|
57
|
+
"default": "./dist/react.js"
|
|
58
|
+
},
|
|
59
|
+
"require": {
|
|
60
|
+
"types": "./dist/react.d.cts",
|
|
61
|
+
"default": "./dist/react.cjs"
|
|
62
|
+
}
|
|
45
63
|
},
|
|
46
64
|
"./tools": {
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
65
|
+
"import": {
|
|
66
|
+
"types": "./dist/tools.d.ts",
|
|
67
|
+
"default": "./dist/tools.js"
|
|
68
|
+
},
|
|
69
|
+
"require": {
|
|
70
|
+
"types": "./dist/tools.d.cts",
|
|
71
|
+
"default": "./dist/tools.cjs"
|
|
72
|
+
}
|
|
50
73
|
}
|
|
51
74
|
},
|
|
52
75
|
"files": [
|
|
53
76
|
"dist",
|
|
77
|
+
"docs",
|
|
78
|
+
"examples",
|
|
54
79
|
"skills",
|
|
55
80
|
"AGENTS.md",
|
|
56
81
|
"README.md",
|
|
@@ -65,16 +90,19 @@
|
|
|
65
90
|
"format:check": "prettier --check .",
|
|
66
91
|
"test": "vitest run",
|
|
67
92
|
"test:watch": "vitest",
|
|
68
|
-
"
|
|
93
|
+
"audit": "bun audit --production",
|
|
94
|
+
"pack:check": "bun scripts/check-packed-package.ts",
|
|
95
|
+
"prepack": "bun run build",
|
|
96
|
+
"ci": "bun run typecheck && bun run lint && bun run format:check && bun run test && bun run audit && bun run build && bun run pack:check"
|
|
69
97
|
},
|
|
70
98
|
"dependencies": {
|
|
71
99
|
"@relayprotocol/relay-sdk": "^6.1.3",
|
|
72
|
-
"@zkp2p/sdk": "^0.8.
|
|
100
|
+
"@zkp2p/sdk": "^0.8.1",
|
|
73
101
|
"zod": "^3.24.1"
|
|
74
102
|
},
|
|
75
103
|
"peerDependencies": {
|
|
76
104
|
"react": ">=18",
|
|
77
|
-
"viem": ">=2.
|
|
105
|
+
"viem": ">=2.37.3 <3"
|
|
78
106
|
},
|
|
79
107
|
"peerDependenciesMeta": {
|
|
80
108
|
"react": {
|
|
@@ -85,14 +113,16 @@
|
|
|
85
113
|
"@eslint/js": "^9.17.0",
|
|
86
114
|
"@types/node": "^22.10.2",
|
|
87
115
|
"@types/react": "^19.0.2",
|
|
116
|
+
"@types/react-test-renderer": "19.1.0",
|
|
88
117
|
"eslint": "^9.17.0",
|
|
89
118
|
"eslint-config-prettier": "^9.1.0",
|
|
90
119
|
"prettier": "^3.4.2",
|
|
91
120
|
"react": "^19.0.0",
|
|
121
|
+
"react-test-renderer": "19.2.7",
|
|
92
122
|
"tsup": "^8.3.5",
|
|
93
123
|
"typescript": "^5.7.2",
|
|
94
124
|
"typescript-eslint": "^8.18.1",
|
|
95
|
-
"viem": "^2.
|
|
96
|
-
"vitest": "^
|
|
125
|
+
"viem": "^2.55.0",
|
|
126
|
+
"vitest": "^4.1.10"
|
|
97
127
|
}
|
|
98
128
|
}
|
|
@@ -20,7 +20,9 @@ custodial off-ramp provider.
|
|
|
20
20
|
Base USDC remains the default/minimal path. Other source chains/tokens come
|
|
21
21
|
from `@relayprotocol/relay-sdk` metadata and quote execution, filtered to
|
|
22
22
|
EVM chains this viem SDK can sign. Non-Base source chains require
|
|
23
|
-
`sourceSigner`.
|
|
23
|
+
`sourceSigner`. Use `EXACT_INPUT` for high-level cash-out flows: `amount` is
|
|
24
|
+
source-token base units, while `source.amount` is Relay's guaranteed minimum
|
|
25
|
+
Base USDC output and the exact order deposit amount, not actual route output.
|
|
24
26
|
- **Oracle-at-fill pricing. There is no quote.** The deposit carries
|
|
25
27
|
`oracleRateConfig { spreadBps: 0 }`; the binding rate is whatever the
|
|
26
28
|
Chainlink feed says when a buyer fills. `estimate()` is deliberately named
|
|
@@ -28,16 +30,17 @@ custodial off-ramp provider.
|
|
|
28
30
|
- **Custody story.** Funds are held by the protocol contract only. An unmatched
|
|
29
31
|
deposit is withdrawable by the maker at any time. The SDK never holds keys.
|
|
30
32
|
- **Honest ETA.** Use `estimate().eta`: `{ seconds, label }` backed by rolling
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
30-day indexer data from zero-spread (`spreadBps: 0`) market-rate deposits in
|
|
34
|
+
the same payout corridor, measured from deposit creation to first fill. Do
|
|
35
|
+
not use signal-to-fulfillment latency and never render it as a guarantee.
|
|
33
36
|
|
|
34
37
|
## 2. Decision tree - entry point by runtime
|
|
35
38
|
|
|
36
|
-
| Runtime | Entry
|
|
37
|
-
| ------------------------- |
|
|
38
|
-
| React app | `@zkp2p/cash/react` hooks + one `createCashClient` in a provider
|
|
39
|
-
| Node service | `createCashClient` + `cashout()`/`withdraw()`
|
|
40
|
-
| Agent host / policy layer | `prepare()`
|
|
39
|
+
| Runtime | Entry | Signer pattern |
|
|
40
|
+
| ------------------------- | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
41
|
+
| React app | `@zkp2p/cash/react` hooks + one `createCashClient` in a provider | wagmi/viem `WalletClient` from the connected wallet |
|
|
42
|
+
| Node service | `createCashClient` + `cashout()`/`withdraw()` | `createWalletClient({ account: privateKeyToAccount(...), chain: base, transport })` |
|
|
43
|
+
| Agent host / policy layer | Base-USDC `prepare*()` -> unsigned `txs[]` + `steps[]` | Host signs; source quote/status tools do not execute Relay |
|
|
41
44
|
|
|
42
45
|
## 3. Recipes - the verbs
|
|
43
46
|
|
|
@@ -47,7 +50,8 @@ not copy types from here; import them.
|
|
|
47
50
|
```ts
|
|
48
51
|
import { createCashClient, usdc } from '@zkp2p/cash';
|
|
49
52
|
|
|
50
|
-
// env: 'production' | 'preproduction' | 'staging'
|
|
53
|
+
// env: 'production' | 'preproduction' | 'staging'. Preproduction and staging
|
|
54
|
+
// select api-preprod.zkp2p.xyz and api-staging.zkp2p.xyz curators by default.
|
|
51
55
|
const cash = createCashClient({ environment: 'staging' });
|
|
52
56
|
|
|
53
57
|
const caps = cash.capabilities(); // 0 discover (sync)
|
|
@@ -72,12 +76,44 @@ await cash.withdraw(res.depositId, { signer }); // 6 unwind (amount: for partial
|
|
|
72
76
|
await cash.topUp(res.depositId, usdc(50), { signer }); // 7 top up a live order
|
|
73
77
|
```
|
|
74
78
|
|
|
79
|
+
Signer-backed exact-input source path:
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
const routed = await cash.cashout(
|
|
83
|
+
{
|
|
84
|
+
amount: sourceAmount,
|
|
85
|
+
source: {
|
|
86
|
+
chainId: sourceChainId,
|
|
87
|
+
currency: sourceToken,
|
|
88
|
+
tradeType: 'EXACT_INPUT',
|
|
89
|
+
},
|
|
90
|
+
receive,
|
|
91
|
+
},
|
|
92
|
+
{ signer, sourceSigner },
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
persist({
|
|
96
|
+
depositId: routed.depositId,
|
|
97
|
+
guaranteedBaseUsdc: routed.source?.amount,
|
|
98
|
+
requestId: routed.source?.requestId,
|
|
99
|
+
transactions: routed.source?.transactions,
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
75
103
|
Base-USDC cashout, withdraw, and top-up also have unsigned `prepare*`
|
|
76
|
-
counterparts. Source-routed cashout runs Relay
|
|
77
|
-
`cashout({ source }, { signer, sourceSigner })
|
|
104
|
+
counterparts. `prepare()` rejects `source`. Source-routed cashout runs Relay
|
|
105
|
+
first; use signed `cashout({ source }, { signer, sourceSigner })`, or execute
|
|
106
|
+
and confirm Relay in the host before preparing a Base-USDC cashout.
|
|
107
|
+
`cash_source_quote` and `cash_source_status` are quote/read tools, not a
|
|
108
|
+
host-side execution path.
|
|
78
109
|
Every protocol transaction carries ERC-8021 attribution (`peer-cash` + your
|
|
79
110
|
`createCashClient({ referrer })` codes).
|
|
80
111
|
|
|
112
|
+
Wise and PayPal require an identity attestation for a new payee registration.
|
|
113
|
+
Do not disable them outright: a previously registered handle can be reused
|
|
114
|
+
with bare payee data. Handle `PAYEE_VERIFICATION_REQUIRED` when registration
|
|
115
|
+
is still needed.
|
|
116
|
+
|
|
81
117
|
## 4. Order management - indexer-native
|
|
82
118
|
|
|
83
119
|
- A cash order IS a deposit; the chain is the database. No storage layer.
|
|
@@ -93,12 +129,33 @@ Every protocol transaction carries ERC-8021 attribution (`peer-cash` + your
|
|
|
93
129
|
|
|
94
130
|
Every error is a `CashError` with `code`, `retryable`, `remediation`. The
|
|
95
131
|
full table lives in `AGENTS.md` and `docs/lifecycle-and-recovery.md` - quote
|
|
96
|
-
those, don't re-derive. The
|
|
132
|
+
those, don't re-derive. The recovery boundaries that matter most in practice:
|
|
97
133
|
|
|
98
134
|
- `ORDER_NOT_FOUND` seconds after `cashout()` = indexer lag. The receipt is
|
|
99
135
|
the truth; retry. `watch()` and the React hooks absorb it.
|
|
100
136
|
- `ACTIVE_INTENT_BLOCKS_WITHDRAWAL` = a buyer may still deliver. Retry
|
|
101
137
|
`withdraw()` after their intent expires; it prunes automatically.
|
|
138
|
+
- `SOURCE_ROUTE_COMPLETED_CASHOUT_FAILED` = Relay completed but the Base
|
|
139
|
+
cashout did not. Never repeat Relay; retry Base-only with
|
|
140
|
+
`BigInt(error.recovery.amount)`.
|
|
141
|
+
- `SOURCE_CASHOUT_SUBMISSION_UNKNOWN` = Relay completed but Base submission
|
|
142
|
+
returned no hash. Inspect Base wallet activity and
|
|
143
|
+
`orders(error.recovery.depositor)` before any retry.
|
|
144
|
+
- `SOURCE_CASHOUT_STATUS_UNKNOWN` = Relay completed and a Base transaction was
|
|
145
|
+
submitted, but its receipt is unknown. Inspect
|
|
146
|
+
`error.recovery.depositTxHash`; do not route or submit again until it is
|
|
147
|
+
known.
|
|
148
|
+
- `TRANSACTION_STATUS_UNKNOWN` = a Base transaction may already have
|
|
149
|
+
succeeded. Inspect `error.recovery.transactionHash` before resubmitting.
|
|
150
|
+
- `TRANSACTION_SUBMISSION_UNKNOWN` = a Base mutation returned no hash but may
|
|
151
|
+
have broadcast. Follow `error.recovery`, inspect Base wallet/protocol state,
|
|
152
|
+
and do not retry until absence is proven.
|
|
153
|
+
- `INDEXER_UNAVAILABLE` / `ORACLE_READ_FAILED` = retry the read only. Do not
|
|
154
|
+
repeat the transaction that produced the id or balance being inspected.
|
|
155
|
+
- `SIGNER_CHAIN_MISMATCH` = switch to the required chain and obtain a fresh
|
|
156
|
+
Relay quote before retrying.
|
|
157
|
+
- `SIGNER_CHAIN_UNAVAILABLE` = reconnect the wallet and verify its live chain
|
|
158
|
+
before any quote or mutation.
|
|
102
159
|
- Buyer never pays → nothing to do: the intent expires, `nextActions` gains
|
|
103
160
|
`'withdraw'`, one `withdraw()` call returns the funds (prune + withdraw).
|
|
104
161
|
|
|
@@ -107,13 +164,19 @@ those, don't re-derive. The three that matter most in practice:
|
|
|
107
164
|
Run against `environment: 'staging'` with a small funded wallet.
|
|
108
165
|
**Maker-side only - never wait on a buyer.**
|
|
109
166
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
167
|
+
Prove both routes without waiting for a buyer:
|
|
168
|
+
|
|
169
|
+
1. Create a real 1–2 USDC Base-USDC deposit; retain `depositId` and Base tx.
|
|
170
|
+
2. Retry through indexer lag until `order(depositId)` is `awaiting-buyer`, and
|
|
171
|
+
assert `orders(owner)` contains it.
|
|
172
|
+
3. Withdraw it; assert `returned` and the Base USDC balance is restored minus
|
|
173
|
+
gas.
|
|
174
|
+
4. Select a live supported source from capabilities and create a real
|
|
175
|
+
exact-input route whose guaranteed Base USDC output is at least 1 USDC.
|
|
176
|
+
Retain Relay `requestId`, origin/destination transaction hashes, Base tx,
|
|
177
|
+
and `depositId`.
|
|
178
|
+
5. Assert the routed order becomes `awaiting-buyer` and appears in
|
|
179
|
+
`orders(owner)`, then withdraw and confirm `returned` plus restored balance.
|
|
117
180
|
|
|
118
181
|
If withdrawal fails with funds stuck: stop, do not retry blindly, escalate to
|
|
119
182
|
a human with the `depositId` and tx hashes.
|
package/dist/chunk-FKVPZVFH.js
DELETED
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
// src/engine/constants.ts
|
|
2
|
-
var BASE_CHAIN_ID = 8453;
|
|
3
|
-
var BASE_USDC_ADDRESS = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913";
|
|
4
|
-
var USDC_DECIMALS = 6;
|
|
5
|
-
var MARKET_SPREAD_BPS = 0;
|
|
6
|
-
var ORACLE_MIN_CONVERSION_RATE_SENTINEL = 1n;
|
|
7
|
-
var CASH_ORDER_STATUSES = [
|
|
8
|
-
"SIGNALED",
|
|
9
|
-
"FULFILLED",
|
|
10
|
-
"PRUNED",
|
|
11
|
-
"MANUALLY_RELEASED"
|
|
12
|
-
];
|
|
13
|
-
var CASH_ORDER_POLL_INTERVAL_MS = 5e3;
|
|
14
|
-
var CASH_RETAIN_ON_EMPTY = false;
|
|
15
|
-
|
|
16
|
-
// src/client/errors.ts
|
|
17
|
-
var CashError = class extends Error {
|
|
18
|
-
code;
|
|
19
|
-
retryable;
|
|
20
|
-
remediation;
|
|
21
|
-
constructor(shape, options) {
|
|
22
|
-
super(shape.message, options);
|
|
23
|
-
this.name = "CashError";
|
|
24
|
-
this.code = shape.code;
|
|
25
|
-
this.retryable = shape.retryable;
|
|
26
|
-
this.remediation = shape.remediation;
|
|
27
|
-
}
|
|
28
|
-
/** Serializable view (for tool results and logs). */
|
|
29
|
-
toJSON() {
|
|
30
|
-
return {
|
|
31
|
-
code: this.code,
|
|
32
|
-
message: this.message,
|
|
33
|
-
retryable: this.retryable,
|
|
34
|
-
remediation: this.remediation
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
function isCashError(value) {
|
|
39
|
-
return value instanceof CashError;
|
|
40
|
-
}
|
|
41
|
-
var errors = {
|
|
42
|
-
oracleUnsupportedCurrency: (currency) => new CashError({
|
|
43
|
-
code: "ORACLE_UNSUPPORTED_CURRENCY",
|
|
44
|
-
message: `${currency} has no live Chainlink oracle feed; Peer Cash is market-rate only.`,
|
|
45
|
-
retryable: false,
|
|
46
|
-
remediation: `Pick a currency listed in capabilities() - each one is priced by a live oracle feed.`
|
|
47
|
-
}),
|
|
48
|
-
unsupportedPlatform: (platform) => new CashError({
|
|
49
|
-
code: "UNSUPPORTED_PLATFORM",
|
|
50
|
-
message: `'${platform}' is not a supported payout platform in this environment.`,
|
|
51
|
-
retryable: false,
|
|
52
|
-
remediation: `Pick a platform listed in capabilities().`
|
|
53
|
-
}),
|
|
54
|
-
amountBelowMinimum: (amount, min) => new CashError({
|
|
55
|
-
code: "AMOUNT_BELOW_MINIMUM",
|
|
56
|
-
message: `Amount ${amount} is below the minimum cash-out of ${min} USDC base units.`,
|
|
57
|
-
retryable: false,
|
|
58
|
-
remediation: `Increase the amount to at least ${min} base units (${Number(min) / 1e6} USDC).`
|
|
59
|
-
}),
|
|
60
|
-
activeIntentBlocksWithdrawal: (depositId) => new CashError({
|
|
61
|
-
code: "ACTIVE_INTENT_BLOCKS_WITHDRAWAL",
|
|
62
|
-
message: `Order ${depositId} has a live buyer intent; escrow blocks withdrawal while a buyer may still deliver.`,
|
|
63
|
-
retryable: true,
|
|
64
|
-
remediation: `Wait for the buyer to complete or for their intent to expire, then call withdraw() again - it prunes expired intents automatically.`
|
|
65
|
-
}),
|
|
66
|
-
insufficientAvailableFunds: (depositId, requested, available) => new CashError({
|
|
67
|
-
code: "INSUFFICIENT_AVAILABLE_FUNDS",
|
|
68
|
-
message: `Order ${depositId} has ${available} base units available; ${requested} requested.`,
|
|
69
|
-
retryable: true,
|
|
70
|
-
remediation: `Withdraw at most the available (unlocked) amount, or omit the amount to close the order fully once no buyer intent is live.`
|
|
71
|
-
}),
|
|
72
|
-
orderNotActive: (depositId) => new CashError({
|
|
73
|
-
code: "ORDER_NOT_ACTIVE",
|
|
74
|
-
message: `Order ${depositId} is closed (delivered or returned); it cannot be topped up.`,
|
|
75
|
-
retryable: false,
|
|
76
|
-
remediation: `Start a new cash-out with cashout() instead.`
|
|
77
|
-
}),
|
|
78
|
-
nothingToWithdraw: (depositId) => new CashError({
|
|
79
|
-
code: "NOTHING_TO_WITHDRAW",
|
|
80
|
-
message: `Order ${depositId} holds no withdrawable funds (already delivered or returned).`,
|
|
81
|
-
retryable: false,
|
|
82
|
-
remediation: `Check order(depositId).state - this order is terminal.`
|
|
83
|
-
}),
|
|
84
|
-
indexerLag: (depositId) => new CashError({
|
|
85
|
-
code: "INDEXER_LAG",
|
|
86
|
-
message: `Order ${depositId} is not indexed yet (the deposit may be seconds old).`,
|
|
87
|
-
retryable: true,
|
|
88
|
-
remediation: `Retry in a few seconds; on-chain state is ahead of the indexer right after a transaction.`
|
|
89
|
-
}),
|
|
90
|
-
orderNotFound: (depositId) => new CashError({
|
|
91
|
-
code: "ORDER_NOT_FOUND",
|
|
92
|
-
message: `No deposit found for id ${depositId}.`,
|
|
93
|
-
retryable: true,
|
|
94
|
-
remediation: `Verify the composite depositId (escrow_onchainId). If the deposit was created seconds ago this is indexer lag - retry shortly.`
|
|
95
|
-
}),
|
|
96
|
-
payeeRegistrationFailed: (cause) => new CashError(
|
|
97
|
-
{
|
|
98
|
-
code: "PAYEE_REGISTRATION_FAILED",
|
|
99
|
-
message: `Registering payee details with the curator failed.`,
|
|
100
|
-
retryable: true,
|
|
101
|
-
remediation: `Check the payee handle format for the platform (see capabilities() hints) and retry.`
|
|
102
|
-
},
|
|
103
|
-
{ cause }
|
|
104
|
-
),
|
|
105
|
-
payeeVerificationRequired: (platform, cause) => new CashError(
|
|
106
|
-
{
|
|
107
|
-
code: "PAYEE_VERIFICATION_REQUIRED",
|
|
108
|
-
message: `${platform} requires a verified maker identity attestation to register a payee; a bare handle is not accepted.`,
|
|
109
|
-
retryable: false,
|
|
110
|
-
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.`
|
|
111
|
-
},
|
|
112
|
-
{ cause }
|
|
113
|
-
),
|
|
114
|
-
sourceRouteUnsupportedInPrepare: () => new CashError({
|
|
115
|
-
code: "SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE",
|
|
116
|
-
message: `prepare() cannot execute a Relay source route before creating the Base USDC cash-out.`,
|
|
117
|
-
retryable: false,
|
|
118
|
-
remediation: `Use cashout(inputWithSource, { signer }) for the one-call bridge-then-cashout flow, or call quoteSource()/executeSourceQuote() first and then prepare() a Base USDC cash-out.`
|
|
119
|
-
}),
|
|
120
|
-
sourceRecipientMismatch: (recipient, owner) => new CashError({
|
|
121
|
-
code: "SOURCE_RECIPIENT_MISMATCH",
|
|
122
|
-
message: `Source recipient ${recipient} does not match the cash-out depositor ${owner}.`,
|
|
123
|
-
retryable: false,
|
|
124
|
-
remediation: `For one-call source cashout, deliver Relay output to the depositor address. For a different recipient, bridge first and then cash out from that recipient's signer.`
|
|
125
|
-
}),
|
|
126
|
-
allowanceNotVisible: (amount) => new CashError({
|
|
127
|
-
code: "ALLOWANCE_NOT_VISIBLE",
|
|
128
|
-
message: `USDC approval for ${amount} base units did not become visible on the read path in time.`,
|
|
129
|
-
retryable: true,
|
|
130
|
-
remediation: `The approve transaction mined but a load-balanced RPC is serving stale state. Retry the same call in a few seconds.`
|
|
131
|
-
}),
|
|
132
|
-
depositResolutionFailed: (txHash) => new CashError({
|
|
133
|
-
code: "DEPOSIT_RESOLUTION_FAILED",
|
|
134
|
-
message: `Deposit transaction ${txHash} succeeded but no DepositReceived event was found in the receipt.`,
|
|
135
|
-
retryable: false,
|
|
136
|
-
remediation: `Inspect the transaction on Basescan; recover the depositId from the DepositReceived log manually, then resume with order(depositId).`
|
|
137
|
-
}),
|
|
138
|
-
signerRequired: (verb) => new CashError({
|
|
139
|
-
code: "SIGNER_REQUIRED",
|
|
140
|
-
message: `${verb}() mutates on-chain state and needs a signer.`,
|
|
141
|
-
retryable: false,
|
|
142
|
-
remediation: `Pass { signer } (a viem WalletClient with an account), or use prepare() and submit the returned txs with your own signing infrastructure.`
|
|
143
|
-
}),
|
|
144
|
-
watchTimeout: (depositId, timeoutMs) => new CashError({
|
|
145
|
-
code: "WATCH_TIMEOUT",
|
|
146
|
-
message: `watch(${depositId}) exceeded ${timeoutMs}ms without reaching a terminal state.`,
|
|
147
|
-
retryable: true,
|
|
148
|
-
remediation: `The order is still live - resume any time with watch(depositId) or order(depositId).`
|
|
149
|
-
}),
|
|
150
|
-
transactionFailed: (txHash, cause) => new CashError(
|
|
151
|
-
{
|
|
152
|
-
code: "TRANSACTION_FAILED",
|
|
153
|
-
message: `Transaction ${txHash} reverted.`,
|
|
154
|
-
retryable: false,
|
|
155
|
-
remediation: `Inspect the transaction on Basescan; the deposit state is unchanged if the revert happened before escrow accepted funds.`
|
|
156
|
-
},
|
|
157
|
-
{ cause }
|
|
158
|
-
),
|
|
159
|
-
escrowPaused: () => new CashError({
|
|
160
|
-
code: "ESCROW_PAUSED",
|
|
161
|
-
message: `The escrow contract is paused; deposits are temporarily disabled.`,
|
|
162
|
-
retryable: true,
|
|
163
|
-
remediation: `Wait for the protocol to unpause and retry. Existing funds remain withdrawable.`
|
|
164
|
-
}),
|
|
165
|
-
/** Generic fallback for an on-chain call that failed for an unrecognized reason. */
|
|
166
|
-
chainCallFailed: (verb, cause) => new CashError(
|
|
167
|
-
{
|
|
168
|
-
code: "TRANSACTION_FAILED",
|
|
169
|
-
message: `The on-chain ${verb} call failed.`,
|
|
170
|
-
retryable: false,
|
|
171
|
-
remediation: `Inspect the error cause and the wallet on Basescan. Deposit state is unchanged if the call reverted before escrow accepted funds.`
|
|
172
|
-
},
|
|
173
|
-
{ cause }
|
|
174
|
-
)
|
|
175
|
-
};
|
|
176
|
-
function mapChainError(verb, err) {
|
|
177
|
-
if (isCashError(err)) return err;
|
|
178
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
179
|
-
if (/\bpaused\b/i.test(message)) return errors.escrowPaused();
|
|
180
|
-
if (/exceeds allowance|insufficient allowance|transfer amount exceeds/i.test(message)) {
|
|
181
|
-
return errors.allowanceNotVisible(0n);
|
|
182
|
-
}
|
|
183
|
-
return errors.chainCallFailed(verb, err);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
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, mapChainError };
|
|
187
|
-
//# sourceMappingURL=chunk-FKVPZVFH.js.map
|
|
188
|
-
//# sourceMappingURL=chunk-FKVPZVFH.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/engine/constants.ts","../src/client/errors.ts"],"names":[],"mappings":";AAaO,IAAM,aAAA,GAAgB;AAGtB,IAAM,iBAAA,GAAoB;AAG1B,IAAM,aAAA,GAAgB;AAOtB,IAAM,iBAAA,GAAoB;AAO1B,IAAM,mCAAA,GAAsC;AAQ5C,IAAM,mBAAA,GAAsC;AAAA,EACjD,UAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF;AAGO,IAAM,2BAAA,GAA8B;AAMpC,IAAM,oBAAA,GAAuB;;;ACvB7B,IAAM,SAAA,GAAN,cAAwB,KAAA,CAAgC;AAAA,EACpD,IAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AAAA,EAET,WAAA,CAAY,OAAuB,OAAA,EAA+B;AAChE,IAAA,KAAA,CAAM,KAAA,CAAM,SAAS,OAAO,CAAA;AAC5B,IAAA,IAAA,CAAK,IAAA,GAAO,WAAA;AACZ,IAAA,IAAA,CAAK,OAAO,KAAA,CAAM,IAAA;AAClB,IAAA,IAAA,CAAK,YAAY,KAAA,CAAM,SAAA;AACvB,IAAA,IAAA,CAAK,cAAc,KAAA,CAAM,WAAA;AAAA,EAC3B;AAAA;AAAA,EAGA,MAAA,GAAyB;AACvB,IAAA,OAAO;AAAA,MACL,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,aAAa,IAAA,CAAK;AAAA,KACpB;AAAA,EACF;AACF;AAEO,SAAS,YAAY,KAAA,EAAoC;AAC9D,EAAA,OAAO,KAAA,YAAiB,SAAA;AAC1B;AAGO,IAAM,MAAA,GAAS;AAAA,EACpB,yBAAA,EAA2B,CAAC,QAAA,KAC1B,IAAI,SAAA,CAAU;AAAA,IACZ,IAAA,EAAM,6BAAA;AAAA,IACN,OAAA,EAAS,GAAG,QAAQ,CAAA,kEAAA,CAAA;AAAA,IACpB,SAAA,EAAW,KAAA;AAAA,IACX,WAAA,EAAa,CAAA,oFAAA;AAAA,GACd,CAAA;AAAA,EACH,mBAAA,EAAqB,CAAC,QAAA,KACpB,IAAI,SAAA,CAAU;AAAA,IACZ,IAAA,EAAM,sBAAA;AAAA,IACN,OAAA,EAAS,IAAI,QAAQ,CAAA,yDAAA,CAAA;AAAA,IACrB,SAAA,EAAW,KAAA;AAAA,IACX,WAAA,EAAa,CAAA,yCAAA;AAAA,GACd,CAAA;AAAA,EACH,kBAAA,EAAoB,CAAC,MAAA,EAAgB,GAAA,KACnC,IAAI,SAAA,CAAU;AAAA,IACZ,IAAA,EAAM,sBAAA;AAAA,IACN,OAAA,EAAS,CAAA,OAAA,EAAU,MAAM,CAAA,kCAAA,EAAqC,GAAG,CAAA,iBAAA,CAAA;AAAA,IACjE,SAAA,EAAW,KAAA;AAAA,IACX,aAAa,CAAA,gCAAA,EAAmC,GAAG,gBAAgB,MAAA,CAAO,GAAG,IAAI,GAAG,CAAA,OAAA;AAAA,GACrF,CAAA;AAAA,EACH,4BAAA,EAA8B,CAAC,SAAA,KAC7B,IAAI,SAAA,CAAU;AAAA,IACZ,IAAA,EAAM,iCAAA;AAAA,IACN,OAAA,EAAS,SAAS,SAAS,CAAA,mFAAA,CAAA;AAAA,IAC3B,SAAA,EAAW,IAAA;AAAA,IACX,WAAA,EAAa,CAAA,mIAAA;AAAA,GACd,CAAA;AAAA,EACH,4BAA4B,CAAC,SAAA,EAAmB,SAAA,EAAmB,SAAA,KACjE,IAAI,SAAA,CAAU;AAAA,IACZ,IAAA,EAAM,8BAAA;AAAA,IACN,SAAS,CAAA,MAAA,EAAS,SAAS,CAAA,KAAA,EAAQ,SAAS,0BAA0B,SAAS,CAAA,WAAA,CAAA;AAAA,IAC/E,SAAA,EAAW,IAAA;AAAA,IACX,WAAA,EAAa,CAAA,2HAAA;AAAA,GACd,CAAA;AAAA,EACH,cAAA,EAAgB,CAAC,SAAA,KACf,IAAI,SAAA,CAAU;AAAA,IACZ,IAAA,EAAM,kBAAA;AAAA,IACN,OAAA,EAAS,SAAS,SAAS,CAAA,2DAAA,CAAA;AAAA,IAC3B,SAAA,EAAW,KAAA;AAAA,IACX,WAAA,EAAa,CAAA,4CAAA;AAAA,GACd,CAAA;AAAA,EACH,iBAAA,EAAmB,CAAC,SAAA,KAClB,IAAI,SAAA,CAAU;AAAA,IACZ,IAAA,EAAM,qBAAA;AAAA,IACN,OAAA,EAAS,SAAS,SAAS,CAAA,6DAAA,CAAA;AAAA,IAC3B,SAAA,EAAW,KAAA;AAAA,IACX,WAAA,EAAa,CAAA,sDAAA;AAAA,GACd,CAAA;AAAA,EACH,UAAA,EAAY,CAAC,SAAA,KACX,IAAI,SAAA,CAAU;AAAA,IACZ,IAAA,EAAM,aAAA;AAAA,IACN,OAAA,EAAS,SAAS,SAAS,CAAA,qDAAA,CAAA;AAAA,IAC3B,SAAA,EAAW,IAAA;AAAA,IACX,WAAA,EAAa,CAAA,yFAAA;AAAA,GACd,CAAA;AAAA,EACH,aAAA,EAAe,CAAC,SAAA,KACd,IAAI,SAAA,CAAU;AAAA,IACZ,IAAA,EAAM,iBAAA;AAAA,IACN,OAAA,EAAS,2BAA2B,SAAS,CAAA,CAAA,CAAA;AAAA,IAC7C,SAAA,EAAW,IAAA;AAAA,IACX,WAAA,EAAa,CAAA,8HAAA;AAAA,GACd,CAAA;AAAA,EACH,uBAAA,EAAyB,CAAC,KAAA,KACxB,IAAI,SAAA;AAAA,IACF;AAAA,MACE,IAAA,EAAM,2BAAA;AAAA,MACN,OAAA,EAAS,CAAA,kDAAA,CAAA;AAAA,MACT,SAAA,EAAW,IAAA;AAAA,MACX,WAAA,EAAa,CAAA,oFAAA;AAAA,KACf;AAAA,IACA,EAAE,KAAA;AAAM,GACV;AAAA,EACF,yBAAA,EAA2B,CAAC,QAAA,EAAkB,KAAA,KAC5C,IAAI,SAAA;AAAA,IACF;AAAA,MACE,IAAA,EAAM,6BAAA;AAAA,MACN,OAAA,EAAS,GAAG,QAAQ,CAAA,mGAAA,CAAA;AAAA,MACpB,SAAA,EAAW,KAAA;AAAA,MACX,WAAA,EAAa,iBAAiB,QAAQ,CAAA,yLAAA;AAAA,KACxC;AAAA,IACA,EAAE,KAAA;AAAM,GACV;AAAA,EACF,+BAAA,EAAiC,MAC/B,IAAI,SAAA,CAAU;AAAA,IACZ,IAAA,EAAM,qCAAA;AAAA,IACN,OAAA,EAAS,CAAA,qFAAA,CAAA;AAAA,IACT,SAAA,EAAW,KAAA;AAAA,IACX,WAAA,EAAa,CAAA,6KAAA;AAAA,GACd,CAAA;AAAA,EACH,uBAAA,EAAyB,CAAC,SAAA,EAAmB,KAAA,KAC3C,IAAI,SAAA,CAAU;AAAA,IACZ,IAAA,EAAM,2BAAA;AAAA,IACN,OAAA,EAAS,CAAA,iBAAA,EAAoB,SAAS,CAAA,uCAAA,EAA0C,KAAK,CAAA,CAAA,CAAA;AAAA,IACrF,SAAA,EAAW,KAAA;AAAA,IACX,WAAA,EAAa,CAAA,mKAAA;AAAA,GACd,CAAA;AAAA,EACH,mBAAA,EAAqB,CAAC,MAAA,KACpB,IAAI,SAAA,CAAU;AAAA,IACZ,IAAA,EAAM,uBAAA;AAAA,IACN,OAAA,EAAS,qBAAqB,MAAM,CAAA,4DAAA,CAAA;AAAA,IACpC,SAAA,EAAW,IAAA;AAAA,IACX,WAAA,EAAa,CAAA,mHAAA;AAAA,GACd,CAAA;AAAA,EACH,uBAAA,EAAyB,CAAC,MAAA,KACxB,IAAI,SAAA,CAAU;AAAA,IACZ,IAAA,EAAM,2BAAA;AAAA,IACN,OAAA,EAAS,uBAAuB,MAAM,CAAA,iEAAA,CAAA;AAAA,IACtC,SAAA,EAAW,KAAA;AAAA,IACX,WAAA,EAAa,CAAA,oIAAA;AAAA,GACd,CAAA;AAAA,EACH,cAAA,EAAgB,CAAC,IAAA,KACf,IAAI,SAAA,CAAU;AAAA,IACZ,IAAA,EAAM,iBAAA;AAAA,IACN,OAAA,EAAS,GAAG,IAAI,CAAA,6CAAA,CAAA;AAAA,IAChB,SAAA,EAAW,KAAA;AAAA,IACX,WAAA,EAAa,CAAA,yIAAA;AAAA,GACd,CAAA;AAAA,EACH,YAAA,EAAc,CAAC,SAAA,EAAmB,SAAA,KAChC,IAAI,SAAA,CAAU;AAAA,IACZ,IAAA,EAAM,eAAA;AAAA,IACN,OAAA,EAAS,CAAA,MAAA,EAAS,SAAS,CAAA,WAAA,EAAc,SAAS,CAAA,qCAAA,CAAA;AAAA,IAClD,SAAA,EAAW,IAAA;AAAA,IACX,WAAA,EAAa,CAAA,oFAAA;AAAA,GACd,CAAA;AAAA,EACH,iBAAA,EAAmB,CAAC,MAAA,EAAgB,KAAA,KAClC,IAAI,SAAA;AAAA,IACF;AAAA,MACE,IAAA,EAAM,oBAAA;AAAA,MACN,OAAA,EAAS,eAAe,MAAM,CAAA,UAAA,CAAA;AAAA,MAC9B,SAAA,EAAW,KAAA;AAAA,MACX,WAAA,EAAa,CAAA,wHAAA;AAAA,KACf;AAAA,IACA,EAAE,KAAA;AAAM,GACV;AAAA,EACF,YAAA,EAAc,MACZ,IAAI,SAAA,CAAU;AAAA,IACZ,IAAA,EAAM,eAAA;AAAA,IACN,OAAA,EAAS,CAAA,iEAAA,CAAA;AAAA,IACT,SAAA,EAAW,IAAA;AAAA,IACX,WAAA,EAAa,CAAA,+EAAA;AAAA,GACd,CAAA;AAAA;AAAA,EAEH,eAAA,EAAiB,CAAC,IAAA,EAAc,KAAA,KAC9B,IAAI,SAAA;AAAA,IACF;AAAA,MACE,IAAA,EAAM,oBAAA;AAAA,MACN,OAAA,EAAS,gBAAgB,IAAI,CAAA,aAAA,CAAA;AAAA,MAC7B,SAAA,EAAW,KAAA;AAAA,MACX,WAAA,EAAa,CAAA,iIAAA;AAAA,KACf;AAAA,IACA,EAAE,KAAA;AAAM;AAEd;AAQO,SAAS,aAAA,CAAc,MAAc,GAAA,EAAyB;AACnE,EAAA,IAAI,WAAA,CAAY,GAAG,CAAA,EAAG,OAAO,GAAA;AAC7B,EAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC/D,EAAA,IAAI,cAAc,IAAA,CAAK,OAAO,CAAA,EAAG,OAAO,OAAO,YAAA,EAAa;AAC5D,EAAA,IAAI,mEAAA,CAAoE,IAAA,CAAK,OAAO,CAAA,EAAG;AACrF,IAAA,OAAO,MAAA,CAAO,oBAAoB,EAAE,CAAA;AAAA,EACtC;AACA,EAAA,OAAO,MAAA,CAAO,eAAA,CAAgB,IAAA,EAAM,GAAG,CAAA;AACzC","file":"chunk-FKVPZVFH.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 | 'SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE'\n | 'SOURCE_RECIPIENT_MISMATCH'\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 sourceRouteUnsupportedInPrepare: () =>\n new CashError({\n code: 'SOURCE_ROUTE_UNSUPPORTED_IN_PREPARE',\n message: `prepare() cannot execute a Relay source route before creating the Base USDC cash-out.`,\n retryable: false,\n remediation: `Use cashout(inputWithSource, { signer }) for the one-call bridge-then-cashout flow, or call quoteSource()/executeSourceQuote() first and then prepare() a Base USDC cash-out.`,\n }),\n sourceRecipientMismatch: (recipient: string, owner: string) =>\n new CashError({\n code: 'SOURCE_RECIPIENT_MISMATCH',\n message: `Source recipient ${recipient} does not match the cash-out depositor ${owner}.`,\n retryable: false,\n remediation: `For one-call source cashout, deliver Relay output to the depositor address. For a different recipient, bridge first and then cash out from that recipient's signer.`,\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"]}
|