@klappay/types 5.0.0 → 5.1.1

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.mjs CHANGED
@@ -4,38 +4,48 @@ import {
4
4
  CHAIN_IDS,
5
5
  EVM_NETWORKS,
6
6
  NETWORK_EXPLORERS,
7
+ NETWORK_FAMILIES,
7
8
  NETWORK_LABELS,
8
9
  OPERATIONAL_NETWORKS,
9
10
  TOKEN_ADDRESSES,
10
11
  TOKEN_DECIMALS,
11
12
  TOKEN_DEPLOYMENTS,
13
+ addressesEqual,
12
14
  getTokenDeployment,
13
- isPaymentDeploymentEnabled
14
- } from "./chunk-VTX32VJN.mjs";
15
+ isEvmAddress,
16
+ isPaymentDeploymentEnabled,
17
+ isSplitAddress,
18
+ isTronAddress,
19
+ tronAddress
20
+ } from "./chunk-VL7W6KNP.mjs";
15
21
 
16
- // src/errors.ts
22
+ // src/addresses.ts
17
23
  import { z } from "zod";
18
- var ErrorPayloadSchema = z.object({
19
- error: z.object({
20
- code: z.string().describe(
24
+ var SplitAddressSchema = z.string().refine(isSplitAddress, "must be a valid EVM (0x...) or TRON (T...) address");
25
+
26
+ // src/errors.ts
27
+ import { z as z2 } from "zod";
28
+ var ErrorPayloadSchema = z2.object({
29
+ error: z2.object({
30
+ code: z2.string().describe(
21
31
  "A stable, machine-readable error identifier (e.g. `validation_error`, `charge_not_found`)."
22
32
  ),
23
- message: z.string().describe(
33
+ message: z2.string().describe(
24
34
  "Human-readable explanation, safe to log or show a developer \u2014 not meant for end users."
25
35
  ),
26
- param: z.string().optional().describe("Which request field the error refers to, when applicable.")
36
+ param: z2.string().optional().describe("Which request field the error refers to, when applicable.")
27
37
  })
28
38
  });
29
39
 
30
40
  // src/environment.ts
31
- import { z as z2 } from "zod";
32
- var EnvironmentSchema = z2.enum(["live", "test"]).describe(
41
+ import { z as z3 } from "zod";
42
+ var EnvironmentSchema = z3.enum(["live", "test"]).describe(
33
43
  "`live` or `test`, matching the `klap_live_.../klap_test_...` prefix of the API key that created or is scoped to this resource. `live` uses the selected network's mainnet with real funds; `test` uses its separately configured testnet. Token contracts and availability are resolved per network/environment; a missing test deployment never falls back to live."
34
44
  );
35
45
 
36
46
  // src/api-key-scopes.ts
37
- import { z as z3 } from "zod";
38
- var ApiKeyScopeSchema = z3.enum([
47
+ import { z as z4 } from "zod";
48
+ var ApiKeyScopeSchema = z4.enum([
39
49
  "charges:read",
40
50
  "charges:write",
41
51
  "webhooks:read",
@@ -67,42 +77,42 @@ function findConflictingScopes(scopes) {
67
77
  }
68
78
 
69
79
  // src/networks.ts
70
- import { z as z4 } from "zod";
71
- var NetworkSchema = z4.enum(["base", "optimism", "polygon", "ethereum", "arbitrum", "avalanche", "bnb"]).describe("The blockchain a charge/payment is on.");
80
+ import { z as z5 } from "zod";
81
+ var NetworkSchema = z5.enum(["base", "optimism", "polygon", "ethereum", "arbitrum", "avalanche", "bnb", "tron", "arc"]).describe("The blockchain a charge/payment is on.");
72
82
 
73
83
  // src/pagination.ts
74
- import { z as z5 } from "zod";
84
+ import { z as z6 } from "zod";
75
85
  var PAGINATION_LIMIT_MIN = 1;
76
86
  var PAGINATION_LIMIT_MAX = 100;
77
87
  var PAGINATION_LIMIT_DEFAULT = 20;
78
- var PaginationQuerySchema = z5.object({
79
- limit: z5.coerce.number().min(PAGINATION_LIMIT_MIN).max(PAGINATION_LIMIT_MAX).default(PAGINATION_LIMIT_DEFAULT).describe(
88
+ var PaginationQuerySchema = z6.object({
89
+ limit: z6.coerce.number().min(PAGINATION_LIMIT_MIN).max(PAGINATION_LIMIT_MAX).default(PAGINATION_LIMIT_DEFAULT).describe(
80
90
  `Max items to return per page (${PAGINATION_LIMIT_MIN}\u2013${PAGINATION_LIMIT_MAX}, default ${PAGINATION_LIMIT_DEFAULT}).`
81
91
  ),
82
- cursor: z5.string().max(500).optional().describe(
92
+ cursor: z6.string().max(500).optional().describe(
83
93
  "Opaque \u2014 pass the previous response's `nextCursor` verbatim to fetch the next page. Never construct or parse this value yourself; its shape is not part of the public contract and may change."
84
94
  )
85
95
  });
86
96
  function paginatedSchema(itemSchema) {
87
- return z5.object({
88
- data: z5.array(itemSchema),
89
- nextCursor: z5.string().nullable().describe("Pass as `cursor` to fetch the next page. `null` when there are no more results."),
90
- hasMore: z5.boolean()
97
+ return z6.object({
98
+ data: z6.array(itemSchema),
99
+ nextCursor: z6.string().nullable().describe("Pass as `cursor` to fetch the next page. `null` when there are no more results."),
100
+ hasMore: z6.boolean()
91
101
  });
92
102
  }
93
103
 
94
104
  // src/tokens.ts
95
- import { z as z6 } from "zod";
96
- var TokenSchema = z6.enum(["USDC", "USDT"]).describe(
105
+ import { z as z7 } from "zod";
106
+ var TokenSchema = z7.enum(["USDC", "USDT"]).describe(
97
107
  "Which stablecoin the payer will send. Availability depends on `network` and `environment`; check `GET /v1/networks` before creating a charge. Unconfigured or disabled pairs are rejected with `422 token_not_supported`. Base, Optimism, and Ethereum have USDC test deployments; no test USDT is configured. The catalog includes both BNB Chain tokens for historical interpretation, but payments with either are currently disabled. Both configured BNB contracts are Binance-Peg tokens with 18 decimals; the other configured deployments use 6. Binance-Peg tokens carry Binance custody/backing risk and must not be represented as direct Circle/Tether issuance. Resolve address and decimals together with `getTokenDeployment`; a catalog entry alone does not imply payment availability."
98
108
  );
99
109
 
100
110
  // src/alt-tokens.ts
101
- import { z as z7 } from "zod";
102
- var AltTokenSchema = z7.enum(["ETH", "BNB", "POL", "AVAX", "BTC", "LINK", "ARB", "OP", "CBETH"]).describe(
111
+ import { z as z8 } from "zod";
112
+ var AltTokenSchema = z8.enum(["ETH", "BNB", "POL", "AVAX", "BTC", "LINK", "ARB", "OP", "CBETH"]).describe(
103
113
  "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. Trusted on a given network only when it has deep, reputably-issued/custodied liquidity there: each network's own native currency, `BTC` (wrapped) on the networks with a trusted deployment, `LINK` (Chainlink's own official per-chain deployment, except Avalanche's bridged `LINK.e`), and a small set of chain-specific blue chips (`ARB` on Arbitrum, `OP` on Optimism, `CBETH` on Base) \u2014 see `ALT_TOKEN_ADDRESSES` for the authoritative per-network list, never assume every value here is available on every network. `POL` replaced `MATIC` as Polygon's native currency name (Polygon's own token migration, 2024) \u2014 this schema tracks the network's current native asset, not the deprecated ticker."
104
114
  );
105
- var SwapAlternativeSchema = z7.object({
115
+ var SwapAlternativeSchema = z8.object({
106
116
  token: AltTokenSchema,
107
117
  network: NetworkSchema.describe(
108
118
  "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."
@@ -119,77 +129,77 @@ function listSwapAlternatives(networks) {
119
129
  }
120
130
 
121
131
  // src/charges.ts
122
- import { z as z11 } from "zod";
132
+ import { z as z12 } from "zod";
123
133
 
124
134
  // src/checkout-metadata.ts
125
- import { z as z8 } from "zod";
135
+ import { z as z9 } from "zod";
126
136
  var CHECKOUT_PRODUCTS_MAX = 20;
127
- var CheckoutProductSchema = z8.object({
128
- name: z8.string().min(1).max(200).describe("What the payer is buying, shown as-is on the hosted checkout page."),
129
- quantity: z8.number().int().positive().max(9999).optional().describe("How many of this item. Omit for a single, unquantified item."),
130
- imageUrl: z8.string().url().max(2048).refine((value) => /^https?:\/\//.test(value), "must use http or https").optional().describe(
137
+ var CheckoutProductSchema = z9.object({
138
+ name: z9.string().min(1).max(200).describe("What the payer is buying, shown as-is on the hosted checkout page."),
139
+ quantity: z9.number().int().positive().max(9999).optional().describe("How many of this item. Omit for a single, unquantified item."),
140
+ imageUrl: z9.string().url().max(2048).refine((value) => /^https?:\/\//.test(value), "must use http or https").optional().describe(
131
141
  "Product image, fetched only by the payer's own browser \u2014 Klappay never fetches it server-side. Must be `http(s)`."
132
142
  )
133
143
  });
134
- var KlappayCheckoutMetadataSchema = z8.object({
135
- products: z8.array(CheckoutProductSchema).max(CHECKOUT_PRODUCTS_MAX).optional().describe(
144
+ var KlappayCheckoutMetadataSchema = z9.object({
145
+ products: z9.array(CheckoutProductSchema).max(CHECKOUT_PRODUCTS_MAX).optional().describe(
136
146
  `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.`
137
147
  )
138
148
  }).describe(
139
149
  "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."
140
150
  );
141
- var MetadataWithKlappaySchema = z8.object({ klappay: KlappayCheckoutMetadataSchema.optional() }).catchall(z8.unknown()).describe(
151
+ var MetadataWithKlappaySchema = z9.object({ klappay: KlappayCheckoutMetadataSchema.optional() }).catchall(z9.unknown()).describe(
142
152
  "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`."
143
153
  );
144
154
 
145
155
  // src/escrow.ts
146
- import { z as z9 } from "zod";
147
- var EscrowConfigSchema = z9.object({
148
- releaserAddress: z9.string().regex(/^0x[0-9a-fA-F]{40}$/, "must be a 20-byte hex address").optional().describe(
156
+ import { z as z10 } from "zod";
157
+ var EscrowConfigSchema = z10.object({
158
+ releaserAddress: z10.string().regex(/^0x[0-9a-fA-F]{40}$/, "must be a 20-byte hex address").optional().describe(
149
159
  "The only address ever authorized to release this charge's escrowed funds \u2014 set once at creation, immutable after. Klappay never holds a key with any release authority of its own; every release requires a signature from this address, verified on-chain, never taken on faith. Omit to default to the API key's own `payoutAddress` \u2014 the common case where the merchant releasing their own charge is the same wallet they already get paid to. Pass an explicit address only when the releaser is a different party (e.g. an operational key distinct from the payout wallet). Not validated against anything else \u2014 any well-formed address is accepted, since Klappay never custodies these funds."
150
160
  )
151
161
  });
152
- var ReleaseEscrowRequestSchema = z9.object({
153
- signature: z9.string().regex(/^0x[0-9a-fA-F]+$/, "must be hex-encoded signature bytes").describe(
162
+ var ReleaseEscrowRequestSchema = z10.object({
163
+ signature: z10.string().regex(/^0x[0-9a-fA-F]+$/, "must be hex-encoded signature bytes").describe(
154
164
  "The Safe transaction signature authorizing this release, produced by signing a transfer of the escrow's entire current token balance to the charge's already-frozen split address (the same split that would have received the payment on a normal, non-escrow charge) with the private key behind this charge's `escrowReleaserAddress` \u2014 never anything Klappay can produce itself. The destination is fixed by the charge's `splitConfig` (frozen at creation); the amount is read live on-chain at release time, not fixed in advance, so it always matches whatever actually arrived \u2014 reconstruct the exact transaction server-side computes (ERC-20 `transfer(splitAddress, balance)` from the escrow Safe, nonce 0) before signing. Independently verified on-chain before anything moves \u2014 the Safe contract itself rejects a signature that isn't from `escrowReleaserAddress`, never trusted at face value by Klappay."
155
165
  )
156
166
  });
157
- var RefundEscrowRequestSchema = z9.object({
158
- signature: z9.string().regex(/^0x[0-9a-fA-F]+$/, "must be hex-encoded signature bytes").describe(
167
+ var RefundEscrowRequestSchema = z10.object({
168
+ signature: z10.string().regex(/^0x[0-9a-fA-F]+$/, "must be hex-encoded signature bytes").describe(
159
169
  "The Safe transaction signature authorizing this refund, produced by signing a transfer of the escrow's entire current token balance back to the address that funded this charge (`Charge.payerAddress`, captured from the credited transfer) with the private key behind this charge's `escrowReleaserAddress` \u2014 never anything Klappay can produce itself. The amount is read live on-chain at refund time, not fixed in advance, so it always matches whatever actually arrived \u2014 reconstruct the exact transaction Klappay computes server-side (ERC-20 `transfer(payerAddress, balance)` from the escrow Safe, nonce 0) before signing. Independently verified on-chain before anything moves \u2014 the Safe contract itself rejects a signature that isn't from `escrowReleaserAddress`, never trusted at face value by Klappay."
160
170
  )
161
171
  });
162
172
 
163
173
  // src/exact-amount.ts
164
- import { z as z10 } from "zod";
165
- var ExactAmountSchema = z10.string().regex(/^(0|[1-9]\d*)(?:\.\d{1,18})?$(?!\s)/).describe(
174
+ import { z as z11 } from "zod";
175
+ var ExactAmountSchema = z11.string().regex(/^(0|[1-9]\d*)(?:\.\d{1,18})?$(?!\s)/).describe(
166
176
  "Nonnegative amount in whole currency/token units, as a decimal string with at most 18 fractional digits and no scientific notation."
167
177
  );
168
178
 
169
179
  // src/charges.ts
170
- var ChargeStatusSchema = z11.enum(["pending", "partially_paid", "confirmed", "expired", "underpaid"]).describe(
180
+ var ChargeStatusSchema = z12.enum(["pending", "partially_paid", "confirmed", "expired", "underpaid"]).describe(
171
181
  "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."
172
182
  );
173
- var SettlementStatusSchema = z11.enum(["pending", "completed", "failed"]).describe(
183
+ var SettlementStatusSchema = z12.enum(["pending", "completed", "failed"]).describe(
174
184
  "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."
175
185
  );
176
- var ChargeFeePayerSchema = z11.enum(["merchant", "payer"]).describe(
186
+ var ChargeFeePayerSchema = z12.enum(["merchant", "payer"]).describe(
177
187
  "Who ends up covering Klappay's `feePercent`. `merchant` (default): `amount` is exactly what you asked for, and Klappay's fee is deducted from your own payout \u2014 you net `amount * (1 - feePercent / 100)`. `payer` : `amount` is grossed up at creation time so that, after the same fee deduction, you still net the amount you originally requested \u2014 the payer sees and sends the larger, fee-inclusive total. Frozen at creation like every other fee input; does not change how `feeAmount`/`merchantAmount` are computed on read, only what `amount` was set to in the first place."
178
188
  );
179
189
  var CHARGE_EXPIRES_IN_MIN_SECONDS = 60;
180
190
  var CHARGE_EXPIRES_IN_MAX_SECONDS = 3600;
181
- var CHARGE_ACCEPTED_PAYMENTS_MAX = 14;
182
- var AcceptedPaymentSchema = z11.object({
191
+ var CHARGE_ACCEPTED_PAYMENTS_MAX = 18;
192
+ var AcceptedPaymentSchema = z12.object({
183
193
  token: TokenSchema,
184
194
  network: NetworkSchema
185
195
  });
186
- var AcceptedPaymentsSchema = z11.array(AcceptedPaymentSchema).min(1, "At least one accepted payment is required.").max(CHARGE_ACCEPTED_PAYMENTS_MAX).superRefine((pairs, ctx) => {
196
+ var AcceptedPaymentsSchema = z12.array(AcceptedPaymentSchema).min(1, "At least one accepted payment is required.").max(CHARGE_ACCEPTED_PAYMENTS_MAX).superRefine((pairs, ctx) => {
187
197
  const seen = /* @__PURE__ */ new Set();
188
198
  pairs.forEach((pair, index) => {
189
199
  const key = `${pair.token}:${pair.network}`;
190
200
  if (seen.has(key)) {
191
201
  ctx.addIssue({
192
- code: z11.ZodIssueCode.custom,
202
+ code: z12.ZodIssueCode.custom,
193
203
  message: `Duplicate accepted payment: ${pair.token} on ${pair.network}.`,
194
204
  path: [index]
195
205
  });
@@ -197,42 +207,51 @@ var AcceptedPaymentsSchema = z11.array(AcceptedPaymentSchema).min(1, "At least o
197
207
  seen.add(key);
198
208
  if (!OPERATIONAL_NETWORKS.some((network) => network === pair.network)) {
199
209
  ctx.addIssue({
200
- code: z11.ZodIssueCode.custom,
210
+ code: z12.ZodIssueCode.custom,
201
211
  message: `Network "${pair.network}" isn't live yet \u2014 only ${OPERATIONAL_NETWORKS.join(", ")} today.`,
202
212
  path: [index, "network"]
203
213
  });
204
214
  }
205
215
  });
216
+ const families = new Set(pairs.map((pair) => NETWORK_FAMILIES[pair.network]));
217
+ if (families.size > 1) {
218
+ ctx.addIssue({
219
+ code: z12.ZodIssueCode.custom,
220
+ message: `acceptedPayments mixes networks from different split families (${[...families].sort().join(", ")}) \u2014 every network in this list must share the same underlying split factory, so a charge can only ever accept networks from one family at a time.`
221
+ });
222
+ }
206
223
  }).describe(
207
- `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\`.`
224
+ `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\`. Every network listed must also share the same split family (which networks are grouped together is an implementation detail, not part of this API's contract) \u2014 a charge predicts one split address up front and reuses it across every accepted network, which is only safe within one family; mixing families is rejected with \`400 validation_error\`.`
208
225
  );
209
226
  var CHARGE_SPLIT_RECIPIENTS_MAX = 5;
210
- var SplitRecipientSchema = z11.object({
211
- address: z11.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."),
212
- percent: z11.number().positive().max(100).describe(
227
+ var SplitRecipientSchema = z12.object({
228
+ address: SplitAddressSchema.describe(
229
+ "Address to send a slice of this charge to \u2014 an EVM 0x... address or a TRON T... address, matching whichever network family the charge accepts (acceptedPayments can only ever list networks from one split family at a time, so this always matches that same family)."
230
+ ),
231
+ percent: z12.number().positive().max(100).describe(
213
232
  "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."
214
233
  ),
215
- label: z11.string().min(1).max(64).optional().describe(
234
+ label: z12.string().min(1).max(64).optional().describe(
216
235
  'Free-form label for your own bookkeeping (e.g. `"supplier"`, `"sales rep"`) \u2014 echoed back unchanged, never interpreted by Klappay.'
217
236
  )
218
237
  });
219
- var SplitRecipientInputSchema = z11.object({
220
- recipientId: z11.string().describe(
238
+ var SplitRecipientInputSchema = z12.object({
239
+ recipientId: z12.string().describe(
221
240
  "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."
222
241
  ),
223
- percent: z11.number().positive().max(100).describe(
242
+ percent: z12.number().positive().max(100).describe(
224
243
  "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."
225
244
  ),
226
- label: z11.string().min(1).max(64).optional().describe(
245
+ label: z12.string().min(1).max(64).optional().describe(
227
246
  '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.'
228
247
  )
229
248
  });
230
- var SplitRecipientsInputSchema = z11.array(SplitRecipientInputSchema).max(CHARGE_SPLIT_RECIPIENTS_MAX).superRefine((recipients, ctx) => {
249
+ var SplitRecipientsInputSchema = z12.array(SplitRecipientInputSchema).max(CHARGE_SPLIT_RECIPIENTS_MAX).superRefine((recipients, ctx) => {
231
250
  const seen = /* @__PURE__ */ new Set();
232
251
  recipients.forEach((recipient, index) => {
233
252
  if (seen.has(recipient.recipientId)) {
234
253
  ctx.addIssue({
235
- code: z11.ZodIssueCode.custom,
254
+ code: z12.ZodIssueCode.custom,
236
255
  message: `Duplicate split recipientId: ${recipient.recipientId}.`,
237
256
  path: [index, "recipientId"]
238
257
  });
@@ -243,114 +262,127 @@ var SplitRecipientsInputSchema = z11.array(SplitRecipientInputSchema).max(CHARGE
243
262
  `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\`.`
244
263
  );
245
264
  var CHARGE_AMOUNT_MAX = 999999999999;
246
- var CreateChargeSchema = z11.object({
247
- amount: z11.number().positive().max(CHARGE_AMOUNT_MAX).describe(
265
+ var CreateChargeSchema = z12.object({
266
+ amount: z12.number().positive().max(CHARGE_AMOUNT_MAX).describe(
248
267
  "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. With `feePayer: 'payer'` (see below), this is your own desired net amount, not the total the payer ends up sending \u2014 the response's `amount` is grossed up to cover `feePercent`, while `merchantAmount` on the response echoes back this exact value."
249
268
  ),
250
269
  feePayer: ChargeFeePayerSchema.optional().default("merchant"),
251
- currency: z11.literal("USD").default("USD").describe("Always `USD` today \u2014 the only supported currency."),
270
+ currency: z12.literal("USD").default("USD").describe("Always `USD` today \u2014 the only supported currency."),
252
271
  acceptedPayments: AcceptedPaymentsSchema,
253
- expiresIn: z11.number().int().min(CHARGE_EXPIRES_IN_MIN_SECONDS).max(CHARGE_EXPIRES_IN_MAX_SECONDS).describe(
272
+ expiresIn: z12.number().int().min(CHARGE_EXPIRES_IN_MIN_SECONDS).max(CHARGE_EXPIRES_IN_MAX_SECONDS).describe(
254
273
  "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."
255
274
  ),
256
- idempotencyKey: z11.string().min(1).max(255).optional().describe(
275
+ idempotencyKey: z12.string().min(1).max(255).optional().describe(
257
276
  "Scoped to your tenant. Replaying the same key with the exact same request body returns the original charge unchanged instead of creating a duplicate \u2014 safe to retry a request after a timeout without double-charging. Reusing the same key with a different body (including a different `escrow` config) is rejected with `409 idempotency_key_reused`, never silently returned as the original charge."
258
277
  ),
259
- externalRef: z11.string().min(1).max(255).optional().describe(
278
+ externalRef: z12.string().min(1).max(255).optional().describe(
260
279
  "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."
261
280
  ),
262
- source: z11.string().min(1).max(64).optional().describe(
281
+ source: z12.string().min(1).max(64).optional().describe(
263
282
  '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.'
264
283
  ),
265
284
  metadata: MetadataWithKlappaySchema.optional(),
266
- redirectUrl: z11.string().url().refine((value) => /^https?:\/\//.test(value), "must use http or https").optional().describe(
285
+ redirectUrl: z12.string().url().refine((value) => /^https?:\/\//.test(value), "must use http or https").optional().describe(
267
286
  "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."
268
287
  ),
269
288
  splitRecipients: SplitRecipientsInputSchema.optional(),
270
289
  escrow: EscrowConfigSchema.optional().describe(
271
- "Configure this charge as an escrow instead of a normal payment. Funds land in a dedicated, non-custodial Safe (not the usual split address) and only `releaserAddress` (or, if omitted, your API key's own `payoutAddress`) can ever release them \u2014 via `POST /v1/charges/{id}/release`, signed on their end, never something Klappay can trigger or redirect. Omit this field entirely for a normal charge."
290
+ "Configure this charge as an escrow instead of a normal payment. Funds land in a dedicated, non-custodial Safe (not the usual split address) and only `releaserAddress` (or, if omitted, your API key's own `payoutAddress`) can ever release them \u2014 via `POST /v1/charges/{id}/release`, signed on their end, never something Klappay can trigger or redirect. Omit this field entirely for a normal charge. **Requires every accepted network to be EVM** (Safe \u2014 the underlying custody contract \u2014 isn't deployed on Tron, and can never be; it's not an EVM chain) \u2014 rejected with `400 validation_error` otherwise."
272
291
  )
292
+ }).superRefine((data, ctx) => {
293
+ if (!data.escrow) return;
294
+ const evmNetworks = EVM_NETWORKS;
295
+ const hasUnsupportedNetwork = data.acceptedPayments.some(
296
+ (pair) => !evmNetworks.includes(pair.network)
297
+ );
298
+ if (hasUnsupportedNetwork) {
299
+ ctx.addIssue({
300
+ code: z12.ZodIssueCode.custom,
301
+ message: "Escrow is not supported for this charge's network \u2014 Safe (the underlying custody contract) isn't an EVM chain there. Remove `escrow`, or accept payment on an EVM network instead.",
302
+ path: ["escrow"]
303
+ });
304
+ }
273
305
  });
274
- var ChargeSchema = z11.object({
275
- id: z11.string().describe("Klappay-generated id, e.g. `ch_...`. Use this to look up the charge later."),
276
- amount: z11.number().describe(
306
+ var ChargeSchema = z12.object({
307
+ id: z12.string().describe("Klappay-generated id, e.g. `ch_...`. Use this to look up the charge later."),
308
+ amount: z12.number().describe(
277
309
  "The total the payer must send, in `currency` units (up to 6 decimal places). This legacy JSON number can lose precision; use `amountExact` for calculations and payment preparation. With `feePayer: 'merchant'` (the default) this is what you requested at creation. With `feePayer: 'payer'` this is grossed up to cover `feePercent` \u2014 see `merchantAmount` for what you requested/will actually net."
278
310
  ),
279
311
  amountExact: ExactAmountSchema.regex(/^(0|[1-9]\d*)(?:\.\d{1,6})?$/).optional().describe(
280
312
  'Exact total the payer must send, in `currency` units, as a nonnegative decimal string with at most 6 fractional digits and no scientific notation (e.g. `"100.000001"`). Use this instead of `amount` for arithmetic. Optional for compatibility with older API responses.'
281
313
  ),
282
314
  feePayer: ChargeFeePayerSchema,
283
- feePercent: z11.number().describe(
315
+ feePercent: z12.number().describe(
284
316
  "Klappay's fee for this charge, as a percent of `amount` (e.g. `2` = 2%) \u2014 includes any escrow surcharge if this charge is an escrow. Frozen at creation; see `feeAmount`/`merchantAmount` for the actual amounts this works out to."
285
317
  ),
286
- feeAmount: z11.number().describe("`amount * feePercent / 100`, in `currency` units \u2014 Klappay's cut of this charge."),
287
- merchantAmount: z11.number().describe(
318
+ feeAmount: z12.number().describe("`amount * feePercent / 100`, in `currency` units \u2014 Klappay's cut of this charge."),
319
+ merchantAmount: z12.number().describe(
288
320
  "`amount - feeAmount`, in `currency` units \u2014 what you actually net once the payout settles, regardless of `feePayer` (this is always what the split delivers to you; `feePayer` only affects what `amount` was set to at creation)."
289
321
  ),
290
- amountReceived: z11.number().nullable().describe(
322
+ amountReceived: z12.number().nullable().describe(
291
323
  "Cumulative amount received on-chain so far, in `currency` units. This legacy JSON number can lose precision; use `amountReceivedExact` for arithmetic with up to 18 fractional digits. `null` until the first transfer arrives. Can exceed `amount` \u2014 see `isOverpaid`."
292
324
  ),
293
325
  amountReceivedExact: ExactAmountSchema.nullable().optional().describe(
294
326
  'Exact cumulative amount received on-chain, in `currency` units, as a nonnegative decimal string with at most 18 fractional digits and no scientific notation (e.g. `"0.0000000001"`). `null` until the first transfer arrives. Can exceed `amountExact`. Optional for compatibility with older API responses.'
295
327
  ),
296
- paymentUnavailable: z11.boolean().optional().describe(
328
+ paymentUnavailable: z12.boolean().optional().describe(
297
329
  "When `true`, payment processing for this charge is temporarily unavailable. Do not offer payment instructions, request another transfer, or fulfill from its monetary/status fields until availability is restored. The charge retains its existing business status. Optional for compatibility with older API responses."
298
330
  ),
299
- isOverpaid: z11.boolean().describe(
331
+ isOverpaid: z12.boolean().describe(
300
332
  "`true` if `amountReceived` ended up greater than `amount`. Klappay never refunds the difference automatically \u2014 see the docs for why."
301
333
  ),
302
- currency: z11.string().describe("Always `USD` today \u2014 the only supported currency."),
303
- acceptedPayments: z11.array(AcceptedPaymentSchema).describe(
334
+ currency: z12.string().describe("Always `USD` today \u2014 the only supported currency."),
335
+ acceptedPayments: z12.array(AcceptedPaymentSchema).describe(
304
336
  "Every `(token, network)` pair this charge was configured to accept, unchanged after creation."
305
337
  ),
306
- paidWith: z11.array(AcceptedPaymentSchema).describe(
338
+ paidWith: z12.array(AcceptedPaymentSchema).describe(
307
339
  "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`."
308
340
  ),
309
- swapAlternatives: z11.array(SwapAlternativeSchema).describe(
341
+ swapAlternatives: z12.array(SwapAlternativeSchema).describe(
310
342
  "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`)."
311
343
  ),
312
- address: z11.string().describe(
344
+ address: z12.string().describe(
313
345
  "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."
314
346
  ),
315
347
  status: ChargeStatusSchema,
316
348
  settlementStatus: SettlementStatusSchema.nullable(),
317
349
  environment: EnvironmentSchema,
318
- apiKeyId: z11.string().nullable().describe(
350
+ apiKeyId: z12.string().nullable().describe(
319
351
  "Which of your API keys created this charge. `null` for a charge created before this field existed."
320
352
  ),
321
- txHash: z11.string().nullable().describe(
353
+ txHash: z12.string().nullable().describe(
322
354
  "Transaction hash of the most recent transfer detected for this charge. `null` until a payment is detected."
323
355
  ),
324
- externalRef: z11.string().nullable(),
325
- source: z11.string().nullable(),
356
+ externalRef: z12.string().nullable(),
357
+ source: z12.string().nullable(),
326
358
  metadata: MetadataWithKlappaySchema.nullable(),
327
- redirectUrl: z11.string().nullable().describe("Echoes the `redirectUrl` set at creation, if any. `null` if none was set."),
328
- checkoutUrl: z11.string().nullable().describe(
359
+ redirectUrl: z12.string().nullable().describe("Echoes the `redirectUrl` set at creation, if any. `null` if none was set."),
360
+ checkoutUrl: z12.string().nullable().describe(
329
361
  "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."
330
362
  ),
331
- splitRecipients: z11.array(SplitRecipientSchema).describe("Echoes whatever extra split recipients were set at creation \u2014 empty array if none."),
332
- createdAt: z11.string().datetime(),
333
- expiresAt: z11.string().datetime().describe(
363
+ splitRecipients: z12.array(SplitRecipientSchema).describe("Echoes whatever extra split recipients were set at creation \u2014 empty array if none."),
364
+ createdAt: z12.string().datetime(),
365
+ expiresAt: z12.string().datetime().describe(
334
366
  "When this charge stops accepting payment, if still `pending`/`partially_paid` by then."
335
367
  ),
336
- confirmedAt: z11.string().datetime().nullable().describe("When `status` first reached `confirmed`. `null` until then."),
337
- settledAt: z11.string().datetime().nullable().describe(
368
+ confirmedAt: z12.string().datetime().nullable().describe("When `status` first reached `confirmed`. `null` until then."),
369
+ settledAt: z12.string().datetime().nullable().describe(
338
370
  "When `settlementStatus` first reached `completed` \u2014 the merchant's wallet actually has the funds. `null` until then, including while `settlementStatus` is `pending`/`failed`."
339
371
  ),
340
- lastActivityAt: z11.string().datetime().describe(
372
+ lastActivityAt: z12.string().datetime().describe(
341
373
  "When a transfer was last credited toward this charge, or `createdAt` if none has arrived yet."
342
374
  ),
343
- escrow: z11.object({
344
- releaserAddress: z11.string().describe("The only address that can ever release this escrow \u2014 never Klappay."),
345
- releasedAt: z11.string().datetime().nullable().describe("When the release actually executed on-chain. `null` until then."),
346
- refundedAt: z11.string().datetime().nullable().describe(
375
+ escrow: z12.object({
376
+ releaserAddress: z12.string().describe("The only address that can ever release this escrow \u2014 never Klappay."),
377
+ releasedAt: z12.string().datetime().nullable().describe("When the release actually executed on-chain. `null` until then."),
378
+ refundedAt: z12.string().datetime().nullable().describe(
347
379
  "When the refund actually executed on-chain. `null` until then. Mutually exclusive with `releasedAt` \u2014 an escrow can only ever be released or refunded once, never both."
348
380
  )
349
381
  }).nullable().describe(
350
382
  "Present only when this charge was created as an escrow (see `escrow` on the create request) \u2014 `null` for a normal charge."
351
383
  )
352
384
  });
353
- var ListChargesSchema = z11.object({
385
+ var ListChargesSchema = z12.object({
354
386
  status: ChargeStatusSchema.optional(),
355
387
  token: TokenSchema.optional().describe(
356
388
  "Filters on `paidWith.token` \u2014 the pair actually paid, not accepted."
@@ -359,13 +391,13 @@ var ListChargesSchema = z11.object({
359
391
  "Filters on `paidWith.network` \u2014 the pair actually paid, not accepted."
360
392
  ),
361
393
  environment: EnvironmentSchema.optional(),
362
- since: z11.string().datetime().optional().describe(
394
+ since: z12.string().datetime().optional().describe(
363
395
  "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."
364
396
  ),
365
- isOverpaid: z11.enum(["true", "false"]).transform((v) => v === "true").optional()
397
+ isOverpaid: z12.enum(["true", "false"]).transform((v) => v === "true").optional()
366
398
  }).extend(PaginationQuerySchema.shape);
367
399
  var PaginatedChargesSchema = paginatedSchema(ChargeSchema);
368
- var GetChargeQrCodeQuerySchema = z11.object({
400
+ var GetChargeQrCodeQuerySchema = z12.object({
369
401
  token: TokenSchema.optional().describe(
370
402
  "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."
371
403
  ),
@@ -373,19 +405,19 @@ var GetChargeQrCodeQuerySchema = z11.object({
373
405
  });
374
406
 
375
407
  // src/charge-check.ts
376
- import { z as z13 } from "zod";
408
+ import { z as z14 } from "zod";
377
409
 
378
410
  // src/confirmation-progress.ts
379
- import { z as z12 } from "zod";
380
- var ConfirmationProgressSchema = z12.object({
411
+ import { z as z13 } from "zod";
412
+ var ConfirmationProgressSchema = z13.object({
381
413
  network: NetworkSchema.describe("Which network the transfer was seen on."),
382
- blocksSeen: z12.number().int().min(0).describe(
414
+ blocksSeen: z13.number().int().min(0).describe(
383
415
  "How many blocks have passed since the transfer's own block, as of this update \u2014 a raw block count, not seconds. Grows toward `blocksRequired` as the network's blocks keep arriving."
384
416
  ),
385
- blocksRequired: z12.number().int().min(1).describe(
417
+ blocksRequired: z13.number().int().min(1).describe(
386
418
  "This network's minimum confirmation depth (a fixed, per-network constant) \u2014 the transfer is only credited once `blocksSeen` reaches this value."
387
419
  ),
388
- percent: z12.number().int().min(0).max(99).describe(
420
+ percent: z13.number().int().min(0).max(99).describe(
389
421
  '`blocksSeen`/`blocksRequired` as a rounded-down 0-99 percentage, for a progress bar. Never reaches 100 by construction \u2014 once a transfer is deep enough it is credited immediately and this stops being reported at all (the charge event itself is the "done" signal).'
390
422
  )
391
423
  }).describe(
@@ -393,8 +425,8 @@ var ConfirmationProgressSchema = z12.object({
393
425
  );
394
426
 
395
427
  // src/charge-check.ts
396
- var CheckChargeRequestSchema = z13.object({
397
- txHash: z13.string().regex(/^0x[0-9a-fA-F]{64}$/, "must be a 32-byte transaction hash").optional().describe(
428
+ var CheckChargeRequestSchema = z14.object({
429
+ txHash: z14.string().regex(/^0x[0-9a-fA-F]{64}$/, "must be a 32-byte transaction hash").optional().describe(
398
430
  "The on-chain transaction hash to verify directly, if you already have it \u2014 e.g. right after a swap-to-pay or wallet-connect transaction is sent. Costs a single RPC call instead of scanning a block range, so the check resolves faster and cheaper. Omit to fall back to scanning recent transfers to this charge's address, the same lookup the background reconciliation pass runs. Never trusted at face value \u2014 whatever this transaction actually contains on-chain is what gets credited, regardless of any amount/token implied elsewhere."
399
431
  ),
400
432
  network: NetworkSchema.optional().describe(
@@ -404,7 +436,7 @@ var CheckChargeRequestSchema = z13.object({
404
436
  message: "`txHash` and `network` must be provided together, or both omitted"
405
437
  });
406
438
  var CheckChargeResponseSchema = ChargeSchema.extend({
407
- transactionSender: z13.string().nullable().describe(
439
+ transactionSender: z14.string().nullable().describe(
408
440
  "The `txHash` transaction's own sender (`from`) \u2014 who actually signed and submitted it on-chain, which stays the payer's own wallet even when the transaction swaps through a router/aggregator on the way to paying, unlike the credited transfer's `from` (which can be the router/pool contract, not the payer). `null` unless `txHash`/`network` was passed in the request and a successful receipt was found for it \u2014 a hint-less background scan, an unaccepted network, or a not-found/reverted transaction all leave this `null`."
409
441
  ),
410
442
  confirmationProgress: ConfirmationProgressSchema.nullable().describe(
@@ -413,61 +445,61 @@ var CheckChargeResponseSchema = ChargeSchema.extend({
413
445
  });
414
446
 
415
447
  // src/distributions.ts
416
- import { z as z14 } from "zod";
417
- var SplitDistributionStatusSchema = z14.enum(["pending", "processing", "completed", "failed"]).describe(
448
+ import { z as z15 } from "zod";
449
+ var SplitDistributionStatusSchema = z15.enum(["pending", "processing", "completed", "failed"]).describe(
418
450
  "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."
419
451
  );
420
- var PendingDistributionRecipientSchema = z14.object({
421
- address: z14.string().describe("On-chain recipient address."),
422
- percentAllocation: z14.number().describe("This recipient's share of the split, as a percentage (e.g. `99.0991` = 99.0991%).")
452
+ var PendingDistributionRecipientSchema = z15.object({
453
+ address: z15.string().describe("On-chain recipient address."),
454
+ percentAllocation: z15.number().describe("This recipient's share of the split, as a percentage (e.g. `99.0991` = 99.0991%).")
423
455
  });
424
- var PendingDistributionSchema = z14.object({
425
- splitAddress: z14.string().describe("The on-chain 0xSplits address to call `distribute()` on."),
456
+ var PendingDistributionSchema = z15.object({
457
+ splitAddress: z15.string().describe("The on-chain 0xSplits address to call `distribute()` on."),
426
458
  network: NetworkSchema,
427
459
  token: TokenSchema,
428
- recipients: z14.array(PendingDistributionRecipientSchema).describe(
460
+ recipients: z15.array(PendingDistributionRecipientSchema).describe(
429
461
  "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."
430
462
  ),
431
- distributorFeePercent: z14.number().describe(
463
+ distributorFeePercent: z15.number().describe(
432
464
  "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."
433
465
  ),
434
- estimatedRewardAmount: z14.number().describe(
466
+ estimatedRewardAmount: z15.number().describe(
435
467
  "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."
436
468
  ),
437
- availableSince: z14.string().datetime().describe("When this distribution entered its grace period."),
438
- graceEndsAt: z14.string().datetime().describe(
469
+ availableSince: z15.string().datetime().describe("When this distribution entered its grace period."),
470
+ graceEndsAt: z15.string().datetime().describe(
439
471
  "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."
440
472
  )
441
473
  });
442
474
  var PaginatedPendingDistributionsSchema = paginatedSchema(PendingDistributionSchema);
443
- var ListenPendingDistributionsQuerySchema = z14.object({
444
- limit: z14.coerce.number().int().min(0).max(PAGINATION_LIMIT_MAX).default(0).describe(
475
+ var ListenPendingDistributionsQuerySchema = z15.object({
476
+ limit: z15.coerce.number().int().min(0).max(PAGINATION_LIMIT_MAX).default(0).describe(
445
477
  "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."
446
478
  )
447
479
  });
448
- var PendingDistributionEventSchema = z14.discriminatedUnion("type", [
449
- z14.object({
450
- type: z14.literal("distribution.available"),
480
+ var PendingDistributionEventSchema = z15.discriminatedUnion("type", [
481
+ z15.object({
482
+ type: z15.literal("distribution.available"),
451
483
  distribution: PendingDistributionSchema
452
484
  }),
453
- z14.object({
454
- type: z14.literal("distribution.claimed"),
455
- splitAddress: z14.string().describe("No longer claimable \u2014 either settled by someone, or picked up by the worker.")
485
+ z15.object({
486
+ type: z15.literal("distribution.claimed"),
487
+ splitAddress: z15.string().describe("No longer claimable \u2014 either settled by someone, or picked up by the worker.")
456
488
  })
457
489
  ]);
458
490
 
459
491
  // src/metrics.ts
460
- import { z as z15 } from "zod";
461
- var MetricsResourceSchema = z15.enum(["charges", "transactions", "distributions"]).describe(
492
+ import { z as z16 } from "zod";
493
+ var MetricsResourceSchema = z16.enum(["charges", "transactions", "distributions"]).describe(
462
494
  "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."
463
495
  );
464
- var MetricsAggregationSchema = z15.enum(["count", "sum", "avg", "min", "max"]).describe(
496
+ var MetricsAggregationSchema = z16.enum(["count", "sum", "avg", "min", "max"]).describe(
465
497
  "`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."
466
498
  );
467
- var MetricsFilterOperatorSchema = z15.enum(["eq", "neq", "in", "gt", "gte", "lt", "lte"]).describe(
499
+ var MetricsFilterOperatorSchema = z16.enum(["eq", "neq", "in", "gt", "gte", "lt", "lte"]).describe(
468
500
  "`in` expects an array value (max 50 entries); every other operator expects a single scalar."
469
501
  );
470
- var MetricsDateGranularitySchema = z15.enum(["day", "week", "month", "year"]).describe(
502
+ var MetricsDateGranularitySchema = z16.enum(["day", "week", "month", "year"]).describe(
471
503
  "Bucket width for a `date_bucket` `groupBy` entry \u2014 Postgres `date_trunc` semantics (UTC)."
472
504
  );
473
505
  var metricsQueryEnvironmentSchema = EnvironmentSchema.describe(
@@ -480,31 +512,32 @@ var METRICS_QUERY_MAX_GROUP_BY = 3;
480
512
  var METRICS_QUERY_MAX_FILTERS = 20;
481
513
  var METRICS_QUERY_MAX_METRICS = 10;
482
514
  var METRIC_ALIAS_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
483
- var metricAliasSchema = z15.string().min(1).max(64).regex(
515
+ var metricAliasSchema = z16.string().min(1).max(64).regex(
484
516
  METRIC_ALIAS_PATTERN,
485
517
  "Must start with a letter or underscore, and contain only letters, digits, and underscores \u2014 this becomes a SQL column alias."
486
518
  ).optional();
487
- var MetricsFilterValueSchema = z15.union([
488
- z15.string().max(255),
489
- z15.number(),
490
- z15.boolean(),
491
- z15.array(z15.union([z15.string().max(255), z15.number()])).min(1).max(50)
519
+ var MetricsFilterValueSchema = z16.union([
520
+ z16.string().max(255),
521
+ z16.number(),
522
+ z16.boolean(),
523
+ z16.null(),
524
+ z16.array(z16.union([z16.string().max(255), z16.number()])).min(1).max(50)
492
525
  ]);
493
- var orderBySchema = z15.object({
494
- key: z15.string().min(1).max(64).regex(
526
+ var orderBySchema = z16.object({
527
+ key: z16.string().min(1).max(64).regex(
495
528
  METRIC_ALIAS_PATTERN,
496
529
  "Must start with a letter or underscore, and contain only letters, digits, and underscores \u2014 every valid output column name already looks like this."
497
530
  ).describe(
498
531
  "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."
499
532
  ),
500
- direction: z15.enum(["asc", "desc"])
533
+ direction: z16.enum(["asc", "desc"])
501
534
  }).describe(
502
535
  "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."
503
536
  );
504
- var limitSchema = z15.number().int().min(1).max(METRICS_QUERY_MAX_ROW_LIMIT).default(METRICS_QUERY_DEFAULT_ROW_LIMIT).describe(
537
+ var limitSchema = z16.number().int().min(1).max(METRICS_QUERY_MAX_ROW_LIMIT).default(METRICS_QUERY_DEFAULT_ROW_LIMIT).describe(
505
538
  `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.`
506
539
  );
507
- var ChargesQueryFieldSchema = z15.enum([
540
+ var ChargesQueryFieldSchema = z16.enum([
508
541
  "status",
509
542
  "source",
510
543
  "apiKeyId",
@@ -515,124 +548,124 @@ var ChargesQueryFieldSchema = z15.enum([
515
548
  ]).describe(
516
549
  "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. `escrowReleaserAddress` is `null` for a normal charge \u2014 filter `escrowReleaserAddress` with operator `neq`/value `null` to isolate escrow-configured charges (see `escrow` in charges.md)."
517
550
  );
518
- var ChargesMetricFieldSchema = z15.enum(["amount", "amountReceived", "feePercent", "escrowFeePercent"]).describe(
551
+ var ChargesMetricFieldSchema = z16.enum(["amount", "amountReceived", "feePercent", "escrowFeePercent"]).describe(
519
552
  "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%. `escrowFeePercent` is the additional escrow-specific fee component, only present on escrow-configured charges \u2014 see `docs/payments.md`."
520
553
  );
521
- var ChargesDateFieldSchema = z15.enum(["createdAt", "confirmedAt", "lastActivityAt", "expiresAt", "escrowReleasedAt"]).describe(
554
+ var ChargesDateFieldSchema = z16.enum(["createdAt", "confirmedAt", "lastActivityAt", "expiresAt", "escrowReleasedAt"]).describe(
522
555
  "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. `escrowReleasedAt` is `null` until an escrow-configured charge is actually released \u2014 same implicit-exclusion behavior as `confirmedAt`, scoped to escrow charges only."
523
556
  );
524
- var ChargesFilterSchema = z15.object({
557
+ var ChargesFilterSchema = z16.object({
525
558
  field: ChargesQueryFieldSchema,
526
559
  operator: MetricsFilterOperatorSchema,
527
560
  value: MetricsFilterValueSchema
528
561
  });
529
- var ChargesGroupBySchema = z15.union([
530
- z15.object({ type: z15.literal("field"), field: ChargesQueryFieldSchema }),
531
- z15.object({
532
- type: z15.literal("date_bucket"),
562
+ var ChargesGroupBySchema = z16.union([
563
+ z16.object({ type: z16.literal("field"), field: ChargesQueryFieldSchema }),
564
+ z16.object({
565
+ type: z16.literal("date_bucket"),
533
566
  field: ChargesDateFieldSchema,
534
567
  granularity: MetricsDateGranularitySchema
535
568
  })
536
569
  ]);
537
- var ChargesMetricSchema = z15.object({
570
+ var ChargesMetricSchema = z16.object({
538
571
  aggregation: MetricsAggregationSchema,
539
572
  field: ChargesMetricFieldSchema.optional(),
540
573
  alias: metricAliasSchema
541
574
  });
542
- var ChargesMetricsQuerySchema = z15.object({
543
- resource: z15.literal("charges"),
575
+ var ChargesMetricsQuerySchema = z16.object({
576
+ resource: z16.literal("charges"),
544
577
  environment: metricsQueryEnvironmentSchema,
545
- dateRange: z15.object({
578
+ dateRange: z16.object({
546
579
  field: ChargesDateFieldSchema,
547
- from: z15.string().max(64).datetime(),
548
- to: z15.string().max(64).datetime()
580
+ from: z16.string().max(64).datetime(),
581
+ to: z16.string().max(64).datetime()
549
582
  }),
550
- groupBy: z15.array(ChargesGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
551
- metrics: z15.array(ChargesMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
552
- filters: z15.array(ChargesFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
583
+ groupBy: z16.array(ChargesGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
584
+ metrics: z16.array(ChargesMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
585
+ filters: z16.array(ChargesFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
553
586
  orderBy: orderBySchema.optional(),
554
587
  limit: limitSchema
555
588
  });
556
- var TransactionsQueryFieldSchema = z15.enum(["network", "token", "source", "causedTransition"]).describe(
589
+ var TransactionsQueryFieldSchema = z16.enum(["network", "token", "source", "causedTransition"]).describe(
557
590
  "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)."
558
591
  );
559
- var TransactionsMetricFieldSchema = z15.enum(["amount"]).describe("The transfer amount, in the charge's `currency` units.");
560
- var TransactionsDateFieldSchema = z15.enum(["detectedAt"]).describe("When Klappay detected this transfer on-chain (not when it was mined).");
561
- var TransactionsFilterSchema = z15.object({
592
+ var TransactionsMetricFieldSchema = z16.enum(["amount"]).describe("The transfer amount, in the charge's `currency` units.");
593
+ var TransactionsDateFieldSchema = z16.enum(["detectedAt"]).describe("When Klappay detected this transfer on-chain (not when it was mined).");
594
+ var TransactionsFilterSchema = z16.object({
562
595
  field: TransactionsQueryFieldSchema,
563
596
  operator: MetricsFilterOperatorSchema,
564
597
  value: MetricsFilterValueSchema
565
598
  });
566
- var TransactionsGroupBySchema = z15.union([
567
- z15.object({ type: z15.literal("field"), field: TransactionsQueryFieldSchema }),
568
- z15.object({
569
- type: z15.literal("date_bucket"),
599
+ var TransactionsGroupBySchema = z16.union([
600
+ z16.object({ type: z16.literal("field"), field: TransactionsQueryFieldSchema }),
601
+ z16.object({
602
+ type: z16.literal("date_bucket"),
570
603
  field: TransactionsDateFieldSchema,
571
604
  granularity: MetricsDateGranularitySchema
572
605
  })
573
606
  ]);
574
- var TransactionsMetricSchema = z15.object({
607
+ var TransactionsMetricSchema = z16.object({
575
608
  aggregation: MetricsAggregationSchema,
576
609
  field: TransactionsMetricFieldSchema.optional(),
577
610
  alias: metricAliasSchema
578
611
  });
579
- var TransactionsMetricsQuerySchema = z15.object({
580
- resource: z15.literal("transactions"),
612
+ var TransactionsMetricsQuerySchema = z16.object({
613
+ resource: z16.literal("transactions"),
581
614
  environment: metricsQueryEnvironmentSchema,
582
- dateRange: z15.object({
615
+ dateRange: z16.object({
583
616
  field: TransactionsDateFieldSchema,
584
- from: z15.string().max(64).datetime(),
585
- to: z15.string().max(64).datetime()
617
+ from: z16.string().max(64).datetime(),
618
+ to: z16.string().max(64).datetime()
586
619
  }),
587
- groupBy: z15.array(TransactionsGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
588
- metrics: z15.array(TransactionsMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
589
- filters: z15.array(TransactionsFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
620
+ groupBy: z16.array(TransactionsGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
621
+ metrics: z16.array(TransactionsMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
622
+ filters: z16.array(TransactionsFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
590
623
  orderBy: orderBySchema.optional(),
591
624
  limit: limitSchema
592
625
  });
593
- var DistributionsQueryFieldSchema = z15.enum(["status", "network", "token", "distributorAddress"]).describe(
626
+ var DistributionsQueryFieldSchema = z16.enum(["status", "network", "token", "distributorAddress"]).describe(
594
627
  "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."
595
628
  );
596
- var DistributionsMetricFieldSchema = z15.enum(["attempts"]).describe(
629
+ var DistributionsMetricFieldSchema = z16.enum(["attempts"]).describe(
597
630
  "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."
598
631
  );
599
- var DistributionsDateFieldSchema = z15.enum(["createdAt", "processingStartedAt", "completedAt"]).describe(
632
+ var DistributionsDateFieldSchema = z16.enum(["createdAt", "processingStartedAt", "completedAt"]).describe(
600
633
  "`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."
601
634
  );
602
- var DistributionsFilterSchema = z15.object({
635
+ var DistributionsFilterSchema = z16.object({
603
636
  field: DistributionsQueryFieldSchema,
604
637
  operator: MetricsFilterOperatorSchema,
605
638
  value: MetricsFilterValueSchema
606
639
  });
607
- var DistributionsGroupBySchema = z15.union([
608
- z15.object({ type: z15.literal("field"), field: DistributionsQueryFieldSchema }),
609
- z15.object({
610
- type: z15.literal("date_bucket"),
640
+ var DistributionsGroupBySchema = z16.union([
641
+ z16.object({ type: z16.literal("field"), field: DistributionsQueryFieldSchema }),
642
+ z16.object({
643
+ type: z16.literal("date_bucket"),
611
644
  field: DistributionsDateFieldSchema,
612
645
  granularity: MetricsDateGranularitySchema
613
646
  })
614
647
  ]);
615
- var DistributionsMetricSchema = z15.object({
648
+ var DistributionsMetricSchema = z16.object({
616
649
  aggregation: MetricsAggregationSchema,
617
650
  field: DistributionsMetricFieldSchema.optional(),
618
651
  alias: metricAliasSchema
619
652
  });
620
- var DistributionsMetricsQuerySchema = z15.object({
621
- resource: z15.literal("distributions"),
653
+ var DistributionsMetricsQuerySchema = z16.object({
654
+ resource: z16.literal("distributions"),
622
655
  environment: metricsQueryEnvironmentSchema,
623
- dateRange: z15.object({
656
+ dateRange: z16.object({
624
657
  field: DistributionsDateFieldSchema,
625
- from: z15.string().max(64).datetime(),
626
- to: z15.string().max(64).datetime()
658
+ from: z16.string().max(64).datetime(),
659
+ to: z16.string().max(64).datetime()
627
660
  }),
628
- groupBy: z15.array(DistributionsGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
629
- metrics: z15.array(DistributionsMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
630
- filters: z15.array(DistributionsFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
661
+ groupBy: z16.array(DistributionsGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
662
+ metrics: z16.array(DistributionsMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
663
+ filters: z16.array(DistributionsFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
631
664
  orderBy: orderBySchema.optional(),
632
665
  limit: limitSchema
633
666
  });
634
667
  var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
635
- var MetricsQuerySchema = z15.discriminatedUnion("resource", [
668
+ var MetricsQuerySchema = z16.discriminatedUnion("resource", [
636
669
  ChargesMetricsQuerySchema,
637
670
  TransactionsMetricsQuerySchema,
638
671
  DistributionsMetricsQuerySchema
@@ -641,7 +674,7 @@ var MetricsQuerySchema = z15.discriminatedUnion("resource", [
641
674
  const to = new Date(input.dateRange.to);
642
675
  if (from >= to) {
643
676
  ctx.addIssue({
644
- code: z15.ZodIssueCode.custom,
677
+ code: z16.ZodIssueCode.custom,
645
678
  message: "`dateRange.from` must be before `dateRange.to`.",
646
679
  path: ["dateRange", "from"]
647
680
  });
@@ -649,7 +682,7 @@ var MetricsQuerySchema = z15.discriminatedUnion("resource", [
649
682
  const spanDays = (to.getTime() - from.getTime()) / ONE_DAY_MS;
650
683
  if (spanDays > MAX_METRICS_QUERY_DATE_RANGE_DAYS) {
651
684
  ctx.addIssue({
652
- code: z15.ZodIssueCode.custom,
685
+ code: z16.ZodIssueCode.custom,
653
686
  message: `\`dateRange\` cannot span more than ${MAX_METRICS_QUERY_DATE_RANGE_DAYS} days.`,
654
687
  path: ["dateRange", "to"]
655
688
  });
@@ -657,7 +690,7 @@ var MetricsQuerySchema = z15.discriminatedUnion("resource", [
657
690
  const dateBucketCount = input.groupBy.filter((entry) => entry.type === "date_bucket").length;
658
691
  if (dateBucketCount > 1) {
659
692
  ctx.addIssue({
660
- code: z15.ZodIssueCode.custom,
693
+ code: z16.ZodIssueCode.custom,
661
694
  message: "At most one `date_bucket` entry is allowed in `groupBy`.",
662
695
  path: ["groupBy"]
663
696
  });
@@ -665,7 +698,7 @@ var MetricsQuerySchema = z15.discriminatedUnion("resource", [
665
698
  input.metrics.forEach((metric, index) => {
666
699
  if (metric.aggregation !== "count" && metric.field === void 0) {
667
700
  ctx.addIssue({
668
- code: z15.ZodIssueCode.custom,
701
+ code: z16.ZodIssueCode.custom,
669
702
  message: "`field` is required unless `aggregation` is `count`.",
670
703
  path: ["metrics", index, "field"]
671
704
  });
@@ -674,7 +707,7 @@ var MetricsQuerySchema = z15.discriminatedUnion("resource", [
674
707
  const aliases = input.metrics.map((metric) => metric.alias).filter((alias) => alias !== void 0);
675
708
  if (new Set(aliases).size !== aliases.length) {
676
709
  ctx.addIssue({
677
- code: z15.ZodIssueCode.custom,
710
+ code: z16.ZodIssueCode.custom,
678
711
  message: "Every `metrics[].alias` must be unique.",
679
712
  path: ["metrics"]
680
713
  });
@@ -683,32 +716,32 @@ var MetricsQuerySchema = z15.discriminatedUnion("resource", [
683
716
  input.metrics.forEach((metric, index) => {
684
717
  if (metric.alias !== void 0 && reservedNames.has(metric.alias)) {
685
718
  ctx.addIssue({
686
- code: z15.ZodIssueCode.custom,
719
+ code: z16.ZodIssueCode.custom,
687
720
  message: `\`alias\` "${metric.alias}" collides with a \`groupBy\` field name (or the reserved word "bucket") \u2014 choose a different alias.`,
688
721
  path: ["metrics", index, "alias"]
689
722
  });
690
723
  }
691
724
  });
692
725
  });
693
- var MetricsQueryResultRowSchema = z15.record(
694
- z15.string(),
695
- z15.union([z15.string(), z15.number(), z15.boolean(), z15.null()])
726
+ var MetricsQueryResultRowSchema = z16.record(
727
+ z16.string(),
728
+ z16.union([z16.string(), z16.number(), z16.boolean(), z16.null()])
696
729
  );
697
- var MetricsQueryResultSchema = z15.object({
698
- data: z15.array(MetricsQueryResultRowSchema),
699
- meta: z15.object({
730
+ var MetricsQueryResultSchema = z16.object({
731
+ data: z16.array(MetricsQueryResultRowSchema),
732
+ meta: z16.object({
700
733
  resource: MetricsResourceSchema,
701
734
  environment: EnvironmentSchema,
702
- rowCount: z15.number().int().describe("Number of rows in `data`."),
703
- truncated: z15.boolean().describe(
735
+ rowCount: z16.number().int().describe("Number of rows in `data`."),
736
+ truncated: z16.boolean().describe(
704
737
  "`true` if more rows matched than `limit` allowed \u2014 `data` holds only the first `limit`."
705
738
  )
706
739
  })
707
740
  });
708
741
 
709
742
  // src/webhook-events.ts
710
- import { z as z16 } from "zod";
711
- var ChargeWebhookEventTypeSchema = z16.enum([
743
+ import { z as z17 } from "zod";
744
+ var ChargeWebhookEventTypeSchema = z17.enum([
712
745
  "charge.created",
713
746
  "charge.partially_paid",
714
747
  "charge.confirmed",
@@ -722,14 +755,14 @@ var ChargeWebhookEventTypeSchema = z16.enum([
722
755
  ]).describe(
723
756
  '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`). `charge.escrow_released` fires once an escrow-configured charge\'s funds have been moved out of its Safe to the split address by `POST /v1/charges/{id}/release` \u2014 a normal `charge.settled` still follows once the split itself finishes distributing. `charge.escrow_refunded` fires once an escrow-configured charge\'s funds have been moved out of its Safe back to the payer by `POST /v1/charges/{id}/refund` \u2014 mutually exclusive with `charge.escrow_released`, an escrow charge only ever emits one of the two. Every event in this category carries the full `Charge` object as `data`.'
724
757
  );
725
- var WebhookDeliveryEventTypeSchema = z16.enum(["webhook.delivery_failed", "webhook.delivery_recovered", "webhook.endpoint_unhealthy"]).describe(
758
+ var WebhookDeliveryEventTypeSchema = z17.enum(["webhook.delivery_failed", "webhook.delivery_recovered", "webhook.endpoint_unhealthy"]).describe(
726
759
  "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`)."
727
760
  );
728
- var WebhookEventTypeSchema = z16.union([
761
+ var WebhookEventTypeSchema = z17.union([
729
762
  ChargeWebhookEventTypeSchema,
730
763
  WebhookDeliveryEventTypeSchema
731
764
  ]);
732
- var WebhookCategorySchema = z16.enum(["payments", "webhooks"]).describe(
765
+ var WebhookCategorySchema = z17.enum(["payments", "webhooks"]).describe(
733
766
  "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."
734
767
  );
735
768
  function buildCategoryMap() {
@@ -759,101 +792,103 @@ var TriggerableChargeEventSchema = ChargeWebhookEventTypeSchema.exclude([
759
792
  );
760
793
 
761
794
  // src/webhooks.ts
762
- import { z as z17 } from "zod";
795
+ import { z as z18 } from "zod";
763
796
  var WEBHOOK_EVENTS_WILDCARD = "*";
764
- var CreateWebhookSchema = z17.object({
765
- url: z17.string().max(2048).url().describe(
797
+ var CreateWebhookSchema = z18.object({
798
+ url: z18.string().max(2048).url().describe(
766
799
  "Must be HTTPS and resolve to a public address \u2014 private/internal IPs are rejected."
767
800
  ),
768
- events: z17.array(z17.union([WebhookEventTypeSchema, z17.literal(WEBHOOK_EVENTS_WILDCARD)])).max(Object.keys(EVENT_CATEGORY_MAP).length + 1).default([]).describe(
801
+ events: z18.array(z18.union([WebhookEventTypeSchema, z18.literal(WEBHOOK_EVENTS_WILDCARD)])).max(Object.keys(EVENT_CATEGORY_MAP).length + 1).default([]).describe(
769
802
  '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.'
770
803
  ),
771
- eventCategories: z17.array(WebhookCategorySchema).max(WebhookCategorySchema.options.length).default([]).describe(
804
+ eventCategories: z18.array(WebhookCategorySchema).max(WebhookCategorySchema.options.length).default([]).describe(
772
805
  "Subscribe to every event in these categories. At least one of `events` or `eventCategories` is required."
773
806
  ),
774
- excludeEvents: z17.array(WebhookEventTypeSchema).max(Object.keys(EVENT_CATEGORY_MAP).length).default([]).describe(
807
+ excludeEvents: z18.array(WebhookEventTypeSchema).max(Object.keys(EVENT_CATEGORY_MAP).length).default([]).describe(
775
808
  'Event types to exclude even if selected via `events: ["*"]` or `eventCategories`.'
776
809
  )
777
810
  }).refine((v) => v.events.length > 0 || v.eventCategories.length > 0, {
778
811
  message: "must select at least one event via `events` or `eventCategories`",
779
812
  path: ["events"]
780
813
  });
781
- var WebhookSchema = z17.object({
782
- id: z17.string(),
814
+ var WebhookSchema = z18.object({
815
+ id: z18.string(),
783
816
  environment: EnvironmentSchema.nullable().describe(
784
817
  "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)."
785
818
  ),
786
- url: z17.string(),
787
- events: z17.array(WebhookEventTypeSchema),
788
- eventCategories: z17.array(WebhookCategorySchema),
789
- excludeEvents: z17.array(WebhookEventTypeSchema),
790
- isWildcard: z17.boolean(),
791
- secret: z17.string().describe(
819
+ url: z18.string(),
820
+ events: z18.array(WebhookEventTypeSchema),
821
+ eventCategories: z18.array(WebhookCategorySchema),
822
+ excludeEvents: z18.array(WebhookEventTypeSchema),
823
+ isWildcard: z18.boolean(),
824
+ secret: z18.string().describe(
792
825
  "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."
793
826
  ),
794
- createdAt: z17.string().datetime()
827
+ createdAt: z18.string().datetime()
795
828
  });
796
829
  var WebhookListItemSchema = WebhookSchema.omit({ secret: true }).extend({
797
- hint: z17.string().describe("A truncated, safe-to-display form of the secret (e.g. `whsec_...ab12`).")
830
+ hint: z18.string().describe("A truncated, safe-to-display form of the secret (e.g. `whsec_...ab12`).")
798
831
  });
799
- var WebhookPayloadSchema = z17.object({
800
- id: z17.string().describe(
832
+ var WebhookPayloadSchema = z18.object({
833
+ id: z18.string().describe(
801
834
  "Unique id for this specific delivery \u2014 also sent as the `X-Klappay-Delivery` header."
802
835
  ),
803
836
  event: WebhookEventTypeSchema,
804
- createdAt: z17.string().datetime(),
805
- data: z17.unknown().describe(
837
+ createdAt: z18.string().datetime(),
838
+ data: z18.unknown().describe(
806
839
  "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."
807
840
  )
808
841
  });
809
- var WebhookDeliveryStatusSchema = z17.enum(["pending", "delivered", "failed"]);
810
- var WebhookDeliverySchema = z17.object({
811
- id: z17.string(),
812
- webhookId: z17.string(),
842
+ var WebhookDeliveryStatusSchema = z18.enum(["pending", "delivered", "failed"]);
843
+ var WebhookDeliverySchema = z18.object({
844
+ id: z18.string(),
845
+ webhookId: z18.string(),
813
846
  event: WebhookEventTypeSchema,
814
847
  status: WebhookDeliveryStatusSchema.describe(
815
848
  "`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."
816
849
  ),
817
- attempts: z17.number(),
818
- responseCode: z17.number().nullable().describe(
850
+ attempts: z18.number(),
851
+ responseCode: z18.number().nullable().describe(
819
852
  "HTTP status your endpoint returned on the most recent attempt. `null` if every attempt failed to connect at all."
820
853
  ),
821
- nextRetryAt: z17.string().datetime().nullable(),
822
- deliveredAt: z17.string().datetime().nullable(),
823
- createdAt: z17.string().datetime()
854
+ nextRetryAt: z18.string().datetime().nullable(),
855
+ deliveredAt: z18.string().datetime().nullable(),
856
+ createdAt: z18.string().datetime()
824
857
  });
825
858
  var ListWebhookDeliveriesSchema = PaginationQuerySchema;
826
859
  var PaginatedWebhookDeliveriesSchema = paginatedSchema(WebhookDeliverySchema);
827
860
 
828
861
  // src/recipients.ts
829
- import { z as z18 } from "zod";
830
- var EVM_ADDRESS_REGEX = /^0x[0-9a-fA-F]{40}$/;
831
- var CreateRecipientSchema = z18.object({
832
- address: z18.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."),
833
- label: z18.string().min(1).max(64).optional().describe('Free-form label for your own bookkeeping (e.g. `"supplier"`) \u2014 never interpreted.')
862
+ import { z as z19 } from "zod";
863
+ var CreateRecipientSchema = z19.object({
864
+ address: SplitAddressSchema.describe(
865
+ "Address to register as a trusted split recipient for your organization \u2014 an EVM 0x... address or a TRON T... address."
866
+ ),
867
+ label: z19.string().min(1).max(64).optional().describe('Free-form label for your own bookkeeping (e.g. `"supplier"`) \u2014 never interpreted.')
834
868
  });
835
- var RecipientSchema = z18.object({
836
- id: z18.string().describe(
869
+ var RecipientSchema = z19.object({
870
+ id: z19.string().describe(
837
871
  "Klappay-generated id, e.g. `rc_...` \u2014 this, not the raw address, is what a charge's `splitRecipients[].recipientId` references."
838
872
  ),
839
873
  environment: EnvironmentSchema,
840
- address: z18.string(),
841
- label: z18.string().nullable(),
842
- payout: z18.boolean().describe(
874
+ address: z19.string(),
875
+ label: z19.string().nullable(),
876
+ payout: z19.boolean().describe(
843
877
  "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`."
844
878
  ),
845
- createdAt: z18.string().datetime()
879
+ createdAt: z19.string().datetime()
846
880
  });
847
- var SetRecipientPayoutSchema = z18.object({
848
- payout: z18.boolean().describe("New payout-eligibility value for this recipient.")
881
+ var PaginatedRecipientsSchema = paginatedSchema(RecipientSchema);
882
+ var SetRecipientPayoutSchema = z19.object({
883
+ payout: z19.boolean().describe("New payout-eligibility value for this recipient.")
849
884
  });
850
885
 
851
886
  // src/timeline.ts
852
- import { z as z19 } from "zod";
853
- var TransactionSourceSchema = z19.enum(["contract_watcher", "reconciliation_job", "sandbox"]).describe(
854
- "How this transfer was detected: `contract_watcher` (the normal path \u2014 a real-time on-chain event subscription), `reconciliation_job` (a fallback poller caught it after the watcher missed or delayed it), or `sandbox` (simulated via `POST /v1/sandbox/charges/{id}/trigger`, no real on-chain transfer)."
887
+ import { z as z20 } from "zod";
888
+ var TransactionSourceSchema = z20.enum(["contract_watcher", "reconciliation_job", "sandbox", "tron_watcher"]).describe(
889
+ "How this transfer was detected: `contract_watcher` (the normal path for EVM networks \u2014 a real-time WebSocket log subscription), `tron_watcher` (the TRON equivalent \u2014 a real-time ZeroMQ event subscription against a self-hosted node, a different underlying mechanism since TRON has no WebSocket log subscription), `reconciliation_job` (a fallback poller caught it after the watcher missed or delayed it), or `sandbox` (simulated via `POST /v1/sandbox/charges/{id}/trigger`, no real on-chain transfer)."
855
890
  );
856
- var TimelineEventTypeSchema = z19.enum([
891
+ var TimelineEventTypeSchema = z20.enum([
857
892
  "charge.created",
858
893
  "charge.expired",
859
894
  "transaction.detected",
@@ -865,13 +900,13 @@ var TimelineEventTypeSchema = z19.enum([
865
900
  ]).describe(
866
901
  "`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). `transfer.reclaimed`: an on-chain transfer was detected but never reached its network's required confirmation depth before vanishing (reverted, or dropped from the canonical chain) \u2014 see `txHash` below for which transfer."
867
902
  );
868
- var TimelineEventSchema = z19.object({
903
+ var TimelineEventSchema = z20.object({
869
904
  type: TimelineEventTypeSchema,
870
- at: z19.string().datetime(),
871
- txHash: z19.string().optional().describe(
905
+ at: z20.string().datetime(),
906
+ txHash: z20.string().optional().describe(
872
907
  "Present for `transaction.detected`, `split.distributed`, and `transfer.reclaimed` events only."
873
908
  ),
874
- amount: z19.number().optional().describe(
909
+ amount: z20.number().optional().describe(
875
910
  "Present for `transaction.detected` events only \u2014 the amount that specific transfer carried."
876
911
  ),
877
912
  source: TransactionSourceSchema.optional().describe(
@@ -883,70 +918,70 @@ var TimelineEventSchema = z19.object({
883
918
  network: NetworkSchema.optional().describe(
884
919
  "Present for `transaction.detected` and `split.distributed` events \u2014 which network this specific transfer, or settlement, used."
885
920
  ),
886
- causedTransition: z19.boolean().optional().describe(
921
+ causedTransition: z20.boolean().optional().describe(
887
922
  "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."
888
923
  ),
889
924
  event: WebhookEventTypeSchema.optional().describe(
890
925
  "Present for `webhook.*` events only \u2014 which event type this delivery was for."
891
926
  ),
892
- responseCode: z19.number().nullable().optional().describe(
927
+ responseCode: z20.number().nullable().optional().describe(
893
928
  "Present for `webhook.*` events only \u2014 HTTP status your endpoint returned, or `null` if the request never connected."
894
929
  ),
895
- attempts: z19.number().optional().describe(
930
+ attempts: z20.number().optional().describe(
896
931
  "Present for `webhook.*` events only \u2014 how many delivery attempts have been made so far."
897
932
  )
898
933
  });
899
934
 
900
935
  // src/health.ts
901
- import { z as z20 } from "zod";
902
- var HealthSchema = z20.object({
903
- status: z20.enum(["ok", "error"]).describe(
936
+ import { z as z21 } from "zod";
937
+ var HealthSchema = z21.object({
938
+ status: z21.enum(["ok", "error"]).describe(
904
939
  "`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."
905
940
  ),
906
- version: z20.string(),
907
- timestamp: z20.string().datetime(),
908
- db: z20.enum(["ok", "error"]).describe("Result of a real database connectivity check, not just a process-alive check."),
909
- pendingWebhooks: z20.number().describe("Count of webhook deliveries still awaiting a successful attempt."),
910
- oldestPendingChargeAgeSeconds: z20.number().nullable().describe("Age of the oldest still-unpaid charge, in seconds. `null` if there are none."),
911
- lastContractWatcherEventAgeSeconds: z20.number().nullable().describe(
941
+ version: z21.string(),
942
+ timestamp: z21.string().datetime(),
943
+ db: z21.enum(["ok", "error"]).describe("Result of a real database connectivity check, not just a process-alive check."),
944
+ pendingWebhooks: z21.number().describe("Count of webhook deliveries still awaiting a successful attempt."),
945
+ oldestPendingChargeAgeSeconds: z21.number().nullable().describe("Age of the oldest still-unpaid charge, in seconds. `null` if there are none."),
946
+ lastContractWatcherEventAgeSeconds: z21.number().nullable().describe(
912
947
  "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."
913
948
  )
914
949
  });
915
950
 
916
951
  // src/sandbox.ts
917
- import { z as z21 } from "zod";
918
- var SandboxTriggerSchema = z21.object({
952
+ import { z as z22 } from "zod";
953
+ var SandboxTriggerSchema = z22.object({
919
954
  event: TriggerableChargeEventSchema,
920
- amount: z21.number().positive().max(CHARGE_AMOUNT_MAX).optional().describe(
955
+ amount: z22.number().positive().max(CHARGE_AMOUNT_MAX).optional().describe(
921
956
  "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."
922
957
  )
923
958
  });
924
959
 
925
960
  // src/capabilities.ts
926
- import { z as z22 } from "zod";
927
- var CapabilitiesSchema = z22.object({
928
- acceptedPayments: z22.array(AcceptedPaymentSchema).describe(
961
+ import { z as z23 } from "zod";
962
+ var CapabilitiesSchema = z23.object({
963
+ acceptedPayments: z23.array(AcceptedPaymentSchema).describe(
929
964
  "Every `(token, network)` pair enabled for your environment right now, using the same deployment metadata and availability policy as `POST /v1/charges`. Cataloged but disabled pairs are omitted. Availability can change between requests, so handle `422 token_not_supported` when creating a charge. Use this to build a picker UI instead of hardcoding the matrix client-side."
930
965
  )
931
966
  });
932
967
 
933
968
  // src/swap.ts
934
- import { z as z23 } from "zod";
935
- var CreateSwapQuoteSchema = z23.object({
969
+ import { z as z24 } from "zod";
970
+ var CreateSwapQuoteSchema = z24.object({
936
971
  inputToken: AltTokenSchema.describe(
937
972
  "Which alt-cryptocurrency the payer wants to send \u2014 must be one of this charge's `swapAlternatives`, or `422 token_not_supported`."
938
973
  ),
939
974
  inputNetwork: NetworkSchema.describe(
940
975
  "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 applies its token preference among enabled pairs the charge accepts. BNB Chain payments are currently disabled for both cataloged Binance-Peg tokens."
941
976
  ),
942
- takerAddress: z23.string().regex(/^0x[0-9a-fA-F]{40}$/, "must be a 20-byte hex address").describe(
977
+ takerAddress: z24.string().regex(/^0x[0-9a-fA-F]{40}$/, "must be a 20-byte hex address").describe(
943
978
  "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."
944
979
  )
945
980
  });
946
- var SwapQuoteSchema = z23.object({
981
+ var SwapQuoteSchema = z24.object({
947
982
  inputToken: AltTokenSchema,
948
983
  inputNetwork: NetworkSchema,
949
- inputAmount: z23.number().describe(
984
+ inputAmount: z24.number().describe(
950
985
  "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."
951
986
  ),
952
987
  inputAmountExact: ExactAmountSchema.optional().describe(
@@ -956,20 +991,20 @@ var SwapQuoteSchema = z23.object({
956
991
  "Which of this charge's `acceptedPayments` tokens the swap resolves to."
957
992
  ),
958
993
  outputNetwork: NetworkSchema,
959
- outputAmount: z23.number().describe(
994
+ outputAmount: z24.number().describe(
960
995
  "The stablecoin amount requested by this quote, in whole `outputToken` units. Covers the remaining balance, rounded up only if the selected token cannot represent it exactly. This legacy JSON number can lose precision; use `outputAmountExact` for arithmetic. The actual transfer is verified on-chain before crediting the charge."
961
996
  ),
962
997
  outputAmountExact: ExactAmountSchema.optional().describe(
963
998
  "Exact stablecoin amount requested by this quote, in whole `outputToken` units as a nonnegative decimal string with no scientific notation. Covers the remaining charge balance and rounds upward only to the smallest representable token unit when needed. Optional for compatibility with older API responses."
964
999
  ),
965
- fees: z23.object({
966
- klappayFee: z23.number().describe(
1000
+ fees: z24.object({
1001
+ klappayFee: z24.number().describe(
967
1002
  "Klappay's own swap fee (1% today), in `outputToken` units \u2014 paid by the payer and already reflected in `inputAmount`, separate from the merchant's own `feePercent`. Never subtracted from `outputAmount`."
968
1003
  ),
969
1004
  klappayFeeExact: ExactAmountSchema.optional().describe(
970
1005
  "Exact Klappay swap fee in whole `outputToken` units as a nonnegative decimal string with at most 18 fractional digits and no scientific notation. Already reflected in the input ceiling. Optional for compatibility with older API responses."
971
1006
  ),
972
- zeroExFee: z23.number().nullable().describe(
1007
+ zeroExFee: z24.number().nullable().describe(
973
1008
  "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. Paid by the payer and already reflected in `inputAmount`, never subtracted from `outputAmount` \u2014 Klappay never sees this fee, it goes straight to 0x."
974
1009
  ),
975
1010
  zeroExFeeExact: ExactAmountSchema.nullable().optional().describe(
@@ -978,19 +1013,19 @@ var SwapQuoteSchema = z23.object({
978
1013
  }).describe(
979
1014
  "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`."
980
1015
  ),
981
- expiresAt: z23.string().datetime().describe(
1016
+ expiresAt: z24.string().datetime().describe(
982
1017
  "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."
983
1018
  ),
984
- transaction: z23.object({
985
- to: z23.string().describe("Contract address the payer's wallet must send this transaction to."),
986
- data: z23.string().describe("Calldata \u2014 opaque, must be sent unmodified."),
987
- value: z23.string().describe(
1019
+ transaction: z24.object({
1020
+ to: z24.string().describe("Contract address the payer's wallet must send this transaction to."),
1021
+ data: z24.string().describe("Calldata \u2014 opaque, must be sent unmodified."),
1022
+ value: z24.string().describe(
988
1023
  "Native currency (ETH/BNB/POL/AVAX) to attach, in wei \u2014 `\"0\"` when `inputToken` isn't this network's native currency."
989
1024
  )
990
1025
  }).describe(
991
1026
  "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."
992
1027
  ),
993
- permit2: z23.object({ eip712: z23.record(z23.unknown()) }).nullish().describe(
1028
+ permit2: z24.object({ eip712: z24.record(z24.unknown()) }).nullish().describe(
994
1029
  "Present only when `inputToken` is an ERC-20 (BTC, LINK, or a chain-specific blue chip like ARB/OP/CBETH) \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. `null` (never omitted, in a genuine 0x-backed quote) when `inputToken` is a network's own native currency (ETH/BNB/POL/AVAX) \u2014 `transaction` is then ready to sign and send directly, no extra step."
995
1030
  )
996
1031
  });
@@ -1054,6 +1089,7 @@ export {
1054
1089
  MetricsQuerySchema,
1055
1090
  MetricsResourceSchema,
1056
1091
  NETWORK_EXPLORERS,
1092
+ NETWORK_FAMILIES,
1057
1093
  NETWORK_LABELS,
1058
1094
  NetworkSchema,
1059
1095
  OPERATIONAL_NETWORKS,
@@ -1062,6 +1098,7 @@ export {
1062
1098
  PAGINATION_LIMIT_MIN,
1063
1099
  PaginatedChargesSchema,
1064
1100
  PaginatedPendingDistributionsSchema,
1101
+ PaginatedRecipientsSchema,
1065
1102
  PaginatedWebhookDeliveriesSchema,
1066
1103
  PaginationQuerySchema,
1067
1104
  PendingDistributionEventSchema,
@@ -1073,6 +1110,7 @@ export {
1073
1110
  SandboxTriggerSchema,
1074
1111
  SetRecipientPayoutSchema,
1075
1112
  SettlementStatusSchema,
1113
+ SplitAddressSchema,
1076
1114
  SplitDistributionStatusSchema,
1077
1115
  SplitRecipientInputSchema,
1078
1116
  SplitRecipientSchema,
@@ -1099,10 +1137,15 @@ export {
1099
1137
  WebhookListItemSchema,
1100
1138
  WebhookPayloadSchema,
1101
1139
  WebhookSchema,
1140
+ addressesEqual,
1102
1141
  findConflictingScopes,
1103
1142
  getTokenDeployment,
1143
+ isEvmAddress,
1104
1144
  isPaymentDeploymentEnabled,
1145
+ isSplitAddress,
1146
+ isTronAddress,
1105
1147
  listSwapAlternatives,
1106
- paginatedSchema
1148
+ paginatedSchema,
1149
+ tronAddress
1107
1150
  };
1108
1151
  //# sourceMappingURL=index.mjs.map