@klappay/types 4.0.0 → 5.0.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 +20 -2
- package/dist/chunk-VTX32VJN.mjs +168 -0
- package/dist/chunk-VTX32VJN.mjs.map +1 -0
- package/dist/{constants-DQGVNS9O.d.mts → constants-Di4Qr6af.d.mts} +16 -7
- package/dist/{constants-DQGVNS9O.d.ts → constants-Di4Qr6af.d.ts} +16 -7
- package/dist/constants.d.mts +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +90 -28
- package/dist/constants.js.map +1 -1
- package/dist/constants.mjs +9 -3
- package/dist/index.d.mts +73 -24
- package/dist/index.d.ts +73 -24
- package/dist/index.js +384 -295
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +304 -271
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-KZ3646WX.mjs +0 -109
- package/dist/chunk-KZ3646WX.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -105,6 +105,7 @@ __export(index_exports, {
|
|
|
105
105
|
SwapQuoteSchema: () => SwapQuoteSchema,
|
|
106
106
|
TOKEN_ADDRESSES: () => TOKEN_ADDRESSES,
|
|
107
107
|
TOKEN_DECIMALS: () => TOKEN_DECIMALS,
|
|
108
|
+
TOKEN_DEPLOYMENTS: () => TOKEN_DEPLOYMENTS,
|
|
108
109
|
TimelineEventSchema: () => TimelineEventSchema,
|
|
109
110
|
TimelineEventTypeSchema: () => TimelineEventTypeSchema,
|
|
110
111
|
TokenSchema: () => TokenSchema,
|
|
@@ -124,6 +125,8 @@ __export(index_exports, {
|
|
|
124
125
|
WebhookPayloadSchema: () => WebhookPayloadSchema,
|
|
125
126
|
WebhookSchema: () => WebhookSchema,
|
|
126
127
|
findConflictingScopes: () => findConflictingScopes,
|
|
128
|
+
getTokenDeployment: () => getTokenDeployment,
|
|
129
|
+
isPaymentDeploymentEnabled: () => isPaymentDeploymentEnabled,
|
|
127
130
|
listSwapAlternatives: () => listSwapAlternatives,
|
|
128
131
|
paginatedSchema: () => paginatedSchema
|
|
129
132
|
});
|
|
@@ -146,7 +149,7 @@ var ErrorPayloadSchema = import_zod.z.object({
|
|
|
146
149
|
// src/environment.ts
|
|
147
150
|
var import_zod2 = require("zod");
|
|
148
151
|
var EnvironmentSchema = import_zod2.z.enum(["live", "test"]).describe(
|
|
149
|
-
"`live` or `test`, matching the `klap_live_.../klap_test_...` prefix of the API key that created or is scoped to this resource. `live`
|
|
152
|
+
"`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."
|
|
150
153
|
);
|
|
151
154
|
|
|
152
155
|
// src/api-key-scopes.ts
|
|
@@ -261,39 +264,64 @@ var import_zod6 = require("zod");
|
|
|
261
264
|
|
|
262
265
|
// src/tokens.constants.ts
|
|
263
266
|
var TOKEN_DECIMALS = 6;
|
|
264
|
-
var
|
|
267
|
+
var TOKEN_DEPLOYMENTS = {
|
|
265
268
|
USDC: {
|
|
266
269
|
base: {
|
|
267
|
-
live: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
268
|
-
test: "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
|
|
270
|
+
live: { address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", decimals: 6 },
|
|
271
|
+
test: { address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", decimals: 6 }
|
|
269
272
|
},
|
|
270
273
|
optimism: {
|
|
271
|
-
live: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
|
|
272
|
-
test: "0x5fd84259d66Cd46123540766Be93DFE6D43130D7"
|
|
274
|
+
live: { address: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85", decimals: 6 },
|
|
275
|
+
test: { address: "0x5fd84259d66Cd46123540766Be93DFE6D43130D7", decimals: 6 }
|
|
273
276
|
},
|
|
274
|
-
polygon: { live: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359" },
|
|
277
|
+
polygon: { live: { address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", decimals: 6 } },
|
|
275
278
|
ethereum: {
|
|
276
|
-
live: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
277
|
-
test: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"
|
|
279
|
+
live: { address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", decimals: 6 },
|
|
280
|
+
test: { address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238", decimals: 6 }
|
|
278
281
|
},
|
|
279
|
-
arbitrum: { live: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831" },
|
|
280
|
-
avalanche: { live: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E" },
|
|
281
|
-
bnb: { live: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d" }
|
|
282
|
+
arbitrum: { live: { address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", decimals: 6 } },
|
|
283
|
+
avalanche: { live: { address: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E", decimals: 6 } },
|
|
284
|
+
bnb: { live: { address: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d", decimals: 18 } }
|
|
282
285
|
},
|
|
283
286
|
USDT: {
|
|
284
|
-
base: { live: "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2" },
|
|
285
|
-
optimism: { live: "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58" },
|
|
286
|
-
polygon: { live: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F" },
|
|
287
|
-
ethereum: { live: "0xdAC17F958D2ee523a2206206994597C13D831ec7" },
|
|
288
|
-
arbitrum: { live: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9" },
|
|
289
|
-
avalanche: { live: "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7" },
|
|
290
|
-
bnb: { live: "0x55d398326f99059fF775485246999027B3197955" }
|
|
287
|
+
base: { live: { address: "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2", decimals: 6 } },
|
|
288
|
+
optimism: { live: { address: "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58", decimals: 6 } },
|
|
289
|
+
polygon: { live: { address: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F", decimals: 6 } },
|
|
290
|
+
ethereum: { live: { address: "0xdAC17F958D2ee523a2206206994597C13D831ec7", decimals: 6 } },
|
|
291
|
+
arbitrum: { live: { address: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9", decimals: 6 } },
|
|
292
|
+
avalanche: { live: { address: "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7", decimals: 6 } },
|
|
293
|
+
bnb: { live: { address: "0x55d398326f99059fF775485246999027B3197955", decimals: 18 } }
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
function getTokenDeployment(token, network, environment) {
|
|
297
|
+
return TOKEN_DEPLOYMENTS[token][network]?.[environment];
|
|
298
|
+
}
|
|
299
|
+
function isPaymentDeploymentEnabled(token, network, environment) {
|
|
300
|
+
if (network === "bnb" && environment === "live") return false;
|
|
301
|
+
return getTokenDeployment(token, network, environment) !== void 0;
|
|
302
|
+
}
|
|
303
|
+
function deriveAddresses(deployments) {
|
|
304
|
+
const addresses = {};
|
|
305
|
+
for (const network of EVM_NETWORKS) {
|
|
306
|
+
const byEnvironment = deployments[network];
|
|
307
|
+
if (!byEnvironment) continue;
|
|
308
|
+
const networkAddresses = {};
|
|
309
|
+
for (const environment of ["live", "test"]) {
|
|
310
|
+
const deployment = byEnvironment[environment];
|
|
311
|
+
if (deployment) networkAddresses[environment] = deployment.address;
|
|
312
|
+
}
|
|
313
|
+
addresses[network] = networkAddresses;
|
|
291
314
|
}
|
|
315
|
+
return addresses;
|
|
316
|
+
}
|
|
317
|
+
var TOKEN_ADDRESSES = {
|
|
318
|
+
USDC: deriveAddresses(TOKEN_DEPLOYMENTS.USDC),
|
|
319
|
+
USDT: deriveAddresses(TOKEN_DEPLOYMENTS.USDT)
|
|
292
320
|
};
|
|
293
321
|
|
|
294
322
|
// src/tokens.ts
|
|
295
323
|
var TokenSchema = import_zod6.z.enum(["USDC", "USDT"]).describe(
|
|
296
|
-
|
|
324
|
+
"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."
|
|
297
325
|
);
|
|
298
326
|
|
|
299
327
|
// src/alt-tokens.ts
|
|
@@ -303,23 +331,54 @@ var import_zod7 = require("zod");
|
|
|
303
331
|
var ALT_TOKEN_DECIMALS = {
|
|
304
332
|
ETH: 18,
|
|
305
333
|
BNB: 18,
|
|
306
|
-
|
|
334
|
+
POL: 18,
|
|
307
335
|
AVAX: 18,
|
|
308
|
-
BTC: 8
|
|
336
|
+
BTC: 8,
|
|
337
|
+
LINK: 18,
|
|
338
|
+
ARB: 18,
|
|
339
|
+
OP: 18,
|
|
340
|
+
CBETH: 18
|
|
309
341
|
};
|
|
310
342
|
var ALT_TOKEN_ADDRESSES = {
|
|
311
|
-
base: {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
343
|
+
base: {
|
|
344
|
+
ETH: "native",
|
|
345
|
+
BTC: "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf",
|
|
346
|
+
LINK: "0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196",
|
|
347
|
+
CBETH: "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22"
|
|
348
|
+
},
|
|
349
|
+
optimism: {
|
|
350
|
+
ETH: "native",
|
|
351
|
+
BTC: "0x68f180fcCe6836688e9084f035309E29Bf0A2095",
|
|
352
|
+
LINK: "0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6",
|
|
353
|
+
OP: "0x4200000000000000000000000000000000000042"
|
|
354
|
+
},
|
|
355
|
+
ethereum: {
|
|
356
|
+
ETH: "native",
|
|
357
|
+
BTC: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
|
|
358
|
+
LINK: "0x514910771AF9Ca656af840dff83E8264EcF986CA"
|
|
359
|
+
},
|
|
360
|
+
arbitrum: {
|
|
361
|
+
ETH: "native",
|
|
362
|
+
BTC: "0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f",
|
|
363
|
+
LINK: "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4",
|
|
364
|
+
ARB: "0x912CE59144191C1204E64559FE8253a0e49E6548"
|
|
365
|
+
},
|
|
366
|
+
polygon: {
|
|
367
|
+
POL: "native",
|
|
368
|
+
BTC: "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6",
|
|
369
|
+
LINK: "0xb0897686c545045aFc77CF20eC7A532E3120E0F1"
|
|
370
|
+
},
|
|
371
|
+
avalanche: {
|
|
372
|
+
AVAX: "native",
|
|
373
|
+
BTC: "0x2297aebd383787a160dd0d9f71508148769342e3",
|
|
374
|
+
LINK: "0x5947BB275c521040051D82396192181b413227A3"
|
|
375
|
+
},
|
|
317
376
|
bnb: { BNB: "native" }
|
|
318
377
|
};
|
|
319
378
|
|
|
320
379
|
// src/alt-tokens.ts
|
|
321
|
-
var AltTokenSchema = import_zod7.z.enum(["ETH", "BNB", "
|
|
322
|
-
"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.
|
|
380
|
+
var AltTokenSchema = import_zod7.z.enum(["ETH", "BNB", "POL", "AVAX", "BTC", "LINK", "ARB", "OP", "CBETH"]).describe(
|
|
381
|
+
"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."
|
|
323
382
|
);
|
|
324
383
|
var SwapAlternativeSchema = import_zod7.z.object({
|
|
325
384
|
token: AltTokenSchema,
|
|
@@ -338,7 +397,7 @@ function listSwapAlternatives(networks) {
|
|
|
338
397
|
}
|
|
339
398
|
|
|
340
399
|
// src/charges.ts
|
|
341
|
-
var
|
|
400
|
+
var import_zod11 = require("zod");
|
|
342
401
|
|
|
343
402
|
// src/checkout-metadata.ts
|
|
344
403
|
var import_zod8 = require("zod");
|
|
@@ -379,38 +438,44 @@ var RefundEscrowRequestSchema = import_zod9.z.object({
|
|
|
379
438
|
)
|
|
380
439
|
});
|
|
381
440
|
|
|
441
|
+
// src/exact-amount.ts
|
|
442
|
+
var import_zod10 = require("zod");
|
|
443
|
+
var ExactAmountSchema = import_zod10.z.string().regex(/^(0|[1-9]\d*)(?:\.\d{1,18})?$(?!\s)/).describe(
|
|
444
|
+
"Nonnegative amount in whole currency/token units, as a decimal string with at most 18 fractional digits and no scientific notation."
|
|
445
|
+
);
|
|
446
|
+
|
|
382
447
|
// src/charges.ts
|
|
383
|
-
var ChargeStatusSchema =
|
|
448
|
+
var ChargeStatusSchema = import_zod11.z.enum(["pending", "partially_paid", "confirmed", "expired", "underpaid"]).describe(
|
|
384
449
|
"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."
|
|
385
450
|
);
|
|
386
|
-
var SettlementStatusSchema =
|
|
451
|
+
var SettlementStatusSchema = import_zod11.z.enum(["pending", "completed", "failed"]).describe(
|
|
387
452
|
"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."
|
|
388
453
|
);
|
|
389
|
-
var ChargeFeePayerSchema =
|
|
454
|
+
var ChargeFeePayerSchema = import_zod11.z.enum(["merchant", "payer"]).describe(
|
|
390
455
|
"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."
|
|
391
456
|
);
|
|
392
457
|
var CHARGE_EXPIRES_IN_MIN_SECONDS = 60;
|
|
393
458
|
var CHARGE_EXPIRES_IN_MAX_SECONDS = 3600;
|
|
394
459
|
var CHARGE_ACCEPTED_PAYMENTS_MAX = 14;
|
|
395
|
-
var AcceptedPaymentSchema =
|
|
460
|
+
var AcceptedPaymentSchema = import_zod11.z.object({
|
|
396
461
|
token: TokenSchema,
|
|
397
462
|
network: NetworkSchema
|
|
398
463
|
});
|
|
399
|
-
var AcceptedPaymentsSchema =
|
|
464
|
+
var AcceptedPaymentsSchema = import_zod11.z.array(AcceptedPaymentSchema).min(1, "At least one accepted payment is required.").max(CHARGE_ACCEPTED_PAYMENTS_MAX).superRefine((pairs, ctx) => {
|
|
400
465
|
const seen = /* @__PURE__ */ new Set();
|
|
401
466
|
pairs.forEach((pair, index) => {
|
|
402
467
|
const key = `${pair.token}:${pair.network}`;
|
|
403
468
|
if (seen.has(key)) {
|
|
404
469
|
ctx.addIssue({
|
|
405
|
-
code:
|
|
470
|
+
code: import_zod11.z.ZodIssueCode.custom,
|
|
406
471
|
message: `Duplicate accepted payment: ${pair.token} on ${pair.network}.`,
|
|
407
472
|
path: [index]
|
|
408
473
|
});
|
|
409
474
|
}
|
|
410
475
|
seen.add(key);
|
|
411
|
-
if (!OPERATIONAL_NETWORKS.
|
|
476
|
+
if (!OPERATIONAL_NETWORKS.some((network) => network === pair.network)) {
|
|
412
477
|
ctx.addIssue({
|
|
413
|
-
code:
|
|
478
|
+
code: import_zod11.z.ZodIssueCode.custom,
|
|
414
479
|
message: `Network "${pair.network}" isn't live yet \u2014 only ${OPERATIONAL_NETWORKS.join(", ")} today.`,
|
|
415
480
|
path: [index, "network"]
|
|
416
481
|
});
|
|
@@ -420,32 +485,32 @@ var AcceptedPaymentsSchema = import_zod10.z.array(AcceptedPaymentSchema).min(1,
|
|
|
420
485
|
`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\`.`
|
|
421
486
|
);
|
|
422
487
|
var CHARGE_SPLIT_RECIPIENTS_MAX = 5;
|
|
423
|
-
var SplitRecipientSchema =
|
|
424
|
-
address:
|
|
425
|
-
percent:
|
|
488
|
+
var SplitRecipientSchema = import_zod11.z.object({
|
|
489
|
+
address: import_zod11.z.string().regex(/^0x[0-9a-fA-F]{40}$/, "must be a 20-byte hex address").describe("EVM address to send a slice of this charge to."),
|
|
490
|
+
percent: import_zod11.z.number().positive().max(100).describe(
|
|
426
491
|
"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."
|
|
427
492
|
),
|
|
428
|
-
label:
|
|
493
|
+
label: import_zod11.z.string().min(1).max(64).optional().describe(
|
|
429
494
|
'Free-form label for your own bookkeeping (e.g. `"supplier"`, `"sales rep"`) \u2014 echoed back unchanged, never interpreted by Klappay.'
|
|
430
495
|
)
|
|
431
496
|
});
|
|
432
|
-
var SplitRecipientInputSchema =
|
|
433
|
-
recipientId:
|
|
497
|
+
var SplitRecipientInputSchema = import_zod11.z.object({
|
|
498
|
+
recipientId: import_zod11.z.string().describe(
|
|
434
499
|
"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."
|
|
435
500
|
),
|
|
436
|
-
percent:
|
|
501
|
+
percent: import_zod11.z.number().positive().max(100).describe(
|
|
437
502
|
"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."
|
|
438
503
|
),
|
|
439
|
-
label:
|
|
504
|
+
label: import_zod11.z.string().min(1).max(64).optional().describe(
|
|
440
505
|
'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.'
|
|
441
506
|
)
|
|
442
507
|
});
|
|
443
|
-
var SplitRecipientsInputSchema =
|
|
508
|
+
var SplitRecipientsInputSchema = import_zod11.z.array(SplitRecipientInputSchema).max(CHARGE_SPLIT_RECIPIENTS_MAX).superRefine((recipients, ctx) => {
|
|
444
509
|
const seen = /* @__PURE__ */ new Set();
|
|
445
510
|
recipients.forEach((recipient, index) => {
|
|
446
511
|
if (seen.has(recipient.recipientId)) {
|
|
447
512
|
ctx.addIssue({
|
|
448
|
-
code:
|
|
513
|
+
code: import_zod11.z.ZodIssueCode.custom,
|
|
449
514
|
message: `Duplicate split recipientId: ${recipient.recipientId}.`,
|
|
450
515
|
path: [index, "recipientId"]
|
|
451
516
|
});
|
|
@@ -456,27 +521,27 @@ var SplitRecipientsInputSchema = import_zod10.z.array(SplitRecipientInputSchema)
|
|
|
456
521
|
`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\`.`
|
|
457
522
|
);
|
|
458
523
|
var CHARGE_AMOUNT_MAX = 999999999999;
|
|
459
|
-
var CreateChargeSchema =
|
|
460
|
-
amount:
|
|
524
|
+
var CreateChargeSchema = import_zod11.z.object({
|
|
525
|
+
amount: import_zod11.z.number().positive().max(CHARGE_AMOUNT_MAX).describe(
|
|
461
526
|
"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."
|
|
462
527
|
),
|
|
463
528
|
feePayer: ChargeFeePayerSchema.optional().default("merchant"),
|
|
464
|
-
currency:
|
|
529
|
+
currency: import_zod11.z.literal("USD").default("USD").describe("Always `USD` today \u2014 the only supported currency."),
|
|
465
530
|
acceptedPayments: AcceptedPaymentsSchema,
|
|
466
|
-
expiresIn:
|
|
531
|
+
expiresIn: import_zod11.z.number().int().min(CHARGE_EXPIRES_IN_MIN_SECONDS).max(CHARGE_EXPIRES_IN_MAX_SECONDS).describe(
|
|
467
532
|
"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."
|
|
468
533
|
),
|
|
469
|
-
idempotencyKey:
|
|
534
|
+
idempotencyKey: import_zod11.z.string().min(1).max(255).optional().describe(
|
|
470
535
|
"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."
|
|
471
536
|
),
|
|
472
|
-
externalRef:
|
|
537
|
+
externalRef: import_zod11.z.string().min(1).max(255).optional().describe(
|
|
473
538
|
"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."
|
|
474
539
|
),
|
|
475
|
-
source:
|
|
540
|
+
source: import_zod11.z.string().min(1).max(64).optional().describe(
|
|
476
541
|
'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.'
|
|
477
542
|
),
|
|
478
543
|
metadata: MetadataWithKlappaySchema.optional(),
|
|
479
|
-
redirectUrl:
|
|
544
|
+
redirectUrl: import_zod11.z.string().url().refine((value) => /^https?:\/\//.test(value), "must use http or https").optional().describe(
|
|
480
545
|
"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."
|
|
481
546
|
),
|
|
482
547
|
splitRecipients: SplitRecipientsInputSchema.optional(),
|
|
@@ -484,77 +549,86 @@ var CreateChargeSchema = import_zod10.z.object({
|
|
|
484
549
|
"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."
|
|
485
550
|
)
|
|
486
551
|
});
|
|
487
|
-
var ChargeSchema =
|
|
488
|
-
id:
|
|
489
|
-
amount:
|
|
490
|
-
"The
|
|
552
|
+
var ChargeSchema = import_zod11.z.object({
|
|
553
|
+
id: import_zod11.z.string().describe("Klappay-generated id, e.g. `ch_...`. Use this to look up the charge later."),
|
|
554
|
+
amount: import_zod11.z.number().describe(
|
|
555
|
+
"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."
|
|
556
|
+
),
|
|
557
|
+
amountExact: ExactAmountSchema.regex(/^(0|[1-9]\d*)(?:\.\d{1,6})?$/).optional().describe(
|
|
558
|
+
'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.'
|
|
491
559
|
),
|
|
492
560
|
feePayer: ChargeFeePayerSchema,
|
|
493
|
-
feePercent:
|
|
561
|
+
feePercent: import_zod11.z.number().describe(
|
|
494
562
|
"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."
|
|
495
563
|
),
|
|
496
|
-
feeAmount:
|
|
497
|
-
merchantAmount:
|
|
564
|
+
feeAmount: import_zod11.z.number().describe("`amount * feePercent / 100`, in `currency` units \u2014 Klappay's cut of this charge."),
|
|
565
|
+
merchantAmount: import_zod11.z.number().describe(
|
|
498
566
|
"`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)."
|
|
499
567
|
),
|
|
500
|
-
amountReceived:
|
|
501
|
-
"Cumulative amount
|
|
568
|
+
amountReceived: import_zod11.z.number().nullable().describe(
|
|
569
|
+
"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`."
|
|
570
|
+
),
|
|
571
|
+
amountReceivedExact: ExactAmountSchema.nullable().optional().describe(
|
|
572
|
+
'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.'
|
|
502
573
|
),
|
|
503
|
-
|
|
574
|
+
paymentUnavailable: import_zod11.z.boolean().optional().describe(
|
|
575
|
+
"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."
|
|
576
|
+
),
|
|
577
|
+
isOverpaid: import_zod11.z.boolean().describe(
|
|
504
578
|
"`true` if `amountReceived` ended up greater than `amount`. Klappay never refunds the difference automatically \u2014 see the docs for why."
|
|
505
579
|
),
|
|
506
|
-
currency:
|
|
507
|
-
acceptedPayments:
|
|
580
|
+
currency: import_zod11.z.string().describe("Always `USD` today \u2014 the only supported currency."),
|
|
581
|
+
acceptedPayments: import_zod11.z.array(AcceptedPaymentSchema).describe(
|
|
508
582
|
"Every `(token, network)` pair this charge was configured to accept, unchanged after creation."
|
|
509
583
|
),
|
|
510
|
-
paidWith:
|
|
584
|
+
paidWith: import_zod11.z.array(AcceptedPaymentSchema).describe(
|
|
511
585
|
"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`."
|
|
512
586
|
),
|
|
513
|
-
swapAlternatives:
|
|
587
|
+
swapAlternatives: import_zod11.z.array(SwapAlternativeSchema).describe(
|
|
514
588
|
"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`)."
|
|
515
589
|
),
|
|
516
|
-
address:
|
|
590
|
+
address: import_zod11.z.string().describe(
|
|
517
591
|
"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."
|
|
518
592
|
),
|
|
519
593
|
status: ChargeStatusSchema,
|
|
520
594
|
settlementStatus: SettlementStatusSchema.nullable(),
|
|
521
595
|
environment: EnvironmentSchema,
|
|
522
|
-
apiKeyId:
|
|
596
|
+
apiKeyId: import_zod11.z.string().nullable().describe(
|
|
523
597
|
"Which of your API keys created this charge. `null` for a charge created before this field existed."
|
|
524
598
|
),
|
|
525
|
-
txHash:
|
|
599
|
+
txHash: import_zod11.z.string().nullable().describe(
|
|
526
600
|
"Transaction hash of the most recent transfer detected for this charge. `null` until a payment is detected."
|
|
527
601
|
),
|
|
528
|
-
externalRef:
|
|
529
|
-
source:
|
|
602
|
+
externalRef: import_zod11.z.string().nullable(),
|
|
603
|
+
source: import_zod11.z.string().nullable(),
|
|
530
604
|
metadata: MetadataWithKlappaySchema.nullable(),
|
|
531
|
-
redirectUrl:
|
|
532
|
-
checkoutUrl:
|
|
605
|
+
redirectUrl: import_zod11.z.string().nullable().describe("Echoes the `redirectUrl` set at creation, if any. `null` if none was set."),
|
|
606
|
+
checkoutUrl: import_zod11.z.string().nullable().describe(
|
|
533
607
|
"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."
|
|
534
608
|
),
|
|
535
|
-
splitRecipients:
|
|
536
|
-
createdAt:
|
|
537
|
-
expiresAt:
|
|
609
|
+
splitRecipients: import_zod11.z.array(SplitRecipientSchema).describe("Echoes whatever extra split recipients were set at creation \u2014 empty array if none."),
|
|
610
|
+
createdAt: import_zod11.z.string().datetime(),
|
|
611
|
+
expiresAt: import_zod11.z.string().datetime().describe(
|
|
538
612
|
"When this charge stops accepting payment, if still `pending`/`partially_paid` by then."
|
|
539
613
|
),
|
|
540
|
-
confirmedAt:
|
|
541
|
-
settledAt:
|
|
614
|
+
confirmedAt: import_zod11.z.string().datetime().nullable().describe("When `status` first reached `confirmed`. `null` until then."),
|
|
615
|
+
settledAt: import_zod11.z.string().datetime().nullable().describe(
|
|
542
616
|
"When `settlementStatus` first reached `completed` \u2014 the merchant's wallet actually has the funds. `null` until then, including while `settlementStatus` is `pending`/`failed`."
|
|
543
617
|
),
|
|
544
|
-
lastActivityAt:
|
|
618
|
+
lastActivityAt: import_zod11.z.string().datetime().describe(
|
|
545
619
|
"When a transfer was last credited toward this charge, or `createdAt` if none has arrived yet."
|
|
546
620
|
),
|
|
547
|
-
escrow:
|
|
548
|
-
releaserAddress:
|
|
549
|
-
releasedAt:
|
|
550
|
-
refundedAt:
|
|
621
|
+
escrow: import_zod11.z.object({
|
|
622
|
+
releaserAddress: import_zod11.z.string().describe("The only address that can ever release this escrow \u2014 never Klappay."),
|
|
623
|
+
releasedAt: import_zod11.z.string().datetime().nullable().describe("When the release actually executed on-chain. `null` until then."),
|
|
624
|
+
refundedAt: import_zod11.z.string().datetime().nullable().describe(
|
|
551
625
|
"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."
|
|
552
626
|
)
|
|
553
627
|
}).nullable().describe(
|
|
554
628
|
"Present only when this charge was created as an escrow (see `escrow` on the create request) \u2014 `null` for a normal charge."
|
|
555
629
|
)
|
|
556
630
|
});
|
|
557
|
-
var ListChargesSchema =
|
|
631
|
+
var ListChargesSchema = import_zod11.z.object({
|
|
558
632
|
status: ChargeStatusSchema.optional(),
|
|
559
633
|
token: TokenSchema.optional().describe(
|
|
560
634
|
"Filters on `paidWith.token` \u2014 the pair actually paid, not accepted."
|
|
@@ -563,13 +637,13 @@ var ListChargesSchema = import_zod10.z.object({
|
|
|
563
637
|
"Filters on `paidWith.network` \u2014 the pair actually paid, not accepted."
|
|
564
638
|
),
|
|
565
639
|
environment: EnvironmentSchema.optional(),
|
|
566
|
-
since:
|
|
640
|
+
since: import_zod11.z.string().datetime().optional().describe(
|
|
567
641
|
"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."
|
|
568
642
|
),
|
|
569
|
-
isOverpaid:
|
|
643
|
+
isOverpaid: import_zod11.z.enum(["true", "false"]).transform((v) => v === "true").optional()
|
|
570
644
|
}).extend(PaginationQuerySchema.shape);
|
|
571
645
|
var PaginatedChargesSchema = paginatedSchema(ChargeSchema);
|
|
572
|
-
var GetChargeQrCodeQuerySchema =
|
|
646
|
+
var GetChargeQrCodeQuerySchema = import_zod11.z.object({
|
|
573
647
|
token: TokenSchema.optional().describe(
|
|
574
648
|
"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."
|
|
575
649
|
),
|
|
@@ -577,19 +651,19 @@ var GetChargeQrCodeQuerySchema = import_zod10.z.object({
|
|
|
577
651
|
});
|
|
578
652
|
|
|
579
653
|
// src/charge-check.ts
|
|
580
|
-
var
|
|
654
|
+
var import_zod13 = require("zod");
|
|
581
655
|
|
|
582
656
|
// src/confirmation-progress.ts
|
|
583
|
-
var
|
|
584
|
-
var ConfirmationProgressSchema =
|
|
657
|
+
var import_zod12 = require("zod");
|
|
658
|
+
var ConfirmationProgressSchema = import_zod12.z.object({
|
|
585
659
|
network: NetworkSchema.describe("Which network the transfer was seen on."),
|
|
586
|
-
blocksSeen:
|
|
660
|
+
blocksSeen: import_zod12.z.number().int().min(0).describe(
|
|
587
661
|
"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."
|
|
588
662
|
),
|
|
589
|
-
blocksRequired:
|
|
663
|
+
blocksRequired: import_zod12.z.number().int().min(1).describe(
|
|
590
664
|
"This network's minimum confirmation depth (a fixed, per-network constant) \u2014 the transfer is only credited once `blocksSeen` reaches this value."
|
|
591
665
|
),
|
|
592
|
-
percent:
|
|
666
|
+
percent: import_zod12.z.number().int().min(0).max(99).describe(
|
|
593
667
|
'`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).'
|
|
594
668
|
)
|
|
595
669
|
}).describe(
|
|
@@ -597,8 +671,8 @@ var ConfirmationProgressSchema = import_zod11.z.object({
|
|
|
597
671
|
);
|
|
598
672
|
|
|
599
673
|
// src/charge-check.ts
|
|
600
|
-
var CheckChargeRequestSchema =
|
|
601
|
-
txHash:
|
|
674
|
+
var CheckChargeRequestSchema = import_zod13.z.object({
|
|
675
|
+
txHash: import_zod13.z.string().regex(/^0x[0-9a-fA-F]{64}$/, "must be a 32-byte transaction hash").optional().describe(
|
|
602
676
|
"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."
|
|
603
677
|
),
|
|
604
678
|
network: NetworkSchema.optional().describe(
|
|
@@ -608,7 +682,7 @@ var CheckChargeRequestSchema = import_zod12.z.object({
|
|
|
608
682
|
message: "`txHash` and `network` must be provided together, or both omitted"
|
|
609
683
|
});
|
|
610
684
|
var CheckChargeResponseSchema = ChargeSchema.extend({
|
|
611
|
-
transactionSender:
|
|
685
|
+
transactionSender: import_zod13.z.string().nullable().describe(
|
|
612
686
|
"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`."
|
|
613
687
|
),
|
|
614
688
|
confirmationProgress: ConfirmationProgressSchema.nullable().describe(
|
|
@@ -617,61 +691,61 @@ var CheckChargeResponseSchema = ChargeSchema.extend({
|
|
|
617
691
|
});
|
|
618
692
|
|
|
619
693
|
// src/distributions.ts
|
|
620
|
-
var
|
|
621
|
-
var SplitDistributionStatusSchema =
|
|
694
|
+
var import_zod14 = require("zod");
|
|
695
|
+
var SplitDistributionStatusSchema = import_zod14.z.enum(["pending", "processing", "completed", "failed"]).describe(
|
|
622
696
|
"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."
|
|
623
697
|
);
|
|
624
|
-
var PendingDistributionRecipientSchema =
|
|
625
|
-
address:
|
|
626
|
-
percentAllocation:
|
|
698
|
+
var PendingDistributionRecipientSchema = import_zod14.z.object({
|
|
699
|
+
address: import_zod14.z.string().describe("On-chain recipient address."),
|
|
700
|
+
percentAllocation: import_zod14.z.number().describe("This recipient's share of the split, as a percentage (e.g. `99.0991` = 99.0991%).")
|
|
627
701
|
});
|
|
628
|
-
var PendingDistributionSchema =
|
|
629
|
-
splitAddress:
|
|
702
|
+
var PendingDistributionSchema = import_zod14.z.object({
|
|
703
|
+
splitAddress: import_zod14.z.string().describe("The on-chain 0xSplits address to call `distribute()` on."),
|
|
630
704
|
network: NetworkSchema,
|
|
631
705
|
token: TokenSchema,
|
|
632
|
-
recipients:
|
|
706
|
+
recipients: import_zod14.z.array(PendingDistributionRecipientSchema).describe(
|
|
633
707
|
"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."
|
|
634
708
|
),
|
|
635
|
-
distributorFeePercent:
|
|
709
|
+
distributorFeePercent: import_zod14.z.number().describe(
|
|
636
710
|
"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."
|
|
637
711
|
),
|
|
638
|
-
estimatedRewardAmount:
|
|
712
|
+
estimatedRewardAmount: import_zod14.z.number().describe(
|
|
639
713
|
"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."
|
|
640
714
|
),
|
|
641
|
-
availableSince:
|
|
642
|
-
graceEndsAt:
|
|
715
|
+
availableSince: import_zod14.z.string().datetime().describe("When this distribution entered its grace period."),
|
|
716
|
+
graceEndsAt: import_zod14.z.string().datetime().describe(
|
|
643
717
|
"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."
|
|
644
718
|
)
|
|
645
719
|
});
|
|
646
720
|
var PaginatedPendingDistributionsSchema = paginatedSchema(PendingDistributionSchema);
|
|
647
|
-
var ListenPendingDistributionsQuerySchema =
|
|
648
|
-
limit:
|
|
721
|
+
var ListenPendingDistributionsQuerySchema = import_zod14.z.object({
|
|
722
|
+
limit: import_zod14.z.coerce.number().int().min(0).max(PAGINATION_LIMIT_MAX).default(0).describe(
|
|
649
723
|
"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."
|
|
650
724
|
)
|
|
651
725
|
});
|
|
652
|
-
var PendingDistributionEventSchema =
|
|
653
|
-
|
|
654
|
-
type:
|
|
726
|
+
var PendingDistributionEventSchema = import_zod14.z.discriminatedUnion("type", [
|
|
727
|
+
import_zod14.z.object({
|
|
728
|
+
type: import_zod14.z.literal("distribution.available"),
|
|
655
729
|
distribution: PendingDistributionSchema
|
|
656
730
|
}),
|
|
657
|
-
|
|
658
|
-
type:
|
|
659
|
-
splitAddress:
|
|
731
|
+
import_zod14.z.object({
|
|
732
|
+
type: import_zod14.z.literal("distribution.claimed"),
|
|
733
|
+
splitAddress: import_zod14.z.string().describe("No longer claimable \u2014 either settled by someone, or picked up by the worker.")
|
|
660
734
|
})
|
|
661
735
|
]);
|
|
662
736
|
|
|
663
737
|
// src/metrics.ts
|
|
664
|
-
var
|
|
665
|
-
var MetricsResourceSchema =
|
|
738
|
+
var import_zod15 = require("zod");
|
|
739
|
+
var MetricsResourceSchema = import_zod15.z.enum(["charges", "transactions", "distributions"]).describe(
|
|
666
740
|
"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."
|
|
667
741
|
);
|
|
668
|
-
var MetricsAggregationSchema =
|
|
742
|
+
var MetricsAggregationSchema = import_zod15.z.enum(["count", "sum", "avg", "min", "max"]).describe(
|
|
669
743
|
"`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."
|
|
670
744
|
);
|
|
671
|
-
var MetricsFilterOperatorSchema =
|
|
745
|
+
var MetricsFilterOperatorSchema = import_zod15.z.enum(["eq", "neq", "in", "gt", "gte", "lt", "lte"]).describe(
|
|
672
746
|
"`in` expects an array value (max 50 entries); every other operator expects a single scalar."
|
|
673
747
|
);
|
|
674
|
-
var MetricsDateGranularitySchema =
|
|
748
|
+
var MetricsDateGranularitySchema = import_zod15.z.enum(["day", "week", "month", "year"]).describe(
|
|
675
749
|
"Bucket width for a `date_bucket` `groupBy` entry \u2014 Postgres `date_trunc` semantics (UTC)."
|
|
676
750
|
);
|
|
677
751
|
var metricsQueryEnvironmentSchema = EnvironmentSchema.describe(
|
|
@@ -684,31 +758,31 @@ var METRICS_QUERY_MAX_GROUP_BY = 3;
|
|
|
684
758
|
var METRICS_QUERY_MAX_FILTERS = 20;
|
|
685
759
|
var METRICS_QUERY_MAX_METRICS = 10;
|
|
686
760
|
var METRIC_ALIAS_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
687
|
-
var metricAliasSchema =
|
|
761
|
+
var metricAliasSchema = import_zod15.z.string().min(1).max(64).regex(
|
|
688
762
|
METRIC_ALIAS_PATTERN,
|
|
689
763
|
"Must start with a letter or underscore, and contain only letters, digits, and underscores \u2014 this becomes a SQL column alias."
|
|
690
764
|
).optional();
|
|
691
|
-
var MetricsFilterValueSchema =
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
765
|
+
var MetricsFilterValueSchema = import_zod15.z.union([
|
|
766
|
+
import_zod15.z.string().max(255),
|
|
767
|
+
import_zod15.z.number(),
|
|
768
|
+
import_zod15.z.boolean(),
|
|
769
|
+
import_zod15.z.array(import_zod15.z.union([import_zod15.z.string().max(255), import_zod15.z.number()])).min(1).max(50)
|
|
696
770
|
]);
|
|
697
|
-
var orderBySchema =
|
|
698
|
-
key:
|
|
771
|
+
var orderBySchema = import_zod15.z.object({
|
|
772
|
+
key: import_zod15.z.string().min(1).max(64).regex(
|
|
699
773
|
METRIC_ALIAS_PATTERN,
|
|
700
774
|
"Must start with a letter or underscore, and contain only letters, digits, and underscores \u2014 every valid output column name already looks like this."
|
|
701
775
|
).describe(
|
|
702
776
|
"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."
|
|
703
777
|
),
|
|
704
|
-
direction:
|
|
778
|
+
direction: import_zod15.z.enum(["asc", "desc"])
|
|
705
779
|
}).describe(
|
|
706
780
|
"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."
|
|
707
781
|
);
|
|
708
|
-
var limitSchema =
|
|
782
|
+
var limitSchema = import_zod15.z.number().int().min(1).max(METRICS_QUERY_MAX_ROW_LIMIT).default(METRICS_QUERY_DEFAULT_ROW_LIMIT).describe(
|
|
709
783
|
`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.`
|
|
710
784
|
);
|
|
711
|
-
var ChargesQueryFieldSchema =
|
|
785
|
+
var ChargesQueryFieldSchema = import_zod15.z.enum([
|
|
712
786
|
"status",
|
|
713
787
|
"source",
|
|
714
788
|
"apiKeyId",
|
|
@@ -719,124 +793,124 @@ var ChargesQueryFieldSchema = import_zod14.z.enum([
|
|
|
719
793
|
]).describe(
|
|
720
794
|
"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)."
|
|
721
795
|
);
|
|
722
|
-
var ChargesMetricFieldSchema =
|
|
796
|
+
var ChargesMetricFieldSchema = import_zod15.z.enum(["amount", "amountReceived", "feePercent", "escrowFeePercent"]).describe(
|
|
723
797
|
"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`."
|
|
724
798
|
);
|
|
725
|
-
var ChargesDateFieldSchema =
|
|
799
|
+
var ChargesDateFieldSchema = import_zod15.z.enum(["createdAt", "confirmedAt", "lastActivityAt", "expiresAt", "escrowReleasedAt"]).describe(
|
|
726
800
|
"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."
|
|
727
801
|
);
|
|
728
|
-
var ChargesFilterSchema =
|
|
802
|
+
var ChargesFilterSchema = import_zod15.z.object({
|
|
729
803
|
field: ChargesQueryFieldSchema,
|
|
730
804
|
operator: MetricsFilterOperatorSchema,
|
|
731
805
|
value: MetricsFilterValueSchema
|
|
732
806
|
});
|
|
733
|
-
var ChargesGroupBySchema =
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
type:
|
|
807
|
+
var ChargesGroupBySchema = import_zod15.z.union([
|
|
808
|
+
import_zod15.z.object({ type: import_zod15.z.literal("field"), field: ChargesQueryFieldSchema }),
|
|
809
|
+
import_zod15.z.object({
|
|
810
|
+
type: import_zod15.z.literal("date_bucket"),
|
|
737
811
|
field: ChargesDateFieldSchema,
|
|
738
812
|
granularity: MetricsDateGranularitySchema
|
|
739
813
|
})
|
|
740
814
|
]);
|
|
741
|
-
var ChargesMetricSchema =
|
|
815
|
+
var ChargesMetricSchema = import_zod15.z.object({
|
|
742
816
|
aggregation: MetricsAggregationSchema,
|
|
743
817
|
field: ChargesMetricFieldSchema.optional(),
|
|
744
818
|
alias: metricAliasSchema
|
|
745
819
|
});
|
|
746
|
-
var ChargesMetricsQuerySchema =
|
|
747
|
-
resource:
|
|
820
|
+
var ChargesMetricsQuerySchema = import_zod15.z.object({
|
|
821
|
+
resource: import_zod15.z.literal("charges"),
|
|
748
822
|
environment: metricsQueryEnvironmentSchema,
|
|
749
|
-
dateRange:
|
|
823
|
+
dateRange: import_zod15.z.object({
|
|
750
824
|
field: ChargesDateFieldSchema,
|
|
751
|
-
from:
|
|
752
|
-
to:
|
|
825
|
+
from: import_zod15.z.string().max(64).datetime(),
|
|
826
|
+
to: import_zod15.z.string().max(64).datetime()
|
|
753
827
|
}),
|
|
754
|
-
groupBy:
|
|
755
|
-
metrics:
|
|
756
|
-
filters:
|
|
828
|
+
groupBy: import_zod15.z.array(ChargesGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
|
|
829
|
+
metrics: import_zod15.z.array(ChargesMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
|
|
830
|
+
filters: import_zod15.z.array(ChargesFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
|
|
757
831
|
orderBy: orderBySchema.optional(),
|
|
758
832
|
limit: limitSchema
|
|
759
833
|
});
|
|
760
|
-
var TransactionsQueryFieldSchema =
|
|
834
|
+
var TransactionsQueryFieldSchema = import_zod15.z.enum(["network", "token", "source", "causedTransition"]).describe(
|
|
761
835
|
"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)."
|
|
762
836
|
);
|
|
763
|
-
var TransactionsMetricFieldSchema =
|
|
764
|
-
var TransactionsDateFieldSchema =
|
|
765
|
-
var TransactionsFilterSchema =
|
|
837
|
+
var TransactionsMetricFieldSchema = import_zod15.z.enum(["amount"]).describe("The transfer amount, in the charge's `currency` units.");
|
|
838
|
+
var TransactionsDateFieldSchema = import_zod15.z.enum(["detectedAt"]).describe("When Klappay detected this transfer on-chain (not when it was mined).");
|
|
839
|
+
var TransactionsFilterSchema = import_zod15.z.object({
|
|
766
840
|
field: TransactionsQueryFieldSchema,
|
|
767
841
|
operator: MetricsFilterOperatorSchema,
|
|
768
842
|
value: MetricsFilterValueSchema
|
|
769
843
|
});
|
|
770
|
-
var TransactionsGroupBySchema =
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
type:
|
|
844
|
+
var TransactionsGroupBySchema = import_zod15.z.union([
|
|
845
|
+
import_zod15.z.object({ type: import_zod15.z.literal("field"), field: TransactionsQueryFieldSchema }),
|
|
846
|
+
import_zod15.z.object({
|
|
847
|
+
type: import_zod15.z.literal("date_bucket"),
|
|
774
848
|
field: TransactionsDateFieldSchema,
|
|
775
849
|
granularity: MetricsDateGranularitySchema
|
|
776
850
|
})
|
|
777
851
|
]);
|
|
778
|
-
var TransactionsMetricSchema =
|
|
852
|
+
var TransactionsMetricSchema = import_zod15.z.object({
|
|
779
853
|
aggregation: MetricsAggregationSchema,
|
|
780
854
|
field: TransactionsMetricFieldSchema.optional(),
|
|
781
855
|
alias: metricAliasSchema
|
|
782
856
|
});
|
|
783
|
-
var TransactionsMetricsQuerySchema =
|
|
784
|
-
resource:
|
|
857
|
+
var TransactionsMetricsQuerySchema = import_zod15.z.object({
|
|
858
|
+
resource: import_zod15.z.literal("transactions"),
|
|
785
859
|
environment: metricsQueryEnvironmentSchema,
|
|
786
|
-
dateRange:
|
|
860
|
+
dateRange: import_zod15.z.object({
|
|
787
861
|
field: TransactionsDateFieldSchema,
|
|
788
|
-
from:
|
|
789
|
-
to:
|
|
862
|
+
from: import_zod15.z.string().max(64).datetime(),
|
|
863
|
+
to: import_zod15.z.string().max(64).datetime()
|
|
790
864
|
}),
|
|
791
|
-
groupBy:
|
|
792
|
-
metrics:
|
|
793
|
-
filters:
|
|
865
|
+
groupBy: import_zod15.z.array(TransactionsGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
|
|
866
|
+
metrics: import_zod15.z.array(TransactionsMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
|
|
867
|
+
filters: import_zod15.z.array(TransactionsFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
|
|
794
868
|
orderBy: orderBySchema.optional(),
|
|
795
869
|
limit: limitSchema
|
|
796
870
|
});
|
|
797
|
-
var DistributionsQueryFieldSchema =
|
|
871
|
+
var DistributionsQueryFieldSchema = import_zod15.z.enum(["status", "network", "token", "distributorAddress"]).describe(
|
|
798
872
|
"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."
|
|
799
873
|
);
|
|
800
|
-
var DistributionsMetricFieldSchema =
|
|
874
|
+
var DistributionsMetricFieldSchema = import_zod15.z.enum(["attempts"]).describe(
|
|
801
875
|
"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."
|
|
802
876
|
);
|
|
803
|
-
var DistributionsDateFieldSchema =
|
|
877
|
+
var DistributionsDateFieldSchema = import_zod15.z.enum(["createdAt", "processingStartedAt", "completedAt"]).describe(
|
|
804
878
|
"`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."
|
|
805
879
|
);
|
|
806
|
-
var DistributionsFilterSchema =
|
|
880
|
+
var DistributionsFilterSchema = import_zod15.z.object({
|
|
807
881
|
field: DistributionsQueryFieldSchema,
|
|
808
882
|
operator: MetricsFilterOperatorSchema,
|
|
809
883
|
value: MetricsFilterValueSchema
|
|
810
884
|
});
|
|
811
|
-
var DistributionsGroupBySchema =
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
type:
|
|
885
|
+
var DistributionsGroupBySchema = import_zod15.z.union([
|
|
886
|
+
import_zod15.z.object({ type: import_zod15.z.literal("field"), field: DistributionsQueryFieldSchema }),
|
|
887
|
+
import_zod15.z.object({
|
|
888
|
+
type: import_zod15.z.literal("date_bucket"),
|
|
815
889
|
field: DistributionsDateFieldSchema,
|
|
816
890
|
granularity: MetricsDateGranularitySchema
|
|
817
891
|
})
|
|
818
892
|
]);
|
|
819
|
-
var DistributionsMetricSchema =
|
|
893
|
+
var DistributionsMetricSchema = import_zod15.z.object({
|
|
820
894
|
aggregation: MetricsAggregationSchema,
|
|
821
895
|
field: DistributionsMetricFieldSchema.optional(),
|
|
822
896
|
alias: metricAliasSchema
|
|
823
897
|
});
|
|
824
|
-
var DistributionsMetricsQuerySchema =
|
|
825
|
-
resource:
|
|
898
|
+
var DistributionsMetricsQuerySchema = import_zod15.z.object({
|
|
899
|
+
resource: import_zod15.z.literal("distributions"),
|
|
826
900
|
environment: metricsQueryEnvironmentSchema,
|
|
827
|
-
dateRange:
|
|
901
|
+
dateRange: import_zod15.z.object({
|
|
828
902
|
field: DistributionsDateFieldSchema,
|
|
829
|
-
from:
|
|
830
|
-
to:
|
|
903
|
+
from: import_zod15.z.string().max(64).datetime(),
|
|
904
|
+
to: import_zod15.z.string().max(64).datetime()
|
|
831
905
|
}),
|
|
832
|
-
groupBy:
|
|
833
|
-
metrics:
|
|
834
|
-
filters:
|
|
906
|
+
groupBy: import_zod15.z.array(DistributionsGroupBySchema).max(METRICS_QUERY_MAX_GROUP_BY).default([]),
|
|
907
|
+
metrics: import_zod15.z.array(DistributionsMetricSchema).min(1).max(METRICS_QUERY_MAX_METRICS),
|
|
908
|
+
filters: import_zod15.z.array(DistributionsFilterSchema).max(METRICS_QUERY_MAX_FILTERS).default([]),
|
|
835
909
|
orderBy: orderBySchema.optional(),
|
|
836
910
|
limit: limitSchema
|
|
837
911
|
});
|
|
838
912
|
var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
|
|
839
|
-
var MetricsQuerySchema =
|
|
913
|
+
var MetricsQuerySchema = import_zod15.z.discriminatedUnion("resource", [
|
|
840
914
|
ChargesMetricsQuerySchema,
|
|
841
915
|
TransactionsMetricsQuerySchema,
|
|
842
916
|
DistributionsMetricsQuerySchema
|
|
@@ -845,7 +919,7 @@ var MetricsQuerySchema = import_zod14.z.discriminatedUnion("resource", [
|
|
|
845
919
|
const to = new Date(input.dateRange.to);
|
|
846
920
|
if (from >= to) {
|
|
847
921
|
ctx.addIssue({
|
|
848
|
-
code:
|
|
922
|
+
code: import_zod15.z.ZodIssueCode.custom,
|
|
849
923
|
message: "`dateRange.from` must be before `dateRange.to`.",
|
|
850
924
|
path: ["dateRange", "from"]
|
|
851
925
|
});
|
|
@@ -853,7 +927,7 @@ var MetricsQuerySchema = import_zod14.z.discriminatedUnion("resource", [
|
|
|
853
927
|
const spanDays = (to.getTime() - from.getTime()) / ONE_DAY_MS;
|
|
854
928
|
if (spanDays > MAX_METRICS_QUERY_DATE_RANGE_DAYS) {
|
|
855
929
|
ctx.addIssue({
|
|
856
|
-
code:
|
|
930
|
+
code: import_zod15.z.ZodIssueCode.custom,
|
|
857
931
|
message: `\`dateRange\` cannot span more than ${MAX_METRICS_QUERY_DATE_RANGE_DAYS} days.`,
|
|
858
932
|
path: ["dateRange", "to"]
|
|
859
933
|
});
|
|
@@ -861,7 +935,7 @@ var MetricsQuerySchema = import_zod14.z.discriminatedUnion("resource", [
|
|
|
861
935
|
const dateBucketCount = input.groupBy.filter((entry) => entry.type === "date_bucket").length;
|
|
862
936
|
if (dateBucketCount > 1) {
|
|
863
937
|
ctx.addIssue({
|
|
864
|
-
code:
|
|
938
|
+
code: import_zod15.z.ZodIssueCode.custom,
|
|
865
939
|
message: "At most one `date_bucket` entry is allowed in `groupBy`.",
|
|
866
940
|
path: ["groupBy"]
|
|
867
941
|
});
|
|
@@ -869,7 +943,7 @@ var MetricsQuerySchema = import_zod14.z.discriminatedUnion("resource", [
|
|
|
869
943
|
input.metrics.forEach((metric, index) => {
|
|
870
944
|
if (metric.aggregation !== "count" && metric.field === void 0) {
|
|
871
945
|
ctx.addIssue({
|
|
872
|
-
code:
|
|
946
|
+
code: import_zod15.z.ZodIssueCode.custom,
|
|
873
947
|
message: "`field` is required unless `aggregation` is `count`.",
|
|
874
948
|
path: ["metrics", index, "field"]
|
|
875
949
|
});
|
|
@@ -878,7 +952,7 @@ var MetricsQuerySchema = import_zod14.z.discriminatedUnion("resource", [
|
|
|
878
952
|
const aliases = input.metrics.map((metric) => metric.alias).filter((alias) => alias !== void 0);
|
|
879
953
|
if (new Set(aliases).size !== aliases.length) {
|
|
880
954
|
ctx.addIssue({
|
|
881
|
-
code:
|
|
955
|
+
code: import_zod15.z.ZodIssueCode.custom,
|
|
882
956
|
message: "Every `metrics[].alias` must be unique.",
|
|
883
957
|
path: ["metrics"]
|
|
884
958
|
});
|
|
@@ -887,32 +961,32 @@ var MetricsQuerySchema = import_zod14.z.discriminatedUnion("resource", [
|
|
|
887
961
|
input.metrics.forEach((metric, index) => {
|
|
888
962
|
if (metric.alias !== void 0 && reservedNames.has(metric.alias)) {
|
|
889
963
|
ctx.addIssue({
|
|
890
|
-
code:
|
|
964
|
+
code: import_zod15.z.ZodIssueCode.custom,
|
|
891
965
|
message: `\`alias\` "${metric.alias}" collides with a \`groupBy\` field name (or the reserved word "bucket") \u2014 choose a different alias.`,
|
|
892
966
|
path: ["metrics", index, "alias"]
|
|
893
967
|
});
|
|
894
968
|
}
|
|
895
969
|
});
|
|
896
970
|
});
|
|
897
|
-
var MetricsQueryResultRowSchema =
|
|
898
|
-
|
|
899
|
-
|
|
971
|
+
var MetricsQueryResultRowSchema = import_zod15.z.record(
|
|
972
|
+
import_zod15.z.string(),
|
|
973
|
+
import_zod15.z.union([import_zod15.z.string(), import_zod15.z.number(), import_zod15.z.boolean(), import_zod15.z.null()])
|
|
900
974
|
);
|
|
901
|
-
var MetricsQueryResultSchema =
|
|
902
|
-
data:
|
|
903
|
-
meta:
|
|
975
|
+
var MetricsQueryResultSchema = import_zod15.z.object({
|
|
976
|
+
data: import_zod15.z.array(MetricsQueryResultRowSchema),
|
|
977
|
+
meta: import_zod15.z.object({
|
|
904
978
|
resource: MetricsResourceSchema,
|
|
905
979
|
environment: EnvironmentSchema,
|
|
906
|
-
rowCount:
|
|
907
|
-
truncated:
|
|
980
|
+
rowCount: import_zod15.z.number().int().describe("Number of rows in `data`."),
|
|
981
|
+
truncated: import_zod15.z.boolean().describe(
|
|
908
982
|
"`true` if more rows matched than `limit` allowed \u2014 `data` holds only the first `limit`."
|
|
909
983
|
)
|
|
910
984
|
})
|
|
911
985
|
});
|
|
912
986
|
|
|
913
987
|
// src/webhook-events.ts
|
|
914
|
-
var
|
|
915
|
-
var ChargeWebhookEventTypeSchema =
|
|
988
|
+
var import_zod16 = require("zod");
|
|
989
|
+
var ChargeWebhookEventTypeSchema = import_zod16.z.enum([
|
|
916
990
|
"charge.created",
|
|
917
991
|
"charge.partially_paid",
|
|
918
992
|
"charge.confirmed",
|
|
@@ -926,14 +1000,14 @@ var ChargeWebhookEventTypeSchema = import_zod15.z.enum([
|
|
|
926
1000
|
]).describe(
|
|
927
1001
|
'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`.'
|
|
928
1002
|
);
|
|
929
|
-
var WebhookDeliveryEventTypeSchema =
|
|
1003
|
+
var WebhookDeliveryEventTypeSchema = import_zod16.z.enum(["webhook.delivery_failed", "webhook.delivery_recovered", "webhook.endpoint_unhealthy"]).describe(
|
|
930
1004
|
"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`)."
|
|
931
1005
|
);
|
|
932
|
-
var WebhookEventTypeSchema =
|
|
1006
|
+
var WebhookEventTypeSchema = import_zod16.z.union([
|
|
933
1007
|
ChargeWebhookEventTypeSchema,
|
|
934
1008
|
WebhookDeliveryEventTypeSchema
|
|
935
1009
|
]);
|
|
936
|
-
var WebhookCategorySchema =
|
|
1010
|
+
var WebhookCategorySchema = import_zod16.z.enum(["payments", "webhooks"]).describe(
|
|
937
1011
|
"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."
|
|
938
1012
|
);
|
|
939
1013
|
function buildCategoryMap() {
|
|
@@ -963,101 +1037,101 @@ var TriggerableChargeEventSchema = ChargeWebhookEventTypeSchema.exclude([
|
|
|
963
1037
|
);
|
|
964
1038
|
|
|
965
1039
|
// src/webhooks.ts
|
|
966
|
-
var
|
|
1040
|
+
var import_zod17 = require("zod");
|
|
967
1041
|
var WEBHOOK_EVENTS_WILDCARD = "*";
|
|
968
|
-
var CreateWebhookSchema =
|
|
969
|
-
url:
|
|
1042
|
+
var CreateWebhookSchema = import_zod17.z.object({
|
|
1043
|
+
url: import_zod17.z.string().max(2048).url().describe(
|
|
970
1044
|
"Must be HTTPS and resolve to a public address \u2014 private/internal IPs are rejected."
|
|
971
1045
|
),
|
|
972
|
-
events:
|
|
1046
|
+
events: import_zod17.z.array(import_zod17.z.union([WebhookEventTypeSchema, import_zod17.z.literal(WEBHOOK_EVENTS_WILDCARD)])).max(Object.keys(EVENT_CATEGORY_MAP).length + 1).default([]).describe(
|
|
973
1047
|
'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.'
|
|
974
1048
|
),
|
|
975
|
-
eventCategories:
|
|
1049
|
+
eventCategories: import_zod17.z.array(WebhookCategorySchema).max(WebhookCategorySchema.options.length).default([]).describe(
|
|
976
1050
|
"Subscribe to every event in these categories. At least one of `events` or `eventCategories` is required."
|
|
977
1051
|
),
|
|
978
|
-
excludeEvents:
|
|
1052
|
+
excludeEvents: import_zod17.z.array(WebhookEventTypeSchema).max(Object.keys(EVENT_CATEGORY_MAP).length).default([]).describe(
|
|
979
1053
|
'Event types to exclude even if selected via `events: ["*"]` or `eventCategories`.'
|
|
980
1054
|
)
|
|
981
1055
|
}).refine((v) => v.events.length > 0 || v.eventCategories.length > 0, {
|
|
982
1056
|
message: "must select at least one event via `events` or `eventCategories`",
|
|
983
1057
|
path: ["events"]
|
|
984
1058
|
});
|
|
985
|
-
var WebhookSchema =
|
|
986
|
-
id:
|
|
1059
|
+
var WebhookSchema = import_zod17.z.object({
|
|
1060
|
+
id: import_zod17.z.string(),
|
|
987
1061
|
environment: EnvironmentSchema.nullable().describe(
|
|
988
1062
|
"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)."
|
|
989
1063
|
),
|
|
990
|
-
url:
|
|
991
|
-
events:
|
|
992
|
-
eventCategories:
|
|
993
|
-
excludeEvents:
|
|
994
|
-
isWildcard:
|
|
995
|
-
secret:
|
|
1064
|
+
url: import_zod17.z.string(),
|
|
1065
|
+
events: import_zod17.z.array(WebhookEventTypeSchema),
|
|
1066
|
+
eventCategories: import_zod17.z.array(WebhookCategorySchema),
|
|
1067
|
+
excludeEvents: import_zod17.z.array(WebhookEventTypeSchema),
|
|
1068
|
+
isWildcard: import_zod17.z.boolean(),
|
|
1069
|
+
secret: import_zod17.z.string().describe(
|
|
996
1070
|
"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."
|
|
997
1071
|
),
|
|
998
|
-
createdAt:
|
|
1072
|
+
createdAt: import_zod17.z.string().datetime()
|
|
999
1073
|
});
|
|
1000
1074
|
var WebhookListItemSchema = WebhookSchema.omit({ secret: true }).extend({
|
|
1001
|
-
hint:
|
|
1075
|
+
hint: import_zod17.z.string().describe("A truncated, safe-to-display form of the secret (e.g. `whsec_...ab12`).")
|
|
1002
1076
|
});
|
|
1003
|
-
var WebhookPayloadSchema =
|
|
1004
|
-
id:
|
|
1077
|
+
var WebhookPayloadSchema = import_zod17.z.object({
|
|
1078
|
+
id: import_zod17.z.string().describe(
|
|
1005
1079
|
"Unique id for this specific delivery \u2014 also sent as the `X-Klappay-Delivery` header."
|
|
1006
1080
|
),
|
|
1007
1081
|
event: WebhookEventTypeSchema,
|
|
1008
|
-
createdAt:
|
|
1009
|
-
data:
|
|
1082
|
+
createdAt: import_zod17.z.string().datetime(),
|
|
1083
|
+
data: import_zod17.z.unknown().describe(
|
|
1010
1084
|
"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."
|
|
1011
1085
|
)
|
|
1012
1086
|
});
|
|
1013
|
-
var WebhookDeliveryStatusSchema =
|
|
1014
|
-
var WebhookDeliverySchema =
|
|
1015
|
-
id:
|
|
1016
|
-
webhookId:
|
|
1087
|
+
var WebhookDeliveryStatusSchema = import_zod17.z.enum(["pending", "delivered", "failed"]);
|
|
1088
|
+
var WebhookDeliverySchema = import_zod17.z.object({
|
|
1089
|
+
id: import_zod17.z.string(),
|
|
1090
|
+
webhookId: import_zod17.z.string(),
|
|
1017
1091
|
event: WebhookEventTypeSchema,
|
|
1018
1092
|
status: WebhookDeliveryStatusSchema.describe(
|
|
1019
1093
|
"`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."
|
|
1020
1094
|
),
|
|
1021
|
-
attempts:
|
|
1022
|
-
responseCode:
|
|
1095
|
+
attempts: import_zod17.z.number(),
|
|
1096
|
+
responseCode: import_zod17.z.number().nullable().describe(
|
|
1023
1097
|
"HTTP status your endpoint returned on the most recent attempt. `null` if every attempt failed to connect at all."
|
|
1024
1098
|
),
|
|
1025
|
-
nextRetryAt:
|
|
1026
|
-
deliveredAt:
|
|
1027
|
-
createdAt:
|
|
1099
|
+
nextRetryAt: import_zod17.z.string().datetime().nullable(),
|
|
1100
|
+
deliveredAt: import_zod17.z.string().datetime().nullable(),
|
|
1101
|
+
createdAt: import_zod17.z.string().datetime()
|
|
1028
1102
|
});
|
|
1029
1103
|
var ListWebhookDeliveriesSchema = PaginationQuerySchema;
|
|
1030
1104
|
var PaginatedWebhookDeliveriesSchema = paginatedSchema(WebhookDeliverySchema);
|
|
1031
1105
|
|
|
1032
1106
|
// src/recipients.ts
|
|
1033
|
-
var
|
|
1107
|
+
var import_zod18 = require("zod");
|
|
1034
1108
|
var EVM_ADDRESS_REGEX = /^0x[0-9a-fA-F]{40}$/;
|
|
1035
|
-
var CreateRecipientSchema =
|
|
1036
|
-
address:
|
|
1037
|
-
label:
|
|
1109
|
+
var CreateRecipientSchema = import_zod18.z.object({
|
|
1110
|
+
address: import_zod18.z.string().regex(EVM_ADDRESS_REGEX, "must be a 20-byte hex address").describe("EVM address to register as a trusted split recipient for your organization."),
|
|
1111
|
+
label: import_zod18.z.string().min(1).max(64).optional().describe('Free-form label for your own bookkeeping (e.g. `"supplier"`) \u2014 never interpreted.')
|
|
1038
1112
|
});
|
|
1039
|
-
var RecipientSchema =
|
|
1040
|
-
id:
|
|
1113
|
+
var RecipientSchema = import_zod18.z.object({
|
|
1114
|
+
id: import_zod18.z.string().describe(
|
|
1041
1115
|
"Klappay-generated id, e.g. `rc_...` \u2014 this, not the raw address, is what a charge's `splitRecipients[].recipientId` references."
|
|
1042
1116
|
),
|
|
1043
1117
|
environment: EnvironmentSchema,
|
|
1044
|
-
address:
|
|
1045
|
-
label:
|
|
1046
|
-
payout:
|
|
1118
|
+
address: import_zod18.z.string(),
|
|
1119
|
+
label: import_zod18.z.string().nullable(),
|
|
1120
|
+
payout: import_zod18.z.boolean().describe(
|
|
1047
1121
|
"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`."
|
|
1048
1122
|
),
|
|
1049
|
-
createdAt:
|
|
1123
|
+
createdAt: import_zod18.z.string().datetime()
|
|
1050
1124
|
});
|
|
1051
|
-
var SetRecipientPayoutSchema =
|
|
1052
|
-
payout:
|
|
1125
|
+
var SetRecipientPayoutSchema = import_zod18.z.object({
|
|
1126
|
+
payout: import_zod18.z.boolean().describe("New payout-eligibility value for this recipient.")
|
|
1053
1127
|
});
|
|
1054
1128
|
|
|
1055
1129
|
// src/timeline.ts
|
|
1056
|
-
var
|
|
1057
|
-
var TransactionSourceSchema =
|
|
1130
|
+
var import_zod19 = require("zod");
|
|
1131
|
+
var TransactionSourceSchema = import_zod19.z.enum(["contract_watcher", "reconciliation_job", "sandbox"]).describe(
|
|
1058
1132
|
"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)."
|
|
1059
1133
|
);
|
|
1060
|
-
var TimelineEventTypeSchema =
|
|
1134
|
+
var TimelineEventTypeSchema = import_zod19.z.enum([
|
|
1061
1135
|
"charge.created",
|
|
1062
1136
|
"charge.expired",
|
|
1063
1137
|
"transaction.detected",
|
|
@@ -1069,13 +1143,13 @@ var TimelineEventTypeSchema = import_zod18.z.enum([
|
|
|
1069
1143
|
]).describe(
|
|
1070
1144
|
"`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."
|
|
1071
1145
|
);
|
|
1072
|
-
var TimelineEventSchema =
|
|
1146
|
+
var TimelineEventSchema = import_zod19.z.object({
|
|
1073
1147
|
type: TimelineEventTypeSchema,
|
|
1074
|
-
at:
|
|
1075
|
-
txHash:
|
|
1148
|
+
at: import_zod19.z.string().datetime(),
|
|
1149
|
+
txHash: import_zod19.z.string().optional().describe(
|
|
1076
1150
|
"Present for `transaction.detected`, `split.distributed`, and `transfer.reclaimed` events only."
|
|
1077
1151
|
),
|
|
1078
|
-
amount:
|
|
1152
|
+
amount: import_zod19.z.number().optional().describe(
|
|
1079
1153
|
"Present for `transaction.detected` events only \u2014 the amount that specific transfer carried."
|
|
1080
1154
|
),
|
|
1081
1155
|
source: TransactionSourceSchema.optional().describe(
|
|
@@ -1087,103 +1161,115 @@ var TimelineEventSchema = import_zod18.z.object({
|
|
|
1087
1161
|
network: NetworkSchema.optional().describe(
|
|
1088
1162
|
"Present for `transaction.detected` and `split.distributed` events \u2014 which network this specific transfer, or settlement, used."
|
|
1089
1163
|
),
|
|
1090
|
-
causedTransition:
|
|
1164
|
+
causedTransition: import_zod19.z.boolean().optional().describe(
|
|
1091
1165
|
"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."
|
|
1092
1166
|
),
|
|
1093
1167
|
event: WebhookEventTypeSchema.optional().describe(
|
|
1094
1168
|
"Present for `webhook.*` events only \u2014 which event type this delivery was for."
|
|
1095
1169
|
),
|
|
1096
|
-
responseCode:
|
|
1170
|
+
responseCode: import_zod19.z.number().nullable().optional().describe(
|
|
1097
1171
|
"Present for `webhook.*` events only \u2014 HTTP status your endpoint returned, or `null` if the request never connected."
|
|
1098
1172
|
),
|
|
1099
|
-
attempts:
|
|
1173
|
+
attempts: import_zod19.z.number().optional().describe(
|
|
1100
1174
|
"Present for `webhook.*` events only \u2014 how many delivery attempts have been made so far."
|
|
1101
1175
|
)
|
|
1102
1176
|
});
|
|
1103
1177
|
|
|
1104
1178
|
// src/health.ts
|
|
1105
|
-
var
|
|
1106
|
-
var HealthSchema =
|
|
1107
|
-
status:
|
|
1179
|
+
var import_zod20 = require("zod");
|
|
1180
|
+
var HealthSchema = import_zod20.z.object({
|
|
1181
|
+
status: import_zod20.z.enum(["ok", "error"]).describe(
|
|
1108
1182
|
"`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."
|
|
1109
1183
|
),
|
|
1110
|
-
version:
|
|
1111
|
-
timestamp:
|
|
1112
|
-
db:
|
|
1113
|
-
pendingWebhooks:
|
|
1114
|
-
oldestPendingChargeAgeSeconds:
|
|
1115
|
-
lastContractWatcherEventAgeSeconds:
|
|
1184
|
+
version: import_zod20.z.string(),
|
|
1185
|
+
timestamp: import_zod20.z.string().datetime(),
|
|
1186
|
+
db: import_zod20.z.enum(["ok", "error"]).describe("Result of a real database connectivity check, not just a process-alive check."),
|
|
1187
|
+
pendingWebhooks: import_zod20.z.number().describe("Count of webhook deliveries still awaiting a successful attempt."),
|
|
1188
|
+
oldestPendingChargeAgeSeconds: import_zod20.z.number().nullable().describe("Age of the oldest still-unpaid charge, in seconds. `null` if there are none."),
|
|
1189
|
+
lastContractWatcherEventAgeSeconds: import_zod20.z.number().nullable().describe(
|
|
1116
1190
|
"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."
|
|
1117
1191
|
)
|
|
1118
1192
|
});
|
|
1119
1193
|
|
|
1120
1194
|
// src/sandbox.ts
|
|
1121
|
-
var
|
|
1122
|
-
var SandboxTriggerSchema =
|
|
1195
|
+
var import_zod21 = require("zod");
|
|
1196
|
+
var SandboxTriggerSchema = import_zod21.z.object({
|
|
1123
1197
|
event: TriggerableChargeEventSchema,
|
|
1124
|
-
amount:
|
|
1198
|
+
amount: import_zod21.z.number().positive().max(CHARGE_AMOUNT_MAX).optional().describe(
|
|
1125
1199
|
"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."
|
|
1126
1200
|
)
|
|
1127
1201
|
});
|
|
1128
1202
|
|
|
1129
1203
|
// src/capabilities.ts
|
|
1130
|
-
var
|
|
1131
|
-
var CapabilitiesSchema =
|
|
1132
|
-
acceptedPayments:
|
|
1133
|
-
"Every `(token, network)` pair
|
|
1204
|
+
var import_zod22 = require("zod");
|
|
1205
|
+
var CapabilitiesSchema = import_zod22.z.object({
|
|
1206
|
+
acceptedPayments: import_zod22.z.array(AcceptedPaymentSchema).describe(
|
|
1207
|
+
"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."
|
|
1134
1208
|
)
|
|
1135
1209
|
});
|
|
1136
1210
|
|
|
1137
1211
|
// src/swap.ts
|
|
1138
|
-
var
|
|
1139
|
-
var CreateSwapQuoteSchema =
|
|
1212
|
+
var import_zod23 = require("zod");
|
|
1213
|
+
var CreateSwapQuoteSchema = import_zod23.z.object({
|
|
1140
1214
|
inputToken: AltTokenSchema.describe(
|
|
1141
1215
|
"Which alt-cryptocurrency the payer wants to send \u2014 must be one of this charge's `swapAlternatives`, or `422 token_not_supported`."
|
|
1142
1216
|
),
|
|
1143
1217
|
inputNetwork: NetworkSchema.describe(
|
|
1144
|
-
"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
|
|
1218
|
+
"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."
|
|
1145
1219
|
),
|
|
1146
|
-
takerAddress:
|
|
1220
|
+
takerAddress: import_zod23.z.string().regex(/^0x[0-9a-fA-F]{40}$/, "must be a 20-byte hex address").describe(
|
|
1147
1221
|
"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."
|
|
1148
1222
|
)
|
|
1149
1223
|
});
|
|
1150
|
-
var SwapQuoteSchema =
|
|
1224
|
+
var SwapQuoteSchema = import_zod23.z.object({
|
|
1151
1225
|
inputToken: AltTokenSchema,
|
|
1152
1226
|
inputNetwork: NetworkSchema,
|
|
1153
|
-
inputAmount:
|
|
1227
|
+
inputAmount: import_zod23.z.number().describe(
|
|
1154
1228
|
"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."
|
|
1155
1229
|
),
|
|
1230
|
+
inputAmountExact: ExactAmountSchema.optional().describe(
|
|
1231
|
+
"Exact ceiling of `inputToken` the payer needs available, in whole token units as a nonnegative decimal string with at most 18 fractional digits and no scientific notation. Prefer this over the legacy numeric `inputAmount`. Optional for compatibility with older API responses."
|
|
1232
|
+
),
|
|
1156
1233
|
outputToken: TokenSchema.describe(
|
|
1157
1234
|
"Which of this charge's `acceptedPayments` tokens the swap resolves to."
|
|
1158
1235
|
),
|
|
1159
1236
|
outputNetwork: NetworkSchema,
|
|
1160
|
-
outputAmount:
|
|
1161
|
-
"The
|
|
1237
|
+
outputAmount: import_zod23.z.number().describe(
|
|
1238
|
+
"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."
|
|
1162
1239
|
),
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1240
|
+
outputAmountExact: ExactAmountSchema.optional().describe(
|
|
1241
|
+
"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."
|
|
1242
|
+
),
|
|
1243
|
+
fees: import_zod23.z.object({
|
|
1244
|
+
klappayFee: import_zod23.z.number().describe(
|
|
1245
|
+
"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`."
|
|
1246
|
+
),
|
|
1247
|
+
klappayFeeExact: ExactAmountSchema.optional().describe(
|
|
1248
|
+
"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."
|
|
1249
|
+
),
|
|
1250
|
+
zeroExFee: import_zod23.z.number().nullable().describe(
|
|
1251
|
+
"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."
|
|
1166
1252
|
),
|
|
1167
|
-
|
|
1168
|
-
"0x
|
|
1253
|
+
zeroExFeeExact: ExactAmountSchema.nullable().optional().describe(
|
|
1254
|
+
"Exact 0x fee in whole `outputToken` units as a nonnegative decimal string with at most 18 fractional digits and no scientific notation, or `null` when no fee applies. Already reflected in the input ceiling. Optional for compatibility with older API responses."
|
|
1169
1255
|
)
|
|
1170
1256
|
}).describe(
|
|
1171
1257
|
"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`."
|
|
1172
1258
|
),
|
|
1173
|
-
expiresAt:
|
|
1259
|
+
expiresAt: import_zod23.z.string().datetime().describe(
|
|
1174
1260
|
"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."
|
|
1175
1261
|
),
|
|
1176
|
-
transaction:
|
|
1177
|
-
to:
|
|
1178
|
-
data:
|
|
1179
|
-
value:
|
|
1180
|
-
"Native currency (ETH/BNB/
|
|
1262
|
+
transaction: import_zod23.z.object({
|
|
1263
|
+
to: import_zod23.z.string().describe("Contract address the payer's wallet must send this transaction to."),
|
|
1264
|
+
data: import_zod23.z.string().describe("Calldata \u2014 opaque, must be sent unmodified."),
|
|
1265
|
+
value: import_zod23.z.string().describe(
|
|
1266
|
+
"Native currency (ETH/BNB/POL/AVAX) to attach, in wei \u2014 `\"0\"` when `inputToken` isn't this network's native currency."
|
|
1181
1267
|
)
|
|
1182
1268
|
}).describe(
|
|
1183
1269
|
"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."
|
|
1184
1270
|
),
|
|
1185
|
-
permit2:
|
|
1186
|
-
"Present only when `inputToken` is an ERC-20 (
|
|
1271
|
+
permit2: import_zod23.z.object({ eip712: import_zod23.z.record(import_zod23.z.unknown()) }).nullish().describe(
|
|
1272
|
+
"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."
|
|
1187
1273
|
)
|
|
1188
1274
|
});
|
|
1189
1275
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1273,6 +1359,7 @@ var SwapQuoteSchema = import_zod22.z.object({
|
|
|
1273
1359
|
SwapQuoteSchema,
|
|
1274
1360
|
TOKEN_ADDRESSES,
|
|
1275
1361
|
TOKEN_DECIMALS,
|
|
1362
|
+
TOKEN_DEPLOYMENTS,
|
|
1276
1363
|
TimelineEventSchema,
|
|
1277
1364
|
TimelineEventTypeSchema,
|
|
1278
1365
|
TokenSchema,
|
|
@@ -1292,6 +1379,8 @@ var SwapQuoteSchema = import_zod22.z.object({
|
|
|
1292
1379
|
WebhookPayloadSchema,
|
|
1293
1380
|
WebhookSchema,
|
|
1294
1381
|
findConflictingScopes,
|
|
1382
|
+
getTokenDeployment,
|
|
1383
|
+
isPaymentDeploymentEnabled,
|
|
1295
1384
|
listSwapAlternatives,
|
|
1296
1385
|
paginatedSchema
|
|
1297
1386
|
});
|