@fun-xyz/fiat-contract 0.23.0 → 0.25.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
@@ -19,7 +19,7 @@ Four things, zero runtime logic beyond validation:
19
19
  | --- | --- | --- | --- |
20
20
  | `@fun-xyz/fiat-contract/types` | **0.1 KB** (types erase) | every type; no runtime values | production, both repos |
21
21
  | `@fun-xyz/fiat-contract/table` | **13.8 KB**, zero deps | `TRANSITION_TABLE`, `stateKey`, `tableEntry`, `isTerminal`, `walkTable`, `TABLE_VERSION`, `TERMINAL_ORDER_STATUSES`, `DOCUMENTED_ENDPOINTS`, `UNOFFERED_ENDPOINTS`, `UNREACHABLE_STATES`, `unofferedEndpoints`, `unreachableStates` | **production frontend** + backend |
22
- | `@fun-xyz/fiat-contract/moonpay` | zero deps | the MoonPay provider-owned flow: `intent` request kinds, response statuses and fault types, and `MOONPAY_ENDPOINTS` | **production frontend** (MoonPay adapter) + backend |
22
+ | `@fun-xyz/fiat-contract/moonpay` | zero deps | the MoonPay flow on `POST /fiat/next`: action requests, prompts, responses, fault types, and `MOONPAY_ENDPOINTS` | **production frontend** (MoonPay adapter) + backend |
23
23
  | `@fun-xyz/fiat-contract/terms` | zero deps | the platform terms route: `TermsDocument`, `FiatTermsRequest`, `FiatTermsResponse`, fault types, and `FIAT_TERMS_ENDPOINT` | **production frontend** + backend |
24
24
  | `@fun-xyz/fiat-contract/routing` | zero deps | the routing table and routing quote: `FiatRoutingTableQuery`, `FiatRoutingTableResponse`, `FiatRoutingQuoteRequest`, both routes' error bodies, and `ROUTING_ENDPOINTS` | **production frontend** + backend |
25
25
  | `@fun-xyz/fiat-contract` | 47.6 KB, needs zod | the above + 77 zod schemas + assertions + 18 fixtures | tests, and backend dev/test guards |
