@fun-xyz/fiat-contract 0.8.0 → 0.10.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
@@ -33,7 +33,9 @@ Source of truth: [Fiat Client Contract](https://app.notion.com/p/3b9fc3b2a002815
33
33
  [Fiat Frontend — State Machine & Screen Map](https://app.notion.com/p/3bbfc3b2a00281c994c2cebd17b1d6d3)
34
34
  (✅ Decisions · per-screen State details · Event bindings per flow state), plus
35
35
  [Fiat KYC — User Flow & API Interfaces](https://app.notion.com/p/3cefc3b2a00281c88e7fe771f0c64332)
36
- for quote-bound KYC states and endpoints.
36
+ for quote-bound KYC states and endpoints, and
37
+ [Fiat Routing Engine — Provider Selection, Ranking & Commit](https://app.notion.com/p/3d1fc3b2a00281f2b604c20869ac420a)
38
+ for quote-screen limits, provider auth channels, and blocked reasons.
37
39
  Tracking: [Headless Fiat Onramp](https://linear.app/funxyz/project/headless-fiat-onramp-0147f4102399) ·
38
40
  this package is [ENG-5268](https://linear.app/funxyz/issue/ENG-5268).
39
41
 
@@ -57,6 +59,11 @@ this package is [ENG-5268](https://linear.app/funxyz/issue/ENG-5268).
57
59
  6. **Surface kind names the renderer; provider selects the adapter.** Sumsub capture is
58
60
  `{ kind: 'KYC_SDK', provider: 'SUMSUB' }`. It is not `URL_EMBED`: the client mounts an SDK,
59
61
  not a URL or iframe.
62
+ 7. **Quote-screen bounds are explicit exact-money strings.** `QUOTE.limits` carries the bounding
63
+ minimum/maximum plus the exact `serviceableRanges` when a routing set has gaps; clients do not
64
+ infer capacity from provider metadata or floating point.
65
+ 8. **Provider auth is capability-shaped.** SMS uses `SMS_OTP`; provider-owned auth uses
66
+ `PROVIDER_RENDERED` with an optional `AUTH_COMPONENT` surface rather than provider-specific channels.
60
67
 
61
68
  ## Versioning — the package version IS the table version
62
69
 
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "0.8.0";
2
+ var version = "0.10.0";
3
3
 
4
4
  // src/table.ts
5
5
  var TABLE_VERSION = version;
@@ -105,6 +105,8 @@ var TRANSITION_TABLE = {
105
105
  ],
106
106
  mayReturn: [
107
107
  "SESSION_AUTH",
108
+ "QUOTE",
109
+ "PAYMENT/CAPTURE",
108
110
  ...KYC_ANY,
109
111
  "ORDER/AWAITING_CONFIRMATION",
110
112
  "PENDING_ORDER"
@@ -498,4 +500,4 @@ export {
498
500
  tableEntry,
499
501
  isTerminal
500
502
  };
501
- //# sourceMappingURL=chunk-LVVQ46YG.mjs.map
503
+ //# sourceMappingURL=chunk-BAGIBS54.mjs.map
package/dist/index.js CHANGED
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  AuthChallengeSchema: () => AuthChallengeSchema,
24
+ BlockedReasonSchema: () => BlockedReasonSchema,
24
25
  BlockedStateSchema: () => BlockedStateSchema,
25
26
  COUNTRY_NAMES: () => COUNTRY_NAMES,
26
27
  COUNTRY_TO_CURRENCY: () => COUNTRY_TO_CURRENCY,
@@ -65,6 +66,8 @@ __export(index_exports, {
65
66
  PaymentInstructStateSchema: () => PaymentInstructStateSchema,
66
67
  PendingOrderStateSchema: () => PendingOrderStateSchema,
67
68
  PollSpecSchema: () => PollSpecSchema,
69
+ QuoteLimitRangeSchema: () => QuoteLimitRangeSchema,
70
+ QuoteLimitsSchema: () => QuoteLimitsSchema,
68
71
  QuoteSchema: () => QuoteSchema,
69
72
  QuoteStateSchema: () => QuoteStateSchema,
70
73
  RecoverySchema: () => RecoverySchema,
@@ -387,7 +390,15 @@ var HTTP_VERBS = ["GET", "POST"];
387
390
  var ENDPOINT_PATTERN = /^(GET|POST) \/fiat\/[^\s]*$/;
388
391
  var $endpoint = import_zod.z.string().regex(ENDPOINT_PATTERN, 'endpoint must read "<GET|POST> /fiat/\u2026"');
389
392
  var FiatEndpointSchema = $endpoint;
390
- var $provider = import_zod.z.enum(["TRANSAK", "SWAPPED", "BANXA", "MOONPAY", "STRIPE"]);
393
+ var $provider = import_zod.z.enum([
394
+ "TRANSAK",
395
+ "SWAPPED",
396
+ "BANXA",
397
+ "MOONPAY",
398
+ "STRIPE",
399
+ "COINBASE",
400
+ "CROSSMINT"
401
+ ]);
391
402
  var FiatProviderSchema = $provider;
392
403
  var $kycProvider = import_zod.z.enum(["SUMSUB"]);
393
404
  var KYCProviderSchema = $kycProvider;
@@ -454,6 +465,14 @@ var $quote = obj({
454
465
  expiresAt: import_zod.z.string()
455
466
  });
456
467
  var QuoteSchema = $quote;
468
+ var $quoteLimitRange = obj({ min: import_zod.z.string(), max: import_zod.z.string() });
469
+ var QuoteLimitRangeSchema = $quoteLimitRange;
470
+ var $quoteLimits = obj({
471
+ min: import_zod.z.string(),
472
+ max: import_zod.z.string(),
473
+ serviceableRanges: import_zod.z.array($quoteLimitRange).min(1).optional()
474
+ });
475
+ var QuoteLimitsSchema = $quoteLimits;
457
476
  var $instrument = obj({ brandLabel: import_zod.z.string(), last4: import_zod.z.string() });
458
477
  var InstrumentSchema = $instrument;
459
478
  var $orderRef = obj({
@@ -484,7 +503,14 @@ var $refund = obj({
484
503
  expectedBy: import_zod.z.string()
485
504
  });
486
505
  var RefundSchema = $refund;
487
- var $surfaceKind = import_zod.z.enum(["URL_REDIRECT", "KYC_SDK", "PCI_COMPONENT", "PAY_SHEET", "ACH_COMPONENT"]);
506
+ var $surfaceKind = import_zod.z.enum([
507
+ "URL_REDIRECT",
508
+ "KYC_SDK",
509
+ "PCI_COMPONENT",
510
+ "PAY_SHEET",
511
+ "ACH_COMPONENT",
512
+ "AUTH_COMPONENT"
513
+ ]);
488
514
  var SurfaceKindSchema = $surfaceKind;
489
515
  var $surface = obj({
490
516
  kind: $surfaceKind,
@@ -629,6 +655,8 @@ var AuthChallengeSchema = $authChallenge;
629
655
  var $quoteState = obj({
630
656
  kind: import_zod.z.literal("QUOTE"),
631
657
  quote: $quote,
658
+ limits: $quoteLimits,
659
+ helper: import_zod.z.string().optional(),
632
660
  /** Present when the provider's component is the primary CTA, inline on the entry screen. */
633
661
  surface: $surface.optional(),
634
662
  error: $failureReason.optional()
@@ -642,7 +670,8 @@ var $funAuthState = obj({
642
670
  var FunAuthStateSchema = $funAuthState;
643
671
  var $sessionAuthState = obj({
644
672
  kind: import_zod.z.literal("SESSION_AUTH"),
645
- channel: import_zod.z.literal("EMAIL_OTP"),
673
+ channel: import_zod.z.enum(["EMAIL_OTP", "SMS_OTP", "PROVIDER_RENDERED"]),
674
+ surface: $surface.optional(),
646
675
  error: $failureReason.optional()
647
676
  });
648
677
  var SessionAuthStateSchema = $sessionAuthState;
@@ -678,9 +707,16 @@ var $pendingOrderState = obj({
678
707
  error: $failureReason.optional()
679
708
  });
680
709
  var PendingOrderStateSchema = $pendingOrderState;
710
+ var $blockedReason = import_zod.z.enum([
711
+ "REGION_UNSUPPORTED",
712
+ "ASSET_UNSUPPORTED",
713
+ "ALL_PROVIDERS_DECLINED",
714
+ "AMOUNT_UNSERVABLE"
715
+ ]);
716
+ var BlockedReasonSchema = $blockedReason;
681
717
  var $blockedState = obj({
682
718
  kind: import_zod.z.literal("BLOCKED"),
683
- reason: import_zod.z.string(),
719
+ reason: $blockedReason,
684
720
  retryAfter: import_zod.z.string().nullable().optional(),
685
721
  error: $failureReason.optional()
686
722
  });
@@ -743,7 +779,7 @@ var $stepResponse = obj({
743
779
  var FiatStepResponseSchema = $stepResponse;
744
780
 
745
781
  // package.json
746
- var version = "0.8.0";
782
+ var version = "0.10.0";
747
783
 
748
784
  // src/table.ts
749
785
  var TABLE_VERSION = version;
@@ -849,6 +885,8 @@ var TRANSITION_TABLE = {
849
885
  ],
850
886
  mayReturn: [
851
887
  "SESSION_AUTH",
888
+ "QUOTE",
889
+ "PAYMENT/CAPTURE",
852
890
  ...KYC_ANY,
853
891
  "ORDER/AWAITING_CONFIRMATION",
854
892
  "PENDING_ORDER"
@@ -1233,6 +1271,20 @@ var FIXTURE_DATA = {
1233
1271
  "screen-01-quote": {
1234
1272
  "state": {
1235
1273
  "kind": "QUOTE",
1274
+ "limits": {
1275
+ "min": "1.00",
1276
+ "max": "3000.00",
1277
+ "serviceableRanges": [
1278
+ {
1279
+ "min": "1.00",
1280
+ "max": "500.00"
1281
+ },
1282
+ {
1283
+ "min": "1000.00",
1284
+ "max": "3000.00"
1285
+ }
1286
+ ]
1287
+ },
1236
1288
  "quote": {
1237
1289
  "quoteRef": "q_8f2",
1238
1290
  "fiat": {
@@ -1277,6 +1329,16 @@ var FIXTURE_DATA = {
1277
1329
  "screen-01b-quote-with-pay-sheet": {
1278
1330
  "state": {
1279
1331
  "kind": "QUOTE",
1332
+ "limits": {
1333
+ "min": "1.00",
1334
+ "max": "3000.00",
1335
+ "serviceableRanges": [
1336
+ {
1337
+ "min": "1.00",
1338
+ "max": "3000.00"
1339
+ }
1340
+ ]
1341
+ },
1280
1342
  "quote": {
1281
1343
  "quoteRef": "q_8f2",
1282
1344
  "fiat": {
@@ -1788,6 +1850,16 @@ var FIXTURE_DATA = {
1788
1850
  "worked-example-01-quote": {
1789
1851
  "state": {
1790
1852
  "kind": "QUOTE",
1853
+ "limits": {
1854
+ "min": "1.00",
1855
+ "max": "3000.00",
1856
+ "serviceableRanges": [
1857
+ {
1858
+ "min": "1.00",
1859
+ "max": "3000.00"
1860
+ }
1861
+ ]
1862
+ },
1791
1863
  "quote": {
1792
1864
  "quoteRef": "q_8f2",
1793
1865
  "fiat": {
package/dist/index.mjs CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  tableEntry,
13
13
  unofferedEndpoints,
14
14
  unreachableStates
15
- } from "./chunk-LVVQ46YG.mjs";
15
+ } from "./chunk-BAGIBS54.mjs";
16
16
 
17
17
  // src/codes.ts
18
18
  var COUNTRY_CURRENCY_LIST = [
@@ -295,7 +295,15 @@ var HTTP_VERBS = ["GET", "POST"];
295
295
  var ENDPOINT_PATTERN = /^(GET|POST) \/fiat\/[^\s]*$/;
296
296
  var $endpoint = z.string().regex(ENDPOINT_PATTERN, 'endpoint must read "<GET|POST> /fiat/\u2026"');
297
297
  var FiatEndpointSchema = $endpoint;
298
- var $provider = z.enum(["TRANSAK", "SWAPPED", "BANXA", "MOONPAY", "STRIPE"]);
298
+ var $provider = z.enum([
299
+ "TRANSAK",
300
+ "SWAPPED",
301
+ "BANXA",
302
+ "MOONPAY",
303
+ "STRIPE",
304
+ "COINBASE",
305
+ "CROSSMINT"
306
+ ]);
299
307
  var FiatProviderSchema = $provider;
300
308
  var $kycProvider = z.enum(["SUMSUB"]);
301
309
  var KYCProviderSchema = $kycProvider;
@@ -362,6 +370,14 @@ var $quote = obj({
362
370
  expiresAt: z.string()
363
371
  });
364
372
  var QuoteSchema = $quote;
373
+ var $quoteLimitRange = obj({ min: z.string(), max: z.string() });
374
+ var QuoteLimitRangeSchema = $quoteLimitRange;
375
+ var $quoteLimits = obj({
376
+ min: z.string(),
377
+ max: z.string(),
378
+ serviceableRanges: z.array($quoteLimitRange).min(1).optional()
379
+ });
380
+ var QuoteLimitsSchema = $quoteLimits;
365
381
  var $instrument = obj({ brandLabel: z.string(), last4: z.string() });
366
382
  var InstrumentSchema = $instrument;
367
383
  var $orderRef = obj({
@@ -392,7 +408,14 @@ var $refund = obj({
392
408
  expectedBy: z.string()
393
409
  });
394
410
  var RefundSchema = $refund;
395
- var $surfaceKind = z.enum(["URL_REDIRECT", "KYC_SDK", "PCI_COMPONENT", "PAY_SHEET", "ACH_COMPONENT"]);
411
+ var $surfaceKind = z.enum([
412
+ "URL_REDIRECT",
413
+ "KYC_SDK",
414
+ "PCI_COMPONENT",
415
+ "PAY_SHEET",
416
+ "ACH_COMPONENT",
417
+ "AUTH_COMPONENT"
418
+ ]);
396
419
  var SurfaceKindSchema = $surfaceKind;
397
420
  var $surface = obj({
398
421
  kind: $surfaceKind,
@@ -537,6 +560,8 @@ var AuthChallengeSchema = $authChallenge;
537
560
  var $quoteState = obj({
538
561
  kind: z.literal("QUOTE"),
539
562
  quote: $quote,
563
+ limits: $quoteLimits,
564
+ helper: z.string().optional(),
540
565
  /** Present when the provider's component is the primary CTA, inline on the entry screen. */
541
566
  surface: $surface.optional(),
542
567
  error: $failureReason.optional()
@@ -550,7 +575,8 @@ var $funAuthState = obj({
550
575
  var FunAuthStateSchema = $funAuthState;
551
576
  var $sessionAuthState = obj({
552
577
  kind: z.literal("SESSION_AUTH"),
553
- channel: z.literal("EMAIL_OTP"),
578
+ channel: z.enum(["EMAIL_OTP", "SMS_OTP", "PROVIDER_RENDERED"]),
579
+ surface: $surface.optional(),
554
580
  error: $failureReason.optional()
555
581
  });
556
582
  var SessionAuthStateSchema = $sessionAuthState;
@@ -586,9 +612,16 @@ var $pendingOrderState = obj({
586
612
  error: $failureReason.optional()
587
613
  });
588
614
  var PendingOrderStateSchema = $pendingOrderState;
615
+ var $blockedReason = z.enum([
616
+ "REGION_UNSUPPORTED",
617
+ "ASSET_UNSUPPORTED",
618
+ "ALL_PROVIDERS_DECLINED",
619
+ "AMOUNT_UNSERVABLE"
620
+ ]);
621
+ var BlockedReasonSchema = $blockedReason;
589
622
  var $blockedState = obj({
590
623
  kind: z.literal("BLOCKED"),
591
- reason: z.string(),
624
+ reason: $blockedReason,
592
625
  retryAfter: z.string().nullable().optional(),
593
626
  error: $failureReason.optional()
594
627
  });
@@ -655,6 +688,20 @@ var FIXTURE_DATA = {
655
688
  "screen-01-quote": {
656
689
  "state": {
657
690
  "kind": "QUOTE",
691
+ "limits": {
692
+ "min": "1.00",
693
+ "max": "3000.00",
694
+ "serviceableRanges": [
695
+ {
696
+ "min": "1.00",
697
+ "max": "500.00"
698
+ },
699
+ {
700
+ "min": "1000.00",
701
+ "max": "3000.00"
702
+ }
703
+ ]
704
+ },
658
705
  "quote": {
659
706
  "quoteRef": "q_8f2",
660
707
  "fiat": {
@@ -699,6 +746,16 @@ var FIXTURE_DATA = {
699
746
  "screen-01b-quote-with-pay-sheet": {
700
747
  "state": {
701
748
  "kind": "QUOTE",
749
+ "limits": {
750
+ "min": "1.00",
751
+ "max": "3000.00",
752
+ "serviceableRanges": [
753
+ {
754
+ "min": "1.00",
755
+ "max": "3000.00"
756
+ }
757
+ ]
758
+ },
702
759
  "quote": {
703
760
  "quoteRef": "q_8f2",
704
761
  "fiat": {
@@ -1210,6 +1267,16 @@ var FIXTURE_DATA = {
1210
1267
  "worked-example-01-quote": {
1211
1268
  "state": {
1212
1269
  "kind": "QUOTE",
1270
+ "limits": {
1271
+ "min": "1.00",
1272
+ "max": "3000.00",
1273
+ "serviceableRanges": [
1274
+ {
1275
+ "min": "1.00",
1276
+ "max": "3000.00"
1277
+ }
1278
+ ]
1279
+ },
1213
1280
  "quote": {
1214
1281
  "quoteRef": "q_8f2",
1215
1282
  "fiat": {
@@ -1652,6 +1719,7 @@ function assertAllFixtures() {
1652
1719
  }
1653
1720
  export {
1654
1721
  AuthChallengeSchema,
1722
+ BlockedReasonSchema,
1655
1723
  BlockedStateSchema,
1656
1724
  COUNTRY_NAMES,
1657
1725
  COUNTRY_TO_CURRENCY,
@@ -1696,6 +1764,8 @@ export {
1696
1764
  PaymentInstructStateSchema,
1697
1765
  PendingOrderStateSchema,
1698
1766
  PollSpecSchema,
1767
+ QuoteLimitRangeSchema,
1768
+ QuoteLimitsSchema,
1699
1769
  QuoteSchema,
1700
1770
  QuoteStateSchema,
1701
1771
  RecoverySchema,
package/dist/schemas.d.ts CHANGED
@@ -27,7 +27,7 @@
27
27
  * They are module-private, so none of it reaches the published declarations.
28
28
  */
29
29
  import { z } from 'zod';
30
- import type { CryptoAmount, FailureReason, FeeLine, FiatEndpoint, FieldSpec, FlowState, FormDescriptor, FormField, FormFieldType, Instructions, InstructionField, Instrument, JsonValue, FiatAmount, OrderRef, OrderStatus, OrderSummary, PollSpec, FiatProvider, Quote, Recovery, Refund, ReportSpec, SelectOption, StatusHistoryEntry, FiatStepResponse, Surface, SurfaceKind, SurfaceProvider, KYCProvider, Transition, TransitionInputs, TransitionParams, Tx } from './types';
30
+ import type { BlockedReason, CryptoAmount, FailureReason, FeeLine, FiatEndpoint, FieldSpec, FlowState, FormDescriptor, FormField, FormFieldType, Instructions, InstructionField, Instrument, JsonValue, FiatAmount, OrderRef, OrderStatus, OrderSummary, PollSpec, FiatProvider, Quote, QuoteLimitRange, QuoteLimits, Recovery, Refund, ReportSpec, SelectOption, StatusHistoryEntry, FiatStepResponse, Surface, SurfaceKind, SurfaceProvider, KYCProvider, Transition, TransitionInputs, TransitionParams, Tx } from './types';
31
31
  export declare const JsonSchema: z.ZodType<JsonValue>;
32
32
  export declare const HTTP_VERBS: readonly ["GET", "POST"];
33
33
  /** `"POST /fiat/session/verify"`, `"GET /fiat/orders/o_31c"` — the verb rides the string. */
@@ -43,6 +43,8 @@ export declare const FiatAmountSchema: z.ZodType<FiatAmount>;
43
43
  export declare const CryptoAmountSchema: z.ZodType<CryptoAmount>;
44
44
  export declare const FeeLineSchema: z.ZodType<FeeLine>;
45
45
  export declare const QuoteSchema: z.ZodType<Quote>;
46
+ export declare const QuoteLimitRangeSchema: z.ZodType<QuoteLimitRange>;
47
+ export declare const QuoteLimitsSchema: z.ZodType<QuoteLimits>;
46
48
  export declare const InstrumentSchema: z.ZodType<Instrument>;
47
49
  export declare const OrderRefSchema: z.ZodType<OrderRef>;
48
50
  export declare const OrderSummarySchema: z.ZodType<OrderSummary>;
@@ -84,6 +86,7 @@ export declare const KycCaptureStateSchema: z.ZodType<State<'KYC', 'CAPTURE'>>;
84
86
  export declare const KycInputRequiredStateSchema: z.ZodType<State<'KYC', 'INPUT_REQUIRED'>>;
85
87
  export declare const KycNoActionRequiredStateSchema: z.ZodType<State<'KYC', 'NO_ACTION_REQUIRED'>>;
86
88
  export declare const PendingOrderStateSchema: z.ZodType<State<'PENDING_ORDER'>>;
89
+ export declare const BlockedReasonSchema: z.ZodType<BlockedReason>;
87
90
  export declare const BlockedStateSchema: z.ZodType<State<'BLOCKED'>>;
88
91
  export declare const PaymentCaptureStateSchema: z.ZodType<State<'PAYMENT', 'CAPTURE'>>;
89
92
  export declare const PaymentInstructStateSchema: z.ZodType<State<'PAYMENT', 'INSTRUCT'>>;
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.8.0";
39
+ var version = "0.10.0";
40
40
 
41
41
  // src/table.ts
42
42
  var TABLE_VERSION = version;
@@ -142,6 +142,8 @@ var TRANSITION_TABLE = {
142
142
  ],
143
143
  mayReturn: [
144
144
  "SESSION_AUTH",
145
+ "QUOTE",
146
+ "PAYMENT/CAPTURE",
145
147
  ...KYC_ANY,
146
148
  "ORDER/AWAITING_CONFIRMATION",
147
149
  "PENDING_ORDER"
package/dist/table.mjs CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  tableEntry,
12
12
  unofferedEndpoints,
13
13
  unreachableStates
14
- } from "./chunk-LVVQ46YG.mjs";
14
+ } from "./chunk-BAGIBS54.mjs";
15
15
  export {
16
16
  DOCUMENTED_ENDPOINTS,
17
17
  STATE_KEYS,
package/dist/types.d.ts CHANGED
@@ -61,7 +61,7 @@ export type FiatEndpoint = 'GET /fiat/payment-methods' | 'POST /fiat/quote' | 'P
61
61
  * Routing metadata, not sequencing policy. Reserved values may be emitted only after their adapter
62
62
  * and conformance fixture land.
63
63
  */
64
- export type FiatProvider = 'TRANSAK' | 'SWAPPED' | 'BANXA' | 'MOONPAY' | 'STRIPE';
64
+ export type FiatProvider = 'TRANSAK' | 'SWAPPED' | 'BANXA' | 'MOONPAY' | 'STRIPE' | 'COINBASE' | 'CROSSMINT';
65
65
  /**
66
66
  * The order status vocabulary. Monotonic ranks, no backwards moves. Terminal outcomes are
67
67
  * OrderStatus, never FlowState kinds.
@@ -151,6 +151,24 @@ export interface Quote {
151
151
  paymentMethod: PaymentMethodCategory;
152
152
  expiresAt: string;
153
153
  }
154
+ /** One inclusive amount interval the current routing set can actually serve. */
155
+ export interface QuoteLimitRange {
156
+ min: string;
157
+ max: string;
158
+ }
159
+ /**
160
+ * Input bounds for the quote screen. Decimal strings in the quote currency.
161
+ *
162
+ * `min`/`max` remain the bounding envelope for clients on contract <=0.9. A routing set can have
163
+ * gaps (one path serves a low interval and another a higher interval), so new emitters also carry
164
+ * the exact sorted, non-overlapping intervals in `serviceableRanges`. The field is optional only so
165
+ * an upgraded client can cold-render an older recorded response during a rolling deployment.
166
+ */
167
+ export interface QuoteLimits {
168
+ min: string;
169
+ max: string;
170
+ serviceableRanges?: QuoteLimitRange[];
171
+ }
154
172
  /** Deferred to the credit-card iteration (FE doc port ledger) — optional wherever it appears. */
155
173
  export interface Instrument {
156
174
  brandLabel: string;
@@ -195,7 +213,7 @@ export interface Refund {
195
213
  expectedBy: string;
196
214
  }
197
215
  /** What the user sees, and therefore where it can be placed. */
198
- export type SurfaceKind = 'URL_REDIRECT' | 'KYC_SDK' | 'PCI_COMPONENT' | 'PAY_SHEET' | 'ACH_COMPONENT';
216
+ export type SurfaceKind = 'URL_REDIRECT' | 'KYC_SDK' | 'PCI_COMPONENT' | 'PAY_SHEET' | 'ACH_COMPONENT' | 'AUTH_COMPONENT';
199
217
  /**
200
218
  * Identity vendors Fun verifies into. Its own axis rather than a `FiatProvider` value, because
201
219
  * Fun is the KYC-of-record in its own tenant — an identity surface is never the onramp's to mint.
@@ -424,6 +442,8 @@ export type FlowState =
424
442
  {
425
443
  kind: 'QUOTE';
426
444
  quote: Quote;
445
+ limits: QuoteLimits;
446
+ helper?: string;
427
447
  surface?: Surface;
428
448
  error?: FailureReason;
429
449
  } | {
@@ -432,7 +452,8 @@ export type FlowState =
432
452
  error?: FailureReason;
433
453
  } | {
434
454
  kind: 'SESSION_AUTH';
435
- channel: 'EMAIL_OTP';
455
+ channel: 'EMAIL_OTP' | 'SMS_OTP' | 'PROVIDER_RENDERED';
456
+ surface?: Surface;
436
457
  error?: FailureReason;
437
458
  }
438
459
  /** Pre-order KYC states carry the routed quote so the entry screen can keep price visible. */
@@ -485,11 +506,7 @@ export type FlowState =
485
506
  error?: FailureReason;
486
507
  } | {
487
508
  kind: 'BLOCKED';
488
- /**
489
- * Observed value: `REGION_UNSUPPORTED` (FE doc Screen 16). The contract types this as
490
- * `string`; no enum is published, so none is invented here.
491
- */
492
- reason: string;
509
+ reason: BlockedReason;
493
510
  /** `null` renders "no comeback date" (FE doc Screen 16 emits it explicitly). */
494
511
  retryAfter?: string | null;
495
512
  error?: FailureReason;
@@ -527,6 +544,7 @@ export type FlowState =
527
544
  error?: FailureReason;
528
545
  };
529
546
  export type FlowStateKind = FlowState['kind'];
547
+ export type BlockedReason = 'REGION_UNSUPPORTED' | 'ASSET_UNSUPPORTED' | 'ALL_PROVIDERS_DECLINED' | 'AMOUNT_UNSERVABLE';
530
548
  /**
531
549
  * Every `/fiat/*` response. `transitions: []` = nothing the wizard can do; whether the *flow*
532
550
  * is over is read from the table (`terminal`), never from array emptiness (ON_HOLD is the proof).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fun-xyz/fiat-contract",
3
- "version": "0.8.0",
3
+ "version": "0.10.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": {