@fun-xyz/fiat-contract 0.22.0 → 0.22.2

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
@@ -127,22 +127,24 @@ three kinds:
127
127
  | --- | --- | --- |
128
128
  | `observe` | `checkout`, and `credentials` (`customerId`, `accessToken`) once the SDK has them | writes nothing new |
129
129
  | `kyc` | `checkout`, `credentials`, `values` keyed by `KycFieldId` (no form id) | drops values MoonPay no longer asks for |
130
- | `order` | `orderId`, `transactionId?`, `quotedAmount` | returns the recorded order |
130
+ | `order` | `orderId`, `transactionId?`, `quotedAmount`, `geo?` (the checkout's) | returns the recorded order |
131
131
 
132
132
  `observe` and `kyc` answer a `MoonPayStepResponse`, which says what the backend needs next:
133
133
 
134
134
  | `status` | Carries | The client then |
135
135
  | --- | --- | --- |
136
136
  | `TERMS` | `stage`, `documents` (at least one, all at `stage`) | sends `POST /fiat/terms`, then `observe` |
137
- | `SDK_AUTH` | `sessionToken`, `quoteInput` | runs the MoonPay connection check, then `observe` with credentials |
138
- | `KYC` | `fields`, `fieldErrors?` (each naming a field in `fields`) | shows the shared form, then sends `kyc` |
137
+ | `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 |
138
+ | `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` |
139
139
  | `PENDING` | `retryAfterMs` (at most 60 s) | sends `observe` after the delay, never `kyc` again |
140
140
  | `READY` | `orderId`, `quoteInput` | mounts Apple Pay, then sends `order` after the charge |
141
141
  | `REFUSED` | `reason` (`NOT_ELIGIBLE`, `DOCUMENTS_REQUIRED`, `FINAL_REJECTION`, `CUSTOMER_MISMATCH`), `recovery: REQUOTE \| NONE` | exits the provider flow |
142
142
 
143
143
  `order` runs after every charge attempt, a failed one too, and answers a `MoonPayOrderResponse`.
144
144
  `transactionId` is optional because a failed charge may have none; without it the backend records the
145
- failed charges MoonPay lists for `orderId`. `quotedAmount` is the fiat amount the quote showed. A
145
+ failed charges MoonPay lists for `orderId`. `quotedAmount` is the fiat amount the quote showed.
146
+ `geo` is the same object `observe` sends in `checkout`; the order records its `alpha2` as its
147
+ country, and no country without it. A
146
148
  failed charge answers `DONE` with the order in `FAILED`, and the client requotes for a new `orderId`.
147
149
  After a failed charge with no `transactionId`, the client caps its `PENDING` polls.
148
150
 
@@ -6,4 +6,4 @@ var MOONPAY_ENDPOINTS = {
6
6
  export {
7
7
  MOONPAY_ENDPOINTS
8
8
  };
9
- //# sourceMappingURL=chunk-SJ7V3YOM.mjs.map
9
+ //# sourceMappingURL=chunk-3HCZ6JBJ.mjs.map
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "0.22.0";
2
+ var version = "0.22.2";
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-7OUDI3JX.mjs.map
517
+ //# sourceMappingURL=chunk-DTHUNDA7.mjs.map
package/dist/index.js CHANGED
@@ -1067,7 +1067,7 @@ var $stepResponse = import_zod.z.union([$providerBoundStepResponse, $blockedStep
1067
1067
  var FiatStepResponseSchema = $stepResponse;
1068
1068
 
1069
1069
  // package.json
1070
- var version = "0.22.0";
1070
+ var version = "0.22.2";
1071
1071
 
1072
1072
  // src/table.ts
1073
1073
  var TABLE_VERSION = version;
@@ -2681,11 +2681,12 @@ var FIAT_CURRENCY_CODES2 = Object.keys(FIAT_CURRENCY_NAMES);
2681
2681
  var obj2 = (shape) => import_zod2.z.object(shape).strict();
2682
2682
  var $nonEmpty = import_zod2.z.string().refine((value) => value.trim().length > 0, "must not be blank");
2683
2683
  var hasUniqueIds2 = (ids) => new Set(ids).size === ids.length;
2684
+ var $geo = obj2({ alpha2: import_zod2.z.string().regex(/^[A-Z]{2}$/), region: $nonEmpty.optional(), ip: $nonEmpty.optional() });
2684
2685
  var $checkout = obj2({
2685
2686
  amount: FiatAmountSchema,
2686
2687
  destination: obj2({ asset: $nonEmpty, network: $nonEmpty }),
2687
2688
  paymentMethod: import_zod2.z.literal("apple_pay"),
2688
- geo: obj2({ alpha2: import_zod2.z.string().regex(/^[A-Z]{2}$/), region: $nonEmpty.optional(), ip: $nonEmpty.optional() })
2689
+ geo: $geo
2689
2690
  });
2690
2691
  var MoonPayCheckoutSchema = $checkout;
2691
2692
  var $credentials = obj2({ customerId: $nonEmpty, accessToken: $nonEmpty });
@@ -2698,7 +2699,13 @@ var $intentRequest = import_zod2.z.discriminatedUnion("kind", [
2698
2699
  credentials: $credentials,
2699
2700
  values: import_zod2.z.record(KycFieldIdSchema, import_zod2.z.string()).refine((values) => Object.keys(values).length > 0, "values must not be empty")
2700
2701
  }),
2701
- obj2({ kind: import_zod2.z.literal("order"), orderId: $nonEmpty, transactionId: $nonEmpty.optional(), quotedAmount: FiatAmountSchema })
2702
+ obj2({
2703
+ kind: import_zod2.z.literal("order"),
2704
+ orderId: $nonEmpty,
2705
+ transactionId: $nonEmpty.optional(),
2706
+ quotedAmount: FiatAmountSchema,
2707
+ geo: $geo.optional()
2708
+ })
2702
2709
  ]);
2703
2710
  var MoonPayIntentRequestSchema = $intentRequest;
2704
2711
  var $quoteInput = obj2({
@@ -2711,11 +2718,12 @@ var $quoteInput = obj2({
2711
2718
  var MoonPayQuoteInputSchema = $quoteInput;
2712
2719
  var $stepRefusal = import_zod2.z.enum(["NOT_ELIGIBLE", "DOCUMENTS_REQUIRED", "FINAL_REJECTION", "CUSTOMER_MISMATCH"]);
2713
2720
  var $orderRefusal = import_zod2.z.enum(["CUSTOMER_MISMATCH", "WALLET_MISMATCH", "UNRECORDABLE"]);
2714
- var $fieldError = obj2({ fieldId: $nonEmpty, message: $nonEmpty });
2721
+ var FIELD_OF_CODE = { PHONE_IN_USE: "PHONE_NUMBER", TAX_ID_IN_USE: "TAX_IDENTIFIER" };
2722
+ var $fieldError = obj2({ fieldId: $nonEmpty, message: $nonEmpty, code: import_zod2.z.enum(["PHONE_IN_USE", "TAX_ID_IN_USE"]).optional() });
2715
2723
  var $pending = obj2({ status: import_zod2.z.literal("PENDING"), retryAfterMs: import_zod2.z.number().int().positive().max(6e4) });
2716
2724
  var $stepStatus = import_zod2.z.discriminatedUnion("status", [
2717
2725
  obj2({ status: import_zod2.z.literal("TERMS"), stage: import_zod2.z.enum(["CHECKOUT", "KYC"]), documents: import_zod2.z.array(TermsDocumentSchema).min(1) }),
2718
- obj2({ status: import_zod2.z.literal("SDK_AUTH"), sessionToken: $nonEmpty, quoteInput: $quoteInput }),
2726
+ obj2({ status: import_zod2.z.literal("SDK_AUTH"), sessionToken: $nonEmpty, quoteInput: $quoteInput, resetConnection: import_zod2.z.literal(true).optional() }),
2719
2727
  obj2({ status: import_zod2.z.literal("KYC"), fields: import_zod2.z.array(FormFieldSchema).min(1), fieldErrors: import_zod2.z.array($fieldError).min(1).optional() }),
2720
2728
  $pending,
2721
2729
  obj2({ status: import_zod2.z.literal("READY"), orderId: $nonEmpty, quoteInput: $quoteInput }),
@@ -2738,6 +2746,9 @@ var $stepResponse2 = $stepStatus.superRefine((response, context) => {
2738
2746
  if (response.fieldErrors?.some((error) => !fieldIds.includes(error.fieldId))) {
2739
2747
  context.addIssue({ code: "custom", path: ["fieldErrors"], message: "a field error must name a field in this response" });
2740
2748
  }
2749
+ if (response.fieldErrors?.some((error) => error.code && FIELD_OF_CODE[error.code] !== error.fieldId)) {
2750
+ context.addIssue({ code: "custom", path: ["fieldErrors"], message: "a field error code must match its field" });
2751
+ }
2741
2752
  }
2742
2753
  });
2743
2754
  var MoonPayStepResponseSchema = $stepResponse2;
package/dist/index.mjs CHANGED
@@ -12,10 +12,10 @@ import {
12
12
  tableEntry,
13
13
  unofferedEndpoints,
14
14
  unreachableStates
15
- } from "./chunk-7OUDI3JX.mjs";
15
+ } from "./chunk-DTHUNDA7.mjs";
16
16
  import {
17
17
  MOONPAY_ENDPOINTS
18
- } from "./chunk-SJ7V3YOM.mjs";
18
+ } from "./chunk-3HCZ6JBJ.mjs";
19
19
  import {
20
20
  FIAT_TERMS_ENDPOINT,
21
21
  FUN_KYC_CONSENT_DOCUMENTS,
@@ -2021,11 +2021,12 @@ var FIAT_CURRENCY_CODES2 = Object.keys(FIAT_CURRENCY_NAMES);
2021
2021
  var obj2 = (shape) => z2.object(shape).strict();
2022
2022
  var $nonEmpty = z2.string().refine((value) => value.trim().length > 0, "must not be blank");
2023
2023
  var hasUniqueIds2 = (ids) => new Set(ids).size === ids.length;
2024
+ var $geo = obj2({ alpha2: z2.string().regex(/^[A-Z]{2}$/), region: $nonEmpty.optional(), ip: $nonEmpty.optional() });
2024
2025
  var $checkout = obj2({
2025
2026
  amount: FiatAmountSchema,
2026
2027
  destination: obj2({ asset: $nonEmpty, network: $nonEmpty }),
2027
2028
  paymentMethod: z2.literal("apple_pay"),
2028
- geo: obj2({ alpha2: z2.string().regex(/^[A-Z]{2}$/), region: $nonEmpty.optional(), ip: $nonEmpty.optional() })
2029
+ geo: $geo
2029
2030
  });
2030
2031
  var MoonPayCheckoutSchema = $checkout;
2031
2032
  var $credentials = obj2({ customerId: $nonEmpty, accessToken: $nonEmpty });
@@ -2038,7 +2039,13 @@ var $intentRequest = z2.discriminatedUnion("kind", [
2038
2039
  credentials: $credentials,
2039
2040
  values: z2.record(KycFieldIdSchema, z2.string()).refine((values) => Object.keys(values).length > 0, "values must not be empty")
2040
2041
  }),
2041
- obj2({ kind: z2.literal("order"), orderId: $nonEmpty, transactionId: $nonEmpty.optional(), quotedAmount: FiatAmountSchema })
2042
+ obj2({
2043
+ kind: z2.literal("order"),
2044
+ orderId: $nonEmpty,
2045
+ transactionId: $nonEmpty.optional(),
2046
+ quotedAmount: FiatAmountSchema,
2047
+ geo: $geo.optional()
2048
+ })
2042
2049
  ]);
2043
2050
  var MoonPayIntentRequestSchema = $intentRequest;
2044
2051
  var $quoteInput = obj2({
@@ -2051,11 +2058,12 @@ var $quoteInput = obj2({
2051
2058
  var MoonPayQuoteInputSchema = $quoteInput;
2052
2059
  var $stepRefusal = z2.enum(["NOT_ELIGIBLE", "DOCUMENTS_REQUIRED", "FINAL_REJECTION", "CUSTOMER_MISMATCH"]);
2053
2060
  var $orderRefusal = z2.enum(["CUSTOMER_MISMATCH", "WALLET_MISMATCH", "UNRECORDABLE"]);
2054
- var $fieldError = obj2({ fieldId: $nonEmpty, message: $nonEmpty });
2061
+ var FIELD_OF_CODE = { PHONE_IN_USE: "PHONE_NUMBER", TAX_ID_IN_USE: "TAX_IDENTIFIER" };
2062
+ var $fieldError = obj2({ fieldId: $nonEmpty, message: $nonEmpty, code: z2.enum(["PHONE_IN_USE", "TAX_ID_IN_USE"]).optional() });
2055
2063
  var $pending = obj2({ status: z2.literal("PENDING"), retryAfterMs: z2.number().int().positive().max(6e4) });
2056
2064
  var $stepStatus = z2.discriminatedUnion("status", [
2057
2065
  obj2({ status: z2.literal("TERMS"), stage: z2.enum(["CHECKOUT", "KYC"]), documents: z2.array(TermsDocumentSchema).min(1) }),
2058
- obj2({ status: z2.literal("SDK_AUTH"), sessionToken: $nonEmpty, quoteInput: $quoteInput }),
2066
+ obj2({ status: z2.literal("SDK_AUTH"), sessionToken: $nonEmpty, quoteInput: $quoteInput, resetConnection: z2.literal(true).optional() }),
2059
2067
  obj2({ status: z2.literal("KYC"), fields: z2.array(FormFieldSchema).min(1), fieldErrors: z2.array($fieldError).min(1).optional() }),
2060
2068
  $pending,
2061
2069
  obj2({ status: z2.literal("READY"), orderId: $nonEmpty, quoteInput: $quoteInput }),
@@ -2078,6 +2086,9 @@ var $stepResponse2 = $stepStatus.superRefine((response, context) => {
2078
2086
  if (response.fieldErrors?.some((error) => !fieldIds.includes(error.fieldId))) {
2079
2087
  context.addIssue({ code: "custom", path: ["fieldErrors"], message: "a field error must name a field in this response" });
2080
2088
  }
2089
+ if (response.fieldErrors?.some((error) => error.code && FIELD_OF_CODE[error.code] !== error.fieldId)) {
2090
+ context.addIssue({ code: "custom", path: ["fieldErrors"], message: "a field error code must match its field" });
2091
+ }
2081
2092
  }
2082
2093
  });
2083
2094
  var MoonPayStepResponseSchema = $stepResponse2;
@@ -60,13 +60,15 @@ export type MoonPayIntentRequest =
60
60
  /**
61
61
  * After every charge attempt, a failed one too. `transactionId` is from the Apple Pay event when it
62
62
  * has one; without it the backend records the failed charges MoonPay lists for `orderId`.
63
- * `quotedAmount` is the fiat amount the buyer saw on the quote.
63
+ * `quotedAmount` is the fiat amount the buyer saw on the quote. `geo` is the checkout's, as sent on
64
+ * `observe`; the order records its `alpha2`, and no country when it is absent.
64
65
  */
65
66
  | {
66
67
  kind: 'order';
67
68
  orderId: string;
68
69
  transactionId?: string;
69
70
  quotedAmount: FiatAmount;
71
+ geo?: MoonPayCheckout['geo'];
70
72
  };
71
73
  export type MoonPayIntentKind = MoonPayIntentRequest['kind'];
72
74
  /**
@@ -101,10 +103,16 @@ export type MoonPayStepRefusal = 'NOT_ELIGIBLE' | 'DOCUMENTS_REQUIRED' | 'FINAL_
101
103
  * assertion's. `UNRECORDABLE`: a charge no retry can record, held for refund review.
102
104
  */
103
105
  export type MoonPayOrderRefusal = 'CUSTOMER_MISMATCH' | 'WALLET_MISMATCH' | 'UNRECORDABLE';
104
- /** A reason on one field of a `KYC` response. `fieldId` names a field in that response. */
106
+ /** Another MoonPay customer already holds the value; only a different one goes through. */
107
+ export type MoonPayFieldErrorCode = 'PHONE_IN_USE' | 'TAX_ID_IN_USE';
108
+ /**
109
+ * A reason on one field of a `KYC` response. `fieldId` names a field in that response. `code` is set
110
+ * only for a refusal the client words itself: `PHONE_IN_USE` on `PHONE_NUMBER`, `TAX_ID_IN_USE` on `TAX_IDENTIFIER`.
111
+ */
105
112
  export interface MoonPayFieldError {
106
113
  fieldId: string;
107
114
  message: string;
115
+ code?: MoonPayFieldErrorCode;
108
116
  }
109
117
  /** The answer to `observe` and `kyc`. */
110
118
  export type MoonPayStepResponse =
@@ -114,11 +122,15 @@ export type MoonPayStepResponse =
114
122
  stage: TermsStage;
115
123
  documents: TermsDocument[];
116
124
  }
117
- /** Run the MoonPay connection check with `sessionToken`, then `observe` with the credentials. */
125
+ /**
126
+ * Run the MoonPay connection check with `sessionToken`, then `observe` with the credentials.
127
+ * `resetConnection`: the device's connection is another buyer's, so reset it before the check.
128
+ */
118
129
  | {
119
130
  status: 'SDK_AUTH';
120
131
  sessionToken: string;
121
132
  quoteInput: MoonPayQuoteInput;
133
+ resetConnection?: true;
122
134
  }
123
135
  /** Show the shared form, then send `kyc`. */
124
136
  | {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  MOONPAY_ENDPOINTS
3
- } from "../chunk-SJ7V3YOM.mjs";
3
+ } from "../chunk-3HCZ6JBJ.mjs";
4
4
  export {
5
5
  MOONPAY_ENDPOINTS
6
6
  };
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.22.0";
39
+ var version = "0.22.2";
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-7OUDI3JX.mjs";
14
+ } from "./chunk-DTHUNDA7.mjs";
15
15
  export {
16
16
  DOCUMENTED_ENDPOINTS,
17
17
  STATE_KEYS,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fun-xyz/fiat-contract",
3
- "version": "0.22.0",
3
+ "version": "0.22.2",
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": {