@fun-xyz/fiat-contract 0.22.2 → 0.24.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 +83 -44
- package/dist/chunk-5UEPWL7B.mjs +11 -0
- package/dist/{chunk-5GRPYE2U.mjs → chunk-CRNKRIKR.mjs} +1 -1
- package/dist/{chunk-DTHUNDA7.mjs → chunk-IPOPANXS.mjs} +2 -2
- package/dist/chunk-T5JAYOWY.mjs +9 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +241 -64
- package/dist/index.mjs +238 -65
- package/dist/providers/moonpay.d.ts +107 -109
- package/dist/providers/moonpay.js +1 -1
- package/dist/providers/moonpay.mjs +1 -1
- package/dist/providers/moonpay.schemas.d.ts +22 -5
- package/dist/routing.d.ts +168 -0
- package/dist/routing.js +31 -0
- package/dist/routing.mjs +7 -0
- package/dist/schemas.d.ts +9 -1
- package/dist/table.js +1 -1
- package/dist/table.mjs +1 -1
- package/dist/terms.d.ts +2 -2
- package/dist/terms.mjs +1 -1
- package/dist/types.d.ts +16 -1
- package/package.json +11 -1
- package/routing.d.ts +1 -0
- package/routing.js +2 -0
- package/dist/chunk-3HCZ6JBJ.mjs +0 -9
|
@@ -1,28 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The MoonPay
|
|
2
|
+
* The MoonPay flow on `POST /fiat/next`.
|
|
3
3
|
*
|
|
4
|
-
* Each
|
|
5
|
-
* needs
|
|
6
|
-
* `
|
|
7
|
-
* the
|
|
8
|
-
*
|
|
4
|
+
* Each action has one name and two types. A response's prompt names it in `next` and carries what
|
|
5
|
+
* the client needs to do it. The client's request names it in `action` and carries the result. Every
|
|
6
|
+
* response is the next prompt, `done`, or `refused` (`MoonPayResponseFor`). `observe` carries no
|
|
7
|
+
* result and answers the current prompt. `wait` has no request: the client sends `observe` after it.
|
|
8
|
+
*
|
|
9
|
+
* The body is `MoonPayNextRequest`: `provider`, the shared `geo`, the context (`checkout`, and
|
|
10
|
+
* `credentials` after `connect`), and the action's result. Identity and the deposit wallet always
|
|
11
|
+
* come from the verified partner assertion, never from a request body.
|
|
9
12
|
*
|
|
10
13
|
* A retry sends the same request. Each write is idempotent on data the request carries, and every
|
|
11
14
|
* call, a retry too, returns the current response.
|
|
12
15
|
*
|
|
13
|
-
* A fault is a 4xx/5xx whose body is `MoonPayErrorBody`. Anything the user can act on is a 200
|
|
14
|
-
* `MoonPayIntentResponse`.
|
|
16
|
+
* A fault is a 4xx/5xx whose body is `MoonPayErrorBody`. Anything the user can act on is a 200.
|
|
15
17
|
*
|
|
16
18
|
* Zero runtime dependencies, so production React Native code can import it. The zod schemas are in
|
|
17
19
|
* `./moonpay.schemas`, exported from the package root.
|
|
18
20
|
*/
|
|
19
21
|
import type { FiatCurrencyCode } from '../codes';
|
|
20
|
-
import type {
|
|
21
|
-
import type { FiatAmount, FiatStepResponse, FormField, KycFieldId } from '../types';
|
|
22
|
+
import type { FiatTermsRequest, TermsDocument } from '../terms';
|
|
23
|
+
import type { FiatAmount, FiatGeo, FiatStepResponse, FormField, KycFieldId } from '../types';
|
|
22
24
|
export declare const MOONPAY_ENDPOINTS: {
|
|
23
|
-
readonly
|
|
25
|
+
readonly next: "POST /fiat/next";
|
|
24
26
|
};
|
|
25
|
-
|
|
27
|
+
export type MoonPayAction = 'observe' | 'consent' | 'connect' | 'kyc' | 'wait' | 'order';
|
|
28
|
+
/** The checkout terms. The client holds them and sends them on every request. */
|
|
26
29
|
export interface MoonPayCheckout {
|
|
27
30
|
amount: FiatAmount;
|
|
28
31
|
/** The quote's `crypto.currency` and `crypto.network`, unchanged. */
|
|
@@ -31,46 +34,17 @@ export interface MoonPayCheckout {
|
|
|
31
34
|
network: string;
|
|
32
35
|
};
|
|
33
36
|
paymentMethod: 'apple_pay';
|
|
34
|
-
/** The geo endpoint's response, as sent to `POST /fiat/quote`. `alpha2` is ISO 3166-1 alpha-2. */
|
|
35
|
-
geo: {
|
|
36
|
-
alpha2: string;
|
|
37
|
-
region?: string;
|
|
38
|
-
ip?: string;
|
|
39
|
-
};
|
|
40
37
|
}
|
|
41
38
|
/** From the SDK's `active` connection. `accessToken` is a credential: the backend never logs it. */
|
|
42
39
|
export interface MoonPaySdkCredentials {
|
|
43
40
|
customerId: string;
|
|
44
41
|
accessToken: string;
|
|
45
42
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
{
|
|
49
|
-
kind: 'observe';
|
|
43
|
+
/** On every request, not part of the result. `credentials` is present after `connect`. */
|
|
44
|
+
export type MoonPayRequestContext = {
|
|
50
45
|
checkout: MoonPayCheckout;
|
|
51
46
|
credentials?: MoonPaySdkCredentials;
|
|
52
|
-
}
|
|
53
|
-
/** Only after a `KYC` response. `values` is keyed by the ids of that response's fields; there is no form id. */
|
|
54
|
-
| {
|
|
55
|
-
kind: 'kyc';
|
|
56
|
-
checkout: MoonPayCheckout;
|
|
57
|
-
credentials: MoonPaySdkCredentials;
|
|
58
|
-
values: Partial<Record<KycFieldId, string>>;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* After every charge attempt, a failed one too. `transactionId` is from the Apple Pay event when it
|
|
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. `geo` is the checkout's, as sent on
|
|
64
|
-
* `observe`; the order records its `alpha2`, and no country when it is absent.
|
|
65
|
-
*/
|
|
66
|
-
| {
|
|
67
|
-
kind: 'order';
|
|
68
|
-
orderId: string;
|
|
69
|
-
transactionId?: string;
|
|
70
|
-
quotedAmount: FiatAmount;
|
|
71
|
-
geo?: MoonPayCheckout['geo'];
|
|
72
47
|
};
|
|
73
|
-
export type MoonPayIntentKind = MoonPayIntentRequest['kind'];
|
|
74
48
|
/**
|
|
75
49
|
* The parameters for the device `client.getQuote`, not a quote. The backend builds them because the
|
|
76
50
|
* wallet must be the verified one and MoonPay's currency codes differ by environment.
|
|
@@ -95,18 +69,39 @@ export interface MoonPayQuoteInput {
|
|
|
95
69
|
};
|
|
96
70
|
feeBehavior: 'inclusive';
|
|
97
71
|
}
|
|
98
|
-
/**
|
|
99
|
-
export type
|
|
72
|
+
/** No prompt of its own: the answer is the current prompt. Writes nothing. */
|
|
73
|
+
export type MoonPayObserveRequest = {
|
|
74
|
+
action: 'observe';
|
|
75
|
+
};
|
|
76
|
+
/** MoonPay's terms first. Later, before `kyc`, Fun's KYC consent if the buyer has not accepted it. */
|
|
77
|
+
export type MoonPayConsentPrompt = {
|
|
78
|
+
next: 'consent';
|
|
79
|
+
documents: TermsDocument[];
|
|
80
|
+
};
|
|
81
|
+
/** The `POST /fiat/terms` items, recorded under the same rules. */
|
|
82
|
+
export type MoonPayConsentRequest = {
|
|
83
|
+
action: 'consent';
|
|
84
|
+
acceptances: FiatTermsRequest['acceptances'];
|
|
85
|
+
};
|
|
100
86
|
/**
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
* assertion's. `UNRECORDABLE`: a charge no retry can record, held for refund review.
|
|
87
|
+
* Run MoonPay's connection check with `sessionToken`; it asks for an OTP only if the hidden check
|
|
88
|
+
* fails. `resetConnection`: the device's connection is another buyer's, so reset it first.
|
|
104
89
|
*/
|
|
105
|
-
export type
|
|
90
|
+
export type MoonPayConnectPrompt = {
|
|
91
|
+
next: 'connect';
|
|
92
|
+
sessionToken: string;
|
|
93
|
+
quoteInput: MoonPayQuoteInput;
|
|
94
|
+
resetConnection?: true;
|
|
95
|
+
};
|
|
96
|
+
export type MoonPayConnectRequest = {
|
|
97
|
+
action: 'connect';
|
|
98
|
+
customerId: string;
|
|
99
|
+
accessToken: string;
|
|
100
|
+
};
|
|
106
101
|
/** Another MoonPay customer already holds the value; only a different one goes through. */
|
|
107
102
|
export type MoonPayFieldErrorCode = 'PHONE_IN_USE' | 'TAX_ID_IN_USE';
|
|
108
103
|
/**
|
|
109
|
-
* A reason on one field of a `
|
|
104
|
+
* A reason on one field of a `kyc` prompt. `fieldId` names a field in that prompt. `code` is set
|
|
110
105
|
* only for a refusal the client words itself: `PHONE_IN_USE` on `PHONE_NUMBER`, `TAX_ID_IN_USE` on `TAX_IDENTIFIER`.
|
|
111
106
|
*/
|
|
112
107
|
export interface MoonPayFieldError {
|
|
@@ -114,82 +109,85 @@ export interface MoonPayFieldError {
|
|
|
114
109
|
message: string;
|
|
115
110
|
code?: MoonPayFieldErrorCode;
|
|
116
111
|
}
|
|
117
|
-
/**
|
|
118
|
-
export type
|
|
119
|
-
|
|
120
|
-
{
|
|
121
|
-
status: 'TERMS';
|
|
122
|
-
stage: TermsStage;
|
|
123
|
-
documents: TermsDocument[];
|
|
124
|
-
}
|
|
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
|
-
*/
|
|
129
|
-
| {
|
|
130
|
-
status: 'SDK_AUTH';
|
|
131
|
-
sessionToken: string;
|
|
132
|
-
quoteInput: MoonPayQuoteInput;
|
|
133
|
-
resetConnection?: true;
|
|
134
|
-
}
|
|
135
|
-
/** Show the shared form, then send `kyc`. */
|
|
136
|
-
| {
|
|
137
|
-
status: 'KYC';
|
|
112
|
+
/** Show the shared form. */
|
|
113
|
+
export type MoonPayKycPrompt = {
|
|
114
|
+
next: 'kyc';
|
|
138
115
|
fields: FormField[];
|
|
139
116
|
fieldErrors?: MoonPayFieldError[];
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
|
|
143
|
-
|
|
117
|
+
};
|
|
118
|
+
/** Keyed by the ids of the prompt's fields; there is no form id. Needs `credentials`: the backend reads the customer. */
|
|
119
|
+
export type MoonPayKycRequest = {
|
|
120
|
+
action: 'kyc';
|
|
121
|
+
credentials: MoonPaySdkCredentials;
|
|
122
|
+
values: Partial<Record<KycFieldId, string>>;
|
|
123
|
+
};
|
|
124
|
+
/** MoonPay is reviewing. No request of its own: send `observe` after the delay. */
|
|
125
|
+
export type MoonPayWaitPrompt = {
|
|
126
|
+
next: 'wait';
|
|
144
127
|
retryAfterMs: number;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
|
|
148
|
-
|
|
128
|
+
};
|
|
129
|
+
/** Get the device quote from `quoteInput`, mount Apple Pay with `externalTransactionId = orderId`. */
|
|
130
|
+
export type MoonPayOrderPrompt = {
|
|
131
|
+
next: 'order';
|
|
149
132
|
orderId: string;
|
|
150
133
|
quoteInput: MoonPayQuoteInput;
|
|
151
|
-
}
|
|
152
|
-
/** Exit the provider flow. `REQUOTE` goes back to `POST /fiat/quote`; `NONE` ends the flow. */
|
|
153
|
-
| {
|
|
154
|
-
status: 'REFUSED';
|
|
155
|
-
reason: MoonPayStepRefusal;
|
|
156
|
-
recovery: 'REQUOTE' | 'NONE';
|
|
157
134
|
};
|
|
158
135
|
/**
|
|
159
|
-
*
|
|
160
|
-
*
|
|
136
|
+
* After every charge attempt, a failed one too. `quotedAmount` is the fiat amount the device quote
|
|
137
|
+
* showed. `transactionId` is from the Apple Pay event when it has one; without it the backend
|
|
138
|
+
* records the failed charges MoonPay lists for `orderId`.
|
|
161
139
|
*/
|
|
162
|
-
export type
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
140
|
+
export type MoonPayOrderRequest = {
|
|
141
|
+
action: 'order';
|
|
142
|
+
orderId: string;
|
|
143
|
+
quotedAmount: FiatAmount;
|
|
144
|
+
transactionId?: string;
|
|
145
|
+
};
|
|
146
|
+
export type MoonPayRequest = MoonPayRequestContext & (MoonPayObserveRequest | MoonPayConsentRequest | MoonPayConnectRequest | MoonPayKycRequest | MoonPayOrderRequest);
|
|
147
|
+
/** The wire body. The orchestrator reads `provider` and `geo`; MoonPay's action schemas read the rest. */
|
|
148
|
+
export type MoonPayNextRequest = {
|
|
149
|
+
provider: 'MOONPAY';
|
|
150
|
+
geo: FiatGeo;
|
|
151
|
+
} & MoonPayRequest;
|
|
152
|
+
/** `REQUOTE` for `NOT_ELIGIBLE` and `DOCUMENTS_REQUIRED`, `NONE` for the others. */
|
|
153
|
+
export type MoonPayStepRefusal = 'NOT_ELIGIBLE' | 'DOCUMENTS_REQUIRED' | 'FINAL_REJECTION' | 'CUSTOMER_MISMATCH';
|
|
168
154
|
/**
|
|
169
|
-
*
|
|
170
|
-
*
|
|
155
|
+
* After a charge, always with `recovery: NONE`. `CUSTOMER_MISMATCH`: the transaction's customer is
|
|
156
|
+
* not bound to this buyer. `WALLET_MISMATCH`: the transaction pays another wallet than the
|
|
157
|
+
* assertion's. `UNRECORDABLE`: a charge no retry can record, held for refund review.
|
|
171
158
|
*/
|
|
172
|
-
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
status: 'REFUSED';
|
|
179
|
-
reason: MoonPayOrderRefusal;
|
|
180
|
-
recovery: 'NONE';
|
|
159
|
+
export type MoonPayOrderRefusal = 'CUSTOMER_MISMATCH' | 'WALLET_MISMATCH' | 'UNRECORDABLE';
|
|
160
|
+
export type MoonPayPrompt = MoonPayConsentPrompt | MoonPayConnectPrompt | MoonPayKycPrompt | MoonPayWaitPrompt | MoonPayOrderPrompt;
|
|
161
|
+
/** `order` is the `GET /fiat/orders/:orderId` body; the shared order screen renders it. */
|
|
162
|
+
export type MoonPayDone = {
|
|
163
|
+
next: 'done';
|
|
164
|
+
order: FiatStepResponse;
|
|
181
165
|
};
|
|
182
|
-
|
|
166
|
+
/** Exit the provider flow. `REQUOTE` goes back to routing; `NONE` ends the flow. */
|
|
167
|
+
export type MoonPayRefused<R, V> = {
|
|
168
|
+
next: 'refused';
|
|
169
|
+
reason: R;
|
|
170
|
+
recovery: V;
|
|
171
|
+
};
|
|
172
|
+
/** The answer to `observe`, `consent`, `connect` and `kyc`. */
|
|
173
|
+
export type MoonPayStepResponse = MoonPayPrompt | MoonPayRefused<MoonPayStepRefusal, 'REQUOTE' | 'NONE'>;
|
|
174
|
+
/**
|
|
175
|
+
* The answer to `order`. A failed charge is recorded too: `done` with the order in `FAILED`, and the
|
|
176
|
+
* client requotes for a new `orderId`. `order` again while MoonPay does not list the transaction
|
|
177
|
+
* yet. A refusal after a charge never requotes: that would start a second payment.
|
|
178
|
+
*/
|
|
179
|
+
export type MoonPayOrderResponse = MoonPayDone | MoonPayOrderPrompt | MoonPayRefused<MoonPayOrderRefusal, 'NONE'>;
|
|
180
|
+
export type MoonPayResponseFor = {
|
|
183
181
|
observe: MoonPayStepResponse;
|
|
182
|
+
consent: MoonPayStepResponse;
|
|
183
|
+
connect: MoonPayStepResponse;
|
|
184
184
|
kyc: MoonPayStepResponse;
|
|
185
185
|
order: MoonPayOrderResponse;
|
|
186
186
|
};
|
|
187
|
-
|
|
188
|
-
export type MoonPayIntentStatus = MoonPayIntentResponse['status'];
|
|
189
|
-
/** `RETRY` sends the same request again. `REQUOTE` goes back to `POST /fiat/quote`. `NONE` ends the flow. */
|
|
187
|
+
/** `RETRY` sends the same request again. `REQUOTE` goes back to routing. `NONE` ends the flow. */
|
|
190
188
|
export type MoonPayRecovery = 'RETRY' | 'REQUOTE' | 'NONE';
|
|
191
189
|
/**
|
|
192
|
-
* `SESSION_BUDGET_SPENT`: the per-login SDK session mint budget (429). `RATE_LIMITED`: the
|
|
190
|
+
* `SESSION_BUDGET_SPENT`: the per-login SDK session mint budget (429). `RATE_LIMITED`: the action's
|
|
193
191
|
* request budget (429). `PROVIDER_UNAVAILABLE`: MoonPay or Sumsub is down. `INVALID_REQUEST`: a bad
|
|
194
192
|
* body (400).
|
|
195
193
|
*/
|
|
@@ -1,16 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* zod schemas for the MoonPay
|
|
3
|
-
* the package root, never from `./moonpay`, so the production entry stays free of zod.
|
|
2
|
+
* zod schemas for the MoonPay flow on `POST /fiat/next`. Test-time and backend-boundary only:
|
|
3
|
+
* exported from 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,
|
|
6
|
+
import type { MoonPayCheckout, MoonPayConnectPrompt, MoonPayConnectRequest, MoonPayConsentPrompt, MoonPayConsentRequest, MoonPayDone, MoonPayErrorBody, MoonPayFault, MoonPayKycPrompt, MoonPayKycRequest, MoonPayNextRequest, MoonPayObserveRequest, MoonPayOrderPrompt, MoonPayOrderRequest, MoonPayOrderResponse, MoonPayPrompt, MoonPayQuoteInput, MoonPayRequest, MoonPayRequestContext, MoonPayResponseFor, MoonPaySdkCredentials, MoonPayStepResponse, MoonPayWaitPrompt } from './moonpay';
|
|
7
7
|
export declare const MoonPayCheckoutSchema: z.ZodType<MoonPayCheckout>;
|
|
8
8
|
export declare const MoonPaySdkCredentialsSchema: z.ZodType<MoonPaySdkCredentials>;
|
|
9
|
-
export declare const
|
|
9
|
+
export declare const MoonPayRequestContextSchema: z.ZodType<MoonPayRequestContext>;
|
|
10
10
|
export declare const MoonPayQuoteInputSchema: z.ZodType<MoonPayQuoteInput>;
|
|
11
|
+
export declare const MoonPayObserveRequestSchema: z.ZodType<MoonPayRequestContext & MoonPayObserveRequest>;
|
|
12
|
+
export declare const MoonPayConsentRequestSchema: z.ZodType<MoonPayRequestContext & MoonPayConsentRequest>;
|
|
13
|
+
export declare const MoonPayConnectRequestSchema: z.ZodType<MoonPayRequestContext & MoonPayConnectRequest>;
|
|
14
|
+
export declare const MoonPayKycRequestSchema: z.ZodType<MoonPayRequestContext & MoonPayKycRequest>;
|
|
15
|
+
export declare const MoonPayOrderRequestSchema: z.ZodType<MoonPayRequestContext & MoonPayOrderRequest>;
|
|
16
|
+
export declare const MoonPayRequestSchema: z.ZodType<MoonPayRequest>;
|
|
17
|
+
export declare const MoonPayNextRequestSchema: z.ZodType<MoonPayNextRequest>;
|
|
18
|
+
export declare const MoonPayConsentPromptSchema: z.ZodType<MoonPayConsentPrompt>;
|
|
19
|
+
export declare const MoonPayConnectPromptSchema: z.ZodType<MoonPayConnectPrompt>;
|
|
20
|
+
export declare const MoonPayKycPromptSchema: z.ZodType<MoonPayKycPrompt>;
|
|
21
|
+
export declare const MoonPayWaitPromptSchema: z.ZodType<MoonPayWaitPrompt>;
|
|
22
|
+
export declare const MoonPayOrderPromptSchema: z.ZodType<MoonPayOrderPrompt>;
|
|
23
|
+
export declare const MoonPayPromptSchema: z.ZodType<MoonPayPrompt>;
|
|
24
|
+
export declare const MoonPayDoneSchema: z.ZodType<MoonPayDone>;
|
|
11
25
|
export declare const MoonPayStepResponseSchema: z.ZodType<MoonPayStepResponse>;
|
|
12
26
|
export declare const MoonPayOrderResponseSchema: z.ZodType<MoonPayOrderResponse>;
|
|
13
|
-
|
|
27
|
+
/** The response schema for each request action, as `MoonPayResponseFor` types it. */
|
|
28
|
+
export declare const MoonPayResponseSchemaFor: {
|
|
29
|
+
readonly [A in keyof MoonPayResponseFor]: z.ZodType<MoonPayResponseFor[A]>;
|
|
30
|
+
};
|
|
14
31
|
export declare const MoonPayFaultSchema: z.ZodType<MoonPayFault>;
|
|
15
32
|
export declare const MoonPayErrorBodySchema: z.ZodType<MoonPayErrorBody>;
|
|
16
33
|
//# sourceMappingURL=moonpay.schemas.d.ts.map
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The routing table: `GET /fiat/routing/table` and `POST /fiat/routing/quote`.
|
|
3
|
+
*
|
|
4
|
+
* The client loads the table when the sheet opens. For each payment method it lists every amount
|
|
5
|
+
* interval and the providers that serve it, best first, each with what it needs from the buyer next.
|
|
6
|
+
* The client then shows min, max, provider and the Continue label for any amount with no call, and
|
|
7
|
+
* quotes only the interval's first provider, and the next one after a fall-through refusal
|
|
8
|
+
* (`FiatRoutingQuoteErrorBody`).
|
|
9
|
+
*
|
|
10
|
+
* The table is advisory: every routing quote checks the named provider's eligibility again. Refetch it
|
|
11
|
+
* at `expiresAt`, on `refreshLimits: true`, and after auth, KYC or a `REQUOTE` refusal.
|
|
12
|
+
*
|
|
13
|
+
* Changes to both routes only add fields and enum values. Map an unknown `next` to the generic
|
|
14
|
+
* Continue label.
|
|
15
|
+
*
|
|
16
|
+
* Zero runtime dependencies, so production React Native code can import it. The zod schemas are
|
|
17
|
+
* exported from the package root. Like every schema in the package they are strict: a request with
|
|
18
|
+
* an extra key or a blank string fails them, so send only the declared fields.
|
|
19
|
+
*/
|
|
20
|
+
import type { CountryCode, FiatCurrencyCode, PaymentMethodCategory } from './codes';
|
|
21
|
+
import type { FiatAmount, FiatProvider, QuoteLimitRange } from './types';
|
|
22
|
+
export declare const ROUTING_ENDPOINTS: {
|
|
23
|
+
readonly table: "GET /fiat/routing/table";
|
|
24
|
+
/** Temporary: `POST /fiat/next` replaces it for each provider that moves there. */
|
|
25
|
+
readonly quote: "POST /fiat/routing/quote";
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* The query string of `GET /fiat/routing/table`. `country` and `region` are the geo endpoint's
|
|
29
|
+
* `alpha2` and `region`, held to the `POST /fiat/quote` geo rules: a US buyer's `region` must be a
|
|
30
|
+
* `UsStateCode`, and an empty `region` counts as absent.
|
|
31
|
+
*/
|
|
32
|
+
export interface FiatRoutingTableQuery {
|
|
33
|
+
/** Defaults to `USD`. */
|
|
34
|
+
fiatCurrencyCode?: FiatCurrencyCode;
|
|
35
|
+
cryptoCurrencyCode: string;
|
|
36
|
+
chainId: string;
|
|
37
|
+
country: CountryCode;
|
|
38
|
+
region?: string;
|
|
39
|
+
/** Comma-separated `PaymentMethodCategory` values, for example `apple_pay,card`. */
|
|
40
|
+
methods: string;
|
|
41
|
+
}
|
|
42
|
+
/** What a provider needs from this buyer before it can take the payment. */
|
|
43
|
+
export type RoutingNextStep = 'READY' | 'AUTH' | 'DECLARATIVE_KYC' | 'DOCUMENTARY_KYC' | 'PENDING_REVIEW';
|
|
44
|
+
/** How much past `next` the backend can see: the whole picture, part of it, or nothing before auth. */
|
|
45
|
+
export type RoutingVisibility = 'COMPLETE' | 'PARTIAL' | 'AUTH_GATED';
|
|
46
|
+
/**
|
|
47
|
+
* Why a method has no interval. Present only when `intervals` is empty, and absent there too when the
|
|
48
|
+
* cause is unknown. `NOT_SERVED`: every provider was ruled out for reasons that depend on neither the
|
|
49
|
+
* buyer nor provider health: it does not offer the corridor, currency, method or asset, or config has
|
|
50
|
+
* not enabled it.
|
|
51
|
+
*/
|
|
52
|
+
export type RoutingUnavailableReason = 'USER_LIMIT' | 'KYC_REJECTED' | 'PROVIDER_OUTAGE' | 'NOT_SERVED';
|
|
53
|
+
/** The providers the backend can route and take an order through. */
|
|
54
|
+
export type RoutingProvider = Extract<FiatProvider, 'TRANSAK' | 'BANXA' | 'MOONPAY' | 'STRIPE' | 'COINBASE'>;
|
|
55
|
+
export interface RoutingTableProvider {
|
|
56
|
+
provider: RoutingProvider;
|
|
57
|
+
next: RoutingNextStep;
|
|
58
|
+
visibility: RoutingVisibility;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* A `QuoteLimitRange` with two decimals (`"20.00"`) and the providers that serve it. The next
|
|
62
|
+
* interval starts one cent above `max`. Adjacent intervals always rank differently.
|
|
63
|
+
*/
|
|
64
|
+
export interface RoutingTableInterval extends QuoteLimitRange {
|
|
65
|
+
/** Best first; never empty. Quote the first, and the next one after a decline. */
|
|
66
|
+
providers: RoutingTableProvider[];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* One requested payment method. An amount in no interval has no provider: show the nearest edges
|
|
70
|
+
* ("Minimum $X", "Maximum $Y", or both around a gap), never a blocked state while `intervals` is not
|
|
71
|
+
* empty. With no interval at all, show `unavailableReason` instead of the amount picker.
|
|
72
|
+
*/
|
|
73
|
+
export interface RoutingTableMethod {
|
|
74
|
+
method: PaymentMethodCategory;
|
|
75
|
+
unavailableReason?: RoutingUnavailableReason;
|
|
76
|
+
/** Sorted and non-overlapping. */
|
|
77
|
+
intervals: RoutingTableInterval[];
|
|
78
|
+
}
|
|
79
|
+
export interface FiatRoutingTableResponse {
|
|
80
|
+
/** ISO-8601. The earliest of 60 s after the build and the expiry of any limit, coverage or provider session behind it. */
|
|
81
|
+
expiresAt: string;
|
|
82
|
+
/** In request order, duplicates removed. */
|
|
83
|
+
methods: RoutingTableMethod[];
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The `POST /fiat/quote` body plus the one `provider` to price, which is the interval's first
|
|
87
|
+
* provider, and never `routingOverrides`. The response is the same `FiatStepResponse` as
|
|
88
|
+
* `POST /fiat/quote`; a refusal is a `FiatRoutingQuoteErrorBody`.
|
|
89
|
+
*/
|
|
90
|
+
export interface FiatRoutingQuoteRequest {
|
|
91
|
+
provider: RoutingProvider;
|
|
92
|
+
fiatCurrency: FiatCurrencyCode;
|
|
93
|
+
/** A positive decimal string with no leading zero, exponent or sign (`"20"`, `"20.5"`). */
|
|
94
|
+
fiatAmount: string;
|
|
95
|
+
cryptoCurrencyCode: string;
|
|
96
|
+
chainId: string;
|
|
97
|
+
paymentMethodId: PaymentMethodCategory;
|
|
98
|
+
/**
|
|
99
|
+
* The Fun geo endpoint's response, forwarded as is. An empty `region` or `ip` counts as absent, a
|
|
100
|
+
* US buyer's `region` must be a `UsStateCode`, and `city` is ignored.
|
|
101
|
+
*/
|
|
102
|
+
geo: {
|
|
103
|
+
alpha2: CountryCode;
|
|
104
|
+
region?: string;
|
|
105
|
+
ip?: string;
|
|
106
|
+
city?: string;
|
|
107
|
+
};
|
|
108
|
+
prepareSessionAuth?: boolean;
|
|
109
|
+
}
|
|
110
|
+
/** One serviceable range of the named provider. `userMax` is this buyer's own ceiling inside it, `null` when unmeasured. */
|
|
111
|
+
export interface RoutingServiceableRange {
|
|
112
|
+
min: FiatAmount;
|
|
113
|
+
max: FiatAmount;
|
|
114
|
+
userMax?: FiatAmount | null;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Why the named provider cannot price the request. `NO_CANDIDATE`: it does not serve this corridor,
|
|
118
|
+
* method or amount. `PROVIDER_DECLINED`: it priced and then declined this buyer. `PROVIDER_OUTAGE`:
|
|
119
|
+
* it is down, so `retryable` is true. `KYC_REJECTED`: it refused this buyer's identity for good.
|
|
120
|
+
* `USER_LIMIT`: this buyer's limits at it do not allow the amount.
|
|
121
|
+
*/
|
|
122
|
+
export type RoutingNoRouteReason = 'NO_CANDIDATE' | 'PROVIDER_DECLINED' | 'PROVIDER_OUTAGE' | 'KYC_REJECTED' | 'USER_LIMIT';
|
|
123
|
+
/** The shared fields of every `/fiat/*` error body. */
|
|
124
|
+
interface ErrorBodyFields {
|
|
125
|
+
errorMsg: string;
|
|
126
|
+
reqId?: string;
|
|
127
|
+
}
|
|
128
|
+
/** 404, or 400 for `USER_LIMIT`, which alone carries `code` and `recovery`. The same body `POST /fiat/quote` sends. */
|
|
129
|
+
export type RoutingNoRouteErrorBody = ErrorBodyFields & {
|
|
130
|
+
errorCode: 'FiatNoRouteError';
|
|
131
|
+
serviceableRanges: RoutingServiceableRange[];
|
|
132
|
+
retryable: boolean;
|
|
133
|
+
} & ({
|
|
134
|
+
reason: Exclude<RoutingNoRouteReason, 'USER_LIMIT'>;
|
|
135
|
+
} | {
|
|
136
|
+
reason: 'USER_LIMIT';
|
|
137
|
+
code: 'LIMITS_EXCEEDED';
|
|
138
|
+
recovery: 'REQUOTE';
|
|
139
|
+
});
|
|
140
|
+
/** 400: the amount is outside the named provider's bounds. */
|
|
141
|
+
export type RoutingAmountErrorBody = ErrorBodyFields & {
|
|
142
|
+
fiatCurrencyCode: FiatCurrencyCode;
|
|
143
|
+
} & ({
|
|
144
|
+
errorCode: 'FiatAmountBelowMinimumError';
|
|
145
|
+
minFiatAmount: string;
|
|
146
|
+
} | {
|
|
147
|
+
errorCode: 'FiatAmountAboveMaximumError';
|
|
148
|
+
maxFiatAmount: string;
|
|
149
|
+
});
|
|
150
|
+
/** 429: the per-login budget is spent. Retry after `retryAfterSeconds`. */
|
|
151
|
+
export type RoutingRateLimitedErrorBody = ErrorBodyFields & {
|
|
152
|
+
errorCode: 'TooManyRequestsError';
|
|
153
|
+
retryAfterSeconds?: number;
|
|
154
|
+
};
|
|
155
|
+
/** Any other fault: a bad request (400), a missing assertion (401) or a server error (5xx). `errorCode` is the error's name. */
|
|
156
|
+
export type RoutingFaultErrorBody = ErrorBodyFields & {
|
|
157
|
+
errorCode: string;
|
|
158
|
+
};
|
|
159
|
+
/** `GET /fiat/routing/table` refusals. */
|
|
160
|
+
export type FiatRoutingTableErrorBody = RoutingRateLimitedErrorBody | RoutingFaultErrorBody;
|
|
161
|
+
/**
|
|
162
|
+
* `POST /fiat/routing/quote` refusals. A `FiatNoRouteError` (any `reason`) or either amount error is
|
|
163
|
+
* the named provider's alone: quote the interval's next provider. Anything else stops the fall-through:
|
|
164
|
+
* a validation or auth refusal, a 5xx, or no provider left to try.
|
|
165
|
+
*/
|
|
166
|
+
export type FiatRoutingQuoteErrorBody = RoutingNoRouteErrorBody | RoutingAmountErrorBody | RoutingFaultErrorBody;
|
|
167
|
+
export {};
|
|
168
|
+
//# sourceMappingURL=routing.d.ts.map
|
package/dist/routing.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/routing.ts
|
|
21
|
+
var routing_exports = {};
|
|
22
|
+
__export(routing_exports, {
|
|
23
|
+
ROUTING_ENDPOINTS: () => ROUTING_ENDPOINTS
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(routing_exports);
|
|
26
|
+
var ROUTING_ENDPOINTS = {
|
|
27
|
+
table: "GET /fiat/routing/table",
|
|
28
|
+
/** Temporary: `POST /fiat/next` replaces it for each provider that moves there. */
|
|
29
|
+
quote: "POST /fiat/routing/quote"
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=routing.js.map
|
package/dist/routing.mjs
ADDED
package/dist/schemas.d.ts
CHANGED
|
@@ -28,8 +28,9 @@
|
|
|
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, KycFieldId, 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, FiatGeo, FiatNextRequest } from './types';
|
|
32
32
|
import type { FiatTermsErrorBody, FiatTermsRequest, FiatTermsResponse, TermsDocument, TermsDocumentAcceptance } from './terms';
|
|
33
|
+
import type { FiatRoutingQuoteErrorBody, FiatRoutingQuoteRequest, FiatRoutingTableErrorBody, FiatRoutingTableQuery, FiatRoutingTableResponse } from './routing';
|
|
33
34
|
export declare const JsonSchema: z.ZodType<JsonValue>;
|
|
34
35
|
export declare const HTTP_VERBS: readonly ["GET", "POST"];
|
|
35
36
|
/** `"POST /fiat/session/verify"`, `"GET /fiat/orders/o_31c"` — the verb rides the string. */
|
|
@@ -111,6 +112,13 @@ export declare const TermsDocumentAcceptanceSchema: z.ZodType<TermsDocumentAccep
|
|
|
111
112
|
export declare const FiatTermsRequestSchema: z.ZodType<FiatTermsRequest>;
|
|
112
113
|
export declare const FiatTermsResponseSchema: z.ZodType<FiatTermsResponse>;
|
|
113
114
|
export declare const FiatTermsErrorBodySchema: z.ZodType<FiatTermsErrorBody>;
|
|
115
|
+
export declare const FiatRoutingTableQuerySchema: z.ZodType<FiatRoutingTableQuery>;
|
|
116
|
+
export declare const FiatRoutingTableResponseSchema: z.ZodType<FiatRoutingTableResponse>;
|
|
117
|
+
export declare const FiatRoutingQuoteRequestSchema: z.ZodType<FiatRoutingQuoteRequest>;
|
|
118
|
+
export declare const FiatRoutingTableErrorBodySchema: z.ZodType<FiatRoutingTableErrorBody>;
|
|
119
|
+
export declare const FiatRoutingQuoteErrorBodySchema: z.ZodType<FiatRoutingQuoteErrorBody>;
|
|
120
|
+
export declare const FiatGeoSchema: z.ZodType<FiatGeo>;
|
|
121
|
+
export declare const FiatNextRequestSchema: z.ZodType<FiatNextRequest>;
|
|
114
122
|
export declare const FiatStepResponseSchema: z.ZodType<FiatStepResponse>;
|
|
115
123
|
export {};
|
|
116
124
|
//# sourceMappingURL=schemas.d.ts.map
|
package/dist/table.js
CHANGED
package/dist/table.mjs
CHANGED
package/dist/terms.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The platform terms route: `POST /fiat/terms`, shared by every provider.
|
|
3
3
|
*
|
|
4
4
|
* A checkout shows the user documents to accept. `CHECKOUT` documents are the constants below;
|
|
5
|
-
* `KYC` documents arrive in a provider flow's
|
|
5
|
+
* `KYC` documents arrive in a provider flow's consent prompt. The user's Continue tap is the
|
|
6
6
|
* acceptance, and the client records it here before the next provider call. A repeat writes nothing.
|
|
7
7
|
*
|
|
8
8
|
* Zero runtime dependencies, so production React Native code can import it. The zod schemas are
|
|
@@ -39,7 +39,7 @@ export interface FiatTermsRequest {
|
|
|
39
39
|
/** One per document the screen showed, each document at most once. */
|
|
40
40
|
acceptances: TermsDocumentAcceptance[];
|
|
41
41
|
}
|
|
42
|
-
/** The recorded document ids. The client then calls
|
|
42
|
+
/** The recorded document ids. The client then calls `POST /fiat/next`. */
|
|
43
43
|
export interface FiatTermsResponse {
|
|
44
44
|
recorded: string[];
|
|
45
45
|
}
|