@fun-xyz/fiat-contract 0.20.1 → 0.21.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 CHANGED
@@ -99,46 +99,61 @@ this package is [ENG-5268](https://linear.app/funxyz/issue/ENG-5268).
99
99
 
100
100
  A provider can run its own flow instead of the shared step machine. `POST /fiat/quote` still routes
101
101
  and prices. When the request's `handoffs` lists the winning provider, the response carries
102
- `handoff: { provider, terms }` and no transitions, and the client calls that provider's
103
- `POST /fiat/providers/{provider}/intent`. `terms` lists the `CHECKOUT` documents this login has not
104
- accepted at the current version; it is empty for a returning buyer. The schema refuses a handoff on
105
- any state but `QUOTE`, a handoff to a provider other than the response's own, a handoff that still
106
- offers transitions, and a `terms` entry that is not a unique `CHECKOUT` document.
102
+ `handoff: { provider }` and no transitions. The client shows that provider's `CHECKOUT` documents
103
+ from `PROVIDER_CHECKOUT_DOCUMENTS`, records them with `POST /fiat/terms` on Continue, and then calls
104
+ `POST /fiat/providers/{provider}/intent`. The schema refuses a handoff on any state but `QUOTE`, a
105
+ handoff to a provider other than the response's own, and a handoff that still offers transitions.
107
106
 
108
107
  **Terms (`./terms`).** Every provider records acceptances through the platform `POST /fiat/terms`
109
- (`FIAT_TERMS_ENDPOINT`), with an `Idempotency-Key`. A `TermsDocument` has an `id`, a `kind`
110
- (`FUN_TERMS`, `PROVIDER_TERMS`, `FUN_KYC_COLLECTION`, `PROVIDER_KYC_SHARING`), a `stage` (`CHECKOUT` or
108
+ (`FIAT_TERMS_ENDPOINT`). A `TermsDocument` has an `id`, a `kind`
109
+ (`PROVIDER_TERMS`, `FUN_KYC_COLLECTION`, `PROVIDER_KYC_SHARING`), a `stage` (`CHECKOUT` or
111
110
  `KYC`), an opaque `version` and `contentDigest`, and at least one `https` link. `FiatTermsRequest` is
112
111
  `{ provider, acceptances: [{ documentId, version, contentDigest, acceptedAt }] }`, each document at
113
112
  most once; `FiatTermsResponse` is `{ recorded }`, the recorded document ids. A fault is a
114
113
  `FiatTermsErrorBody`: the shared `errorCode`, `errorMsg` and `reqId`, plus `reason` (`STALE_TERMS`,
115
- `IN_PROGRESS`, `IDEMPOTENCY_KEY_REUSED`, `INVALID_REQUEST`, `RATE_LIMITED`, `PROVIDER_UNAVAILABLE`) and `recovery`.
114
+ `IN_PROGRESS`, `INVALID_REQUEST`, `RATE_LIMITED`, `PROVIDER_UNAVAILABLE`) and `recovery`.
115
+
116
+ The package publishes every document as a constant, so the client and the backend read the same
117
+ text. `PROVIDER_CHECKOUT_DOCUMENTS` maps each provider to its current `CHECKOUT` documents.
118
+ `FUN_KYC_CONSENT_DOCUMENTS` is Fun's KYC consent, one digest per `FunKycConsentLocale`.
119
+ `PUBLISHED_TERMS_DOCUMENTS` is every version and locale ever published. Every published version
120
+ stays valid: the backend refuses only an unknown version, a wrong digest, or an `acceptedAt` older
121
+ than 5 minutes. A repeat of a version the login already holds writes nothing and returns the ids.
116
122
 
117
123
  **MoonPay (`./moonpay`).** One route, `MOONPAY_ENDPOINTS.intent`. A `MoonPayIntentRequest` is one of
118
124
  three kinds:
119
125
 
120
- | `kind` | Carries | `Idempotency-Key` |
126
+ | `kind` | Carries | A repeat |
121
127
  | --- | --- | --- |
122
- | `observe` | `checkout`, and `credentials` (`customerId`, `accessToken`) once the SDK has them | ignored |
123
- | `kyc` | `checkout`, `credentials`, `values` keyed by field id (no form id) | required |
124
- | `order` | `orderId`, `transactionId` | required |
128
+ | `observe` | `checkout`, and `credentials` (`customerId`, `accessToken`) once the SDK has them | writes nothing new |
129
+ | `kyc` | `checkout`, `credentials`, `values` keyed by `KycFieldId` (no form id) | drops values MoonPay no longer asks for; a concurrent one gets `409 IN_PROGRESS` |
130
+ | `order` | `orderId`, `transactionId` | returns the claimed order |
125
131
 
126
- A `MoonPayIntentResponse` says what the backend needs next:
132
+ `observe` and `kyc` answer a `MoonPayStepResponse`, which says what the backend needs next:
127
133
 
128
134
  | `status` | Carries | The client then |
129
135
  | --- | --- | --- |
130
136
  | `TERMS` | `stage`, `documents` (at least one, all at `stage`) | sends `POST /fiat/terms`, then `observe` |
131
137
  | `SDK_AUTH` | `sessionToken`, `quoteInput` | runs the MoonPay connection check, then `observe` with credentials |
132
138
  | `KYC` | `fields`, `fieldErrors?` (each naming a field in `fields`) | shows the shared form, then sends `kyc` |
133
- | `PENDING` | `retryAfterMs` (at most 60 s) | sends the same request again after the delay |
139
+ | `PENDING` | `retryAfterMs` (at most 60 s) | sends `observe` after the delay, never `kyc` again |
134
140
  | `READY` | `orderId`, `quoteInput` | mounts Apple Pay, then sends `order` after the charge |
135
- | `DONE` | `order`, the `GET /fiat/orders/:orderId` response | shows the shared order status |
136
141
  | `REFUSED` | `reason` (`NOT_ELIGIBLE`, `DOCUMENTS_REQUIRED`, `FINAL_REJECTION`, `CUSTOMER_MISMATCH`), `recovery: REQUOTE \| NONE` | exits the provider flow |
137
142
 
143
+ `order` runs after the charge and answers a `MoonPayOrderResponse`:
144
+
145
+ | `status` | Carries | The client then |
146
+ | --- | --- | --- |
147
+ | `DONE` | `order`, the `GET /fiat/orders/:orderId` response | shows the shared order status |
148
+ | `PENDING` | `retryAfterMs` (at most 60 s) | sends the same `order` after the delay |
149
+ | `REFUSED` | `reason` (`CUSTOMER_MISMATCH`, `WALLET_MISMATCH`, `UNRECORDABLE`), `recovery: NONE` | exits the provider flow |
150
+
151
+ `MoonPayIntentResponseFor` maps each `kind` to its union, and `MoonPayIntentResponse` is both.
152
+
138
153
  A fault is a 4xx or 5xx with a `MoonPayErrorBody`: the shared `errorCode`, `errorMsg` and `reqId`,
139
154
  plus `reason` (`SESSION_BUDGET_SPENT`, `RATE_LIMITED`, `PROVIDER_UNAVAILABLE`, `IN_PROGRESS`,
140
- `IDEMPOTENCY_KEY_REUSED`, `INVALID_REQUEST`, `TRANSACTION_MISMATCH`, `WALLET_MISMATCH`) and `recovery`:
141
- `RETRY` (send the same request, with the same key), `REQUOTE`, or `NONE`. A field error is a `KYC`
155
+ `INVALID_REQUEST`) and `recovery`:
156
+ `RETRY` (send the same request again), `REQUOTE`, or `NONE`. A field error is a `KYC`
142
157
  response, not a fault. The zod schemas (`MoonPay*Schema`, `TermsDocumentSchema`, `FiatTerms*Schema`)
143
158
  are exported from the root only.
144
159
 
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "0.20.1";
2
+ var version = "0.21.0";
3
3
 
4
4
  // src/table.ts
5
5
  var TABLE_VERSION = version;
@@ -514,4 +514,4 @@ export {
514
514
  tableEntry,
515
515
  isTerminal
516
516
  };
