@klappay/types 3.6.0 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.mts +175 -54
- package/dist/index.d.ts +175 -54
- package/dist/index.js +255 -199
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +252 -199
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -151,6 +151,11 @@ var ReleaseEscrowRequestSchema = z9.object({
|
|
|
151
151
|
"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."
|
|
152
152
|
)
|
|
153
153
|
});
|
|
154
|
+
var RefundEscrowRequestSchema = z9.object({
|
|
155
|
+
signature: z9.string().regex(/^0x[0-9a-fA-F]+$/, "must be hex-encoded signature bytes").describe(
|
|
156
|
+
"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."
|
|
157
|
+
)
|
|
158
|
+
});
|
|
154
159
|
|
|
155
160
|
// src/charges.ts
|
|
156
161
|
var ChargeStatusSchema = z10.enum(["pending", "partially_paid", "confirmed", "expired", "underpaid"]).describe(
|
|
@@ -159,6 +164,9 @@ var ChargeStatusSchema = z10.enum(["pending", "partially_paid", "confirmed", "ex
|
|
|
159
164
|
var SettlementStatusSchema = z10.enum(["pending", "completed", "failed"]).describe(
|
|
160
165
|
"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."
|
|
161
166
|
);
|
|
167
|
+
var ChargeFeePayerSchema = z10.enum(["merchant", "payer"]).describe(
|
|
168
|
+
"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."
|
|
169
|
+
);
|
|
162
170
|
var CHARGE_EXPIRES_IN_MIN_SECONDS = 60;
|
|
163
171
|
var CHARGE_EXPIRES_IN_MAX_SECONDS = 3600;
|
|
164
172
|
var CHARGE_ACCEPTED_PAYMENTS_MAX = 14;
|
|
@@ -228,8 +236,9 @@ var SplitRecipientsInputSchema = z10.array(SplitRecipientInputSchema).max(CHARGE
|
|
|
228
236
|
var CHARGE_AMOUNT_MAX = 999999999999;
|
|
229
237
|
var CreateChargeSchema = z10.object({
|
|
230
238
|
amount: z10.number().positive().max(CHARGE_AMOUNT_MAX).describe(
|
|
231
|
-
"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."
|
|
239
|
+
"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."
|
|
232
240
|
),
|
|
241
|
+
feePayer: ChargeFeePayerSchema.optional().default("merchant"),
|
|
233
242
|
currency: z10.literal("USD").default("USD").describe("Always `USD` today \u2014 the only supported currency."),
|
|
234
243
|
acceptedPayments: AcceptedPaymentsSchema,
|
|
235
244
|
expiresIn: z10.number().int().min(CHARGE_EXPIRES_IN_MIN_SECONDS).max(CHARGE_EXPIRES_IN_MAX_SECONDS).describe(
|
|
@@ -255,7 +264,17 @@ var CreateChargeSchema = z10.object({
|
|
|
255
264
|
});
|
|
256
265
|
var ChargeSchema = z10.object({
|
|
257
266
|
id: z10.string().describe("Klappay-generated id, e.g. `ch_...`. Use this to look up the charge later."),
|
|
258
|
-
amount: z10.number().describe(
|
|
267
|
+
amount: z10.number().describe(
|
|
268
|
+
"The exact total the payer must send, in `currency` units (up to 6 decimal places). With `feePayer: 'merchant'` (the default) this is exactly 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."
|
|
269
|
+
),
|
|
270
|
+
feePayer: ChargeFeePayerSchema,
|
|
271
|
+
feePercent: z10.number().describe(
|
|
272
|
+
"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."
|
|
273
|
+
),
|
|
274
|
+
feeAmount: z10.number().describe("`amount * feePercent / 100`, in `currency` units \u2014 Klappay's cut of this charge."),
|
|
275
|
+
merchantAmount: z10.number().describe(
|
|
276
|
+
"`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)."
|
|
277
|
+
),
|
|
259
278
|
amountReceived: z10.number().nullable().describe(
|
|
260
279
|
"Cumulative amount actually received on-chain so far, in `currency` units (up to 6 decimal places). `null` until the first transfer arrives. Can exceed `amount` \u2014 see `isOverpaid`."
|
|
261
280
|
),
|
|
@@ -305,7 +324,10 @@ var ChargeSchema = z10.object({
|
|
|
305
324
|
),
|
|
306
325
|
escrow: z10.object({
|
|
307
326
|
releaserAddress: z10.string().describe("The only address that can ever release this escrow \u2014 never Klappay."),
|
|
308
|
-
releasedAt: z10.string().datetime().nullable().describe("When the release actually executed on-chain. `null` until then.")
|
|
327
|
+
releasedAt: z10.string().datetime().nullable().describe("When the release actually executed on-chain. `null` until then."),
|
|
328
|
+
refundedAt: z10.string().datetime().nullable().describe(
|
|
329
|
+
"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."
|
|
330
|
+
)
|
|
309
331
|
}).nullable().describe(
|
|
310
332
|
"Present only when this charge was created as an escrow (see `escrow` on the create request) \u2014 `null` for a normal charge."
|
|
311
333
|
)
|
|
@@ -333,9 +355,28 @@ var GetChargeQrCodeQuerySchema = z10.object({
|
|
|
333
355
|
});
|
|
334
356
|
|
|
335
357
|
// src/charge-check.ts
|
|
358
|
+
import { z as z12 } from "zod";
|
|
359
|
+
|
|
360
|
+
// src/confirmation-progress.ts
|
|
336
361
|
import { z as z11 } from "zod";
|
|
337
|
-
var
|
|
338
|
-
|
|
362
|
+
var ConfirmationProgressSchema = z11.object({
|
|
363
|
+
network: NetworkSchema.describe("Which network the transfer was seen on."),
|
|
364
|
+
blocksSeen: z11.number().int().min(0).describe(
|
|
365
|
+
"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."
|
|
366
|
+
),
|
|
367
|
+
blocksRequired: z11.number().int().min(1).describe(
|
|
368
|
+
"This network's minimum confirmation depth (a fixed, per-network constant) \u2014 the transfer is only credited once `blocksSeen` reaches this value."
|
|
369
|
+
),
|
|
370
|
+
percent: z11.number().int().min(0).max(99).describe(
|
|
371
|
+
'`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).'
|
|
372
|
+
)
|
|
373
|
+
}).describe(
|
|
374
|
+
"How close an already-detected transfer is to being trusted as final and credited, before its network's minimum confirmation depth is reached (see `docs/payments.md`'s \"Confirmation depth\" section). Only ever present for a transfer that's been seen on-chain but isn't deep enough yet \u2014 absent/null once it's credited (the charge's own status change is what signals that) or if nothing has been detected at all."
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
// src/charge-check.ts
|
|
378
|
+
var CheckChargeRequestSchema = z12.object({
|
|
379
|
+
txHash: z12.string().regex(/^0x[0-9a-fA-F]{64}$/, "must be a 32-byte transaction hash").optional().describe(
|
|
339
380
|
"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."
|
|
340
381
|
),
|
|
341
382
|
network: NetworkSchema.optional().describe(
|
|
@@ -345,67 +386,70 @@ var CheckChargeRequestSchema = z11.object({
|
|
|
345
386
|
message: "`txHash` and `network` must be provided together, or both omitted"
|
|
346
387
|
});
|
|
347
388
|
var CheckChargeResponseSchema = ChargeSchema.extend({
|
|
348
|
-
transactionSender:
|
|
389
|
+
transactionSender: z12.string().nullable().describe(
|
|
349
390
|
"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`."
|
|
391
|
+
),
|
|
392
|
+
confirmationProgress: ConfirmationProgressSchema.nullable().describe(
|
|
393
|
+
"Present when this check found a real matching transfer on-chain that has not yet reached its network's required confirmation depth \u2014 use it to render a progress bar while waiting. `null` when nothing new was found, when the charge is already terminal (this check short-circuits with no RPC call), or once the transfer is deep enough to have already been credited (the charge's own `status` field is the signal for that, not this one)."
|
|
350
394
|
)
|
|
351
395
|
});
|
|
352
396
|
|
|
353
397
|
// src/distributions.ts
|
|
354
|
-
import { z as
|
|
355
|
-
var SplitDistributionStatusSchema =
|
|
398
|
+
import { z as z13 } from "zod";
|
|
399
|
+
var SplitDistributionStatusSchema = z13.enum(["pending", "processing", "completed", "failed"]).describe(
|
|
356
400
|
"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."
|
|
357
401
|
);
|
|
358
|
-
var PendingDistributionRecipientSchema =
|
|
359
|
-
address:
|
|
360
|
-
percentAllocation:
|
|
402
|
+
var PendingDistributionRecipientSchema = z13.object({
|
|
403
|
+
address: z13.string().describe("On-chain recipient address."),
|
|
404
|
+
percentAllocation: z13.number().describe("This recipient's share of the split, as a percentage (e.g. `99.0991` = 99.0991%).")
|
|
361
405
|
});
|
|
362
|
-
var PendingDistributionSchema =
|
|
363
|
-
splitAddress:
|
|
406
|
+
var PendingDistributionSchema = z13.object({
|
|
407
|
+
splitAddress: z13.string().describe("The on-chain 0xSplits address to call `distribute()` on."),
|
|
364
408
|
network: NetworkSchema,
|
|
365
409
|
token: TokenSchema,
|
|
366
|
-
recipients:
|
|
410
|
+
recipients: z13.array(PendingDistributionRecipientSchema).describe(
|
|
367
411
|
"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."
|
|
368
412
|
),
|
|
369
|
-
distributorFeePercent:
|
|
413
|
+
distributorFeePercent: z13.number().describe(
|
|
370
414
|
"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."
|
|
371
415
|
),
|
|
372
|
-
estimatedRewardAmount:
|
|
416
|
+
estimatedRewardAmount: z13.number().describe(
|
|
373
417
|
"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."
|
|
374
418
|
),
|
|
375
|
-
availableSince:
|
|
376
|
-
graceEndsAt:
|
|
419
|
+
availableSince: z13.string().datetime().describe("When this distribution entered its grace period."),
|
|
420
|
+
graceEndsAt: z13.string().datetime().describe(
|
|
377
421
|
"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."
|
|
378
422
|
)
|
|
379
423
|
});
|
|
380
424
|
var PaginatedPendingDistributionsSchema = paginatedSchema(PendingDistributionSchema);
|
|
381
|
-
var ListenPendingDistributionsQuerySchema =
|
|
382
|
-
limit:
|
|
425
|
+
var ListenPendingDistributionsQuerySchema = z13.object({
|
|
426
|
+
limit: z13.coerce.number().int().min(0).max(PAGINATION_LIMIT_MAX).default(0).describe(
|
|
383
427
|
"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."
|
|
384
428
|
)
|
|
385
429
|
});
|
|
386
|
-
var PendingDistributionEventSchema =
|
|
387
|
-
|
|
388
|
-
type:
|
|
430
|
+
var PendingDistributionEventSchema = z13.discriminatedUnion("type", [
|
|
431
|
+
z13.object({
|
|
432
|
+
type: z13.literal("distribution.available"),
|
|
389
433
|
distribution: PendingDistributionSchema
|
|
390
434
|
}),
|
|
391
|
-
|
|
392
|
-
type:
|
|
393
|
-
splitAddress:
|
|
435
|
+
z13.object({
|
|
436
|
+
type: z13.literal("distribution.claimed"),
|
|
437
|
+
splitAddress: z13.string().describe("No longer claimable \u2014 either settled by someone, or picked up by the worker.")
|
|
394
438
|
})
|
|
395
439
|
]);
|
|
396
440
|
|
|
397
441
|
// src/metrics.ts
|
|
398
|
-
import { z as
|
|
399
|
-
var MetricsResourceSchema =
|
|
442
|
+
import { z as z14 } from "zod";
|
|
443
|
+
var MetricsResourceSchema = z14.enum(["charges", "transactions", "distributions"]).describe(
|
|
400
444
|
"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."
|
|
401
445
|
);
|
|
402
|
-
var MetricsAggregationSchema =
|
|
446
|
+
var MetricsAggregationSchema = z14.enum(["count", "sum", "avg", "min", "max"]).describe(
|
|
403
447
|
"`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."
|
|
404
448
|
);
|
|
405
|
-
var MetricsFilterOperatorSchema =
|
|
449
|
+
var MetricsFilterOperatorSchema = z14.enum(["eq", "neq", "in", "gt", "gte", "lt", "lte"]).describe(
|
|
406
450
|
"`in` expects an array value (max 50 entries); every other operator expects a single scalar."
|
|
407
451
|
);
|
|
408
|
-
var MetricsDateGranularitySchema =
|
|
452
|
+
var MetricsDateGranularitySchema = z14.enum(["day", "week", "month", "year"]).describe(
|
|
409
453
|
"Bucket width for a `date_bucket` `groupBy` entry \u2014 Postgres `date_trunc` semantics (UTC)."
|
|
410
454
|
);
|
|
411
455
|
var metricsQueryEnvironmentSchema = EnvironmentSchema.describe(
|
|
@@ -418,31 +462,31 @@ var METRICS_QUERY_MAX_GROUP_BY = 3;
|
|
|
418
462
|
var METRICS_QUERY_MAX_FILTERS = 20;
|
|
419
463
|
var METRICS_QUERY_MAX_METRICS = 10;
|
|
420
464
|
var METRIC_ALIAS_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
421
|
-
var metricAliasSchema =
|
|
465
|
+
var metricAliasSchema = z14.string().min(1).max(64).regex(
|
|
422
466
|
METRIC_ALIAS_PATTERN,
|
|
423
467
|
"Must start with a letter or underscore, and contain only letters, digits, and underscores \u2014 this becomes a SQL column alias."
|
|
424
468
|
).optional();
|
|
425
|
-
var MetricsFilterValueSchema =
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
469
|
+
var MetricsFilterValueSchema = z14.union([
|
|
470
|
+
z14.string().max(255),
|
|
471
|
+
z14.number(),
|
|
472
|
+
z14.boolean(),
|
|
473
|
+
z14.array(z14.union([z14.string().max(255), z14.number()])).min(1).max(50)
|
|
430
474
|
]);
|
|
431
|
-
var orderBySchema =
|
|
432
|
-
key:
|
|
475
|
+
var orderBySchema = z14.object({
|
|
476
|
+
key: z14.string().min(1).max(64).regex(
|
|
433
477
|
METRIC_ALIAS_PATTERN,
|
|
434
478
|
"Must start with a letter or underscore, and contain only letters, digits, and underscores \u2014 every valid output column name already looks like this."
|
|
435
479
|
).describe(
|
|
436
480
|
"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."
|
|
437
481
|
),
|
|
438
|
-
direction:
|
|
482
|
+
direction: z14.enum(["asc", "desc"])
|
|
439
483
|
}).describe(
|
|
440
484
|
"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."
|
|
441
485
|
);
|
|
442
|
-
var limitSchema =
|
|
486
|
+
var limitSchema = z14.number().int().min(1).max(METRICS_QUERY_MAX_ROW_LIMIT).default(METRICS_QUERY_DEFAULT_ROW_LIMIT).describe(
|
|
443
487
|
`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.`
|
|
444
488
|
);
|
|
445
|
-
var ChargesQueryFieldSchema =
|
|
489
|
+
var ChargesQueryFieldSchema = z14.enum([
|
|
446
490
|
"status",
|
|
447
491
|
"source",
|
|
448
492
|
"apiKeyId",
|
|
@@ -453,124 +497,124 @@ var ChargesQueryFieldSchema = z13.enum([
|
|
|
453
497
|
]).describe(
|
|
454
498
|
"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)."
|
|
455
499
|
);
|
|
456
|
-
var ChargesMetricFieldSchema =
|
|
500
|
+
var ChargesMetricFieldSchema = z14.enum(["amount", "amountReceived", "feePercent", "escrowFeePercent"]).describe(
|
|
457
501
|
"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`."
|
|
458
502
|
);
|
|
459
|
-
var ChargesDateFieldSchema =
|
|
503
|
+
var ChargesDateFieldSchema = z14.enum(["createdAt", "confirmedAt", "lastActivityAt", "expiresAt", "escrowReleasedAt"]).describe(
|
|
460
504
|
"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."
|
|
461
505
|
);
|
|
462
|
-
var ChargesFilterSchema =
|
|
506
|
+
var ChargesFilterSchema = z14.object({
|
|
463
507
|
field: ChargesQueryFieldSchema,
|
|
464
508
|
operator: MetricsFilterOperatorSchema,
|
|
465
509
|
value: MetricsFilterValueSchema
|
|
466
510
|
});
|
|
467
|
-
var ChargesGroupBySchema =
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
type:
|
|
511
|
+
var ChargesGroupBySchema = z14.union([
|
|
512
|
+
z14.object({ type: z14.literal("field"), field: ChargesQueryFieldSchema }),
|
|
513
|
+
z14.object({
|
|
514
|
+
type: z14.literal("date_bucket"),
|
|
471
515
|
field: ChargesDateFieldSchema,
|
|
472
516
|
granularity: MetricsDateGranularitySchema
|
|
473
517
|
})
|
|
474
518
|
]);
|
|
475
|
-
var ChargesMetricSchema =
|
|
519
|
+
var ChargesMetricSchema = z14.object({
|
|
476
520
|
aggregation: MetricsAggregationSchema,
|
|
477
521
|
field: ChargesMetricFieldSchema.optional(),
|
|
478
522
|
alias: metricAliasSchema
|
|
479
523
|
});
|
|
480
|
-
var ChargesMetricsQuerySchema =
|
|
481
|
-
resource:
|
|
524
|
+
var ChargesMetricsQuerySchema = z14.object({
|
|
525
|
+
resource: z14.literal("charges"),
|
|
482
526
|
environment: metricsQueryEnvironmentSchema,
|
|
483
|
-
dateRange:
|
|
527
|
+
dateRange: z14.object({
|
|
484
528
|
field: ChargesDateFieldSchema,
|
|
485
|
-
from:
|
|
486
|
-
to:
|
|
529
|
+
from: z14.string().max(64).datetime(),
|
|
530
|
+
to: z14.string().max(64).datetime()
|
|
487
531
|
}),
|
|
488
|
-
groupBy:
|
|
489
|
-
metrics:
|
|
490
|
-
filters:
|
|
532
|
+
groupBy: z14.array(ChargesGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
|
|
533
|
+
metrics: z14.array(ChargesMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
|
|
534
|
+
filters: z14.array(ChargesFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
|
|
491
535
|
orderBy: orderBySchema.optional(),
|
|
492
536
|
limit: limitSchema
|
|
493
537
|
});
|
|
494
|
-
var TransactionsQueryFieldSchema =
|
|
538
|
+
var TransactionsQueryFieldSchema = z14.enum(["network", "token", "source", "causedTransition"]).describe(
|
|
495
539
|
"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)."
|
|
496
540
|
);
|
|
497
|
-
var TransactionsMetricFieldSchema =
|
|
498
|
-
var TransactionsDateFieldSchema =
|
|
499
|
-
var TransactionsFilterSchema =
|
|
541
|
+
var TransactionsMetricFieldSchema = z14.enum(["amount"]).describe("The transfer amount, in the charge's `currency` units.");
|
|
542
|
+
var TransactionsDateFieldSchema = z14.enum(["detectedAt"]).describe("When Klappay detected this transfer on-chain (not when it was mined).");
|
|
543
|
+
var TransactionsFilterSchema = z14.object({
|
|
500
544
|
field: TransactionsQueryFieldSchema,
|
|
501
545
|
operator: MetricsFilterOperatorSchema,
|
|
502
546
|
value: MetricsFilterValueSchema
|
|
503
547
|
});
|
|
504
|
-
var TransactionsGroupBySchema =
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
type:
|
|
548
|
+
var TransactionsGroupBySchema = z14.union([
|
|
549
|
+
z14.object({ type: z14.literal("field"), field: TransactionsQueryFieldSchema }),
|
|
550
|
+
z14.object({
|
|
551
|
+
type: z14.literal("date_bucket"),
|
|
508
552
|
field: TransactionsDateFieldSchema,
|
|
509
553
|
granularity: MetricsDateGranularitySchema
|
|
510
554
|
})
|
|
511
555
|
]);
|
|
512
|
-
var TransactionsMetricSchema =
|
|
556
|
+
var TransactionsMetricSchema = z14.object({
|
|
513
557
|
aggregation: MetricsAggregationSchema,
|
|
514
558
|
field: TransactionsMetricFieldSchema.optional(),
|
|
515
559
|
alias: metricAliasSchema
|
|
516
560
|
});
|
|
517
|
-
var TransactionsMetricsQuerySchema =
|
|
518
|
-
resource:
|
|
561
|
+
var TransactionsMetricsQuerySchema = z14.object({
|
|
562
|
+
resource: z14.literal("transactions"),
|
|
519
563
|
environment: metricsQueryEnvironmentSchema,
|
|
520
|
-
dateRange:
|
|
564
|
+
dateRange: z14.object({
|
|
521
565
|
field: TransactionsDateFieldSchema,
|
|
522
|
-
from:
|
|
523
|
-
to:
|
|
566
|
+
from: z14.string().max(64).datetime(),
|
|
567
|
+
to: z14.string().max(64).datetime()
|
|
524
568
|
}),
|
|
525
|
-
groupBy:
|
|
526
|
-
metrics:
|
|
527
|
-
filters:
|
|
569
|
+
groupBy: z14.array(TransactionsGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
|
|
570
|
+
metrics: z14.array(TransactionsMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
|
|
571
|
+
filters: z14.array(TransactionsFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
|
|
528
572
|
orderBy: orderBySchema.optional(),
|
|
529
573
|
limit: limitSchema
|
|
530
574
|
});
|
|
531
|
-
var DistributionsQueryFieldSchema =
|
|
575
|
+
var DistributionsQueryFieldSchema = z14.enum(["status", "network", "token", "distributorAddress"]).describe(
|
|
532
576
|
"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."
|
|
533
577
|
);
|
|
534
|
-
var DistributionsMetricFieldSchema =
|
|
578
|
+
var DistributionsMetricFieldSchema = z14.enum(["attempts"]).describe(
|
|
535
579
|
"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."
|
|
536
580
|
);
|
|
537
|
-
var DistributionsDateFieldSchema =
|
|
581
|
+
var DistributionsDateFieldSchema = z14.enum(["createdAt", "processingStartedAt", "completedAt"]).describe(
|
|
538
582
|
"`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."
|
|
539
583
|
);
|
|
540
|
-
var DistributionsFilterSchema =
|
|
584
|
+
var DistributionsFilterSchema = z14.object({
|
|
541
585
|
field: DistributionsQueryFieldSchema,
|
|
542
586
|
operator: MetricsFilterOperatorSchema,
|
|
543
587
|
value: MetricsFilterValueSchema
|
|
544
588
|
});
|
|
545
|
-
var DistributionsGroupBySchema =
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
type:
|
|
589
|
+
var DistributionsGroupBySchema = z14.union([
|
|
590
|
+
z14.object({ type: z14.literal("field"), field: DistributionsQueryFieldSchema }),
|
|
591
|
+
z14.object({
|
|
592
|
+
type: z14.literal("date_bucket"),
|
|
549
593
|
field: DistributionsDateFieldSchema,
|
|
550
594
|
granularity: MetricsDateGranularitySchema
|
|
551
595
|
})
|
|
552
596
|
]);
|
|
553
|
-
var DistributionsMetricSchema =
|
|
597
|
+
var DistributionsMetricSchema = z14.object({
|
|
554
598
|
aggregation: MetricsAggregationSchema,
|
|
555
599
|
field: DistributionsMetricFieldSchema.optional(),
|
|
556
600
|
alias: metricAliasSchema
|
|
557
601
|
});
|
|
558
|
-
var DistributionsMetricsQuerySchema =
|
|
559
|
-
resource:
|
|
602
|
+
var DistributionsMetricsQuerySchema = z14.object({
|
|
603
|
+
resource: z14.literal("distributions"),
|
|
560
604
|
environment: metricsQueryEnvironmentSchema,
|
|
561
|
-
dateRange:
|
|
605
|
+
dateRange: z14.object({
|
|
562
606
|
field: DistributionsDateFieldSchema,
|
|
563
|
-
from:
|
|
564
|
-
to:
|
|
607
|
+
from: z14.string().max(64).datetime(),
|
|
608
|
+
to: z14.string().max(64).datetime()
|
|
565
609
|
}),
|
|
566
|
-
groupBy:
|
|
567
|
-
metrics:
|
|
568
|
-
filters:
|
|
610
|
+
groupBy: z14.array(DistributionsGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
|
|
611
|
+
metrics: z14.array(DistributionsMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
|
|
612
|
+
filters: z14.array(DistributionsFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
|
|
569
613
|
orderBy: orderBySchema.optional(),
|
|
570
614
|
limit: limitSchema
|
|
571
615
|
});
|
|
572
616
|
var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
|
|
573
|
-
var MetricsQuerySchema =
|
|
617
|
+
var MetricsQuerySchema = z14.discriminatedUnion("resource", [
|
|
574
618
|
ChargesMetricsQuerySchema,
|
|
575
619
|
TransactionsMetricsQuerySchema,
|
|
576
620
|
DistributionsMetricsQuerySchema
|
|
@@ -579,7 +623,7 @@ var MetricsQuerySchema = z13.discriminatedUnion("resource", [
|
|
|
579
623
|
const to = new Date(input.dateRange.to);
|
|
580
624
|
if (from >= to) {
|
|
581
625
|
ctx.addIssue({
|
|
582
|
-
code:
|
|
626
|
+
code: z14.ZodIssueCode.custom,
|
|
583
627
|
message: "`dateRange.from` must be before `dateRange.to`.",
|
|
584
628
|
path: ["dateRange", "from"]
|
|
585
629
|
});
|
|
@@ -587,7 +631,7 @@ var MetricsQuerySchema = z13.discriminatedUnion("resource", [
|
|
|
587
631
|
const spanDays = (to.getTime() - from.getTime()) / ONE_DAY_MS;
|
|
588
632
|
if (spanDays > MAX_METRICS_QUERY_DATE_RANGE_DAYS) {
|
|
589
633
|
ctx.addIssue({
|
|
590
|
-
code:
|
|
634
|
+
code: z14.ZodIssueCode.custom,
|
|
591
635
|
message: `\`dateRange\` cannot span more than ${MAX_METRICS_QUERY_DATE_RANGE_DAYS} days.`,
|
|
592
636
|
path: ["dateRange", "to"]
|
|
593
637
|
});
|
|
@@ -595,7 +639,7 @@ var MetricsQuerySchema = z13.discriminatedUnion("resource", [
|
|
|
595
639
|
const dateBucketCount = input.groupBy.filter((entry) => entry.type === "date_bucket").length;
|
|
596
640
|
if (dateBucketCount > 1) {
|
|
597
641
|
ctx.addIssue({
|
|
598
|
-
code:
|
|
642
|
+
code: z14.ZodIssueCode.custom,
|
|
599
643
|
message: "At most one `date_bucket` entry is allowed in `groupBy`.",
|
|
600
644
|
path: ["groupBy"]
|
|
601
645
|
});
|
|
@@ -603,7 +647,7 @@ var MetricsQuerySchema = z13.discriminatedUnion("resource", [
|
|
|
603
647
|
input.metrics.forEach((metric, index) => {
|
|
604
648
|
if (metric.aggregation !== "count" && metric.field === void 0) {
|
|
605
649
|
ctx.addIssue({
|
|
606
|
-
code:
|
|
650
|
+
code: z14.ZodIssueCode.custom,
|
|
607
651
|
message: "`field` is required unless `aggregation` is `count`.",
|
|
608
652
|
path: ["metrics", index, "field"]
|
|
609
653
|
});
|
|
@@ -612,7 +656,7 @@ var MetricsQuerySchema = z13.discriminatedUnion("resource", [
|
|
|
612
656
|
const aliases = input.metrics.map((metric) => metric.alias).filter((alias) => alias !== void 0);
|
|
613
657
|
if (new Set(aliases).size !== aliases.length) {
|
|
614
658
|
ctx.addIssue({
|
|
615
|
-
code:
|
|
659
|
+
code: z14.ZodIssueCode.custom,
|
|
616
660
|
message: "Every `metrics[].alias` must be unique.",
|
|
617
661
|
path: ["metrics"]
|
|
618
662
|
});
|
|
@@ -621,32 +665,32 @@ var MetricsQuerySchema = z13.discriminatedUnion("resource", [
|
|
|
621
665
|
input.metrics.forEach((metric, index) => {
|
|
622
666
|
if (metric.alias !== void 0 && reservedNames.has(metric.alias)) {
|
|
623
667
|
ctx.addIssue({
|
|
624
|
-
code:
|
|
668
|
+
code: z14.ZodIssueCode.custom,
|
|
625
669
|
message: `\`alias\` "${metric.alias}" collides with a \`groupBy\` field name (or the reserved word "bucket") \u2014 choose a different alias.`,
|
|
626
670
|
path: ["metrics", index, "alias"]
|
|
627
671
|
});
|
|
628
672
|
}
|
|
629
673
|
});
|
|
630
674
|
});
|
|
631
|
-
var MetricsQueryResultRowSchema =
|
|
632
|
-
|
|
633
|
-
|
|
675
|
+
var MetricsQueryResultRowSchema = z14.record(
|
|
676
|
+
z14.string(),
|
|
677
|
+
z14.union([z14.string(), z14.number(), z14.boolean(), z14.null()])
|
|
634
678
|
);
|
|
635
|
-
var MetricsQueryResultSchema =
|
|
636
|
-
data:
|
|
637
|
-
meta:
|
|
679
|
+
var MetricsQueryResultSchema = z14.object({
|
|
680
|
+
data: z14.array(MetricsQueryResultRowSchema),
|
|
681
|
+
meta: z14.object({
|
|
638
682
|
resource: MetricsResourceSchema,
|
|
639
683
|
environment: EnvironmentSchema,
|
|
640
|
-
rowCount:
|
|
641
|
-
truncated:
|
|
684
|
+
rowCount: z14.number().int().describe("Number of rows in `data`."),
|
|
685
|
+
truncated: z14.boolean().describe(
|
|
642
686
|
"`true` if more rows matched than `limit` allowed \u2014 `data` holds only the first `limit`."
|
|
643
687
|
)
|
|
644
688
|
})
|
|
645
689
|
});
|
|
646
690
|
|
|
647
691
|
// src/webhook-events.ts
|
|
648
|
-
import { z as
|
|
649
|
-
var ChargeWebhookEventTypeSchema =
|
|
692
|
+
import { z as z15 } from "zod";
|
|
693
|
+
var ChargeWebhookEventTypeSchema = z15.enum([
|
|
650
694
|
"charge.created",
|
|
651
695
|
"charge.partially_paid",
|
|
652
696
|
"charge.confirmed",
|
|
@@ -655,18 +699,19 @@ var ChargeWebhookEventTypeSchema = z14.enum([
|
|
|
655
699
|
"charge.settled",
|
|
656
700
|
"charge.settlement_failed",
|
|
657
701
|
"charge.overpaid",
|
|
658
|
-
"charge.escrow_released"
|
|
702
|
+
"charge.escrow_released",
|
|
703
|
+
"charge.escrow_refunded"
|
|
659
704
|
]).describe(
|
|
660
|
-
'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. Every event in this category carries the full `Charge` object as `data`.'
|
|
705
|
+
'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`.'
|
|
661
706
|
);
|
|
662
|
-
var WebhookDeliveryEventTypeSchema =
|
|
707
|
+
var WebhookDeliveryEventTypeSchema = z15.enum(["webhook.delivery_failed", "webhook.delivery_recovered", "webhook.endpoint_unhealthy"]).describe(
|
|
663
708
|
"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`)."
|
|
664
709
|
);
|
|
665
|
-
var WebhookEventTypeSchema =
|
|
710
|
+
var WebhookEventTypeSchema = z15.union([
|
|
666
711
|
ChargeWebhookEventTypeSchema,
|
|
667
712
|
WebhookDeliveryEventTypeSchema
|
|
668
713
|
]);
|
|
669
|
-
var WebhookCategorySchema =
|
|
714
|
+
var WebhookCategorySchema = z15.enum(["payments", "webhooks"]).describe(
|
|
670
715
|
"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."
|
|
671
716
|
);
|
|
672
717
|
function buildCategoryMap() {
|
|
@@ -688,122 +733,127 @@ var WEBHOOK_EVENT_CATEGORIES = {
|
|
|
688
733
|
webhooks: WebhookDeliveryEventTypeSchema.options
|
|
689
734
|
};
|
|
690
735
|
var TriggerableChargeEventSchema = ChargeWebhookEventTypeSchema.exclude([
|
|
691
|
-
"charge.created"
|
|
736
|
+
"charge.created",
|
|
737
|
+
"charge.escrow_released",
|
|
738
|
+
"charge.escrow_refunded"
|
|
692
739
|
]).describe(
|
|
693
|
-
"Every charge event that represents a payment-progress state transition a sandbox charge can be pushed into \u2014 everything except `charge.created` (a charge already exists by the time you have an id to trigger against)."
|
|
740
|
+
"Every charge event that represents a payment-progress state transition a sandbox charge can be pushed into \u2014 everything except `charge.created` (a charge already exists by the time you have an id to trigger against) and the two escrow-terminal events, which are reached by actually calling `POST /v1/charges/{id}/release` or `POST /v1/charges/{id}/refund` on a test-environment escrow charge (a real Safe transaction on that network's testnet), not this generic trigger."
|
|
694
741
|
);
|
|
695
742
|
|
|
696
743
|
// src/webhooks.ts
|
|
697
|
-
import { z as
|
|
744
|
+
import { z as z16 } from "zod";
|
|
698
745
|
var WEBHOOK_EVENTS_WILDCARD = "*";
|
|
699
|
-
var CreateWebhookSchema =
|
|
700
|
-
url:
|
|
746
|
+
var CreateWebhookSchema = z16.object({
|
|
747
|
+
url: z16.string().max(2048).url().describe(
|
|
701
748
|
"Must be HTTPS and resolve to a public address \u2014 private/internal IPs are rejected."
|
|
702
749
|
),
|
|
703
|
-
events:
|
|
750
|
+
events: z16.array(z16.union([WebhookEventTypeSchema, z16.literal(WEBHOOK_EVENTS_WILDCARD)])).max(Object.keys(EVENT_CATEGORY_MAP).length + 1).default([]).describe(
|
|
704
751
|
'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.'
|
|
705
752
|
),
|
|
706
|
-
eventCategories:
|
|
753
|
+
eventCategories: z16.array(WebhookCategorySchema).max(WebhookCategorySchema.options.length).default([]).describe(
|
|
707
754
|
"Subscribe to every event in these categories. At least one of `events` or `eventCategories` is required."
|
|
708
755
|
),
|
|
709
|
-
excludeEvents:
|
|
756
|
+
excludeEvents: z16.array(WebhookEventTypeSchema).max(Object.keys(EVENT_CATEGORY_MAP).length).default([]).describe(
|
|
710
757
|
'Event types to exclude even if selected via `events: ["*"]` or `eventCategories`.'
|
|
711
758
|
)
|
|
712
759
|
}).refine((v) => v.events.length > 0 || v.eventCategories.length > 0, {
|
|
713
760
|
message: "must select at least one event via `events` or `eventCategories`",
|
|
714
761
|
path: ["events"]
|
|
715
762
|
});
|
|
716
|
-
var WebhookSchema =
|
|
717
|
-
id:
|
|
763
|
+
var WebhookSchema = z16.object({
|
|
764
|
+
id: z16.string(),
|
|
718
765
|
environment: EnvironmentSchema.nullable().describe(
|
|
719
766
|
"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)."
|
|
720
767
|
),
|
|
721
|
-
url:
|
|
722
|
-
events:
|
|
723
|
-
eventCategories:
|
|
724
|
-
excludeEvents:
|
|
725
|
-
isWildcard:
|
|
726
|
-
secret:
|
|
768
|
+
url: z16.string(),
|
|
769
|
+
events: z16.array(WebhookEventTypeSchema),
|
|
770
|
+
eventCategories: z16.array(WebhookCategorySchema),
|
|
771
|
+
excludeEvents: z16.array(WebhookEventTypeSchema),
|
|
772
|
+
isWildcard: z16.boolean(),
|
|
773
|
+
secret: z16.string().describe(
|
|
727
774
|
"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."
|
|
728
775
|
),
|
|
729
|
-
createdAt:
|
|
776
|
+
createdAt: z16.string().datetime()
|
|
730
777
|
});
|
|
731
778
|
var WebhookListItemSchema = WebhookSchema.omit({ secret: true }).extend({
|
|
732
|
-
hint:
|
|
779
|
+
hint: z16.string().describe("A truncated, safe-to-display form of the secret (e.g. `whsec_...ab12`).")
|
|
733
780
|
});
|
|
734
|
-
var WebhookPayloadSchema =
|
|
735
|
-
id:
|
|
781
|
+
var WebhookPayloadSchema = z16.object({
|
|
782
|
+
id: z16.string().describe(
|
|
736
783
|
"Unique id for this specific delivery \u2014 also sent as the `X-Klappay-Delivery` header."
|
|
737
784
|
),
|
|
738
785
|
event: WebhookEventTypeSchema,
|
|
739
|
-
createdAt:
|
|
740
|
-
data:
|
|
786
|
+
createdAt: z16.string().datetime(),
|
|
787
|
+
data: z16.unknown().describe(
|
|
741
788
|
"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."
|
|
742
789
|
)
|
|
743
790
|
});
|
|
744
|
-
var WebhookDeliveryStatusSchema =
|
|
745
|
-
var WebhookDeliverySchema =
|
|
746
|
-
id:
|
|
747
|
-
webhookId:
|
|
791
|
+
var WebhookDeliveryStatusSchema = z16.enum(["pending", "delivered", "failed"]);
|
|
792
|
+
var WebhookDeliverySchema = z16.object({
|
|
793
|
+
id: z16.string(),
|
|
794
|
+
webhookId: z16.string(),
|
|
748
795
|
event: WebhookEventTypeSchema,
|
|
749
796
|
status: WebhookDeliveryStatusSchema.describe(
|
|
750
797
|
"`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."
|
|
751
798
|
),
|
|
752
|
-
attempts:
|
|
753
|
-
responseCode:
|
|
799
|
+
attempts: z16.number(),
|
|
800
|
+
responseCode: z16.number().nullable().describe(
|
|
754
801
|
"HTTP status your endpoint returned on the most recent attempt. `null` if every attempt failed to connect at all."
|
|
755
802
|
),
|
|
756
|
-
nextRetryAt:
|
|
757
|
-
deliveredAt:
|
|
758
|
-
createdAt:
|
|
803
|
+
nextRetryAt: z16.string().datetime().nullable(),
|
|
804
|
+
deliveredAt: z16.string().datetime().nullable(),
|
|
805
|
+
createdAt: z16.string().datetime()
|
|
759
806
|
});
|
|
760
807
|
var ListWebhookDeliveriesSchema = PaginationQuerySchema;
|
|
761
808
|
var PaginatedWebhookDeliveriesSchema = paginatedSchema(WebhookDeliverySchema);
|
|
762
809
|
|
|
763
810
|
// src/recipients.ts
|
|
764
|
-
import { z as
|
|
811
|
+
import { z as z17 } from "zod";
|
|
765
812
|
var EVM_ADDRESS_REGEX = /^0x[0-9a-fA-F]{40}$/;
|
|
766
|
-
var CreateRecipientSchema =
|
|
767
|
-
address:
|
|
768
|
-
label:
|
|
813
|
+
var CreateRecipientSchema = z17.object({
|
|
814
|
+
address: z17.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."),
|
|
815
|
+
label: z17.string().min(1).max(64).optional().describe('Free-form label for your own bookkeeping (e.g. `"supplier"`) \u2014 never interpreted.')
|
|
769
816
|
});
|
|
770
|
-
var RecipientSchema =
|
|
771
|
-
id:
|
|
817
|
+
var RecipientSchema = z17.object({
|
|
818
|
+
id: z17.string().describe(
|
|
772
819
|
"Klappay-generated id, e.g. `rc_...` \u2014 this, not the raw address, is what a charge's `splitRecipients[].recipientId` references."
|
|
773
820
|
),
|
|
774
821
|
environment: EnvironmentSchema,
|
|
775
|
-
address:
|
|
776
|
-
label:
|
|
777
|
-
payout:
|
|
822
|
+
address: z17.string(),
|
|
823
|
+
label: z17.string().nullable(),
|
|
824
|
+
payout: z17.boolean().describe(
|
|
778
825
|
"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`."
|
|
779
826
|
),
|
|
780
|
-
createdAt:
|
|
827
|
+
createdAt: z17.string().datetime()
|
|
781
828
|
});
|
|
782
|
-
var SetRecipientPayoutSchema =
|
|
783
|
-
payout:
|
|
829
|
+
var SetRecipientPayoutSchema = z17.object({
|
|
830
|
+
payout: z17.boolean().describe("New payout-eligibility value for this recipient.")
|
|
784
831
|
});
|
|
785
832
|
|
|
786
833
|
// src/timeline.ts
|
|
787
|
-
import { z as
|
|
788
|
-
var TransactionSourceSchema =
|
|
834
|
+
import { z as z18 } from "zod";
|
|
835
|
+
var TransactionSourceSchema = z18.enum(["moralis_webhook", "reconciliation_job", "sandbox"]).describe(
|
|
789
836
|
"How this transfer was detected: `moralis_webhook` (the normal path), `reconciliation_job` (a fallback poller caught it after the webhook was missed or delayed), or `sandbox` (simulated via `POST /v1/sandbox/charges/{id}/trigger`, no real on-chain transfer)."
|
|
790
837
|
);
|
|
791
|
-
var TimelineEventTypeSchema =
|
|
838
|
+
var TimelineEventTypeSchema = z18.enum([
|
|
792
839
|
"charge.created",
|
|
793
840
|
"charge.expired",
|
|
794
841
|
"transaction.detected",
|
|
795
842
|
"split.distributed",
|
|
796
843
|
"webhook.dispatched",
|
|
797
844
|
"webhook.delivered",
|
|
798
|
-
"webhook.failed"
|
|
845
|
+
"webhook.failed",
|
|
846
|
+
"transfer.reclaimed"
|
|
799
847
|
]).describe(
|
|
800
|
-
"`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)."
|
|
848
|
+
"`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."
|
|
801
849
|
);
|
|
802
|
-
var TimelineEventSchema =
|
|
850
|
+
var TimelineEventSchema = z18.object({
|
|
803
851
|
type: TimelineEventTypeSchema,
|
|
804
|
-
at:
|
|
805
|
-
txHash:
|
|
806
|
-
|
|
852
|
+
at: z18.string().datetime(),
|
|
853
|
+
txHash: z18.string().optional().describe(
|
|
854
|
+
"Present for `transaction.detected`, `split.distributed`, and `transfer.reclaimed` events only."
|
|
855
|
+
),
|
|
856
|
+
amount: z18.number().optional().describe(
|
|
807
857
|
"Present for `transaction.detected` events only \u2014 the amount that specific transfer carried."
|
|
808
858
|
),
|
|
809
859
|
source: TransactionSourceSchema.optional().describe(
|
|
@@ -815,102 +865,102 @@ var TimelineEventSchema = z17.object({
|
|
|
815
865
|
network: NetworkSchema.optional().describe(
|
|
816
866
|
"Present for `transaction.detected` and `split.distributed` events \u2014 which network this specific transfer, or settlement, used."
|
|
817
867
|
),
|
|
818
|
-
causedTransition:
|
|
868
|
+
causedTransition: z18.boolean().optional().describe(
|
|
819
869
|
"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."
|
|
820
870
|
),
|
|
821
871
|
event: WebhookEventTypeSchema.optional().describe(
|
|
822
872
|
"Present for `webhook.*` events only \u2014 which event type this delivery was for."
|
|
823
873
|
),
|
|
824
|
-
responseCode:
|
|
874
|
+
responseCode: z18.number().nullable().optional().describe(
|
|
825
875
|
"Present for `webhook.*` events only \u2014 HTTP status your endpoint returned, or `null` if the request never connected."
|
|
826
876
|
),
|
|
827
|
-
attempts:
|
|
877
|
+
attempts: z18.number().optional().describe(
|
|
828
878
|
"Present for `webhook.*` events only \u2014 how many delivery attempts have been made so far."
|
|
829
879
|
)
|
|
830
880
|
});
|
|
831
881
|
|
|
832
882
|
// src/health.ts
|
|
833
|
-
import { z as
|
|
834
|
-
var HealthSchema =
|
|
835
|
-
status:
|
|
883
|
+
import { z as z19 } from "zod";
|
|
884
|
+
var HealthSchema = z19.object({
|
|
885
|
+
status: z19.enum(["ok", "error"]).describe(
|
|
836
886
|
"`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."
|
|
837
887
|
),
|
|
838
|
-
version:
|
|
839
|
-
timestamp:
|
|
840
|
-
db:
|
|
841
|
-
pendingWebhooks:
|
|
842
|
-
oldestPendingChargeAgeSeconds:
|
|
843
|
-
lastMoralisEventAgeSeconds:
|
|
888
|
+
version: z19.string(),
|
|
889
|
+
timestamp: z19.string().datetime(),
|
|
890
|
+
db: z19.enum(["ok", "error"]).describe("Result of a real database connectivity check, not just a process-alive check."),
|
|
891
|
+
pendingWebhooks: z19.number().describe("Count of webhook deliveries still awaiting a successful attempt."),
|
|
892
|
+
oldestPendingChargeAgeSeconds: z19.number().nullable().describe("Age of the oldest still-unpaid charge, in seconds. `null` if there are none."),
|
|
893
|
+
lastMoralisEventAgeSeconds: z19.number().nullable().describe(
|
|
844
894
|
"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."
|
|
845
895
|
)
|
|
846
896
|
});
|
|
847
897
|
|
|
848
898
|
// src/sandbox.ts
|
|
849
|
-
import { z as
|
|
850
|
-
var SandboxTriggerSchema =
|
|
899
|
+
import { z as z20 } from "zod";
|
|
900
|
+
var SandboxTriggerSchema = z20.object({
|
|
851
901
|
event: TriggerableChargeEventSchema,
|
|
852
|
-
amount:
|
|
902
|
+
amount: z20.number().positive().max(CHARGE_AMOUNT_MAX).optional().describe(
|
|
853
903
|
"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."
|
|
854
904
|
)
|
|
855
905
|
});
|
|
856
906
|
|
|
857
907
|
// src/capabilities.ts
|
|
858
|
-
import { z as
|
|
859
|
-
var CapabilitiesSchema =
|
|
860
|
-
acceptedPayments:
|
|
908
|
+
import { z as z21 } from "zod";
|
|
909
|
+
var CapabilitiesSchema = z21.object({
|
|
910
|
+
acceptedPayments: z21.array(AcceptedPaymentSchema).describe(
|
|
861
911
|
"Every `(token, network)` pair actually configured for your environment right now \u2014 read straight from the same lookup `POST /v1/charges` validates `acceptedPayments` against, so it can never list a pair that charge creation would then reject. Use this to build a picker UI instead of hardcoding the matrix client-side."
|
|
862
912
|
)
|
|
863
913
|
});
|
|
864
914
|
|
|
865
915
|
// src/swap.ts
|
|
866
|
-
import { z as
|
|
867
|
-
var CreateSwapQuoteSchema =
|
|
916
|
+
import { z as z22 } from "zod";
|
|
917
|
+
var CreateSwapQuoteSchema = z22.object({
|
|
868
918
|
inputToken: AltTokenSchema.describe(
|
|
869
919
|
"Which alt-cryptocurrency the payer wants to send \u2014 must be one of this charge's `swapAlternatives`, or `422 token_not_supported`."
|
|
870
920
|
),
|
|
871
921
|
inputNetwork: NetworkSchema.describe(
|
|
872
922
|
"Which network the payer will send `inputToken` on. Also picks which of this charge's `acceptedPayments` pairs the swap resolves to \u2014 a charge accepting USDC on both Base and Optimism resolves to whichever `inputNetwork` you pass. If the charge accepts more than one token on that same network, Klappay breaks the tie using its own trust ranking for that network (e.g. USDT over USDC on BNB Chain, where \"USDC\" is a third-party Binance-Peg token, not Circle's) \u2014 never a token the charge doesn't actually accept."
|
|
873
923
|
),
|
|
874
|
-
takerAddress:
|
|
924
|
+
takerAddress: z22.string().regex(/^0x[0-9a-fA-F]{40}$/, "must be a 20-byte hex address").describe(
|
|
875
925
|
"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."
|
|
876
926
|
)
|
|
877
927
|
});
|
|
878
|
-
var SwapQuoteSchema =
|
|
928
|
+
var SwapQuoteSchema = z22.object({
|
|
879
929
|
inputToken: AltTokenSchema,
|
|
880
930
|
inputNetwork: NetworkSchema,
|
|
881
|
-
inputAmount:
|
|
931
|
+
inputAmount: z22.number().describe(
|
|
882
932
|
"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."
|
|
883
933
|
),
|
|
884
934
|
outputToken: TokenSchema.describe(
|
|
885
935
|
"Which of this charge's `acceptedPayments` tokens the swap resolves to."
|
|
886
936
|
),
|
|
887
937
|
outputNetwork: NetworkSchema,
|
|
888
|
-
outputAmount:
|
|
938
|
+
outputAmount: z22.number().describe(
|
|
889
939
|
"The exact remaining amount owed on this charge (`amount - amountReceived`), in `currency` units \u2014 always what the merchant's split address receives, regardless of `inputAmount`."
|
|
890
940
|
),
|
|
891
|
-
fees:
|
|
892
|
-
klappayFee:
|
|
941
|
+
fees: z22.object({
|
|
942
|
+
klappayFee: z22.number().describe(
|
|
893
943
|
"Klappay's own swap fee (1% today), in `outputToken` units \u2014 paid by the payer, on top of `inputAmount`, separate from the merchant's own `feePercent`. Never subtracted from `outputAmount`."
|
|
894
944
|
),
|
|
895
|
-
zeroExFee:
|
|
945
|
+
zeroExFee: z22.number().nullable().describe(
|
|
896
946
|
"0x's own protocol fee for this specific token pair, in `outputToken` units, or `null` when this pair isn't currently one 0x charges on. Also paid by the payer on top of `inputAmount`, also never subtracted from `outputAmount` \u2014 Klappay never sees this fee, it goes straight to 0x."
|
|
897
947
|
)
|
|
898
948
|
}).describe(
|
|
899
949
|
"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`."
|
|
900
950
|
),
|
|
901
|
-
expiresAt:
|
|
951
|
+
expiresAt: z22.string().datetime().describe(
|
|
902
952
|
"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."
|
|
903
953
|
),
|
|
904
|
-
transaction:
|
|
905
|
-
to:
|
|
906
|
-
data:
|
|
907
|
-
value:
|
|
954
|
+
transaction: z22.object({
|
|
955
|
+
to: z22.string().describe("Contract address the payer's wallet must send this transaction to."),
|
|
956
|
+
data: z22.string().describe("Calldata \u2014 opaque, must be sent unmodified."),
|
|
957
|
+
value: z22.string().describe(
|
|
908
958
|
"Native currency (ETH/BNB/MATIC/AVAX) to attach, in wei \u2014 `\"0\"` when `inputToken` isn't this network's native currency."
|
|
909
959
|
)
|
|
910
960
|
}).describe(
|
|
911
961
|
"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."
|
|
912
962
|
),
|
|
913
|
-
permit2:
|
|
963
|
+
permit2: z22.object({ eip712: z22.record(z22.unknown()) }).nullish().describe(
|
|
914
964
|
"Present only when `inputToken` is an ERC-20 (today, only `BTC`) \u2014 the payer's wallet must sign this EIP-712 message and append the signature to `transaction.data` before sending, since an ERC-20 sell needs a Permit2 allowance signature that a native-currency sell doesn't. `null` (never omitted, in a genuine 0x-backed quote) when `inputToken` is a network's own native currency (ETH/BNB/MATIC/AVAX) \u2014 `transaction` is then ready to sign and send directly, no extra step."
|
|
915
965
|
)
|
|
916
966
|
});
|
|
@@ -930,6 +980,7 @@ export {
|
|
|
930
980
|
CHECKOUT_PRODUCTS_MAX,
|
|
931
981
|
CONFLICTING_SCOPE_PAIRS,
|
|
932
982
|
CapabilitiesSchema,
|
|
983
|
+
ChargeFeePayerSchema,
|
|
933
984
|
ChargeSchema,
|
|
934
985
|
ChargeStatusSchema,
|
|
935
986
|
ChargeWebhookEventTypeSchema,
|
|
@@ -939,6 +990,7 @@ export {
|
|
|
939
990
|
CheckChargeRequestSchema,
|
|
940
991
|
CheckChargeResponseSchema,
|
|
941
992
|
CheckoutProductSchema,
|
|
993
|
+
ConfirmationProgressSchema,
|
|
942
994
|
CreateChargeSchema,
|
|
943
995
|
CreateRecipientSchema,
|
|
944
996
|
CreateSwapQuoteSchema,
|
|
@@ -986,6 +1038,7 @@ export {
|
|
|
986
1038
|
PendingDistributionRecipientSchema,
|
|
987
1039
|
PendingDistributionSchema,
|
|
988
1040
|
RecipientSchema,
|
|
1041
|
+
RefundEscrowRequestSchema,
|
|
989
1042
|
ReleaseEscrowRequestSchema,
|
|
990
1043
|
SandboxTriggerSchema,
|
|
991
1044
|
SetRecipientPayoutSchema,
|