@@ -102,7 +102,7 @@ A provider can run its own flow instead of the shared step machine. `POST /fiat/
102
102
  and prices. When the request's `handoffs` lists the winning provider, the response carries
103
103
  `handoff: { provider }` and no transitions. The client shows that provider's `CHECKOUT` documents
104
104
  from `PROVIDER_CHECKOUT_DOCUMENTS`, records them with `POST /fiat/terms` on Continue, and then calls
105
- `POST /fiat/providers/{provider}/intent`. The schema refuses a handoff on any state but `QUOTE`, a
105
+ `POST /fiat/next`. The schema refuses a handoff on any state but `QUOTE`, a
106
106
  handoff to a provider other than the response's own, and a handoff that still offers transitions.
107
107
 
108
108
  **Terms (`./terms`).** Every provider records acceptances through the platform `POST /fiat/terms`
@@ -133,74 +133,81 @@ cause is unknown. Refetch the table at `expiresAt`, on `refreshLimits: true`, an
133
133
  a `REQUOTE`. The schemas hold the table's invariants: each method once, sorted, non-overlapping
134
134
  intervals, at least one provider each and none twice, and a reason only on an empty method.
135
135
 
136
- `ROUTING_ENDPOINTS.quote` (`POST /fiat/routing/quote`) takes the `POST /fiat/quote` body plus the
137
- interval's first `provider`, never `routingOverrides`, and answers the same `FiatStepResponse`. A
138
- refusal is a `FiatRoutingQuoteErrorBody`, and it decides whether to quote the interval's next
139
- provider:
136
+ `ROUTING_ENDPOINTS.quote` (`POST /fiat/routing/quote`) takes the `POST /fiat/quote` body
137
+ (`FiatRoutingQuoteTerms`), never `routingOverrides`, plus one of two forms:
138
+
139
+ - `providers`: the interval's providers, best first. The backend prices them in order, falls
140
+ through on the refusals marked "next provider" below, and answers the first that prices or the
141
+ last provider's refusal.
142
+ - `provider`: one provider only. The client falls through itself.
143
+
144
+ It answers the same `FiatStepResponse`, whose `provider` names the one that priced. A refusal is a
145
+ `FiatRoutingQuoteErrorBody`, and it decides whether the next provider may still price:
140
146
 
141
147
  | Status | `errorCode` | Then |
142
148
  | --- | --- | --- |
143
- | 404 | `FiatNoRouteError`, `reason` `NO_CANDIDATE`, `PROVIDER_DECLINED`, `PROVIDER_OUTAGE` or `KYC_REJECTED` | quote the next provider |
144
- | 400 | `FiatNoRouteError`, `reason: USER_LIMIT`, `code: LIMITS_EXCEEDED`, `recovery: REQUOTE` | quote the next provider |
145
- | 400 | `FiatAmountBelowMinimumError` (`minFiatAmount`) or `FiatAmountAboveMaximumError` (`maxFiatAmount`) | quote the next provider |
149
+ | 404 | `FiatNoRouteError`, `reason` `NO_CANDIDATE`, `PROVIDER_DECLINED`, `PROVIDER_OUTAGE` or `KYC_REJECTED` | next provider |
150
+ | 400 | `FiatNoRouteError`, `reason: USER_LIMIT`, `code: LIMITS_EXCEEDED`, `recovery: REQUOTE` | next provider |
151
+ | 400 | `FiatAmountBelowMinimumError` (`minFiatAmount`) or `FiatAmountAboveMaximumError` (`maxFiatAmount`) | next provider |
146
152
  | 400 | `InvalidParameterError`: a bad request, an asset Fun cannot deliver, or no verified email | stop |
147
153
  | 401, 5xx | any other: a missing or invalid identity assertion, or a server error | stop |
148
154
 
149
- Every fall-through refusal is the named provider's alone, because the route prices only that
150
- provider: `KYC_REJECTED` there means that provider refused the buyer's identity, not every provider.
151
- With no provider left in the interval, refetch the table. The table route refuses with a
155
+ Every fall-through refusal is that provider's alone, because each attempt prices only one provider:
156
+ `KYC_REJECTED` there means that provider refused the buyer's identity, not every provider. With no
157
+ provider left in the interval, refetch the table. The table route refuses with a
152
158
  `FiatRoutingTableErrorBody`: a 429 `TooManyRequestsError` with `retryAfterSeconds` when the
153
159
  per-login budget is spent, or a 400 or 5xx as above. The quote route has no rate limit of its own.
154
160
 
155
161
  Both routes take geo under the `POST /fiat/quote` rules: a known `CountryCode`, a `UsStateCode`
156
162
  region for a US buyer, and an empty `region` or `ip` read as absent. The quote route's `geo` is the
157
163
  Fun geo endpoint's response forwarded as is. The request schemas are strict like every schema here,
158
- so a client sends only the declared keys and no blank strings. `provider` is one of the five
159
- providers the backend routes (`RoutingProvider`). The quote route is temporary: each provider's
160
- `intent` route replaces it.
161
-
162
- **MoonPay (`./moonpay`).** One route, `MOONPAY_ENDPOINTS.intent`. A `MoonPayIntentRequest` is one of
163
- three kinds:
164
-
165
- | `kind` | Carries | A repeat |
166
- | --- | --- | --- |
167
- | `observe` | `checkout`, and `credentials` (`customerId`, `accessToken`) once the SDK has them | writes nothing new |
168
- | `kyc` | `checkout`, `credentials`, `values` keyed by `KycFieldId` (no form id) | drops values MoonPay no longer asks for |
169
- | `order` | `orderId`, `transactionId?`, `quotedAmount`, `geo?` (the checkout's) | returns the recorded order |
170
-
171
- `observe` and `kyc` answer a `MoonPayStepResponse`, which says what the backend needs next:
172
-
173
- | `status` | Carries | The client then |
174
- | --- | --- | --- |
175
- | `TERMS` | `stage`, `documents` (at least one, all at `stage`) | sends `POST /fiat/terms`, then `observe` |
176
- | `SDK_AUTH` | `sessionToken`, `quoteInput`, `resetConnection?` (`true` when the device's MoonPay connection is another buyer's) | resets the connection when asked, runs the MoonPay connection check, then `observe` with credentials |
177
- | `KYC` | `fields`, `fieldErrors?` (each naming a field in `fields`, with `code?` `PHONE_IN_USE` on `PHONE_NUMBER` or `TAX_ID_IN_USE` on `TAX_IDENTIFIER` when another MoonPay customer holds the value) | shows the shared form, then sends `kyc` |
178
- | `PENDING` | `retryAfterMs` (at most 60 s) | sends `observe` after the delay, never `kyc` again |
179
- | `READY` | `orderId`, `quoteInput` | mounts Apple Pay, then sends `order` after the charge |
180
- | `REFUSED` | `reason` (`NOT_ELIGIBLE`, `DOCUMENTS_REQUIRED`, `FINAL_REJECTION`, `CUSTOMER_MISMATCH`), `recovery: REQUOTE \| NONE` | exits the provider flow |
181
-
182
- `order` runs after every charge attempt, a failed one too, and answers a `MoonPayOrderResponse`.
183
- `transactionId` is optional because a failed charge may have none; without it the backend records the
184
- failed charges MoonPay lists for `orderId`. `quotedAmount` is the fiat amount the quote showed.
185
- `geo` is the same object `observe` sends in `checkout`; the order records its `alpha2` as its
186
- country, and no country without it. A
187
- failed charge answers `DONE` with the order in `FAILED`, and the client requotes for a new `orderId`.
188
- After a failed charge with no `transactionId`, the client caps its `PENDING` polls.
189
-
190
- | `status` | Carries | The client then |
191
- | --- | --- | --- |
192
- | `DONE` | `order`, the `GET /fiat/orders/:orderId` response | shows the shared order status |
193
- | `PENDING` | `retryAfterMs` (at most 60 s) | sends the same `order` after the delay |
194
- | `REFUSED` | `reason` (`CUSTOMER_MISMATCH`, `WALLET_MISMATCH`, `UNRECORDABLE`), `recovery: NONE` | exits the provider flow |
195
-
196
- `MoonPayIntentResponseFor` maps each `kind` to its union, and `MoonPayIntentResponse` is both.
164
+ so a client sends only the declared keys and no blank strings. `provider` and each `providers`
165
+ entry are one of the five providers the backend routes (`RoutingProvider`), `providers` with no
166
+ duplicates. The quote route is temporary: `POST /fiat/next` replaces it for each provider that
167
+ moves there.
168
+
169
+ **MoonPay (`./moonpay`).** MoonPay runs on the shared `POST /fiat/next` (`MOONPAY_ENDPOINTS.next`).
170
+ Every `/next` body is a `FiatNextRequest`: `provider`, `geo` (a `FiatGeo`, the geo endpoint's
171
+ response), and the provider's own request, which names its `action`. The orchestrator reads
172
+ `provider` and `geo`; the provider's action schema reads the rest. MoonPay's body is a
173
+ `MoonPayNextRequest`, and every MoonPay request also carries the context `checkout` and, after
174
+ `connect`, `credentials` (`customerId`, `accessToken`).
175
+
176
+ Each `MoonPayAction` has one name. A response's prompt names it in `next` and carries what the
177
+ client needs; the client's request names it in `action` and carries the result:
178
+
179
+ | Action | Prompt carries | Request carries | A repeat |
180
+ | --- | --- | --- | --- |
181
+ | `observe` | no prompt: the answer is the current prompt | nothing | writes nothing |
182
+ | `consent` | `documents` (at least one, unique ids) | `acceptances`, the `POST /fiat/terms` items | writes nothing new |
183
+ | `connect` | `sessionToken`, `quoteInput`, `resetConnection?` (`true` when the device's MoonPay connection is another buyer's) | `customerId`, `accessToken` | rebinds the same customer |
184
+ | `kyc` | `fields`, `fieldErrors?` (each naming a field in `fields`, with `code?` `PHONE_IN_USE` on `PHONE_NUMBER` or `TAX_ID_IN_USE` on `TAX_IDENTIFIER` when another MoonPay customer holds the value) | `credentials`, `values` keyed by `KycFieldId` (no form id) | drops values MoonPay no longer asks for |
185
+ | `wait` | `retryAfterMs` (at most 60 s) | no request: the client sends `observe` after the delay | |
186
+ | `order` | `orderId`, `quoteInput` | `orderId`, `quotedAmount`, `transactionId?` | returns the recorded order |
187
+
188
+ Every response is the next prompt, `done`, or `refused` (`MoonPayRefused`), and
189
+ `MoonPayResponseFor` maps each request action to its union. `observe`, `consent`, `connect` and `kyc`
190
+ answer a `MoonPayStepResponse`: any `MoonPayPrompt`, or `refused` with `reason` (`NOT_ELIGIBLE`,
191
+ `DOCUMENTS_REQUIRED`, `FINAL_REJECTION`, `CUSTOMER_MISMATCH`) and `recovery: REQUOTE | NONE`.
192
+
193
+ `order` runs after every charge attempt, a failed one too, and answers a `MoonPayOrderResponse`:
194
+ `done` with `order`, the `GET /fiat/orders/:orderId` response; `order` again while MoonPay does not
195
+ list the transaction yet; or `refused` with `reason` (`CUSTOMER_MISMATCH`, `WALLET_MISMATCH`,
196
+ `UNRECORDABLE`) and `recovery: NONE`. `transactionId` is optional because a failed charge may have
197
+ none; without it the backend records the failed charges MoonPay lists for `orderId`. `quotedAmount`
198
+ is the fiat amount the device quote showed. The order records the body's `geo.alpha2` as its country.
199
+ A failed charge answers `done` with the order in `FAILED`, and the client requotes for a new `orderId`.
200
+
201
+ A first-time buyer goes `observe` → `consent` → `connect` → `kyc` → `wait` → `observe` → `order` →
202
+ `done`; a returning buyer `observe` → `connect` → `order` → `done`. Both walks are recorded in
203
+ `test/fixtures/moonpay-next/`.
197
204
 
198
205
  A fault is a 4xx or 5xx with a `MoonPayErrorBody`: the shared `errorCode`, `errorMsg` and `reqId`,
199
206
  plus `reason` (`SESSION_BUDGET_SPENT`, `RATE_LIMITED`, `PROVIDER_UNAVAILABLE`, `INVALID_REQUEST`)
200
207
  and `recovery`:
201
- `RETRY` (send the same request again), `REQUOTE`, or `NONE`. A field error is a `KYC`
202
- response, not a fault. The zod schemas (`MoonPay*Schema`, `TermsDocumentSchema`, `FiatTerms*Schema`)
203
- are exported from the root only.
208
+ `RETRY` (send the same request again), `REQUOTE`, or `NONE`. A field error is a `kyc`
209
+ prompt, not a fault. The zod schemas (`MoonPay*Schema`, `FiatGeoSchema`, `FiatNextRequestSchema`,
210
+ `TermsDocumentSchema`, `FiatTerms*Schema`) are exported from the root only.
204
211
 
205
212
  ## KYC SDK hints, results, and client delivery
206
213
 
@@ -41,4 +41,4 @@ export {
41
41
  FUN_KYC_CONSENT_DOCUMENTS,
42
42
  PUBLISHED_TERMS_DOCUMENTS
43
43
  };
44
- //# sourceMappingURL=chunk-5GRPYE2U.mjs.map
44
+ //# sourceMappingURL=chunk-CRNKRIKR.mjs.map
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "0.23.0";
2
+ var version = "0.25.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-EI56NQ7K.mjs.map
517
+ //# sourceMappingURL=chunk-LHCED3AP.mjs.map
@@ -0,0 +1,9 @@
1
+ // src/providers/moonpay.ts
2
+ var MOONPAY_ENDPOINTS = {
3
+ next: "POST /fiat/next"
4
+ };
5
+
6
+ export {
7
+ MOONPAY_ENDPOINTS
8
+ };
9
+ //# sourceMappingURL=chunk-T5JAYOWY.mjs.map
@@ -1,11 +1,11 @@
1
1
  // src/routing.ts
2
2
  var ROUTING_ENDPOINTS = {
3
3
  table: "GET /fiat/routing/table",
4
- /** Temporary: each provider's `intent` route replaces it. */
4
+ /** Temporary: `POST /fiat/next` replaces it for each provider that moves there. */
5
5
  quote: "POST /fiat/routing/quote"
6
6
  };
7
7
 
8
8
  export {
9
9
  ROUTING_ENDPOINTS
10
10
  };
11
- //# sourceMappingURL=chunk-KYE2HYV5.mjs.map
11
+ //# sourceMappingURL=chunk-WEXD7UEE.mjs.map
package/dist/index.js CHANGED
@@ -42,9 +42,12 @@ __export(index_exports, {
42
42
  FiatAmountSchema: () => FiatAmountSchema,
43
43
  FiatCurrencyCode: () => FiatCurrencyCode,
44
44
  FiatEndpointSchema: () => FiatEndpointSchema,
45
+ FiatGeoSchema: () => FiatGeoSchema,
46
+ FiatNextRequestSchema: () => FiatNextRequestSchema,
45
47
  FiatProviderSchema: () => FiatProviderSchema,
46
48
  FiatRoutingQuoteErrorBodySchema: () => FiatRoutingQuoteErrorBodySchema,
47
49
  FiatRoutingQuoteRequestSchema: () => FiatRoutingQuoteRequestSchema,
50
+ FiatRoutingQuoteTermsSchema: () => FiatRoutingQuoteTermsSchema,
48
51
  FiatRoutingTableErrorBodySchema: () => FiatRoutingTableErrorBodySchema,
49
52
  FiatRoutingTableQuerySchema: () => FiatRoutingTableQuerySchema,
50
53
  FiatRoutingTableResponseSchema: () => FiatRoutingTableResponseSchema,
@@ -72,14 +75,28 @@ __export(index_exports, {
72
75
  KycSdkResultReportSchema: () => KycSdkResultReportSchema,
73
76
  MOONPAY_ENDPOINTS: () => MOONPAY_ENDPOINTS,
74
77
  MoonPayCheckoutSchema: () => MoonPayCheckoutSchema,
78
+ MoonPayConnectPromptSchema: () => MoonPayConnectPromptSchema,
79
+ MoonPayConnectRequestSchema: () => MoonPayConnectRequestSchema,
80
+ MoonPayConsentPromptSchema: () => MoonPayConsentPromptSchema,
81
+ MoonPayConsentRequestSchema: () => MoonPayConsentRequestSchema,
82
+ MoonPayDoneSchema: () => MoonPayDoneSchema,
75
83
  MoonPayErrorBodySchema: () => MoonPayErrorBodySchema,
76
84
  MoonPayFaultSchema: () => MoonPayFaultSchema,
77
- MoonPayIntentRequestSchema: () => MoonPayIntentRequestSchema,
78
- MoonPayIntentResponseSchema: () => MoonPayIntentResponseSchema,
85
+ MoonPayKycPromptSchema: () => MoonPayKycPromptSchema,
86
+ MoonPayKycRequestSchema: () => MoonPayKycRequestSchema,
87
+ MoonPayNextRequestSchema: () => MoonPayNextRequestSchema,
88
+ MoonPayObserveRequestSchema: () => MoonPayObserveRequestSchema,
89
+ MoonPayOrderPromptSchema: () => MoonPayOrderPromptSchema,
90
+ MoonPayOrderRequestSchema: () => MoonPayOrderRequestSchema,
79
91
  MoonPayOrderResponseSchema: () => MoonPayOrderResponseSchema,
92
+ MoonPayPromptSchema: () => MoonPayPromptSchema,
80
93
  MoonPayQuoteInputSchema: () => MoonPayQuoteInputSchema,
94
+ MoonPayRequestContextSchema: () => MoonPayRequestContextSchema,
95
+ MoonPayRequestSchema: () => MoonPayRequestSchema,
96
+ MoonPayResponseSchemaFor: () => MoonPayResponseSchemaFor,
81
97
  MoonPaySdkCredentialsSchema: () => MoonPaySdkCredentialsSchema,
82
98
  MoonPayStepResponseSchema: () => MoonPayStepResponseSchema,
99
+ MoonPayWaitPromptSchema: () => MoonPayWaitPromptSchema,
83
100
  OrderAwaitingConfirmationStateSchema: () => OrderAwaitingConfirmationStateSchema,
84
101
  OrderCreatedStateSchema: () => OrderCreatedStateSchema,
85
102
  OrderRefSchema: () => OrderRefSchema,
@@ -1072,8 +1089,7 @@ var $routingTableResponse = obj({
1072
1089
  methods: import_zod.z.array($routingTableMethod).refine((methods) => hasUniqueIds(methods.map((entry) => entry.method)), "each method is listed once")
1073
1090
  });
1074
1091
  var FiatRoutingTableResponseSchema = $routingTableResponse;
1075
- var $routingQuoteRequest = obj({
1076
- provider: $routingProvider,
1092
+ var $routingQuoteTermsShape = {
1077
1093
  fiatCurrency: import_zod.z.enum(FIAT_CURRENCY_CODES),
1078
1094
  fiatAmount: $decimalAmount.refine((amount) => Number(amount) > 0, "must be positive"),
1079
1095
  cryptoCurrencyCode: $nonBlank,
@@ -1084,7 +1100,16 @@ var $routingQuoteRequest = obj({
1084
1100
  { message: US_REGION_REQUIRED, path: ["region"] }
1085
1101
  ),
1086
1102
  prepareSessionAuth: import_zod.z.boolean().optional()
1087
- });
1103
+ };
1104
+ var $routingQuoteTerms = obj($routingQuoteTermsShape);
1105
+ var FiatRoutingQuoteTermsSchema = $routingQuoteTerms;
1106
+ var $routingQuoteRequest = import_zod.z.union([
1107
+ obj({
1108
+ ...$routingQuoteTermsShape,
1109
+ providers: import_zod.z.array($routingProvider).min(1).refine((providers) => hasUniqueIds(providers), "each provider is listed once")
1110
+ }),
1111
+ obj({ ...$routingQuoteTermsShape, provider: $routingProvider })
1112
+ ]);
1088
1113
  var FiatRoutingQuoteRequestSchema = $routingQuoteRequest;
1089
1114
  var $routingServiceableRange = obj({ min: $money, max: $money, userMax: $money.nullable().optional() });
1090
1115
  var $noRouteFields = {
@@ -1121,6 +1146,10 @@ var $routingTableErrorBody = import_zod.z.union([$routingRateLimitedErrorBody, $
1121
1146
  var FiatRoutingTableErrorBodySchema = $routingTableErrorBody;
1122
1147
  var $routingQuoteErrorBody = import_zod.z.union([$routingNoRouteErrorBody, $routingAmountErrorBody, $routingFaultErrorBody]);
1123
1148
  var FiatRoutingQuoteErrorBodySchema = $routingQuoteErrorBody;
1149
+ var $fiatGeo = obj({ alpha2: import_zod.z.string().regex(/^[A-Z]{2}$/), region: $nonBlank.optional(), ip: $nonBlank.optional() });
1150
+ var FiatGeoSchema = $fiatGeo;
1151
+ var $nextRequest = import_zod.z.object({ provider: $provider, action: $nonBlank, geo: $fiatGeo }).catchall(import_zod.z.unknown());
1152
+ var FiatNextRequestSchema = $nextRequest;
1124
1153
  var $providerBoundStepResponse = obj({
1125
1154
  state: $providerBoundFlowState,
1126
1155
  provider: $provider,
@@ -1180,7 +1209,7 @@ var $stepResponse = import_zod.z.union([$providerBoundStepResponse, $blockedStep
1180
1209
  var FiatStepResponseSchema = $stepResponse;
1181
1210
 
1182
1211
  // package.json
1183
- var version = "0.23.0";
1212
+ var version = "0.25.0";
1184
1213
 
1185
1214
  // src/table.ts
1186
1215
  var TABLE_VERSION = version;
@@ -2786,13 +2815,13 @@ var PUBLISHED_TERMS_DOCUMENTS = [MOONPAY_TERMS, ...Object.values(FUN_KYC_CONSENT
2786
2815
  // src/routing.ts
2787
2816
  var ROUTING_ENDPOINTS = {
2788
2817
  table: "GET /fiat/routing/table",
2789
- /** Temporary: each provider's `intent` route replaces it. */
2818
+ /** Temporary: `POST /fiat/next` replaces it for each provider that moves there. */
2790
2819
  quote: "POST /fiat/routing/quote"
2791
2820
  };
2792
2821
 
2793
2822
  // src/providers/moonpay.ts
2794
2823
  var MOONPAY_ENDPOINTS = {
2795
- intent: "POST /fiat/providers/moonpay/intent"
2824
+ next: "POST /fiat/next"
2796
2825
  };
2797
2826
 
2798
2827
  // src/providers/moonpay.schemas.ts
@@ -2801,33 +2830,17 @@ var FIAT_CURRENCY_CODES2 = Object.keys(FIAT_CURRENCY_NAMES);
2801
2830
  var obj2 = (shape) => import_zod2.z.object(shape).strict();
2802
2831
  var $nonEmpty = import_zod2.z.string().refine((value) => value.trim().length > 0, "must not be blank");
2803
2832
  var hasUniqueIds2 = (ids) => new Set(ids).size === ids.length;
2804
- var $geo = obj2({ alpha2: import_zod2.z.string().regex(/^[A-Z]{2}$/), region: $nonEmpty.optional(), ip: $nonEmpty.optional() });
2805
2833
  var $checkout = obj2({
2806
2834
  amount: FiatAmountSchema,
2807
2835
  destination: obj2({ asset: $nonEmpty, network: $nonEmpty }),
2808
- paymentMethod: import_zod2.z.literal("apple_pay"),
2809
- geo: $geo
2836
+ paymentMethod: import_zod2.z.literal("apple_pay")
2810
2837
  });
2811
2838
  var MoonPayCheckoutSchema = $checkout;
2812
2839
  var $credentials = obj2({ customerId: $nonEmpty, accessToken: $nonEmpty });
2813
2840
  var MoonPaySdkCredentialsSchema = $credentials;
2814
- var $intentRequest = import_zod2.z.discriminatedUnion("kind", [
2815
- obj2({ kind: import_zod2.z.literal("observe"), checkout: $checkout, credentials: $credentials.optional() }),
2816
- obj2({
2817
- kind: import_zod2.z.literal("kyc"),
2818
- checkout: $checkout,
2819
- credentials: $credentials,
2820
- values: import_zod2.z.record(KycFieldIdSchema, import_zod2.z.string()).refine((values) => Object.keys(values).length > 0, "values must not be empty")
2821
- }),
2822
- obj2({
2823
- kind: import_zod2.z.literal("order"),
2824
- orderId: $nonEmpty,
2825
- transactionId: $nonEmpty.optional(),
2826
- quotedAmount: FiatAmountSchema,
2827
- geo: $geo.optional()
2828
- })
2829
- ]);
2830
- var MoonPayIntentRequestSchema = $intentRequest;
2841
+ var $context = { checkout: $checkout, credentials: $credentials.optional() };
2842
+ var $requestContext = obj2($context);
2843
+ var MoonPayRequestContextSchema = $requestContext;
2831
2844
  var $quoteInput = obj2({
2832
2845
  source: obj2({ asset: obj2({ code: import_zod2.z.enum(FIAT_CURRENCY_CODES2) }), amount: $nonEmpty }),
2833
2846
  destination: obj2({ asset: obj2({ code: $nonEmpty }) }),
@@ -2836,50 +2849,103 @@ var $quoteInput = obj2({
2836
2849
  feeBehavior: import_zod2.z.literal("inclusive")
2837
2850
  });
2838
2851
  var MoonPayQuoteInputSchema = $quoteInput;
2839
- var $stepRefusal = import_zod2.z.enum(["NOT_ELIGIBLE", "DOCUMENTS_REQUIRED", "FINAL_REJECTION", "CUSTOMER_MISMATCH"]);
2840
- var $orderRefusal = import_zod2.z.enum(["CUSTOMER_MISMATCH", "WALLET_MISMATCH", "UNRECORDABLE"]);
2852
+ var $observeFields = { action: import_zod2.z.literal("observe") };
2853
+ var $consentFields = {
2854
+ action: import_zod2.z.literal("consent"),
2855
+ acceptances: import_zod2.z.array(TermsDocumentAcceptanceSchema).min(1).refine((acceptances) => hasUniqueIds2(acceptances.map((acceptance) => acceptance.documentId)), "each document is accepted once")
2856
+ };
2857
+ var $connectFields = { action: import_zod2.z.literal("connect"), customerId: $nonEmpty, accessToken: $nonEmpty };
2858
+ var $kycFields = {
2859
+ action: import_zod2.z.literal("kyc"),
2860
+ credentials: $credentials,
2861
+ values: import_zod2.z.record(KycFieldIdSchema, import_zod2.z.string()).refine((values) => Object.keys(values).length > 0, "values must not be empty")
2862
+ };
2863
+ var $orderFields = { action: import_zod2.z.literal("order"), orderId: $nonEmpty, quotedAmount: FiatAmountSchema, transactionId: $nonEmpty.optional() };
2864
+ var $observeRequest = obj2({ ...$context, ...$observeFields });
2865
+ var $consentRequest = obj2({ ...$context, ...$consentFields });
2866
+ var $connectRequest = obj2({ ...$context, ...$connectFields });
2867
+ var $kycRequest = obj2({ ...$context, ...$kycFields });
2868
+ var $orderRequest = obj2({ ...$context, ...$orderFields });
2869
+ var MoonPayObserveRequestSchema = $observeRequest;
2870
+ var MoonPayConsentRequestSchema = $consentRequest;
2871
+ var MoonPayConnectRequestSchema = $connectRequest;
2872
+ var MoonPayKycRequestSchema = $kycRequest;
2873
+ var MoonPayOrderRequestSchema = $orderRequest;
2874
+ var $request = import_zod2.z.discriminatedUnion("action", [$observeRequest, $consentRequest, $connectRequest, $kycRequest, $orderRequest]);
2875
+ var MoonPayRequestSchema = $request;
2876
+ var $envelope = { provider: import_zod2.z.literal("MOONPAY"), geo: FiatGeoSchema, ...$context };
2877
+ var $nextRequest2 = import_zod2.z.discriminatedUnion("action", [
2878
+ obj2({ ...$envelope, ...$observeFields }),
2879
+ obj2({ ...$envelope, ...$consentFields }),
2880
+ obj2({ ...$envelope, ...$connectFields }),
2881
+ obj2({ ...$envelope, ...$kycFields }),
2882
+ obj2({ ...$envelope, ...$orderFields })
2883
+ ]);
2884
+ var MoonPayNextRequestSchema = $nextRequest2;
2841
2885
  var FIELD_OF_CODE = { PHONE_IN_USE: "PHONE_NUMBER", TAX_ID_IN_USE: "TAX_IDENTIFIER" };
2842
2886
  var $fieldError = obj2({ fieldId: $nonEmpty, message: $nonEmpty, code: import_zod2.z.enum(["PHONE_IN_USE", "TAX_ID_IN_USE"]).optional() });
2843
- var $pending = obj2({ status: import_zod2.z.literal("PENDING"), retryAfterMs: import_zod2.z.number().int().positive().max(6e4) });
2844
- var $stepStatus = import_zod2.z.discriminatedUnion("status", [
2845
- obj2({ status: import_zod2.z.literal("TERMS"), stage: import_zod2.z.enum(["CHECKOUT", "KYC"]), documents: import_zod2.z.array(TermsDocumentSchema).min(1) }),
2846
- obj2({ status: import_zod2.z.literal("SDK_AUTH"), sessionToken: $nonEmpty, quoteInput: $quoteInput, resetConnection: import_zod2.z.literal(true).optional() }),
2847
- obj2({ status: import_zod2.z.literal("KYC"), fields: import_zod2.z.array(FormFieldSchema).min(1), fieldErrors: import_zod2.z.array($fieldError).min(1).optional() }),
2848
- $pending,
2849
- obj2({ status: import_zod2.z.literal("READY"), orderId: $nonEmpty, quoteInput: $quoteInput }),
2850
- obj2({ status: import_zod2.z.literal("REFUSED"), reason: $stepRefusal, recovery: import_zod2.z.enum(["REQUOTE", "NONE"]) })
2851
- ]);
2852
- var $stepResponse2 = $stepStatus.superRefine((response, context) => {
2853
- if (response.status === "TERMS") {
2854
- if (!hasUniqueIds2(response.documents.map((document) => document.id))) {
2855
- context.addIssue({ code: "custom", path: ["documents"], message: "document ids must be unique" });
2856
- }
2857
- if (response.documents.some((document) => document.stage !== response.stage)) {
2858
- context.addIssue({ code: "custom", path: ["documents"], message: "every document must be at the response stage" });
2859
- }
2887
+ var $consentShape = obj2({ next: import_zod2.z.literal("consent"), documents: import_zod2.z.array(TermsDocumentSchema).min(1) });
2888
+ var $connectPrompt = obj2({
2889
+ next: import_zod2.z.literal("connect"),
2890
+ sessionToken: $nonEmpty,
2891
+ quoteInput: $quoteInput,
2892
+ resetConnection: import_zod2.z.literal(true).optional()
2893
+ });
2894
+ var $kycShape = obj2({ next: import_zod2.z.literal("kyc"), fields: import_zod2.z.array(FormFieldSchema).min(1), fieldErrors: import_zod2.z.array($fieldError).min(1).optional() });
2895
+ var $waitPrompt = obj2({ next: import_zod2.z.literal("wait"), retryAfterMs: import_zod2.z.number().int().positive().max(6e4) });
2896
+ var $orderPrompt = obj2({ next: import_zod2.z.literal("order"), orderId: $nonEmpty, quoteInput: $quoteInput });
2897
+ var checkConsent = (prompt, context) => {
2898
+ if (!hasUniqueIds2(prompt.documents.map((document) => document.id))) {
2899
+ context.addIssue({ code: "custom", path: ["documents"], message: "document ids must be unique" });
2860
2900
  }
2861
- if (response.status === "KYC") {
2862
- const fieldIds = response.fields.map((field) => field.id);
2863
- if (!hasUniqueIds2(fieldIds)) {
2864
- context.addIssue({ code: "custom", path: ["fields"], message: "field ids must be unique" });
2865
- }
2866
- if (response.fieldErrors?.some((error) => !fieldIds.includes(error.fieldId))) {
2867
- context.addIssue({ code: "custom", path: ["fieldErrors"], message: "a field error must name a field in this response" });
2868
- }
2869
- if (response.fieldErrors?.some((error) => error.code && FIELD_OF_CODE[error.code] !== error.fieldId)) {
2870
- context.addIssue({ code: "custom", path: ["fieldErrors"], message: "a field error code must match its field" });
2871
- }
2901
+ };
2902
+ var checkKyc = (prompt, context) => {
2903
+ const fieldIds = prompt.fields.map((field) => field.id);
2904
+ if (!hasUniqueIds2(fieldIds)) {
2905
+ context.addIssue({ code: "custom", path: ["fields"], message: "field ids must be unique" });
2906
+ }
2907
+ if (prompt.fieldErrors?.some((error) => !fieldIds.includes(error.fieldId))) {
2908
+ context.addIssue({ code: "custom", path: ["fieldErrors"], message: "a field error must name a field in this prompt" });
2872
2909
  }
2910
+ if (prompt.fieldErrors?.some((error) => error.code && FIELD_OF_CODE[error.code] !== error.fieldId)) {
2911
+ context.addIssue({ code: "custom", path: ["fieldErrors"], message: "a field error code must match its field" });
2912
+ }
2913
+ };
2914
+ var MoonPayConsentPromptSchema = $consentShape.superRefine(checkConsent);
2915
+ var MoonPayConnectPromptSchema = $connectPrompt;
2916
+ var MoonPayKycPromptSchema = $kycShape.superRefine(checkKyc);
2917
+ var MoonPayWaitPromptSchema = $waitPrompt;
2918
+ var MoonPayOrderPromptSchema = $orderPrompt;
2919
+ var checkPrompt = (response, context) => {
2920
+ if (response.next === "consent") checkConsent(response, context);
2921
+ if (response.next === "kyc") checkKyc(response, context);
2922
+ };
2923
+ var $promptOptions = [$consentShape, $connectPrompt, $kycShape, $waitPrompt, $orderPrompt];
2924
+ var $prompt = import_zod2.z.discriminatedUnion("next", [...$promptOptions]).superRefine(checkPrompt);
2925
+ var MoonPayPromptSchema = $prompt;
2926
+ var $done = obj2({ next: import_zod2.z.literal("done"), order: FiatStepResponseSchema });
2927
+ var MoonPayDoneSchema = $done;
2928
+ var $stepRefused = obj2({
2929
+ next: import_zod2.z.literal("refused"),
2930
+ reason: import_zod2.z.enum(["NOT_ELIGIBLE", "DOCUMENTS_REQUIRED", "FINAL_REJECTION", "CUSTOMER_MISMATCH"]),
2931
+ recovery: import_zod2.z.enum(["REQUOTE", "NONE"])
2873
2932
  });
2933
+ var $orderRefused = obj2({
2934
+ next: import_zod2.z.literal("refused"),
2935
+ reason: import_zod2.z.enum(["CUSTOMER_MISMATCH", "WALLET_MISMATCH", "UNRECORDABLE"]),
2936
+ recovery: import_zod2.z.literal("NONE")
2937
+ });
2938
+ var $stepResponse2 = import_zod2.z.discriminatedUnion("next", [...$promptOptions, $stepRefused]).superRefine(checkPrompt);
2874
2939
  var MoonPayStepResponseSchema = $stepResponse2;
2875
- var $orderResponse = import_zod2.z.discriminatedUnion("status", [
2876
- obj2({ status: import_zod2.z.literal("DONE"), order: FiatStepResponseSchema }),
2877
- $pending,
2878
- obj2({ status: import_zod2.z.literal("REFUSED"), reason: $orderRefusal, recovery: import_zod2.z.literal("NONE") })
2879
- ]);
2940
+ var $orderResponse = import_zod2.z.discriminatedUnion("next", [$done, $orderPrompt, $orderRefused]);
2880
2941
  var MoonPayOrderResponseSchema = $orderResponse;
2881
- var $intentResponse = import_zod2.z.union([$stepResponse2, $orderResponse]);
2882
- var MoonPayIntentResponseSchema = $intentResponse;
2942
+ var MoonPayResponseSchemaFor = {
2943
+ observe: MoonPayStepResponseSchema,
2944
+ consent: MoonPayStepResponseSchema,
2945
+ connect: MoonPayStepResponseSchema,
2946
+ kyc: MoonPayStepResponseSchema,
2947
+ order: MoonPayOrderResponseSchema
2948
+ };
2883
2949
  var $faultFields = {
2884
2950
  reason: import_zod2.z.enum(["SESSION_BUDGET_SPENT", "RATE_LIMITED", "PROVIDER_UNAVAILABLE", "INVALID_REQUEST"]),
2885
2951
  recovery: import_zod2.z.enum(["RETRY", "REQUOTE", "NONE"])