@klappay/types 2.0.3 → 3.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/dist/index.d.mts +199 -10
- package/dist/index.d.ts +199 -10
- package/dist/index.js +103 -35
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +93 -35
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -1
package/dist/index.mjs
CHANGED
|
@@ -30,11 +30,26 @@ var ApiKeyScopeSchema = z3.enum([
|
|
|
30
30
|
"metrics:charges:read",
|
|
31
31
|
"metrics:transactions:read",
|
|
32
32
|
"metrics:distributions:read",
|
|
33
|
-
"sandbox:trigger"
|
|
33
|
+
"sandbox:trigger",
|
|
34
|
+
"charges:split_write",
|
|
35
|
+
"recipients:read",
|
|
36
|
+
"recipients:write",
|
|
37
|
+
"recipients:manage_payout"
|
|
34
38
|
]).describe(
|
|
35
|
-
"What an API key is allowed to do, independent of `tenantId`/`environment` (which scope *whose* data, not *what actions*). A key with none of these can still authenticate but every scoped route rejects it with `403 insufficient_scope`. `metrics:read` alone grants every metrics resource; `metrics:{resource}:read` grants only that one \u2014 a key can hold either or both."
|
|
39
|
+
"What an API key is allowed to do, independent of `tenantId`/`environment` (which scope *whose* data, not *what actions*). A key with none of these can still authenticate but every scoped route rejects it with `403 insufficient_scope`. `metrics:read` alone grants every metrics resource; `metrics:{resource}:read` grants only that one \u2014 a key can hold either or both. `charges:split_write` is required on top of `charges:write` whenever a charge request includes `splitRecipients` \u2014 a key without it can create ordinary charges but never redirect part of the payout. `recipients:write` registers/revokes recipients (addresses eligible to be *referenced* in a split); `recipients:manage_payout` is separate and strictly more sensitive \u2014 it is what lets a recipient actually become an API key's `payoutAddress`, and should be granted only to a key that already went through out-of-band approval for that (Dashboard's own internal key, never a merchant-facing or third-party integration key like a marketplace's). `charges:split_write` can never be combined with `recipients:write`/`recipients:manage_payout` on the same key (see `CONFLICTING_SCOPE_PAIRS`) \u2014 Core rejects such a key outright, before any route runs."
|
|
36
40
|
);
|
|
37
41
|
var API_KEY_SCOPES = ApiKeyScopeSchema.options;
|
|
42
|
+
var CONFLICTING_SCOPE_PAIRS = [
|
|
43
|
+
["charges:split_write", "recipients:write"],
|
|
44
|
+
["charges:split_write", "recipients:manage_payout"]
|
|
45
|
+
];
|
|
46
|
+
function findConflictingScopes(scopes) {
|
|
47
|
+
const held = new Set(scopes);
|
|
48
|
+
for (const [a, b] of CONFLICTING_SCOPE_PAIRS) {
|
|
49
|
+
if (held.has(a) && held.has(b)) return [a, b];
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
38
53
|
|
|
39
54
|
// src/networks.ts
|
|
40
55
|
import { z as z4 } from "zod";
|
|
@@ -204,21 +219,31 @@ var SplitRecipientSchema = z8.object({
|
|
|
204
219
|
'Free-form label for your own bookkeeping (e.g. `"supplier"`, `"sales rep"`) \u2014 echoed back unchanged, never interpreted by Klappay.'
|
|
205
220
|
)
|
|
206
221
|
});
|
|
207
|
-
var
|
|
222
|
+
var SplitRecipientInputSchema = z8.object({
|
|
223
|
+
recipientId: z8.string().describe(
|
|
224
|
+
"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."
|
|
225
|
+
),
|
|
226
|
+
percent: z8.number().positive().max(100).describe(
|
|
227
|
+
"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."
|
|
228
|
+
),
|
|
229
|
+
label: z8.string().min(1).max(64).optional().describe(
|
|
230
|
+
'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.'
|
|
231
|
+
)
|
|
232
|
+
});
|
|
233
|
+
var SplitRecipientsInputSchema = z8.array(SplitRecipientInputSchema).max(CHARGE_SPLIT_RECIPIENTS_MAX).superRefine((recipients, ctx) => {
|
|
208
234
|
const seen = /* @__PURE__ */ new Set();
|
|
209
235
|
recipients.forEach((recipient, index) => {
|
|
210
|
-
|
|
211
|
-
if (seen.has(key)) {
|
|
236
|
+
if (seen.has(recipient.recipientId)) {
|
|
212
237
|
ctx.addIssue({
|
|
213
238
|
code: z8.ZodIssueCode.custom,
|
|
214
|
-
message: `Duplicate split
|
|
215
|
-
path: [index, "
|
|
239
|
+
message: `Duplicate split recipientId: ${recipient.recipientId}.`,
|
|
240
|
+
path: [index, "recipientId"]
|
|
216
241
|
});
|
|
217
242
|
}
|
|
218
|
-
seen.add(
|
|
243
|
+
seen.add(recipient.recipientId);
|
|
219
244
|
});
|
|
220
245
|
}).describe(
|
|
221
|
-
`Optional extra recipients for this charge's split \u2014 e.g. a supplier or the sales rep who closed the deal \u2014 up to ${CHARGE_SPLIT_RECIPIENTS_MAX}. Frozen at creation exactly like everything else that shapes the split address; cannot be changed afterward. The sum of every \`percent\` here must fit within \`100 - feePercent\` (your own net share) \u2014 a request that doesn't is rejected with \`422 split_recipients_exceed_available_percent\`.`
|
|
246
|
+
`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\`.`
|
|
222
247
|
);
|
|
223
248
|
var CHARGE_AMOUNT_MAX = 999999999999;
|
|
224
249
|
var CreateChargeSchema = z8.object({
|
|
@@ -243,7 +268,7 @@ var CreateChargeSchema = z8.object({
|
|
|
243
268
|
redirectUrl: z8.string().url().refine((value) => /^https?:\/\//.test(value), "must use http or https").optional().describe(
|
|
244
269
|
"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."
|
|
245
270
|
),
|
|
246
|
-
splitRecipients:
|
|
271
|
+
splitRecipients: SplitRecipientsInputSchema.optional()
|
|
247
272
|
});
|
|
248
273
|
var ChargeSchema = z8.object({
|
|
249
274
|
id: z8.string().describe("Klappay-generated id, e.g. `ch_...`. Use this to look up the charge later."),
|
|
@@ -716,12 +741,35 @@ var WebhookDeliverySchema = z12.object({
|
|
|
716
741
|
var ListWebhookDeliveriesSchema = PaginationQuerySchema;
|
|
717
742
|
var PaginatedWebhookDeliveriesSchema = paginatedSchema(WebhookDeliverySchema);
|
|
718
743
|
|
|
719
|
-
// src/
|
|
744
|
+
// src/recipients.ts
|
|
720
745
|
import { z as z13 } from "zod";
|
|
721
|
-
var
|
|
746
|
+
var EVM_ADDRESS_REGEX = /^0x[0-9a-fA-F]{40}$/;
|
|
747
|
+
var CreateRecipientSchema = z13.object({
|
|
748
|
+
address: z13.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."),
|
|
749
|
+
label: z13.string().min(1).max(64).optional().describe('Free-form label for your own bookkeeping (e.g. `"supplier"`) \u2014 never interpreted.')
|
|
750
|
+
});
|
|
751
|
+
var RecipientSchema = z13.object({
|
|
752
|
+
id: z13.string().describe(
|
|
753
|
+
"Klappay-generated id, e.g. `rc_...` \u2014 this, not the raw address, is what a charge's `splitRecipients[].recipientId` references."
|
|
754
|
+
),
|
|
755
|
+
environment: EnvironmentSchema,
|
|
756
|
+
address: z13.string(),
|
|
757
|
+
label: z13.string().nullable(),
|
|
758
|
+
payout: z13.boolean().describe(
|
|
759
|
+
"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`."
|
|
760
|
+
),
|
|
761
|
+
createdAt: z13.string().datetime()
|
|
762
|
+
});
|
|
763
|
+
var SetRecipientPayoutSchema = z13.object({
|
|
764
|
+
payout: z13.boolean().describe("New payout-eligibility value for this recipient.")
|
|
765
|
+
});
|
|
766
|
+
|
|
767
|
+
// src/timeline.ts
|
|
768
|
+
import { z as z14 } from "zod";
|
|
769
|
+
var TransactionSourceSchema = z14.enum(["moralis_webhook", "reconciliation_job", "sandbox"]).describe(
|
|
722
770
|
"How this transfer was detected: `moralis_webhook` (the normal path), `reconciliation_job` (a fallback poller caught it after the webhook was missed or delayed), or `sandbox` (simulated via `POST /v1/sandbox/charges/{id}/trigger`, no real on-chain transfer)."
|
|
723
771
|
);
|
|
724
|
-
var TimelineEventTypeSchema =
|
|
772
|
+
var TimelineEventTypeSchema = z14.enum([
|
|
725
773
|
"charge.created",
|
|
726
774
|
"charge.expired",
|
|
727
775
|
"transaction.detected",
|
|
@@ -732,11 +780,11 @@ var TimelineEventTypeSchema = z13.enum([
|
|
|
732
780
|
]).describe(
|
|
733
781
|
"`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)."
|
|
734
782
|
);
|
|
735
|
-
var TimelineEventSchema =
|
|
783
|
+
var TimelineEventSchema = z14.object({
|
|
736
784
|
type: TimelineEventTypeSchema,
|
|
737
|
-
at:
|
|
738
|
-
txHash:
|
|
739
|
-
amount:
|
|
785
|
+
at: z14.string().datetime(),
|
|
786
|
+
txHash: z14.string().optional().describe("Present for `transaction.detected` and `split.distributed` events only."),
|
|
787
|
+
amount: z14.number().optional().describe(
|
|
740
788
|
"Present for `transaction.detected` events only \u2014 the amount that specific transfer carried."
|
|
741
789
|
),
|
|
742
790
|
source: TransactionSourceSchema.optional().describe(
|
|
@@ -748,49 +796,49 @@ var TimelineEventSchema = z13.object({
|
|
|
748
796
|
network: NetworkSchema.optional().describe(
|
|
749
797
|
"Present for `transaction.detected` and `split.distributed` events \u2014 which network this specific transfer, or settlement, used."
|
|
750
798
|
),
|
|
751
|
-
causedTransition:
|
|
799
|
+
causedTransition: z14.boolean().optional().describe(
|
|
752
800
|
"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."
|
|
753
801
|
),
|
|
754
802
|
event: WebhookEventTypeSchema.optional().describe(
|
|
755
803
|
"Present for `webhook.*` events only \u2014 which event type this delivery was for."
|
|
756
804
|
),
|
|
757
|
-
responseCode:
|
|
805
|
+
responseCode: z14.number().nullable().optional().describe(
|
|
758
806
|
"Present for `webhook.*` events only \u2014 HTTP status your endpoint returned, or `null` if the request never connected."
|
|
759
807
|
),
|
|
760
|
-
attempts:
|
|
808
|
+
attempts: z14.number().optional().describe(
|
|
761
809
|
"Present for `webhook.*` events only \u2014 how many delivery attempts have been made so far."
|
|
762
810
|
)
|
|
763
811
|
});
|
|
764
812
|
|
|
765
813
|
// src/health.ts
|
|
766
|
-
import { z as
|
|
767
|
-
var HealthSchema =
|
|
768
|
-
status:
|
|
814
|
+
import { z as z15 } from "zod";
|
|
815
|
+
var HealthSchema = z15.object({
|
|
816
|
+
status: z15.enum(["ok", "error"]).describe(
|
|
769
817
|
"`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."
|
|
770
818
|
),
|
|
771
|
-
version:
|
|
772
|
-
timestamp:
|
|
773
|
-
db:
|
|
774
|
-
pendingWebhooks:
|
|
775
|
-
oldestPendingChargeAgeSeconds:
|
|
776
|
-
lastMoralisEventAgeSeconds:
|
|
819
|
+
version: z15.string(),
|
|
820
|
+
timestamp: z15.string().datetime(),
|
|
821
|
+
db: z15.enum(["ok", "error"]).describe("Result of a real database connectivity check, not just a process-alive check."),
|
|
822
|
+
pendingWebhooks: z15.number().describe("Count of webhook deliveries still awaiting a successful attempt."),
|
|
823
|
+
oldestPendingChargeAgeSeconds: z15.number().nullable().describe("Age of the oldest still-unpaid charge, in seconds. `null` if there are none."),
|
|
824
|
+
lastMoralisEventAgeSeconds: z15.number().nullable().describe(
|
|
777
825
|
"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."
|
|
778
826
|
)
|
|
779
827
|
});
|
|
780
828
|
|
|
781
829
|
// src/sandbox.ts
|
|
782
|
-
import { z as
|
|
783
|
-
var SandboxTriggerSchema =
|
|
830
|
+
import { z as z16 } from "zod";
|
|
831
|
+
var SandboxTriggerSchema = z16.object({
|
|
784
832
|
event: TriggerableChargeEventSchema,
|
|
785
|
-
amount:
|
|
833
|
+
amount: z16.number().positive().max(CHARGE_AMOUNT_MAX).optional().describe(
|
|
786
834
|
"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."
|
|
787
835
|
)
|
|
788
836
|
});
|
|
789
837
|
|
|
790
838
|
// src/capabilities.ts
|
|
791
|
-
import { z as
|
|
792
|
-
var CapabilitiesSchema =
|
|
793
|
-
acceptedPayments:
|
|
839
|
+
import { z as z17 } from "zod";
|
|
840
|
+
var CapabilitiesSchema = z17.object({
|
|
841
|
+
acceptedPayments: z17.array(AcceptedPaymentSchema).describe(
|
|
794
842
|
"Every `(token, network)` pair actually configured for your environment right now \u2014 read straight from the same lookup `POST /v1/charges` validates `acceptedPayments` against, so it can never list a pair that charge creation would then reject. Use this to build a picker UI instead of hardcoding the matrix client-side."
|
|
795
843
|
)
|
|
796
844
|
});
|
|
@@ -803,6 +851,8 @@ export {
|
|
|
803
851
|
CHARGE_EXPIRES_IN_MAX_SECONDS,
|
|
804
852
|
CHARGE_EXPIRES_IN_MIN_SECONDS,
|
|
805
853
|
CHARGE_SPLIT_RECIPIENTS_MAX,
|
|
854
|
+
CHECKOUT_PRODUCTS_MAX,
|
|
855
|
+
CONFLICTING_SCOPE_PAIRS,
|
|
806
856
|
CapabilitiesSchema,
|
|
807
857
|
ChargeSchema,
|
|
808
858
|
ChargeStatusSchema,
|
|
@@ -810,7 +860,9 @@ export {
|
|
|
810
860
|
ChargesDateFieldSchema,
|
|
811
861
|
ChargesMetricFieldSchema,
|
|
812
862
|
ChargesQueryFieldSchema,
|
|
863
|
+
CheckoutProductSchema,
|
|
813
864
|
CreateChargeSchema,
|
|
865
|
+
CreateRecipientSchema,
|
|
814
866
|
CreateWebhookSchema,
|
|
815
867
|
DistributionsDateFieldSchema,
|
|
816
868
|
DistributionsMetricFieldSchema,
|
|
@@ -821,6 +873,7 @@ export {
|
|
|
821
873
|
ErrorPayloadSchema,
|
|
822
874
|
GetChargeQrCodeQuerySchema,
|
|
823
875
|
HealthSchema,
|
|
876
|
+
KlappayCheckoutMetadataSchema,
|
|
824
877
|
ListChargesSchema,
|
|
825
878
|
ListWebhookDeliveriesSchema,
|
|
826
879
|
ListenPendingDistributionsQuerySchema,
|
|
@@ -830,6 +883,7 @@ export {
|
|
|
830
883
|
METRICS_QUERY_MAX_GROUP_BY,
|
|
831
884
|
METRICS_QUERY_MAX_METRICS,
|
|
832
885
|
METRICS_QUERY_MAX_ROW_LIMIT,
|
|
886
|
+
MetadataWithKlappaySchema,
|
|
833
887
|
MetricsAggregationSchema,
|
|
834
888
|
MetricsDateGranularitySchema,
|
|
835
889
|
MetricsFilterOperatorSchema,
|
|
@@ -851,9 +905,12 @@ export {
|
|
|
851
905
|
PendingDistributionEventSchema,
|
|
852
906
|
PendingDistributionRecipientSchema,
|
|
853
907
|
PendingDistributionSchema,
|
|
908
|
+
RecipientSchema,
|
|
854
909
|
SandboxTriggerSchema,
|
|
910
|
+
SetRecipientPayoutSchema,
|
|
855
911
|
SettlementStatusSchema,
|
|
856
912
|
SplitDistributionStatusSchema,
|
|
913
|
+
SplitRecipientInputSchema,
|
|
857
914
|
SplitRecipientSchema,
|
|
858
915
|
TOKEN_ADDRESSES,
|
|
859
916
|
TOKEN_DECIMALS,
|
|
@@ -875,6 +932,7 @@ export {
|
|
|
875
932
|
WebhookListItemSchema,
|
|
876
933
|
WebhookPayloadSchema,
|
|
877
934
|
WebhookSchema,
|
|
935
|
+
findConflictingScopes,
|
|
878
936
|
paginatedSchema
|
|
879
937
|
};
|
|
880
938
|
//# sourceMappingURL=index.mjs.map
|