@genesis-tech/genesispay-seller 0.8.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/CHANGELOG.md +330 -0
- package/LICENSE +21 -0
- package/README.md +429 -0
- package/dist/client.d.ts +275 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +541 -0
- package/dist/client.js.map +1 -0
- package/dist/customers.d.ts +41 -0
- package/dist/customers.d.ts.map +1 -0
- package/dist/customers.js +76 -0
- package/dist/customers.js.map +1 -0
- package/dist/errors.d.ts +63 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +162 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/invoices.d.ts +80 -0
- package/dist/invoices.d.ts.map +1 -0
- package/dist/invoices.js +133 -0
- package/dist/invoices.js.map +1 -0
- package/dist/mandate-gate.d.ts +49 -0
- package/dist/mandate-gate.d.ts.map +1 -0
- package/dist/mandate-gate.js +109 -0
- package/dist/mandate-gate.js.map +1 -0
- package/dist/mandates.d.ts +172 -0
- package/dist/mandates.d.ts.map +1 -0
- package/dist/mandates.js +213 -0
- package/dist/mandates.js.map +1 -0
- package/dist/networks.d.ts +10 -0
- package/dist/networks.d.ts.map +1 -0
- package/dist/networks.js +22 -0
- package/dist/networks.js.map +1 -0
- package/dist/payment-gate.d.ts +67 -0
- package/dist/payment-gate.d.ts.map +1 -0
- package/dist/payment-gate.js +106 -0
- package/dist/payment-gate.js.map +1 -0
- package/dist/peerpay-settlement.d.ts +27 -0
- package/dist/peerpay-settlement.d.ts.map +1 -0
- package/dist/peerpay-settlement.js +100 -0
- package/dist/peerpay-settlement.js.map +1 -0
- package/dist/plans.d.ts +68 -0
- package/dist/plans.d.ts.map +1 -0
- package/dist/plans.js +127 -0
- package/dist/plans.js.map +1 -0
- package/dist/resource.d.ts +47 -0
- package/dist/resource.d.ts.map +1 -0
- package/dist/resource.js +71 -0
- package/dist/resource.js.map +1 -0
- package/dist/usdc-amount.d.ts +7 -0
- package/dist/usdc-amount.d.ts.map +1 -0
- package/dist/usdc-amount.js +21 -0
- package/dist/usdc-amount.js.map +1 -0
- package/dist/webhooks.d.ts +277 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +223 -0
- package/dist/webhooks.js.map +1 -0
- package/package.json +58 -0
package/dist/client.js
ADDED
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
import { PeerPayConfigError, PeerPayNetworkSafetyError, PeerPayValidationError, throwForErrorResponse, } from "./errors.js";
|
|
2
|
+
import { createMandatesResource } from "./mandates.js";
|
|
3
|
+
import { createCustomersResource } from "./customers.js";
|
|
4
|
+
import { createInvoicesResource } from "./invoices.js";
|
|
5
|
+
import { createPaymentGate } from "./payment-gate.js";
|
|
6
|
+
import { DEFAULT_FACILITATOR_BASE_URL, peerPaySettlement } from "./peerpay-settlement.js";
|
|
7
|
+
import { createPlansResource } from "./plans.js";
|
|
8
|
+
import { resolvePaymentGateNetwork } from "./networks.js";
|
|
9
|
+
import { parseUsdcAmountToMinorUnits } from "./usdc-amount.js";
|
|
10
|
+
import { asRecord, oneOf, optionalMetadata, optionalString, requiredString, toCount, } from "./resource.js";
|
|
11
|
+
import { constructEvent } from "./webhooks.js";
|
|
12
|
+
// The error classes live in ./errors.js (shared with every future resource:
|
|
13
|
+
// plans, mandates, …) and are re-exported here so existing imports from
|
|
14
|
+
// "./client.js" keep working.
|
|
15
|
+
export { PeerPayConfigError, PeerPayNetworkSafetyError, PeerPayNotFoundError, PeerPayRateLimitError, PeerPayValidationError, } from "./errors.js";
|
|
16
|
+
/**
|
|
17
|
+
* Production GenesisPay facilitator — the `peerpay-app` Railway production
|
|
18
|
+
* environment (see docs/runbooks/DEPLOY_RAILWAY.md). Hardcoded so a live key always
|
|
19
|
+
* resolves to our facilitator with zero config, mirroring the test default.
|
|
20
|
+
* Update this if/when GenesisPay moves to a custom production domain (D4).
|
|
21
|
+
*/
|
|
22
|
+
const PRODUCTION_FACILITATOR_BASE_URL = "https://peerpay-app-production.up.railway.app";
|
|
23
|
+
// Both facilitator URLs are hardcoded so the key mode alone routes to the right
|
|
24
|
+
// GenesisPay facilitator; an explicit `baseUrl` still overrides for self-host/staging.
|
|
25
|
+
const MODE_BASE_URLS = {
|
|
26
|
+
test: DEFAULT_FACILITATOR_BASE_URL,
|
|
27
|
+
live: PRODUCTION_FACILITATOR_BASE_URL,
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Appended to the error when simulate-payment answers 403. The server sends its
|
|
31
|
+
* own explanation in the body, but a proxy or a future rewording must not be
|
|
32
|
+
* able to leave the caller without the one fact that matters: the endpoint is
|
|
33
|
+
* gated on the *key mode*, and a live key can never mint a payment.
|
|
34
|
+
*/
|
|
35
|
+
const SIMULATE_PAYMENT_LIVE_KEY_HINT = "simulate-payment only works with a test-mode key (pp_sk_test_…); this client " +
|
|
36
|
+
"is using a live key, and live keys can only record real, on-chain payments.";
|
|
37
|
+
/** Which networks each key mode may legitimately resolve to (fail-closed guard). */
|
|
38
|
+
const MODE_NETWORKS = {
|
|
39
|
+
test: ["base-sepolia"],
|
|
40
|
+
live: ["base"],
|
|
41
|
+
};
|
|
42
|
+
function parseKeyMode(apiKey) {
|
|
43
|
+
if (apiKey.startsWith("pp_sk_live_"))
|
|
44
|
+
return "live";
|
|
45
|
+
if (apiKey.startsWith("pp_sk_"))
|
|
46
|
+
return "test"; // pp_sk_test_… and legacy pp_sk_<32>
|
|
47
|
+
throw new PeerPayConfigError("apiKey must be a GenesisPay seller key (pp_sk_test_… or pp_sk_live_…).");
|
|
48
|
+
}
|
|
49
|
+
function normalizeBaseUrl(url) {
|
|
50
|
+
const trimmed = url.trim().replace(/\/+$/, "");
|
|
51
|
+
const isHttps = /^https:\/\//i.test(trimmed);
|
|
52
|
+
const isLocalHttp = /^http:\/\/(localhost|127\.0\.0\.1)(:\d+)?(\/|$)/i.test(trimmed);
|
|
53
|
+
if (!isHttps && !isLocalHttp) {
|
|
54
|
+
throw new PeerPayConfigError(`baseUrl must be https (got "${trimmed}").`);
|
|
55
|
+
}
|
|
56
|
+
return trimmed;
|
|
57
|
+
}
|
|
58
|
+
function describeError(error) {
|
|
59
|
+
return error instanceof Error ? error.message : "unknown error";
|
|
60
|
+
}
|
|
61
|
+
function toCheckoutLink(raw) {
|
|
62
|
+
// A backend older than 0.6.0 reports the amount only as `amountUsdc`; both
|
|
63
|
+
// names carry the same decimal string, so either one populates both fields.
|
|
64
|
+
// The check is on "is a string" rather than "is present", so a backend that
|
|
65
|
+
// sends a non-string `amount` still falls back instead of yielding "".
|
|
66
|
+
const amount = requiredString(typeof raw.amount === "string" ? raw.amount : raw.amountUsdc);
|
|
67
|
+
return {
|
|
68
|
+
publicId: requiredString(raw.publicId),
|
|
69
|
+
payUrl: requiredString(raw.payUrl),
|
|
70
|
+
amount,
|
|
71
|
+
amountUsdc: amount,
|
|
72
|
+
asset: oneOf(raw.asset, ["USDC", "EURC"], "USDC"),
|
|
73
|
+
title: requiredString(raw.title),
|
|
74
|
+
metadata: optionalMetadata(raw.metadata),
|
|
75
|
+
clientReferenceId: optionalString(raw.clientReferenceId),
|
|
76
|
+
returnUrl: optionalString(raw.returnUrl),
|
|
77
|
+
cancelUrl: optionalString(raw.cancelUrl),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Maps the server's attempt views tolerantly: a non-array (or missing) field
|
|
82
|
+
* yields `[]`, an entry without a usable `id` is skipped, and every optional
|
|
83
|
+
* field degrades to `null` — an older backend must never crash a poll loop.
|
|
84
|
+
*/
|
|
85
|
+
function toCheckoutAttempts(value) {
|
|
86
|
+
if (!Array.isArray(value))
|
|
87
|
+
return [];
|
|
88
|
+
const attempts = [];
|
|
89
|
+
for (const entry of value) {
|
|
90
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry))
|
|
91
|
+
continue;
|
|
92
|
+
const raw = entry;
|
|
93
|
+
const id = optionalString(raw.id);
|
|
94
|
+
if (!id)
|
|
95
|
+
continue;
|
|
96
|
+
attempts.push({
|
|
97
|
+
id,
|
|
98
|
+
status: oneOf(raw.status, ["pending", "submitted", "confirmed", "failed", "expired"], "pending"),
|
|
99
|
+
txHash: optionalString(raw.txHash),
|
|
100
|
+
payerWallet: optionalString(raw.payerWallet),
|
|
101
|
+
createdAt: requiredString(raw.createdAt),
|
|
102
|
+
confirmedAt: optionalString(raw.confirmedAt),
|
|
103
|
+
failureReason: optionalString(raw.failureReason),
|
|
104
|
+
// Only an explicit `true` counts: an older backend omits the field, and
|
|
105
|
+
// treating anything truthy as simulated would misreport real payments.
|
|
106
|
+
simulated: raw.simulated === true,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return attempts;
|
|
110
|
+
}
|
|
111
|
+
function toCheckoutSession(raw) {
|
|
112
|
+
const confirmedPaymentCount = toCount(raw.confirmedPaymentCount);
|
|
113
|
+
return {
|
|
114
|
+
...toCheckoutLink(raw),
|
|
115
|
+
description: optionalString(raw.description),
|
|
116
|
+
linkType: oneOf(raw.linkType, ["single", "reusable"], "single"),
|
|
117
|
+
status: oneOf(raw.status, ["active", "paid", "archived"], "active"),
|
|
118
|
+
destinationWallet: requiredString(raw.destinationWallet),
|
|
119
|
+
chainId: toCount(raw.chainId),
|
|
120
|
+
// Derived, not sent by the server: one confirmed payment is what "paid" means
|
|
121
|
+
// for a reusable link too, so this is the single value worth polling on.
|
|
122
|
+
paid: confirmedPaymentCount > 0,
|
|
123
|
+
confirmedPaymentCount,
|
|
124
|
+
createdAt: requiredString(raw.createdAt),
|
|
125
|
+
attempts: toCheckoutAttempts(raw.attempts),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Folds the `{ attempt, link }` that `simulate-payment` answers with into one
|
|
130
|
+
* `CheckoutSession`, so the method returns the same shape `checkout.retrieve`
|
|
131
|
+
* does and a test can go straight from simulating to asserting on `paid`.
|
|
132
|
+
*
|
|
133
|
+
* The merge is necessary rather than cosmetic: the simulate route's `link` is a
|
|
134
|
+
* plain link view with no `confirmedPaymentCount` and no `attempts`, so mapping
|
|
135
|
+
* it alone would report `paid: false` immediately after minting a confirmed
|
|
136
|
+
* payment. The confirmed attempt from the same response supplies both.
|
|
137
|
+
*
|
|
138
|
+
* The one thing this cannot know is how many payments a *reusable* link already
|
|
139
|
+
* had — `confirmedPaymentCount` is therefore "at least this one". Call
|
|
140
|
+
* `checkout.retrieve()` when the exact total matters.
|
|
141
|
+
*/
|
|
142
|
+
function toSimulatedCheckoutSession(rawLink, attempt) {
|
|
143
|
+
const session = toCheckoutSession(rawLink);
|
|
144
|
+
const confirmedPaymentCount = session.confirmedPaymentCount + (attempt.status === "confirmed" ? 1 : 0);
|
|
145
|
+
return {
|
|
146
|
+
...session,
|
|
147
|
+
attempts: [attempt, ...session.attempts],
|
|
148
|
+
confirmedPaymentCount,
|
|
149
|
+
paid: confirmedPaymentCount > 0,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* True when two amount strings mean different money. `"5.0"` and `"5.00"` are
|
|
154
|
+
* the same amount, so the comparison is on parsed minor units rather than on
|
|
155
|
+
* the strings; a value the parser cannot read at all is left to the server,
|
|
156
|
+
* which owns amount validation, and only counts as a disagreement if the other
|
|
157
|
+
* string differs from it.
|
|
158
|
+
*/
|
|
159
|
+
function amountsDisagree(a, b) {
|
|
160
|
+
if (a.trim() === b.trim())
|
|
161
|
+
return false;
|
|
162
|
+
const minorUnits = (value) => {
|
|
163
|
+
try {
|
|
164
|
+
return parseUsdcAmountToMinorUnits(value);
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
const [minorA, minorB] = [minorUnits(a), minorUnits(b)];
|
|
171
|
+
if (minorA === null || minorB === null)
|
|
172
|
+
return true;
|
|
173
|
+
return minorA !== minorB;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Resolves `amount` and the deprecated `amountUsdc` down to the single value
|
|
177
|
+
* the request carries.
|
|
178
|
+
*
|
|
179
|
+
* The disagreement case is stopped here rather than on the server because a
|
|
180
|
+
* create call that names two different prices has no correct interpretation —
|
|
181
|
+
* picking either one would create a link for money the caller did not mean.
|
|
182
|
+
*/
|
|
183
|
+
function resolveCheckoutAmount(input) {
|
|
184
|
+
const { amount, amountUsdc } = input;
|
|
185
|
+
if (amount === undefined && amountUsdc === undefined) {
|
|
186
|
+
throw new PeerPayValidationError('checkout.create requires `amount` — a decimal string in the link\'s asset, e.g. "5.00".', [{ path: "amount", message: "amount is required." }]);
|
|
187
|
+
}
|
|
188
|
+
if (amount !== undefined && amountUsdc !== undefined && amountsDisagree(amount, amountUsdc)) {
|
|
189
|
+
throw new PeerPayValidationError(`checkout.create got amount "${amount}" and the deprecated amountUsdc "${amountUsdc}", ` +
|
|
190
|
+
"which are different amounts. Set `amount` on its own.", [{ path: "amount", message: "amount and amountUsdc disagree." }]);
|
|
191
|
+
}
|
|
192
|
+
return (amount ?? amountUsdc);
|
|
193
|
+
}
|
|
194
|
+
function paymentNotConfiguredResponse() {
|
|
195
|
+
return Response.json({
|
|
196
|
+
error: "payment_not_configured",
|
|
197
|
+
message: "This seller has no receiving wallet configured yet.",
|
|
198
|
+
}, { status: 402 });
|
|
199
|
+
}
|
|
200
|
+
function paymentUnavailableResponse(error) {
|
|
201
|
+
return Response.json({
|
|
202
|
+
error: "payment_unavailable",
|
|
203
|
+
message: `Payment is temporarily unavailable: ${describeError(error)}`,
|
|
204
|
+
}, { status: 503 });
|
|
205
|
+
}
|
|
206
|
+
export class PeerPay {
|
|
207
|
+
mode;
|
|
208
|
+
baseUrl;
|
|
209
|
+
checkout;
|
|
210
|
+
/** Subscription plans and their hosted `checkoutUrl` — see ./plans.ts. */
|
|
211
|
+
plans;
|
|
212
|
+
/** Reusable billing contacts for one-off invoices. */
|
|
213
|
+
customers;
|
|
214
|
+
/** Draft, finalize, deliver, and collect one-off invoices. */
|
|
215
|
+
invoices;
|
|
216
|
+
/**
|
|
217
|
+
* Payment mandates: bounded, revocable spending approvals a payer signs once.
|
|
218
|
+
*
|
|
219
|
+
* There is no `mandates.activate` on purpose — activation carries the
|
|
220
|
+
* *payer's* signature, is authorized by their wallet rather than by this API
|
|
221
|
+
* key, and therefore belongs in the payer-facing frontend. See the module
|
|
222
|
+
* comment in ./mandates.ts.
|
|
223
|
+
*/
|
|
224
|
+
mandates;
|
|
225
|
+
/**
|
|
226
|
+
* Webhook signature verification. Also exported as the free function
|
|
227
|
+
* `constructEvent` — a webhook route rarely has a client instance in scope,
|
|
228
|
+
* and verification needs the endpoint secret rather than the API key.
|
|
229
|
+
*/
|
|
230
|
+
webhooks;
|
|
231
|
+
apiKey;
|
|
232
|
+
fetchFn;
|
|
233
|
+
configTtlMs;
|
|
234
|
+
expectedPayTo;
|
|
235
|
+
cache;
|
|
236
|
+
inflight;
|
|
237
|
+
/**
|
|
238
|
+
* The single authenticated-JSON seam every resource goes through. Bound as a
|
|
239
|
+
* field so it can be handed to `./plans.ts` / `./mandates.ts` without leaking
|
|
240
|
+
* the key, the base URL or `fetch` into them.
|
|
241
|
+
*/
|
|
242
|
+
request = (options) => this.performRequest(options);
|
|
243
|
+
constructor(options) {
|
|
244
|
+
const apiKey = options.apiKey?.trim();
|
|
245
|
+
if (!apiKey) {
|
|
246
|
+
throw new PeerPayConfigError("apiKey (pp_sk_test_… / pp_sk_live_…) is required.");
|
|
247
|
+
}
|
|
248
|
+
this.apiKey = apiKey;
|
|
249
|
+
this.mode = parseKeyMode(apiKey);
|
|
250
|
+
const chosen = options.baseUrl?.trim() || MODE_BASE_URLS[this.mode];
|
|
251
|
+
if (!chosen) {
|
|
252
|
+
throw new PeerPayConfigError(`GenesisPay ${this.mode} base URL is not configured yet; pass baseUrl explicitly.`);
|
|
253
|
+
}
|
|
254
|
+
this.baseUrl = normalizeBaseUrl(chosen);
|
|
255
|
+
this.fetchFn = options.fetchFn ?? fetch;
|
|
256
|
+
this.configTtlMs = options.configTtlMs ?? 300_000;
|
|
257
|
+
this.expectedPayTo = options.expectedPayTo?.trim().toLowerCase() || undefined;
|
|
258
|
+
this.checkout = {
|
|
259
|
+
create: (input) => this.createCheckout(input),
|
|
260
|
+
retrieve: (publicId) => this.retrieveCheckout(publicId),
|
|
261
|
+
simulatePayment: (publicId, opts) => this.simulateCheckoutPayment(publicId, opts),
|
|
262
|
+
};
|
|
263
|
+
// Both resources get the same bound request seam, so their errors go
|
|
264
|
+
// through the one shared mapper in ./errors.ts like checkout's do.
|
|
265
|
+
this.plans = createPlansResource(this.request, (wallet, what) => this.assertPinnedDestination(wallet, what));
|
|
266
|
+
this.mandates = createMandatesResource(this.request);
|
|
267
|
+
this.customers = createCustomersResource(this.request);
|
|
268
|
+
this.invoices = createInvoicesResource(this.request);
|
|
269
|
+
// Stateless pass-through: verification depends only on the endpoint secret,
|
|
270
|
+
// never on this client's key, mode or base URL.
|
|
271
|
+
this.webhooks = {
|
|
272
|
+
constructEvent: (rawBody, signatureHeader, secret, opts) => constructEvent(rawBody, signatureHeader, secret, opts),
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Resolve (and cache) the seller config from the key. Single-flight so a
|
|
277
|
+
* cold-start burst shares one request; failures are never cached (the memo is
|
|
278
|
+
* cleared on rejection so the next call retries).
|
|
279
|
+
*/
|
|
280
|
+
async retrieveSeller(opts) {
|
|
281
|
+
const now = Date.now();
|
|
282
|
+
if (!opts?.forceRefresh && this.cache && now - this.cache.fetchedAt < this.configTtlMs) {
|
|
283
|
+
return this.cache.config;
|
|
284
|
+
}
|
|
285
|
+
if (!this.inflight) {
|
|
286
|
+
this.inflight = this.fetchSeller()
|
|
287
|
+
.then((config) => {
|
|
288
|
+
this.cache = { config, fetchedAt: Date.now() };
|
|
289
|
+
return config;
|
|
290
|
+
})
|
|
291
|
+
.finally(() => {
|
|
292
|
+
this.inflight = undefined;
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
return this.inflight;
|
|
296
|
+
}
|
|
297
|
+
gate(config) {
|
|
298
|
+
const innerGates = new Map();
|
|
299
|
+
const defaultSettle = peerPaySettlement({
|
|
300
|
+
facilitatorBaseUrl: this.baseUrl,
|
|
301
|
+
apiKey: this.apiKey,
|
|
302
|
+
fetchFn: this.fetchFn,
|
|
303
|
+
});
|
|
304
|
+
const buildInner = (seller) => {
|
|
305
|
+
// Key by (payTo, chainId): a wallet rotation after TTL builds a fresh gate,
|
|
306
|
+
// while any single gate stays internally consistent across challenge/replay.
|
|
307
|
+
const cacheKey = `${seller.payTo}:${seller.network.chainId}`;
|
|
308
|
+
let inner = innerGates.get(cacheKey);
|
|
309
|
+
if (!inner) {
|
|
310
|
+
inner = createPaymentGate({
|
|
311
|
+
amountUsdc: config.amountUsdc,
|
|
312
|
+
payTo: seller.payTo,
|
|
313
|
+
network: seller.network.networkName,
|
|
314
|
+
description: config.description,
|
|
315
|
+
resource: config.resource,
|
|
316
|
+
mimeType: config.mimeType,
|
|
317
|
+
maxTimeoutSeconds: config.maxTimeoutSeconds,
|
|
318
|
+
});
|
|
319
|
+
innerGates.set(cacheKey, inner);
|
|
320
|
+
}
|
|
321
|
+
return inner;
|
|
322
|
+
};
|
|
323
|
+
const resolveSeller = () => this.retrieveSeller();
|
|
324
|
+
return {
|
|
325
|
+
prime: async () => {
|
|
326
|
+
await resolveSeller();
|
|
327
|
+
},
|
|
328
|
+
wrap: (handler, opts) => {
|
|
329
|
+
const verifySettlement = opts?.verifySettlement ?? defaultSettle;
|
|
330
|
+
return async (request, ...args) => {
|
|
331
|
+
let seller;
|
|
332
|
+
try {
|
|
333
|
+
seller = await resolveSeller();
|
|
334
|
+
}
|
|
335
|
+
catch (error) {
|
|
336
|
+
// Fail closed: never run the paid handler when config can't be resolved.
|
|
337
|
+
return paymentUnavailableResponse(error);
|
|
338
|
+
}
|
|
339
|
+
if (!seller.hasPayTo || !seller.payTo) {
|
|
340
|
+
return paymentNotConfiguredResponse();
|
|
341
|
+
}
|
|
342
|
+
return buildInner(seller).wrap(handler, { verifySettlement })(request, ...args);
|
|
343
|
+
};
|
|
344
|
+
},
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
async fetchSeller() {
|
|
348
|
+
let response;
|
|
349
|
+
try {
|
|
350
|
+
response = await this.fetchFn(`${this.baseUrl}/api/v1/seller`, {
|
|
351
|
+
headers: { authorization: `Bearer ${this.apiKey}` },
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
catch (error) {
|
|
355
|
+
throw new PeerPayConfigError(`Failed to reach GenesisPay to resolve the seller: ${describeError(error)}`);
|
|
356
|
+
}
|
|
357
|
+
if (!response.ok) {
|
|
358
|
+
// 401/403/500 land on PeerPayConfigError with the key/base-URL hint; a
|
|
359
|
+
// 429 on the seller lookup is a rate limit like any other, not a broken key.
|
|
360
|
+
await throwForErrorResponse(response, {
|
|
361
|
+
operation: "GET /api/v1/seller",
|
|
362
|
+
hint: "Could not resolve the seller — check the API key and base URL.",
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
const config = (await response.json());
|
|
366
|
+
this.assertSafe(config);
|
|
367
|
+
return config;
|
|
368
|
+
}
|
|
369
|
+
assertSafe(config) {
|
|
370
|
+
const net = config.network;
|
|
371
|
+
// (1) Mode consistency: the mode encoded in the key prefix and the mode the
|
|
372
|
+
// server resolved from its stored column must agree. For keys minted by this
|
|
373
|
+
// system they always do (both come from the deployment network at creation);
|
|
374
|
+
// a disagreement means key/DB corruption or a spoofed response — fail closed.
|
|
375
|
+
if (config.mode !== this.mode) {
|
|
376
|
+
throw new PeerPayNetworkSafetyError(`Key mode "${this.mode}" does not match the server-resolved mode "${config.mode}".`);
|
|
377
|
+
}
|
|
378
|
+
// (2) Mode↔network: a live key must never resolve to a testnet, and vice
|
|
379
|
+
// versa. Checked before the asset table so an unknown/foreign network name
|
|
380
|
+
// surfaces as a typed safety error instead of a generic lookup throw.
|
|
381
|
+
if (!MODE_NETWORKS[this.mode].includes(net.networkName)) {
|
|
382
|
+
throw new PeerPayNetworkSafetyError(`A ${this.mode} key must not resolve to network "${net.networkName}".`);
|
|
383
|
+
}
|
|
384
|
+
// (3) Asset integrity: the backend-reported USDC/chainId must match the
|
|
385
|
+
// SDK's own native-USDC table for that (now-known) network.
|
|
386
|
+
const known = resolvePaymentGateNetwork(net.networkName);
|
|
387
|
+
if (known.chainId !== net.chainId ||
|
|
388
|
+
known.usdcAddress.toLowerCase() !== String(net.usdcAddress).toLowerCase()) {
|
|
389
|
+
throw new PeerPayNetworkSafetyError(`Backend network is inconsistent for "${net.networkName}" (chainId ${net.chainId}, usdc ${net.usdcAddress}).`);
|
|
390
|
+
}
|
|
391
|
+
// (4) Optional local pin on the payout wallet.
|
|
392
|
+
if (this.expectedPayTo && config.payTo && config.payTo.toLowerCase() !== this.expectedPayTo) {
|
|
393
|
+
throw new PeerPayNetworkSafetyError(`Resolved payTo does not match expectedPayTo.`);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Applies the `expectedPayTo` pin to a destination the server just froze onto
|
|
398
|
+
* a newly created object.
|
|
399
|
+
*
|
|
400
|
+
* Checking it in `assertSafe` alone was not enough: that only covers the
|
|
401
|
+
* `/api/v1/seller` config lookup, while a checkout link and a subscription
|
|
402
|
+
* plan each record their own `destinationWallet` at creation. Those are the
|
|
403
|
+
* addresses money actually moves to — a pin that does not cover them is not
|
|
404
|
+
* the guarantee the option advertises.
|
|
405
|
+
*/
|
|
406
|
+
assertPinnedDestination(wallet, what) {
|
|
407
|
+
if (!this.expectedPayTo)
|
|
408
|
+
return;
|
|
409
|
+
if (typeof wallet !== "string" || !wallet)
|
|
410
|
+
return;
|
|
411
|
+
if (wallet.toLowerCase() !== this.expectedPayTo) {
|
|
412
|
+
throw new PeerPayNetworkSafetyError(`The ${what} was created with a destinationWallet that does not match expectedPayTo.`);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* One authenticated JSON round-trip, with the error mapping every method
|
|
417
|
+
* shares. A transport failure (no response at all) is the only case handled
|
|
418
|
+
* here rather than in `throwForErrorResponse`, because there is no status to
|
|
419
|
+
* map — it is always a config/connectivity problem.
|
|
420
|
+
*/
|
|
421
|
+
async performRequest(options) {
|
|
422
|
+
const hasBody = options.body !== undefined;
|
|
423
|
+
let response;
|
|
424
|
+
try {
|
|
425
|
+
response = await this.fetchFn(`${this.baseUrl}${options.path}`, {
|
|
426
|
+
method: options.method ?? "GET",
|
|
427
|
+
headers: {
|
|
428
|
+
authorization: `Bearer ${this.apiKey}`,
|
|
429
|
+
...(hasBody ? { "content-type": "application/json" } : {}),
|
|
430
|
+
...options.headers,
|
|
431
|
+
},
|
|
432
|
+
...(hasBody ? { body: JSON.stringify(options.body) } : {}),
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
catch (error) {
|
|
436
|
+
throw new PeerPayConfigError(`Failed to reach GenesisPay to ${options.action}: ${describeError(error)}`);
|
|
437
|
+
}
|
|
438
|
+
if (!response.ok) {
|
|
439
|
+
// Shared mapping: 422 → PeerPayValidationError (with the field issues),
|
|
440
|
+
// 429 → PeerPayRateLimitError (with Retry-After), 404 → NotFound, rest → Config.
|
|
441
|
+
await throwForErrorResponse(response, {
|
|
442
|
+
operation: options.operation,
|
|
443
|
+
notFoundMessage: options.notFoundMessage,
|
|
444
|
+
hint: typeof options.hint === "function" ? options.hint(response.status) : options.hint,
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
// An OK response with an unparseable body yields null; each caller decides
|
|
448
|
+
// what a missing object means, and says so in its own error message.
|
|
449
|
+
return (await response.json().catch(() => null));
|
|
450
|
+
}
|
|
451
|
+
async createCheckout(input) {
|
|
452
|
+
const amount = resolveCheckoutAmount(input);
|
|
453
|
+
const body = await this.request({
|
|
454
|
+
method: "POST",
|
|
455
|
+
path: "/api/v1/links",
|
|
456
|
+
operation: "POST /api/v1/links",
|
|
457
|
+
action: "create a checkout link",
|
|
458
|
+
body: {
|
|
459
|
+
title: input.title,
|
|
460
|
+
description: input.description,
|
|
461
|
+
amount,
|
|
462
|
+
// Both names, one value: a backend older than 0.6.0 only knows
|
|
463
|
+
// `amountUsdc`, and a newer one accepts the pair precisely because they
|
|
464
|
+
// agree. Nothing here can disagree — it is the same string twice.
|
|
465
|
+
amountUsdc: amount,
|
|
466
|
+
linkType: input.linkType ?? "single",
|
|
467
|
+
...(input.destinationWallet ? { destinationWallet: input.destinationWallet } : {}),
|
|
468
|
+
...(input.asset ? { asset: input.asset } : {}),
|
|
469
|
+
...(input.metadata ? { metadata: input.metadata } : {}),
|
|
470
|
+
...(input.clientReferenceId ? { clientReferenceId: input.clientReferenceId } : {}),
|
|
471
|
+
...(input.returnUrl ? { returnUrl: input.returnUrl } : {}),
|
|
472
|
+
...(input.cancelUrl ? { cancelUrl: input.cancelUrl } : {}),
|
|
473
|
+
},
|
|
474
|
+
});
|
|
475
|
+
const link = asRecord(body)?.link;
|
|
476
|
+
if (!link || typeof link.payUrl !== "string" || !link.payUrl) {
|
|
477
|
+
throw new PeerPayConfigError(`GenesisPay link created but no payUrl in response: ${JSON.stringify(body)}`);
|
|
478
|
+
}
|
|
479
|
+
this.assertPinnedDestination(link.destinationWallet, "checkout link");
|
|
480
|
+
return toCheckoutLink(link);
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Fetch the current state of a checkout link. `paid` is the field to poll on;
|
|
484
|
+
* an unknown publicId raises `PeerPayNotFoundError`, never a config error.
|
|
485
|
+
*/
|
|
486
|
+
async retrieveCheckout(publicId) {
|
|
487
|
+
const id = publicId?.trim();
|
|
488
|
+
if (!id) {
|
|
489
|
+
throw new PeerPayConfigError("checkout.retrieve(publicId) requires the publicId returned by checkout.create().");
|
|
490
|
+
}
|
|
491
|
+
const body = await this.request({
|
|
492
|
+
path: `/api/v1/links/${encodeURIComponent(id)}`,
|
|
493
|
+
operation: `GET /api/v1/links/${id}`,
|
|
494
|
+
action: `retrieve checkout "${id}"`,
|
|
495
|
+
notFoundMessage: `No GenesisPay checkout with publicId "${id}". Check the id and that it belongs to the account this API key authenticates.`,
|
|
496
|
+
});
|
|
497
|
+
const link = asRecord(body)?.link;
|
|
498
|
+
if (!link || typeof link.publicId !== "string" || !link.publicId) {
|
|
499
|
+
throw new PeerPayConfigError(`GenesisPay returned no link for publicId "${id}": ${JSON.stringify(body)}`);
|
|
500
|
+
}
|
|
501
|
+
return toCheckoutSession(link);
|
|
502
|
+
}
|
|
503
|
+
/** Test-mode only — see the doc on `checkout.simulatePayment`. */
|
|
504
|
+
async simulateCheckoutPayment(publicId, opts) {
|
|
505
|
+
const id = publicId?.trim();
|
|
506
|
+
if (!id) {
|
|
507
|
+
throw new PeerPayConfigError("checkout.simulatePayment(publicId) requires the publicId returned by checkout.create().");
|
|
508
|
+
}
|
|
509
|
+
const body = await this.request({
|
|
510
|
+
method: "POST",
|
|
511
|
+
path: `/api/v1/links/${encodeURIComponent(id)}/simulate-payment`,
|
|
512
|
+
operation: `POST /api/v1/links/${id}/simulate-payment`,
|
|
513
|
+
action: `simulate a payment on checkout "${id}"`,
|
|
514
|
+
body: opts?.payerWallet ? { payerWallet: opts.payerWallet } : {},
|
|
515
|
+
// A 404 here has two very different causes and the server cannot tell you
|
|
516
|
+
// which — by design, since a mainnet deployment must not even confirm the
|
|
517
|
+
// endpoint exists. Naming both stops the "the id is definitely right, why
|
|
518
|
+
// is it 404" hunt at the wrong end.
|
|
519
|
+
notFoundMessage: `GenesisPay simulate-payment returned 404 for checkout "${id}". Either no such ` +
|
|
520
|
+
`checkout exists for the account this API key authenticates, or this GenesisPay ` +
|
|
521
|
+
`deployment runs on mainnet, where the endpoint does not exist at all. ` +
|
|
522
|
+
`Check the publicId first, then the deployment's network.`,
|
|
523
|
+
hint: (status) => status === 403 ? SIMULATE_PAYMENT_LIVE_KEY_HINT : undefined,
|
|
524
|
+
});
|
|
525
|
+
const record = asRecord(body);
|
|
526
|
+
const link = record?.link;
|
|
527
|
+
if (!link || typeof link.publicId !== "string" || !link.publicId) {
|
|
528
|
+
throw new PeerPayConfigError(`GenesisPay simulated a payment on "${id}" but returned no link: ${JSON.stringify(body)}`);
|
|
529
|
+
}
|
|
530
|
+
// The attempt is not an optional detail here the way an unknown field would
|
|
531
|
+
// be: without it the merged session would report `paid: false` right after
|
|
532
|
+
// a payment was minted. A 201 that omits it is a broken contract, not an
|
|
533
|
+
// older backend — the endpoint and the field shipped together.
|
|
534
|
+
const [attempt] = toCheckoutAttempts([record?.attempt]);
|
|
535
|
+
if (!attempt) {
|
|
536
|
+
throw new PeerPayConfigError(`GenesisPay simulated a payment on "${id}" but returned no attempt: ${JSON.stringify(body)}`);
|
|
537
|
+
}
|
|
538
|
+
return toSimulatedCheckoutSession(link, attempt);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAEvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAEzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,4BAA4B,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC1F,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEjD,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAE1D,OAAO,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EACL,QAAQ,EACR,KAAK,EACL,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,OAAO,GAGR,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAyM/C,4EAA4E;AAC5E,wEAAwE;AACxE,8BAA8B;AAC9B,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,GAEvB,MAAM,aAAa,CAAC;AAErB;;;;;GAKG;AACH,MAAM,+BAA+B,GAAG,+CAA+C,CAAC;AAExF,gFAAgF;AAChF,uFAAuF;AACvF,MAAM,cAAc,GAAmC;IACrD,IAAI,EAAE,4BAA4B;IAClC,IAAI,EAAE,+BAA+B;CACtC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,8BAA8B,GAClC,+EAA+E;IAC/E,6EAA6E,CAAC;AAEhF,oFAAoF;AACpF,MAAM,aAAa,GAAiD;IAClE,IAAI,EAAE,CAAC,cAAc,CAAC;IACtB,IAAI,EAAE,CAAC,MAAM,CAAC;CACf,CAAC;AAEF,SAAS,YAAY,CAAC,MAAc;IAClC,IAAI,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC;QAAE,OAAO,MAAM,CAAC;IACpD,IAAI,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,MAAM,CAAC,CAAC,qCAAqC;IACrF,MAAM,IAAI,kBAAkB,CAC1B,wEAAwE,CACzE,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAW;IACnC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,WAAW,GAAG,kDAAkD,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrF,IAAI,CAAC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;QAC7B,MAAM,IAAI,kBAAkB,CAAC,+BAA+B,OAAO,KAAK,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;AAClE,CAAC;AA+BD,SAAS,cAAc,CAAC,GAAoB;IAC1C,2EAA2E;IAC3E,4EAA4E;IAC5E,4EAA4E;IAC5E,uEAAuE;IACvE,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAE5F,OAAO;QACL,QAAQ,EAAE,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC;QACtC,MAAM,EAAE,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC;QAClC,MAAM;QACN,UAAU,EAAE,MAAM;QAClB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAU,EAAE,MAAM,CAAC;QAC1D,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC;QAChC,QAAQ,EAAE,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC;QACxC,iBAAiB,EAAE,cAAc,CAAC,GAAG,CAAC,iBAAiB,CAAC;QACxD,SAAS,EAAE,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC;QACxC,SAAS,EAAE,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC;KACzC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,KAAc;IACxC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAErC,MAAM,QAAQ,GAAsB,EAAE,CAAC;IACvC,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QAC1B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,SAAS;QAC1E,MAAM,GAAG,GAAG,KAAgC,CAAC;QAC7C,MAAM,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,EAAE;YAAE,SAAS;QAElB,QAAQ,CAAC,IAAI,CAAC;YACZ,EAAE;YACF,MAAM,EAAE,KAAK,CACX,GAAG,CAAC,MAAM,EACV,CAAC,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,CAAU,EACnE,SAAS,CACV;YACD,MAAM,EAAE,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC;YAClC,WAAW,EAAE,cAAc,CAAC,GAAG,CAAC,WAAW,CAAC;YAC5C,SAAS,EAAE,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC;YACxC,WAAW,EAAE,cAAc,CAAC,GAAG,CAAC,WAAW,CAAC;YAC5C,aAAa,EAAE,cAAc,CAAC,GAAG,CAAC,aAAa,CAAC;YAChD,wEAAwE;YACxE,uEAAuE;YACvE,SAAS,EAAE,GAAG,CAAC,SAAS,KAAK,IAAI;SAClC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAuB;IAChD,MAAM,qBAAqB,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;IACjE,OAAO;QACL,GAAG,cAAc,CAAC,GAAG,CAAC;QACtB,WAAW,EAAE,cAAc,CAAC,GAAG,CAAC,WAAW,CAAC;QAC5C,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAU,EAAE,QAAQ,CAAC;QACxE,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAU,EAAE,QAAQ,CAAC;QAC5E,iBAAiB,EAAE,cAAc,CAAC,GAAG,CAAC,iBAAiB,CAAC;QACxD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;QAC7B,8EAA8E;QAC9E,yEAAyE;QACzE,IAAI,EAAE,qBAAqB,GAAG,CAAC;QAC/B,qBAAqB;QACrB,SAAS,EAAE,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC;QACxC,QAAQ,EAAE,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC;KAC3C,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAS,0BAA0B,CACjC,OAA2B,EAC3B,OAAwB;IAExB,MAAM,OAAO,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,qBAAqB,GACzB,OAAO,CAAC,qBAAqB,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE3E,OAAO;QACL,GAAG,OAAO;QACV,QAAQ,EAAE,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC;QACxC,qBAAqB;QACrB,IAAI,EAAE,qBAAqB,GAAG,CAAC;KAChC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAS,eAAe,CAAC,CAAS,EAAE,CAAS;IAC3C,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE;QAAE,OAAO,KAAK,CAAC;IAExC,MAAM,UAAU,GAAG,CAAC,KAAa,EAAiB,EAAE;QAClD,IAAI,CAAC;YACH,OAAO,2BAA2B,CAAC,KAAK,CAAC,CAAC;QAC5C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACpD,OAAO,MAAM,KAAK,MAAM,CAAC;AAC3B,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,qBAAqB,CAAC,KAA0B;IACvD,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;IAErC,IAAI,MAAM,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QACrD,MAAM,IAAI,sBAAsB,CAC9B,yFAAyF,EACzF,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC,CACrD,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS,IAAI,eAAe,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC;QAC5F,MAAM,IAAI,sBAAsB,CAC9B,+BAA+B,MAAM,oCAAoC,UAAU,KAAK;YACtF,uDAAuD,EACzD,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,iCAAiC,EAAE,CAAC,CACjE,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,MAAM,IAAI,UAAU,CAAW,CAAC;AAC1C,CAAC;AAED,SAAS,4BAA4B;IACnC,OAAO,QAAQ,CAAC,IAAI,CAClB;QACE,KAAK,EAAE,wBAAwB;QAC/B,OAAO,EAAE,qDAAqD;KAC/D,EACD,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;AACJ,CAAC;AAED,SAAS,0BAA0B,CAAC,KAAc;IAChD,OAAO,QAAQ,CAAC,IAAI,CAClB;QACE,KAAK,EAAE,qBAAqB;QAC5B,OAAO,EAAE,uCAAuC,aAAa,CAAC,KAAK,CAAC,EAAE;KACvE,EACD,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,OAAO;IACT,IAAI,CAAiB;IACrB,OAAO,CAAS;IAChB,QAAQ,CAiBf;IACF,0EAA0E;IACjE,KAAK,CAAgB;IAC9B,sDAAsD;IAC7C,SAAS,CAAoB;IACtC,8DAA8D;IACrD,QAAQ,CAAmB;IACpC;;;;;;;OAOG;IACM,QAAQ,CAAmB;IACpC;;;;OAIG;IACM,QAAQ,CAOf;IAEe,MAAM,CAAS;IACf,OAAO,CAAe;IACtB,WAAW,CAAS;IACpB,aAAa,CAAU;IAEhC,KAAK,CAA+C;IACpD,QAAQ,CAAyB;IAEzC;;;;OAIG;IACc,OAAO,GAAmB,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAErF,YAAY,OAA6B;QACvC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;QACtC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,kBAAkB,CAAC,mDAAmD,CAAC,CAAC;QACpF,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;QAEjC,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,kBAAkB,CAC1B,cAAc,IAAI,CAAC,IAAI,2DAA2D,CACnF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC;QACxC,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC;QAClD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,SAAS,CAAC;QAE9E,IAAI,CAAC,QAAQ,GAAG;YACd,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC;YAC7C,QAAQ,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC;YACvD,eAAe,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,uBAAuB,CAAC,QAAQ,EAAE,IAAI,CAAC;SAClF,CAAC;QAEF,qEAAqE;QACrE,mEAAmE;QACnE,IAAI,CAAC,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAC9D,IAAI,CAAC,uBAAuB,CAAC,MAAM,EAAE,IAAI,CAAC,CAC3C,CAAC;QACF,IAAI,CAAC,QAAQ,GAAG,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrD,IAAI,CAAC,SAAS,GAAG,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvD,IAAI,CAAC,QAAQ,GAAG,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAErD,4EAA4E;QAC5E,gDAAgD;QAChD,IAAI,CAAC,QAAQ,GAAG;YACd,cAAc,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CACzD,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,IAAI,CAAC;SACzD,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,cAAc,CAAC,IAAiC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,EAAE,YAAY,IAAI,IAAI,CAAC,KAAK,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YACvF,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QAC3B,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE;iBAC/B,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;gBACf,IAAI,CAAC,KAAK,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBAC/C,OAAO,MAAM,CAAC;YAChB,CAAC,CAAC;iBACD,OAAO,CAAC,GAAG,EAAE;gBACZ,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;YAC5B,CAAC,CAAC,CAAC;QACP,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,IAAI,CAAC,MAAkB;QACrB,MAAM,UAAU,GAAG,IAAI,GAAG,EAAuB,CAAC;QAClD,MAAM,aAAa,GAAG,iBAAiB,CAAC;YACtC,kBAAkB,EAAE,IAAI,CAAC,OAAO;YAChC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,CAAC,MAAoB,EAAe,EAAE;YACvD,4EAA4E;YAC5E,6EAA6E;YAC7E,MAAM,QAAQ,GAAG,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAC7D,IAAI,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACrC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,KAAK,GAAG,iBAAiB,CAAC;oBACxB,UAAU,EAAE,MAAM,CAAC,UAAU;oBAC7B,KAAK,EAAE,MAAM,CAAC,KAAe;oBAC7B,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW;oBACnC,WAAW,EAAE,MAAM,CAAC,WAAW;oBAC/B,QAAQ,EAAE,MAAM,CAAC,QAAQ;oBACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ;oBACzB,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;iBAC5C,CAAC,CAAC;gBACH,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAClC,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC;QAEF,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;QAElD,OAAO;YACL,KAAK,EAAE,KAAK,IAAI,EAAE;gBAChB,MAAM,aAAa,EAAE,CAAC;YACxB,CAAC;YACD,IAAI,EAAE,CACJ,OAA0B,EAC1B,IAA8C,EAC9C,EAAE;gBACF,MAAM,gBAAgB,GAAG,IAAI,EAAE,gBAAgB,IAAI,aAAa,CAAC;gBACjE,OAAO,KAAK,EAAE,OAAgB,EAAE,GAAG,IAAU,EAAqB,EAAE;oBAClE,IAAI,MAAoB,CAAC;oBACzB,IAAI,CAAC;wBACH,MAAM,GAAG,MAAM,aAAa,EAAE,CAAC;oBACjC,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,yEAAyE;wBACzE,OAAO,0BAA0B,CAAC,KAAK,CAAC,CAAC;oBAC3C,CAAC;oBACD,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;wBACtC,OAAO,4BAA4B,EAAE,CAAC;oBACxC,CAAC;oBACD,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,gBAAgB,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;gBAClF,CAAC,CAAC;YACJ,CAAC;SACF,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,WAAW;QACvB,IAAI,QAAkB,CAAC;QACvB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,gBAAgB,EAAE;gBAC7D,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE,EAAE;aACpD,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,kBAAkB,CAC1B,qDAAqD,aAAa,CAAC,KAAK,CAAC,EAAE,CAC5E,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,uEAAuE;YACvE,6EAA6E;YAC7E,MAAM,qBAAqB,CAAC,QAAQ,EAAE;gBACpC,SAAS,EAAE,oBAAoB;gBAC/B,IAAI,EAAE,gEAAgE;aACvE,CAAC,CAAC;QACL,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAiB,CAAC;QACvD,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACxB,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,UAAU,CAAC,MAAoB;QACrC,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC;QAE3B,4EAA4E;QAC5E,6EAA6E;QAC7E,6EAA6E;QAC7E,8EAA8E;QAC9E,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,yBAAyB,CACjC,aAAa,IAAI,CAAC,IAAI,8CAA8C,MAAM,CAAC,IAAI,IAAI,CACpF,CAAC;QACJ,CAAC;QAED,yEAAyE;QACzE,2EAA2E;QAC3E,sEAAsE;QACtE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YACxD,MAAM,IAAI,yBAAyB,CACjC,KAAK,IAAI,CAAC,IAAI,qCAAqC,GAAG,CAAC,WAAW,IAAI,CACvE,CAAC;QACJ,CAAC;QAED,wEAAwE;QACxE,4DAA4D;QAC5D,MAAM,KAAK,GAAG,yBAAyB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACzD,IACE,KAAK,CAAC,OAAO,KAAK,GAAG,CAAC,OAAO;YAC7B,KAAK,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,EACzE,CAAC;YACD,MAAM,IAAI,yBAAyB,CACjC,wCAAwC,GAAG,CAAC,WAAW,cAAc,GAAG,CAAC,OAAO,UAAU,GAAG,CAAC,WAAW,IAAI,CAC9G,CAAC;QACJ,CAAC;QAED,+CAA+C;QAC/C,IAAI,IAAI,CAAC,aAAa,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC;YAC5F,MAAM,IAAI,yBAAyB,CACjC,8CAA8C,CAC/C,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;;;;;OASG;IACK,uBAAuB,CAAC,MAAe,EAAE,IAAY;QAC3D,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE,OAAO;QAChC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM;YAAE,OAAO;QAClD,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC;YAChD,MAAM,IAAI,yBAAyB,CACjC,OAAO,IAAI,0EAA0E,CACtF,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,cAAc,CAAC,OAA8B;QACzD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC;QAC3C,IAAI,QAAkB,CAAC;QACvB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,EAAE;gBAC9D,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;gBAC/B,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;oBACtC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC1D,GAAG,OAAO,CAAC,OAAO;iBACnB;gBACD,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC3D,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,kBAAkB,CAC1B,iCAAiC,OAAO,CAAC,MAAM,KAAK,aAAa,CAAC,KAAK,CAAC,EAAE,CAC3E,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,wEAAwE;YACxE,iFAAiF;YACjF,MAAM,qBAAqB,CAAC,QAAQ,EAAE;gBACpC,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,eAAe,EAAE,OAAO,CAAC,eAAe;gBACxC,IAAI,EACF,OAAO,OAAO,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI;aACpF,CAAC,CAAC;QACL,CAAC;QAED,2EAA2E;QAC3E,qEAAqE;QACrE,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAY,CAAC;IAC9D,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,KAA0B;QACrD,MAAM,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;QAE5C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC;YAC9B,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,eAAe;YACrB,SAAS,EAAE,oBAAoB;YAC/B,MAAM,EAAE,wBAAwB;YAChC,IAAI,EAAE;gBACJ,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,MAAM;gBACN,+DAA+D;gBAC/D,wEAAwE;gBACxE,kEAAkE;gBAClE,UAAU,EAAE,MAAM;gBAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,QAAQ;gBACpC,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAClF,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9C,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvD,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAClF,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1D,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC3D;SACF,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAmC,CAAC;QACjE,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YAC7D,MAAM,IAAI,kBAAkB,CAC1B,sDAAsD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAC7E,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,uBAAuB,CACzB,IAAwC,CAAC,iBAAiB,EAC3D,eAAe,CAChB,CAAC;QACF,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,gBAAgB,CAAC,QAAgB;QAC7C,MAAM,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,MAAM,IAAI,kBAAkB,CAC1B,kFAAkF,CACnF,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC;YAC9B,IAAI,EAAE,iBAAiB,kBAAkB,CAAC,EAAE,CAAC,EAAE;YAC/C,SAAS,EAAE,qBAAqB,EAAE,EAAE;YACpC,MAAM,EAAE,sBAAsB,EAAE,GAAG;YACnC,eAAe,EAAE,yCAAyC,EAAE,gFAAgF;SAC7I,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAsC,CAAC;QACpE,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjE,MAAM,IAAI,kBAAkB,CAC1B,6CAA6C,EAAE,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAC5E,CAAC;QACJ,CAAC;QACD,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,kEAAkE;IAC1D,KAAK,CAAC,uBAAuB,CACnC,QAAgB,EAChB,IAA6B;QAE7B,MAAM,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,MAAM,IAAI,kBAAkB,CAC1B,yFAAyF,CAC1F,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC;YAC9B,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,iBAAiB,kBAAkB,CAAC,EAAE,CAAC,mBAAmB;YAChE,SAAS,EAAE,sBAAsB,EAAE,mBAAmB;YACtD,MAAM,EAAE,mCAAmC,EAAE,GAAG;YAChD,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE;YAChE,0EAA0E;YAC1E,0EAA0E;YAC1E,0EAA0E;YAC1E,oCAAoC;YACpC,eAAe,EACb,0DAA0D,EAAE,oBAAoB;gBAChF,iFAAiF;gBACjF,wEAAwE;gBACxE,0DAA0D;YAC5D,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CACf,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,SAAS;SAC9D,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,IAAI,GAAG,MAAM,EAAE,IAAsC,CAAC;QAC5D,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjE,MAAM,IAAI,kBAAkB,CAC1B,sCAAsC,EAAE,2BAA2B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAC1F,CAAC;QACJ,CAAC;QAED,4EAA4E;QAC5E,2EAA2E;QAC3E,yEAAyE;QACzE,+DAA+D;QAC/D,MAAM,CAAC,OAAO,CAAC,GAAG,kBAAkB,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;QACxD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,kBAAkB,CAC1B,sCAAsC,EAAE,8BAA8B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAC7F,CAAC;QACJ,CAAC;QACD,OAAO,0BAA0B,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC;CACF"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type PeerPayRequest } from "./resource.js";
|
|
2
|
+
export type Customer = {
|
|
3
|
+
id: string;
|
|
4
|
+
publicId: string;
|
|
5
|
+
name: string;
|
|
6
|
+
email: string;
|
|
7
|
+
companyName: string | null;
|
|
8
|
+
addressLine1: string | null;
|
|
9
|
+
addressLine2: string | null;
|
|
10
|
+
city: string | null;
|
|
11
|
+
postalCode: string | null;
|
|
12
|
+
countryCode: string | null;
|
|
13
|
+
taxId: string | null;
|
|
14
|
+
metadata: Record<string, string> | null;
|
|
15
|
+
createdAt: string;
|
|
16
|
+
updatedAt: string;
|
|
17
|
+
archivedAt: string | null;
|
|
18
|
+
};
|
|
19
|
+
export type CustomerCreateInput = {
|
|
20
|
+
name: string;
|
|
21
|
+
email: string;
|
|
22
|
+
companyName?: string;
|
|
23
|
+
addressLine1?: string;
|
|
24
|
+
addressLine2?: string;
|
|
25
|
+
city?: string;
|
|
26
|
+
postalCode?: string;
|
|
27
|
+
countryCode?: string;
|
|
28
|
+
taxId?: string;
|
|
29
|
+
metadata?: Record<string, string>;
|
|
30
|
+
};
|
|
31
|
+
export type CustomerUpdateInput = Partial<CustomerCreateInput>;
|
|
32
|
+
export interface CustomersResource {
|
|
33
|
+
create(input: CustomerCreateInput): Promise<Customer>;
|
|
34
|
+
list(): Promise<Customer[]>;
|
|
35
|
+
retrieve(publicId: string): Promise<Customer>;
|
|
36
|
+
update(publicId: string, input: CustomerUpdateInput): Promise<Customer>;
|
|
37
|
+
archive(publicId: string): Promise<Customer>;
|
|
38
|
+
}
|
|
39
|
+
export declare function createCustomersResource(request: PeerPayRequest): CustomersResource;
|
|
40
|
+
export declare function toCustomer(raw: Record<string, unknown>): Customer;
|
|
41
|
+
//# sourceMappingURL=customers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"customers.d.ts","sourceRoot":"","sources":["../src/customers.ts"],"names":[],"mappings":"AAGA,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,eAAe,CAAC;AAEvB,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAE/D,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtD,IAAI,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxE,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC9C;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,cAAc,GAAG,iBAAiB,CAoDlF;AAmCD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,QAAQ,CAkBjE"}
|