@klappay/types 2.0.2 → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -28,6 +28,7 @@ __export(index_exports, {
28
28
  CHARGE_EXPIRES_IN_MAX_SECONDS: () => CHARGE_EXPIRES_IN_MAX_SECONDS,
29
29
  CHARGE_EXPIRES_IN_MIN_SECONDS: () => CHARGE_EXPIRES_IN_MIN_SECONDS,
30
30
  CHARGE_SPLIT_RECIPIENTS_MAX: () => CHARGE_SPLIT_RECIPIENTS_MAX,
31
+ CHECKOUT_PRODUCTS_MAX: () => CHECKOUT_PRODUCTS_MAX,
31
32
  CapabilitiesSchema: () => CapabilitiesSchema,
32
33
  ChargeSchema: () => ChargeSchema,
33
34
  ChargeStatusSchema: () => ChargeStatusSchema,
@@ -35,6 +36,7 @@ __export(index_exports, {
35
36
  ChargesDateFieldSchema: () => ChargesDateFieldSchema,
36
37
  ChargesMetricFieldSchema: () => ChargesMetricFieldSchema,
37
38
  ChargesQueryFieldSchema: () => ChargesQueryFieldSchema,
39
+ CheckoutProductSchema: () => CheckoutProductSchema,
38
40
  CreateChargeSchema: () => CreateChargeSchema,
39
41
  CreateWebhookSchema: () => CreateWebhookSchema,
40
42
  DistributionsDateFieldSchema: () => DistributionsDateFieldSchema,
@@ -46,6 +48,7 @@ __export(index_exports, {
46
48
  ErrorPayloadSchema: () => ErrorPayloadSchema,
47
49
  GetChargeQrCodeQuerySchema: () => GetChargeQrCodeQuerySchema,
48
50
  HealthSchema: () => HealthSchema,
51
+ KlappayCheckoutMetadataSchema: () => KlappayCheckoutMetadataSchema,
49
52
  ListChargesSchema: () => ListChargesSchema,
50
53
  ListWebhookDeliveriesSchema: () => ListWebhookDeliveriesSchema,
51
54
  ListenPendingDistributionsQuerySchema: () => ListenPendingDistributionsQuerySchema,
@@ -55,6 +58,7 @@ __export(index_exports, {
55
58
  METRICS_QUERY_MAX_GROUP_BY: () => METRICS_QUERY_MAX_GROUP_BY,
56
59
  METRICS_QUERY_MAX_METRICS: () => METRICS_QUERY_MAX_METRICS,
57
60
  METRICS_QUERY_MAX_ROW_LIMIT: () => METRICS_QUERY_MAX_ROW_LIMIT,
61
+ MetadataWithKlappaySchema: () => MetadataWithKlappaySchema,
58
62
  MetricsAggregationSchema: () => MetricsAggregationSchema,
59
63
  MetricsDateGranularitySchema: () => MetricsDateGranularitySchema,
60
64
  MetricsFilterOperatorSchema: () => MetricsFilterOperatorSchema,
@@ -240,27 +244,50 @@ var TOKEN_ADDRESSES = {
240
244
  };
241
245
 
242
246
  // src/charges.ts
247
+ var import_zod8 = require("zod");
248
+
249
+ // src/checkout-metadata.ts
243
250
  var import_zod7 = require("zod");
244
- var ChargeStatusSchema = import_zod7.z.enum(["pending", "partially_paid", "confirmed", "expired", "underpaid"]).describe(
251
+ var CHECKOUT_PRODUCTS_MAX = 20;
252
+ var CheckoutProductSchema = import_zod7.z.object({
253
+ name: import_zod7.z.string().min(1).max(200).describe("What the payer is buying, shown as-is on the hosted checkout page."),
254
+ quantity: import_zod7.z.number().int().positive().max(9999).optional().describe("How many of this item. Omit for a single, unquantified item."),
255
+ imageUrl: import_zod7.z.string().url().max(2048).refine((value) => /^https?:\/\//.test(value), "must use http or https").optional().describe(
256
+ "Product image, fetched only by the payer's own browser \u2014 Klappay never fetches it server-side. Must be `http(s)`."
257
+ )
258
+ });
259
+ var KlappayCheckoutMetadataSchema = import_zod7.z.object({
260
+ products: import_zod7.z.array(CheckoutProductSchema).max(CHECKOUT_PRODUCTS_MAX).optional().describe(
261
+ `What the payer is buying, shown on the hosted checkout page \u2014 up to ${CHECKOUT_PRODUCTS_MAX} items. Purely informational: never validated against \`amount\`, never used by any payment or distribution logic.`
262
+ )
263
+ }).describe(
264
+ "Reserved for Klappay \u2014 the one namespace inside `metadata` whose format is defined and enforced by Klappay, not by you. A `metadata.klappay` that does not match this shape is rejected outright (`400 validation_error`), unlike every other key in `metadata`, which accepts absolutely anything and never fails validation."
265
+ );
266
+ var MetadataWithKlappaySchema = import_zod7.z.object({ klappay: KlappayCheckoutMetadataSchema.optional() }).catchall(import_zod7.z.unknown()).describe(
267
+ "Arbitrary key/value data, returned as-is on every read. Put whatever you want in here \u2014 none of it is validated, except the `klappay` key, which is reserved for Klappay: if present, it must match `KlappayCheckoutMetadataSchema` exactly, or the whole request is rejected with `400 validation_error`."
268
+ );
269
+
270
+ // src/charges.ts
271
+ var ChargeStatusSchema = import_zod8.z.enum(["pending", "partially_paid", "confirmed", "expired", "underpaid"]).describe(
245
272
  "Payment progress, from the payer side. `pending`: created, nothing received yet. `partially_paid`: some funds received, less than `amount`. `confirmed`: full amount received (or more \u2014 see `isOverpaid`). `expired`: `expiresAt` passed with zero funds received. `underpaid`: `expiresAt` passed while `partially_paid`. Every status is reached automatically, on its own timeline \u2014 there is no merchant-initiated cancellation. This never reflects whether funds actually reached the merchant \u2014 see `settlementStatus` for that."
246
273
  );
247
- var SettlementStatusSchema = import_zod7.z.enum(["pending", "completed", "failed"]).describe(
274
+ var SettlementStatusSchema = import_zod8.z.enum(["pending", "completed", "failed"]).describe(
248
275
  "Progress of the payout to the merchant's wallet, a separate step from `status` \u2014 `status: confirmed` only means the payment was detected on-chain, not that the merchant has been paid yet. `pending`: payment detected, payout not yet attempted. `completed`: the merchant's wallet has the funds. `failed`: the payout attempt failed and retries were exhausted (rare; contact support). `null` on the parent `Charge` means no payout has been attempted yet \u2014 nothing has been received, or the charge is still in progress."
249
276
  );
250
277
  var CHARGE_EXPIRES_IN_MIN_SECONDS = 60;
251
278
  var CHARGE_EXPIRES_IN_MAX_SECONDS = 3600;
252
279
  var CHARGE_ACCEPTED_PAYMENTS_MAX = 14;
253
- var AcceptedPaymentSchema = import_zod7.z.object({
280
+ var AcceptedPaymentSchema = import_zod8.z.object({
254
281
  token: TokenSchema,
255
282
  network: NetworkSchema
256
283
  });
257
- var AcceptedPaymentsSchema = import_zod7.z.array(AcceptedPaymentSchema).min(1, "At least one accepted payment is required.").max(CHARGE_ACCEPTED_PAYMENTS_MAX).superRefine((pairs, ctx) => {
284
+ var AcceptedPaymentsSchema = import_zod8.z.array(AcceptedPaymentSchema).min(1, "At least one accepted payment is required.").max(CHARGE_ACCEPTED_PAYMENTS_MAX).superRefine((pairs, ctx) => {
258
285
  const seen = /* @__PURE__ */ new Set();
259
286
  pairs.forEach((pair, index) => {
260
287
  const key = `${pair.token}:${pair.network}`;
261
288
  if (seen.has(key)) {
262
289
  ctx.addIssue({
263
- code: import_zod7.z.ZodIssueCode.custom,
290
+ code: import_zod8.z.ZodIssueCode.custom,
264
291
  message: `Duplicate accepted payment: ${pair.token} on ${pair.network}.`,
265
292
  path: [index]
266
293
  });
@@ -268,7 +295,7 @@ var AcceptedPaymentsSchema = import_zod7.z.array(AcceptedPaymentSchema).min(1, "
268
295
  seen.add(key);
269
296
  if (!OPERATIONAL_NETWORKS.includes(pair.network)) {
270
297
  ctx.addIssue({
271
- code: import_zod7.z.ZodIssueCode.custom,
298
+ code: import_zod8.z.ZodIssueCode.custom,
272
299
  message: `Network "${pair.network}" isn't live yet \u2014 only ${OPERATIONAL_NETWORKS.join(", ")} today.`,
273
300
  path: [index, "network"]
274
301
  });
@@ -278,22 +305,22 @@ var AcceptedPaymentsSchema = import_zod7.z.array(AcceptedPaymentSchema).min(1, "
278
305
  `Every \`(token, network)\` pair the payer is allowed to pay with \u2014 at least one, up to ${CHARGE_ACCEPTED_PAYMENTS_MAX}. This list is also the only restriction knob: the payer can use any combination of the pairs listed here, and every transfer on one of them is credited and sums toward the charge total (see \`paidWith\`) \u2014 e.g. a charge accepting USDC and USDT can be confirmed by $9 in USDC plus $1 in USDT, or by USDC arriving on two different accepted networks. To require payment in one specific token on one specific network, list only that single pair \u2014 a transfer on any pair not in this list is still recorded (for audit) but never credited. Each network must be live (see \`GET /v1/networks\` for the current matrix) \u2014 an unconfigured \`(token, network)\` combination for your environment is rejected with \`422 token_not_supported\`.`
279
306
  );
280
307
  var CHARGE_SPLIT_RECIPIENTS_MAX = 5;
281
- var SplitRecipientSchema = import_zod7.z.object({
282
- address: import_zod7.z.string().regex(/^0x[0-9a-fA-F]{40}$/, "must be a 20-byte hex address").describe("EVM address to send a slice of this charge to."),
283
- percent: import_zod7.z.number().positive().max(100).describe(
308
+ var SplitRecipientSchema = import_zod8.z.object({
309
+ address: import_zod8.z.string().regex(/^0x[0-9a-fA-F]{40}$/, "must be a 20-byte hex address").describe("EVM address to send a slice of this charge to."),
310
+ percent: import_zod8.z.number().positive().max(100).describe(
284
311
  "Percent of *your own* net share (i.e. of `100 - feePercent`, not of the charge's gross `amount`) to route to this address instead of your own payout wallet. Klappay's fee is computed on the gross amount first and is never diluted by how you choose to split what's left \u2014 see `docs/payments.md`'s \"Settling the payout\" section for the exact math."
285
312
  ),
286
- label: import_zod7.z.string().min(1).max(64).optional().describe(
313
+ label: import_zod8.z.string().min(1).max(64).optional().describe(
287
314
  'Free-form label for your own bookkeeping (e.g. `"supplier"`, `"sales rep"`) \u2014 echoed back unchanged, never interpreted by Klappay.'
288
315
  )
289
316
  });
290
- var SplitRecipientsSchema = import_zod7.z.array(SplitRecipientSchema).max(CHARGE_SPLIT_RECIPIENTS_MAX).superRefine((recipients, ctx) => {
317
+ var SplitRecipientsSchema = import_zod8.z.array(SplitRecipientSchema).max(CHARGE_SPLIT_RECIPIENTS_MAX).superRefine((recipients, ctx) => {
291
318
  const seen = /* @__PURE__ */ new Set();
292
319
  recipients.forEach((recipient, index) => {
293
320
  const key = recipient.address.toLowerCase();
294
321
  if (seen.has(key)) {
295
322
  ctx.addIssue({
296
- code: import_zod7.z.ZodIssueCode.custom,
323
+ code: import_zod8.z.ZodIssueCode.custom,
297
324
  message: `Duplicate split recipient address: ${recipient.address}.`,
298
325
  path: [index, "address"]
299
326
  });
@@ -304,79 +331,79 @@ var SplitRecipientsSchema = import_zod7.z.array(SplitRecipientSchema).max(CHARGE
304
331
  `Optional extra recipients for this charge's split \u2014 e.g. a supplier or the sales rep who closed the deal \u2014 up to ${CHARGE_SPLIT_RECIPIENTS_MAX}. Frozen at creation exactly like everything else that shapes the split address; cannot be changed afterward. The sum of every \`percent\` here must fit within \`100 - feePercent\` (your own net share) \u2014 a request that doesn't is rejected with \`422 split_recipients_exceed_available_percent\`.`
305
332
  );
306
333
  var CHARGE_AMOUNT_MAX = 999999999999;
307
- var CreateChargeSchema = import_zod7.z.object({
308
- amount: import_zod7.z.number().positive().max(CHARGE_AMOUNT_MAX).describe(
334
+ var CreateChargeSchema = import_zod8.z.object({
335
+ amount: import_zod8.z.number().positive().max(CHARGE_AMOUNT_MAX).describe(
309
336
  "Amount to charge, in `currency` units (e.g. `49.9` = $49.90) \u2014 up to 6 decimal places; anything more precise is silently truncated. Required \u2014 every charge has a target amount, the first credited transfer that reaches it confirms the charge."
310
337
  ),
311
- currency: import_zod7.z.literal("USD").default("USD").describe("Always `USD` today \u2014 the only supported currency."),
338
+ currency: import_zod8.z.literal("USD").default("USD").describe("Always `USD` today \u2014 the only supported currency."),
312
339
  acceptedPayments: AcceptedPaymentsSchema,
313
- expiresIn: import_zod7.z.number().int().min(CHARGE_EXPIRES_IN_MIN_SECONDS).max(CHARGE_EXPIRES_IN_MAX_SECONDS).describe(
340
+ expiresIn: import_zod8.z.number().int().min(CHARGE_EXPIRES_IN_MIN_SECONDS).max(CHARGE_EXPIRES_IN_MAX_SECONDS).describe(
314
341
  "Seconds, not minutes or milliseconds \u2014 how long the charge stays open before it expires. Required, min 60, max 3600 (60 minutes) \u2014 sized off the slowest chain Klappay supports today (Ethereum mainnet, where a safely-confirmed transfer takes up to ~15 minutes), leaving real margin for payer-side delay (gas spikes, wallet friction) on top of that. Cannot be extended or shortened after creation."
315
342
  ),
316
- idempotencyKey: import_zod7.z.string().min(1).max(255).optional().describe(
343
+ idempotencyKey: import_zod8.z.string().min(1).max(255).optional().describe(
317
344
  "Scoped to your tenant. Replaying the same key returns the original charge unchanged instead of creating a duplicate \u2014 safe to retry a request after a timeout without double-charging."
318
345
  ),
319
- externalRef: import_zod7.z.string().min(1).max(255).optional().describe(
346
+ externalRef: import_zod8.z.string().min(1).max(255).optional().describe(
320
347
  "An opaque correlation id from your own system (e.g. an order id) \u2014 echoed back on the charge and in every webhook payload. Not interpreted or validated by Klappay."
321
348
  ),
322
- source: import_zod7.z.string().min(1).max(64).optional().describe(
349
+ source: import_zod8.z.string().min(1).max(64).optional().describe(
323
350
  'Free-form label for what created this charge (e.g. `"checkout"`, `"invoice"`) \u2014 useful if you create charges from more than one flow and want to tell them apart later. Not a fixed enum; use whatever values make sense to you.'
324
351
  ),
325
- metadata: import_zod7.z.record(import_zod7.z.string(), import_zod7.z.unknown()).optional().describe("Arbitrary key/value data to attach to the charge, returned as-is on every read."),
326
- redirectUrl: import_zod7.z.string().url().refine((value) => /^https?:\/\//.test(value), "must use http or https").optional().describe(
352
+ metadata: MetadataWithKlappaySchema.optional(),
353
+ redirectUrl: import_zod8.z.string().url().refine((value) => /^https?:\/\//.test(value), "must use http or https").optional().describe(
327
354
  "Where to send the payer once this charge resolves, if you use Klappay's hosted checkout page (see `checkoutUrl` on the read shape) \u2014 ignored otherwise. Must be `http(s)` \u2014 a browser will navigate here, so `javascript:`/`data:` and other non-navigational schemes are rejected. Otherwise not validated beyond being well-formed; what happens at that destination is yours to build."
328
355
  ),
329
356
  splitRecipients: SplitRecipientsSchema.optional()
330
357
  });
331
- var ChargeSchema = import_zod7.z.object({
332
- id: import_zod7.z.string().describe("Klappay-generated id, e.g. `ch_...`. Use this to look up the charge later."),
333
- amount: import_zod7.z.number().describe("The amount originally requested, in `currency` units (up to 6 decimal places)."),
334
- amountReceived: import_zod7.z.number().nullable().describe(
358
+ var ChargeSchema = import_zod8.z.object({
359
+ id: import_zod8.z.string().describe("Klappay-generated id, e.g. `ch_...`. Use this to look up the charge later."),
360
+ amount: import_zod8.z.number().describe("The amount originally requested, in `currency` units (up to 6 decimal places)."),
361
+ amountReceived: import_zod8.z.number().nullable().describe(
335
362
  "Cumulative amount actually received on-chain so far, in `currency` units (up to 6 decimal places). `null` until the first transfer arrives. Can exceed `amount` \u2014 see `isOverpaid`."
336
363
  ),
337
- isOverpaid: import_zod7.z.boolean().describe(
364
+ isOverpaid: import_zod8.z.boolean().describe(
338
365
  "`true` if `amountReceived` ended up greater than `amount`. Klappay never refunds the difference automatically \u2014 see the docs for why."
339
366
  ),
340
- currency: import_zod7.z.string().describe("Always `USD` today \u2014 the only supported currency."),
341
- acceptedPayments: import_zod7.z.array(AcceptedPaymentSchema).describe(
367
+ currency: import_zod8.z.string().describe("Always `USD` today \u2014 the only supported currency."),
368
+ acceptedPayments: import_zod8.z.array(AcceptedPaymentSchema).describe(
342
369
  "Every `(token, network)` pair this charge was configured to accept, unchanged after creation."
343
370
  ),
344
- paidWith: import_zod7.z.array(AcceptedPaymentSchema).describe(
371
+ paidWith: import_zod8.z.array(AcceptedPaymentSchema).describe(
345
372
  "Every distinct `(token, network)` pair that has actually contributed a credited transfer so far \u2014 empty until the first one arrives. Can hold more than one entry: a charge accepting several pairs can be paid across a combination of them, and every entry here sums toward `amountReceived`."
346
373
  ),
347
- address: import_zod7.z.string().describe(
374
+ address: import_zod8.z.string().describe(
348
375
  "The on-chain address the payer must send funds to \u2014 identical across every accepted network (0xSplits addresses are chain-agnostic). Unique per charge, predicted at creation time \u2014 funds sent here go directly to the merchant, Klappay never custodies them."
349
376
  ),
350
377
  status: ChargeStatusSchema,
351
378
  settlementStatus: SettlementStatusSchema.nullable(),
352
379
  environment: EnvironmentSchema,
353
- apiKeyId: import_zod7.z.string().nullable().describe(
380
+ apiKeyId: import_zod8.z.string().nullable().describe(
354
381
  "Which of your API keys created this charge. `null` for a charge created before this field existed."
355
382
  ),
356
- txHash: import_zod7.z.string().nullable().describe(
383
+ txHash: import_zod8.z.string().nullable().describe(
357
384
  "Transaction hash of the most recent transfer detected for this charge. `null` until a payment is detected."
358
385
  ),
359
- externalRef: import_zod7.z.string().nullable(),
360
- source: import_zod7.z.string().nullable(),
361
- metadata: import_zod7.z.record(import_zod7.z.string(), import_zod7.z.unknown()).nullable(),
362
- redirectUrl: import_zod7.z.string().nullable().describe("Echoes the `redirectUrl` set at creation, if any. `null` if none was set."),
363
- checkoutUrl: import_zod7.z.string().nullable().describe(
386
+ externalRef: import_zod8.z.string().nullable(),
387
+ source: import_zod8.z.string().nullable(),
388
+ metadata: MetadataWithKlappaySchema.nullable(),
389
+ redirectUrl: import_zod8.z.string().nullable().describe("Echoes the `redirectUrl` set at creation, if any. `null` if none was set."),
390
+ checkoutUrl: import_zod8.z.string().nullable().describe(
364
391
  "Link to Klappay's hosted checkout page for this charge. `null` if this deployment has no hosted checkout configured \u2014 build your own payment UI from `address`/`acceptedPayments` instead."
365
392
  ),
366
- splitRecipients: import_zod7.z.array(SplitRecipientSchema).describe("Echoes whatever extra split recipients were set at creation \u2014 empty array if none."),
367
- createdAt: import_zod7.z.string().datetime(),
368
- expiresAt: import_zod7.z.string().datetime().describe(
393
+ splitRecipients: import_zod8.z.array(SplitRecipientSchema).describe("Echoes whatever extra split recipients were set at creation \u2014 empty array if none."),
394
+ createdAt: import_zod8.z.string().datetime(),
395
+ expiresAt: import_zod8.z.string().datetime().describe(
369
396
  "When this charge stops accepting payment, if still `pending`/`partially_paid` by then."
370
397
  ),
371
- confirmedAt: import_zod7.z.string().datetime().nullable().describe("When `status` first reached `confirmed`. `null` until then."),
372
- settledAt: import_zod7.z.string().datetime().nullable().describe(
398
+ confirmedAt: import_zod8.z.string().datetime().nullable().describe("When `status` first reached `confirmed`. `null` until then."),
399
+ settledAt: import_zod8.z.string().datetime().nullable().describe(
373
400
  "When `settlementStatus` first reached `completed` \u2014 the merchant's wallet actually has the funds. `null` until then, including while `settlementStatus` is `pending`/`failed`."
374
401
  ),
375
- lastActivityAt: import_zod7.z.string().datetime().describe(
402
+ lastActivityAt: import_zod8.z.string().datetime().describe(
376
403
  "When a transfer was last credited toward this charge, or `createdAt` if none has arrived yet."
377
404
  )
378
405
  });
379
- var ListChargesSchema = import_zod7.z.object({
406
+ var ListChargesSchema = import_zod8.z.object({
380
407
  status: ChargeStatusSchema.optional(),
381
408
  token: TokenSchema.optional().describe(
382
409
  "Filters on `paidWith.token` \u2014 the pair actually paid, not accepted."
@@ -385,13 +412,13 @@ var ListChargesSchema = import_zod7.z.object({
385
412
  "Filters on `paidWith.network` \u2014 the pair actually paid, not accepted."
386
413
  ),
387
414
  environment: EnvironmentSchema.optional(),
388
- since: import_zod7.z.string().datetime().optional().describe(
415
+ since: import_zod8.z.string().datetime().optional().describe(
389
416
  "Only return charges created at or after this timestamp (filters on `createdAt`, not on when the status last changed). If polling as a fallback for missed webhooks, use a window at least as wide as the longest `expiresIn` your charges use, or you can miss a long-lived charge that changed status outside a narrower window."
390
417
  ),
391
- isOverpaid: import_zod7.z.enum(["true", "false"]).transform((v) => v === "true").optional()
418
+ isOverpaid: import_zod8.z.enum(["true", "false"]).transform((v) => v === "true").optional()
392
419
  }).extend(PaginationQuerySchema.shape);
393
420
  var PaginatedChargesSchema = paginatedSchema(ChargeSchema);
394
- var GetChargeQrCodeQuerySchema = import_zod7.z.object({
421
+ var GetChargeQrCodeQuerySchema = import_zod8.z.object({
395
422
  token: TokenSchema.optional().describe(
396
423
  "Which accepted `(token, network)` pair to encode in the QR \u2014 required if `acceptedPayments` has more than one pair, since there is no single unambiguous default to fall back to. Ignored (and unnecessary) when the charge accepts exactly one pair."
397
424
  ),
@@ -399,61 +426,61 @@ var GetChargeQrCodeQuerySchema = import_zod7.z.object({
399
426
  });
400
427
 
401
428
  // src/distributions.ts
402
- var import_zod8 = require("zod");
403
- var SplitDistributionStatusSchema = import_zod8.z.enum(["pending", "processing", "completed", "failed"]).describe(
429
+ var import_zod9 = require("zod");
430
+ var SplitDistributionStatusSchema = import_zod9.z.enum(["pending", "processing", "completed", "failed"]).describe(
404
431
  "Status of one payout attempt to the merchant, for a single `(token, network)` pair \u2014 a charge that settles across more than one pair has one of these per pair. `pending`: queued, not yet claimed by a distributor. `processing`: a distributor (Klappay's own worker, or anyone racing to call `distribute()` first, see `PendingDistributionSchema`) has claimed it and is submitting the on-chain transaction. `completed`: the merchant's wallet has the funds. `failed`: every automatic retry was exhausted."
405
432
  );
406
- var PendingDistributionRecipientSchema = import_zod8.z.object({
407
- address: import_zod8.z.string().describe("On-chain recipient address."),
408
- percentAllocation: import_zod8.z.number().describe("This recipient's share of the split, as a percentage (e.g. `99.0991` = 99.0991%).")
433
+ var PendingDistributionRecipientSchema = import_zod9.z.object({
434
+ address: import_zod9.z.string().describe("On-chain recipient address."),
435
+ percentAllocation: import_zod9.z.number().describe("This recipient's share of the split, as a percentage (e.g. `99.0991` = 99.0991%).")
409
436
  });
410
- var PendingDistributionSchema = import_zod8.z.object({
411
- splitAddress: import_zod8.z.string().describe("The on-chain 0xSplits address to call `distribute()` on."),
437
+ var PendingDistributionSchema = import_zod9.z.object({
438
+ splitAddress: import_zod9.z.string().describe("The on-chain 0xSplits address to call `distribute()` on."),
412
439
  network: NetworkSchema,
413
440
  token: TokenSchema,
414
- recipients: import_zod8.z.array(PendingDistributionRecipientSchema).describe(
441
+ recipients: import_zod9.z.array(PendingDistributionRecipientSchema).describe(
415
442
  "The exact recipient list to pass to `distribute()` \u2014 the split contract only stores a hash of this config, so the caller must supply the identical array to prove it matches. Always present, never reconstructed from partial data."
416
443
  ),
417
- distributorFeePercent: import_zod8.z.number().describe(
444
+ distributorFeePercent: import_zod9.z.number().describe(
418
445
  "Percentage of the split balance paid to whoever calls `distribute()` first (e.g. `0.1` = 0.1%). Frozen at charge creation, same for every distribution today."
419
446
  ),
420
- estimatedRewardAmount: import_zod8.z.number().describe(
447
+ estimatedRewardAmount: import_zod9.z.number().describe(
421
448
  "Estimate only, in the charge's `currency` units, based on the amount Klappay detected on-chain \u2014 not a live read of the split's current balance. Read the balance yourself before submitting a transaction; a stale estimate is harmless (see the docs), never a reason to skip that check."
422
449
  ),
423
- availableSince: import_zod8.z.string().datetime().describe("When this distribution entered its grace period."),
424
- graceEndsAt: import_zod8.z.string().datetime().describe(
450
+ availableSince: import_zod9.z.string().datetime().describe("When this distribution entered its grace period."),
451
+ graceEndsAt: import_zod9.z.string().datetime().describe(
425
452
  "When Klappay's own worker may claim this distribution. Racing to call `distribute()` after this timestamp is possible but increasingly likely to lose to the worker."
426
453
  )
427
454
  });
428
455
  var PaginatedPendingDistributionsSchema = paginatedSchema(PendingDistributionSchema);
429
- var ListenPendingDistributionsQuerySchema = import_zod8.z.object({
430
- limit: import_zod8.z.coerce.number().int().min(0).max(PAGINATION_LIMIT_MAX).default(0).describe(
456
+ var ListenPendingDistributionsQuerySchema = import_zod9.z.object({
457
+ limit: import_zod9.z.coerce.number().int().min(0).max(PAGINATION_LIMIT_MAX).default(0).describe(
431
458
  "How many currently-claimable distributions to emit as an initial snapshot right after connecting \u2014 each as a synthetic `distribution.available` event \u2014 before continuing with real-time deltas. `0` (the default, same as omitting it) sends no snapshot at all, matching this endpoint's original behavior: connect first, then call `GET /v1/distributions/pending` yourself to bootstrap. Not a page \u2014 there is no cursor for this snapshot, so if more than `limit` are claimable at connect time, the excess is simply not sent; call `GET /v1/distributions/pending` directly for a complete, paginated listing."
432
459
  )
433
460
  });
434
- var PendingDistributionEventSchema = import_zod8.z.discriminatedUnion("type", [
435
- import_zod8.z.object({
436
- type: import_zod8.z.literal("distribution.available"),
461
+ var PendingDistributionEventSchema = import_zod9.z.discriminatedUnion("type", [
462
+ import_zod9.z.object({
463
+ type: import_zod9.z.literal("distribution.available"),
437
464
  distribution: PendingDistributionSchema
438
465
  }),
439
- import_zod8.z.object({
440
- type: import_zod8.z.literal("distribution.claimed"),
441
- splitAddress: import_zod8.z.string().describe("No longer claimable \u2014 either settled by someone, or picked up by the worker.")
466
+ import_zod9.z.object({
467
+ type: import_zod9.z.literal("distribution.claimed"),
468
+ splitAddress: import_zod9.z.string().describe("No longer claimable \u2014 either settled by someone, or picked up by the worker.")
442
469
  })
443
470
  ]);
444
471
 
445
472
  // src/metrics.ts
446
- var import_zod9 = require("zod");
447
- var MetricsResourceSchema = import_zod9.z.enum(["charges", "transactions", "distributions"]).describe(
473
+ var import_zod10 = require("zod");
474
+ var MetricsResourceSchema = import_zod10.z.enum(["charges", "transactions", "distributions"]).describe(
448
475
  "Which underlying dataset to query. `charges`: one row per charge. `transactions`: one row per detected on-chain transfer \u2014 a charge paid in installments has more than one. `distributions`: one row per payout attempt to the merchant, one per `(token, network)` pair a charge settled across."
449
476
  );
450
- var MetricsAggregationSchema = import_zod9.z.enum(["count", "sum", "avg", "min", "max"]).describe(
477
+ var MetricsAggregationSchema = import_zod10.z.enum(["count", "sum", "avg", "min", "max"]).describe(
451
478
  "`count` counts matching rows and never takes `field`. `sum`/`avg`/`min`/`max` require `field` to be set to one of the resource\u2019s numeric fields."
452
479
  );
453
- var MetricsFilterOperatorSchema = import_zod9.z.enum(["eq", "neq", "in", "gt", "gte", "lt", "lte"]).describe(
480
+ var MetricsFilterOperatorSchema = import_zod10.z.enum(["eq", "neq", "in", "gt", "gte", "lt", "lte"]).describe(
454
481
  "`in` expects an array value (max 50 entries); every other operator expects a single scalar."
455
482
  );
456
- var MetricsDateGranularitySchema = import_zod9.z.enum(["day", "week", "month", "year"]).describe(
483
+ var MetricsDateGranularitySchema = import_zod10.z.enum(["day", "week", "month", "year"]).describe(
457
484
  "Bucket width for a `date_bucket` `groupBy` entry \u2014 Postgres `date_trunc` semantics (UTC)."
458
485
  );
459
486
  var metricsQueryEnvironmentSchema = EnvironmentSchema.describe(
@@ -466,151 +493,151 @@ var METRICS_QUERY_MAX_GROUP_BY = 3;
466
493
  var METRICS_QUERY_MAX_FILTERS = 20;
467
494
  var METRICS_QUERY_MAX_METRICS = 10;
468
495
  var METRIC_ALIAS_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
469
- var metricAliasSchema = import_zod9.z.string().min(1).max(64).regex(
496
+ var metricAliasSchema = import_zod10.z.string().min(1).max(64).regex(
470
497
  METRIC_ALIAS_PATTERN,
471
498
  "Must start with a letter or underscore, and contain only letters, digits, and underscores \u2014 this becomes a SQL column alias."
472
499
  ).optional();
473
- var MetricsFilterValueSchema = import_zod9.z.union([
474
- import_zod9.z.string().max(255),
475
- import_zod9.z.number(),
476
- import_zod9.z.boolean(),
477
- import_zod9.z.array(import_zod9.z.union([import_zod9.z.string().max(255), import_zod9.z.number()])).min(1).max(50)
500
+ var MetricsFilterValueSchema = import_zod10.z.union([
501
+ import_zod10.z.string().max(255),
502
+ import_zod10.z.number(),
503
+ import_zod10.z.boolean(),
504
+ import_zod10.z.array(import_zod10.z.union([import_zod10.z.string().max(255), import_zod10.z.number()])).min(1).max(50)
478
505
  ]);
479
- var orderBySchema = import_zod9.z.object({
480
- key: import_zod9.z.string().min(1).max(64).regex(
506
+ var orderBySchema = import_zod10.z.object({
507
+ key: import_zod10.z.string().min(1).max(64).regex(
481
508
  METRIC_ALIAS_PATTERN,
482
509
  "Must start with a letter or underscore, and contain only letters, digits, and underscores \u2014 every valid output column name already looks like this."
483
510
  ).describe(
484
511
  "An output column name from this same query \u2014 either a `groupBy` field name, or a metric\u2019s `alias` (or its default name: `${aggregation}` for `count`, `${aggregation}_${field}` otherwise, e.g. `sum_amount`). Must match `^[a-zA-Z_][a-zA-Z0-9_]*$` \u2014 every real output column name already does, so this only ever rejects a value that could never have been one."
485
512
  ),
486
- direction: import_zod9.z.enum(["asc", "desc"])
513
+ direction: import_zod10.z.enum(["asc", "desc"])
487
514
  }).describe(
488
515
  "Sort the result rows by any output column \u2014 including the bucket field itself for a `date_bucket` query (e.g. `createdAt`). Omit to get ascending-by-bucket order for a date-bucketed query, or implementation-defined (not guaranteed stable) order otherwise."
489
516
  );
490
- var limitSchema = import_zod9.z.number().int().min(1).max(METRICS_QUERY_MAX_ROW_LIMIT).default(METRICS_QUERY_DEFAULT_ROW_LIMIT).describe(
517
+ var limitSchema = import_zod10.z.number().int().min(1).max(METRICS_QUERY_MAX_ROW_LIMIT).default(METRICS_QUERY_DEFAULT_ROW_LIMIT).describe(
491
518
  `Max rows to return, ${1}\u2013${METRICS_QUERY_MAX_ROW_LIMIT}, default ${METRICS_QUERY_DEFAULT_ROW_LIMIT}. If more rows matched, \`meta.truncated\` is \`true\` on the response \u2014 narrow the query instead of just raising this.`
492
519
  );
493
- var ChargesQueryFieldSchema = import_zod9.z.enum(["status", "source", "apiKeyId", "currency", "isOverpaid", "externalRef"]).describe(
520
+ var ChargesQueryFieldSchema = import_zod10.z.enum(["status", "source", "apiKeyId", "currency", "isOverpaid", "externalRef"]).describe(
494
521
  "A `Charge` field to filter or group by \u2014 see `ChargeStatusSchema` for `status`'s own possible values (charges.md). `source`/`externalRef` are free-form strings your own integration set at creation, not a fixed enum."
495
522
  );
496
- var ChargesMetricFieldSchema = import_zod9.z.enum(["amount", "amountReceived", "feePercent"]).describe(
523
+ var ChargesMetricFieldSchema = import_zod10.z.enum(["amount", "amountReceived", "feePercent"]).describe(
497
524
  "A `Charge` numeric field to aggregate. `amount`/`amountReceived` are decimal currency amounts (requested vs. actually received \u2014 see `charges.md`). `feePercent` is the platform fee frozen on the charge at creation, e.g. `1.5` means 1.5%."
498
525
  );
499
- var ChargesDateFieldSchema = import_zod9.z.enum(["createdAt", "confirmedAt", "lastActivityAt", "expiresAt"]).describe(
526
+ var ChargesDateFieldSchema = import_zod10.z.enum(["createdAt", "confirmedAt", "lastActivityAt", "expiresAt"]).describe(
500
527
  "A `Charge` timestamp to filter/bucket by. `confirmedAt` is `null` until the charge reaches `confirmed` \u2014 a `dateRange`/`date_bucket` on it implicitly excludes every charge that never confirmed. `expiresAt` is always present (set at creation), useful for e.g. finding charges expiring soon or measuring how close to expiry charges typically resolve."
501
528
  );
502
- var ChargesFilterSchema = import_zod9.z.object({
529
+ var ChargesFilterSchema = import_zod10.z.object({
503
530
  field: ChargesQueryFieldSchema,
504
531
  operator: MetricsFilterOperatorSchema,
505
532
  value: MetricsFilterValueSchema
506
533
  });
507
- var ChargesGroupBySchema = import_zod9.z.union([
508
- import_zod9.z.object({ type: import_zod9.z.literal("field"), field: ChargesQueryFieldSchema }),
509
- import_zod9.z.object({
510
- type: import_zod9.z.literal("date_bucket"),
534
+ var ChargesGroupBySchema = import_zod10.z.union([
535
+ import_zod10.z.object({ type: import_zod10.z.literal("field"), field: ChargesQueryFieldSchema }),
536
+ import_zod10.z.object({
537
+ type: import_zod10.z.literal("date_bucket"),
511
538
  field: ChargesDateFieldSchema,
512
539
  granularity: MetricsDateGranularitySchema
513
540
  })
514
541
  ]);
515
- var ChargesMetricSchema = import_zod9.z.object({
542
+ var ChargesMetricSchema = import_zod10.z.object({
516
543
  aggregation: MetricsAggregationSchema,
517
544
  field: ChargesMetricFieldSchema.optional(),
518
545
  alias: metricAliasSchema
519
546
  });
520
- var ChargesMetricsQuerySchema = import_zod9.z.object({
521
- resource: import_zod9.z.literal("charges"),
547
+ var ChargesMetricsQuerySchema = import_zod10.z.object({
548
+ resource: import_zod10.z.literal("charges"),
522
549
  environment: metricsQueryEnvironmentSchema,
523
- dateRange: import_zod9.z.object({
550
+ dateRange: import_zod10.z.object({
524
551
  field: ChargesDateFieldSchema,
525
- from: import_zod9.z.string().max(64).datetime(),
526
- to: import_zod9.z.string().max(64).datetime()
552
+ from: import_zod10.z.string().max(64).datetime(),
553
+ to: import_zod10.z.string().max(64).datetime()
527
554
  }),
528
- groupBy: import_zod9.z.array(ChargesGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
529
- metrics: import_zod9.z.array(ChargesMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
530
- filters: import_zod9.z.array(ChargesFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
555
+ groupBy: import_zod10.z.array(ChargesGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
556
+ metrics: import_zod10.z.array(ChargesMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
557
+ filters: import_zod10.z.array(ChargesFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
531
558
  orderBy: orderBySchema.optional(),
532
559
  limit: limitSchema
533
560
  });
534
- var TransactionsQueryFieldSchema = import_zod9.z.enum(["network", "token", "source", "causedTransition"]).describe(
561
+ var TransactionsQueryFieldSchema = import_zod10.z.enum(["network", "token", "source", "causedTransition"]).describe(
535
562
  "A `Transaction` field to filter or group by \u2014 see `NetworkSchema`/`TokenSchema`/`TransactionSourceSchema` for their possible values. `causedTransition` is `true` only for the transfer(s) that actually flipped the charge's `status` \u2014 a charge paid in installments can have more than one; filtering/grouping on it excludes no-op duplicate transfers (see `TimelineEvent.causedTransition` in charges.md for the full explanation)."
536
563
  );
537
- var TransactionsMetricFieldSchema = import_zod9.z.enum(["amount"]).describe("The transfer amount, in the charge's `currency` units.");
538
- var TransactionsDateFieldSchema = import_zod9.z.enum(["detectedAt"]).describe("When Klappay detected this transfer on-chain (not when it was mined).");
539
- var TransactionsFilterSchema = import_zod9.z.object({
564
+ var TransactionsMetricFieldSchema = import_zod10.z.enum(["amount"]).describe("The transfer amount, in the charge's `currency` units.");
565
+ var TransactionsDateFieldSchema = import_zod10.z.enum(["detectedAt"]).describe("When Klappay detected this transfer on-chain (not when it was mined).");
566
+ var TransactionsFilterSchema = import_zod10.z.object({
540
567
  field: TransactionsQueryFieldSchema,
541
568
  operator: MetricsFilterOperatorSchema,
542
569
  value: MetricsFilterValueSchema
543
570
  });
544
- var TransactionsGroupBySchema = import_zod9.z.union([
545
- import_zod9.z.object({ type: import_zod9.z.literal("field"), field: TransactionsQueryFieldSchema }),
546
- import_zod9.z.object({
547
- type: import_zod9.z.literal("date_bucket"),
571
+ var TransactionsGroupBySchema = import_zod10.z.union([
572
+ import_zod10.z.object({ type: import_zod10.z.literal("field"), field: TransactionsQueryFieldSchema }),
573
+ import_zod10.z.object({
574
+ type: import_zod10.z.literal("date_bucket"),
548
575
  field: TransactionsDateFieldSchema,
549
576
  granularity: MetricsDateGranularitySchema
550
577
  })
551
578
  ]);
552
- var TransactionsMetricSchema = import_zod9.z.object({
579
+ var TransactionsMetricSchema = import_zod10.z.object({
553
580
  aggregation: MetricsAggregationSchema,
554
581
  field: TransactionsMetricFieldSchema.optional(),
555
582
  alias: metricAliasSchema
556
583
  });
557
- var TransactionsMetricsQuerySchema = import_zod9.z.object({
558
- resource: import_zod9.z.literal("transactions"),
584
+ var TransactionsMetricsQuerySchema = import_zod10.z.object({
585
+ resource: import_zod10.z.literal("transactions"),
559
586
  environment: metricsQueryEnvironmentSchema,
560
- dateRange: import_zod9.z.object({
587
+ dateRange: import_zod10.z.object({
561
588
  field: TransactionsDateFieldSchema,
562
- from: import_zod9.z.string().max(64).datetime(),
563
- to: import_zod9.z.string().max(64).datetime()
589
+ from: import_zod10.z.string().max(64).datetime(),
590
+ to: import_zod10.z.string().max(64).datetime()
564
591
  }),
565
- groupBy: import_zod9.z.array(TransactionsGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
566
- metrics: import_zod9.z.array(TransactionsMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
567
- filters: import_zod9.z.array(TransactionsFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
592
+ groupBy: import_zod10.z.array(TransactionsGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
593
+ metrics: import_zod10.z.array(TransactionsMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
594
+ filters: import_zod10.z.array(TransactionsFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
568
595
  orderBy: orderBySchema.optional(),
569
596
  limit: limitSchema
570
597
  });
571
- var DistributionsQueryFieldSchema = import_zod9.z.enum(["status", "network", "token", "distributorAddress"]).describe(
598
+ var DistributionsQueryFieldSchema = import_zod10.z.enum(["status", "network", "token", "distributorAddress"]).describe(
572
599
  "A `SplitDistribution` field to filter or group by \u2014 see `SplitDistributionStatusSchema`/`NetworkSchema`/`TokenSchema` for their possible values. `distributorAddress` is the public on-chain address that actually called `distribute()` for a `completed` distribution \u2014 Klappay's own operator address if settled by Klappay's own worker, a community keeper's address if settled externally (or `null` on the rare case that lookup failed), `null` for every non-`completed` status."
573
600
  );
574
- var DistributionsMetricFieldSchema = import_zod9.z.enum(["attempts"]).describe(
601
+ var DistributionsMetricFieldSchema = import_zod10.z.enum(["attempts"]).describe(
575
602
  "How many times a payout was attempted for this settlement so far \u2014 incremented on every attempt, whether it succeeded or is being retried after failing. A high `attempts` alongside `status: 'failed'` means every automatic retry was exhausted."
576
603
  );
577
- var DistributionsDateFieldSchema = import_zod9.z.enum(["createdAt", "processingStartedAt", "completedAt"]).describe(
604
+ var DistributionsDateFieldSchema = import_zod10.z.enum(["createdAt", "processingStartedAt", "completedAt"]).describe(
578
605
  "`createdAt`: when this settlement was queued. `processingStartedAt`: when a worker began its most recent attempt at the payout \u2014 `null` until the first attempt, then overwritten on every subsequent retry, so it reflects the *latest* attempt's start, not the first. `completedAt`: when it actually paid out \u2014 `null` until `status` reaches `completed`, so a `dateRange`/`date_bucket` on it implicitly excludes every distribution still pending/processing/failed."
579
606
  );
580
- var DistributionsFilterSchema = import_zod9.z.object({
607
+ var DistributionsFilterSchema = import_zod10.z.object({
581
608
  field: DistributionsQueryFieldSchema,
582
609
  operator: MetricsFilterOperatorSchema,
583
610
  value: MetricsFilterValueSchema
584
611
  });
585
- var DistributionsGroupBySchema = import_zod9.z.union([
586
- import_zod9.z.object({ type: import_zod9.z.literal("field"), field: DistributionsQueryFieldSchema }),
587
- import_zod9.z.object({
588
- type: import_zod9.z.literal("date_bucket"),
612
+ var DistributionsGroupBySchema = import_zod10.z.union([
613
+ import_zod10.z.object({ type: import_zod10.z.literal("field"), field: DistributionsQueryFieldSchema }),
614
+ import_zod10.z.object({
615
+ type: import_zod10.z.literal("date_bucket"),
589
616
  field: DistributionsDateFieldSchema,
590
617
  granularity: MetricsDateGranularitySchema
591
618
  })
592
619
  ]);
593
- var DistributionsMetricSchema = import_zod9.z.object({
620
+ var DistributionsMetricSchema = import_zod10.z.object({
594
621
  aggregation: MetricsAggregationSchema,
595
622
  field: DistributionsMetricFieldSchema.optional(),
596
623
  alias: metricAliasSchema
597
624
  });
598
- var DistributionsMetricsQuerySchema = import_zod9.z.object({
599
- resource: import_zod9.z.literal("distributions"),
625
+ var DistributionsMetricsQuerySchema = import_zod10.z.object({
626
+ resource: import_zod10.z.literal("distributions"),
600
627
  environment: metricsQueryEnvironmentSchema,
601
- dateRange: import_zod9.z.object({
628
+ dateRange: import_zod10.z.object({
602
629
  field: DistributionsDateFieldSchema,
603
- from: import_zod9.z.string().max(64).datetime(),
604
- to: import_zod9.z.string().max(64).datetime()
630
+ from: import_zod10.z.string().max(64).datetime(),
631
+ to: import_zod10.z.string().max(64).datetime()
605
632
  }),
606
- groupBy: import_zod9.z.array(DistributionsGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
607
- metrics: import_zod9.z.array(DistributionsMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
608
- filters: import_zod9.z.array(DistributionsFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
633
+ groupBy: import_zod10.z.array(DistributionsGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
634
+ metrics: import_zod10.z.array(DistributionsMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
635
+ filters: import_zod10.z.array(DistributionsFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
609
636
  orderBy: orderBySchema.optional(),
610
637
  limit: limitSchema
611
638
  });
612
639
  var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
613
- var MetricsQuerySchema = import_zod9.z.discriminatedUnion("resource", [
640
+ var MetricsQuerySchema = import_zod10.z.discriminatedUnion("resource", [
614
641
  ChargesMetricsQuerySchema,
615
642
  TransactionsMetricsQuerySchema,
616
643
  DistributionsMetricsQuerySchema
@@ -619,7 +646,7 @@ var MetricsQuerySchema = import_zod9.z.discriminatedUnion("resource", [
619
646
  const to = new Date(input.dateRange.to);
620
647
  if (from >= to) {
621
648
  ctx.addIssue({
622
- code: import_zod9.z.ZodIssueCode.custom,
649
+ code: import_zod10.z.ZodIssueCode.custom,
623
650
  message: "`dateRange.from` must be before `dateRange.to`.",
624
651
  path: ["dateRange", "from"]
625
652
  });
@@ -627,7 +654,7 @@ var MetricsQuerySchema = import_zod9.z.discriminatedUnion("resource", [
627
654
  const spanDays = (to.getTime() - from.getTime()) / ONE_DAY_MS;
628
655
  if (spanDays > MAX_METRICS_QUERY_DATE_RANGE_DAYS) {
629
656
  ctx.addIssue({
630
- code: import_zod9.z.ZodIssueCode.custom,
657
+ code: import_zod10.z.ZodIssueCode.custom,
631
658
  message: `\`dateRange\` cannot span more than ${MAX_METRICS_QUERY_DATE_RANGE_DAYS} days.`,
632
659
  path: ["dateRange", "to"]
633
660
  });
@@ -635,7 +662,7 @@ var MetricsQuerySchema = import_zod9.z.discriminatedUnion("resource", [
635
662
  const dateBucketCount = input.groupBy.filter((entry) => entry.type === "date_bucket").length;
636
663
  if (dateBucketCount > 1) {
637
664
  ctx.addIssue({
638
- code: import_zod9.z.ZodIssueCode.custom,
665
+ code: import_zod10.z.ZodIssueCode.custom,
639
666
  message: "At most one `date_bucket` entry is allowed in `groupBy`.",
640
667
  path: ["groupBy"]
641
668
  });
@@ -643,7 +670,7 @@ var MetricsQuerySchema = import_zod9.z.discriminatedUnion("resource", [
643
670
  input.metrics.forEach((metric, index) => {
644
671
  if (metric.aggregation !== "count" && metric.field === void 0) {
645
672
  ctx.addIssue({
646
- code: import_zod9.z.ZodIssueCode.custom,
673
+ code: import_zod10.z.ZodIssueCode.custom,
647
674
  message: "`field` is required unless `aggregation` is `count`.",
648
675
  path: ["metrics", index, "field"]
649
676
  });
@@ -652,7 +679,7 @@ var MetricsQuerySchema = import_zod9.z.discriminatedUnion("resource", [
652
679
  const aliases = input.metrics.map((metric) => metric.alias).filter((alias) => alias !== void 0);
653
680
  if (new Set(aliases).size !== aliases.length) {
654
681
  ctx.addIssue({
655
- code: import_zod9.z.ZodIssueCode.custom,
682
+ code: import_zod10.z.ZodIssueCode.custom,
656
683
  message: "Every `metrics[].alias` must be unique.",
657
684
  path: ["metrics"]
658
685
  });
@@ -661,32 +688,32 @@ var MetricsQuerySchema = import_zod9.z.discriminatedUnion("resource", [
661
688
  input.metrics.forEach((metric, index) => {
662
689
  if (metric.alias !== void 0 && reservedNames.has(metric.alias)) {
663
690
  ctx.addIssue({
664
- code: import_zod9.z.ZodIssueCode.custom,
691
+ code: import_zod10.z.ZodIssueCode.custom,
665
692
  message: `\`alias\` "${metric.alias}" collides with a \`groupBy\` field name (or the reserved word "bucket") \u2014 choose a different alias.`,
666
693
  path: ["metrics", index, "alias"]
667
694
  });
668
695
  }
669
696
  });
670
697
  });
671
- var MetricsQueryResultRowSchema = import_zod9.z.record(
672
- import_zod9.z.string(),
673
- import_zod9.z.union([import_zod9.z.string(), import_zod9.z.number(), import_zod9.z.boolean(), import_zod9.z.null()])
698
+ var MetricsQueryResultRowSchema = import_zod10.z.record(
699
+ import_zod10.z.string(),
700
+ import_zod10.z.union([import_zod10.z.string(), import_zod10.z.number(), import_zod10.z.boolean(), import_zod10.z.null()])
674
701
  );
675
- var MetricsQueryResultSchema = import_zod9.z.object({
676
- data: import_zod9.z.array(MetricsQueryResultRowSchema),
677
- meta: import_zod9.z.object({
702
+ var MetricsQueryResultSchema = import_zod10.z.object({
703
+ data: import_zod10.z.array(MetricsQueryResultRowSchema),
704
+ meta: import_zod10.z.object({
678
705
  resource: MetricsResourceSchema,
679
706
  environment: EnvironmentSchema,
680
- rowCount: import_zod9.z.number().int().describe("Number of rows in `data`."),
681
- truncated: import_zod9.z.boolean().describe(
707
+ rowCount: import_zod10.z.number().int().describe("Number of rows in `data`."),
708
+ truncated: import_zod10.z.boolean().describe(
682
709
  "`true` if more rows matched than `limit` allowed \u2014 `data` holds only the first `limit`."
683
710
  )
684
711
  })
685
712
  });
686
713
 
687
714
  // src/webhook-events.ts
688
- var import_zod10 = require("zod");
689
- var ChargeWebhookEventTypeSchema = import_zod10.z.enum([
715
+ var import_zod11 = require("zod");
716
+ var ChargeWebhookEventTypeSchema = import_zod11.z.enum([
690
717
  "charge.created",
691
718
  "charge.partially_paid",
692
719
  "charge.confirmed",
@@ -698,14 +725,14 @@ var ChargeWebhookEventTypeSchema = import_zod10.z.enum([
698
725
  ]).describe(
699
726
  'Note the distinction between `charge.confirmed` and `charge.settled`: `confirmed` means the payment was detected on-chain; `settled` means the merchant\'s wallet actually received the funds \u2014 a separate, later step. Subscribe to `confirmed` if you only need "will I get paid," or `settled` if you need "has the money actually arrived." `charge.overpaid` fires alongside `charge.confirmed`/`charge.partially_paid` whenever the cumulative amount received ends up above `amount` (see `Charge.isOverpaid`). Every event in this category carries the full `Charge` object as `data`.'
700
727
  );
701
- var WebhookDeliveryEventTypeSchema = import_zod10.z.enum(["webhook.delivery_failed", "webhook.delivery_recovered", "webhook.endpoint_unhealthy"]).describe(
728
+ var WebhookDeliveryEventTypeSchema = import_zod11.z.enum(["webhook.delivery_failed", "webhook.delivery_recovered", "webhook.endpoint_unhealthy"]).describe(
702
729
  "Meta-events about the health of your own webhook endpoints \u2014 useful for monitoring without polling `GET /v1/webhooks/{id}/deliveries`. `webhook.endpoint_unhealthy` fires once when a webhook's failure rate over the trailing 24h crosses 20%, and `webhook.delivery_recovered` fires once when a delivery to that webhook next succeeds. `data` for every event in this category: `{ webhookId, url, failureRatio? }` (`failureRatio` only present on `webhook.endpoint_unhealthy`)."
703
730
  );
704
- var WebhookEventTypeSchema = import_zod10.z.union([
731
+ var WebhookEventTypeSchema = import_zod11.z.union([
705
732
  ChargeWebhookEventTypeSchema,
706
733
  WebhookDeliveryEventTypeSchema
707
734
  ]);
708
- var WebhookCategorySchema = import_zod10.z.enum(["payments", "webhooks"]).describe(
735
+ var WebhookCategorySchema = import_zod11.z.enum(["payments", "webhooks"]).describe(
709
736
  "Subscribe to every event in a category via `eventCategories` instead of listing events one by one \u2014 new events added to a category later arrive automatically, no subscription update needed."
710
737
  );
711
738
  function buildCategoryMap() {
@@ -733,78 +760,78 @@ var TriggerableChargeEventSchema = ChargeWebhookEventTypeSchema.exclude([
733
760
  );
734
761
 
735
762
  // src/webhooks.ts
736
- var import_zod11 = require("zod");
763
+ var import_zod12 = require("zod");
737
764
  var WEBHOOK_EVENTS_WILDCARD = "*";
738
- var CreateWebhookSchema = import_zod11.z.object({
739
- url: import_zod11.z.string().max(2048).url().describe(
765
+ var CreateWebhookSchema = import_zod12.z.object({
766
+ url: import_zod12.z.string().max(2048).url().describe(
740
767
  "Must be HTTPS and resolve to a public address \u2014 private/internal IPs are rejected."
741
768
  ),
742
- events: import_zod11.z.array(import_zod11.z.union([WebhookEventTypeSchema, import_zod11.z.literal(WEBHOOK_EVENTS_WILDCARD)])).max(Object.keys(EVENT_CATEGORY_MAP).length + 1).default([]).describe(
769
+ events: import_zod12.z.array(import_zod12.z.union([WebhookEventTypeSchema, import_zod12.z.literal(WEBHOOK_EVENTS_WILDCARD)])).max(Object.keys(EVENT_CATEGORY_MAP).length + 1).default([]).describe(
743
770
  'Individual event types to receive, or `"*"` for every event (combine with `excludeEvents` to opt back out of specific ones). Omit in favor of `eventCategories` if you want whole categories instead.'
744
771
  ),
745
- eventCategories: import_zod11.z.array(WebhookCategorySchema).max(WebhookCategorySchema.options.length).default([]).describe(
772
+ eventCategories: import_zod12.z.array(WebhookCategorySchema).max(WebhookCategorySchema.options.length).default([]).describe(
746
773
  "Subscribe to every event in these categories. At least one of `events` or `eventCategories` is required."
747
774
  ),
748
- excludeEvents: import_zod11.z.array(WebhookEventTypeSchema).max(Object.keys(EVENT_CATEGORY_MAP).length).default([]).describe(
775
+ excludeEvents: import_zod12.z.array(WebhookEventTypeSchema).max(Object.keys(EVENT_CATEGORY_MAP).length).default([]).describe(
749
776
  'Event types to exclude even if selected via `events: ["*"]` or `eventCategories`.'
750
777
  )
751
778
  }).refine((v) => v.events.length > 0 || v.eventCategories.length > 0, {
752
779
  message: "must select at least one event via `events` or `eventCategories`",
753
780
  path: ["events"]
754
781
  });
755
- var WebhookSchema = import_zod11.z.object({
756
- id: import_zod11.z.string(),
782
+ var WebhookSchema = import_zod12.z.object({
783
+ id: import_zod12.z.string(),
757
784
  environment: EnvironmentSchema.nullable().describe(
758
785
  "Which environment's API key created this webhook \u2014 `live` or `test`. Every event is only ever delivered to a webhook whose `environment` matches the event's own (or to a webhook with `environment: null`, which receives every environment \u2014 the case for every webhook created before this field existed)."
759
786
  ),
760
- url: import_zod11.z.string(),
761
- events: import_zod11.z.array(WebhookEventTypeSchema),
762
- eventCategories: import_zod11.z.array(WebhookCategorySchema),
763
- excludeEvents: import_zod11.z.array(WebhookEventTypeSchema),
764
- isWildcard: import_zod11.z.boolean(),
765
- secret: import_zod11.z.string().describe(
787
+ url: import_zod12.z.string(),
788
+ events: import_zod12.z.array(WebhookEventTypeSchema),
789
+ eventCategories: import_zod12.z.array(WebhookCategorySchema),
790
+ excludeEvents: import_zod12.z.array(WebhookEventTypeSchema),
791
+ isWildcard: import_zod12.z.boolean(),
792
+ secret: import_zod12.z.string().describe(
766
793
  "The signing secret, used to verify the `X-Klappay-Signature` header on every delivery. Returned in full only this once \u2014 store it now, it is not recoverable afterward. Header format: `t=<unix-seconds>,v1=<hex-encoded HMAC-SHA256>`. Compute the expected signature as `HMAC-SHA256(secret, \"${t}.${raw request body}\")` (hex-encoded) and compare it to `v1` using a constant-time comparison; as a replay-protection measure, also reject if `t` is too far from the current time \u2014 Klappay does not enforce or check any particular tolerance server-side, so the exact threshold is entirely the receiver's own policy call. An official SDK's `constructEvent()`/`verifySignature()` do this for you, defaulting to a 300-second tolerance, overridable via `constructEvent`'s `toleranceSeconds` option \u2014 see github.com/klappay for available SDKs."
767
794
  ),
768
- createdAt: import_zod11.z.string().datetime()
795
+ createdAt: import_zod12.z.string().datetime()
769
796
  });
770
797
  var WebhookListItemSchema = WebhookSchema.omit({ secret: true }).extend({
771
- hint: import_zod11.z.string().describe("A truncated, safe-to-display form of the secret (e.g. `whsec_...ab12`).")
798
+ hint: import_zod12.z.string().describe("A truncated, safe-to-display form of the secret (e.g. `whsec_...ab12`).")
772
799
  });
773
- var WebhookPayloadSchema = import_zod11.z.object({
774
- id: import_zod11.z.string().describe(
800
+ var WebhookPayloadSchema = import_zod12.z.object({
801
+ id: import_zod12.z.string().describe(
775
802
  "Unique id for this specific delivery \u2014 also sent as the `X-Klappay-Delivery` header."
776
803
  ),
777
804
  event: WebhookEventTypeSchema,
778
- createdAt: import_zod11.z.string().datetime(),
779
- data: import_zod11.z.unknown().describe(
805
+ createdAt: import_zod12.z.string().datetime(),
806
+ data: import_zod12.z.unknown().describe(
780
807
  "Event-specific data. Charge events (`charge.*`) carry the full `Charge` object; webhook-delivery events carry a smaller, event-specific object \u2014 see `WebhookEventDataMap`/`TypedWebhookPayload` for the exact shape per event, or docs/webhooks.md."
781
808
  )
782
809
  });
783
- var WebhookDeliveryStatusSchema = import_zod11.z.enum(["pending", "delivered", "failed"]);
784
- var WebhookDeliverySchema = import_zod11.z.object({
785
- id: import_zod11.z.string(),
786
- webhookId: import_zod11.z.string(),
810
+ var WebhookDeliveryStatusSchema = import_zod12.z.enum(["pending", "delivered", "failed"]);
811
+ var WebhookDeliverySchema = import_zod12.z.object({
812
+ id: import_zod12.z.string(),
813
+ webhookId: import_zod12.z.string(),
787
814
  event: WebhookEventTypeSchema,
788
815
  status: WebhookDeliveryStatusSchema.describe(
789
816
  "`pending`: still retrying. `delivered`: got a 2xx response. `failed`: retries exhausted (5 attempts over ~24h) \u2014 use `POST /v1/webhooks/{id}/deliveries/{deliveryId}/retry` to try again manually."
790
817
  ),
791
- attempts: import_zod11.z.number(),
792
- responseCode: import_zod11.z.number().nullable().describe(
818
+ attempts: import_zod12.z.number(),
819
+ responseCode: import_zod12.z.number().nullable().describe(
793
820
  "HTTP status your endpoint returned on the most recent attempt. `null` if every attempt failed to connect at all."
794
821
  ),
795
- nextRetryAt: import_zod11.z.string().datetime().nullable(),
796
- deliveredAt: import_zod11.z.string().datetime().nullable(),
797
- createdAt: import_zod11.z.string().datetime()
822
+ nextRetryAt: import_zod12.z.string().datetime().nullable(),
823
+ deliveredAt: import_zod12.z.string().datetime().nullable(),
824
+ createdAt: import_zod12.z.string().datetime()
798
825
  });
799
826
  var ListWebhookDeliveriesSchema = PaginationQuerySchema;
800
827
  var PaginatedWebhookDeliveriesSchema = paginatedSchema(WebhookDeliverySchema);
801
828
 
802
829
  // src/timeline.ts
803
- var import_zod12 = require("zod");
804
- var TransactionSourceSchema = import_zod12.z.enum(["moralis_webhook", "reconciliation_job", "sandbox"]).describe(
830
+ var import_zod13 = require("zod");
831
+ var TransactionSourceSchema = import_zod13.z.enum(["moralis_webhook", "reconciliation_job", "sandbox"]).describe(
805
832
  "How this transfer was detected: `moralis_webhook` (the normal path), `reconciliation_job` (a fallback poller caught it after the webhook was missed or delayed), or `sandbox` (simulated via `POST /v1/sandbox/charges/{id}/trigger`, no real on-chain transfer)."
806
833
  );
807
- var TimelineEventTypeSchema = import_zod12.z.enum([
834
+ var TimelineEventTypeSchema = import_zod13.z.enum([
808
835
  "charge.created",
809
836
  "charge.expired",
810
837
  "transaction.detected",
@@ -815,11 +842,11 @@ var TimelineEventTypeSchema = import_zod12.z.enum([
815
842
  ]).describe(
816
843
  "`charge.created`: the charge was created. `charge.expired`: `expiresAt` passed with no full payment. `transaction.detected`: a raw on-chain transfer was seen (see the `event`-shaped fields below for details \u2014 a charge can have more than one, e.g. a partial payment followed by the rest). `split.distributed`: a payout to the merchant completed on-chain, for one contributing `(token, network)` pair \u2014 a charge settled across more than one pair emits one of these per pair (see the `token`/`network` fields below). `webhook.dispatched`/`webhook.delivered`/`webhook.failed`: one specific delivery *attempt* for one webhook subscription \u2014 `failed` here means this single attempt failed, not that all retries were exhausted (see `WebhookDeliveryStatusSchema` for the exhausted-all-retries state)."
817
844
  );
818
- var TimelineEventSchema = import_zod12.z.object({
845
+ var TimelineEventSchema = import_zod13.z.object({
819
846
  type: TimelineEventTypeSchema,
820
- at: import_zod12.z.string().datetime(),
821
- txHash: import_zod12.z.string().optional().describe("Present for `transaction.detected` and `split.distributed` events only."),
822
- amount: import_zod12.z.number().optional().describe(
847
+ at: import_zod13.z.string().datetime(),
848
+ txHash: import_zod13.z.string().optional().describe("Present for `transaction.detected` and `split.distributed` events only."),
849
+ amount: import_zod13.z.number().optional().describe(
823
850
  "Present for `transaction.detected` events only \u2014 the amount that specific transfer carried."
824
851
  ),
825
852
  source: TransactionSourceSchema.optional().describe(
@@ -831,49 +858,49 @@ var TimelineEventSchema = import_zod12.z.object({
831
858
  network: NetworkSchema.optional().describe(
832
859
  "Present for `transaction.detected` and `split.distributed` events \u2014 which network this specific transfer, or settlement, used."
833
860
  ),
834
- causedTransition: import_zod12.z.boolean().optional().describe(
861
+ causedTransition: import_zod13.z.boolean().optional().describe(
835
862
  "Present for `transaction.detected` events only. `true` if this specific transfer changed the charge's status (e.g. PENDING\u2192CONFIRMED) \u2014 a charge paid in installments can have more than one such event."
836
863
  ),
837
864
  event: WebhookEventTypeSchema.optional().describe(
838
865
  "Present for `webhook.*` events only \u2014 which event type this delivery was for."
839
866
  ),
840
- responseCode: import_zod12.z.number().nullable().optional().describe(
867
+ responseCode: import_zod13.z.number().nullable().optional().describe(
841
868
  "Present for `webhook.*` events only \u2014 HTTP status your endpoint returned, or `null` if the request never connected."
842
869
  ),
843
- attempts: import_zod12.z.number().optional().describe(
870
+ attempts: import_zod13.z.number().optional().describe(
844
871
  "Present for `webhook.*` events only \u2014 how many delivery attempts have been made so far."
845
872
  )
846
873
  });
847
874
 
848
875
  // src/health.ts
849
- var import_zod13 = require("zod");
850
- var HealthSchema = import_zod13.z.object({
851
- status: import_zod13.z.enum(["ok", "error"]).describe(
876
+ var import_zod14 = require("zod");
877
+ var HealthSchema = import_zod14.z.object({
878
+ status: import_zod14.z.enum(["ok", "error"]).describe(
852
879
  "`error` when the database connectivity check fails \u2014 the HTTP status code mirrors this (503 instead of 200), so a plain uptime check (not just a JSON-aware one) still catches a DB outage."
853
880
  ),
854
- version: import_zod13.z.string(),
855
- timestamp: import_zod13.z.string().datetime(),
856
- db: import_zod13.z.enum(["ok", "error"]).describe("Result of a real database connectivity check, not just a process-alive check."),
857
- pendingWebhooks: import_zod13.z.number().describe("Count of webhook deliveries still awaiting a successful attempt."),
858
- oldestPendingChargeAgeSeconds: import_zod13.z.number().nullable().describe("Age of the oldest still-unpaid charge, in seconds. `null` if there are none."),
859
- lastMoralisEventAgeSeconds: import_zod13.z.number().nullable().describe(
881
+ version: import_zod14.z.string(),
882
+ timestamp: import_zod14.z.string().datetime(),
883
+ db: import_zod14.z.enum(["ok", "error"]).describe("Result of a real database connectivity check, not just a process-alive check."),
884
+ pendingWebhooks: import_zod14.z.number().describe("Count of webhook deliveries still awaiting a successful attempt."),
885
+ oldestPendingChargeAgeSeconds: import_zod14.z.number().nullable().describe("Age of the oldest still-unpaid charge, in seconds. `null` if there are none."),
886
+ lastMoralisEventAgeSeconds: import_zod14.z.number().nullable().describe(
860
887
  "Seconds since the last on-chain payment notification was received \u2014 a cheap signal for whether payment detection is currently working. `null` if none have ever been received."
861
888
  )
862
889
  });
863
890
 
864
891
  // src/sandbox.ts
865
- var import_zod14 = require("zod");
866
- var SandboxTriggerSchema = import_zod14.z.object({
892
+ var import_zod15 = require("zod");
893
+ var SandboxTriggerSchema = import_zod15.z.object({
867
894
  event: TriggerableChargeEventSchema,
868
- amount: import_zod14.z.number().positive().max(CHARGE_AMOUNT_MAX).optional().describe(
895
+ amount: import_zod15.z.number().positive().max(CHARGE_AMOUNT_MAX).optional().describe(
869
896
  "Used with `charge.partially_paid` (amount to simulate as received so far \u2014 must be less than the charge amount, defaults to half of it if omitted) and with `charge.overpaid` (amount received \u2014 must be greater than the charge amount, defaults to 1.5x it if omitted). Ignored for every other event."
870
897
  )
871
898
  });
872
899
 
873
900
  // src/capabilities.ts
874
- var import_zod15 = require("zod");
875
- var CapabilitiesSchema = import_zod15.z.object({
876
- acceptedPayments: import_zod15.z.array(AcceptedPaymentSchema).describe(
901
+ var import_zod16 = require("zod");
902
+ var CapabilitiesSchema = import_zod16.z.object({
903
+ acceptedPayments: import_zod16.z.array(AcceptedPaymentSchema).describe(
877
904
  "Every `(token, network)` pair actually configured for your environment right now \u2014 read straight from the same lookup `POST /v1/charges` validates `acceptedPayments` against, so it can never list a pair that charge creation would then reject. Use this to build a picker UI instead of hardcoding the matrix client-side."
878
905
  )
879
906
  });
@@ -887,6 +914,7 @@ var CapabilitiesSchema = import_zod15.z.object({
887
914
  CHARGE_EXPIRES_IN_MAX_SECONDS,
888
915
  CHARGE_EXPIRES_IN_MIN_SECONDS,
889
916
  CHARGE_SPLIT_RECIPIENTS_MAX,
917
+ CHECKOUT_PRODUCTS_MAX,
890
918
  CapabilitiesSchema,
891
919
  ChargeSchema,
892
920
  ChargeStatusSchema,
@@ -894,6 +922,7 @@ var CapabilitiesSchema = import_zod15.z.object({
894
922
  ChargesDateFieldSchema,
895
923
  ChargesMetricFieldSchema,
896
924
  ChargesQueryFieldSchema,
925
+ CheckoutProductSchema,
897
926
  CreateChargeSchema,
898
927
  CreateWebhookSchema,
899
928
  DistributionsDateFieldSchema,
@@ -905,6 +934,7 @@ var CapabilitiesSchema = import_zod15.z.object({
905
934
  ErrorPayloadSchema,
906
935
  GetChargeQrCodeQuerySchema,
907
936
  HealthSchema,
937
+ KlappayCheckoutMetadataSchema,
908
938
  ListChargesSchema,
909
939
  ListWebhookDeliveriesSchema,
910
940
  ListenPendingDistributionsQuerySchema,
@@ -914,6 +944,7 @@ var CapabilitiesSchema = import_zod15.z.object({
914
944
  METRICS_QUERY_MAX_GROUP_BY,
915
945
  METRICS_QUERY_MAX_METRICS,
916
946
  METRICS_QUERY_MAX_ROW_LIMIT,
947
+ MetadataWithKlappaySchema,
917
948
  MetricsAggregationSchema,
918
949
  MetricsDateGranularitySchema,
919
950
  MetricsFilterOperatorSchema,