@zkp2p/cash 0.1.0-dev.0
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 +131 -0
- package/LICENSE +21 -0
- package/README.md +138 -0
- package/dist/chunk-4DRZRWWS.js +176 -0
- package/dist/chunk-4DRZRWWS.js.map +1 -0
- package/dist/createCashClient-DpAx9A1A.d.cts +449 -0
- package/dist/createCashClient-DpAx9A1A.d.ts +449 -0
- package/dist/index.cjs +1572 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1367 -0
- package/dist/index.d.ts +1367 -0
- package/dist/index.js +1322 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +292 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +97 -0
- package/dist/react.d.ts +97 -0
- package/dist/react.js +258 -0
- package/dist/react.js.map +1 -0
- package/dist/tools.cjs +148 -0
- package/dist/tools.cjs.map +1 -0
- package/dist/tools.d.cts +31 -0
- package/dist/tools.d.ts +31 -0
- package/dist/tools.js +145 -0
- package/dist/tools.js.map +1 -0
- package/package.json +89 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1572 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var viem = require('viem');
|
|
4
|
+
var chains = require('viem/chains');
|
|
5
|
+
var sdk = require('@zkp2p/sdk');
|
|
6
|
+
var zod = require('zod');
|
|
7
|
+
|
|
8
|
+
// src/client/createCashClient.ts
|
|
9
|
+
|
|
10
|
+
// src/engine/constants.ts
|
|
11
|
+
var BASE_CHAIN_ID = 8453;
|
|
12
|
+
var BASE_USDC_ADDRESS = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913";
|
|
13
|
+
var USDC_DECIMALS = 6;
|
|
14
|
+
var MARKET_SPREAD_BPS = 0;
|
|
15
|
+
var ORACLE_MIN_CONVERSION_RATE_SENTINEL = 1n;
|
|
16
|
+
var CASH_ORDER_STATUSES = [
|
|
17
|
+
"SIGNALED",
|
|
18
|
+
"FULFILLED",
|
|
19
|
+
"PRUNED",
|
|
20
|
+
"MANUALLY_RELEASED"
|
|
21
|
+
];
|
|
22
|
+
var CASH_ORDER_POLL_INTERVAL_MS = 5e3;
|
|
23
|
+
var CASH_RETAIN_ON_EMPTY = false;
|
|
24
|
+
function isMarketRateSupported(currency, adapters) {
|
|
25
|
+
return sdk.getSpreadOracleConfig(currency, adapters) != null;
|
|
26
|
+
}
|
|
27
|
+
function buildMarketRateCurrencyOverride(currency, adapters) {
|
|
28
|
+
const code = sdk.currencyInfo[currency]?.currencyCodeHash;
|
|
29
|
+
const oracle = sdk.getSpreadOracleConfig(currency, adapters);
|
|
30
|
+
if (!code || !oracle) return null;
|
|
31
|
+
return {
|
|
32
|
+
code,
|
|
33
|
+
minConversionRate: ORACLE_MIN_CONVERSION_RATE_SENTINEL,
|
|
34
|
+
oracleRateConfig: {
|
|
35
|
+
adapter: oracle.adapter,
|
|
36
|
+
adapterConfig: oracle.adapterConfig,
|
|
37
|
+
spreadBps: MARKET_SPREAD_BPS,
|
|
38
|
+
maxStaleness: oracle.maxStaleness
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
var DEFAULT_MIN_ORDER_FLOOR = 1000000n;
|
|
43
|
+
function buildIntentAmountRange(amount) {
|
|
44
|
+
if (amount <= 0n) throw new Error("Cash-out amount must be positive");
|
|
45
|
+
const min = amount < DEFAULT_MIN_ORDER_FLOOR ? amount : DEFAULT_MIN_ORDER_FLOOR;
|
|
46
|
+
return { min, max: amount };
|
|
47
|
+
}
|
|
48
|
+
async function prepareCashDepositParams(client, input, adapters) {
|
|
49
|
+
const { payouts } = input;
|
|
50
|
+
if (!payouts.length) throw new Error("At least one payout is required");
|
|
51
|
+
const chainId = client.chainId;
|
|
52
|
+
const runtimeEnv = client.runtimeEnv;
|
|
53
|
+
const catalog = sdk.getPaymentMethodsCatalog(chainId, runtimeEnv);
|
|
54
|
+
const intentGatingService = sdk.getGatingServiceAddress(chainId, runtimeEnv);
|
|
55
|
+
for (const payout of payouts) {
|
|
56
|
+
if (!isMarketRateSupported(payout.currency, adapters)) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
`${payout.currency} has no live market-rate oracle feed; Peer Cash supports market-rate currencies only.`
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const processorNames = payouts.map((p) => p.processorName);
|
|
63
|
+
const { hashedOnchainIds } = await client.registerPayeeDetails({
|
|
64
|
+
processorNames,
|
|
65
|
+
payeeData: payouts.map((p) => p.payeeData)
|
|
66
|
+
});
|
|
67
|
+
if (hashedOnchainIds.length !== payouts.length) {
|
|
68
|
+
throw new Error("Payee registration returned an unexpected number of hashes");
|
|
69
|
+
}
|
|
70
|
+
const paymentMethodsOverride = processorNames.map(
|
|
71
|
+
(name) => sdk.resolvePaymentMethodHashFromCatalog(name, catalog)
|
|
72
|
+
);
|
|
73
|
+
const paymentMethodDataOverride = hashedOnchainIds.map((hid) => ({
|
|
74
|
+
intentGatingService,
|
|
75
|
+
payeeDetails: hid,
|
|
76
|
+
data: "0x"
|
|
77
|
+
}));
|
|
78
|
+
const currenciesOverride = payouts.map((p) => {
|
|
79
|
+
const tuple = buildMarketRateCurrencyOverride(p.currency, adapters);
|
|
80
|
+
if (!tuple) throw new Error(`Failed to build market-rate config for ${p.currency}`);
|
|
81
|
+
return [tuple];
|
|
82
|
+
});
|
|
83
|
+
const conversionRates = payouts.map((p) => [
|
|
84
|
+
{ currency: p.currency, conversionRate: ORACLE_MIN_CONVERSION_RATE_SENTINEL.toString() }
|
|
85
|
+
]);
|
|
86
|
+
const intentAmountRange = input.intentAmountRange ?? buildIntentAmountRange(input.amount);
|
|
87
|
+
return {
|
|
88
|
+
token: input.token ?? BASE_USDC_ADDRESS,
|
|
89
|
+
amount: input.amount,
|
|
90
|
+
intentAmountRange,
|
|
91
|
+
processorNames,
|
|
92
|
+
conversionRates,
|
|
93
|
+
paymentMethodsOverride,
|
|
94
|
+
paymentMethodDataOverride,
|
|
95
|
+
currenciesOverride,
|
|
96
|
+
retainOnEmpty: CASH_RETAIN_ON_EMPTY
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// src/internal/convert.ts
|
|
101
|
+
function toBigInt(value) {
|
|
102
|
+
return toBigIntOrUndefined(value) ?? 0n;
|
|
103
|
+
}
|
|
104
|
+
function toBigIntOrUndefined(value) {
|
|
105
|
+
if (value === null || value === void 0 || value === "") return void 0;
|
|
106
|
+
try {
|
|
107
|
+
return BigInt(typeof value === "number" ? Math.trunc(value) : String(value));
|
|
108
|
+
} catch {
|
|
109
|
+
return void 0;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// src/engine/amounts.ts
|
|
114
|
+
function usdc(amount) {
|
|
115
|
+
const text = typeof amount === "number" ? amount.toString() : amount.trim();
|
|
116
|
+
if (!/^\d+(\.\d+)?$/.test(text)) {
|
|
117
|
+
throw new Error(`Invalid USDC amount: '${amount}'`);
|
|
118
|
+
}
|
|
119
|
+
const [whole = "0", frac = ""] = text.split(".");
|
|
120
|
+
if (frac.length > USDC_DECIMALS) {
|
|
121
|
+
throw new Error(`USDC has ${USDC_DECIMALS} decimals; '${amount}' has too many`);
|
|
122
|
+
}
|
|
123
|
+
return BigInt(whole) * 10n ** BigInt(USDC_DECIMALS) + BigInt(frac.padEnd(USDC_DECIMALS, "0") || "0");
|
|
124
|
+
}
|
|
125
|
+
function formatUsdc(amount) {
|
|
126
|
+
const negative = amount < 0n;
|
|
127
|
+
const abs = negative ? -amount : amount;
|
|
128
|
+
const whole = abs / 10n ** BigInt(USDC_DECIMALS);
|
|
129
|
+
const frac = (abs % 10n ** BigInt(USDC_DECIMALS)).toString().padStart(USDC_DECIMALS, "0");
|
|
130
|
+
const trimmed = frac.replace(/0+$/, "");
|
|
131
|
+
return `${negative ? "-" : ""}${whole}${trimmed ? `.${trimmed}` : ""}`;
|
|
132
|
+
}
|
|
133
|
+
var RATE_PRECISION = 10n ** 18n;
|
|
134
|
+
function fiatFromUsdc(amount, conversionRate) {
|
|
135
|
+
const raw = amount * conversionRate / RATE_PRECISION;
|
|
136
|
+
const penny = 10n ** BigInt(USDC_DECIMALS - 2);
|
|
137
|
+
const remainder = raw % penny;
|
|
138
|
+
return remainder > 0n ? raw - remainder + penny : raw;
|
|
139
|
+
}
|
|
140
|
+
function rateToNumber(conversionRate) {
|
|
141
|
+
return Number(conversionRate) / 1e18;
|
|
142
|
+
}
|
|
143
|
+
function fiatToNumber(fiat) {
|
|
144
|
+
return Number(fiat) / 10 ** USDC_DECIMALS;
|
|
145
|
+
}
|
|
146
|
+
function centsToNumber(cents) {
|
|
147
|
+
return Number(cents) / 100;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// src/engine/orderState.ts
|
|
151
|
+
var DUST_THRESHOLD = 10000n;
|
|
152
|
+
function toUnixSeconds(value) {
|
|
153
|
+
if (value === null || value === void 0 || value === "") return void 0;
|
|
154
|
+
const n = Number(value);
|
|
155
|
+
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
156
|
+
}
|
|
157
|
+
var FULFILLED_STATUSES = /* @__PURE__ */ new Set([
|
|
158
|
+
"FULFILLED",
|
|
159
|
+
"MANUALLY_RELEASED"
|
|
160
|
+
]);
|
|
161
|
+
function toFill(intent) {
|
|
162
|
+
const signaledAt = toUnixSeconds(intent.signalTimestamp);
|
|
163
|
+
const expiresAt = toUnixSeconds(intent.expiryTime);
|
|
164
|
+
const fulfilledAt = toUnixSeconds(intent.fulfillTimestamp);
|
|
165
|
+
const prunedAt = toUnixSeconds(intent.prunedTimestamp ?? intent.pruneTimestamp);
|
|
166
|
+
const paidAt = toUnixSeconds(intent.paymentTimestamp);
|
|
167
|
+
const amount = toBigInt(intent.amount);
|
|
168
|
+
const conversionRate = toBigIntOrUndefined(intent.conversionRate);
|
|
169
|
+
const currency = intent.fiatCurrency != null ? sdk.getCurrencyCodeFromHash(intent.fiatCurrency) : void 0;
|
|
170
|
+
const paidCurrency = intent.paymentCurrency != null ? sdk.getCurrencyCodeFromHash(intent.paymentCurrency) : void 0;
|
|
171
|
+
const paymentCents = toBigIntOrUndefined(intent.paymentAmount);
|
|
172
|
+
const releasedAmount = toBigIntOrUndefined(intent.releasedAmount);
|
|
173
|
+
const fillLatencySeconds = signaledAt !== void 0 && fulfilledAt !== void 0 && fulfilledAt >= signaledAt ? fulfilledAt - signaledAt : void 0;
|
|
174
|
+
return {
|
|
175
|
+
intentHash: intent.intentHash,
|
|
176
|
+
status: intent.status,
|
|
177
|
+
amount,
|
|
178
|
+
buyer: (intent.owner ?? "").toLowerCase(),
|
|
179
|
+
...currency !== void 0 ? { currency } : {},
|
|
180
|
+
...intent.fiatCurrency != null ? { currencyHash: intent.fiatCurrency } : {},
|
|
181
|
+
...conversionRate !== void 0 && conversionRate > 0n ? {
|
|
182
|
+
conversionRate,
|
|
183
|
+
rate: rateToNumber(conversionRate),
|
|
184
|
+
fiatOwed: fiatToNumber(fiatFromUsdc(amount, conversionRate))
|
|
185
|
+
} : {},
|
|
186
|
+
...paymentCents !== void 0 && paymentCents > 0n ? { fiatPaid: centsToNumber(paymentCents) } : {},
|
|
187
|
+
...paidCurrency !== void 0 ? { paidCurrency } : {},
|
|
188
|
+
...intent.paymentId != null && intent.paymentId !== "" ? { paymentId: intent.paymentId } : {},
|
|
189
|
+
...paidAt !== void 0 ? { paidAt } : {},
|
|
190
|
+
...releasedAmount !== void 0 && releasedAmount > 0n ? { releasedAmount } : {},
|
|
191
|
+
...fillLatencySeconds !== void 0 ? { fillLatencySeconds } : {},
|
|
192
|
+
...intent.isExpired != null ? { isExpired: intent.isExpired } : {},
|
|
193
|
+
...signaledAt !== void 0 ? { signaledAt } : {},
|
|
194
|
+
...expiresAt !== void 0 ? { expiresAt } : {},
|
|
195
|
+
...fulfilledAt !== void 0 ? { fulfilledAt } : {},
|
|
196
|
+
...prunedAt !== void 0 ? { prunedAt } : {}
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function isFillLive(fill, nowSeconds) {
|
|
200
|
+
if (fill.status !== "SIGNALED") return false;
|
|
201
|
+
if (fill.isExpired === true) return false;
|
|
202
|
+
return fill.expiresAt === void 0 || fill.expiresAt > nowSeconds;
|
|
203
|
+
}
|
|
204
|
+
function fmtUsdc(amount) {
|
|
205
|
+
return `${formatUsdc(amount)} USDC`;
|
|
206
|
+
}
|
|
207
|
+
function explainOrder(order) {
|
|
208
|
+
switch (order.state) {
|
|
209
|
+
case "awaiting-buyer":
|
|
210
|
+
return `Your ${fmtUsdc(order.totalAmount)} cash-out is live and waiting for a buyer; you can withdraw it any time before a buyer commits.`;
|
|
211
|
+
case "matched":
|
|
212
|
+
return `A buyer committed to ${fmtUsdc(order.pendingAmount)} and is sending fiat now; funds release automatically once their payment is proven.`;
|
|
213
|
+
case "delivering":
|
|
214
|
+
return `${fmtUsdc(order.filledAmount)} of ${fmtUsdc(order.totalAmount)} has been delivered; the rest is ${order.pendingAmount > 0n ? "locked by an active buyer" : "still waiting for a buyer"}.`;
|
|
215
|
+
case "delivered":
|
|
216
|
+
return `Cash-out complete: ${fmtUsdc(order.filledAmount)} was delivered to ${order.fills.filter((f) => f.fulfilledAt !== void 0).length || "your"} buyer fill(s).`;
|
|
217
|
+
case "returned":
|
|
218
|
+
return order.filledAmount > 0n ? `${fmtUsdc(order.filledAmount)} was delivered and the remaining ${fmtUsdc(order.returnedAmount)} was returned to your wallet.` : `No buyer delivered; ${fmtUsdc(order.returnedAmount)} was returned to your wallet.`;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function withExplain(data) {
|
|
222
|
+
return { ...data, explain: () => explainOrder(data) };
|
|
223
|
+
}
|
|
224
|
+
function deriveNextActions(state, hasLiveIntent) {
|
|
225
|
+
if (state === "delivered" || state === "returned") return [];
|
|
226
|
+
if (state === "awaiting-buyer") return ["wait", "withdraw"];
|
|
227
|
+
return hasLiveIntent ? ["wait"] : ["wait", "withdraw"];
|
|
228
|
+
}
|
|
229
|
+
function deriveCashOrder(depositId, intents, options = {}) {
|
|
230
|
+
const fills = intents.map(toFill);
|
|
231
|
+
const taken = options.takenAmount ?? fills.filter((f) => FULFILLED_STATUSES.has(f.status)).reduce((a, f) => a + f.amount, 0n);
|
|
232
|
+
const outstanding = options.outstandingAmount ?? fills.filter((f) => f.status === "SIGNALED").reduce((a, f) => a + f.amount, 0n);
|
|
233
|
+
const withdrawn = options.withdrawnAmount ?? 0n;
|
|
234
|
+
const remaining = options.remainingAmount ?? 0n;
|
|
235
|
+
const total = options.totalAmount ?? remaining + outstanding + taken + withdrawn;
|
|
236
|
+
const status = options.status;
|
|
237
|
+
const isTerminal = status === "CLOSED" || status === "WITHDRAWN";
|
|
238
|
+
const hasLiveFunds = remaining > DUST_THRESHOLD || outstanding > 0n;
|
|
239
|
+
let state;
|
|
240
|
+
if (outstanding > 0n) {
|
|
241
|
+
state = taken > 0n ? "delivering" : "matched";
|
|
242
|
+
} else if (taken > 0n && !hasLiveFunds) {
|
|
243
|
+
state = "delivered";
|
|
244
|
+
} else if (taken > 0n && hasLiveFunds) {
|
|
245
|
+
state = "delivering";
|
|
246
|
+
} else if (!hasLiveFunds && (withdrawn > 0n || isTerminal)) {
|
|
247
|
+
state = "returned";
|
|
248
|
+
} else if (hasLiveFunds) {
|
|
249
|
+
state = "awaiting-buyer";
|
|
250
|
+
} else {
|
|
251
|
+
state = taken > 0n ? "delivered" : "returned";
|
|
252
|
+
}
|
|
253
|
+
let matchedAt;
|
|
254
|
+
let deliveredAt;
|
|
255
|
+
for (const fill of fills) {
|
|
256
|
+
if (fill.signaledAt && (!matchedAt || fill.signaledAt < matchedAt)) matchedAt = fill.signaledAt;
|
|
257
|
+
if (FULFILLED_STATUSES.has(fill.status) && fill.fulfilledAt) {
|
|
258
|
+
if (!deliveredAt || fill.fulfilledAt > deliveredAt) deliveredAt = fill.fulfilledAt;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
const primary = fills.find((f) => f.status === "SIGNALED") ?? fills.find((f) => FULFILLED_STATUSES.has(f.status)) ?? fills[0];
|
|
262
|
+
const isInFlight = state === "awaiting-buyer" || state === "matched" || state === "delivering";
|
|
263
|
+
const nowSeconds = options.nowSeconds ?? Math.floor(Date.now() / 1e3);
|
|
264
|
+
const fillsIncluded = options.fillsIncluded ?? fills.length > 0;
|
|
265
|
+
const hasLiveIntent = fillsIncluded ? fills.some((f) => isFillLive(f, nowSeconds)) : outstanding > 0n;
|
|
266
|
+
return withExplain({
|
|
267
|
+
depositId,
|
|
268
|
+
state,
|
|
269
|
+
fills,
|
|
270
|
+
totalAmount: total,
|
|
271
|
+
filledAmount: taken,
|
|
272
|
+
pendingAmount: outstanding,
|
|
273
|
+
returnedAmount: withdrawn,
|
|
274
|
+
nextActions: deriveNextActions(state, hasLiveIntent),
|
|
275
|
+
...primary?.intentHash !== void 0 ? { primaryIntentHash: primary.intentHash } : {},
|
|
276
|
+
...matchedAt !== void 0 ? { matchedAt } : {},
|
|
277
|
+
...deliveredAt !== void 0 ? { deliveredAt } : {},
|
|
278
|
+
...options.updatedAt !== void 0 ? { updatedAt: options.updatedAt } : {},
|
|
279
|
+
intentCount: options.intentCount ?? fills.length,
|
|
280
|
+
...options.payouts !== void 0 ? { payouts: options.payouts } : {},
|
|
281
|
+
...options.successRateBps !== void 0 ? { successRateBps: options.successRateBps } : {},
|
|
282
|
+
isInFlight,
|
|
283
|
+
withdrawn: isTerminal
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
var ORACLE_KINDS = /* @__PURE__ */ new Set(["oracle_chainlink", "oracle_pyth"]);
|
|
287
|
+
function toPricing(tuple) {
|
|
288
|
+
if (!tuple) return { marketRate: false };
|
|
289
|
+
const spreadBps = tuple.spreadBps != null ? Number(tuple.spreadBps) : void 0;
|
|
290
|
+
const oracleRate = toBigIntOrUndefined(tuple.oracleRate);
|
|
291
|
+
const lastOracleUpdatedAt = tuple.lastOracleUpdatedAt != null ? Number(tuple.lastOracleUpdatedAt) : void 0;
|
|
292
|
+
return {
|
|
293
|
+
...spreadBps !== void 0 && Number.isFinite(spreadBps) ? { spreadBps } : {},
|
|
294
|
+
...tuple.kind != null ? { kind: tuple.kind } : {},
|
|
295
|
+
...tuple.rateSource != null ? { rateSource: tuple.rateSource } : {},
|
|
296
|
+
...oracleRate !== void 0 && oracleRate > 0n ? { oracleRate: rateToNumber(oracleRate) } : {},
|
|
297
|
+
...lastOracleUpdatedAt !== void 0 && Number.isFinite(lastOracleUpdatedAt) ? { lastOracleUpdatedAt } : {},
|
|
298
|
+
marketRate: spreadBps === 0 && tuple.kind != null && ORACLE_KINDS.has(tuple.kind)
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
function derivePayouts(paymentMethods, currencies, catalog) {
|
|
302
|
+
return paymentMethods.flatMap((method) => {
|
|
303
|
+
const platformHash = method.paymentMethodHash ?? "";
|
|
304
|
+
if (!platformHash) return [];
|
|
305
|
+
let platform;
|
|
306
|
+
try {
|
|
307
|
+
platform = sdk.resolvePaymentMethodNameFromHash(platformHash, catalog);
|
|
308
|
+
} catch {
|
|
309
|
+
platform = void 0;
|
|
310
|
+
}
|
|
311
|
+
const tuples = currencies.filter(
|
|
312
|
+
(c) => (c.paymentMethodHash ?? "").toLowerCase() === platformHash.toLowerCase()
|
|
313
|
+
);
|
|
314
|
+
const base2 = {
|
|
315
|
+
...platform !== void 0 ? { platform } : {},
|
|
316
|
+
platformHash,
|
|
317
|
+
payeeHash: method.payeeDetailsHash ?? "",
|
|
318
|
+
active: method.active ?? true
|
|
319
|
+
};
|
|
320
|
+
if (tuples.length === 0) return [{ ...base2, pricing: toPricing(void 0) }];
|
|
321
|
+
return tuples.map((tuple) => {
|
|
322
|
+
const currency = tuple.currencyCode != null ? sdk.getCurrencyCodeFromHash(tuple.currencyCode) : void 0;
|
|
323
|
+
return {
|
|
324
|
+
...base2,
|
|
325
|
+
...currency !== void 0 ? { currency } : {},
|
|
326
|
+
...tuple.currencyCode != null ? { currencyHash: tuple.currencyCode } : {},
|
|
327
|
+
pricing: toPricing(tuple)
|
|
328
|
+
};
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// src/engine/buyerProfile.ts
|
|
334
|
+
function toSeconds(value) {
|
|
335
|
+
if (value === null || value === void 0 || value === "") return void 0;
|
|
336
|
+
const n = Number(value);
|
|
337
|
+
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
338
|
+
}
|
|
339
|
+
function deriveBuyerProfile(address, intents) {
|
|
340
|
+
let fulfilled = 0;
|
|
341
|
+
let pruned = 0;
|
|
342
|
+
let signaled = 0;
|
|
343
|
+
let firstSeenAt;
|
|
344
|
+
let lastSeenAt;
|
|
345
|
+
for (const intent of intents) {
|
|
346
|
+
const status = intent.status ?? "";
|
|
347
|
+
if (status === "FULFILLED" || status === "MANUALLY_RELEASED") fulfilled += 1;
|
|
348
|
+
else if (status === "PRUNED") pruned += 1;
|
|
349
|
+
else if (status === "SIGNALED") signaled += 1;
|
|
350
|
+
const at = toSeconds(intent.signalTimestamp);
|
|
351
|
+
if (at !== void 0) {
|
|
352
|
+
if (firstSeenAt === void 0 || at < firstSeenAt) firstSeenAt = at;
|
|
353
|
+
if (lastSeenAt === void 0 || at > lastSeenAt) lastSeenAt = at;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
const settled = fulfilled + pruned;
|
|
357
|
+
return {
|
|
358
|
+
address: address.toLowerCase(),
|
|
359
|
+
totalIntents: intents.length,
|
|
360
|
+
fulfilled,
|
|
361
|
+
pruned,
|
|
362
|
+
signaled,
|
|
363
|
+
...settled > 0 ? { successRateBps: Math.round(fulfilled / settled * 1e4) } : {},
|
|
364
|
+
...firstSeenAt !== void 0 ? { firstSeenAt } : {},
|
|
365
|
+
...lastSeenAt !== void 0 ? { lastSeenAt } : {}
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
function resolveCashDepositId(params) {
|
|
369
|
+
let events;
|
|
370
|
+
try {
|
|
371
|
+
events = viem.parseEventLogs({
|
|
372
|
+
abi: params.abi,
|
|
373
|
+
eventName: "DepositReceived",
|
|
374
|
+
logs: params.logs
|
|
375
|
+
});
|
|
376
|
+
} catch {
|
|
377
|
+
return null;
|
|
378
|
+
}
|
|
379
|
+
const event = events[0];
|
|
380
|
+
if (!event) return null;
|
|
381
|
+
const rawId = event.args.depositId;
|
|
382
|
+
if (rawId === void 0 || rawId === null) return null;
|
|
383
|
+
const onchainDepositId = BigInt(rawId);
|
|
384
|
+
const escrowAddress = event.address.toLowerCase();
|
|
385
|
+
return {
|
|
386
|
+
onchainDepositId,
|
|
387
|
+
escrowAddress,
|
|
388
|
+
compositeId: sdk.createCompositeDepositId(escrowAddress, onchainDepositId)
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
function parseCompositeDepositId(compositeId) {
|
|
392
|
+
const idx = compositeId.lastIndexOf("_");
|
|
393
|
+
if (idx === -1) {
|
|
394
|
+
return { escrowAddress: "", onchainDepositId: BigInt(compositeId) };
|
|
395
|
+
}
|
|
396
|
+
const escrowAddress = compositeId.slice(0, idx);
|
|
397
|
+
const onchainDepositId = BigInt(compositeId.slice(idx + 1) || "0");
|
|
398
|
+
return { escrowAddress, onchainDepositId };
|
|
399
|
+
}
|
|
400
|
+
var MIN_CASHOUT_AMOUNT = 10000n;
|
|
401
|
+
var RECOMMENDED_MIN_CASHOUT_AMOUNT = 1000000n;
|
|
402
|
+
var PAYEE_HINTS = {
|
|
403
|
+
venmo: "Venmo username, with or without the leading @ (e.g. @andrew-w)",
|
|
404
|
+
cashapp: "Cashtag, with or without the leading $ (e.g. $andrew)",
|
|
405
|
+
revolut: "Revtag (e.g. andrew1abc)",
|
|
406
|
+
wise: "Wisetag or the email on the Wise account",
|
|
407
|
+
zelle: "Email address or US phone number enrolled with Zelle",
|
|
408
|
+
paypal: "PayPal.Me handle or account email",
|
|
409
|
+
mercadopago: "Mercado Pago alias or CVU",
|
|
410
|
+
monzo: "Monzo.me username",
|
|
411
|
+
chime: "ChimeSign (e.g. $andrew)",
|
|
412
|
+
luxon: "Luxon Pay ID or account email",
|
|
413
|
+
n26: "MoneyBeam email or phone number"
|
|
414
|
+
};
|
|
415
|
+
var IDENTITY_ATTESTATION_PLATFORMS = /* @__PURE__ */ new Set(["wise", "paypal"]);
|
|
416
|
+
function platformRequiresIdentityAttestation(platform) {
|
|
417
|
+
return IDENTITY_ATTESTATION_PLATFORMS.has(platform);
|
|
418
|
+
}
|
|
419
|
+
function buildCapabilities(environment) {
|
|
420
|
+
const catalog = sdk.getPaymentMethodsCatalog(BASE_CHAIN_ID, environment);
|
|
421
|
+
const platforms = Object.entries(catalog).map(([platform, entry]) => {
|
|
422
|
+
const currencies2 = (entry.currencies ?? []).map((hash) => sdk.getCurrencyCodeFromHash(hash)).filter(
|
|
423
|
+
(code) => code != null && isMarketRateSupported(code)
|
|
424
|
+
);
|
|
425
|
+
return {
|
|
426
|
+
platform,
|
|
427
|
+
currencies: [...new Set(currencies2)],
|
|
428
|
+
payeeHint: PAYEE_HINTS[platform] ?? "Your payment handle for this platform",
|
|
429
|
+
requiresIdentityAttestation: IDENTITY_ATTESTATION_PLATFORMS.has(platform)
|
|
430
|
+
};
|
|
431
|
+
}).filter((p) => p.currencies.length > 0).sort((a, b) => a.platform.localeCompare(b.platform));
|
|
432
|
+
const currencies = [...new Set(platforms.flatMap((p) => p.currencies))].sort();
|
|
433
|
+
return {
|
|
434
|
+
chainId: BASE_CHAIN_ID,
|
|
435
|
+
token: { address: BASE_USDC_ADDRESS, symbol: "USDC", decimals: USDC_DECIMALS },
|
|
436
|
+
environment,
|
|
437
|
+
platforms,
|
|
438
|
+
currencies,
|
|
439
|
+
amount: { min: MIN_CASHOUT_AMOUNT, recommendedMin: RECOMMENDED_MIN_CASHOUT_AMOUNT, max: null },
|
|
440
|
+
pricing: { kind: "oracle-market-rate", spreadBps: 0 }
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// src/client/errors.ts
|
|
445
|
+
var CashError = class extends Error {
|
|
446
|
+
code;
|
|
447
|
+
retryable;
|
|
448
|
+
remediation;
|
|
449
|
+
constructor(shape, options) {
|
|
450
|
+
super(shape.message, options);
|
|
451
|
+
this.name = "CashError";
|
|
452
|
+
this.code = shape.code;
|
|
453
|
+
this.retryable = shape.retryable;
|
|
454
|
+
this.remediation = shape.remediation;
|
|
455
|
+
}
|
|
456
|
+
/** Serializable view (for tool results and logs). */
|
|
457
|
+
toJSON() {
|
|
458
|
+
return {
|
|
459
|
+
code: this.code,
|
|
460
|
+
message: this.message,
|
|
461
|
+
retryable: this.retryable,
|
|
462
|
+
remediation: this.remediation
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
function isCashError(value) {
|
|
467
|
+
return value instanceof CashError;
|
|
468
|
+
}
|
|
469
|
+
var errors = {
|
|
470
|
+
oracleUnsupportedCurrency: (currency) => new CashError({
|
|
471
|
+
code: "ORACLE_UNSUPPORTED_CURRENCY",
|
|
472
|
+
message: `${currency} has no live Chainlink oracle feed; Peer Cash is market-rate only.`,
|
|
473
|
+
retryable: false,
|
|
474
|
+
remediation: `Pick a currency listed in capabilities() - each one is priced by a live oracle feed.`
|
|
475
|
+
}),
|
|
476
|
+
unsupportedPlatform: (platform) => new CashError({
|
|
477
|
+
code: "UNSUPPORTED_PLATFORM",
|
|
478
|
+
message: `'${platform}' is not a supported payout platform in this environment.`,
|
|
479
|
+
retryable: false,
|
|
480
|
+
remediation: `Pick a platform listed in capabilities().`
|
|
481
|
+
}),
|
|
482
|
+
amountBelowMinimum: (amount, min) => new CashError({
|
|
483
|
+
code: "AMOUNT_BELOW_MINIMUM",
|
|
484
|
+
message: `Amount ${amount} is below the minimum cash-out of ${min} USDC base units.`,
|
|
485
|
+
retryable: false,
|
|
486
|
+
remediation: `Increase the amount to at least ${min} base units (${Number(min) / 1e6} USDC).`
|
|
487
|
+
}),
|
|
488
|
+
activeIntentBlocksWithdrawal: (depositId) => new CashError({
|
|
489
|
+
code: "ACTIVE_INTENT_BLOCKS_WITHDRAWAL",
|
|
490
|
+
message: `Order ${depositId} has a live buyer intent; escrow blocks withdrawal while a buyer may still deliver.`,
|
|
491
|
+
retryable: true,
|
|
492
|
+
remediation: `Wait for the buyer to complete or for their intent to expire, then call withdraw() again - it prunes expired intents automatically.`
|
|
493
|
+
}),
|
|
494
|
+
insufficientAvailableFunds: (depositId, requested, available) => new CashError({
|
|
495
|
+
code: "INSUFFICIENT_AVAILABLE_FUNDS",
|
|
496
|
+
message: `Order ${depositId} has ${available} base units available; ${requested} requested.`,
|
|
497
|
+
retryable: true,
|
|
498
|
+
remediation: `Withdraw at most the available (unlocked) amount, or omit the amount to close the order fully once no buyer intent is live.`
|
|
499
|
+
}),
|
|
500
|
+
orderNotActive: (depositId) => new CashError({
|
|
501
|
+
code: "ORDER_NOT_ACTIVE",
|
|
502
|
+
message: `Order ${depositId} is closed (delivered or returned); it cannot be topped up.`,
|
|
503
|
+
retryable: false,
|
|
504
|
+
remediation: `Start a new cash-out with cashout() instead.`
|
|
505
|
+
}),
|
|
506
|
+
nothingToWithdraw: (depositId) => new CashError({
|
|
507
|
+
code: "NOTHING_TO_WITHDRAW",
|
|
508
|
+
message: `Order ${depositId} holds no withdrawable funds (already delivered or returned).`,
|
|
509
|
+
retryable: false,
|
|
510
|
+
remediation: `Check order(depositId).state - this order is terminal.`
|
|
511
|
+
}),
|
|
512
|
+
indexerLag: (depositId) => new CashError({
|
|
513
|
+
code: "INDEXER_LAG",
|
|
514
|
+
message: `Order ${depositId} is not indexed yet (the deposit may be seconds old).`,
|
|
515
|
+
retryable: true,
|
|
516
|
+
remediation: `Retry in a few seconds; on-chain state is ahead of the indexer right after a transaction.`
|
|
517
|
+
}),
|
|
518
|
+
orderNotFound: (depositId) => new CashError({
|
|
519
|
+
code: "ORDER_NOT_FOUND",
|
|
520
|
+
message: `No deposit found for id ${depositId}.`,
|
|
521
|
+
retryable: true,
|
|
522
|
+
remediation: `Verify the composite depositId (escrow_onchainId). If the deposit was created seconds ago this is indexer lag - retry shortly.`
|
|
523
|
+
}),
|
|
524
|
+
payeeRegistrationFailed: (cause) => new CashError(
|
|
525
|
+
{
|
|
526
|
+
code: "PAYEE_REGISTRATION_FAILED",
|
|
527
|
+
message: `Registering payee details with the curator failed.`,
|
|
528
|
+
retryable: true,
|
|
529
|
+
remediation: `Check the payee handle format for the platform (see capabilities() hints) and retry.`
|
|
530
|
+
},
|
|
531
|
+
{ cause }
|
|
532
|
+
),
|
|
533
|
+
payeeVerificationRequired: (platform, cause) => new CashError(
|
|
534
|
+
{
|
|
535
|
+
code: "PAYEE_VERIFICATION_REQUIRED",
|
|
536
|
+
message: `${platform} requires a verified maker identity attestation to register a payee; a bare handle is not accepted.`,
|
|
537
|
+
retryable: false,
|
|
538
|
+
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.`
|
|
539
|
+
},
|
|
540
|
+
{ cause }
|
|
541
|
+
),
|
|
542
|
+
allowanceNotVisible: (amount) => new CashError({
|
|
543
|
+
code: "ALLOWANCE_NOT_VISIBLE",
|
|
544
|
+
message: `USDC approval for ${amount} base units did not become visible on the read path in time.`,
|
|
545
|
+
retryable: true,
|
|
546
|
+
remediation: `The approve transaction mined but a load-balanced RPC is serving stale state. Retry the same call in a few seconds.`
|
|
547
|
+
}),
|
|
548
|
+
depositResolutionFailed: (txHash) => new CashError({
|
|
549
|
+
code: "DEPOSIT_RESOLUTION_FAILED",
|
|
550
|
+
message: `Deposit transaction ${txHash} succeeded but no DepositReceived event was found in the receipt.`,
|
|
551
|
+
retryable: false,
|
|
552
|
+
remediation: `Inspect the transaction on Basescan; recover the depositId from the DepositReceived log manually, then resume with order(depositId).`
|
|
553
|
+
}),
|
|
554
|
+
signerRequired: (verb) => new CashError({
|
|
555
|
+
code: "SIGNER_REQUIRED",
|
|
556
|
+
message: `${verb}() mutates on-chain state and needs a signer.`,
|
|
557
|
+
retryable: false,
|
|
558
|
+
remediation: `Pass { signer } (a viem WalletClient with an account), or use prepare() and submit the returned txs with your own signing infrastructure.`
|
|
559
|
+
}),
|
|
560
|
+
watchTimeout: (depositId, timeoutMs) => new CashError({
|
|
561
|
+
code: "WATCH_TIMEOUT",
|
|
562
|
+
message: `watch(${depositId}) exceeded ${timeoutMs}ms without reaching a terminal state.`,
|
|
563
|
+
retryable: true,
|
|
564
|
+
remediation: `The order is still live - resume any time with watch(depositId) or order(depositId).`
|
|
565
|
+
}),
|
|
566
|
+
transactionFailed: (txHash, cause) => new CashError(
|
|
567
|
+
{
|
|
568
|
+
code: "TRANSACTION_FAILED",
|
|
569
|
+
message: `Transaction ${txHash} reverted.`,
|
|
570
|
+
retryable: false,
|
|
571
|
+
remediation: `Inspect the transaction on Basescan; the deposit state is unchanged if the revert happened before escrow accepted funds.`
|
|
572
|
+
},
|
|
573
|
+
{ cause }
|
|
574
|
+
),
|
|
575
|
+
escrowPaused: () => new CashError({
|
|
576
|
+
code: "ESCROW_PAUSED",
|
|
577
|
+
message: `The escrow contract is paused; deposits are temporarily disabled.`,
|
|
578
|
+
retryable: true,
|
|
579
|
+
remediation: `Wait for the protocol to unpause and retry. Existing funds remain withdrawable.`
|
|
580
|
+
}),
|
|
581
|
+
/** Generic fallback for an on-chain call that failed for an unrecognized reason. */
|
|
582
|
+
chainCallFailed: (verb, cause) => new CashError(
|
|
583
|
+
{
|
|
584
|
+
code: "TRANSACTION_FAILED",
|
|
585
|
+
message: `The on-chain ${verb} call failed.`,
|
|
586
|
+
retryable: false,
|
|
587
|
+
remediation: `Inspect the error cause and the wallet on Basescan. Deposit state is unchanged if the call reverted before escrow accepted funds.`
|
|
588
|
+
},
|
|
589
|
+
{ cause }
|
|
590
|
+
)
|
|
591
|
+
};
|
|
592
|
+
function mapChainError(verb, err) {
|
|
593
|
+
if (isCashError(err)) return err;
|
|
594
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
595
|
+
if (/\bpaused\b/i.test(message)) return errors.escrowPaused();
|
|
596
|
+
if (/exceeds allowance|insufficient allowance|transfer amount exceeds/i.test(message)) {
|
|
597
|
+
return errors.allowanceNotVisible(0n);
|
|
598
|
+
}
|
|
599
|
+
return errors.chainCallFailed(verb, err);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// src/client/estimate.ts
|
|
603
|
+
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
604
|
+
var CHAINLINK_LATEST_ROUND_ABI = [
|
|
605
|
+
{
|
|
606
|
+
name: "latestRoundData",
|
|
607
|
+
type: "function",
|
|
608
|
+
stateMutability: "view",
|
|
609
|
+
inputs: [],
|
|
610
|
+
outputs: [
|
|
611
|
+
{ name: "roundId", type: "uint80" },
|
|
612
|
+
{ name: "answer", type: "int256" },
|
|
613
|
+
{ name: "startedAt", type: "uint256" },
|
|
614
|
+
{ name: "updatedAt", type: "uint256" },
|
|
615
|
+
{ name: "answeredInRound", type: "uint80" }
|
|
616
|
+
]
|
|
617
|
+
}
|
|
618
|
+
];
|
|
619
|
+
var DEFAULT_MAX_STALENESS_SECONDS = 86400;
|
|
620
|
+
async function readEstimate(publicClient, input) {
|
|
621
|
+
const { amount, currency } = input;
|
|
622
|
+
if (amount < MIN_CASHOUT_AMOUNT) {
|
|
623
|
+
throw errors.amountBelowMinimum(amount, MIN_CASHOUT_AMOUNT);
|
|
624
|
+
}
|
|
625
|
+
if (!isMarketRateSupported(currency)) {
|
|
626
|
+
throw errors.oracleUnsupportedCurrency(currency);
|
|
627
|
+
}
|
|
628
|
+
const feedConfig = sdk.CHAINLINK_ORACLE_FEEDS[currency];
|
|
629
|
+
const asOf = Math.floor(Date.now() / 1e3);
|
|
630
|
+
let rate;
|
|
631
|
+
let oracleUpdatedAt;
|
|
632
|
+
if (!feedConfig || feedConfig.feed.toLowerCase() === ZERO_ADDRESS) {
|
|
633
|
+
rate = 1;
|
|
634
|
+
} else {
|
|
635
|
+
const result = await publicClient.readContract({
|
|
636
|
+
address: feedConfig.feed,
|
|
637
|
+
abi: CHAINLINK_LATEST_ROUND_ABI,
|
|
638
|
+
functionName: "latestRoundData"
|
|
639
|
+
});
|
|
640
|
+
const answer = Number(result[1]);
|
|
641
|
+
const price = answer / 10 ** feedConfig.decimals;
|
|
642
|
+
if (!Number.isFinite(price) || price <= 0) {
|
|
643
|
+
throw errors.oracleUnsupportedCurrency(currency);
|
|
644
|
+
}
|
|
645
|
+
const updatedAt = Number(result[3]);
|
|
646
|
+
if (Number.isFinite(updatedAt) && updatedAt > 0) oracleUpdatedAt = updatedAt;
|
|
647
|
+
rate = feedConfig.invert ? 1 / price : price;
|
|
648
|
+
}
|
|
649
|
+
const stale = oracleUpdatedAt !== void 0 && asOf - oracleUpdatedAt > DEFAULT_MAX_STALENESS_SECONDS;
|
|
650
|
+
return {
|
|
651
|
+
kind: "oracle-estimate",
|
|
652
|
+
currency,
|
|
653
|
+
amount,
|
|
654
|
+
rate,
|
|
655
|
+
receiveAmount: Number(amount) / 10 ** USDC_DECIMALS * rate,
|
|
656
|
+
asOf,
|
|
657
|
+
...oracleUpdatedAt !== void 0 ? { oracleUpdatedAt } : {},
|
|
658
|
+
...stale ? { stale: true } : {}
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// src/client/createCashClient.ts
|
|
663
|
+
var DEFAULT_RPC_URL = "https://mainnet.base.org";
|
|
664
|
+
var CASH_ATTRIBUTION_CODE = "peer-cash";
|
|
665
|
+
var DEFAULT_CURATOR_URLS = {
|
|
666
|
+
staging: "https://api-staging.zkp2p.xyz"
|
|
667
|
+
};
|
|
668
|
+
var ERC20_APPROVE_ABI = viem.parseAbi([
|
|
669
|
+
"function approve(address spender, uint256 amount) returns (bool)"
|
|
670
|
+
]);
|
|
671
|
+
var ERC20_ALLOWANCE_ABI = viem.parseAbi([
|
|
672
|
+
"function allowance(address owner, address spender) view returns (uint256)"
|
|
673
|
+
]);
|
|
674
|
+
function sleep(ms, signal) {
|
|
675
|
+
return new Promise((resolve) => {
|
|
676
|
+
const timer = setTimeout(done, ms);
|
|
677
|
+
function done() {
|
|
678
|
+
signal?.removeEventListener("abort", done);
|
|
679
|
+
clearTimeout(timer);
|
|
680
|
+
resolve();
|
|
681
|
+
}
|
|
682
|
+
signal?.addEventListener("abort", done, { once: true });
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
function orderFingerprint(order) {
|
|
686
|
+
return [
|
|
687
|
+
order.state,
|
|
688
|
+
order.filledAmount,
|
|
689
|
+
order.pendingAmount,
|
|
690
|
+
order.returnedAmount,
|
|
691
|
+
order.intentCount ?? 0,
|
|
692
|
+
order.nextActions.join("+")
|
|
693
|
+
].join("|");
|
|
694
|
+
}
|
|
695
|
+
async function submitAndConfirm(client, verb, send) {
|
|
696
|
+
let hash;
|
|
697
|
+
try {
|
|
698
|
+
hash = await send();
|
|
699
|
+
} catch (err) {
|
|
700
|
+
throw mapChainError(verb, err);
|
|
701
|
+
}
|
|
702
|
+
const receipt = await client.publicClient.waitForTransactionReceipt({ hash });
|
|
703
|
+
if (receipt.status === "reverted") throw errors.transactionFailed(hash);
|
|
704
|
+
return hash;
|
|
705
|
+
}
|
|
706
|
+
function depositOrderOptions(deposit) {
|
|
707
|
+
const remaining = toBigIntOrUndefined(deposit.remainingDeposits);
|
|
708
|
+
const outstanding = toBigIntOrUndefined(deposit.outstandingIntentAmount);
|
|
709
|
+
const taken = toBigIntOrUndefined(deposit.totalAmountTaken);
|
|
710
|
+
const withdrawn = toBigIntOrUndefined(deposit.totalWithdrawn);
|
|
711
|
+
const updatedAt = deposit.updatedAt != null ? Number(deposit.updatedAt) : void 0;
|
|
712
|
+
return {
|
|
713
|
+
...remaining !== void 0 ? { remainingAmount: remaining } : {},
|
|
714
|
+
...outstanding !== void 0 ? { outstandingAmount: outstanding } : {},
|
|
715
|
+
...taken !== void 0 ? { takenAmount: taken } : {},
|
|
716
|
+
...withdrawn !== void 0 ? { withdrawnAmount: withdrawn } : {},
|
|
717
|
+
...deposit.status != null ? { status: deposit.status } : {},
|
|
718
|
+
...deposit.totalIntents != null ? { intentCount: deposit.totalIntents } : {},
|
|
719
|
+
...deposit.successRateBps != null ? { successRateBps: deposit.successRateBps } : {},
|
|
720
|
+
...updatedAt !== void 0 && Number.isFinite(updatedAt) ? { updatedAt } : {}
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
function createCashClient(options) {
|
|
724
|
+
const { environment } = options;
|
|
725
|
+
const transport = options.transport ?? viem.http(options.rpcUrl ?? DEFAULT_RPC_URL);
|
|
726
|
+
const referrerCodes = [
|
|
727
|
+
CASH_ATTRIBUTION_CODE,
|
|
728
|
+
...options.referrer === void 0 ? [] : Array.isArray(options.referrer) ? options.referrer : [options.referrer]
|
|
729
|
+
];
|
|
730
|
+
const attribution = { referrer: referrerCodes };
|
|
731
|
+
function buildSdkClient(walletClient) {
|
|
732
|
+
return new sdk.Zkp2pClient({
|
|
733
|
+
walletClient,
|
|
734
|
+
chainId: BASE_CHAIN_ID,
|
|
735
|
+
runtimeEnv: environment,
|
|
736
|
+
rpcTransport: transport,
|
|
737
|
+
...options.rpcUrl ? { rpcUrl: options.rpcUrl } : {},
|
|
738
|
+
...options.indexerUrl ? { indexerUrl: options.indexerUrl } : {},
|
|
739
|
+
...options.curatorUrl ?? DEFAULT_CURATOR_URLS[environment] ? { baseApiUrl: options.curatorUrl ?? DEFAULT_CURATOR_URLS[environment] } : {},
|
|
740
|
+
...options.apiKey ? { apiKey: options.apiKey } : {}
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
const readClient = buildSdkClient(viem.createWalletClient({ chain: chains.base, transport }));
|
|
744
|
+
const signingClients = /* @__PURE__ */ new WeakMap();
|
|
745
|
+
function signingClient(verb, opts) {
|
|
746
|
+
const signer = opts?.signer;
|
|
747
|
+
if (!signer?.account) throw errors.signerRequired(verb);
|
|
748
|
+
let client = signingClients.get(signer);
|
|
749
|
+
if (!client) {
|
|
750
|
+
client = buildSdkClient(signer);
|
|
751
|
+
signingClients.set(signer, client);
|
|
752
|
+
}
|
|
753
|
+
return client;
|
|
754
|
+
}
|
|
755
|
+
function validateInput(input) {
|
|
756
|
+
const { amount, receive } = input;
|
|
757
|
+
if (amount < MIN_CASHOUT_AMOUNT) throw errors.amountBelowMinimum(amount, MIN_CASHOUT_AMOUNT);
|
|
758
|
+
const catalog = sdk.getPaymentMethodsCatalog(BASE_CHAIN_ID, environment);
|
|
759
|
+
if (!catalog[receive.platform]) throw errors.unsupportedPlatform(receive.platform);
|
|
760
|
+
if (!isMarketRateSupported(receive.currency)) {
|
|
761
|
+
throw errors.oracleUnsupportedCurrency(receive.currency);
|
|
762
|
+
}
|
|
763
|
+
if (platformRequiresIdentityAttestation(receive.platform) && !receive.payee.identityAttestation) {
|
|
764
|
+
throw errors.payeeVerificationRequired(receive.platform);
|
|
765
|
+
}
|
|
766
|
+
return {
|
|
767
|
+
amount,
|
|
768
|
+
payouts: [
|
|
769
|
+
{
|
|
770
|
+
processorName: receive.platform,
|
|
771
|
+
currency: receive.currency,
|
|
772
|
+
payeeData: receive.payee
|
|
773
|
+
}
|
|
774
|
+
],
|
|
775
|
+
...input.intentAmountRange ? { intentAmountRange: input.intentAmountRange } : {}
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
async function buildDepositParams(client, depositInput) {
|
|
779
|
+
try {
|
|
780
|
+
return await prepareCashDepositParams(client, depositInput);
|
|
781
|
+
} catch (err) {
|
|
782
|
+
if (isCashError(err)) throw err;
|
|
783
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
784
|
+
if (/identityAttestation is required|identity attestation/i.test(message)) {
|
|
785
|
+
const platform = depositInput.payouts[0]?.processorName ?? "this platform";
|
|
786
|
+
throw errors.payeeVerificationRequired(platform, err);
|
|
787
|
+
}
|
|
788
|
+
throw errors.payeeRegistrationFailed(err);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
async function fetchOrder(depositId) {
|
|
792
|
+
const deposits = await readClient.indexer.getDepositsByIdsWithRelations([depositId], {
|
|
793
|
+
includeIntents: true,
|
|
794
|
+
intentStatuses: CASH_ORDER_STATUSES
|
|
795
|
+
});
|
|
796
|
+
const deposit = deposits[0];
|
|
797
|
+
if (!deposit) {
|
|
798
|
+
const intents = await readClient.indexer.getIntentsForDeposits(
|
|
799
|
+
[depositId],
|
|
800
|
+
CASH_ORDER_STATUSES
|
|
801
|
+
);
|
|
802
|
+
if (intents.length === 0) throw errors.orderNotFound(depositId);
|
|
803
|
+
return deriveCashOrder(depositId, intents);
|
|
804
|
+
}
|
|
805
|
+
const payouts = derivePayouts(
|
|
806
|
+
deposit.paymentMethods ?? [],
|
|
807
|
+
deposit.currencies ?? [],
|
|
808
|
+
sdk.getPaymentMethodsCatalog(BASE_CHAIN_ID, environment)
|
|
809
|
+
);
|
|
810
|
+
return deriveCashOrder(depositId, deposit.intents ?? [], {
|
|
811
|
+
...depositOrderOptions(deposit),
|
|
812
|
+
...payouts.length > 0 ? { payouts } : {}
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
function escrowContext(depositId) {
|
|
816
|
+
const { escrowAddress, onchainDepositId } = parseCompositeDepositId(depositId);
|
|
817
|
+
return {
|
|
818
|
+
onchainDepositId,
|
|
819
|
+
escrowArg: escrowAddress ? { escrowAddress } : {}
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
function availableAmount(order) {
|
|
823
|
+
return order.totalAmount - order.filledAmount - order.pendingAmount - order.returnedAmount;
|
|
824
|
+
}
|
|
825
|
+
async function withdrawContext(depositId) {
|
|
826
|
+
const order = await fetchOrder(depositId);
|
|
827
|
+
const nowSeconds = Math.floor(Date.now() / 1e3);
|
|
828
|
+
const signaled = order.fills.filter((f) => f.status === "SIGNALED");
|
|
829
|
+
const liveIntent = signaled.some((f) => isFillLive(f, nowSeconds));
|
|
830
|
+
const expiredIntent = signaled.length > 0 && !liveIntent;
|
|
831
|
+
if (order.pendingAmount > 0n && liveIntent) {
|
|
832
|
+
throw errors.activeIntentBlocksWithdrawal(depositId);
|
|
833
|
+
}
|
|
834
|
+
if (availableAmount(order) <= 0n && order.pendingAmount === 0n) {
|
|
835
|
+
throw errors.nothingToWithdraw(depositId);
|
|
836
|
+
}
|
|
837
|
+
return { expiredIntent, ...escrowContext(depositId) };
|
|
838
|
+
}
|
|
839
|
+
async function partialWithdrawContext(depositId, amount) {
|
|
840
|
+
if (amount <= 0n) throw errors.amountBelowMinimum(amount, 1n);
|
|
841
|
+
const order = await fetchOrder(depositId);
|
|
842
|
+
const available = availableAmount(order);
|
|
843
|
+
if (amount > available) {
|
|
844
|
+
throw errors.insufficientAvailableFunds(depositId, amount, available);
|
|
845
|
+
}
|
|
846
|
+
return escrowContext(depositId);
|
|
847
|
+
}
|
|
848
|
+
async function topUpContext(depositId, amount) {
|
|
849
|
+
if (amount < MIN_CASHOUT_AMOUNT) throw errors.amountBelowMinimum(amount, MIN_CASHOUT_AMOUNT);
|
|
850
|
+
const order = await fetchOrder(depositId);
|
|
851
|
+
if (!order.isInFlight) throw errors.orderNotActive(depositId);
|
|
852
|
+
return escrowContext(depositId);
|
|
853
|
+
}
|
|
854
|
+
async function settleAllowance(client, token, owner, escrow, amount) {
|
|
855
|
+
let allowance;
|
|
856
|
+
try {
|
|
857
|
+
allowance = await client.ensureAllowance({
|
|
858
|
+
token,
|
|
859
|
+
amount,
|
|
860
|
+
spender: escrow,
|
|
861
|
+
txOverrides: attribution
|
|
862
|
+
});
|
|
863
|
+
} catch (err) {
|
|
864
|
+
throw mapChainError("approve", err);
|
|
865
|
+
}
|
|
866
|
+
if (allowance.hadAllowance || !allowance.hash) return;
|
|
867
|
+
const receipt = await client.publicClient.waitForTransactionReceipt({ hash: allowance.hash });
|
|
868
|
+
if (receipt.status === "reverted") throw errors.transactionFailed(allowance.hash);
|
|
869
|
+
for (let attempt = 0; attempt < 15; attempt++) {
|
|
870
|
+
const visible = await client.publicClient.readContract({
|
|
871
|
+
address: token,
|
|
872
|
+
abi: ERC20_ALLOWANCE_ABI,
|
|
873
|
+
functionName: "allowance",
|
|
874
|
+
args: [owner, escrow]
|
|
875
|
+
});
|
|
876
|
+
if (visible >= amount) return;
|
|
877
|
+
await sleep(1e3);
|
|
878
|
+
}
|
|
879
|
+
throw errors.allowanceNotVisible(amount);
|
|
880
|
+
}
|
|
881
|
+
return {
|
|
882
|
+
capabilities() {
|
|
883
|
+
return buildCapabilities(environment);
|
|
884
|
+
},
|
|
885
|
+
async estimate(input) {
|
|
886
|
+
return readEstimate(readClient.publicClient, input);
|
|
887
|
+
},
|
|
888
|
+
async cashout(input, opts) {
|
|
889
|
+
const depositInput = validateInput(input);
|
|
890
|
+
const client = signingClient("cashout", opts);
|
|
891
|
+
const params = await buildDepositParams(client, depositInput);
|
|
892
|
+
const escrow = client.escrowV2Address ?? client.escrowAddress;
|
|
893
|
+
const owner = opts.signer.account.address;
|
|
894
|
+
await settleAllowance(client, params.token, owner, escrow, depositInput.amount);
|
|
895
|
+
const attributedParams = { ...params, txOverrides: attribution };
|
|
896
|
+
const send = async () => {
|
|
897
|
+
try {
|
|
898
|
+
return (await client.createDeposit(attributedParams)).hash;
|
|
899
|
+
} catch (err) {
|
|
900
|
+
if (err instanceof Error && /exceeds allowance/i.test(err.message)) {
|
|
901
|
+
await sleep(2e3);
|
|
902
|
+
return (await client.createDeposit(attributedParams)).hash;
|
|
903
|
+
}
|
|
904
|
+
throw err;
|
|
905
|
+
}
|
|
906
|
+
};
|
|
907
|
+
let hash;
|
|
908
|
+
try {
|
|
909
|
+
hash = await send();
|
|
910
|
+
} catch (err) {
|
|
911
|
+
throw mapChainError("createDeposit", err);
|
|
912
|
+
}
|
|
913
|
+
const receipt = await client.publicClient.waitForTransactionReceipt({ hash });
|
|
914
|
+
if (receipt.status === "reverted") throw errors.transactionFailed(hash);
|
|
915
|
+
const abi = client.escrowV2Abi ?? client.escrowAbi;
|
|
916
|
+
const resolved = resolveCashDepositId({ logs: receipt.logs, abi });
|
|
917
|
+
if (!resolved) throw errors.depositResolutionFailed(hash);
|
|
918
|
+
const order = deriveCashOrder(resolved.compositeId, [], {
|
|
919
|
+
remainingAmount: depositInput.amount,
|
|
920
|
+
status: "ACTIVE"
|
|
921
|
+
});
|
|
922
|
+
return {
|
|
923
|
+
depositId: resolved.compositeId,
|
|
924
|
+
txHash: hash,
|
|
925
|
+
escrowAddress: resolved.escrowAddress,
|
|
926
|
+
onchainDepositId: resolved.onchainDepositId,
|
|
927
|
+
order
|
|
928
|
+
};
|
|
929
|
+
},
|
|
930
|
+
async prepare(input) {
|
|
931
|
+
const depositInput = validateInput(input);
|
|
932
|
+
const params = await buildDepositParams(readClient, depositInput);
|
|
933
|
+
const { prepared } = await readClient.prepareCreateDeposit({
|
|
934
|
+
...params,
|
|
935
|
+
txOverrides: attribution
|
|
936
|
+
});
|
|
937
|
+
const approve = {
|
|
938
|
+
to: params.token,
|
|
939
|
+
data: sdk.appendAttributionToCalldata(
|
|
940
|
+
viem.encodeFunctionData({
|
|
941
|
+
abi: ERC20_APPROVE_ABI,
|
|
942
|
+
functionName: "approve",
|
|
943
|
+
args: [prepared.to, depositInput.amount]
|
|
944
|
+
}),
|
|
945
|
+
referrerCodes
|
|
946
|
+
),
|
|
947
|
+
value: 0n,
|
|
948
|
+
chainId: BASE_CHAIN_ID
|
|
949
|
+
};
|
|
950
|
+
const hashedOnchainIds = (params.paymentMethodDataOverride ?? []).map((d) => d.payeeDetails);
|
|
951
|
+
return {
|
|
952
|
+
txs: [approve, prepared],
|
|
953
|
+
steps: [
|
|
954
|
+
{
|
|
955
|
+
kind: "approve",
|
|
956
|
+
description: "Approve Base USDC for the Peer Cash escrow."
|
|
957
|
+
},
|
|
958
|
+
{
|
|
959
|
+
kind: "createDeposit",
|
|
960
|
+
description: "Create the protocol-held cash-out order."
|
|
961
|
+
}
|
|
962
|
+
],
|
|
963
|
+
register: { hashedOnchainIds }
|
|
964
|
+
};
|
|
965
|
+
},
|
|
966
|
+
async order(depositId) {
|
|
967
|
+
return fetchOrder(depositId);
|
|
968
|
+
},
|
|
969
|
+
async buyer(address) {
|
|
970
|
+
const intents = await readClient.indexer.getOwnerIntents(address, CASH_ORDER_STATUSES);
|
|
971
|
+
return deriveBuyerProfile(address, intents);
|
|
972
|
+
},
|
|
973
|
+
async orders(owner, opts = {}) {
|
|
974
|
+
const { inFlight = false, limit = 100 } = opts;
|
|
975
|
+
const deposits = await readClient.indexer.getDeposits({ depositor: owner }, { limit });
|
|
976
|
+
const derived = deposits.map((d) => deriveCashOrder(d.id, [], { ...depositOrderOptions(d), fillsIncluded: false })).filter((o) => o.totalAmount > 10000n).sort((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0));
|
|
977
|
+
return inFlight ? derived.filter((o) => o.isInFlight) : derived;
|
|
978
|
+
},
|
|
979
|
+
async *watch(depositId, opts = {}) {
|
|
980
|
+
const { signal, pollIntervalMs = 5e3, timeoutMs } = opts;
|
|
981
|
+
const startedAt = Date.now();
|
|
982
|
+
let lastFingerprint;
|
|
983
|
+
while (true) {
|
|
984
|
+
if (signal?.aborted) return;
|
|
985
|
+
if (timeoutMs !== void 0 && Date.now() - startedAt >= timeoutMs) {
|
|
986
|
+
throw errors.watchTimeout(depositId, timeoutMs);
|
|
987
|
+
}
|
|
988
|
+
let order = null;
|
|
989
|
+
try {
|
|
990
|
+
order = await fetchOrder(depositId);
|
|
991
|
+
} catch (err) {
|
|
992
|
+
if (!(isCashError(err) && err.code === "ORDER_NOT_FOUND")) throw err;
|
|
993
|
+
}
|
|
994
|
+
if (order) {
|
|
995
|
+
const fingerprint = orderFingerprint(order);
|
|
996
|
+
if (fingerprint !== lastFingerprint) {
|
|
997
|
+
lastFingerprint = fingerprint;
|
|
998
|
+
yield order;
|
|
999
|
+
}
|
|
1000
|
+
if (!order.isInFlight) return;
|
|
1001
|
+
}
|
|
1002
|
+
await sleep(pollIntervalMs, signal);
|
|
1003
|
+
}
|
|
1004
|
+
},
|
|
1005
|
+
async withdraw(depositId, opts) {
|
|
1006
|
+
const client = signingClient("withdraw", opts);
|
|
1007
|
+
if (opts.amount !== void 0) {
|
|
1008
|
+
const { onchainDepositId: onchainDepositId2, escrowArg: escrowArg2 } = await partialWithdrawContext(
|
|
1009
|
+
depositId,
|
|
1010
|
+
opts.amount
|
|
1011
|
+
);
|
|
1012
|
+
const withdrawTxHash2 = await submitAndConfirm(
|
|
1013
|
+
client,
|
|
1014
|
+
"removeFunds",
|
|
1015
|
+
() => client.removeFunds({
|
|
1016
|
+
depositId: onchainDepositId2,
|
|
1017
|
+
amount: opts.amount,
|
|
1018
|
+
...escrowArg2,
|
|
1019
|
+
txOverrides: attribution
|
|
1020
|
+
})
|
|
1021
|
+
);
|
|
1022
|
+
return { depositId, withdrawTxHash: withdrawTxHash2 };
|
|
1023
|
+
}
|
|
1024
|
+
const { expiredIntent, onchainDepositId, escrowArg } = await withdrawContext(depositId);
|
|
1025
|
+
let pruneTxHash;
|
|
1026
|
+
if (expiredIntent) {
|
|
1027
|
+
pruneTxHash = await submitAndConfirm(
|
|
1028
|
+
client,
|
|
1029
|
+
"pruneExpiredIntents",
|
|
1030
|
+
() => client.pruneExpiredIntents({
|
|
1031
|
+
depositId: onchainDepositId,
|
|
1032
|
+
...escrowArg,
|
|
1033
|
+
txOverrides: attribution
|
|
1034
|
+
})
|
|
1035
|
+
);
|
|
1036
|
+
}
|
|
1037
|
+
const withdrawTxHash = await submitAndConfirm(
|
|
1038
|
+
client,
|
|
1039
|
+
"withdrawDeposit",
|
|
1040
|
+
() => client.withdrawDeposit({
|
|
1041
|
+
depositId: onchainDepositId,
|
|
1042
|
+
...escrowArg,
|
|
1043
|
+
txOverrides: attribution
|
|
1044
|
+
})
|
|
1045
|
+
);
|
|
1046
|
+
return {
|
|
1047
|
+
depositId,
|
|
1048
|
+
...pruneTxHash !== void 0 ? { pruneTxHash } : {},
|
|
1049
|
+
withdrawTxHash
|
|
1050
|
+
};
|
|
1051
|
+
},
|
|
1052
|
+
async prepareWithdraw(depositId, opts = {}) {
|
|
1053
|
+
if (opts.amount !== void 0) {
|
|
1054
|
+
const { onchainDepositId: onchainDepositId2, escrowArg: escrowArg2 } = await partialWithdrawContext(
|
|
1055
|
+
depositId,
|
|
1056
|
+
opts.amount
|
|
1057
|
+
);
|
|
1058
|
+
const tx = await readClient.removeFunds.prepare({
|
|
1059
|
+
depositId: onchainDepositId2,
|
|
1060
|
+
amount: opts.amount,
|
|
1061
|
+
...escrowArg2,
|
|
1062
|
+
txOverrides: attribution
|
|
1063
|
+
});
|
|
1064
|
+
return {
|
|
1065
|
+
txs: [tx],
|
|
1066
|
+
steps: [
|
|
1067
|
+
{
|
|
1068
|
+
kind: "removeFunds",
|
|
1069
|
+
description: "Withdraw the requested unlocked USDC amount."
|
|
1070
|
+
}
|
|
1071
|
+
]
|
|
1072
|
+
};
|
|
1073
|
+
}
|
|
1074
|
+
const { expiredIntent, onchainDepositId, escrowArg } = await withdrawContext(depositId);
|
|
1075
|
+
const txs = [];
|
|
1076
|
+
const steps = [];
|
|
1077
|
+
if (expiredIntent) {
|
|
1078
|
+
txs.push(
|
|
1079
|
+
await readClient.pruneExpiredIntents.prepare({
|
|
1080
|
+
depositId: onchainDepositId,
|
|
1081
|
+
...escrowArg,
|
|
1082
|
+
txOverrides: attribution
|
|
1083
|
+
})
|
|
1084
|
+
);
|
|
1085
|
+
steps.push({
|
|
1086
|
+
kind: "pruneExpiredIntents",
|
|
1087
|
+
description: "Prune expired buyer intents so the locked amount becomes withdrawable."
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
txs.push(
|
|
1091
|
+
await readClient.withdrawDeposit.prepare({
|
|
1092
|
+
depositId: onchainDepositId,
|
|
1093
|
+
...escrowArg,
|
|
1094
|
+
txOverrides: attribution
|
|
1095
|
+
})
|
|
1096
|
+
);
|
|
1097
|
+
steps.push({
|
|
1098
|
+
kind: "withdrawDeposit",
|
|
1099
|
+
description: "Close the order and withdraw all remaining USDC."
|
|
1100
|
+
});
|
|
1101
|
+
return { txs, steps };
|
|
1102
|
+
},
|
|
1103
|
+
async topUp(depositId, amount, opts) {
|
|
1104
|
+
const client = signingClient("topUp", opts);
|
|
1105
|
+
const { onchainDepositId, escrowArg } = await topUpContext(depositId, amount);
|
|
1106
|
+
const owner = opts.signer.account.address;
|
|
1107
|
+
const escrow = escrowArg.escrowAddress ?? client.escrowV2Address ?? client.escrowAddress;
|
|
1108
|
+
await settleAllowance(client, BASE_USDC_ADDRESS, owner, escrow, amount);
|
|
1109
|
+
const txHash = await submitAndConfirm(
|
|
1110
|
+
client,
|
|
1111
|
+
"addFunds",
|
|
1112
|
+
() => client.addFunds({
|
|
1113
|
+
depositId: onchainDepositId,
|
|
1114
|
+
amount,
|
|
1115
|
+
...escrowArg,
|
|
1116
|
+
txOverrides: attribution
|
|
1117
|
+
})
|
|
1118
|
+
);
|
|
1119
|
+
return { depositId, txHash };
|
|
1120
|
+
},
|
|
1121
|
+
async prepareTopUp(depositId, amount) {
|
|
1122
|
+
const { onchainDepositId, escrowArg } = await topUpContext(depositId, amount);
|
|
1123
|
+
const prepared = await readClient.addFunds.prepare({
|
|
1124
|
+
depositId: onchainDepositId,
|
|
1125
|
+
amount,
|
|
1126
|
+
...escrowArg,
|
|
1127
|
+
txOverrides: attribution
|
|
1128
|
+
});
|
|
1129
|
+
const approve = {
|
|
1130
|
+
to: BASE_USDC_ADDRESS,
|
|
1131
|
+
data: sdk.appendAttributionToCalldata(
|
|
1132
|
+
viem.encodeFunctionData({
|
|
1133
|
+
abi: ERC20_APPROVE_ABI,
|
|
1134
|
+
functionName: "approve",
|
|
1135
|
+
args: [prepared.to, amount]
|
|
1136
|
+
}),
|
|
1137
|
+
referrerCodes
|
|
1138
|
+
),
|
|
1139
|
+
value: 0n,
|
|
1140
|
+
chainId: BASE_CHAIN_ID
|
|
1141
|
+
};
|
|
1142
|
+
return {
|
|
1143
|
+
txs: [approve, prepared],
|
|
1144
|
+
steps: [
|
|
1145
|
+
{
|
|
1146
|
+
kind: "approve",
|
|
1147
|
+
description: "Approve additional Base USDC for the Peer Cash escrow."
|
|
1148
|
+
},
|
|
1149
|
+
{
|
|
1150
|
+
kind: "addFunds",
|
|
1151
|
+
description: "Add USDC to the live cash-out order."
|
|
1152
|
+
}
|
|
1153
|
+
]
|
|
1154
|
+
};
|
|
1155
|
+
}
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1158
|
+
var bigintString = zod.z.string().regex(/^-?\d+$/, "expected a decimal bigint string");
|
|
1159
|
+
var cashOrderStateSchema = zod.z.enum([
|
|
1160
|
+
"awaiting-buyer",
|
|
1161
|
+
"matched",
|
|
1162
|
+
"delivering",
|
|
1163
|
+
"delivered",
|
|
1164
|
+
"returned"
|
|
1165
|
+
]);
|
|
1166
|
+
var cashNextActionSchema = zod.z.enum(["wait", "withdraw"]);
|
|
1167
|
+
var intentStatusSchema = zod.z.enum(["SIGNALED", "FULFILLED", "PRUNED", "MANUALLY_RELEASED"]);
|
|
1168
|
+
var cashFillJsonSchema = zod.z.object({
|
|
1169
|
+
intentHash: zod.z.string(),
|
|
1170
|
+
status: intentStatusSchema,
|
|
1171
|
+
amount: bigintString,
|
|
1172
|
+
buyer: zod.z.string(),
|
|
1173
|
+
currency: zod.z.string().optional(),
|
|
1174
|
+
currencyHash: zod.z.string().optional(),
|
|
1175
|
+
rate: zod.z.number().optional(),
|
|
1176
|
+
conversionRate: bigintString.optional(),
|
|
1177
|
+
fiatOwed: zod.z.number().optional(),
|
|
1178
|
+
fiatPaid: zod.z.number().optional(),
|
|
1179
|
+
paidCurrency: zod.z.string().optional(),
|
|
1180
|
+
paymentId: zod.z.string().optional(),
|
|
1181
|
+
paidAt: zod.z.number().optional(),
|
|
1182
|
+
releasedAmount: bigintString.optional(),
|
|
1183
|
+
fillLatencySeconds: zod.z.number().optional(),
|
|
1184
|
+
isExpired: zod.z.boolean().optional(),
|
|
1185
|
+
signaledAt: zod.z.number().optional(),
|
|
1186
|
+
expiresAt: zod.z.number().optional(),
|
|
1187
|
+
fulfilledAt: zod.z.number().optional(),
|
|
1188
|
+
prunedAt: zod.z.number().optional()
|
|
1189
|
+
});
|
|
1190
|
+
var cashPayoutPricingJsonSchema = zod.z.object({
|
|
1191
|
+
spreadBps: zod.z.number().optional(),
|
|
1192
|
+
kind: zod.z.string().optional(),
|
|
1193
|
+
rateSource: zod.z.string().optional(),
|
|
1194
|
+
oracleRate: zod.z.number().optional(),
|
|
1195
|
+
lastOracleUpdatedAt: zod.z.number().optional(),
|
|
1196
|
+
marketRate: zod.z.boolean()
|
|
1197
|
+
});
|
|
1198
|
+
var cashPayoutInfoJsonSchema = zod.z.object({
|
|
1199
|
+
platform: zod.z.string().optional(),
|
|
1200
|
+
platformHash: zod.z.string(),
|
|
1201
|
+
currency: zod.z.string().optional(),
|
|
1202
|
+
currencyHash: zod.z.string().optional(),
|
|
1203
|
+
payeeHash: zod.z.string(),
|
|
1204
|
+
active: zod.z.boolean(),
|
|
1205
|
+
pricing: cashPayoutPricingJsonSchema
|
|
1206
|
+
});
|
|
1207
|
+
var cashBuyerProfileJsonSchema = zod.z.object({
|
|
1208
|
+
address: zod.z.string(),
|
|
1209
|
+
totalIntents: zod.z.number(),
|
|
1210
|
+
fulfilled: zod.z.number(),
|
|
1211
|
+
pruned: zod.z.number(),
|
|
1212
|
+
signaled: zod.z.number(),
|
|
1213
|
+
successRateBps: zod.z.number().optional(),
|
|
1214
|
+
firstSeenAt: zod.z.number().optional(),
|
|
1215
|
+
lastSeenAt: zod.z.number().optional()
|
|
1216
|
+
});
|
|
1217
|
+
var cashOrderJsonSchema = zod.z.object({
|
|
1218
|
+
depositId: zod.z.string(),
|
|
1219
|
+
state: cashOrderStateSchema,
|
|
1220
|
+
fills: zod.z.array(cashFillJsonSchema),
|
|
1221
|
+
totalAmount: bigintString,
|
|
1222
|
+
filledAmount: bigintString,
|
|
1223
|
+
pendingAmount: bigintString,
|
|
1224
|
+
returnedAmount: bigintString,
|
|
1225
|
+
nextActions: zod.z.array(cashNextActionSchema),
|
|
1226
|
+
primaryIntentHash: zod.z.string().optional(),
|
|
1227
|
+
matchedAt: zod.z.number().optional(),
|
|
1228
|
+
deliveredAt: zod.z.number().optional(),
|
|
1229
|
+
updatedAt: zod.z.number().optional(),
|
|
1230
|
+
intentCount: zod.z.number().optional(),
|
|
1231
|
+
payouts: zod.z.array(cashPayoutInfoJsonSchema).optional(),
|
|
1232
|
+
successRateBps: zod.z.number().optional(),
|
|
1233
|
+
isInFlight: zod.z.boolean(),
|
|
1234
|
+
withdrawn: zod.z.boolean().optional()
|
|
1235
|
+
});
|
|
1236
|
+
var cashEstimateJsonSchema = zod.z.object({
|
|
1237
|
+
kind: zod.z.literal("oracle-estimate"),
|
|
1238
|
+
currency: zod.z.string(),
|
|
1239
|
+
amount: bigintString,
|
|
1240
|
+
rate: zod.z.number(),
|
|
1241
|
+
receiveAmount: zod.z.number(),
|
|
1242
|
+
asOf: zod.z.number(),
|
|
1243
|
+
oracleUpdatedAt: zod.z.number().optional(),
|
|
1244
|
+
stale: zod.z.boolean().optional()
|
|
1245
|
+
});
|
|
1246
|
+
var preparedTransactionJsonSchema = zod.z.object({
|
|
1247
|
+
to: zod.z.string(),
|
|
1248
|
+
data: zod.z.string(),
|
|
1249
|
+
value: bigintString,
|
|
1250
|
+
chainId: zod.z.number()
|
|
1251
|
+
});
|
|
1252
|
+
var cashPreparedStepJsonSchema = zod.z.object({
|
|
1253
|
+
kind: zod.z.enum([
|
|
1254
|
+
"approve",
|
|
1255
|
+
"createDeposit",
|
|
1256
|
+
"pruneExpiredIntents",
|
|
1257
|
+
"withdrawDeposit",
|
|
1258
|
+
"removeFunds",
|
|
1259
|
+
"addFunds"
|
|
1260
|
+
]),
|
|
1261
|
+
description: zod.z.string()
|
|
1262
|
+
});
|
|
1263
|
+
var cashoutResultJsonSchema = zod.z.object({
|
|
1264
|
+
depositId: zod.z.string(),
|
|
1265
|
+
txHash: zod.z.string(),
|
|
1266
|
+
escrowAddress: zod.z.string(),
|
|
1267
|
+
onchainDepositId: bigintString,
|
|
1268
|
+
order: cashOrderJsonSchema
|
|
1269
|
+
});
|
|
1270
|
+
var prepareResultJsonSchema = zod.z.object({
|
|
1271
|
+
txs: zod.z.array(preparedTransactionJsonSchema),
|
|
1272
|
+
steps: zod.z.array(cashPreparedStepJsonSchema),
|
|
1273
|
+
register: zod.z.object({ hashedOnchainIds: zod.z.array(zod.z.string()) })
|
|
1274
|
+
});
|
|
1275
|
+
var withdrawResultJsonSchema = zod.z.object({
|
|
1276
|
+
depositId: zod.z.string(),
|
|
1277
|
+
pruneTxHash: zod.z.string().optional(),
|
|
1278
|
+
withdrawTxHash: zod.z.string()
|
|
1279
|
+
});
|
|
1280
|
+
var topUpResultJsonSchema = zod.z.object({
|
|
1281
|
+
depositId: zod.z.string(),
|
|
1282
|
+
txHash: zod.z.string()
|
|
1283
|
+
});
|
|
1284
|
+
var cashCapabilitiesJsonSchema = zod.z.object({
|
|
1285
|
+
chainId: zod.z.number(),
|
|
1286
|
+
token: zod.z.object({ address: zod.z.string(), symbol: zod.z.literal("USDC"), decimals: zod.z.number() }),
|
|
1287
|
+
environment: zod.z.enum(["production", "preproduction", "staging"]),
|
|
1288
|
+
platforms: zod.z.array(
|
|
1289
|
+
zod.z.object({
|
|
1290
|
+
platform: zod.z.string(),
|
|
1291
|
+
currencies: zod.z.array(zod.z.string()),
|
|
1292
|
+
payeeHint: zod.z.string(),
|
|
1293
|
+
requiresIdentityAttestation: zod.z.boolean()
|
|
1294
|
+
})
|
|
1295
|
+
),
|
|
1296
|
+
currencies: zod.z.array(zod.z.string()),
|
|
1297
|
+
amount: zod.z.object({ min: bigintString, recommendedMin: bigintString, max: zod.z.null() }),
|
|
1298
|
+
pricing: zod.z.object({ kind: zod.z.literal("oracle-market-rate"), spreadBps: zod.z.literal(0) })
|
|
1299
|
+
});
|
|
1300
|
+
var cashErrorJsonSchema = zod.z.object({
|
|
1301
|
+
code: zod.z.string(),
|
|
1302
|
+
message: zod.z.string(),
|
|
1303
|
+
retryable: zod.z.boolean(),
|
|
1304
|
+
remediation: zod.z.string()
|
|
1305
|
+
});
|
|
1306
|
+
|
|
1307
|
+
// src/codecs/json.ts
|
|
1308
|
+
function omitUndefined(obj) {
|
|
1309
|
+
return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== void 0));
|
|
1310
|
+
}
|
|
1311
|
+
function fillToJson(fill) {
|
|
1312
|
+
return omitUndefined({
|
|
1313
|
+
intentHash: fill.intentHash,
|
|
1314
|
+
status: fill.status,
|
|
1315
|
+
amount: fill.amount.toString(),
|
|
1316
|
+
buyer: fill.buyer,
|
|
1317
|
+
currency: fill.currency,
|
|
1318
|
+
currencyHash: fill.currencyHash,
|
|
1319
|
+
rate: fill.rate,
|
|
1320
|
+
conversionRate: fill.conversionRate?.toString(),
|
|
1321
|
+
fiatOwed: fill.fiatOwed,
|
|
1322
|
+
fiatPaid: fill.fiatPaid,
|
|
1323
|
+
paidCurrency: fill.paidCurrency,
|
|
1324
|
+
paymentId: fill.paymentId,
|
|
1325
|
+
paidAt: fill.paidAt,
|
|
1326
|
+
releasedAmount: fill.releasedAmount?.toString(),
|
|
1327
|
+
fillLatencySeconds: fill.fillLatencySeconds,
|
|
1328
|
+
isExpired: fill.isExpired,
|
|
1329
|
+
signaledAt: fill.signaledAt,
|
|
1330
|
+
expiresAt: fill.expiresAt,
|
|
1331
|
+
fulfilledAt: fill.fulfilledAt,
|
|
1332
|
+
prunedAt: fill.prunedAt
|
|
1333
|
+
});
|
|
1334
|
+
}
|
|
1335
|
+
function fillFromJson(json) {
|
|
1336
|
+
return omitUndefined({
|
|
1337
|
+
...json,
|
|
1338
|
+
amount: BigInt(json.amount),
|
|
1339
|
+
conversionRate: json.conversionRate !== void 0 ? BigInt(json.conversionRate) : void 0,
|
|
1340
|
+
releasedAmount: json.releasedAmount !== void 0 ? BigInt(json.releasedAmount) : void 0
|
|
1341
|
+
});
|
|
1342
|
+
}
|
|
1343
|
+
function orderToJson(order) {
|
|
1344
|
+
return omitUndefined({
|
|
1345
|
+
depositId: order.depositId,
|
|
1346
|
+
state: order.state,
|
|
1347
|
+
fills: order.fills.map(fillToJson),
|
|
1348
|
+
totalAmount: order.totalAmount.toString(),
|
|
1349
|
+
filledAmount: order.filledAmount.toString(),
|
|
1350
|
+
pendingAmount: order.pendingAmount.toString(),
|
|
1351
|
+
returnedAmount: order.returnedAmount.toString(),
|
|
1352
|
+
nextActions: order.nextActions,
|
|
1353
|
+
primaryIntentHash: order.primaryIntentHash,
|
|
1354
|
+
matchedAt: order.matchedAt,
|
|
1355
|
+
deliveredAt: order.deliveredAt,
|
|
1356
|
+
updatedAt: order.updatedAt,
|
|
1357
|
+
intentCount: order.intentCount,
|
|
1358
|
+
payouts: order.payouts?.map(
|
|
1359
|
+
(p) => omitUndefined({ ...p, pricing: omitUndefined({ ...p.pricing }) })
|
|
1360
|
+
),
|
|
1361
|
+
successRateBps: order.successRateBps,
|
|
1362
|
+
isInFlight: order.isInFlight,
|
|
1363
|
+
withdrawn: order.withdrawn
|
|
1364
|
+
});
|
|
1365
|
+
}
|
|
1366
|
+
function orderFromJson(json) {
|
|
1367
|
+
const parsed = cashOrderJsonSchema.parse(json);
|
|
1368
|
+
const data = omitUndefined({
|
|
1369
|
+
...parsed,
|
|
1370
|
+
fills: parsed.fills.map(fillFromJson),
|
|
1371
|
+
totalAmount: BigInt(parsed.totalAmount),
|
|
1372
|
+
filledAmount: BigInt(parsed.filledAmount),
|
|
1373
|
+
pendingAmount: BigInt(parsed.pendingAmount),
|
|
1374
|
+
returnedAmount: BigInt(parsed.returnedAmount)
|
|
1375
|
+
});
|
|
1376
|
+
return withExplain(data);
|
|
1377
|
+
}
|
|
1378
|
+
function estimateToJson(estimate) {
|
|
1379
|
+
return { ...estimate, amount: estimate.amount.toString() };
|
|
1380
|
+
}
|
|
1381
|
+
function estimateFromJson(json) {
|
|
1382
|
+
const parsed = cashEstimateJsonSchema.parse(json);
|
|
1383
|
+
return omitUndefined({
|
|
1384
|
+
...parsed,
|
|
1385
|
+
currency: parsed.currency,
|
|
1386
|
+
amount: BigInt(parsed.amount)
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
function preparedTxToJson(tx) {
|
|
1390
|
+
return { to: tx.to, data: tx.data, value: tx.value.toString(), chainId: tx.chainId };
|
|
1391
|
+
}
|
|
1392
|
+
function preparedTxFromJson(json) {
|
|
1393
|
+
const parsed = preparedTransactionJsonSchema.parse(json);
|
|
1394
|
+
return {
|
|
1395
|
+
to: parsed.to,
|
|
1396
|
+
data: parsed.data,
|
|
1397
|
+
value: BigInt(parsed.value),
|
|
1398
|
+
chainId: parsed.chainId
|
|
1399
|
+
};
|
|
1400
|
+
}
|
|
1401
|
+
function preparedStepToJson(step) {
|
|
1402
|
+
return { kind: step.kind, description: step.description };
|
|
1403
|
+
}
|
|
1404
|
+
function preparedStepFromJson(json) {
|
|
1405
|
+
return cashPreparedStepJsonSchema.parse(json);
|
|
1406
|
+
}
|
|
1407
|
+
function cashoutResultToJson(result) {
|
|
1408
|
+
return {
|
|
1409
|
+
depositId: result.depositId,
|
|
1410
|
+
txHash: result.txHash,
|
|
1411
|
+
escrowAddress: result.escrowAddress,
|
|
1412
|
+
onchainDepositId: result.onchainDepositId.toString(),
|
|
1413
|
+
order: orderToJson(result.order)
|
|
1414
|
+
};
|
|
1415
|
+
}
|
|
1416
|
+
function cashoutResultFromJson(json) {
|
|
1417
|
+
const parsed = cashoutResultJsonSchema.parse(json);
|
|
1418
|
+
return {
|
|
1419
|
+
depositId: parsed.depositId,
|
|
1420
|
+
txHash: parsed.txHash,
|
|
1421
|
+
escrowAddress: parsed.escrowAddress,
|
|
1422
|
+
onchainDepositId: BigInt(parsed.onchainDepositId),
|
|
1423
|
+
order: orderFromJson(parsed.order)
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
function prepareResultToJson(result) {
|
|
1427
|
+
return {
|
|
1428
|
+
txs: result.txs.map(preparedTxToJson),
|
|
1429
|
+
steps: result.steps.map(preparedStepToJson),
|
|
1430
|
+
register: result.register
|
|
1431
|
+
};
|
|
1432
|
+
}
|
|
1433
|
+
function prepareResultFromJson(json) {
|
|
1434
|
+
const parsed = prepareResultJsonSchema.parse(json);
|
|
1435
|
+
return {
|
|
1436
|
+
txs: parsed.txs.map(preparedTxFromJson),
|
|
1437
|
+
steps: parsed.steps.map(preparedStepFromJson),
|
|
1438
|
+
register: parsed.register
|
|
1439
|
+
};
|
|
1440
|
+
}
|
|
1441
|
+
function withdrawResultToJson(result) {
|
|
1442
|
+
return omitUndefined({
|
|
1443
|
+
depositId: result.depositId,
|
|
1444
|
+
pruneTxHash: result.pruneTxHash,
|
|
1445
|
+
withdrawTxHash: result.withdrawTxHash
|
|
1446
|
+
});
|
|
1447
|
+
}
|
|
1448
|
+
function withdrawResultFromJson(json) {
|
|
1449
|
+
const parsed = withdrawResultJsonSchema.parse(json);
|
|
1450
|
+
return omitUndefined({
|
|
1451
|
+
depositId: parsed.depositId,
|
|
1452
|
+
pruneTxHash: parsed.pruneTxHash,
|
|
1453
|
+
withdrawTxHash: parsed.withdrawTxHash
|
|
1454
|
+
});
|
|
1455
|
+
}
|
|
1456
|
+
function buyerProfileToJson(profile) {
|
|
1457
|
+
return omitUndefined({ ...profile });
|
|
1458
|
+
}
|
|
1459
|
+
function buyerProfileFromJson(json) {
|
|
1460
|
+
return omitUndefined(cashBuyerProfileJsonSchema.parse(json));
|
|
1461
|
+
}
|
|
1462
|
+
function topUpResultToJson(result) {
|
|
1463
|
+
return { depositId: result.depositId, txHash: result.txHash };
|
|
1464
|
+
}
|
|
1465
|
+
function topUpResultFromJson(json) {
|
|
1466
|
+
const parsed = topUpResultJsonSchema.parse(json);
|
|
1467
|
+
return { depositId: parsed.depositId, txHash: parsed.txHash };
|
|
1468
|
+
}
|
|
1469
|
+
function capabilitiesToJson(caps) {
|
|
1470
|
+
return {
|
|
1471
|
+
...caps,
|
|
1472
|
+
amount: {
|
|
1473
|
+
min: caps.amount.min.toString(),
|
|
1474
|
+
recommendedMin: caps.amount.recommendedMin.toString(),
|
|
1475
|
+
max: null
|
|
1476
|
+
}
|
|
1477
|
+
};
|
|
1478
|
+
}
|
|
1479
|
+
function capabilitiesFromJson(json) {
|
|
1480
|
+
const parsed = cashCapabilitiesJsonSchema.parse(json);
|
|
1481
|
+
return {
|
|
1482
|
+
...parsed,
|
|
1483
|
+
platforms: parsed.platforms.map((p) => ({
|
|
1484
|
+
...p,
|
|
1485
|
+
currencies: p.currencies
|
|
1486
|
+
})),
|
|
1487
|
+
currencies: parsed.currencies,
|
|
1488
|
+
amount: {
|
|
1489
|
+
min: BigInt(parsed.amount.min),
|
|
1490
|
+
recommendedMin: BigInt(parsed.amount.recommendedMin),
|
|
1491
|
+
max: null
|
|
1492
|
+
}
|
|
1493
|
+
};
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
exports.BASE_CHAIN_ID = BASE_CHAIN_ID;
|
|
1497
|
+
exports.BASE_USDC_ADDRESS = BASE_USDC_ADDRESS;
|
|
1498
|
+
exports.CASH_ATTRIBUTION_CODE = CASH_ATTRIBUTION_CODE;
|
|
1499
|
+
exports.CASH_ORDER_POLL_INTERVAL_MS = CASH_ORDER_POLL_INTERVAL_MS;
|
|
1500
|
+
exports.CASH_ORDER_STATUSES = CASH_ORDER_STATUSES;
|
|
1501
|
+
exports.CASH_RETAIN_ON_EMPTY = CASH_RETAIN_ON_EMPTY;
|
|
1502
|
+
exports.CashError = CashError;
|
|
1503
|
+
exports.MARKET_SPREAD_BPS = MARKET_SPREAD_BPS;
|
|
1504
|
+
exports.MIN_CASHOUT_AMOUNT = MIN_CASHOUT_AMOUNT;
|
|
1505
|
+
exports.ORACLE_MIN_CONVERSION_RATE_SENTINEL = ORACLE_MIN_CONVERSION_RATE_SENTINEL;
|
|
1506
|
+
exports.RATE_PRECISION = RATE_PRECISION;
|
|
1507
|
+
exports.RECOMMENDED_MIN_CASHOUT_AMOUNT = RECOMMENDED_MIN_CASHOUT_AMOUNT;
|
|
1508
|
+
exports.USDC_DECIMALS = USDC_DECIMALS;
|
|
1509
|
+
exports.bigintString = bigintString;
|
|
1510
|
+
exports.buildCapabilities = buildCapabilities;
|
|
1511
|
+
exports.buildIntentAmountRange = buildIntentAmountRange;
|
|
1512
|
+
exports.buildMarketRateCurrencyOverride = buildMarketRateCurrencyOverride;
|
|
1513
|
+
exports.buyerProfileFromJson = buyerProfileFromJson;
|
|
1514
|
+
exports.buyerProfileToJson = buyerProfileToJson;
|
|
1515
|
+
exports.capabilitiesFromJson = capabilitiesFromJson;
|
|
1516
|
+
exports.capabilitiesToJson = capabilitiesToJson;
|
|
1517
|
+
exports.cashBuyerProfileJsonSchema = cashBuyerProfileJsonSchema;
|
|
1518
|
+
exports.cashCapabilitiesJsonSchema = cashCapabilitiesJsonSchema;
|
|
1519
|
+
exports.cashErrorJsonSchema = cashErrorJsonSchema;
|
|
1520
|
+
exports.cashEstimateJsonSchema = cashEstimateJsonSchema;
|
|
1521
|
+
exports.cashFillJsonSchema = cashFillJsonSchema;
|
|
1522
|
+
exports.cashNextActionSchema = cashNextActionSchema;
|
|
1523
|
+
exports.cashOrderJsonSchema = cashOrderJsonSchema;
|
|
1524
|
+
exports.cashOrderStateSchema = cashOrderStateSchema;
|
|
1525
|
+
exports.cashPayoutInfoJsonSchema = cashPayoutInfoJsonSchema;
|
|
1526
|
+
exports.cashPayoutPricingJsonSchema = cashPayoutPricingJsonSchema;
|
|
1527
|
+
exports.cashPreparedStepJsonSchema = cashPreparedStepJsonSchema;
|
|
1528
|
+
exports.cashoutResultFromJson = cashoutResultFromJson;
|
|
1529
|
+
exports.cashoutResultJsonSchema = cashoutResultJsonSchema;
|
|
1530
|
+
exports.cashoutResultToJson = cashoutResultToJson;
|
|
1531
|
+
exports.centsToNumber = centsToNumber;
|
|
1532
|
+
exports.createCashClient = createCashClient;
|
|
1533
|
+
exports.deriveBuyerProfile = deriveBuyerProfile;
|
|
1534
|
+
exports.deriveCashOrder = deriveCashOrder;
|
|
1535
|
+
exports.derivePayouts = derivePayouts;
|
|
1536
|
+
exports.errors = errors;
|
|
1537
|
+
exports.estimateFromJson = estimateFromJson;
|
|
1538
|
+
exports.estimateToJson = estimateToJson;
|
|
1539
|
+
exports.explainOrder = explainOrder;
|
|
1540
|
+
exports.fiatFromUsdc = fiatFromUsdc;
|
|
1541
|
+
exports.fiatToNumber = fiatToNumber;
|
|
1542
|
+
exports.fillFromJson = fillFromJson;
|
|
1543
|
+
exports.fillToJson = fillToJson;
|
|
1544
|
+
exports.formatUsdc = formatUsdc;
|
|
1545
|
+
exports.intentStatusSchema = intentStatusSchema;
|
|
1546
|
+
exports.isCashError = isCashError;
|
|
1547
|
+
exports.isFillLive = isFillLive;
|
|
1548
|
+
exports.isMarketRateSupported = isMarketRateSupported;
|
|
1549
|
+
exports.orderFromJson = orderFromJson;
|
|
1550
|
+
exports.orderToJson = orderToJson;
|
|
1551
|
+
exports.parseCompositeDepositId = parseCompositeDepositId;
|
|
1552
|
+
exports.prepareCashDepositParams = prepareCashDepositParams;
|
|
1553
|
+
exports.prepareResultFromJson = prepareResultFromJson;
|
|
1554
|
+
exports.prepareResultJsonSchema = prepareResultJsonSchema;
|
|
1555
|
+
exports.prepareResultToJson = prepareResultToJson;
|
|
1556
|
+
exports.preparedStepFromJson = preparedStepFromJson;
|
|
1557
|
+
exports.preparedStepToJson = preparedStepToJson;
|
|
1558
|
+
exports.preparedTransactionJsonSchema = preparedTransactionJsonSchema;
|
|
1559
|
+
exports.preparedTxFromJson = preparedTxFromJson;
|
|
1560
|
+
exports.preparedTxToJson = preparedTxToJson;
|
|
1561
|
+
exports.rateToNumber = rateToNumber;
|
|
1562
|
+
exports.resolveCashDepositId = resolveCashDepositId;
|
|
1563
|
+
exports.topUpResultFromJson = topUpResultFromJson;
|
|
1564
|
+
exports.topUpResultJsonSchema = topUpResultJsonSchema;
|
|
1565
|
+
exports.topUpResultToJson = topUpResultToJson;
|
|
1566
|
+
exports.usdc = usdc;
|
|
1567
|
+
exports.withExplain = withExplain;
|
|
1568
|
+
exports.withdrawResultFromJson = withdrawResultFromJson;
|
|
1569
|
+
exports.withdrawResultJsonSchema = withdrawResultJsonSchema;
|
|
1570
|
+
exports.withdrawResultToJson = withdrawResultToJson;
|
|
1571
|
+
//# sourceMappingURL=index.cjs.map
|
|
1572
|
+
//# sourceMappingURL=index.cjs.map
|