517
- //# sourceMappingURL=chunk-544S4IEU.mjs.map
517
+ //# sourceMappingURL=chunk-LBYBZDOW.mjs.map
@@ -0,0 +1,44 @@
1
+ // src/terms.ts
2
+ var FIAT_TERMS_ENDPOINT = "POST /fiat/terms";
3
+ var MOONPAY_TERMS = {
4
+ id: "MOONPAY_TERMS",
5
+ kind: "PROVIDER_TERMS",
6
+ stage: "CHECKOUT",
7
+ version: "2026-09-l2-kyc-sharing-v2",
8
+ contentDigest: "44e096af329262134fe6680659c9bd42014cbf5e96f064d67869173a4f7d822b",
9
+ links: [
10
+ { label: "MoonPay Terms of Use", url: "https://www.moonpay.com/legal/terms" },
11
+ { label: "MoonPay Privacy Policy", url: "https://www.moonpay.com/legal/privacy_policy" },
12
+ { label: "Persona Privacy Policy", url: "https://withpersona.com/legal/privacy-policy" }
13
+ ]
14
+ };
15
+ var PROVIDER_CHECKOUT_DOCUMENTS = {
16
+ MOONPAY: [MOONPAY_TERMS]
17
+ };
18
+ var funKycConsent = (contentDigest) => ({
19
+ id: "FUN_KYC_CONSENT",
20
+ kind: "FUN_KYC_COLLECTION",
21
+ stage: "KYC",
22
+ version: "fun-kyc-consent-2026-09-11",
23
+ contentDigest,
24
+ links: [{ label: "Fun.xyz Privacy Policy", url: "https://fun.xyz/privacy" }]
25
+ });
26
+ var FUN_KYC_CONSENT_DOCUMENTS = {
27
+ en: funKycConsent("da31f2467deb996476b131116508ea2a00220765e658a79abc6d2bd44337504a"),
28
+ es: funKycConsent("73753b70ad8d1b48dfdcda35e6028c3a7ada66c311a67a1d8f6fe13c76a32f3b"),
29
+ fr: funKycConsent("5ee82675984591dbf66337f31246179103c5624a189850943d400f9b85a84965"),
30
+ ja: funKycConsent("3f272da313f66601a20c3ca43c967aff4bb7f73488177f0a4ce94cbc78bafce2"),
31
+ ko: funKycConsent("aab7839bfba3f34aa47ca6b10647c2c8965c37d845494ef8f3067ca3e3821200"),
32
+ ru: funKycConsent("17168083ebcc4fd11ea80b08c3f230bdec03a1e7b89173a38819ae5533b0fc96"),
33
+ tr: funKycConsent("463040c3b58c922ecae2ae8262a78eb732bbcc5606c394723626378b3db2bbc3"),
34
+ zh: funKycConsent("7f76d850adaf69783c5d9365e51abb5446f4e5778c63eabbdb4784d72464f855")
35
+ };
36
+ var PUBLISHED_TERMS_DOCUMENTS = [MOONPAY_TERMS, ...Object.values(FUN_KYC_CONSENT_DOCUMENTS)];
37
+
38
+ export {
39
+ FIAT_TERMS_ENDPOINT,
40
+ PROVIDER_CHECKOUT_DOCUMENTS,
41
+ FUN_KYC_CONSENT_DOCUMENTS,
42
+ PUBLISHED_TERMS_DOCUMENTS
43
+ };
44
+ //# sourceMappingURL=chunk-N6GHUS2K.mjs.map
@@ -6,4 +6,4 @@ var MOONPAY_ENDPOINTS = {
6
6
  export {
7
7
  MOONPAY_ENDPOINTS
8
8
  };
9
- //# sourceMappingURL=chunk-UN3WTIMI.mjs.map
9
+ //# sourceMappingURL=chunk-YOMQWXTD.mjs.map
package/dist/index.js CHANGED
@@ -36,6 +36,7 @@ __export(index_exports, {
36
36
  FIELD_SPEC_TYPES: () => FIELD_SPEC_TYPES,
37
37
  FIXTURES: () => FIXTURES,
38
38
  FIXTURE_COVERAGE_GAPS: () => FIXTURE_COVERAGE_GAPS,
39
+ FUN_KYC_CONSENT_DOCUMENTS: () => FUN_KYC_CONSENT_DOCUMENTS,
39
40
  FailureReasonSchema: () => FailureReasonSchema,
40
41
  FeeLineSchema: () => FeeLineSchema,
41
42
  FiatAmountSchema: () => FiatAmountSchema,
@@ -60,6 +61,7 @@ __export(index_exports, {
60
61
  KYCProviderSchema: () => KYCProviderSchema,
61
62
  KYC_ACKNOWLEDGEMENT_FIELD_IDS: () => KYC_ACKNOWLEDGEMENT_FIELD_IDS,
62
63
  KycCaptureStateSchema: () => KycCaptureStateSchema,
64
+ KycFieldIdSchema: () => KycFieldIdSchema,
63
65
  KycInputRequiredStateSchema: () => KycInputRequiredStateSchema,
64
66
  KycNoActionRequiredStateSchema: () => KycNoActionRequiredStateSchema,
65
67
  KycSdkResultReportSchema: () => KycSdkResultReportSchema,
@@ -69,14 +71,18 @@ __export(index_exports, {
69
71
  MoonPayFaultSchema: () => MoonPayFaultSchema,
70
72
  MoonPayIntentRequestSchema: () => MoonPayIntentRequestSchema,
71
73
  MoonPayIntentResponseSchema: () => MoonPayIntentResponseSchema,
74
+ MoonPayOrderResponseSchema: () => MoonPayOrderResponseSchema,
72
75
  MoonPayQuoteInputSchema: () => MoonPayQuoteInputSchema,
73
76
  MoonPaySdkCredentialsSchema: () => MoonPaySdkCredentialsSchema,
77
+ MoonPayStepResponseSchema: () => MoonPayStepResponseSchema,
74
78
  OrderAwaitingConfirmationStateSchema: () => OrderAwaitingConfirmationStateSchema,
75
79
  OrderCreatedStateSchema: () => OrderCreatedStateSchema,
76
80
  OrderRefSchema: () => OrderRefSchema,
77
81
  OrderStatusSchema: () => OrderStatusSchema,
78
82
  OrderSummarySchema: () => OrderSummarySchema,
79
83
  PAYMENT_METHOD_CATEGORIES: () => PAYMENT_METHOD_CATEGORIES,
84
+ PROVIDER_CHECKOUT_DOCUMENTS: () => PROVIDER_CHECKOUT_DOCUMENTS,
85
+ PUBLISHED_TERMS_DOCUMENTS: () => PUBLISHED_TERMS_DOCUMENTS,
80
86
  PaymentCaptureStateSchema: () => PaymentCaptureStateSchema,
81
87
  PaymentInstructStateSchema: () => PaymentInstructStateSchema,
82
88
  PaymentSurfaceSchema: () => PaymentSurfaceSchema,
@@ -658,6 +664,7 @@ var $kycFieldId = import_zod.z.union([
658
664
  import_zod.z.enum(KYC_ACKNOWLEDGEMENT_FIELD_IDS),
659
665
  $questionnaireKycFieldId
660
666
  ]);
667
+ var KycFieldIdSchema = $kycFieldId;
661
668
  var $clientExecutedDelivery = obj({
662
669
  channel: import_zod.z.literal("CLIENT_EXECUTED"),
663
670
  source: import_zod.z.literal("CURRENT_SESSION_INPUTS"),
@@ -971,7 +978,7 @@ var $nonBlank = import_zod.z.string().refine((value) => value.trim().length > 0,
971
978
  var $termsStage = import_zod.z.enum(["CHECKOUT", "KYC"]);
972
979
  var $termsDocument = obj({
973
980
  id: $nonBlank,
974
- kind: import_zod.z.enum(["FUN_TERMS", "PROVIDER_TERMS", "FUN_KYC_COLLECTION", "PROVIDER_KYC_SHARING"]),
981
+ kind: import_zod.z.enum(["PROVIDER_TERMS", "FUN_KYC_COLLECTION", "PROVIDER_KYC_SHARING"]),
975
982
  stage: $termsStage,
976
983
  version: $nonBlank,
977
984
  contentDigest: $nonBlank,
@@ -979,10 +986,6 @@ var $termsDocument = obj({
979
986
  });
980
987
  var TermsDocumentSchema = $termsDocument;
981
988
  var hasUniqueIds = (ids) => new Set(ids).size === ids.length;
982
- var $termsDocuments = (stage) => import_zod.z.array($termsDocument).refine((documents) => hasUniqueIds(documents.map((document) => document.id)), "document ids must be unique").refine(
983
- (documents) => stage === void 0 || documents.every((document) => document.stage === stage),
984
- `every document must be at stage ${stage}`
985
- );
986
989
  var $termsAcceptance = obj({
987
990
  documentId: $nonBlank,
988
991
  version: $nonBlank,
@@ -1001,7 +1004,7 @@ var $termsErrorBody = obj({
1001
1004
  errorCode: $nonBlank,
1002
1005
  errorMsg: import_zod.z.string(),
1003
1006
  reqId: import_zod.z.string().optional(),
1004
- reason: import_zod.z.enum(["STALE_TERMS", "IN_PROGRESS", "IDEMPOTENCY_KEY_REUSED", "INVALID_REQUEST", "RATE_LIMITED", "PROVIDER_UNAVAILABLE"]),
1007
+ reason: import_zod.z.enum(["STALE_TERMS", "IN_PROGRESS", "INVALID_REQUEST", "RATE_LIMITED", "PROVIDER_UNAVAILABLE"]),
1005
1008
  recovery: import_zod.z.enum(["RETRY", "REQUOTE", "NONE"])
1006
1009
  });
1007
1010
  var FiatTermsErrorBodySchema = $termsErrorBody;
@@ -1010,7 +1013,7 @@ var $providerBoundStepResponse = obj({
1010
1013
  provider: $provider,
1011
1014
  transitions: import_zod.z.array($transition),
1012
1015
  preparedPayment: $preparedPayment.optional(),
1013
- handoff: obj({ provider: $provider, terms: $termsDocuments("CHECKOUT") }).optional(),
1016
+ handoff: obj({ provider: $provider }).optional(),
1014
1017
  routingSessionRef: import_zod.z.string().optional(),
1015
1018
  providerAuthToken: obj({
1016
1019
  clientSecret: import_zod.z.string(),
@@ -1064,7 +1067,7 @@ var $stepResponse = import_zod.z.union([$providerBoundStepResponse, $blockedStep
1064
1067
  var FiatStepResponseSchema = $stepResponse;
1065
1068
 
1066
1069
  // package.json
1067
- var version = "0.20.1";
1070
+ var version = "0.21.0";
1068
1071
 
1069
1072
  // src/table.ts
1070
1073
  var TABLE_VERSION = version;
@@ -2632,6 +2635,40 @@ function assertAllFixtures() {
2632
2635
 
2633
2636
  // src/terms.ts
2634
2637
  var FIAT_TERMS_ENDPOINT = "POST /fiat/terms";
2638
+ var MOONPAY_TERMS = {
2639
+ id: "MOONPAY_TERMS",
2640
+ kind: "PROVIDER_TERMS",
2641
+ stage: "CHECKOUT",
2642
+ version: "2026-09-l2-kyc-sharing-v2",
2643
+ contentDigest: "44e096af329262134fe6680659c9bd42014cbf5e96f064d67869173a4f7d822b",
2644
+ links: [
2645
+ { label: "MoonPay Terms of Use", url: "https://www.moonpay.com/legal/terms" },
2646
+ { label: "MoonPay Privacy Policy", url: "https://www.moonpay.com/legal/privacy_policy" },
2647
+ { label: "Persona Privacy Policy", url: "https://withpersona.com/legal/privacy-policy" }
2648
+ ]
2649
+ };
2650
+ var PROVIDER_CHECKOUT_DOCUMENTS = {
2651
+ MOONPAY: [MOONPAY_TERMS]
2652
+ };
2653
+ var funKycConsent = (contentDigest) => ({
2654
+ id: "FUN_KYC_CONSENT",
2655
+ kind: "FUN_KYC_COLLECTION",
2656
+ stage: "KYC",
2657
+ version: "fun-kyc-consent-2026-09-11",
2658
+ contentDigest,
2659
+ links: [{ label: "Fun.xyz Privacy Policy", url: "https://fun.xyz/privacy" }]
2660
+ });
2661
+ var FUN_KYC_CONSENT_DOCUMENTS = {
2662
+ en: funKycConsent("da31f2467deb996476b131116508ea2a00220765e658a79abc6d2bd44337504a"),
2663
+ es: funKycConsent("73753b70ad8d1b48dfdcda35e6028c3a7ada66c311a67a1d8f6fe13c76a32f3b"),
2664
+ fr: funKycConsent("5ee82675984591dbf66337f31246179103c5624a189850943d400f9b85a84965"),
2665
+ ja: funKycConsent("3f272da313f66601a20c3ca43c967aff4bb7f73488177f0a4ce94cbc78bafce2"),
2666
+ ko: funKycConsent("aab7839bfba3f34aa47ca6b10647c2c8965c37d845494ef8f3067ca3e3821200"),
2667
+ ru: funKycConsent("17168083ebcc4fd11ea80b08c3f230bdec03a1e7b89173a38819ae5533b0fc96"),
2668
+ tr: funKycConsent("463040c3b58c922ecae2ae8262a78eb732bbcc5606c394723626378b3db2bbc3"),
2669
+ zh: funKycConsent("7f76d850adaf69783c5d9365e51abb5446f4e5778c63eabbdb4784d72464f855")
2670
+ };
2671
+ var PUBLISHED_TERMS_DOCUMENTS = [MOONPAY_TERMS, ...Object.values(FUN_KYC_CONSENT_DOCUMENTS)];
2635
2672
 
2636
2673
  // src/providers/moonpay.ts
2637
2674
  var MOONPAY_ENDPOINTS = {
@@ -2659,7 +2696,7 @@ var $intentRequest = import_zod2.z.discriminatedUnion("kind", [
2659
2696
  kind: import_zod2.z.literal("kyc"),
2660
2697
  checkout: $checkout,
2661
2698
  credentials: $credentials,
2662
- values: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.string()).refine((values) => Object.keys(values).length > 0, "values must not be empty")
2699
+ values: import_zod2.z.record(KycFieldIdSchema, import_zod2.z.string()).refine((values) => Object.keys(values).length > 0, "values must not be empty")
2663
2700
  }),
2664
2701
  obj2({ kind: import_zod2.z.literal("order"), orderId: $nonEmpty, transactionId: $nonEmpty })
2665
2702
  ]);
@@ -2672,18 +2709,19 @@ var $quoteInput = obj2({
2672
2709
  feeBehavior: import_zod2.z.literal("inclusive")
2673
2710
  });
2674
2711
  var MoonPayQuoteInputSchema = $quoteInput;
2675
- var $refusal = import_zod2.z.enum(["NOT_ELIGIBLE", "DOCUMENTS_REQUIRED", "FINAL_REJECTION", "CUSTOMER_MISMATCH"]);
2712
+ var $stepRefusal = import_zod2.z.enum(["NOT_ELIGIBLE", "DOCUMENTS_REQUIRED", "FINAL_REJECTION", "CUSTOMER_MISMATCH"]);
2713
+ var $orderRefusal = import_zod2.z.enum(["CUSTOMER_MISMATCH", "WALLET_MISMATCH", "UNRECORDABLE"]);
2676
2714
  var $fieldError = obj2({ fieldId: $nonEmpty, message: $nonEmpty });
2677
- var $intentStatus = import_zod2.z.discriminatedUnion("status", [
2715
+ var $pending = obj2({ status: import_zod2.z.literal("PENDING"), retryAfterMs: import_zod2.z.number().int().positive().max(6e4) });
2716
+ var $stepStatus = import_zod2.z.discriminatedUnion("status", [
2678
2717
  obj2({ status: import_zod2.z.literal("TERMS"), stage: import_zod2.z.enum(["CHECKOUT", "KYC"]), documents: import_zod2.z.array(TermsDocumentSchema).min(1) }),
2679
2718
  obj2({ status: import_zod2.z.literal("SDK_AUTH"), sessionToken: $nonEmpty, quoteInput: $quoteInput }),
2680
2719
  obj2({ status: import_zod2.z.literal("KYC"), fields: import_zod2.z.array(FormFieldSchema).min(1), fieldErrors: import_zod2.z.array($fieldError).min(1).optional() }),
2681
- obj2({ status: import_zod2.z.literal("PENDING"), retryAfterMs: import_zod2.z.number().int().positive().max(6e4) }),
2720
+ $pending,
2682
2721
  obj2({ status: import_zod2.z.literal("READY"), orderId: $nonEmpty, quoteInput: $quoteInput }),
2683
- obj2({ status: import_zod2.z.literal("DONE"), order: FiatStepResponseSchema }),
2684
- obj2({ status: import_zod2.z.literal("REFUSED"), reason: $refusal, recovery: import_zod2.z.enum(["REQUOTE", "NONE"]) })
2722
+ obj2({ status: import_zod2.z.literal("REFUSED"), reason: $stepRefusal, recovery: import_zod2.z.enum(["REQUOTE", "NONE"]) })
2685
2723
  ]);
2686
- var $intentResponse = $intentStatus.superRefine((response, context) => {
2724
+ var $stepResponse2 = $stepStatus.superRefine((response, context) => {
2687
2725
  if (response.status === "TERMS") {
2688
2726
  if (!hasUniqueIds2(response.documents.map((document) => document.id))) {
2689
2727
  context.addIssue({ code: "custom", path: ["documents"], message: "document ids must be unique" });
@@ -2702,6 +2740,14 @@ var $intentResponse = $intentStatus.superRefine((response, context) => {
2702
2740
  }
2703
2741
  }
2704
2742
  });
2743
+ var MoonPayStepResponseSchema = $stepResponse2;
2744
+ var $orderResponse = import_zod2.z.discriminatedUnion("status", [
2745
+ obj2({ status: import_zod2.z.literal("DONE"), order: FiatStepResponseSchema }),
2746
+ $pending,
2747
+ obj2({ status: import_zod2.z.literal("REFUSED"), reason: $orderRefusal, recovery: import_zod2.z.literal("NONE") })
2748
+ ]);
2749
+ var MoonPayOrderResponseSchema = $orderResponse;
2750
+ var $intentResponse = import_zod2.z.union([$stepResponse2, $orderResponse]);
2705
2751
  var MoonPayIntentResponseSchema = $intentResponse;
2706
2752
  var $faultFields = {
2707
2753
  reason: import_zod2.z.enum([
@@ -2709,10 +2755,7 @@ var $faultFields = {
2709
2755
  "RATE_LIMITED",
2710
2756
  "PROVIDER_UNAVAILABLE",
2711
2757
  "IN_PROGRESS",
2712
- "IDEMPOTENCY_KEY_REUSED",
2713
- "INVALID_REQUEST",
2714
- "TRANSACTION_MISMATCH",
2715
- "WALLET_MISMATCH"
2758
+ "INVALID_REQUEST"
2716
2759
  ]),
2717
2760
  recovery: import_zod2.z.enum(["RETRY", "REQUOTE", "NONE"])
2718
2761
  };
package/dist/index.mjs CHANGED
@@ -12,13 +12,16 @@ import {
12
12
  tableEntry,
13
13
  unofferedEndpoints,
14
14
  unreachableStates
15
- } from "./chunk-544S4IEU.mjs";
15
+ } from "./chunk-LBYBZDOW.mjs";
16
16
  import {
17
17
  MOONPAY_ENDPOINTS
18
- } from "./chunk-UN3WTIMI.mjs";
18
+ } from "./chunk-YOMQWXTD.mjs";
19
19
  import {
20
- FIAT_TERMS_ENDPOINT
21
- } from "./chunk-WRRCWAY2.mjs";
20
+ FIAT_TERMS_ENDPOINT,
21
+ FUN_KYC_CONSENT_DOCUMENTS,
22
+ PROVIDER_CHECKOUT_DOCUMENTS,
23
+ PUBLISHED_TERMS_DOCUMENTS
24
+ } from "./chunk-N6GHUS2K.mjs";
22
25
 
23
26
  // src/codes.ts
24
27
  var US_STATE_CODES = [
@@ -545,6 +548,7 @@ var $kycFieldId = z.union([
545
548
  z.enum(KYC_ACKNOWLEDGEMENT_FIELD_IDS),
546
549
  $questionnaireKycFieldId
547
550
  ]);
551
+ var KycFieldIdSchema = $kycFieldId;
548
552
  var $clientExecutedDelivery = obj({
549
553
  channel: z.literal("CLIENT_EXECUTED"),
550
554
  source: z.literal("CURRENT_SESSION_INPUTS"),
@@ -858,7 +862,7 @@ var $nonBlank = z.string().refine((value) => value.trim().length > 0, "must not
858
862
  var $termsStage = z.enum(["CHECKOUT", "KYC"]);
859
863
  var $termsDocument = obj({
860
864
  id: $nonBlank,
861
- kind: z.enum(["FUN_TERMS", "PROVIDER_TERMS", "FUN_KYC_COLLECTION", "PROVIDER_KYC_SHARING"]),
865
+ kind: z.enum(["PROVIDER_TERMS", "FUN_KYC_COLLECTION", "PROVIDER_KYC_SHARING"]),
862
866
  stage: $termsStage,
863
867
  version: $nonBlank,
864
868
  contentDigest: $nonBlank,
@@ -866,10 +870,6 @@ var $termsDocument = obj({
866
870
  });
867
871
  var TermsDocumentSchema = $termsDocument;
868
872
  var hasUniqueIds = (ids) => new Set(ids).size === ids.length;
869
- var $termsDocuments = (stage) => z.array($termsDocument).refine((documents) => hasUniqueIds(documents.map((document) => document.id)), "document ids must be unique").refine(
870
- (documents) => stage === void 0 || documents.every((document) => document.stage === stage),
871
- `every document must be at stage ${stage}`
872
- );
873
873
  var $termsAcceptance = obj({
874
874
  documentId: $nonBlank,
875
875
  version: $nonBlank,
@@ -888,7 +888,7 @@ var $termsErrorBody = obj({
888
888
  errorCode: $nonBlank,
889
889
  errorMsg: z.string(),
890
890
  reqId: z.string().optional(),
891
- reason: z.enum(["STALE_TERMS", "IN_PROGRESS", "IDEMPOTENCY_KEY_REUSED", "INVALID_REQUEST", "RATE_LIMITED", "PROVIDER_UNAVAILABLE"]),
891
+ reason: z.enum(["STALE_TERMS", "IN_PROGRESS", "INVALID_REQUEST", "RATE_LIMITED", "PROVIDER_UNAVAILABLE"]),
892
892
  recovery: z.enum(["RETRY", "REQUOTE", "NONE"])
893
893
  });
894
894
  var FiatTermsErrorBodySchema = $termsErrorBody;
@@ -897,7 +897,7 @@ var $providerBoundStepResponse = obj({
897
897
  provider: $provider,
898
898
  transitions: z.array($transition),
899
899
  preparedPayment: $preparedPayment.optional(),
900
- handoff: obj({ provider: $provider, terms: $termsDocuments("CHECKOUT") }).optional(),
900
+ handoff: obj({ provider: $provider }).optional(),
901
901
  routingSessionRef: z.string().optional(),
902
902
  providerAuthToken: obj({
903
903
  clientSecret: z.string(),
@@ -2036,7 +2036,7 @@ var $intentRequest = z2.discriminatedUnion("kind", [
2036
2036
  kind: z2.literal("kyc"),
2037
2037
  checkout: $checkout,
2038
2038
  credentials: $credentials,
2039
- values: z2.record(z2.string(), z2.string()).refine((values) => Object.keys(values).length > 0, "values must not be empty")
2039
+ values: z2.record(KycFieldIdSchema, z2.string()).refine((values) => Object.keys(values).length > 0, "values must not be empty")
2040
2040
  }),
2041
2041
  obj2({ kind: z2.literal("order"), orderId: $nonEmpty, transactionId: $nonEmpty })
2042
2042
  ]);
@@ -2049,18 +2049,19 @@ var $quoteInput = obj2({
2049
2049
  feeBehavior: z2.literal("inclusive")
2050
2050
  });
2051
2051
  var MoonPayQuoteInputSchema = $quoteInput;
2052
- var $refusal = z2.enum(["NOT_ELIGIBLE", "DOCUMENTS_REQUIRED", "FINAL_REJECTION", "CUSTOMER_MISMATCH"]);
2052
+ var $stepRefusal = z2.enum(["NOT_ELIGIBLE", "DOCUMENTS_REQUIRED", "FINAL_REJECTION", "CUSTOMER_MISMATCH"]);
2053
+ var $orderRefusal = z2.enum(["CUSTOMER_MISMATCH", "WALLET_MISMATCH", "UNRECORDABLE"]);
2053
2054
  var $fieldError = obj2({ fieldId: $nonEmpty, message: $nonEmpty });
2054
- var $intentStatus = z2.discriminatedUnion("status", [
2055
+ var $pending = obj2({ status: z2.literal("PENDING"), retryAfterMs: z2.number().int().positive().max(6e4) });
2056
+ var $stepStatus = z2.discriminatedUnion("status", [
2055
2057
  obj2({ status: z2.literal("TERMS"), stage: z2.enum(["CHECKOUT", "KYC"]), documents: z2.array(TermsDocumentSchema).min(1) }),
2056
2058
  obj2({ status: z2.literal("SDK_AUTH"), sessionToken: $nonEmpty, quoteInput: $quoteInput }),
2057
2059
  obj2({ status: z2.literal("KYC"), fields: z2.array(FormFieldSchema).min(1), fieldErrors: z2.array($fieldError).min(1).optional() }),
2058
- obj2({ status: z2.literal("PENDING"), retryAfterMs: z2.number().int().positive().max(6e4) }),
2060
+ $pending,
2059
2061
  obj2({ status: z2.literal("READY"), orderId: $nonEmpty, quoteInput: $quoteInput }),
2060
- obj2({ status: z2.literal("DONE"), order: FiatStepResponseSchema }),
2061
- obj2({ status: z2.literal("REFUSED"), reason: $refusal, recovery: z2.enum(["REQUOTE", "NONE"]) })
2062
+ obj2({ status: z2.literal("REFUSED"), reason: $stepRefusal, recovery: z2.enum(["REQUOTE", "NONE"]) })
2062
2063
  ]);
2063
- var $intentResponse = $intentStatus.superRefine((response, context) => {
2064
+ var $stepResponse2 = $stepStatus.superRefine((response, context) => {
2064
2065
  if (response.status === "TERMS") {
2065
2066
  if (!hasUniqueIds2(response.documents.map((document) => document.id))) {
2066
2067
  context.addIssue({ code: "custom", path: ["documents"], message: "document ids must be unique" });
@@ -2079,6 +2080,14 @@ var $intentResponse = $intentStatus.superRefine((response, context) => {
2079
2080
  }
2080
2081
  }
2081
2082
  });
2083
+ var MoonPayStepResponseSchema = $stepResponse2;
2084
+ var $orderResponse = z2.discriminatedUnion("status", [
2085
+ obj2({ status: z2.literal("DONE"), order: FiatStepResponseSchema }),
2086
+ $pending,
2087
+ obj2({ status: z2.literal("REFUSED"), reason: $orderRefusal, recovery: z2.literal("NONE") })
2088
+ ]);
2089
+ var MoonPayOrderResponseSchema = $orderResponse;
2090
+ var $intentResponse = z2.union([$stepResponse2, $orderResponse]);
2082
2091
  var MoonPayIntentResponseSchema = $intentResponse;
2083
2092
  var $faultFields = {
2084
2093
  reason: z2.enum([
@@ -2086,10 +2095,7 @@ var $faultFields = {
2086
2095
  "RATE_LIMITED",
2087
2096
  "PROVIDER_UNAVAILABLE",
2088
2097
  "IN_PROGRESS",
2089
- "IDEMPOTENCY_KEY_REUSED",
2090
- "INVALID_REQUEST",
2091
- "TRANSACTION_MISMATCH",
2092
- "WALLET_MISMATCH"
2098
+ "INVALID_REQUEST"
2093
2099
  ]),
2094
2100
  recovery: z2.enum(["RETRY", "REQUOTE", "NONE"])
2095
2101
  };
@@ -2114,6 +2120,7 @@ export {
2114
2120
  FIELD_SPEC_TYPES,
2115
2121
  FIXTURES,
2116
2122
  FIXTURE_COVERAGE_GAPS,
2123
+ FUN_KYC_CONSENT_DOCUMENTS,
2117
2124
  FailureReasonSchema,
2118
2125
  FeeLineSchema,
2119
2126
  FiatAmountSchema,
@@ -2138,6 +2145,7 @@ export {
2138
2145
  KYCProviderSchema,
2139
2146
  KYC_ACKNOWLEDGEMENT_FIELD_IDS,
2140
2147
  KycCaptureStateSchema,
2148
+ KycFieldIdSchema,
2141
2149
  KycInputRequiredStateSchema,
2142
2150
  KycNoActionRequiredStateSchema,
2143
2151
  KycSdkResultReportSchema,
@@ -2147,14 +2155,18 @@ export {
2147
2155
  MoonPayFaultSchema,
2148
2156
  MoonPayIntentRequestSchema,
2149
2157
  MoonPayIntentResponseSchema,
2158
+ MoonPayOrderResponseSchema,
2150
2159
  MoonPayQuoteInputSchema,
2151
2160
  MoonPaySdkCredentialsSchema,
2161
+ MoonPayStepResponseSchema,
2152
2162
  OrderAwaitingConfirmationStateSchema,
2153
2163
  OrderCreatedStateSchema,
2154
2164
  OrderRefSchema,
2155
2165
  OrderStatusSchema,
2156
2166
  OrderSummarySchema,
2157
2167
  PAYMENT_METHOD_CATEGORIES,
2168
+ PROVIDER_CHECKOUT_DOCUMENTS,
2169
+ PUBLISHED_TERMS_DOCUMENTS,
2158
2170
  PaymentCaptureStateSchema,
2159
2171
  PaymentInstructStateSchema,
2160
2172
  PaymentSurfaceSchema,
@@ -2,12 +2,13 @@
2
2
  * The MoonPay provider-owned flow: one route, `POST /fiat/providers/moonpay/intent`.
3
3
  *
4
4
  * Each request carries evidence or a user action (`kind`), and each response says what the backend
5
- * needs next (`status`). The client repeats until `DONE` or `REFUSED`. Terms and consents go through
5
+ * needs next (`status`). `observe` and `kyc` answer a `MoonPayStepResponse`, and `order` answers a
6
+ * `MoonPayOrderResponse` (`MoonPayIntentResponseFor`). Terms and consents go through
6
7
  * the platform `POST /fiat/terms` (`./terms`). Identity and the deposit wallet always come from the
7
8
  * verified partner assertion, never from a request body.
8
9
  *
9
- * `kyc` and `order` require an `Idempotency-Key` header; `observe` ignores it. A repeated key skips
10
- * the effect and still returns the current response.
10
+ * A retry sends the same request. Each write is idempotent on data the request carries, and every
11
+ * call, a retry too, returns the current response.
11
12
  *
12
13
  * A fault is a 4xx/5xx whose body is `MoonPayErrorBody`. Anything the user can act on is a 200
13
14
  * `MoonPayIntentResponse`.
@@ -17,7 +18,7 @@
17
18
  */
18
19
  import type { FiatCurrencyCode } from '../codes';
19
20
  import type { TermsDocument, TermsStage } from '../terms';
20
- import type { FiatAmount, FiatStepResponse, FormField } from '../types';
21
+ import type { FiatAmount, FiatStepResponse, FormField, KycFieldId } from '../types';
21
22
  export declare const MOONPAY_ENDPOINTS: {
22
23
  readonly intent: "POST /fiat/providers/moonpay/intent";
23
24
  };
@@ -49,12 +50,12 @@ export type MoonPayIntentRequest =
49
50
  checkout: MoonPayCheckout;
50
51
  credentials?: MoonPaySdkCredentials;
51
52
  }
52
- /** Only after a `KYC` response. `values` is keyed by field id; there is no form id. */
53
+ /** Only after a `KYC` response. `values` is keyed by the ids of that response's fields; there is no form id. */
53
54
  | {
54
55
  kind: 'kyc';
55
56
  checkout: MoonPayCheckout;
56
57
  credentials: MoonPaySdkCredentials;
57
- values: Record<string, string>;
58
+ values: Partial<Record<KycFieldId, string>>;
58
59
  }
59
60
  /** After the Apple Pay sheet. `transactionId` is from the Apple Pay completion event. */
60
61
  | {
@@ -87,13 +88,21 @@ export interface MoonPayQuoteInput {
87
88
  };
88
89
  feeBehavior: 'inclusive';
89
90
  }
90
- export type MoonPayRefusal = 'NOT_ELIGIBLE' | 'DOCUMENTS_REQUIRED' | 'FINAL_REJECTION' | 'CUSTOMER_MISMATCH';
91
+ /** `REQUOTE` for `NOT_ELIGIBLE` and `DOCUMENTS_REQUIRED`, `NONE` for the others. */
92
+ export type MoonPayStepRefusal = 'NOT_ELIGIBLE' | 'DOCUMENTS_REQUIRED' | 'FINAL_REJECTION' | 'CUSTOMER_MISMATCH';
93
+ /**
94
+ * After a charge, always with `recovery: NONE`. `CUSTOMER_MISMATCH`: the transaction's customer is
95
+ * not bound to this buyer. `WALLET_MISMATCH`: the transaction pays another wallet than the
96
+ * assertion's. `UNRECORDABLE`: a charge no retry can record, held for refund review.
97
+ */
98
+ export type MoonPayOrderRefusal = 'CUSTOMER_MISMATCH' | 'WALLET_MISMATCH' | 'UNRECORDABLE';
91
99
  /** A reason on one field of a `KYC` response. `fieldId` names a field in that response. */
92
100
  export interface MoonPayFieldError {
93
101
  fieldId: string;
94
102
  message: string;
95
103
  }
96
- export type MoonPayIntentResponse =
104
+ /** The answer to `observe` and `kyc`. */
105
+ export type MoonPayStepResponse =
97
106
  /** Show `documents` (every one at `stage`), send `POST /fiat/terms`, then `observe`. */
98
107
  {
99
108
  status: 'TERMS';
@@ -112,7 +121,7 @@ export type MoonPayIntentResponse =
112
121
  fields: FormField[];
113
122
  fieldErrors?: MoonPayFieldError[];
114
123
  }
115
- /** Send the same request again after the delay. */
124
+ /** Send `observe` after the delay. Never `kyc` again: its write is done. */
116
125
  | {
117
126
  status: 'PENDING';
118
127
  retryAfterMs: number;
@@ -123,29 +132,45 @@ export type MoonPayIntentResponse =
123
132
  orderId: string;
124
133
  quoteInput: MoonPayQuoteInput;
125
134
  }
126
- /** The `GET /fiat/orders/:orderId` response; the shared order screen renders it. */
135
+ /** Exit the provider flow. `REQUOTE` goes back to `POST /fiat/quote`; `NONE` ends the flow. */
127
136
  | {
137
+ status: 'REFUSED';
138
+ reason: MoonPayStepRefusal;
139
+ recovery: 'REQUOTE' | 'NONE';
140
+ };
141
+ /** The answer to `order`, which runs after the charge. */
142
+ export type MoonPayOrderResponse =
143
+ /** The `GET /fiat/orders/:orderId` response; the shared order screen renders it. */
144
+ {
128
145
  status: 'DONE';
129
146
  order: FiatStepResponse;
130
147
  }
131
- /** Exit the provider flow. `REQUOTE` goes back to `POST /fiat/quote`; `NONE` ends the flow. */
148
+ /** MoonPay does not show the transaction yet. Send the same `order` after the delay. */
149
+ | {
150
+ status: 'PENDING';
151
+ retryAfterMs: number;
152
+ }
153
+ /** Exit the provider flow. A requote after a charge would start a second payment. */
132
154
  | {
133
155
  status: 'REFUSED';
134
- reason: MoonPayRefusal;
135
- recovery: 'REQUOTE' | 'NONE';
156
+ reason: MoonPayOrderRefusal;
157
+ recovery: 'NONE';
158
+ };
159
+ export type MoonPayIntentResponseFor = {
160
+ observe: MoonPayStepResponse;
161
+ kyc: MoonPayStepResponse;
162
+ order: MoonPayOrderResponse;
136
163
  };
164
+ export type MoonPayIntentResponse = MoonPayStepResponse | MoonPayOrderResponse;
137
165
  export type MoonPayIntentStatus = MoonPayIntentResponse['status'];
138
- /** `RETRY` sends the same request again, with the same key. `REQUOTE` goes back to `POST /fiat/quote`. `NONE` ends the flow. */
166
+ /** `RETRY` sends the same request again. `REQUOTE` goes back to `POST /fiat/quote`. `NONE` ends the flow. */
139
167
  export type MoonPayRecovery = 'RETRY' | 'REQUOTE' | 'NONE';
140
168
  /**
141
169
  * `SESSION_BUDGET_SPENT`: the per-login SDK session mint budget (429). `RATE_LIMITED`: the kind's
142
- * request budget (429). `PROVIDER_UNAVAILABLE`: MoonPay or Sumsub is down, or a charge cannot be
143
- * recorded. `IN_PROGRESS`: the same key is still running (409). `IDEMPOTENCY_KEY_REUSED`: the same
144
- * key with a different body (422). `INVALID_REQUEST`: a bad body or a missing key (400).
145
- * `TRANSACTION_MISMATCH`: the transaction is not this buyer's (400). `WALLET_MISMATCH`: the
146
- * transaction pays another wallet.
170
+ * request budget (429). `PROVIDER_UNAVAILABLE`: MoonPay or Sumsub is down. `IN_PROGRESS`: a `kyc`
171
+ * for this buyer is still running (409). `INVALID_REQUEST`: a bad body (400).
147
172
  */
148
- export type MoonPayFaultReason = 'SESSION_BUDGET_SPENT' | 'RATE_LIMITED' | 'PROVIDER_UNAVAILABLE' | 'IN_PROGRESS' | 'IDEMPOTENCY_KEY_REUSED' | 'INVALID_REQUEST' | 'TRANSACTION_MISMATCH' | 'WALLET_MISMATCH';
173
+ export type MoonPayFaultReason = 'SESSION_BUDGET_SPENT' | 'RATE_LIMITED' | 'PROVIDER_UNAVAILABLE' | 'IN_PROGRESS' | 'INVALID_REQUEST';
149
174
  /** The fields a MoonPay fault adds to the shared error body. */
150
175
  export interface MoonPayFault {
151
176
  reason: MoonPayFaultReason;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  MOONPAY_ENDPOINTS
3
- } from "../chunk-UN3WTIMI.mjs";
3
+ } from "../chunk-YOMQWXTD.mjs";
4
4
  export {
5
5
  MOONPAY_ENDPOINTS
6
6
  };
@@ -3,11 +3,13 @@
3
3
  * the package root, never from `./moonpay`, so the production entry stays free of zod.
4
4
  */
5
5
  import { z } from 'zod';
6
- import type { MoonPayCheckout, MoonPayErrorBody, MoonPayFault, MoonPayIntentRequest, MoonPayIntentResponse, MoonPayQuoteInput, MoonPaySdkCredentials } from './moonpay';
6
+ import type { MoonPayCheckout, MoonPayErrorBody, MoonPayFault, MoonPayIntentRequest, MoonPayIntentResponse, MoonPayOrderResponse, MoonPayQuoteInput, MoonPaySdkCredentials, MoonPayStepResponse } from './moonpay';
7
7
  export declare const MoonPayCheckoutSchema: z.ZodType<MoonPayCheckout>;
8
8
  export declare const MoonPaySdkCredentialsSchema: z.ZodType<MoonPaySdkCredentials>;
9
9
  export declare const MoonPayIntentRequestSchema: z.ZodType<MoonPayIntentRequest>;
10
10
  export declare const MoonPayQuoteInputSchema: z.ZodType<MoonPayQuoteInput>;
11
+ export declare const MoonPayStepResponseSchema: z.ZodType<MoonPayStepResponse>;
12
+ export declare const MoonPayOrderResponseSchema: z.ZodType<MoonPayOrderResponse>;
11
13
  export declare const MoonPayIntentResponseSchema: z.ZodType<MoonPayIntentResponse>;
12
14
  export declare const MoonPayFaultSchema: z.ZodType<MoonPayFault>;
13
15
  export declare const MoonPayErrorBodySchema: z.ZodType<MoonPayErrorBody>;
package/dist/schemas.d.ts CHANGED
@@ -28,7 +28,7 @@
28
28
  */
29
29
  import { z } from 'zod';
30
30
  import type { UsStateCode } from './codes';
31
- import type { BlockedReason, CryptoAmount, FailureReason, FeeLine, FiatAmount, FiatEndpoint, FiatProvider, FiatStepResponse, FieldSpec, FlowState, FormDescriptor, FormField, FormFieldType, InstructionField, Instructions, Instrument, JsonValue, KYCProvider, OrderRef, OrderStatus, OrderSummary, PollSpec, PreparedPayment, PaymentSurface, Quote, QuoteLimitRange, QuoteLimits, Recovery, Refund, ReportSpec, SelectOption, StatusHistoryEntry, Surface, PreferredIdentityDocument, ClientExecutedDelivery, KycSdkResultReport, SurfaceKind, SurfaceProvider, TermsAcceptance, Transition, TransitionInputs, TransitionParams, Tx } from './types';
31
+ import type { BlockedReason, CryptoAmount, FailureReason, FeeLine, FiatAmount, FiatEndpoint, FiatProvider, FiatStepResponse, FieldSpec, FlowState, FormDescriptor, FormField, FormFieldType, InstructionField, Instructions, Instrument, JsonValue, KYCProvider, OrderRef, OrderStatus, OrderSummary, PollSpec, PreparedPayment, PaymentSurface, Quote, QuoteLimitRange, QuoteLimits, Recovery, Refund, ReportSpec, SelectOption, StatusHistoryEntry, Surface, PreferredIdentityDocument, KycFieldId, ClientExecutedDelivery, KycSdkResultReport, SurfaceKind, SurfaceProvider, TermsAcceptance, Transition, TransitionInputs, TransitionParams, Tx } from './types';
32
32
  import type { FiatTermsErrorBody, FiatTermsRequest, FiatTermsResponse, TermsDocument, TermsDocumentAcceptance } from './terms';
33
33
  export declare const JsonSchema: z.ZodType<JsonValue>;
34
34
  export declare const HTTP_VERBS: readonly ["GET", "POST"];
@@ -58,6 +58,7 @@ export declare const SurfaceKindSchema: z.ZodType<SurfaceKind>;
58
58
  export declare const PreferredIdentityDocumentSchema: z.ZodType<PreferredIdentityDocument>;
59
59
  export declare const STANDARD_KYC_FIELD_IDS: readonly ["LEGAL_FIRST_NAME", "LEGAL_MIDDLE_NAME", "LEGAL_LAST_NAME", "DATE_OF_BIRTH", "COUNTRY_OF_BIRTH", "CITY_OF_BIRTH", "NATIONALITY", "EMAIL_ADDRESS", "EMAIL_OWNERSHIP_VERIFICATION", "PHONE_NUMBER", "PHONE_OWNERSHIP_VERIFICATION", "RESIDENTIAL_ADDRESS_LINE_1", "RESIDENTIAL_ADDRESS_LINE_2", "RESIDENTIAL_ADDRESS_CITY", "RESIDENTIAL_ADDRESS_REGION", "RESIDENTIAL_ADDRESS_POSTAL_CODE", "RESIDENTIAL_ADDRESS_COUNTRY", "TAX_IDENTIFIER", "US_SSN_LAST_FOUR", "TAX_RESIDENCE_COUNTRY", "EMPLOYMENT_STATUS", "OCCUPATION_INDUSTRY", "OCCUPATION_TITLE", "SOURCE_OF_FUNDS_DECLARATION", "SOURCE_OF_INCOME_DECLARATION", "SOURCE_OF_WEALTH_DECLARATION", "PURPOSE_OF_SERVICE", "PURPOSE_OF_TRANSACTION", "CUSTOMER_CATEGORY"];
60
60
  export declare const KYC_ACKNOWLEDGEMENT_FIELD_IDS: readonly ["RISK_ACKNOWLEDGEMENT", "COOLING_OFF_ACKNOWLEDGEMENT", "TERMS_ACCEPTANCE"];
61
+ export declare const KycFieldIdSchema: z.ZodType<KycFieldId>;
61
62
  export declare const ClientExecutedDeliverySchema: z.ZodType<ClientExecutedDelivery>;
62
63
  export declare const SurfaceSchema: z.ZodType<Surface>;
63
64
  export declare const PaymentSurfaceSchema: z.ZodType<PaymentSurface>;
package/dist/table.js CHANGED
@@ -36,7 +36,7 @@ __export(table_exports, {
36
36
  module.exports = __toCommonJS(table_exports);
37
37
 
38
38
  // package.json
39
- var version = "0.20.1";
39
+ var version = "0.21.0";
40
40
 
41
41
  // src/table.ts
42
42
  var TABLE_VERSION = version;
package/dist/table.mjs CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  tableEntry,
12
12
  unofferedEndpoints,
13
13
  unreachableStates
14
- } from "./chunk-544S4IEU.mjs";
14
+ } from "./chunk-LBYBZDOW.mjs";
15
15
  export {
16
16
  DOCUMENTED_ENDPOINTS,
17
17
  STATE_KEYS,
package/dist/terms.d.ts CHANGED
@@ -1,17 +1,16 @@
1
1
  /**
2
2
  * The platform terms route: `POST /fiat/terms`, shared by every provider.
3
3
  *
4
- * A checkout shows the user documents to accept. `CHECKOUT` documents arrive in `handoff.terms` on
5
- * a `QUOTE`; `KYC` documents arrive in a provider flow's `TERMS` response. The user's Continue tap
6
- * is the acceptance, and the client records it here, with an `Idempotency-Key`, before the next
7
- * provider call.
4
+ * A checkout shows the user documents to accept. `CHECKOUT` documents are the constants below;
5
+ * `KYC` documents arrive in a provider flow's `TERMS` response. The user's Continue tap is the
6
+ * acceptance, and the client records it here before the next provider call. A repeat writes nothing.
8
7
  *
9
8
  * Zero runtime dependencies, so production React Native code can import it. The zod schemas are
10
9
  * exported from the package root.
11
10
  */
12
11
  import type { FiatProvider } from './types';
13
12
  export declare const FIAT_TERMS_ENDPOINT: "POST /fiat/terms";
14
- export type TermsDocumentKind = 'FUN_TERMS' | 'PROVIDER_TERMS' | 'FUN_KYC_COLLECTION' | 'PROVIDER_KYC_SHARING';
13
+ export type TermsDocumentKind = 'PROVIDER_TERMS' | 'FUN_KYC_COLLECTION' | 'PROVIDER_KYC_SHARING';
15
14
  /** `CHECKOUT` documents gate the provider session; `KYC` documents gate the first KYC write. */
16
15
  export type TermsStage = 'CHECKOUT' | 'KYC';
17
16
  export interface TermsDocument {
@@ -45,14 +44,13 @@ export interface FiatTermsResponse {
45
44
  recorded: string[];
46
45
  }
47
46
  /**
48
- * `STALE_TERMS`: a version, digest, or `acceptedAt` the backend no longer accepts; the client
49
- * fetches the documents again. `IN_PROGRESS`: the same key is still running (409).
50
- * `IDEMPOTENCY_KEY_REUSED`: the same key with a different body (422). `INVALID_REQUEST`: a bad body
51
- * or a missing key (400). `RATE_LIMITED`: the per-login terms budget is spent (429).
52
- * `PROVIDER_UNAVAILABLE`: the KYC service or a store is down (503); nothing is recorded, so retry.
47
+ * `STALE_TERMS`: an unpublished version, a wrong digest, or an `acceptedAt` older than 5 minutes
48
+ * (400). `IN_PROGRESS`: the same request is still running (409). `INVALID_REQUEST`: a bad body (400).
49
+ * `RATE_LIMITED`: the per-login terms budget is spent (429). `PROVIDER_UNAVAILABLE`: the KYC service
50
+ * or a store is down (503); nothing is recorded, so retry.
53
51
  */
54
- export type FiatTermsFaultReason = 'STALE_TERMS' | 'IN_PROGRESS' | 'IDEMPOTENCY_KEY_REUSED' | 'INVALID_REQUEST' | 'RATE_LIMITED' | 'PROVIDER_UNAVAILABLE';
55
- /** `RETRY` sends the same request, with the same key. `REQUOTE` goes back to `POST /fiat/quote`. `NONE` ends the flow. */
52
+ export type FiatTermsFaultReason = 'STALE_TERMS' | 'IN_PROGRESS' | 'INVALID_REQUEST' | 'RATE_LIMITED' | 'PROVIDER_UNAVAILABLE';
53
+ /** `RETRY` sends the same request again. `REQUOTE` goes back to `POST /fiat/quote`. `NONE` ends the flow. */
56
54
  export type FiatTermsRecovery = 'RETRY' | 'REQUOTE' | 'NONE';
57
55
  /** The 4xx/5xx body of `POST /fiat/terms`: the shared error body plus `reason` and `recovery`. */
58
56
  export interface FiatTermsErrorBody {
@@ -62,4 +60,14 @@ export interface FiatTermsErrorBody {
62
60
  reason: FiatTermsFaultReason;
63
61
  recovery: FiatTermsRecovery;
64
62
  }
63
+ /** Each provider's current `CHECKOUT` documents, shown next to Continue on the amount screen. */
64
+ export declare const PROVIDER_CHECKOUT_DOCUMENTS: Readonly<Partial<Record<FiatProvider, readonly TermsDocument[]>>>;
65
+ export type FunKycConsentLocale = 'en' | 'es' | 'fr' | 'ja' | 'ko' | 'ru' | 'tr' | 'zh';
66
+ /** Fun's KYC consent, one digest per locale the KYC intro screen shows. It counts under any provider. */
67
+ export declare const FUN_KYC_CONSENT_DOCUMENTS: Readonly<Record<FunKycConsentLocale, TermsDocument>>;
68
+ /**
69
+ * Every version and locale ever published. Append a new version here and keep the old one: the
70
+ * backend accepts any entry, so a client that ships an older version can still check out.
71
+ */
72
+ export declare const PUBLISHED_TERMS_DOCUMENTS: readonly TermsDocument[];
65
73
  //# sourceMappingURL=terms.d.ts.map
package/dist/terms.js CHANGED
@@ -20,8 +20,45 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/terms.ts
21
21
  var terms_exports = {};
22
22
  __export(terms_exports, {
23
- FIAT_TERMS_ENDPOINT: () => FIAT_TERMS_ENDPOINT
23
+ FIAT_TERMS_ENDPOINT: () => FIAT_TERMS_ENDPOINT,
24
+ FUN_KYC_CONSENT_DOCUMENTS: () => FUN_KYC_CONSENT_DOCUMENTS,
25
+ PROVIDER_CHECKOUT_DOCUMENTS: () => PROVIDER_CHECKOUT_DOCUMENTS,
26
+ PUBLISHED_TERMS_DOCUMENTS: () => PUBLISHED_TERMS_DOCUMENTS
24
27
  });
25
28
  module.exports = __toCommonJS(terms_exports);
26
29
  var FIAT_TERMS_ENDPOINT = "POST /fiat/terms";
30
+ var MOONPAY_TERMS = {
31
+ id: "MOONPAY_TERMS",
32
+ kind: "PROVIDER_TERMS",
33
+ stage: "CHECKOUT",
34
+ version: "2026-09-l2-kyc-sharing-v2",
35
+ contentDigest: "44e096af329262134fe6680659c9bd42014cbf5e96f064d67869173a4f7d822b",
36
+ links: [
37
+ { label: "MoonPay Terms of Use", url: "https://www.moonpay.com/legal/terms" },
38
+ { label: "MoonPay Privacy Policy", url: "https://www.moonpay.com/legal/privacy_policy" },
39
+ { label: "Persona Privacy Policy", url: "https://withpersona.com/legal/privacy-policy" }
40
+ ]
41
+ };
42
+ var PROVIDER_CHECKOUT_DOCUMENTS = {
43
+ MOONPAY: [MOONPAY_TERMS]
44
+ };
45
+ var funKycConsent = (contentDigest) => ({
46
+ id: "FUN_KYC_CONSENT",
47
+ kind: "FUN_KYC_COLLECTION",
48
+ stage: "KYC",
49
+ version: "fun-kyc-consent-2026-09-11",
50
+ contentDigest,
51
+ links: [{ label: "Fun.xyz Privacy Policy", url: "https://fun.xyz/privacy" }]
52
+ });
53
+ var FUN_KYC_CONSENT_DOCUMENTS = {
54
+ en: funKycConsent("da31f2467deb996476b131116508ea2a00220765e658a79abc6d2bd44337504a"),
55
+ es: funKycConsent("73753b70ad8d1b48dfdcda35e6028c3a7ada66c311a67a1d8f6fe13c76a32f3b"),
56
+ fr: funKycConsent("5ee82675984591dbf66337f31246179103c5624a189850943d400f9b85a84965"),
57
+ ja: funKycConsent("3f272da313f66601a20c3ca43c967aff4bb7f73488177f0a4ce94cbc78bafce2"),
58
+ ko: funKycConsent("aab7839bfba3f34aa47ca6b10647c2c8965c37d845494ef8f3067ca3e3821200"),
59
+ ru: funKycConsent("17168083ebcc4fd11ea80b08c3f230bdec03a1e7b89173a38819ae5533b0fc96"),
60
+ tr: funKycConsent("463040c3b58c922ecae2ae8262a78eb732bbcc5606c394723626378b3db2bbc3"),
61
+ zh: funKycConsent("7f76d850adaf69783c5d9365e51abb5446f4e5778c63eabbdb4784d72464f855")
62
+ };
63
+ var PUBLISHED_TERMS_DOCUMENTS = [MOONPAY_TERMS, ...Object.values(FUN_KYC_CONSENT_DOCUMENTS)];
27
64
  //# sourceMappingURL=terms.js.map
package/dist/terms.mjs CHANGED
@@ -1,7 +1,13 @@
1
1
  import {
2
- FIAT_TERMS_ENDPOINT
3
- } from "./chunk-WRRCWAY2.mjs";
2
+ FIAT_TERMS_ENDPOINT,
3
+ FUN_KYC_CONSENT_DOCUMENTS,
4
+ PROVIDER_CHECKOUT_DOCUMENTS,
5
+ PUBLISHED_TERMS_DOCUMENTS
6
+ } from "./chunk-N6GHUS2K.mjs";
4
7
  export {
5
- FIAT_TERMS_ENDPOINT
8
+ FIAT_TERMS_ENDPOINT,
9
+ FUN_KYC_CONSENT_DOCUMENTS,
10
+ PROVIDER_CHECKOUT_DOCUMENTS,
11
+ PUBLISHED_TERMS_DOCUMENTS
6
12
  };
7
13
  //# sourceMappingURL=terms.mjs.map
package/dist/types.d.ts CHANGED
@@ -19,7 +19,6 @@
19
19
  * - terminality comes from the table (`src/table.ts`), never from `transitions.length`
20
20
  */
21
21
  import type { FiatCurrencyCode, PaymentMethodCategory } from './codes';
22
- import type { TermsDocument } from './terms';
23
22
  /**
24
23
  * JSON value. `params` carry these — opaque literals the client spreads verbatim.
25
24
  * Named `JsonValue` rather than `Json` because this package's surface is re-exported wholesale;
@@ -722,11 +721,6 @@ export type FiatStepResponse = (FiatStepResponseBase & {
722
721
  */
723
722
  handoff?: {
724
723
  provider: FiatProvider;
725
- /**
726
- * The `CHECKOUT` documents this login has not accepted at the current version, shown next to
727
- * Continue and recorded with `POST /fiat/terms` on the tap. Empty for a returning buyer.
728
- */
729
- terms: TermsDocument[];
730
724
  };
731
725
  });
732
726
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fun-xyz/fiat-contract",
3
- "version": "0.20.1",
3
+ "version": "0.21.0",
4
4
  "description": "Published conformance contract for Fun's headless fiat onramp: FlowState/Transition types, zod schemas, the transition table as data, recorded fixtures, assertion helpers.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,7 +0,0 @@
1
- // src/terms.ts
2
- var FIAT_TERMS_ENDPOINT = "POST /fiat/terms";
3
-
4
- export {
5
- FIAT_TERMS_ENDPOINT
6
- };
7
- //# sourceMappingURL=chunk-WRRCWAY2.mjs.map