@zkp2p/cash 0.1.5 → 0.1.6
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/README.md +18 -5
- package/dist/index.cjs +27 -7
- package/dist/index.js +27 -7
- package/dist/tools.cjs +1 -1
- package/dist/tools.js +1 -1
- package/llms.txt +3 -4
- package/package.json +21 -14
package/README.md
CHANGED
|
@@ -5,12 +5,25 @@ on Venmo, Revolut, Wise, Zelle, and more at the live Chainlink market rate,
|
|
|
5
5
|
with zero spread and no centralized off-ramp provider.
|
|
6
6
|
|
|
7
7
|
Peer Cash is an **offramp-only** SDK for the [ZKP2P](https://peer.xyz)
|
|
8
|
-
protocol. The cashing-out user is the maker: their USDC becomes a
|
|
9
|
-
protocol
|
|
10
|
-
integrator a small set of typed verbs plus readable order state.
|
|
11
|
-
widget, no provider custody, no quote engine to maintain.
|
|
8
|
+
protocol. The cashing-out user is the maker: their USDC becomes a deposit in
|
|
9
|
+
the protocol contracts, a buyer pays them fiat and proves the payment, and the
|
|
10
|
+
SDK gives the integrator a small set of typed verbs plus readable order state.
|
|
11
|
+
No hosted widget, no provider custody, no quote engine to maintain.
|
|
12
12
|
|
|
13
|
-
**[
|
|
13
|
+
**[npm](https://www.npmjs.com/package/@zkp2p/cash)** · **[Lifecycle and recovery](docs/lifecycle-and-recovery.md)** · **[Agent integration manual](AGENTS.md)**
|
|
14
|
+
|
|
15
|
+
## Pick the right SDK
|
|
16
|
+
|
|
17
|
+
Peer Cash and the general ZKP2P SDK serve different integration depths:
|
|
18
|
+
|
|
19
|
+
| Package | Use it when | Boundary |
|
|
20
|
+
| ------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
21
|
+
| `@zkp2p/cash` | Cash-out is the product | Offramp only. The user is always the maker, the destination is Base USDC, pricing is the live Chainlink rate at fill with zero spread, and the SDK owns the resumable order lifecycle. |
|
|
22
|
+
| `@zkp2p/sdk` | You are composing directly with the Peer protocol | General maker and taker operations, deposits, intents, proofs, quotes, vaults, rate managers, referrals, hooks, and API helpers. Your application owns the workflow and protocol choices. |
|
|
23
|
+
|
|
24
|
+
Peer Cash is a narrow facade over `@zkp2p/sdk`, not a replacement for it. It
|
|
25
|
+
cannot express custom spreads, buyer-side proof flows, vaults, disputes, or
|
|
26
|
+
arbitrary protocol operations.
|
|
14
27
|
|
|
15
28
|
```ts
|
|
16
29
|
import { createCashClient, usdc } from '@zkp2p/cash';
|
package/dist/index.cjs
CHANGED
|
@@ -1717,32 +1717,51 @@ function createCashClient(options) {
|
|
|
1717
1717
|
(transaction) => transaction.chainId === BASE_CHAIN_ID
|
|
1718
1718
|
);
|
|
1719
1719
|
const batchIds = baseTransactions.filter((transaction) => transaction.isBatchTx === true).map((transaction) => transaction.hash);
|
|
1720
|
+
const batchExecutionFailed = (cause) => errors.sourceExecutionFailed(cause, {
|
|
1721
|
+
...executed.requestId ? { requestId: executed.requestId } : {},
|
|
1722
|
+
txHashes: executed.txHashes,
|
|
1723
|
+
...executed.transactions ? { transactions: executed.transactions } : {}
|
|
1724
|
+
});
|
|
1720
1725
|
let batchTransactionHashes = [];
|
|
1721
1726
|
if (batchIds.length > 0) {
|
|
1722
1727
|
let batchError;
|
|
1723
1728
|
let batchesComplete = false;
|
|
1729
|
+
let batchesSucceededWithoutReceipts = false;
|
|
1724
1730
|
for (let attempt = 0; attempt < 20; attempt++) {
|
|
1725
1731
|
try {
|
|
1726
1732
|
const statuses = await Promise.all(
|
|
1727
1733
|
batchIds.map((id) => sourceSigner.getCallsStatus({ id }))
|
|
1728
1734
|
);
|
|
1729
1735
|
if (statuses.some((status) => status.status === "failure")) {
|
|
1730
|
-
throw new Error("Relay wallet call bundle failed");
|
|
1736
|
+
throw batchExecutionFailed(new Error("Relay wallet call bundle failed"));
|
|
1731
1737
|
}
|
|
1732
1738
|
if (statuses.every((status) => status.status === "success")) {
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1739
|
+
const receiptGroups = statuses.map((status) => status.receipts ?? []);
|
|
1740
|
+
if (receiptGroups.some((receipts) => receipts.length === 0)) {
|
|
1741
|
+
batchError = new Error(
|
|
1742
|
+
"Relay wallet call bundle did not include transaction receipts"
|
|
1743
|
+
);
|
|
1744
|
+
batchesSucceededWithoutReceipts = true;
|
|
1745
|
+
break;
|
|
1746
|
+
} else {
|
|
1747
|
+
batchTransactionHashes = receiptGroups.flatMap(
|
|
1748
|
+
(receipts) => receipts.map((receipt) => receipt.transactionHash)
|
|
1749
|
+
);
|
|
1750
|
+
batchesComplete = true;
|
|
1751
|
+
break;
|
|
1752
|
+
}
|
|
1738
1753
|
}
|
|
1739
1754
|
} catch (err) {
|
|
1755
|
+
if (isCashError(err)) throw err;
|
|
1740
1756
|
batchError = err;
|
|
1741
1757
|
}
|
|
1742
1758
|
await sleep(250);
|
|
1743
1759
|
}
|
|
1744
1760
|
if (!batchesComplete) {
|
|
1745
|
-
|
|
1761
|
+
if (batchesSucceededWithoutReceipts) throw batchError;
|
|
1762
|
+
throw batchExecutionFailed(
|
|
1763
|
+
batchError ?? new Error("Relay wallet call bundle did not complete")
|
|
1764
|
+
);
|
|
1746
1765
|
}
|
|
1747
1766
|
}
|
|
1748
1767
|
const hashes = [
|
|
@@ -1864,6 +1883,7 @@ function createCashClient(options) {
|
|
|
1864
1883
|
executed
|
|
1865
1884
|
);
|
|
1866
1885
|
} catch (err) {
|
|
1886
|
+
if (isCashError(err)) throw err;
|
|
1867
1887
|
throw errors.sourceRouteCompletedCashoutFailed(
|
|
1868
1888
|
routedSource,
|
|
1869
1889
|
mapChainError("resolve same-chain Relay nonce", err)
|
package/dist/index.js
CHANGED
|
@@ -1344,32 +1344,51 @@ function createCashClient(options) {
|
|
|
1344
1344
|
(transaction) => transaction.chainId === BASE_CHAIN_ID
|
|
1345
1345
|
);
|
|
1346
1346
|
const batchIds = baseTransactions.filter((transaction) => transaction.isBatchTx === true).map((transaction) => transaction.hash);
|
|
1347
|
+
const batchExecutionFailed = (cause) => errors.sourceExecutionFailed(cause, {
|
|
1348
|
+
...executed.requestId ? { requestId: executed.requestId } : {},
|
|
1349
|
+
txHashes: executed.txHashes,
|
|
1350
|
+
...executed.transactions ? { transactions: executed.transactions } : {}
|
|
1351
|
+
});
|
|
1347
1352
|
let batchTransactionHashes = [];
|
|
1348
1353
|
if (batchIds.length > 0) {
|
|
1349
1354
|
let batchError;
|
|
1350
1355
|
let batchesComplete = false;
|
|
1356
|
+
let batchesSucceededWithoutReceipts = false;
|
|
1351
1357
|
for (let attempt = 0; attempt < 20; attempt++) {
|
|
1352
1358
|
try {
|
|
1353
1359
|
const statuses = await Promise.all(
|
|
1354
1360
|
batchIds.map((id) => sourceSigner.getCallsStatus({ id }))
|
|
1355
1361
|
);
|
|
1356
1362
|
if (statuses.some((status) => status.status === "failure")) {
|
|
1357
|
-
throw new Error("Relay wallet call bundle failed");
|
|
1363
|
+
throw batchExecutionFailed(new Error("Relay wallet call bundle failed"));
|
|
1358
1364
|
}
|
|
1359
1365
|
if (statuses.every((status) => status.status === "success")) {
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1366
|
+
const receiptGroups = statuses.map((status) => status.receipts ?? []);
|
|
1367
|
+
if (receiptGroups.some((receipts) => receipts.length === 0)) {
|
|
1368
|
+
batchError = new Error(
|
|
1369
|
+
"Relay wallet call bundle did not include transaction receipts"
|
|
1370
|
+
);
|
|
1371
|
+
batchesSucceededWithoutReceipts = true;
|
|
1372
|
+
break;
|
|
1373
|
+
} else {
|
|
1374
|
+
batchTransactionHashes = receiptGroups.flatMap(
|
|
1375
|
+
(receipts) => receipts.map((receipt) => receipt.transactionHash)
|
|
1376
|
+
);
|
|
1377
|
+
batchesComplete = true;
|
|
1378
|
+
break;
|
|
1379
|
+
}
|
|
1365
1380
|
}
|
|
1366
1381
|
} catch (err) {
|
|
1382
|
+
if (isCashError(err)) throw err;
|
|
1367
1383
|
batchError = err;
|
|
1368
1384
|
}
|
|
1369
1385
|
await sleep(250);
|
|
1370
1386
|
}
|
|
1371
1387
|
if (!batchesComplete) {
|
|
1372
|
-
|
|
1388
|
+
if (batchesSucceededWithoutReceipts) throw batchError;
|
|
1389
|
+
throw batchExecutionFailed(
|
|
1390
|
+
batchError ?? new Error("Relay wallet call bundle did not complete")
|
|
1391
|
+
);
|
|
1373
1392
|
}
|
|
1374
1393
|
}
|
|
1375
1394
|
const hashes = [
|
|
@@ -1491,6 +1510,7 @@ function createCashClient(options) {
|
|
|
1491
1510
|
executed
|
|
1492
1511
|
);
|
|
1493
1512
|
} catch (err) {
|
|
1513
|
+
if (isCashError(err)) throw err;
|
|
1494
1514
|
throw errors.sourceRouteCompletedCashoutFailed(
|
|
1495
1515
|
routedSource,
|
|
1496
1516
|
mapChainError("resolve same-chain Relay nonce", err)
|
package/dist/tools.cjs
CHANGED
package/dist/tools.js
CHANGED
package/llms.txt
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
> Offramp-only SDK for the ZKP2P protocol: route any Relay-supported EVM source
|
|
4
4
|
> asset to Base USDC, then cash out to fiat (Venmo, Revolut, Wise, Zelle, ...)
|
|
5
5
|
> at the live Chainlink oracle market rate with zero spread and no centralized
|
|
6
|
-
> off-ramp provider. The user is the maker,
|
|
7
|
-
> SDK exposes readable order state.
|
|
6
|
+
> off-ramp provider. The user is the maker, a buyer pays them fiat and proves
|
|
7
|
+
> the payment, and the SDK exposes readable order state.
|
|
8
8
|
> Base-USDC flows are serializable through prepare paths; source-routed cashout
|
|
9
9
|
> uses Relay execution first. React apps, Node services, and agent hosts use the
|
|
10
10
|
> same typed surface.
|
|
@@ -59,9 +59,8 @@ Key facts:
|
|
|
59
59
|
|
|
60
60
|
## Links
|
|
61
61
|
|
|
62
|
-
- Live demo: https://react-cashout-demo.vercel.app
|
|
63
|
-
- Product page: https://peer.xyz/cash
|
|
64
62
|
- npm: https://www.npmjs.com/package/@zkp2p/cash
|
|
63
|
+
- Source: https://github.com/zkp2p/peer-cash
|
|
65
64
|
|
|
66
65
|
## Docs
|
|
67
66
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zkp2p/cash",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
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)",
|
|
@@ -12,7 +12,14 @@
|
|
|
12
12
|
"publishConfig": {
|
|
13
13
|
"access": "public"
|
|
14
14
|
},
|
|
15
|
-
"homepage": "https://
|
|
15
|
+
"homepage": "https://github.com/zkp2p/peer-cash#readme",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/zkp2p/peer-cash.git"
|
|
19
|
+
},
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/zkp2p/peer-cash/issues"
|
|
22
|
+
},
|
|
16
23
|
"keywords": [
|
|
17
24
|
"zkp2p",
|
|
18
25
|
"peer",
|
|
@@ -98,7 +105,7 @@
|
|
|
98
105
|
"dependencies": {
|
|
99
106
|
"@relayprotocol/relay-sdk": "^6.1.3",
|
|
100
107
|
"@zkp2p/sdk": "^0.8.1",
|
|
101
|
-
"zod": "^3.
|
|
108
|
+
"zod": "^3.25.76"
|
|
102
109
|
},
|
|
103
110
|
"peerDependencies": {
|
|
104
111
|
"react": ">=18",
|
|
@@ -110,19 +117,19 @@
|
|
|
110
117
|
}
|
|
111
118
|
},
|
|
112
119
|
"devDependencies": {
|
|
113
|
-
"@eslint/js": "^9.
|
|
114
|
-
"@types/node": "^22.
|
|
115
|
-
"@types/react": "^19.
|
|
120
|
+
"@eslint/js": "^9.39.5",
|
|
121
|
+
"@types/node": "^22.20.1",
|
|
122
|
+
"@types/react": "^19.2.17",
|
|
116
123
|
"@types/react-test-renderer": "19.1.0",
|
|
117
|
-
"eslint": "^9.
|
|
118
|
-
"eslint-config-prettier": "^9.1.
|
|
119
|
-
"prettier": "^3.
|
|
120
|
-
"react": "^19.
|
|
124
|
+
"eslint": "^9.39.5",
|
|
125
|
+
"eslint-config-prettier": "^9.1.2",
|
|
126
|
+
"prettier": "^3.9.5",
|
|
127
|
+
"react": "^19.2.7",
|
|
121
128
|
"react-test-renderer": "19.2.7",
|
|
122
|
-
"tsup": "^8.
|
|
123
|
-
"typescript": "^5.
|
|
124
|
-
"typescript-eslint": "^8.
|
|
125
|
-
"viem": "^2.55.
|
|
129
|
+
"tsup": "^8.5.1",
|
|
130
|
+
"typescript": "^5.9.3",
|
|
131
|
+
"typescript-eslint": "^8.63.0",
|
|
132
|
+
"viem": "^2.55.1",
|
|
126
133
|
"vitest": "^4.1.10"
|
|
127
134
|
}
|
|
128
135
|
}
|