@zkp2p/cash 0.1.4 → 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/dist/index.js CHANGED
@@ -607,10 +607,18 @@ function collectRelayTransactions(steps, sourceChainId) {
607
607
  for (const step of steps) {
608
608
  for (const item of step.items) {
609
609
  for (const tx of item.internalTxHashes ?? []) {
610
- record({ hash: tx.txHash, chainId: tx.chainId });
610
+ record({
611
+ hash: tx.txHash,
612
+ chainId: tx.chainId,
613
+ ...tx.isBatchTx ? { isBatchTx: true } : {}
614
+ });
611
615
  }
612
616
  for (const tx of item.txHashes ?? []) {
613
- record({ hash: tx.txHash, chainId: tx.chainId });
617
+ record({
618
+ hash: tx.txHash,
619
+ chainId: tx.chainId,
620
+ ...tx.isBatchTx ? { isBatchTx: true } : {}
621
+ });
614
622
  }
615
623
  }
616
624
  }
@@ -1330,6 +1338,97 @@ function createCashClient(options) {
1330
1338
  }
1331
1339
  throw errors.allowanceNotVisible(amount, lastReadError);
1332
1340
  }
1341
+ async function waitForBaseSignerAfterRelay(client, cashoutSigner, sourceSigner, owner, sourceChainId, executed) {
1342
+ if (sourceChainId !== BASE_CHAIN_ID) return;
1343
+ const baseTransactions = (executed.transactions?.origin ?? []).filter(
1344
+ (transaction) => transaction.chainId === BASE_CHAIN_ID
1345
+ );
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
+ });
1352
+ let batchTransactionHashes = [];
1353
+ if (batchIds.length > 0) {
1354
+ let batchError;
1355
+ let batchesComplete = false;
1356
+ let batchesSucceededWithoutReceipts = false;
1357
+ for (let attempt = 0; attempt < 20; attempt++) {
1358
+ try {
1359
+ const statuses = await Promise.all(
1360
+ batchIds.map((id) => sourceSigner.getCallsStatus({ id }))
1361
+ );
1362
+ if (statuses.some((status) => status.status === "failure")) {
1363
+ throw batchExecutionFailed(new Error("Relay wallet call bundle failed"));
1364
+ }
1365
+ if (statuses.every((status) => status.status === "success")) {
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
+ }
1380
+ }
1381
+ } catch (err) {
1382
+ if (isCashError(err)) throw err;
1383
+ batchError = err;
1384
+ }
1385
+ await sleep(250);
1386
+ }
1387
+ if (!batchesComplete) {
1388
+ if (batchesSucceededWithoutReceipts) throw batchError;
1389
+ throw batchExecutionFailed(
1390
+ batchError ?? new Error("Relay wallet call bundle did not complete")
1391
+ );
1392
+ }
1393
+ }
1394
+ const hashes = [
1395
+ ...baseTransactions.filter((transaction) => transaction.isBatchTx !== true).map((transaction) => transaction.hash),
1396
+ ...batchTransactionHashes
1397
+ ];
1398
+ if (hashes.length === 0) return;
1399
+ let transactions;
1400
+ let lastLookupError;
1401
+ for (let attempt = 0; attempt < 20; attempt++) {
1402
+ try {
1403
+ transactions = await Promise.all(
1404
+ hashes.map((hash) => client.publicClient.getTransaction({ hash }))
1405
+ );
1406
+ break;
1407
+ } catch (err) {
1408
+ lastLookupError = err;
1409
+ await sleep(250);
1410
+ }
1411
+ }
1412
+ if (!transactions) throw lastLookupError;
1413
+ const ownerNonces = transactions.filter((transaction) => transaction.from.toLowerCase() === owner.toLowerCase()).map((transaction) => transaction.nonce);
1414
+ if (ownerNonces.length === 0) return;
1415
+ const afterRelay = Math.max(...ownerNonces) + 1;
1416
+ let lastNonceError;
1417
+ for (let attempt = 0; attempt < 20; attempt++) {
1418
+ try {
1419
+ const pendingHex = await cashoutSigner.transport.request({
1420
+ method: "eth_getTransactionCount",
1421
+ params: [owner, "pending"]
1422
+ });
1423
+ if (Number(BigInt(pendingHex)) >= afterRelay) return;
1424
+ } catch (err) {
1425
+ lastNonceError = err;
1426
+ }
1427
+ await sleep(250);
1428
+ }
1429
+ if (lastNonceError) throw lastNonceError;
1430
+ throw new Error(`Signer provider did not observe Relay nonce ${afterRelay - 1}`);
1431
+ }
1333
1432
  return {
1334
1433
  capabilities,
1335
1434
  async sourceCapabilities() {
@@ -1401,6 +1500,22 @@ function createCashClient(options) {
1401
1500
  ...executed.transactions ? { transactions: executed.transactions } : {}
1402
1501
  };
1403
1502
  sourceResult = routedSource;
1503
+ try {
1504
+ await waitForBaseSignerAfterRelay(
1505
+ client,
1506
+ opts.signer,
1507
+ sourceSigner,
1508
+ owner,
1509
+ input.source.chainId,
1510
+ executed
1511
+ );
1512
+ } catch (err) {
1513
+ if (isCashError(err)) throw err;
1514
+ throw errors.sourceRouteCompletedCashoutFailed(
1515
+ routedSource,
1516
+ mapChainError("resolve same-chain Relay nonce", err)
1517
+ );
1518
+ }
1404
1519
  const attributedParams2 = { ...params2, txOverrides: attribution };
1405
1520
  const send2 = async () => {
1406
1521
  try {
@@ -1773,7 +1888,8 @@ var bigintString = z.string().regex(/^-?\d+$/, "expected a decimal bigint string
1773
1888
  var nonNegativeBigintString = z.string().regex(/^\d+$/, "expected a non-negative decimal bigint string");
1774
1889
  var relayTransactionJsonSchema = z.object({
1775
1890
  hash: z.string(),
1776
- chainId: z.number()
1891
+ chainId: z.number(),
1892
+ isBatchTx: z.boolean().optional()
1777
1893
  });
1778
1894
  var relayTransactionsJsonSchema = z.object({
1779
1895
  origin: z.array(relayTransactionJsonSchema),
package/dist/react.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { CurrencyType } from '@zkp2p/sdk';
2
- import { q as CashClient, E as EstimateInput, i as CashEstimate, B as CashoutOptions, h as CashoutResult, A as CashoutInput, T as TopUpResult, W as WithdrawResult, e as CashOrder } from './createCashClient-BbkfxILl.cjs';
2
+ import { q as CashClient, E as EstimateInput, i as CashEstimate, B as CashoutOptions, h as CashoutResult, A as CashoutInput, T as TopUpResult, W as WithdrawResult, e as CashOrder } from './createCashClient-jUA_GNdh.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 { q as CashClient, E as EstimateInput, i as CashEstimate, B as CashoutOptions, h as CashoutResult, A as CashoutInput, T as TopUpResult, W as WithdrawResult, e as CashOrder } from './createCashClient-BbkfxILl.js';
2
+ import { q as CashClient, E as EstimateInput, i as CashEstimate, B as CashoutOptions, h as CashoutResult, A as CashoutInput, T as TopUpResult, W as WithdrawResult, e as CashOrder } from './createCashClient-jUA_GNdh.js';
3
3
  import { WalletClient } from 'viem';
4
4
  import '@relayprotocol/relay-sdk';
5
5
 
package/dist/tools.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // package.json
4
4
  var package_default = {
5
- version: "0.1.4"};
5
+ version: "0.1.6"};
6
6
 
7
7
  // src/tools/index.ts
8
8
  var bigintString = {
package/dist/tools.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // package.json
2
2
  var package_default = {
3
- version: "0.1.4"};
3
+ version: "0.1.6"};
4
4
 
5
5
  // src/tools/index.ts
6
6
  var bigintString = {
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, Peer handles the buyer side, and the
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.4",
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://peer.xyz/cash",
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.24.1"
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.17.0",
114
- "@types/node": "^22.10.2",
115
- "@types/react": "^19.0.2",
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.17.0",
118
- "eslint-config-prettier": "^9.1.0",
119
- "prettier": "^3.4.2",
120
- "react": "^19.0.0",
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.3.5",
123
- "typescript": "^5.7.2",
124
- "typescript-eslint": "^8.18.1",
125
- "viem": "^2.55.0",
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
  }