@klappay/types 3.0.0 → 3.0.2

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
@@ -20,8 +20,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ ALT_TOKEN_ADDRESSES: () => ALT_TOKEN_ADDRESSES,
24
+ ALT_TOKEN_DECIMALS: () => ALT_TOKEN_DECIMALS,
23
25
  API_KEY_SCOPES: () => API_KEY_SCOPES,
24
26
  AcceptedPaymentSchema: () => AcceptedPaymentSchema,
27
+ AltTokenSchema: () => AltTokenSchema,
25
28
  ApiKeyScopeSchema: () => ApiKeyScopeSchema,
26
29
  CHARGE_ACCEPTED_PAYMENTS_MAX: () => CHARGE_ACCEPTED_PAYMENTS_MAX,
27
30
  CHARGE_AMOUNT_MAX: () => CHARGE_AMOUNT_MAX,
@@ -40,6 +43,7 @@ __export(index_exports, {
40
43
  CheckoutProductSchema: () => CheckoutProductSchema,
41
44
  CreateChargeSchema: () => CreateChargeSchema,
42
45
  CreateRecipientSchema: () => CreateRecipientSchema,
46
+ CreateSwapQuoteSchema: () => CreateSwapQuoteSchema,
43
47
  CreateWebhookSchema: () => CreateWebhookSchema,
44
48
  DistributionsDateFieldSchema: () => DistributionsDateFieldSchema,
45
49
  DistributionsMetricFieldSchema: () => DistributionsMetricFieldSchema,
@@ -89,6 +93,8 @@ __export(index_exports, {
89
93
  SplitDistributionStatusSchema: () => SplitDistributionStatusSchema,
90
94
  SplitRecipientInputSchema: () => SplitRecipientInputSchema,
91
95
  SplitRecipientSchema: () => SplitRecipientSchema,
96
+ SwapAlternativeSchema: () => SwapAlternativeSchema,
97
+ SwapQuoteSchema: () => SwapQuoteSchema,
92
98
  TOKEN_ADDRESSES: () => TOKEN_ADDRESSES,
93
99
  TOKEN_DECIMALS: () => TOKEN_DECIMALS,
94
100
  TimelineEventSchema: () => TimelineEventSchema,
@@ -110,6 +116,7 @@ __export(index_exports, {
110
116
  WebhookPayloadSchema: () => WebhookPayloadSchema,
111
117
  WebhookSchema: () => WebhookSchema,
112
118
  findConflictingScopes: () => findConflictingScopes,
119
+ listSwapAlternatives: () => listSwapAlternatives,
113
120
  paginatedSchema: () => paginatedSchema
114
121
  });
115
122
  module.exports = __toCommonJS(index_exports);
@@ -264,51 +271,88 @@ var TOKEN_ADDRESSES = {
264
271
  }
265
272
  };
266
273
 
274
+ // src/alt-tokens.ts
275
+ var import_zod7 = require("zod");
276
+ var AltTokenSchema = import_zod7.z.enum(["ETH", "BNB", "MATIC", "AVAX", "BTC"]).describe(
277
+ "A non-stablecoin cryptocurrency Klappay trusts as swap input for a charge, via the 0x Swap API \u2014 swapped to one of the charge's `acceptedPayments` tokens before it ever reaches the merchant, so the merchant always receives USDC/USDT regardless of what the payer sent. Only a network's own native currency, plus `BTC` (wrapped) on the networks with deep, reputably-custodied liquidity, is trusted today (see `ALT_TOKEN_ADDRESSES`) \u2014 never assume every value here is available on every network."
278
+ );
279
+ var ALT_TOKEN_DECIMALS = {
280
+ ETH: 18,
281
+ BNB: 18,
282
+ MATIC: 18,
283
+ AVAX: 18,
284
+ BTC: 8
285
+ };
286
+ var ALT_TOKEN_ADDRESSES = {
287
+ base: { ETH: "native", BTC: "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf" },
288
+ optimism: { ETH: "native", BTC: "0x68f180fcCe6836688e9084f035309E29Bf0A2095" },
289
+ ethereum: { ETH: "native", BTC: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599" },
290
+ arbitrum: { ETH: "native", BTC: "0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f" },
291
+ polygon: { MATIC: "native", BTC: "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6" },
292
+ avalanche: { AVAX: "native" },
293
+ bnb: { BNB: "native" }
294
+ };
295
+ var SwapAlternativeSchema = import_zod7.z.object({
296
+ token: AltTokenSchema,
297
+ network: NetworkSchema.describe(
298
+ "Which network to send `token` on \u2014 pass both as `inputToken`/`inputNetwork` to `POST /v1/charges/{id}/quote`. The same token can appear more than once here, once per network that trusts it and that this charge accepts payment on."
299
+ )
300
+ });
301
+ function listSwapAlternatives(networks) {
302
+ const alternatives = [];
303
+ for (const network of new Set(networks)) {
304
+ for (const token of Object.keys(ALT_TOKEN_ADDRESSES[network] ?? {})) {
305
+ alternatives.push({ token, network });
306
+ }
307
+ }
308
+ return alternatives;
309
+ }
310
+
267
311
  // src/charges.ts
268
- var import_zod8 = require("zod");
312
+ var import_zod9 = require("zod");
269
313
 
270
314
  // src/checkout-metadata.ts
271
- var import_zod7 = require("zod");
315
+ var import_zod8 = require("zod");
272
316
  var CHECKOUT_PRODUCTS_MAX = 20;
273
- var CheckoutProductSchema = import_zod7.z.object({
274
- name: import_zod7.z.string().min(1).max(200).describe("What the payer is buying, shown as-is on the hosted checkout page."),
275
- quantity: import_zod7.z.number().int().positive().max(9999).optional().describe("How many of this item. Omit for a single, unquantified item."),
276
- imageUrl: import_zod7.z.string().url().max(2048).refine((value) => /^https?:\/\//.test(value), "must use http or https").optional().describe(
317
+ var CheckoutProductSchema = import_zod8.z.object({
318
+ name: import_zod8.z.string().min(1).max(200).describe("What the payer is buying, shown as-is on the hosted checkout page."),
319
+ quantity: import_zod8.z.number().int().positive().max(9999).optional().describe("How many of this item. Omit for a single, unquantified item."),
320
+ imageUrl: import_zod8.z.string().url().max(2048).refine((value) => /^https?:\/\//.test(value), "must use http or https").optional().describe(
277
321
  "Product image, fetched only by the payer's own browser \u2014 Klappay never fetches it server-side. Must be `http(s)`."
278
322
  )
279
323
  });
280
- var KlappayCheckoutMetadataSchema = import_zod7.z.object({
281
- products: import_zod7.z.array(CheckoutProductSchema).max(CHECKOUT_PRODUCTS_MAX).optional().describe(
324
+ var KlappayCheckoutMetadataSchema = import_zod8.z.object({
325
+ products: import_zod8.z.array(CheckoutProductSchema).max(CHECKOUT_PRODUCTS_MAX).optional().describe(
282
326
  `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.`
283
327
  )
284
328
  }).describe(
285
329
  "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."
286
330
  );
287
- var MetadataWithKlappaySchema = import_zod7.z.object({ klappay: KlappayCheckoutMetadataSchema.optional() }).catchall(import_zod7.z.unknown()).describe(
331
+ var MetadataWithKlappaySchema = import_zod8.z.object({ klappay: KlappayCheckoutMetadataSchema.optional() }).catchall(import_zod8.z.unknown()).describe(
288
332
  "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`."
289
333
  );
290
334
 
291
335
  // src/charges.ts
292
- var ChargeStatusSchema = import_zod8.z.enum(["pending", "partially_paid", "confirmed", "expired", "underpaid"]).describe(
336
+ var ChargeStatusSchema = import_zod9.z.enum(["pending", "partially_paid", "confirmed", "expired", "underpaid"]).describe(
293
337
  "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."
294
338
  );
295
- var SettlementStatusSchema = import_zod8.z.enum(["pending", "completed", "failed"]).describe(
339
+ var SettlementStatusSchema = import_zod9.z.enum(["pending", "completed", "failed"]).describe(
296
340
  "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."
297
341
  );
298
342
  var CHARGE_EXPIRES_IN_MIN_SECONDS = 60;
299
343
  var CHARGE_EXPIRES_IN_MAX_SECONDS = 3600;
300
344
  var CHARGE_ACCEPTED_PAYMENTS_MAX = 14;
301
- var AcceptedPaymentSchema = import_zod8.z.object({
345
+ var AcceptedPaymentSchema = import_zod9.z.object({
302
346
  token: TokenSchema,
303
347
  network: NetworkSchema
304
348
  });
305
- var AcceptedPaymentsSchema = import_zod8.z.array(AcceptedPaymentSchema).min(1, "At least one accepted payment is required.").max(CHARGE_ACCEPTED_PAYMENTS_MAX).superRefine((pairs, ctx) => {
349
+ var AcceptedPaymentsSchema = import_zod9.z.array(AcceptedPaymentSchema).min(1, "At least one accepted payment is required.").max(CHARGE_ACCEPTED_PAYMENTS_MAX).superRefine((pairs, ctx) => {
306
350
  const seen = /* @__PURE__ */ new Set();
307
351
  pairs.forEach((pair, index) => {
308
352
  const key = `${pair.token}:${pair.network}`;
309
353
  if (seen.has(key)) {
310
354
  ctx.addIssue({
311
- code: import_zod8.z.ZodIssueCode.custom,
355
+ code: import_zod9.z.ZodIssueCode.custom,
312
356
  message: `Duplicate accepted payment: ${pair.token} on ${pair.network}.`,
313
357
  path: [index]
314
358
  });
@@ -316,7 +360,7 @@ var AcceptedPaymentsSchema = import_zod8.z.array(AcceptedPaymentSchema).min(1, "
316
360
  seen.add(key);
317
361
  if (!OPERATIONAL_NETWORKS.includes(pair.network)) {
318
362
  ctx.addIssue({
319
- code: import_zod8.z.ZodIssueCode.custom,
363
+ code: import_zod9.z.ZodIssueCode.custom,
320
364
  message: `Network "${pair.network}" isn't live yet \u2014 only ${OPERATIONAL_NETWORKS.join(", ")} today.`,
321
365
  path: [index, "network"]
322
366
  });
@@ -326,32 +370,32 @@ var AcceptedPaymentsSchema = import_zod8.z.array(AcceptedPaymentSchema).min(1, "
326
370
  `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\`.`
327
371
  );
328
372
  var CHARGE_SPLIT_RECIPIENTS_MAX = 5;
329
- var SplitRecipientSchema = import_zod8.z.object({
330
- 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."),
331
- percent: import_zod8.z.number().positive().max(100).describe(
373
+ var SplitRecipientSchema = import_zod9.z.object({
374
+ address: import_zod9.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."),
375
+ percent: import_zod9.z.number().positive().max(100).describe(
332
376
  "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."
333
377
  ),
334
- label: import_zod8.z.string().min(1).max(64).optional().describe(
378
+ label: import_zod9.z.string().min(1).max(64).optional().describe(
335
379
  'Free-form label for your own bookkeeping (e.g. `"supplier"`, `"sales rep"`) \u2014 echoed back unchanged, never interpreted by Klappay.'
336
380
  )
337
381
  });
338
- var SplitRecipientInputSchema = import_zod8.z.object({
339
- recipientId: import_zod8.z.string().describe(
382
+ var SplitRecipientInputSchema = import_zod9.z.object({
383
+ recipientId: import_zod9.z.string().describe(
340
384
  "id of a `Recipient` you already registered via `POST /v1/recipients` (not a raw address) \u2014 see `recipients:write`/`charges:split_write` scopes. A leaked `charges:write`-only key can never redirect payout to a brand new address this way, only reference one already trusted."
341
385
  ),
342
- percent: import_zod8.z.number().positive().max(100).describe(
386
+ percent: import_zod9.z.number().positive().max(100).describe(
343
387
  "Percent of *your own* net share (i.e. of `100 - feePercent`, not of the charge's gross `amount`) to route to this recipient 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."
344
388
  ),
345
- label: import_zod8.z.string().min(1).max(64).optional().describe(
389
+ label: import_zod9.z.string().min(1).max(64).optional().describe(
346
390
  'Free-form label for your own bookkeeping (e.g. `"supplier"`, `"sales rep"`) \u2014 echoed back unchanged, never interpreted by Klappay. Independent of the label the recipient was registered with.'
347
391
  )
348
392
  });
349
- var SplitRecipientsInputSchema = import_zod8.z.array(SplitRecipientInputSchema).max(CHARGE_SPLIT_RECIPIENTS_MAX).superRefine((recipients, ctx) => {
393
+ var SplitRecipientsInputSchema = import_zod9.z.array(SplitRecipientInputSchema).max(CHARGE_SPLIT_RECIPIENTS_MAX).superRefine((recipients, ctx) => {
350
394
  const seen = /* @__PURE__ */ new Set();
351
395
  recipients.forEach((recipient, index) => {
352
396
  if (seen.has(recipient.recipientId)) {
353
397
  ctx.addIssue({
354
- code: import_zod8.z.ZodIssueCode.custom,
398
+ code: import_zod9.z.ZodIssueCode.custom,
355
399
  message: `Duplicate split recipientId: ${recipient.recipientId}.`,
356
400
  path: [index, "recipientId"]
357
401
  });
@@ -362,79 +406,82 @@ var SplitRecipientsInputSchema = import_zod8.z.array(SplitRecipientInputSchema).
362
406
  `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}, each referenced by \`recipientId\` (see \`POST /v1/recipients\`), never a raw address. Requires the \`charges:split_write\` scope in addition to \`charges:write\`. 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\`.`
363
407
  );
364
408
  var CHARGE_AMOUNT_MAX = 999999999999;
365
- var CreateChargeSchema = import_zod8.z.object({
366
- amount: import_zod8.z.number().positive().max(CHARGE_AMOUNT_MAX).describe(
409
+ var CreateChargeSchema = import_zod9.z.object({
410
+ amount: import_zod9.z.number().positive().max(CHARGE_AMOUNT_MAX).describe(
367
411
  "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."
368
412
  ),
369
- currency: import_zod8.z.literal("USD").default("USD").describe("Always `USD` today \u2014 the only supported currency."),
413
+ currency: import_zod9.z.literal("USD").default("USD").describe("Always `USD` today \u2014 the only supported currency."),
370
414
  acceptedPayments: AcceptedPaymentsSchema,
371
- expiresIn: import_zod8.z.number().int().min(CHARGE_EXPIRES_IN_MIN_SECONDS).max(CHARGE_EXPIRES_IN_MAX_SECONDS).describe(
415
+ expiresIn: import_zod9.z.number().int().min(CHARGE_EXPIRES_IN_MIN_SECONDS).max(CHARGE_EXPIRES_IN_MAX_SECONDS).describe(
372
416
  "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."
373
417
  ),
374
- idempotencyKey: import_zod8.z.string().min(1).max(255).optional().describe(
418
+ idempotencyKey: import_zod9.z.string().min(1).max(255).optional().describe(
375
419
  "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."
376
420
  ),
377
- externalRef: import_zod8.z.string().min(1).max(255).optional().describe(
421
+ externalRef: import_zod9.z.string().min(1).max(255).optional().describe(
378
422
  "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."
379
423
  ),
380
- source: import_zod8.z.string().min(1).max(64).optional().describe(
424
+ source: import_zod9.z.string().min(1).max(64).optional().describe(
381
425
  '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.'
382
426
  ),
383
427
  metadata: MetadataWithKlappaySchema.optional(),
384
- redirectUrl: import_zod8.z.string().url().refine((value) => /^https?:\/\//.test(value), "must use http or https").optional().describe(
428
+ redirectUrl: import_zod9.z.string().url().refine((value) => /^https?:\/\//.test(value), "must use http or https").optional().describe(
385
429
  "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."
386
430
  ),
387
431
  splitRecipients: SplitRecipientsInputSchema.optional()
388
432
  });
389
- var ChargeSchema = import_zod8.z.object({
390
- id: import_zod8.z.string().describe("Klappay-generated id, e.g. `ch_...`. Use this to look up the charge later."),
391
- amount: import_zod8.z.number().describe("The amount originally requested, in `currency` units (up to 6 decimal places)."),
392
- amountReceived: import_zod8.z.number().nullable().describe(
433
+ var ChargeSchema = import_zod9.z.object({
434
+ id: import_zod9.z.string().describe("Klappay-generated id, e.g. `ch_...`. Use this to look up the charge later."),
435
+ amount: import_zod9.z.number().describe("The amount originally requested, in `currency` units (up to 6 decimal places)."),
436
+ amountReceived: import_zod9.z.number().nullable().describe(
393
437
  "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`."
394
438
  ),
395
- isOverpaid: import_zod8.z.boolean().describe(
439
+ isOverpaid: import_zod9.z.boolean().describe(
396
440
  "`true` if `amountReceived` ended up greater than `amount`. Klappay never refunds the difference automatically \u2014 see the docs for why."
397
441
  ),
398
- currency: import_zod8.z.string().describe("Always `USD` today \u2014 the only supported currency."),
399
- acceptedPayments: import_zod8.z.array(AcceptedPaymentSchema).describe(
442
+ currency: import_zod9.z.string().describe("Always `USD` today \u2014 the only supported currency."),
443
+ acceptedPayments: import_zod9.z.array(AcceptedPaymentSchema).describe(
400
444
  "Every `(token, network)` pair this charge was configured to accept, unchanged after creation."
401
445
  ),
402
- paidWith: import_zod8.z.array(AcceptedPaymentSchema).describe(
446
+ paidWith: import_zod9.z.array(AcceptedPaymentSchema).describe(
403
447
  "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`."
404
448
  ),
405
- address: import_zod8.z.string().describe(
449
+ swapAlternatives: import_zod9.z.array(SwapAlternativeSchema).describe(
450
+ "Every `(token, network)` pair the payer can pay with instead, via `POST /v1/charges/{id}/quote` \u2014 derived from the networks in `acceptedPayments` (e.g. a charge accepting USDC on both Base and Optimism lists `ETH` on Base and `ETH` on Optimism separately, since they're different networks the payer has to choose between, not one merged option). Pass an entry's `token`/`network` straight through as `inputToken`/`inputNetwork`. Recomputed on every read against Klappay's current trusted list, not frozen at creation \u2014 empty if this charge's networks have no trusted alt-token, if swap-to-pay isn't configured on this deployment, or if `environment` is `test` (0x, who powers the swap, has no testnet support at all \u2014 `POST /v1/charges/{id}/quote` always rejects a test-environment charge with `422 swap_test_environment_unsupported`)."
451
+ ),
452
+ address: import_zod9.z.string().describe(
406
453
  "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."
407
454
  ),
408
455
  status: ChargeStatusSchema,
409
456
  settlementStatus: SettlementStatusSchema.nullable(),
410
457
  environment: EnvironmentSchema,
411
- apiKeyId: import_zod8.z.string().nullable().describe(
458
+ apiKeyId: import_zod9.z.string().nullable().describe(
412
459
  "Which of your API keys created this charge. `null` for a charge created before this field existed."
413
460
  ),
414
- txHash: import_zod8.z.string().nullable().describe(
461
+ txHash: import_zod9.z.string().nullable().describe(
415
462
  "Transaction hash of the most recent transfer detected for this charge. `null` until a payment is detected."
416
463
  ),
417
- externalRef: import_zod8.z.string().nullable(),
418
- source: import_zod8.z.string().nullable(),
464
+ externalRef: import_zod9.z.string().nullable(),
465
+ source: import_zod9.z.string().nullable(),
419
466
  metadata: MetadataWithKlappaySchema.nullable(),
420
- redirectUrl: import_zod8.z.string().nullable().describe("Echoes the `redirectUrl` set at creation, if any. `null` if none was set."),
421
- checkoutUrl: import_zod8.z.string().nullable().describe(
467
+ redirectUrl: import_zod9.z.string().nullable().describe("Echoes the `redirectUrl` set at creation, if any. `null` if none was set."),
468
+ checkoutUrl: import_zod9.z.string().nullable().describe(
422
469
  "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."
423
470
  ),
424
- splitRecipients: import_zod8.z.array(SplitRecipientSchema).describe("Echoes whatever extra split recipients were set at creation \u2014 empty array if none."),
425
- createdAt: import_zod8.z.string().datetime(),
426
- expiresAt: import_zod8.z.string().datetime().describe(
471
+ splitRecipients: import_zod9.z.array(SplitRecipientSchema).describe("Echoes whatever extra split recipients were set at creation \u2014 empty array if none."),
472
+ createdAt: import_zod9.z.string().datetime(),
473
+ expiresAt: import_zod9.z.string().datetime().describe(
427
474
  "When this charge stops accepting payment, if still `pending`/`partially_paid` by then."
428
475
  ),
429
- confirmedAt: import_zod8.z.string().datetime().nullable().describe("When `status` first reached `confirmed`. `null` until then."),
430
- settledAt: import_zod8.z.string().datetime().nullable().describe(
476
+ confirmedAt: import_zod9.z.string().datetime().nullable().describe("When `status` first reached `confirmed`. `null` until then."),
477
+ settledAt: import_zod9.z.string().datetime().nullable().describe(
431
478
  "When `settlementStatus` first reached `completed` \u2014 the merchant's wallet actually has the funds. `null` until then, including while `settlementStatus` is `pending`/`failed`."
432
479
  ),
433
- lastActivityAt: import_zod8.z.string().datetime().describe(
480
+ lastActivityAt: import_zod9.z.string().datetime().describe(
434
481
  "When a transfer was last credited toward this charge, or `createdAt` if none has arrived yet."
435
482
  )
436
483
  });
437
- var ListChargesSchema = import_zod8.z.object({
484
+ var ListChargesSchema = import_zod9.z.object({
438
485
  status: ChargeStatusSchema.optional(),
439
486
  token: TokenSchema.optional().describe(
440
487
  "Filters on `paidWith.token` \u2014 the pair actually paid, not accepted."
@@ -443,13 +490,13 @@ var ListChargesSchema = import_zod8.z.object({
443
490
  "Filters on `paidWith.network` \u2014 the pair actually paid, not accepted."
444
491
  ),
445
492
  environment: EnvironmentSchema.optional(),
446
- since: import_zod8.z.string().datetime().optional().describe(
493
+ since: import_zod9.z.string().datetime().optional().describe(
447
494
  "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."
448
495
  ),
449
- isOverpaid: import_zod8.z.enum(["true", "false"]).transform((v) => v === "true").optional()
496
+ isOverpaid: import_zod9.z.enum(["true", "false"]).transform((v) => v === "true").optional()
450
497
  }).extend(PaginationQuerySchema.shape);
451
498
  var PaginatedChargesSchema = paginatedSchema(ChargeSchema);
452
- var GetChargeQrCodeQuerySchema = import_zod8.z.object({
499
+ var GetChargeQrCodeQuerySchema = import_zod9.z.object({
453
500
  token: TokenSchema.optional().describe(
454
501
  "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."
455
502
  ),
@@ -457,61 +504,61 @@ var GetChargeQrCodeQuerySchema = import_zod8.z.object({
457
504
  });
458
505
 
459
506
  // src/distributions.ts
460
- var import_zod9 = require("zod");
461
- var SplitDistributionStatusSchema = import_zod9.z.enum(["pending", "processing", "completed", "failed"]).describe(
507
+ var import_zod10 = require("zod");
508
+ var SplitDistributionStatusSchema = import_zod10.z.enum(["pending", "processing", "completed", "failed"]).describe(
462
509
  "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."
463
510
  );
464
- var PendingDistributionRecipientSchema = import_zod9.z.object({
465
- address: import_zod9.z.string().describe("On-chain recipient address."),
466
- percentAllocation: import_zod9.z.number().describe("This recipient's share of the split, as a percentage (e.g. `99.0991` = 99.0991%).")
511
+ var PendingDistributionRecipientSchema = import_zod10.z.object({
512
+ address: import_zod10.z.string().describe("On-chain recipient address."),
513
+ percentAllocation: import_zod10.z.number().describe("This recipient's share of the split, as a percentage (e.g. `99.0991` = 99.0991%).")
467
514
  });
468
- var PendingDistributionSchema = import_zod9.z.object({
469
- splitAddress: import_zod9.z.string().describe("The on-chain 0xSplits address to call `distribute()` on."),
515
+ var PendingDistributionSchema = import_zod10.z.object({
516
+ splitAddress: import_zod10.z.string().describe("The on-chain 0xSplits address to call `distribute()` on."),
470
517
  network: NetworkSchema,
471
518
  token: TokenSchema,
472
- recipients: import_zod9.z.array(PendingDistributionRecipientSchema).describe(
519
+ recipients: import_zod10.z.array(PendingDistributionRecipientSchema).describe(
473
520
  "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."
474
521
  ),
475
- distributorFeePercent: import_zod9.z.number().describe(
522
+ distributorFeePercent: import_zod10.z.number().describe(
476
523
  "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."
477
524
  ),
478
- estimatedRewardAmount: import_zod9.z.number().describe(
525
+ estimatedRewardAmount: import_zod10.z.number().describe(
479
526
  "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."
480
527
  ),
481
- availableSince: import_zod9.z.string().datetime().describe("When this distribution entered its grace period."),
482
- graceEndsAt: import_zod9.z.string().datetime().describe(
528
+ availableSince: import_zod10.z.string().datetime().describe("When this distribution entered its grace period."),
529
+ graceEndsAt: import_zod10.z.string().datetime().describe(
483
530
  "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."
484
531
  )
485
532
  });
486
533
  var PaginatedPendingDistributionsSchema = paginatedSchema(PendingDistributionSchema);
487
- var ListenPendingDistributionsQuerySchema = import_zod9.z.object({
488
- limit: import_zod9.z.coerce.number().int().min(0).max(PAGINATION_LIMIT_MAX).default(0).describe(
534
+ var ListenPendingDistributionsQuerySchema = import_zod10.z.object({
535
+ limit: import_zod10.z.coerce.number().int().min(0).max(PAGINATION_LIMIT_MAX).default(0).describe(
489
536
  "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."
490
537
  )
491
538
  });
492
- var PendingDistributionEventSchema = import_zod9.z.discriminatedUnion("type", [
493
- import_zod9.z.object({
494
- type: import_zod9.z.literal("distribution.available"),
539
+ var PendingDistributionEventSchema = import_zod10.z.discriminatedUnion("type", [
540
+ import_zod10.z.object({
541
+ type: import_zod10.z.literal("distribution.available"),
495
542
  distribution: PendingDistributionSchema
496
543
  }),
497
- import_zod9.z.object({
498
- type: import_zod9.z.literal("distribution.claimed"),
499
- splitAddress: import_zod9.z.string().describe("No longer claimable \u2014 either settled by someone, or picked up by the worker.")
544
+ import_zod10.z.object({
545
+ type: import_zod10.z.literal("distribution.claimed"),
546
+ splitAddress: import_zod10.z.string().describe("No longer claimable \u2014 either settled by someone, or picked up by the worker.")
500
547
  })
501
548
  ]);
502
549
 
503
550
  // src/metrics.ts
504
- var import_zod10 = require("zod");
505
- var MetricsResourceSchema = import_zod10.z.enum(["charges", "transactions", "distributions"]).describe(
551
+ var import_zod11 = require("zod");
552
+ var MetricsResourceSchema = import_zod11.z.enum(["charges", "transactions", "distributions"]).describe(
506
553
  "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."
507
554
  );
508
- var MetricsAggregationSchema = import_zod10.z.enum(["count", "sum", "avg", "min", "max"]).describe(
555
+ var MetricsAggregationSchema = import_zod11.z.enum(["count", "sum", "avg", "min", "max"]).describe(
509
556
  "`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."
510
557
  );
511
- var MetricsFilterOperatorSchema = import_zod10.z.enum(["eq", "neq", "in", "gt", "gte", "lt", "lte"]).describe(
558
+ var MetricsFilterOperatorSchema = import_zod11.z.enum(["eq", "neq", "in", "gt", "gte", "lt", "lte"]).describe(
512
559
  "`in` expects an array value (max 50 entries); every other operator expects a single scalar."
513
560
  );
514
- var MetricsDateGranularitySchema = import_zod10.z.enum(["day", "week", "month", "year"]).describe(
561
+ var MetricsDateGranularitySchema = import_zod11.z.enum(["day", "week", "month", "year"]).describe(
515
562
  "Bucket width for a `date_bucket` `groupBy` entry \u2014 Postgres `date_trunc` semantics (UTC)."
516
563
  );
517
564
  var metricsQueryEnvironmentSchema = EnvironmentSchema.describe(
@@ -524,151 +571,151 @@ var METRICS_QUERY_MAX_GROUP_BY = 3;
524
571
  var METRICS_QUERY_MAX_FILTERS = 20;
525
572
  var METRICS_QUERY_MAX_METRICS = 10;
526
573
  var METRIC_ALIAS_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
527
- var metricAliasSchema = import_zod10.z.string().min(1).max(64).regex(
574
+ var metricAliasSchema = import_zod11.z.string().min(1).max(64).regex(
528
575
  METRIC_ALIAS_PATTERN,
529
576
  "Must start with a letter or underscore, and contain only letters, digits, and underscores \u2014 this becomes a SQL column alias."
530
577
  ).optional();
531
- var MetricsFilterValueSchema = import_zod10.z.union([
532
- import_zod10.z.string().max(255),
533
- import_zod10.z.number(),
534
- import_zod10.z.boolean(),
535
- import_zod10.z.array(import_zod10.z.union([import_zod10.z.string().max(255), import_zod10.z.number()])).min(1).max(50)
578
+ var MetricsFilterValueSchema = import_zod11.z.union([
579
+ import_zod11.z.string().max(255),
580
+ import_zod11.z.number(),
581
+ import_zod11.z.boolean(),
582
+ import_zod11.z.array(import_zod11.z.union([import_zod11.z.string().max(255), import_zod11.z.number()])).min(1).max(50)
536
583
  ]);
537
- var orderBySchema = import_zod10.z.object({
538
- key: import_zod10.z.string().min(1).max(64).regex(
584
+ var orderBySchema = import_zod11.z.object({
585
+ key: import_zod11.z.string().min(1).max(64).regex(
539
586
  METRIC_ALIAS_PATTERN,
540
587
  "Must start with a letter or underscore, and contain only letters, digits, and underscores \u2014 every valid output column name already looks like this."
541
588
  ).describe(
542
589
  "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."
543
590
  ),
544
- direction: import_zod10.z.enum(["asc", "desc"])
591
+ direction: import_zod11.z.enum(["asc", "desc"])
545
592
  }).describe(
546
593
  "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."
547
594
  );
548
- var limitSchema = import_zod10.z.number().int().min(1).max(METRICS_QUERY_MAX_ROW_LIMIT).default(METRICS_QUERY_DEFAULT_ROW_LIMIT).describe(
595
+ var limitSchema = import_zod11.z.number().int().min(1).max(METRICS_QUERY_MAX_ROW_LIMIT).default(METRICS_QUERY_DEFAULT_ROW_LIMIT).describe(
549
596
  `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.`
550
597
  );
551
- var ChargesQueryFieldSchema = import_zod10.z.enum(["status", "source", "apiKeyId", "currency", "isOverpaid", "externalRef"]).describe(
598
+ var ChargesQueryFieldSchema = import_zod11.z.enum(["status", "source", "apiKeyId", "currency", "isOverpaid", "externalRef"]).describe(
552
599
  "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."
553
600
  );
554
- var ChargesMetricFieldSchema = import_zod10.z.enum(["amount", "amountReceived", "feePercent"]).describe(
601
+ var ChargesMetricFieldSchema = import_zod11.z.enum(["amount", "amountReceived", "feePercent"]).describe(
555
602
  "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%."
556
603
  );
557
- var ChargesDateFieldSchema = import_zod10.z.enum(["createdAt", "confirmedAt", "lastActivityAt", "expiresAt"]).describe(
604
+ var ChargesDateFieldSchema = import_zod11.z.enum(["createdAt", "confirmedAt", "lastActivityAt", "expiresAt"]).describe(
558
605
  "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."
559
606
  );
560
- var ChargesFilterSchema = import_zod10.z.object({
607
+ var ChargesFilterSchema = import_zod11.z.object({
561
608
  field: ChargesQueryFieldSchema,
562
609
  operator: MetricsFilterOperatorSchema,
563
610
  value: MetricsFilterValueSchema
564
611
  });
565
- var ChargesGroupBySchema = import_zod10.z.union([
566
- import_zod10.z.object({ type: import_zod10.z.literal("field"), field: ChargesQueryFieldSchema }),
567
- import_zod10.z.object({
568
- type: import_zod10.z.literal("date_bucket"),
612
+ var ChargesGroupBySchema = import_zod11.z.union([
613
+ import_zod11.z.object({ type: import_zod11.z.literal("field"), field: ChargesQueryFieldSchema }),
614
+ import_zod11.z.object({
615
+ type: import_zod11.z.literal("date_bucket"),
569
616
  field: ChargesDateFieldSchema,
570
617
  granularity: MetricsDateGranularitySchema
571
618
  })
572
619
  ]);
573
- var ChargesMetricSchema = import_zod10.z.object({
620
+ var ChargesMetricSchema = import_zod11.z.object({
574
621
  aggregation: MetricsAggregationSchema,
575
622
  field: ChargesMetricFieldSchema.optional(),
576
623
  alias: metricAliasSchema
577
624
  });
578
- var ChargesMetricsQuerySchema = import_zod10.z.object({
579
- resource: import_zod10.z.literal("charges"),
625
+ var ChargesMetricsQuerySchema = import_zod11.z.object({
626
+ resource: import_zod11.z.literal("charges"),
580
627
  environment: metricsQueryEnvironmentSchema,
581
- dateRange: import_zod10.z.object({
628
+ dateRange: import_zod11.z.object({
582
629
  field: ChargesDateFieldSchema,
583
- from: import_zod10.z.string().max(64).datetime(),
584
- to: import_zod10.z.string().max(64).datetime()
630
+ from: import_zod11.z.string().max(64).datetime(),
631
+ to: import_zod11.z.string().max(64).datetime()
585
632
  }),
586
- groupBy: import_zod10.z.array(ChargesGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
587
- metrics: import_zod10.z.array(ChargesMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
588
- filters: import_zod10.z.array(ChargesFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
633
+ groupBy: import_zod11.z.array(ChargesGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
634
+ metrics: import_zod11.z.array(ChargesMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
635
+ filters: import_zod11.z.array(ChargesFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
589
636
  orderBy: orderBySchema.optional(),
590
637
  limit: limitSchema
591
638
  });
592
- var TransactionsQueryFieldSchema = import_zod10.z.enum(["network", "token", "source", "causedTransition"]).describe(
639
+ var TransactionsQueryFieldSchema = import_zod11.z.enum(["network", "token", "source", "causedTransition"]).describe(
593
640
  "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)."
594
641
  );
595
- var TransactionsMetricFieldSchema = import_zod10.z.enum(["amount"]).describe("The transfer amount, in the charge's `currency` units.");
596
- var TransactionsDateFieldSchema = import_zod10.z.enum(["detectedAt"]).describe("When Klappay detected this transfer on-chain (not when it was mined).");
597
- var TransactionsFilterSchema = import_zod10.z.object({
642
+ var TransactionsMetricFieldSchema = import_zod11.z.enum(["amount"]).describe("The transfer amount, in the charge's `currency` units.");
643
+ var TransactionsDateFieldSchema = import_zod11.z.enum(["detectedAt"]).describe("When Klappay detected this transfer on-chain (not when it was mined).");
644
+ var TransactionsFilterSchema = import_zod11.z.object({
598
645
  field: TransactionsQueryFieldSchema,
599
646
  operator: MetricsFilterOperatorSchema,
600
647
  value: MetricsFilterValueSchema
601
648
  });
602
- var TransactionsGroupBySchema = import_zod10.z.union([
603
- import_zod10.z.object({ type: import_zod10.z.literal("field"), field: TransactionsQueryFieldSchema }),
604
- import_zod10.z.object({
605
- type: import_zod10.z.literal("date_bucket"),
649
+ var TransactionsGroupBySchema = import_zod11.z.union([
650
+ import_zod11.z.object({ type: import_zod11.z.literal("field"), field: TransactionsQueryFieldSchema }),
651
+ import_zod11.z.object({
652
+ type: import_zod11.z.literal("date_bucket"),
606
653
  field: TransactionsDateFieldSchema,
607
654
  granularity: MetricsDateGranularitySchema
608
655
  })
609
656
  ]);
610
- var TransactionsMetricSchema = import_zod10.z.object({
657
+ var TransactionsMetricSchema = import_zod11.z.object({
611
658
  aggregation: MetricsAggregationSchema,
612
659
  field: TransactionsMetricFieldSchema.optional(),
613
660
  alias: metricAliasSchema
614
661
  });
615
- var TransactionsMetricsQuerySchema = import_zod10.z.object({
616
- resource: import_zod10.z.literal("transactions"),
662
+ var TransactionsMetricsQuerySchema = import_zod11.z.object({
663
+ resource: import_zod11.z.literal("transactions"),
617
664
  environment: metricsQueryEnvironmentSchema,
618
- dateRange: import_zod10.z.object({
665
+ dateRange: import_zod11.z.object({
619
666
  field: TransactionsDateFieldSchema,
620
- from: import_zod10.z.string().max(64).datetime(),
621
- to: import_zod10.z.string().max(64).datetime()
667
+ from: import_zod11.z.string().max(64).datetime(),
668
+ to: import_zod11.z.string().max(64).datetime()
622
669
  }),
623
- groupBy: import_zod10.z.array(TransactionsGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
624
- metrics: import_zod10.z.array(TransactionsMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
625
- filters: import_zod10.z.array(TransactionsFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
670
+ groupBy: import_zod11.z.array(TransactionsGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
671
+ metrics: import_zod11.z.array(TransactionsMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
672
+ filters: import_zod11.z.array(TransactionsFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
626
673
  orderBy: orderBySchema.optional(),
627
674
  limit: limitSchema
628
675
  });
629
- var DistributionsQueryFieldSchema = import_zod10.z.enum(["status", "network", "token", "distributorAddress"]).describe(
676
+ var DistributionsQueryFieldSchema = import_zod11.z.enum(["status", "network", "token", "distributorAddress"]).describe(
630
677
  "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."
631
678
  );
632
- var DistributionsMetricFieldSchema = import_zod10.z.enum(["attempts"]).describe(
679
+ var DistributionsMetricFieldSchema = import_zod11.z.enum(["attempts"]).describe(
633
680
  "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."
634
681
  );
635
- var DistributionsDateFieldSchema = import_zod10.z.enum(["createdAt", "processingStartedAt", "completedAt"]).describe(
682
+ var DistributionsDateFieldSchema = import_zod11.z.enum(["createdAt", "processingStartedAt", "completedAt"]).describe(
636
683
  "`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."
637
684
  );
638
- var DistributionsFilterSchema = import_zod10.z.object({
685
+ var DistributionsFilterSchema = import_zod11.z.object({
639
686
  field: DistributionsQueryFieldSchema,
640
687
  operator: MetricsFilterOperatorSchema,
641
688
  value: MetricsFilterValueSchema
642
689
  });
643
- var DistributionsGroupBySchema = import_zod10.z.union([
644
- import_zod10.z.object({ type: import_zod10.z.literal("field"), field: DistributionsQueryFieldSchema }),
645
- import_zod10.z.object({
646
- type: import_zod10.z.literal("date_bucket"),
690
+ var DistributionsGroupBySchema = import_zod11.z.union([
691
+ import_zod11.z.object({ type: import_zod11.z.literal("field"), field: DistributionsQueryFieldSchema }),
692
+ import_zod11.z.object({
693
+ type: import_zod11.z.literal("date_bucket"),
647
694
  field: DistributionsDateFieldSchema,
648
695
  granularity: MetricsDateGranularitySchema
649
696
  })
650
697
  ]);
651
- var DistributionsMetricSchema = import_zod10.z.object({
698
+ var DistributionsMetricSchema = import_zod11.z.object({
652
699
  aggregation: MetricsAggregationSchema,
653
700
  field: DistributionsMetricFieldSchema.optional(),
654
701
  alias: metricAliasSchema
655
702
  });
656
- var DistributionsMetricsQuerySchema = import_zod10.z.object({
657
- resource: import_zod10.z.literal("distributions"),
703
+ var DistributionsMetricsQuerySchema = import_zod11.z.object({
704
+ resource: import_zod11.z.literal("distributions"),
658
705
  environment: metricsQueryEnvironmentSchema,
659
- dateRange: import_zod10.z.object({
706
+ dateRange: import_zod11.z.object({
660
707
  field: DistributionsDateFieldSchema,
661
- from: import_zod10.z.string().max(64).datetime(),
662
- to: import_zod10.z.string().max(64).datetime()
708
+ from: import_zod11.z.string().max(64).datetime(),
709
+ to: import_zod11.z.string().max(64).datetime()
663
710
  }),
664
- groupBy: import_zod10.z.array(DistributionsGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
665
- metrics: import_zod10.z.array(DistributionsMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
666
- filters: import_zod10.z.array(DistributionsFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
711
+ groupBy: import_zod11.z.array(DistributionsGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
712
+ metrics: import_zod11.z.array(DistributionsMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
713
+ filters: import_zod11.z.array(DistributionsFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
667
714
  orderBy: orderBySchema.optional(),
668
715
  limit: limitSchema
669
716
  });
670
717
  var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
671
- var MetricsQuerySchema = import_zod10.z.discriminatedUnion("resource", [
718
+ var MetricsQuerySchema = import_zod11.z.discriminatedUnion("resource", [
672
719
  ChargesMetricsQuerySchema,
673
720
  TransactionsMetricsQuerySchema,
674
721
  DistributionsMetricsQuerySchema
@@ -677,7 +724,7 @@ var MetricsQuerySchema = import_zod10.z.discriminatedUnion("resource", [
677
724
  const to = new Date(input.dateRange.to);
678
725
  if (from >= to) {
679
726
  ctx.addIssue({
680
- code: import_zod10.z.ZodIssueCode.custom,
727
+ code: import_zod11.z.ZodIssueCode.custom,
681
728
  message: "`dateRange.from` must be before `dateRange.to`.",
682
729
  path: ["dateRange", "from"]
683
730
  });
@@ -685,7 +732,7 @@ var MetricsQuerySchema = import_zod10.z.discriminatedUnion("resource", [
685
732
  const spanDays = (to.getTime() - from.getTime()) / ONE_DAY_MS;
686
733
  if (spanDays > MAX_METRICS_QUERY_DATE_RANGE_DAYS) {
687
734
  ctx.addIssue({
688
- code: import_zod10.z.ZodIssueCode.custom,
735
+ code: import_zod11.z.ZodIssueCode.custom,
689
736
  message: `\`dateRange\` cannot span more than ${MAX_METRICS_QUERY_DATE_RANGE_DAYS} days.`,
690
737
  path: ["dateRange", "to"]
691
738
  });
@@ -693,7 +740,7 @@ var MetricsQuerySchema = import_zod10.z.discriminatedUnion("resource", [
693
740
  const dateBucketCount = input.groupBy.filter((entry) => entry.type === "date_bucket").length;
694
741
  if (dateBucketCount > 1) {
695
742
  ctx.addIssue({
696
- code: import_zod10.z.ZodIssueCode.custom,
743
+ code: import_zod11.z.ZodIssueCode.custom,
697
744
  message: "At most one `date_bucket` entry is allowed in `groupBy`.",
698
745
  path: ["groupBy"]
699
746
  });
@@ -701,7 +748,7 @@ var MetricsQuerySchema = import_zod10.z.discriminatedUnion("resource", [
701
748
  input.metrics.forEach((metric, index) => {
702
749
  if (metric.aggregation !== "count" && metric.field === void 0) {
703
750
  ctx.addIssue({
704
- code: import_zod10.z.ZodIssueCode.custom,
751
+ code: import_zod11.z.ZodIssueCode.custom,
705
752
  message: "`field` is required unless `aggregation` is `count`.",
706
753
  path: ["metrics", index, "field"]
707
754
  });
@@ -710,7 +757,7 @@ var MetricsQuerySchema = import_zod10.z.discriminatedUnion("resource", [
710
757
  const aliases = input.metrics.map((metric) => metric.alias).filter((alias) => alias !== void 0);
711
758
  if (new Set(aliases).size !== aliases.length) {
712
759
  ctx.addIssue({
713
- code: import_zod10.z.ZodIssueCode.custom,
760
+ code: import_zod11.z.ZodIssueCode.custom,
714
761
  message: "Every `metrics[].alias` must be unique.",
715
762
  path: ["metrics"]
716
763
  });
@@ -719,32 +766,32 @@ var MetricsQuerySchema = import_zod10.z.discriminatedUnion("resource", [
719
766
  input.metrics.forEach((metric, index) => {
720
767
  if (metric.alias !== void 0 && reservedNames.has(metric.alias)) {
721
768
  ctx.addIssue({
722
- code: import_zod10.z.ZodIssueCode.custom,
769
+ code: import_zod11.z.ZodIssueCode.custom,
723
770
  message: `\`alias\` "${metric.alias}" collides with a \`groupBy\` field name (or the reserved word "bucket") \u2014 choose a different alias.`,
724
771
  path: ["metrics", index, "alias"]
725
772
  });
726
773
  }
727
774
  });
728
775
  });
729
- var MetricsQueryResultRowSchema = import_zod10.z.record(
730
- import_zod10.z.string(),
731
- import_zod10.z.union([import_zod10.z.string(), import_zod10.z.number(), import_zod10.z.boolean(), import_zod10.z.null()])
776
+ var MetricsQueryResultRowSchema = import_zod11.z.record(
777
+ import_zod11.z.string(),
778
+ import_zod11.z.union([import_zod11.z.string(), import_zod11.z.number(), import_zod11.z.boolean(), import_zod11.z.null()])
732
779
  );
733
- var MetricsQueryResultSchema = import_zod10.z.object({
734
- data: import_zod10.z.array(MetricsQueryResultRowSchema),
735
- meta: import_zod10.z.object({
780
+ var MetricsQueryResultSchema = import_zod11.z.object({
781
+ data: import_zod11.z.array(MetricsQueryResultRowSchema),
782
+ meta: import_zod11.z.object({
736
783
  resource: MetricsResourceSchema,
737
784
  environment: EnvironmentSchema,
738
- rowCount: import_zod10.z.number().int().describe("Number of rows in `data`."),
739
- truncated: import_zod10.z.boolean().describe(
785
+ rowCount: import_zod11.z.number().int().describe("Number of rows in `data`."),
786
+ truncated: import_zod11.z.boolean().describe(
740
787
  "`true` if more rows matched than `limit` allowed \u2014 `data` holds only the first `limit`."
741
788
  )
742
789
  })
743
790
  });
744
791
 
745
792
  // src/webhook-events.ts
746
- var import_zod11 = require("zod");
747
- var ChargeWebhookEventTypeSchema = import_zod11.z.enum([
793
+ var import_zod12 = require("zod");
794
+ var ChargeWebhookEventTypeSchema = import_zod12.z.enum([
748
795
  "charge.created",
749
796
  "charge.partially_paid",
750
797
  "charge.confirmed",
@@ -756,14 +803,14 @@ var ChargeWebhookEventTypeSchema = import_zod11.z.enum([
756
803
  ]).describe(
757
804
  '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`.'
758
805
  );
759
- var WebhookDeliveryEventTypeSchema = import_zod11.z.enum(["webhook.delivery_failed", "webhook.delivery_recovered", "webhook.endpoint_unhealthy"]).describe(
806
+ var WebhookDeliveryEventTypeSchema = import_zod12.z.enum(["webhook.delivery_failed", "webhook.delivery_recovered", "webhook.endpoint_unhealthy"]).describe(
760
807
  "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`)."
761
808
  );
762
- var WebhookEventTypeSchema = import_zod11.z.union([
809
+ var WebhookEventTypeSchema = import_zod12.z.union([
763
810
  ChargeWebhookEventTypeSchema,
764
811
  WebhookDeliveryEventTypeSchema
765
812
  ]);
766
- var WebhookCategorySchema = import_zod11.z.enum(["payments", "webhooks"]).describe(
813
+ var WebhookCategorySchema = import_zod12.z.enum(["payments", "webhooks"]).describe(
767
814
  "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."
768
815
  );
769
816
  function buildCategoryMap() {
@@ -791,101 +838,101 @@ var TriggerableChargeEventSchema = ChargeWebhookEventTypeSchema.exclude([
791
838
  );
792
839
 
793
840
  // src/webhooks.ts
794
- var import_zod12 = require("zod");
841
+ var import_zod13 = require("zod");
795
842
  var WEBHOOK_EVENTS_WILDCARD = "*";
796
- var CreateWebhookSchema = import_zod12.z.object({
797
- url: import_zod12.z.string().max(2048).url().describe(
843
+ var CreateWebhookSchema = import_zod13.z.object({
844
+ url: import_zod13.z.string().max(2048).url().describe(
798
845
  "Must be HTTPS and resolve to a public address \u2014 private/internal IPs are rejected."
799
846
  ),
800
- 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(
847
+ events: import_zod13.z.array(import_zod13.z.union([WebhookEventTypeSchema, import_zod13.z.literal(WEBHOOK_EVENTS_WILDCARD)])).max(Object.keys(EVENT_CATEGORY_MAP).length + 1).default([]).describe(
801
848
  '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.'
802
849
  ),
803
- eventCategories: import_zod12.z.array(WebhookCategorySchema).max(WebhookCategorySchema.options.length).default([]).describe(
850
+ eventCategories: import_zod13.z.array(WebhookCategorySchema).max(WebhookCategorySchema.options.length).default([]).describe(
804
851
  "Subscribe to every event in these categories. At least one of `events` or `eventCategories` is required."
805
852
  ),
806
- excludeEvents: import_zod12.z.array(WebhookEventTypeSchema).max(Object.keys(EVENT_CATEGORY_MAP).length).default([]).describe(
853
+ excludeEvents: import_zod13.z.array(WebhookEventTypeSchema).max(Object.keys(EVENT_CATEGORY_MAP).length).default([]).describe(
807
854
  'Event types to exclude even if selected via `events: ["*"]` or `eventCategories`.'
808
855
  )
809
856
  }).refine((v) => v.events.length > 0 || v.eventCategories.length > 0, {
810
857
  message: "must select at least one event via `events` or `eventCategories`",
811
858
  path: ["events"]
812
859
  });
813
- var WebhookSchema = import_zod12.z.object({
814
- id: import_zod12.z.string(),
860
+ var WebhookSchema = import_zod13.z.object({
861
+ id: import_zod13.z.string(),
815
862
  environment: EnvironmentSchema.nullable().describe(
816
863
  "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)."
817
864
  ),
818
- url: import_zod12.z.string(),
819
- events: import_zod12.z.array(WebhookEventTypeSchema),
820
- eventCategories: import_zod12.z.array(WebhookCategorySchema),
821
- excludeEvents: import_zod12.z.array(WebhookEventTypeSchema),
822
- isWildcard: import_zod12.z.boolean(),
823
- secret: import_zod12.z.string().describe(
865
+ url: import_zod13.z.string(),
866
+ events: import_zod13.z.array(WebhookEventTypeSchema),
867
+ eventCategories: import_zod13.z.array(WebhookCategorySchema),
868
+ excludeEvents: import_zod13.z.array(WebhookEventTypeSchema),
869
+ isWildcard: import_zod13.z.boolean(),
870
+ secret: import_zod13.z.string().describe(
824
871
  "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."
825
872
  ),
826
- createdAt: import_zod12.z.string().datetime()
873
+ createdAt: import_zod13.z.string().datetime()
827
874
  });
828
875
  var WebhookListItemSchema = WebhookSchema.omit({ secret: true }).extend({
829
- hint: import_zod12.z.string().describe("A truncated, safe-to-display form of the secret (e.g. `whsec_...ab12`).")
876
+ hint: import_zod13.z.string().describe("A truncated, safe-to-display form of the secret (e.g. `whsec_...ab12`).")
830
877
  });
831
- var WebhookPayloadSchema = import_zod12.z.object({
832
- id: import_zod12.z.string().describe(
878
+ var WebhookPayloadSchema = import_zod13.z.object({
879
+ id: import_zod13.z.string().describe(
833
880
  "Unique id for this specific delivery \u2014 also sent as the `X-Klappay-Delivery` header."
834
881
  ),
835
882
  event: WebhookEventTypeSchema,
836
- createdAt: import_zod12.z.string().datetime(),
837
- data: import_zod12.z.unknown().describe(
883
+ createdAt: import_zod13.z.string().datetime(),
884
+ data: import_zod13.z.unknown().describe(
838
885
  "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."
839
886
  )
840
887
  });
841
- var WebhookDeliveryStatusSchema = import_zod12.z.enum(["pending", "delivered", "failed"]);
842
- var WebhookDeliverySchema = import_zod12.z.object({
843
- id: import_zod12.z.string(),
844
- webhookId: import_zod12.z.string(),
888
+ var WebhookDeliveryStatusSchema = import_zod13.z.enum(["pending", "delivered", "failed"]);
889
+ var WebhookDeliverySchema = import_zod13.z.object({
890
+ id: import_zod13.z.string(),
891
+ webhookId: import_zod13.z.string(),
845
892
  event: WebhookEventTypeSchema,
846
893
  status: WebhookDeliveryStatusSchema.describe(
847
894
  "`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."
848
895
  ),
849
- attempts: import_zod12.z.number(),
850
- responseCode: import_zod12.z.number().nullable().describe(
896
+ attempts: import_zod13.z.number(),
897
+ responseCode: import_zod13.z.number().nullable().describe(
851
898
  "HTTP status your endpoint returned on the most recent attempt. `null` if every attempt failed to connect at all."
852
899
  ),
853
- nextRetryAt: import_zod12.z.string().datetime().nullable(),
854
- deliveredAt: import_zod12.z.string().datetime().nullable(),
855
- createdAt: import_zod12.z.string().datetime()
900
+ nextRetryAt: import_zod13.z.string().datetime().nullable(),
901
+ deliveredAt: import_zod13.z.string().datetime().nullable(),
902
+ createdAt: import_zod13.z.string().datetime()
856
903
  });
857
904
  var ListWebhookDeliveriesSchema = PaginationQuerySchema;
858
905
  var PaginatedWebhookDeliveriesSchema = paginatedSchema(WebhookDeliverySchema);
859
906
 
860
907
  // src/recipients.ts
861
- var import_zod13 = require("zod");
908
+ var import_zod14 = require("zod");
862
909
  var EVM_ADDRESS_REGEX = /^0x[0-9a-fA-F]{40}$/;
863
- var CreateRecipientSchema = import_zod13.z.object({
864
- address: import_zod13.z.string().regex(EVM_ADDRESS_REGEX, "must be a 20-byte hex address").describe("EVM address to register as a trusted split recipient for your organization."),
865
- label: import_zod13.z.string().min(1).max(64).optional().describe('Free-form label for your own bookkeeping (e.g. `"supplier"`) \u2014 never interpreted.')
910
+ var CreateRecipientSchema = import_zod14.z.object({
911
+ address: import_zod14.z.string().regex(EVM_ADDRESS_REGEX, "must be a 20-byte hex address").describe("EVM address to register as a trusted split recipient for your organization."),
912
+ label: import_zod14.z.string().min(1).max(64).optional().describe('Free-form label for your own bookkeeping (e.g. `"supplier"`) \u2014 never interpreted.')
866
913
  });
867
- var RecipientSchema = import_zod13.z.object({
868
- id: import_zod13.z.string().describe(
914
+ var RecipientSchema = import_zod14.z.object({
915
+ id: import_zod14.z.string().describe(
869
916
  "Klappay-generated id, e.g. `rc_...` \u2014 this, not the raw address, is what a charge's `splitRecipients[].recipientId` references."
870
917
  ),
871
918
  environment: EnvironmentSchema,
872
- address: import_zod13.z.string(),
873
- label: import_zod13.z.string().nullable(),
874
- payout: import_zod13.z.boolean().describe(
919
+ address: import_zod14.z.string(),
920
+ label: import_zod14.z.string().nullable(),
921
+ payout: import_zod14.z.boolean().describe(
875
922
  "Whether this recipient is eligible to be used as an API key's `payoutAddress` (in addition to being referenceable in a split, which every non-revoked recipient already is). Set via `PATCH /v1/recipients/{id}` \u2014 requires the `recipients:manage_payout` scope, deliberately separate from `recipients:write`."
876
923
  ),
877
- createdAt: import_zod13.z.string().datetime()
924
+ createdAt: import_zod14.z.string().datetime()
878
925
  });
879
- var SetRecipientPayoutSchema = import_zod13.z.object({
880
- payout: import_zod13.z.boolean().describe("New payout-eligibility value for this recipient.")
926
+ var SetRecipientPayoutSchema = import_zod14.z.object({
927
+ payout: import_zod14.z.boolean().describe("New payout-eligibility value for this recipient.")
881
928
  });
882
929
 
883
930
  // src/timeline.ts
884
- var import_zod14 = require("zod");
885
- var TransactionSourceSchema = import_zod14.z.enum(["moralis_webhook", "reconciliation_job", "sandbox"]).describe(
931
+ var import_zod15 = require("zod");
932
+ var TransactionSourceSchema = import_zod15.z.enum(["moralis_webhook", "reconciliation_job", "sandbox"]).describe(
886
933
  "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)."
887
934
  );
888
- var TimelineEventTypeSchema = import_zod14.z.enum([
935
+ var TimelineEventTypeSchema = import_zod15.z.enum([
889
936
  "charge.created",
890
937
  "charge.expired",
891
938
  "transaction.detected",
@@ -896,11 +943,11 @@ var TimelineEventTypeSchema = import_zod14.z.enum([
896
943
  ]).describe(
897
944
  "`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)."
898
945
  );
899
- var TimelineEventSchema = import_zod14.z.object({
946
+ var TimelineEventSchema = import_zod15.z.object({
900
947
  type: TimelineEventTypeSchema,
901
- at: import_zod14.z.string().datetime(),
902
- txHash: import_zod14.z.string().optional().describe("Present for `transaction.detected` and `split.distributed` events only."),
903
- amount: import_zod14.z.number().optional().describe(
948
+ at: import_zod15.z.string().datetime(),
949
+ txHash: import_zod15.z.string().optional().describe("Present for `transaction.detected` and `split.distributed` events only."),
950
+ amount: import_zod15.z.number().optional().describe(
904
951
  "Present for `transaction.detected` events only \u2014 the amount that specific transfer carried."
905
952
  ),
906
953
  source: TransactionSourceSchema.optional().describe(
@@ -912,56 +959,112 @@ var TimelineEventSchema = import_zod14.z.object({
912
959
  network: NetworkSchema.optional().describe(
913
960
  "Present for `transaction.detected` and `split.distributed` events \u2014 which network this specific transfer, or settlement, used."
914
961
  ),
915
- causedTransition: import_zod14.z.boolean().optional().describe(
962
+ causedTransition: import_zod15.z.boolean().optional().describe(
916
963
  "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."
917
964
  ),
918
965
  event: WebhookEventTypeSchema.optional().describe(
919
966
  "Present for `webhook.*` events only \u2014 which event type this delivery was for."
920
967
  ),
921
- responseCode: import_zod14.z.number().nullable().optional().describe(
968
+ responseCode: import_zod15.z.number().nullable().optional().describe(
922
969
  "Present for `webhook.*` events only \u2014 HTTP status your endpoint returned, or `null` if the request never connected."
923
970
  ),
924
- attempts: import_zod14.z.number().optional().describe(
971
+ attempts: import_zod15.z.number().optional().describe(
925
972
  "Present for `webhook.*` events only \u2014 how many delivery attempts have been made so far."
926
973
  )
927
974
  });
928
975
 
929
976
  // src/health.ts
930
- var import_zod15 = require("zod");
931
- var HealthSchema = import_zod15.z.object({
932
- status: import_zod15.z.enum(["ok", "error"]).describe(
977
+ var import_zod16 = require("zod");
978
+ var HealthSchema = import_zod16.z.object({
979
+ status: import_zod16.z.enum(["ok", "error"]).describe(
933
980
  "`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."
934
981
  ),
935
- version: import_zod15.z.string(),
936
- timestamp: import_zod15.z.string().datetime(),
937
- db: import_zod15.z.enum(["ok", "error"]).describe("Result of a real database connectivity check, not just a process-alive check."),
938
- pendingWebhooks: import_zod15.z.number().describe("Count of webhook deliveries still awaiting a successful attempt."),
939
- oldestPendingChargeAgeSeconds: import_zod15.z.number().nullable().describe("Age of the oldest still-unpaid charge, in seconds. `null` if there are none."),
940
- lastMoralisEventAgeSeconds: import_zod15.z.number().nullable().describe(
982
+ version: import_zod16.z.string(),
983
+ timestamp: import_zod16.z.string().datetime(),
984
+ db: import_zod16.z.enum(["ok", "error"]).describe("Result of a real database connectivity check, not just a process-alive check."),
985
+ pendingWebhooks: import_zod16.z.number().describe("Count of webhook deliveries still awaiting a successful attempt."),
986
+ oldestPendingChargeAgeSeconds: import_zod16.z.number().nullable().describe("Age of the oldest still-unpaid charge, in seconds. `null` if there are none."),
987
+ lastMoralisEventAgeSeconds: import_zod16.z.number().nullable().describe(
941
988
  "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."
942
989
  )
943
990
  });
944
991
 
945
992
  // src/sandbox.ts
946
- var import_zod16 = require("zod");
947
- var SandboxTriggerSchema = import_zod16.z.object({
993
+ var import_zod17 = require("zod");
994
+ var SandboxTriggerSchema = import_zod17.z.object({
948
995
  event: TriggerableChargeEventSchema,
949
- amount: import_zod16.z.number().positive().max(CHARGE_AMOUNT_MAX).optional().describe(
996
+ amount: import_zod17.z.number().positive().max(CHARGE_AMOUNT_MAX).optional().describe(
950
997
  "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."
951
998
  )
952
999
  });
953
1000
 
954
1001
  // src/capabilities.ts
955
- var import_zod17 = require("zod");
956
- var CapabilitiesSchema = import_zod17.z.object({
957
- acceptedPayments: import_zod17.z.array(AcceptedPaymentSchema).describe(
1002
+ var import_zod18 = require("zod");
1003
+ var CapabilitiesSchema = import_zod18.z.object({
1004
+ acceptedPayments: import_zod18.z.array(AcceptedPaymentSchema).describe(
958
1005
  "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."
959
1006
  )
960
1007
  });
1008
+
1009
+ // src/swap.ts
1010
+ var import_zod19 = require("zod");
1011
+ var CreateSwapQuoteSchema = import_zod19.z.object({
1012
+ inputToken: AltTokenSchema.describe(
1013
+ "Which alt-cryptocurrency the payer wants to send \u2014 must be one of this charge's `swapAlternatives`, or `422 token_not_supported`."
1014
+ ),
1015
+ inputNetwork: NetworkSchema.describe(
1016
+ "Which network the payer will send `inputToken` on. Also picks which of this charge's `acceptedPayments` pairs the swap resolves to \u2014 a charge accepting USDC on both Base and Optimism resolves to whichever `inputNetwork` you pass. If the charge accepts more than one token on that same network, Klappay breaks the tie using its own trust ranking for that network (e.g. USDT over USDC on BNB Chain, where \"USDC\" is a third-party Binance-Peg token, not Circle's) \u2014 never a token the charge doesn't actually accept."
1017
+ ),
1018
+ takerAddress: import_zod19.z.string().regex(/^0x[0-9a-fA-F]{40}$/, "must be a 20-byte hex address").describe(
1019
+ "The payer's own wallet address \u2014 the account that will sign and submit the swap transaction. Not validated against anything else; any well-formed address is accepted, since Klappay never custodies these funds."
1020
+ )
1021
+ });
1022
+ var SwapQuoteSchema = import_zod19.z.object({
1023
+ inputToken: AltTokenSchema,
1024
+ inputNetwork: NetworkSchema,
1025
+ inputAmount: import_zod19.z.number().describe(
1026
+ "The ceiling of `inputToken` the payer needs available to sign for, in whole units (not wei/base units) \u2014 not necessarily the exact final cost. Any `inputToken` beyond what the swap actually needs (price moved favorably, less slippage than budgeted) is swapped back and refunded to the payer automatically, in the same transaction \u2014 never a separate step or a Klappay-side refund."
1027
+ ),
1028
+ outputToken: TokenSchema.describe(
1029
+ "Which of this charge's `acceptedPayments` tokens the swap resolves to."
1030
+ ),
1031
+ outputNetwork: NetworkSchema,
1032
+ outputAmount: import_zod19.z.number().describe(
1033
+ "The exact remaining amount owed on this charge (`amount - amountReceived`), in `currency` units \u2014 always what the merchant's split address receives, regardless of `inputAmount`."
1034
+ ),
1035
+ fees: import_zod19.z.object({
1036
+ klappayFee: import_zod19.z.number().describe(
1037
+ "Klappay's own swap fee (1% today), in `outputToken` units \u2014 paid by the payer, on top of `inputAmount`, separate from the merchant's own `feePercent`. Never subtracted from `outputAmount`."
1038
+ ),
1039
+ zeroExFee: import_zod19.z.number().nullable().describe(
1040
+ "0x's own protocol fee for this specific token pair, in `outputToken` units, or `null` when this pair isn't currently one 0x charges on. Also paid by the payer on top of `inputAmount`, also never subtracted from `outputAmount` \u2014 Klappay never sees this fee, it goes straight to 0x."
1041
+ )
1042
+ }).describe(
1043
+ "Every fee the payer is charged for using swap-to-pay, broken out by who collects it \u2014 both already reflected in `inputAmount`, shown here separately for transparency. Neither ever reduces `outputAmount`."
1044
+ ),
1045
+ expiresAt: import_zod19.z.string().datetime().describe(
1046
+ "When this quote's price is no longer safely valid \u2014 a rough guide for the payer's UI countdown only. The actual price guarantee is enforced on-chain by the swap transaction itself (a signed Permit2 deadline, or a minimum-output check for a native-currency sell), not by this timestamp \u2014 submitting after it expires either reverts on-chain or simply gets re-quoted at the current price, never silently executes at a stale rate."
1047
+ ),
1048
+ transaction: import_zod19.z.object({
1049
+ to: import_zod19.z.string().describe("Contract address the payer's wallet must send this transaction to."),
1050
+ data: import_zod19.z.string().describe("Calldata \u2014 opaque, must be sent unmodified."),
1051
+ value: import_zod19.z.string().describe(
1052
+ "Native currency (ETH/BNB/MATIC/AVAX) to attach, in wei \u2014 `\"0\"` when `inputToken` isn't this network's native currency."
1053
+ )
1054
+ }).describe(
1055
+ "Pass this directly to the payer's wallet (e.g. viem/ethers `sendTransaction`) \u2014 Klappay never touches the payer's private key or submits anything on their behalf. If `permit2` is present on this response, sign that first and append the signature to this `data` before sending; if `permit2` is absent, send `transaction` as-is with no extra step."
1056
+ ),
1057
+ permit2: import_zod19.z.object({ eip712: import_zod19.z.record(import_zod19.z.unknown()) }).optional().describe(
1058
+ "Present only when `inputToken` is an ERC-20 (today, only `BTC`) \u2014 the payer's wallet must sign this EIP-712 message and append the signature to `transaction.data` before sending, since an ERC-20 sell needs a Permit2 allowance signature that a native-currency sell doesn't. Absent when `inputToken` is a network's own native currency (ETH/BNB/MATIC/AVAX) \u2014 `transaction` is then ready to sign and send directly, no extra step."
1059
+ )
1060
+ });
961
1061
  // Annotate the CommonJS export names for ESM import in node:
962
1062
  0 && (module.exports = {
1063
+ ALT_TOKEN_ADDRESSES,
1064
+ ALT_TOKEN_DECIMALS,
963
1065
  API_KEY_SCOPES,
964
1066
  AcceptedPaymentSchema,
1067
+ AltTokenSchema,
965
1068
  ApiKeyScopeSchema,
966
1069
  CHARGE_ACCEPTED_PAYMENTS_MAX,
967
1070
  CHARGE_AMOUNT_MAX,
@@ -980,6 +1083,7 @@ var CapabilitiesSchema = import_zod17.z.object({
980
1083
  CheckoutProductSchema,
981
1084
  CreateChargeSchema,
982
1085
  CreateRecipientSchema,
1086
+ CreateSwapQuoteSchema,
983
1087
  CreateWebhookSchema,
984
1088
  DistributionsDateFieldSchema,
985
1089
  DistributionsMetricFieldSchema,
@@ -1029,6 +1133,8 @@ var CapabilitiesSchema = import_zod17.z.object({
1029
1133
  SplitDistributionStatusSchema,
1030
1134
  SplitRecipientInputSchema,
1031
1135
  SplitRecipientSchema,
1136
+ SwapAlternativeSchema,
1137
+ SwapQuoteSchema,
1032
1138
  TOKEN_ADDRESSES,
1033
1139
  TOKEN_DECIMALS,
1034
1140
  TimelineEventSchema,
@@ -1050,6 +1156,7 @@ var CapabilitiesSchema = import_zod17.z.object({
1050
1156
  WebhookPayloadSchema,
1051
1157
  WebhookSchema,
1052
1158
  findConflictingScopes,
1159
+ listSwapAlternatives,
1053
1160
  paginatedSchema
1054
1161
  });
1055
1162
  //# sourceMappingURL=index.js.map