@pollar/react 0.11.4-rc.2 → 0.11.4
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 +9 -1
- package/dist/index.css +193 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +39 -5
- package/dist/index.d.ts +39 -5
- package/dist/index.js +1085 -44
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1085 -45
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1038,7 +1038,7 @@ var PollarModalFooter = ({ shield = false }) => {
|
|
|
1038
1038
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-footer-name", children: "Pollar" }),
|
|
1039
1039
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-footer-version", children: [
|
|
1040
1040
|
"v",
|
|
1041
|
-
"0.11.4
|
|
1041
|
+
"0.11.4"
|
|
1042
1042
|
] })
|
|
1043
1043
|
] })
|
|
1044
1044
|
] });
|
|
@@ -2079,7 +2079,8 @@ function KycModalTemplate({
|
|
|
2079
2079
|
kycStatus !== "approved" && kycStatus !== "rejected" && kycStatus !== "expired" && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onDoneVerifying, children: "Check again" }),
|
|
2080
2080
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", onClick: onClose, children: "Close" })
|
|
2081
2081
|
] })
|
|
2082
|
-
] })
|
|
2082
|
+
] }),
|
|
2083
|
+
/* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
|
|
2083
2084
|
]
|
|
2084
2085
|
}
|
|
2085
2086
|
);
|
|
@@ -2089,7 +2090,15 @@ function newIdempotencyKey() {
|
|
|
2089
2090
|
if (c && typeof c.randomUUID === "function") return c.randomUUID();
|
|
2090
2091
|
return `kyc-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;
|
|
2091
2092
|
}
|
|
2092
|
-
function KycModal({
|
|
2093
|
+
function KycModal({
|
|
2094
|
+
onClose,
|
|
2095
|
+
country = "MX",
|
|
2096
|
+
level = "basic",
|
|
2097
|
+
onApproved,
|
|
2098
|
+
corridorId,
|
|
2099
|
+
cardProviderId,
|
|
2100
|
+
providerId
|
|
2101
|
+
}) {
|
|
2093
2102
|
const { getClient, styles } = usePollar();
|
|
2094
2103
|
const [step, setStep] = react.useState("select_provider");
|
|
2095
2104
|
const [providers, setProviders] = react.useState([]);
|
|
@@ -2117,7 +2126,7 @@ function KycModal({ onClose, country = "MX", level = "basic", onApproved, corrid
|
|
|
2117
2126
|
else finish(read.decisionStatus === "expired" ? "expired" : read.status);
|
|
2118
2127
|
}
|
|
2119
2128
|
function readStatus(providerId2) {
|
|
2120
|
-
return corridorId ? client.getKycStatus(void 0, corridorId) : client.getKycStatus(providerId2);
|
|
2129
|
+
return corridorId || cardProviderId ? client.getKycStatus(void 0, corridorId, cardProviderId) : client.getKycStatus(providerId2);
|
|
2121
2130
|
}
|
|
2122
2131
|
const starting = react.useRef(false);
|
|
2123
2132
|
async function handleSelectProvider(provider, listed = true) {
|
|
@@ -2134,7 +2143,8 @@ function KycModal({ onClose, country = "MX", level = "basic", onApproved, corrid
|
|
|
2134
2143
|
provider.levels?.[0] ?? level,
|
|
2135
2144
|
listed ? country : void 0,
|
|
2136
2145
|
corridorId,
|
|
2137
|
-
key
|
|
2146
|
+
key,
|
|
2147
|
+
cardProviderId
|
|
2138
2148
|
);
|
|
2139
2149
|
if (result.alreadyApproved) {
|
|
2140
2150
|
finish("approved");
|
|
@@ -2163,7 +2173,7 @@ function KycModal({ onClose, country = "MX", level = "basic", onApproved, corrid
|
|
|
2163
2173
|
const loadProviders = react.useCallback(() => {
|
|
2164
2174
|
setIsLoading(true);
|
|
2165
2175
|
setError(null);
|
|
2166
|
-
return getClient().getKycProviders(country, corridorId).then((result) => {
|
|
2176
|
+
return getClient().getKycProviders(country, corridorId, cardProviderId).then((result) => {
|
|
2167
2177
|
setProviders(result.providers);
|
|
2168
2178
|
return result.providers;
|
|
2169
2179
|
}).catch((e) => {
|
|
@@ -2171,7 +2181,7 @@ function KycModal({ onClose, country = "MX", level = "basic", onApproved, corrid
|
|
|
2171
2181
|
setError(kycErrorMessage(e, "load"));
|
|
2172
2182
|
return [];
|
|
2173
2183
|
}).finally(() => setIsLoading(false));
|
|
2174
|
-
}, [getClient, country, corridorId]);
|
|
2184
|
+
}, [getClient, country, corridorId, cardProviderId]);
|
|
2175
2185
|
react.useEffect(() => {
|
|
2176
2186
|
void loadProviders().then((list) => {
|
|
2177
2187
|
if (!providerId || autoOpened.current) return;
|
|
@@ -2193,7 +2203,8 @@ function KycModal({ onClose, country = "MX", level = "basic", onApproved, corrid
|
|
|
2193
2203
|
const read = await client.pollKycDecision(selectedProvider.id, {
|
|
2194
2204
|
intervalMs: 3e3,
|
|
2195
2205
|
timeoutMs: 12e4,
|
|
2196
|
-
...corridorId ? { corridorId } : {}
|
|
2206
|
+
...corridorId ? { corridorId } : {},
|
|
2207
|
+
...cardProviderId ? { cardProviderId } : {}
|
|
2197
2208
|
});
|
|
2198
2209
|
finishWith(read);
|
|
2199
2210
|
} catch {
|
|
@@ -2253,15 +2264,35 @@ function initialValues(fields, answers) {
|
|
|
2253
2264
|
return values;
|
|
2254
2265
|
}
|
|
2255
2266
|
var DATE = /^\d{4}-\d{2}-\d{2}$/;
|
|
2267
|
+
function localFieldError(field, value) {
|
|
2268
|
+
if (typeof value !== "string" || !value.trim()) return null;
|
|
2269
|
+
const text = value.trim();
|
|
2270
|
+
const rules = field.validation ?? {};
|
|
2271
|
+
if (field.type === "number") {
|
|
2272
|
+
const number = Number(text);
|
|
2273
|
+
if (!Number.isFinite(number)) return "invalid_type";
|
|
2274
|
+
if (rules.min !== void 0 && number < rules.min) return "too_small";
|
|
2275
|
+
if (rules.max !== void 0 && number > rules.max) return "too_large";
|
|
2276
|
+
return null;
|
|
2277
|
+
}
|
|
2278
|
+
if (field.type === "date") {
|
|
2279
|
+
return DATE.test(text) && !Number.isNaN(Date.parse(`${text}T00:00:00Z`)) ? null : "invalid_format";
|
|
2280
|
+
}
|
|
2281
|
+
if (field.type === "select" || field.type === "multiselect" || field.type === "checkbox") return null;
|
|
2282
|
+
if (rules.maxLength !== void 0 && text.length > rules.maxLength) return "too_long";
|
|
2283
|
+
if (rules.pattern) {
|
|
2284
|
+
try {
|
|
2285
|
+
if (!new RegExp(rules.pattern).test(text)) return "pattern";
|
|
2286
|
+
} catch {
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
return null;
|
|
2290
|
+
}
|
|
2256
2291
|
function localFieldErrors(fields, values) {
|
|
2257
2292
|
const errors = {};
|
|
2258
2293
|
for (const field of fields) {
|
|
2259
|
-
const
|
|
2260
|
-
if (
|
|
2261
|
-
if (field.type === "number" && !Number.isFinite(Number(value))) errors[field.key] = "invalid_type";
|
|
2262
|
-
if (field.type === "date" && (!DATE.test(value.trim()) || Number.isNaN(Date.parse(`${value.trim()}T00:00:00Z`)))) {
|
|
2263
|
-
errors[field.key] = "invalid_format";
|
|
2264
|
-
}
|
|
2294
|
+
const error = localFieldError(field, values[field.key]);
|
|
2295
|
+
if (error) errors[field.key] = error;
|
|
2265
2296
|
}
|
|
2266
2297
|
return errors;
|
|
2267
2298
|
}
|
|
@@ -2341,7 +2372,8 @@ function FieldInput({
|
|
|
2341
2372
|
value,
|
|
2342
2373
|
language,
|
|
2343
2374
|
disabled,
|
|
2344
|
-
onChange
|
|
2375
|
+
onChange,
|
|
2376
|
+
onBlur
|
|
2345
2377
|
}) {
|
|
2346
2378
|
const id = `pollar-form-${field.key}`;
|
|
2347
2379
|
const text = typeof value === "string" ? value : "";
|
|
@@ -2375,7 +2407,8 @@ function FieldInput({
|
|
|
2375
2407
|
value: text,
|
|
2376
2408
|
disabled,
|
|
2377
2409
|
maxLength: field.validation?.maxLength,
|
|
2378
|
-
onChange: (e) => onChange(e.target.value)
|
|
2410
|
+
onChange: (e) => onChange(e.target.value),
|
|
2411
|
+
onBlur
|
|
2379
2412
|
}
|
|
2380
2413
|
);
|
|
2381
2414
|
default:
|
|
@@ -2391,7 +2424,8 @@ function FieldInput({
|
|
|
2391
2424
|
min: field.validation?.min,
|
|
2392
2425
|
max: field.validation?.max,
|
|
2393
2426
|
maxLength: field.validation?.maxLength,
|
|
2394
|
-
onChange: (e) => onChange(e.target.value)
|
|
2427
|
+
onChange: (e) => onChange(e.target.value),
|
|
2428
|
+
onBlur
|
|
2395
2429
|
}
|
|
2396
2430
|
);
|
|
2397
2431
|
}
|
|
@@ -2422,6 +2456,24 @@ function RequirementFormModal({ formId, progress, onClose, onSubmitted }) {
|
|
|
2422
2456
|
setValues(initialValues(loaded.fields, loaded.answers));
|
|
2423
2457
|
}).catch(() => mounted.current && setError(copy.loadError));
|
|
2424
2458
|
}, [formId]);
|
|
2459
|
+
function recheck(field, value, onlyIfShown) {
|
|
2460
|
+
if (typeof value === "string" && !value.trim()) return;
|
|
2461
|
+
setFieldErrors((errors) => {
|
|
2462
|
+
if (onlyIfShown && !(field.key in errors)) return errors;
|
|
2463
|
+
const next = { ...errors };
|
|
2464
|
+
const error2 = localFieldError(field, value);
|
|
2465
|
+
if (error2) next[field.key] = error2;
|
|
2466
|
+
else delete next[field.key];
|
|
2467
|
+
return next;
|
|
2468
|
+
});
|
|
2469
|
+
}
|
|
2470
|
+
function change(field, value) {
|
|
2471
|
+
setValues((v) => ({ ...v, [field.key]: value }));
|
|
2472
|
+
recheck(field, value, true);
|
|
2473
|
+
}
|
|
2474
|
+
function blur(field) {
|
|
2475
|
+
recheck(field, values[field.key], false);
|
|
2476
|
+
}
|
|
2425
2477
|
async function submit() {
|
|
2426
2478
|
if (!form) return;
|
|
2427
2479
|
setError(null);
|
|
@@ -2501,7 +2553,8 @@ function RequirementFormModal({ formId, progress, onClose, onSubmitted }) {
|
|
|
2501
2553
|
value: values[field.key] ?? "",
|
|
2502
2554
|
language,
|
|
2503
2555
|
disabled: submitting,
|
|
2504
|
-
onChange: (value) =>
|
|
2556
|
+
onChange: (value) => change(field, value),
|
|
2557
|
+
onBlur: () => blur(field)
|
|
2505
2558
|
}
|
|
2506
2559
|
)
|
|
2507
2560
|
] }),
|
|
@@ -2515,7 +2568,8 @@ function RequirementFormModal({ formId, progress, onClose, onSubmitted }) {
|
|
|
2515
2568
|
] })
|
|
2516
2569
|
]
|
|
2517
2570
|
}
|
|
2518
|
-
)
|
|
2571
|
+
),
|
|
2572
|
+
/* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
|
|
2519
2573
|
]
|
|
2520
2574
|
}
|
|
2521
2575
|
) });
|
|
@@ -3892,7 +3946,8 @@ function RampWidgetTemplate({
|
|
|
3892
3946
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: "Close" }),
|
|
3893
3947
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", onClick: onRetry, children: "Try again" })
|
|
3894
3948
|
] })
|
|
3895
|
-
] })
|
|
3949
|
+
] }),
|
|
3950
|
+
/* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
|
|
3896
3951
|
] });
|
|
3897
3952
|
}
|
|
3898
3953
|
|
|
@@ -3953,9 +4008,16 @@ var REGISTRATION_COPY = {
|
|
|
3953
4008
|
close: "Close",
|
|
3954
4009
|
notReady: "Complete the previous steps first.",
|
|
3955
4010
|
missing: "Some details are missing: {fields}.",
|
|
4011
|
+
invalid: "Some details need to be corrected: {fields}.",
|
|
4012
|
+
fix: "Review my details",
|
|
4013
|
+
incomplete: "Your registration with the provider did not finish. Register again to complete it.",
|
|
4014
|
+
providerDown: "The provider is not responding right now. Please try again in a few minutes.",
|
|
4015
|
+
ipNotSupported: "The provider cannot accept your current connection (IPv6). Please try again from another network, for example Wi-Fi.",
|
|
4016
|
+
emailTaken: "This email is already registered with the provider through another app. Use a different email to register here.",
|
|
3956
4017
|
loadError: "Could not load the registration. Please try again.",
|
|
3957
4018
|
submitError: "Could not register you. Please try again.",
|
|
3958
|
-
step: "Step {n} of {total}"
|
|
4019
|
+
step: "Step {n} of {total}",
|
|
4020
|
+
terms: "Read the provider's terms of service"
|
|
3959
4021
|
},
|
|
3960
4022
|
es: {
|
|
3961
4023
|
title: "Registro con el proveedor de pagos",
|
|
@@ -3966,9 +4028,16 @@ var REGISTRATION_COPY = {
|
|
|
3966
4028
|
close: "Cerrar",
|
|
3967
4029
|
notReady: "Primero completa los pasos anteriores.",
|
|
3968
4030
|
missing: "Faltan algunos datos: {fields}.",
|
|
4031
|
+
invalid: "Hay datos que corregir: {fields}.",
|
|
4032
|
+
fix: "Revisar mis datos",
|
|
4033
|
+
incomplete: "Tu registro con el proveedor no se complet\xF3. Reg\xEDstrate de nuevo para terminarlo.",
|
|
4034
|
+
providerDown: "El proveedor no responde en este momento. Intenta de nuevo en unos minutos.",
|
|
4035
|
+
ipNotSupported: "El proveedor no acepta tu conexi\xF3n actual (IPv6). Intenta desde otra red, por ejemplo Wi-Fi.",
|
|
4036
|
+
emailTaken: "Este email ya est\xE1 registrado con el proveedor desde otra app. Usa otro email para registrarte aqu\xED.",
|
|
3969
4037
|
loadError: "No se pudo cargar el registro. Intenta de nuevo.",
|
|
3970
4038
|
submitError: "No se pudo completar el registro. Intenta de nuevo.",
|
|
3971
|
-
step: "Paso {n} de {total}"
|
|
4039
|
+
step: "Paso {n} de {total}",
|
|
4040
|
+
terms: "Leer los t\xE9rminos de servicio del proveedor"
|
|
3972
4041
|
}
|
|
3973
4042
|
};
|
|
3974
4043
|
var SHARED_FIELD_LABELS = {
|
|
@@ -3983,7 +4052,24 @@ var SHARED_FIELD_LABELS = {
|
|
|
3983
4052
|
source_of_funds: "Source of funds",
|
|
3984
4053
|
destination_of_funds: "Use of funds",
|
|
3985
4054
|
income_level: "Income level",
|
|
3986
|
-
doc_provider_id: "SEGIP validation"
|
|
4055
|
+
doc_provider_id: "SEGIP validation",
|
|
4056
|
+
first_name: "First name",
|
|
4057
|
+
last_name: "Last name",
|
|
4058
|
+
email: "Email",
|
|
4059
|
+
birth_date: "Date of birth",
|
|
4060
|
+
document_country: "Document country",
|
|
4061
|
+
phone_country_code: "Phone country code",
|
|
4062
|
+
phone_number: "Phone number",
|
|
4063
|
+
occupation: "Occupation",
|
|
4064
|
+
annual_salary: "Annual income",
|
|
4065
|
+
account_purpose: "Purpose of the card",
|
|
4066
|
+
expected_monthly_volume: "Expected monthly spend",
|
|
4067
|
+
address_line1: "Street address",
|
|
4068
|
+
address_line2: "Address line 2",
|
|
4069
|
+
city: "City",
|
|
4070
|
+
region: "State or province",
|
|
4071
|
+
postal_code: "Postal code",
|
|
4072
|
+
country_code: "Country of residence"
|
|
3987
4073
|
},
|
|
3988
4074
|
es: {
|
|
3989
4075
|
name: "Nombres",
|
|
@@ -3996,7 +4082,24 @@ var SHARED_FIELD_LABELS = {
|
|
|
3996
4082
|
source_of_funds: "Origen de los fondos",
|
|
3997
4083
|
destination_of_funds: "Destino de los fondos",
|
|
3998
4084
|
income_level: "Nivel de ingresos",
|
|
3999
|
-
doc_provider_id: "Validaci\xF3n SEGIP"
|
|
4085
|
+
doc_provider_id: "Validaci\xF3n SEGIP",
|
|
4086
|
+
first_name: "Nombres",
|
|
4087
|
+
last_name: "Apellidos",
|
|
4088
|
+
email: "Correo electr\xF3nico",
|
|
4089
|
+
birth_date: "Fecha de nacimiento",
|
|
4090
|
+
document_country: "Pa\xEDs del documento",
|
|
4091
|
+
phone_country_code: "C\xF3digo de pa\xEDs del tel\xE9fono",
|
|
4092
|
+
phone_number: "Tel\xE9fono",
|
|
4093
|
+
occupation: "Ocupaci\xF3n",
|
|
4094
|
+
annual_salary: "Ingreso anual",
|
|
4095
|
+
account_purpose: "Uso de la tarjeta",
|
|
4096
|
+
expected_monthly_volume: "Gasto mensual esperado",
|
|
4097
|
+
address_line1: "Direcci\xF3n",
|
|
4098
|
+
address_line2: "Direcci\xF3n (l\xEDnea 2)",
|
|
4099
|
+
city: "Ciudad",
|
|
4100
|
+
region: "Estado o provincia",
|
|
4101
|
+
postal_code: "C\xF3digo postal",
|
|
4102
|
+
country_code: "Pa\xEDs de residencia"
|
|
4000
4103
|
}
|
|
4001
4104
|
};
|
|
4002
4105
|
var errorCode = (error) => error && typeof error === "object" && typeof error.code === "string" ? error.code : null;
|
|
@@ -4004,6 +4107,15 @@ function missingFieldsOf(error) {
|
|
|
4004
4107
|
const body = error && typeof error === "object" ? error.body : void 0;
|
|
4005
4108
|
return Array.isArray(body?.missing) ? body.missing.filter((item) => typeof item === "string") : [];
|
|
4006
4109
|
}
|
|
4110
|
+
function registrationFixOf(error) {
|
|
4111
|
+
const body = error && typeof error === "object" ? error.body : void 0;
|
|
4112
|
+
const strings = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
4113
|
+
const forms = Array.isArray(body?.forms) ? body.forms.flatMap((item) => {
|
|
4114
|
+
const form = item && typeof item === "object" ? item : {};
|
|
4115
|
+
return typeof form.formId === "string" ? [{ formId: form.formId, keys: strings(form.keys) }] : [];
|
|
4116
|
+
}) : [];
|
|
4117
|
+
return { invalid: strings(body?.invalid), forms };
|
|
4118
|
+
}
|
|
4007
4119
|
function RegistryCheckModal({ optionId, progress, onClose, onApproved }) {
|
|
4008
4120
|
const { getClient, styles } = usePollar();
|
|
4009
4121
|
const client = getClient();
|
|
@@ -4016,6 +4128,7 @@ function RegistryCheckModal({ optionId, progress, onClose, onApproved }) {
|
|
|
4016
4128
|
const [surname2, setSurname2] = react.useState("");
|
|
4017
4129
|
const [complement, setComplement] = react.useState("");
|
|
4018
4130
|
const [error, setError] = react.useState(null);
|
|
4131
|
+
const [rejected, setRejected] = react.useState([]);
|
|
4019
4132
|
const [review, setReview] = react.useState(false);
|
|
4020
4133
|
const [submitting, setSubmitting] = react.useState(false);
|
|
4021
4134
|
const mounted = react.useRef(true);
|
|
@@ -4031,7 +4144,7 @@ function RegistryCheckModal({ optionId, progress, onClose, onApproved }) {
|
|
|
4031
4144
|
if (loaded.status === "approved") return onApproved();
|
|
4032
4145
|
setCheck(loaded);
|
|
4033
4146
|
if (loaded.status === "pending") setReview(true);
|
|
4034
|
-
if (loaded.status === "rejected")
|
|
4147
|
+
if (loaded.status === "rejected") showRejected(loaded.rejectedFields);
|
|
4035
4148
|
if (loaded.prefill.applies) {
|
|
4036
4149
|
setSurname1(loaded.prefill.surname1);
|
|
4037
4150
|
setSurname2(loaded.prefill.surname2 ?? "");
|
|
@@ -4043,15 +4156,21 @@ function RegistryCheckModal({ optionId, progress, onClose, onApproved }) {
|
|
|
4043
4156
|
});
|
|
4044
4157
|
}, [optionId]);
|
|
4045
4158
|
const prefill = check?.prefill.applies ? check.prefill : null;
|
|
4046
|
-
function
|
|
4047
|
-
const labels = {
|
|
4048
|
-
|
|
4049
|
-
|
|
4159
|
+
function showRejected(fields) {
|
|
4160
|
+
const labels = {
|
|
4161
|
+
surname1: copy.surname1,
|
|
4162
|
+
surname2: copy.surname2,
|
|
4163
|
+
complementNumber: copy.complement
|
|
4164
|
+
};
|
|
4165
|
+
const named = fields?.length ? fields : ["surname2"];
|
|
4166
|
+
setRejected(named);
|
|
4167
|
+
setError(copy.rejected.replace("{fields}", named.map((field) => labels[field] ?? field).join(", ")));
|
|
4050
4168
|
}
|
|
4051
4169
|
async function submit() {
|
|
4052
4170
|
if (!prefill) return;
|
|
4053
4171
|
setSubmitting(true);
|
|
4054
4172
|
setError(null);
|
|
4173
|
+
setRejected([]);
|
|
4055
4174
|
try {
|
|
4056
4175
|
const result = await client.submitRegistryCheck(optionId, {
|
|
4057
4176
|
surname1: surname1.trim(),
|
|
@@ -4060,7 +4179,7 @@ function RegistryCheckModal({ optionId, progress, onClose, onApproved }) {
|
|
|
4060
4179
|
});
|
|
4061
4180
|
if (!mounted.current) return;
|
|
4062
4181
|
if (result.status === "approved") onApproved();
|
|
4063
|
-
else if (result.status === "rejected")
|
|
4182
|
+
else if (result.status === "rejected") showRejected(result.rejectedFields);
|
|
4064
4183
|
else setReview(true);
|
|
4065
4184
|
} catch (e) {
|
|
4066
4185
|
if (!mounted.current) return;
|
|
@@ -4125,6 +4244,7 @@ function RegistryCheckModal({ optionId, progress, onClose, onApproved }) {
|
|
|
4125
4244
|
value: surname1,
|
|
4126
4245
|
required: true,
|
|
4127
4246
|
disabled: submitting,
|
|
4247
|
+
"aria-invalid": rejected.includes("surname1") || void 0,
|
|
4128
4248
|
onChange: (e) => setSurname1(e.target.value)
|
|
4129
4249
|
}
|
|
4130
4250
|
)
|
|
@@ -4138,6 +4258,7 @@ function RegistryCheckModal({ optionId, progress, onClose, onApproved }) {
|
|
|
4138
4258
|
className: "pollar-input",
|
|
4139
4259
|
value: surname2,
|
|
4140
4260
|
disabled: submitting,
|
|
4261
|
+
"aria-invalid": rejected.includes("surname2") || void 0,
|
|
4141
4262
|
onChange: (e) => setSurname2(e.target.value)
|
|
4142
4263
|
}
|
|
4143
4264
|
)
|
|
@@ -4154,6 +4275,7 @@ function RegistryCheckModal({ optionId, progress, onClose, onApproved }) {
|
|
|
4154
4275
|
value: complement,
|
|
4155
4276
|
maxLength: 3,
|
|
4156
4277
|
disabled: submitting,
|
|
4278
|
+
"aria-invalid": rejected.includes("complementNumber") || void 0,
|
|
4157
4279
|
onChange: (e) => setComplement(e.target.value.toUpperCase().replace(/[^0-9A-Z]/g, ""))
|
|
4158
4280
|
}
|
|
4159
4281
|
)
|
|
@@ -4164,12 +4286,19 @@ function RegistryCheckModal({ optionId, progress, onClose, onApproved }) {
|
|
|
4164
4286
|
] })
|
|
4165
4287
|
]
|
|
4166
4288
|
}
|
|
4167
|
-
)
|
|
4289
|
+
),
|
|
4290
|
+
/* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
|
|
4168
4291
|
]
|
|
4169
4292
|
}
|
|
4170
4293
|
) });
|
|
4171
4294
|
}
|
|
4172
|
-
function ProviderRegistrationModal({
|
|
4295
|
+
function ProviderRegistrationModal({
|
|
4296
|
+
corridorId,
|
|
4297
|
+
cardProviderId,
|
|
4298
|
+
progress,
|
|
4299
|
+
onClose,
|
|
4300
|
+
onRegistered
|
|
4301
|
+
}) {
|
|
4173
4302
|
const { getClient, styles } = usePollar();
|
|
4174
4303
|
const client = getClient();
|
|
4175
4304
|
const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
|
|
@@ -4178,9 +4307,12 @@ function ProviderRegistrationModal({ corridorId, progress, onClose, onRegistered
|
|
|
4178
4307
|
const copy = REGISTRATION_COPY[language];
|
|
4179
4308
|
const labels = SHARED_FIELD_LABELS[language];
|
|
4180
4309
|
const [registration, setRegistration] = react.useState(null);
|
|
4310
|
+
const [termsUrl, setTermsUrl] = react.useState(null);
|
|
4181
4311
|
const [consent, setConsent] = react.useState(false);
|
|
4182
4312
|
const [error, setError] = react.useState(null);
|
|
4183
4313
|
const [submitting, setSubmitting] = react.useState(false);
|
|
4314
|
+
const [fixForm, setFixForm] = react.useState(null);
|
|
4315
|
+
const [fixing, setFixing] = react.useState(null);
|
|
4184
4316
|
const mounted = react.useRef(true);
|
|
4185
4317
|
react.useEffect(() => {
|
|
4186
4318
|
mounted.current = true;
|
|
@@ -4189,34 +4321,60 @@ function ProviderRegistrationModal({ corridorId, progress, onClose, onRegistered
|
|
|
4189
4321
|
};
|
|
4190
4322
|
}, []);
|
|
4191
4323
|
react.useEffect(() => {
|
|
4192
|
-
client.
|
|
4324
|
+
const load = cardProviderId ? client.getCardProviderRegistration(cardProviderId).then((loaded) => {
|
|
4325
|
+
setTermsUrl(loaded.termsUrl);
|
|
4326
|
+
return loaded;
|
|
4327
|
+
}) : client.getProviderRegistration(corridorId ?? "");
|
|
4328
|
+
load.then((loaded) => {
|
|
4193
4329
|
if (!mounted.current) return;
|
|
4194
4330
|
if (loaded.status === "registered") onRegistered();
|
|
4195
4331
|
else setRegistration(loaded);
|
|
4196
4332
|
}).catch(() => mounted.current && setError(copy.loadError));
|
|
4197
|
-
}, [corridorId]);
|
|
4333
|
+
}, [corridorId, cardProviderId]);
|
|
4198
4334
|
async function submit() {
|
|
4199
4335
|
setSubmitting(true);
|
|
4200
4336
|
setError(null);
|
|
4337
|
+
setFixForm(null);
|
|
4201
4338
|
try {
|
|
4202
|
-
await client.
|
|
4339
|
+
if (cardProviderId) await client.submitCardProviderRegistration(cardProviderId);
|
|
4340
|
+
else await client.submitProviderRegistration(corridorId ?? "");
|
|
4203
4341
|
if (mounted.current) onRegistered();
|
|
4204
4342
|
} catch (e) {
|
|
4205
4343
|
if (!mounted.current) return;
|
|
4206
4344
|
const code = errorCode(e);
|
|
4207
4345
|
if (code === "KYC_REGISTRATION_MISSING_DATA") {
|
|
4346
|
+
const fix = registrationFixOf(e);
|
|
4347
|
+
const named = (keys) => keys.map((key) => labels[key] ?? key).join(", ");
|
|
4348
|
+
const missing = missingFieldsOf(e).filter((key) => !fix.invalid.includes(key));
|
|
4208
4349
|
setError(
|
|
4209
|
-
|
|
4210
|
-
"{fields}",
|
|
4211
|
-
|
|
4212
|
-
)
|
|
4350
|
+
[
|
|
4351
|
+
fix.invalid.length ? copy.invalid.replace("{fields}", named(fix.invalid)) : null,
|
|
4352
|
+
missing.length ? copy.missing.replace("{fields}", named(missing)) : null
|
|
4353
|
+
].filter(Boolean).join(" ")
|
|
4213
4354
|
);
|
|
4355
|
+
setFixForm(fix.forms[0]?.formId ?? null);
|
|
4214
4356
|
} else if (code === "KYC_REGISTRATION_STEPS_PENDING") setError(copy.notReady);
|
|
4357
|
+
else if (code === "SDK_CARDS_PROVIDER_ERROR") setError(copy.providerDown);
|
|
4358
|
+
else if (code === "SDK_CARDS_IP_NOT_SUPPORTED") setError(copy.ipNotSupported);
|
|
4359
|
+
else if (code === "SDK_CARDS_PROVIDER_USER_TAKEN") setError(copy.emailTaken);
|
|
4215
4360
|
else setError(copy.submitError);
|
|
4216
4361
|
} finally {
|
|
4217
4362
|
if (mounted.current) setSubmitting(false);
|
|
4218
4363
|
}
|
|
4219
4364
|
}
|
|
4365
|
+
if (fixing) {
|
|
4366
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4367
|
+
RequirementFormModal,
|
|
4368
|
+
{
|
|
4369
|
+
formId: fixing,
|
|
4370
|
+
onClose: () => setFixing(null),
|
|
4371
|
+
onSubmitted: () => {
|
|
4372
|
+
setFixing(null);
|
|
4373
|
+
void submit();
|
|
4374
|
+
}
|
|
4375
|
+
}
|
|
4376
|
+
);
|
|
4377
|
+
}
|
|
4220
4378
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4221
4379
|
"div",
|
|
4222
4380
|
{
|
|
@@ -4235,6 +4393,7 @@ function ProviderRegistrationModal({ corridorId, progress, onClose, onRegistered
|
|
|
4235
4393
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": copy.close, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
|
|
4236
4394
|
] }),
|
|
4237
4395
|
error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-form-error", role: "alert", children: error }),
|
|
4396
|
+
fixForm && !submitting && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", onClick: () => setFixing(fixForm), children: copy.fix }) }),
|
|
4238
4397
|
!registration && !error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-loading-block", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-spinner" }) }),
|
|
4239
4398
|
registration && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4240
4399
|
"form",
|
|
@@ -4246,8 +4405,10 @@ function ProviderRegistrationModal({ corridorId, progress, onClose, onRegistered
|
|
|
4246
4405
|
},
|
|
4247
4406
|
children: [
|
|
4248
4407
|
registration.ready ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4408
|
+
registration.status === "incomplete" && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-form-error", role: "status", children: copy.incomplete }),
|
|
4249
4409
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-form-description", children: copy.intro }),
|
|
4250
4410
|
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "pollar-form-description", children: registration.fields.map((key) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: labels[key] ?? key }, key)) }),
|
|
4411
|
+
termsUrl && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-form-description", children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: termsUrl, target: "_blank", rel: "noreferrer", children: copy.terms }) }),
|
|
4251
4412
|
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "pollar-form-choice", children: [
|
|
4252
4413
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4253
4414
|
"input",
|
|
@@ -4267,7 +4428,8 @@ function ProviderRegistrationModal({ corridorId, progress, onClose, onRegistered
|
|
|
4267
4428
|
] })
|
|
4268
4429
|
]
|
|
4269
4430
|
}
|
|
4270
|
-
)
|
|
4431
|
+
),
|
|
4432
|
+
/* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
|
|
4271
4433
|
]
|
|
4272
4434
|
}
|
|
4273
4435
|
) });
|
|
@@ -6778,6 +6940,782 @@ function EarnModal({ onClose }) {
|
|
|
6778
6940
|
}
|
|
6779
6941
|
) });
|
|
6780
6942
|
}
|
|
6943
|
+
|
|
6944
|
+
// src/components/card-modal/card-kyc.ts
|
|
6945
|
+
var nonEmpty2 = (value) => typeof value === "string" && !!value.trim();
|
|
6946
|
+
function requiredCardStep(error) {
|
|
6947
|
+
if (!error || typeof error !== "object") return null;
|
|
6948
|
+
const { code, body } = error;
|
|
6949
|
+
if (code !== "SDK_CARDS_REQUIREMENT_REQUIRED" || !body || typeof body !== "object") return null;
|
|
6950
|
+
const { cardProviderId, requirementType, optionId } = body;
|
|
6951
|
+
if (!nonEmpty2(cardProviderId) || !nonEmpty2(optionId)) return null;
|
|
6952
|
+
if (requirementType === "KYC" || requirementType === "FORM" || requirementType === "REGISTRY_CHECK" || requirementType === "PROVIDER_REGISTRATION") {
|
|
6953
|
+
return { cardProviderId, type: requirementType, optionId };
|
|
6954
|
+
}
|
|
6955
|
+
return null;
|
|
6956
|
+
}
|
|
6957
|
+
function pendingFromRequirement(cardProviderId, next) {
|
|
6958
|
+
return {
|
|
6959
|
+
cardProviderId,
|
|
6960
|
+
type: next.type,
|
|
6961
|
+
optionId: next.optionId,
|
|
6962
|
+
progress: { position: next.completed + 1, total: next.total }
|
|
6963
|
+
};
|
|
6964
|
+
}
|
|
6965
|
+
function blockedStepMessage(next) {
|
|
6966
|
+
if (next.type === "REGISTRY_CHECK" && next.status === "pending") return "Your details are under review.";
|
|
6967
|
+
if (next.type !== "KYC") return null;
|
|
6968
|
+
if (next.status === "pending" && next.reviewReason) return "Your verification is under review.";
|
|
6969
|
+
if (next.status === "rejected") return "Your verification was not approved.";
|
|
6970
|
+
return null;
|
|
6971
|
+
}
|
|
6972
|
+
function cardStage(holder, requirements) {
|
|
6973
|
+
if (holder === void 0 || requirements === void 0) return null;
|
|
6974
|
+
if (holder === null || holder.kycStatus === "NOT_STARTED" && requirements?.next) return "steps";
|
|
6975
|
+
if (holder.kycStatus !== "NOT_STARTED") return null;
|
|
6976
|
+
return requirements?.steps.some((step) => step.type === "PROVIDER_REGISTRATION") ? "steps" : "provider-form";
|
|
6977
|
+
}
|
|
6978
|
+
var KYC_POLL_MS = 5e3;
|
|
6979
|
+
var REVEAL_MS = 3e4;
|
|
6980
|
+
var TX_LIMIT = 10;
|
|
6981
|
+
var FUNDING_POLL_MS = 5e3;
|
|
6982
|
+
var FUNDING_INFLIGHT = /* @__PURE__ */ new Set(["CREATED", "BURNED", "ATTESTED", "MINTED"]);
|
|
6983
|
+
var FUNDING_COPY = {
|
|
6984
|
+
CREATED: {
|
|
6985
|
+
title: "Confirming your payment",
|
|
6986
|
+
step: 1,
|
|
6987
|
+
hint: "Your USDC payment is being confirmed on Stellar. This takes a few seconds."
|
|
6988
|
+
},
|
|
6989
|
+
BURNED: {
|
|
6990
|
+
title: "Sending it to the card network",
|
|
6991
|
+
step: 2,
|
|
6992
|
+
hint: "Your USDC left Stellar. Circle is confirming the transfer, usually in about a minute."
|
|
6993
|
+
},
|
|
6994
|
+
ATTESTED: {
|
|
6995
|
+
title: "Crossing to the card network",
|
|
6996
|
+
step: 3,
|
|
6997
|
+
hint: "Transfer confirmed. Delivering the USDC to the card network."
|
|
6998
|
+
},
|
|
6999
|
+
MINTED: {
|
|
7000
|
+
title: "Arrived, crediting your card",
|
|
7001
|
+
step: 4,
|
|
7002
|
+
hint: "The USDC reached the card provider, which is adding it to your card. This can take a few minutes."
|
|
7003
|
+
},
|
|
7004
|
+
CREDITED: { title: "Credited to your card" },
|
|
7005
|
+
FAILED: { title: "Failed" }
|
|
7006
|
+
};
|
|
7007
|
+
var FUNDING_STEPS = 4;
|
|
7008
|
+
var INCOME_RANGES = [
|
|
7009
|
+
{ value: "0-1000", label: "Up to 1,000 USD" },
|
|
7010
|
+
{ value: "1000-5000", label: "1,000 to 5,000 USD" },
|
|
7011
|
+
{ value: "5000-10000", label: "5,000 to 10,000 USD" },
|
|
7012
|
+
{ value: "10000+", label: "More than 10,000 USD" }
|
|
7013
|
+
];
|
|
7014
|
+
var TX_LABELS = {
|
|
7015
|
+
deposit: "Deposit",
|
|
7016
|
+
transactionTransfer: "Bank deposit",
|
|
7017
|
+
spend: "Purchase",
|
|
7018
|
+
spend_adjustment: "Adjustment",
|
|
7019
|
+
fee: "Fee",
|
|
7020
|
+
fee_refund: "Fee refund",
|
|
7021
|
+
withdrawal: "Withdrawal",
|
|
7022
|
+
card_insurance: "Card issuance"
|
|
7023
|
+
};
|
|
7024
|
+
var KYC_PENDING_COPY = {
|
|
7025
|
+
PENDING: "Your information is being reviewed.",
|
|
7026
|
+
NEEDS_ACTION: "Finish verifying your identity with the card provider: you will be asked for a photo of your document and a selfie.",
|
|
7027
|
+
IN_REVIEW: "Your verification is under manual review. This can take a while."
|
|
7028
|
+
};
|
|
7029
|
+
var KYC_FINAL_COPY = {
|
|
7030
|
+
DENIED: "Your verification was denied.",
|
|
7031
|
+
LOCKED: "Your account is locked.",
|
|
7032
|
+
CANCELED: "Your verification was canceled."
|
|
7033
|
+
};
|
|
7034
|
+
var emptyKyc = {
|
|
7035
|
+
firstName: "",
|
|
7036
|
+
lastName: "",
|
|
7037
|
+
birthDate: "",
|
|
7038
|
+
nationalId: "",
|
|
7039
|
+
countryOfIssue: "",
|
|
7040
|
+
phoneCountryCode: "",
|
|
7041
|
+
phoneNumber: "",
|
|
7042
|
+
occupation: "",
|
|
7043
|
+
annualSalary: "1000-5000",
|
|
7044
|
+
accountPurpose: "Personal expenses",
|
|
7045
|
+
expectedMonthlyVolume: "1000-5000",
|
|
7046
|
+
address: { line1: "", line2: "", city: "", region: "", postalCode: "", countryCode: "" }
|
|
7047
|
+
};
|
|
7048
|
+
function usd(cents) {
|
|
7049
|
+
if (cents === null || cents === void 0) return "-";
|
|
7050
|
+
return (cents / 100).toLocaleString("en-US", { style: "currency", currency: "USD" });
|
|
7051
|
+
}
|
|
7052
|
+
function money(amount, currency) {
|
|
7053
|
+
const n = Number(amount);
|
|
7054
|
+
try {
|
|
7055
|
+
return n.toLocaleString("en-US", { style: "currency", currency });
|
|
7056
|
+
} catch {
|
|
7057
|
+
return `${n.toFixed(2)} ${currency}`;
|
|
7058
|
+
}
|
|
7059
|
+
}
|
|
7060
|
+
function groupPan(pan) {
|
|
7061
|
+
return pan.replace(/\s+/g, "").replace(/(.{4})/g, "$1 ").trim();
|
|
7062
|
+
}
|
|
7063
|
+
var CARD_ERROR_COPY = {
|
|
7064
|
+
SDK_CARDS_PROVIDER_ERROR: "The card provider is not responding right now. Please try again in a few minutes.",
|
|
7065
|
+
SDK_CARDS_IP_NOT_SUPPORTED: "The card provider cannot accept your current connection (IPv6). Please try again from another network, for example Wi-Fi.",
|
|
7066
|
+
SDK_CARDS_PROVIDER_USER_TAKEN: "This email is already registered with the card provider through another app. Use a different email to get a card here."
|
|
7067
|
+
};
|
|
7068
|
+
function errorText(e, fallback) {
|
|
7069
|
+
if (core.isPollarApiError(e)) {
|
|
7070
|
+
const known = CARD_ERROR_COPY[e.code];
|
|
7071
|
+
if (known) return known;
|
|
7072
|
+
const providerMessage = e.body.providerMessage;
|
|
7073
|
+
if (typeof providerMessage === "string" && providerMessage) return providerMessage;
|
|
7074
|
+
const message = e.body.message;
|
|
7075
|
+
if (typeof message === "string" && message) return message;
|
|
7076
|
+
return e.code;
|
|
7077
|
+
}
|
|
7078
|
+
return e instanceof Error && e.message ? e.message : fallback;
|
|
7079
|
+
}
|
|
7080
|
+
function CardModal({ onClose }) {
|
|
7081
|
+
const { getClient, styles, wallet } = usePollar();
|
|
7082
|
+
const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
|
|
7083
|
+
const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
|
|
7084
|
+
const [providers, setProviders] = react.useState(null);
|
|
7085
|
+
const [holder, setHolder] = react.useState(void 0);
|
|
7086
|
+
const [requirements, setRequirements] = react.useState(void 0);
|
|
7087
|
+
const [pendingStep, setPendingStep] = react.useState(null);
|
|
7088
|
+
const stepAttempt = react.useRef(null);
|
|
7089
|
+
const [cards, setCards] = react.useState(null);
|
|
7090
|
+
const [balance, setBalance] = react.useState(null);
|
|
7091
|
+
const [transactions, setTransactions] = react.useState(null);
|
|
7092
|
+
const [deposit, setDeposit] = react.useState(null);
|
|
7093
|
+
const [fundings, setFundings] = react.useState(null);
|
|
7094
|
+
const [fundAmount, setFundAmount] = react.useState("");
|
|
7095
|
+
const [showManual, setShowManual] = react.useState(false);
|
|
7096
|
+
const [occupations, setOccupations] = react.useState([]);
|
|
7097
|
+
const [kyc, setKyc] = react.useState(emptyKyc);
|
|
7098
|
+
const [terms, setTerms] = react.useState(false);
|
|
7099
|
+
const [nickname, setNickname] = react.useState("");
|
|
7100
|
+
const [secrets, setSecrets] = react.useState(null);
|
|
7101
|
+
const [panel, setPanel] = react.useState("card");
|
|
7102
|
+
const [busy, setBusy] = react.useState(null);
|
|
7103
|
+
const [error, setError] = react.useState("");
|
|
7104
|
+
const revealTimer = react.useRef(null);
|
|
7105
|
+
const provider = providers?.[0] ?? null;
|
|
7106
|
+
const card = cards?.[0] ?? null;
|
|
7107
|
+
const loadHolder = react.useCallback(async () => {
|
|
7108
|
+
const h = await getClient().getCardHolder();
|
|
7109
|
+
setHolder(h);
|
|
7110
|
+
return h;
|
|
7111
|
+
}, [getClient]);
|
|
7112
|
+
const loadRequirements = react.useCallback(
|
|
7113
|
+
async (cardProviderId) => {
|
|
7114
|
+
try {
|
|
7115
|
+
const r = await getClient().getCardRequirements({ cardProviderId });
|
|
7116
|
+
setRequirements(r);
|
|
7117
|
+
return r;
|
|
7118
|
+
} catch {
|
|
7119
|
+
setRequirements(null);
|
|
7120
|
+
return null;
|
|
7121
|
+
}
|
|
7122
|
+
},
|
|
7123
|
+
[getClient]
|
|
7124
|
+
);
|
|
7125
|
+
const loadCardData = react.useCallback(async () => {
|
|
7126
|
+
const client = getClient();
|
|
7127
|
+
const list = await client.getCards();
|
|
7128
|
+
if (list.length === 0) {
|
|
7129
|
+
setCards(list);
|
|
7130
|
+
return;
|
|
7131
|
+
}
|
|
7132
|
+
const [b, tx] = await Promise.all([client.getCardBalance(), client.getCardTransactions({ limit: TX_LIMIT })]);
|
|
7133
|
+
setBalance(b);
|
|
7134
|
+
setTransactions(tx.transactions);
|
|
7135
|
+
setCards(list);
|
|
7136
|
+
}, [getClient]);
|
|
7137
|
+
react.useEffect(() => {
|
|
7138
|
+
let cancelled = false;
|
|
7139
|
+
(async () => {
|
|
7140
|
+
try {
|
|
7141
|
+
const ps = await getClient().getCardProviders();
|
|
7142
|
+
if (cancelled) return;
|
|
7143
|
+
setProviders(ps);
|
|
7144
|
+
if (ps.length === 0) return;
|
|
7145
|
+
const [h] = await Promise.all([loadHolder(), loadRequirements(ps[0].id)]);
|
|
7146
|
+
if (cancelled) return;
|
|
7147
|
+
if (h?.kycStatus === "APPROVED") await loadCardData();
|
|
7148
|
+
} catch (e) {
|
|
7149
|
+
if (!cancelled) {
|
|
7150
|
+
setProviders((cur) => cur ?? []);
|
|
7151
|
+
setError(errorText(e, "Could not load your card"));
|
|
7152
|
+
}
|
|
7153
|
+
}
|
|
7154
|
+
})();
|
|
7155
|
+
return () => {
|
|
7156
|
+
cancelled = true;
|
|
7157
|
+
};
|
|
7158
|
+
}, [getClient, loadHolder, loadRequirements, loadCardData]);
|
|
7159
|
+
const stage = cardStage(holder, requirements);
|
|
7160
|
+
react.useEffect(() => {
|
|
7161
|
+
if (stage !== "provider-form") return;
|
|
7162
|
+
const profile = getClient().getUserProfile();
|
|
7163
|
+
setKyc((k) => ({
|
|
7164
|
+
...k,
|
|
7165
|
+
firstName: k.firstName || profile?.first_name || "",
|
|
7166
|
+
lastName: k.lastName || profile?.last_name || ""
|
|
7167
|
+
}));
|
|
7168
|
+
getClient().getCardOccupations().then(setOccupations).catch(() => setOccupations([]));
|
|
7169
|
+
}, [stage, getClient]);
|
|
7170
|
+
const kycPending = holder ? holder.kycStatus in KYC_PENDING_COPY : false;
|
|
7171
|
+
react.useEffect(() => {
|
|
7172
|
+
if (!kycPending) return;
|
|
7173
|
+
const id = setInterval(() => {
|
|
7174
|
+
loadHolder().then((h) => {
|
|
7175
|
+
if (h?.kycStatus === "APPROVED") void loadCardData();
|
|
7176
|
+
}).catch(() => {
|
|
7177
|
+
});
|
|
7178
|
+
}, KYC_POLL_MS);
|
|
7179
|
+
return () => clearInterval(id);
|
|
7180
|
+
}, [kycPending, loadHolder, loadCardData]);
|
|
7181
|
+
react.useEffect(
|
|
7182
|
+
() => () => {
|
|
7183
|
+
if (revealTimer.current) clearTimeout(revealTimer.current);
|
|
7184
|
+
},
|
|
7185
|
+
[]
|
|
7186
|
+
);
|
|
7187
|
+
function openStep(step) {
|
|
7188
|
+
stepAttempt.current = step;
|
|
7189
|
+
setPendingStep(step);
|
|
7190
|
+
}
|
|
7191
|
+
async function run(key, work, fallback) {
|
|
7192
|
+
if (busy) return;
|
|
7193
|
+
setBusy(key);
|
|
7194
|
+
setError("");
|
|
7195
|
+
try {
|
|
7196
|
+
await work();
|
|
7197
|
+
} catch (e) {
|
|
7198
|
+
const step = requiredCardStep(e);
|
|
7199
|
+
if (step) openStep(step);
|
|
7200
|
+
else setError(errorText(e, fallback));
|
|
7201
|
+
} finally {
|
|
7202
|
+
setBusy(null);
|
|
7203
|
+
}
|
|
7204
|
+
}
|
|
7205
|
+
async function afterStep() {
|
|
7206
|
+
if (!provider) return;
|
|
7207
|
+
const [h, r] = await Promise.all([loadHolder(), loadRequirements(provider.id)]);
|
|
7208
|
+
if (h?.kycStatus === "APPROVED") await loadCardData();
|
|
7209
|
+
if (r?.next && !blockedStepMessage(r.next)) openStep(pendingFromRequirement(provider.id, r.next));
|
|
7210
|
+
}
|
|
7211
|
+
const start = () => run(
|
|
7212
|
+
"start",
|
|
7213
|
+
async () => {
|
|
7214
|
+
if (!provider) return;
|
|
7215
|
+
if (requirements?.next) {
|
|
7216
|
+
openStep(pendingFromRequirement(provider.id, requirements.next));
|
|
7217
|
+
return;
|
|
7218
|
+
}
|
|
7219
|
+
if (holder) return afterStep();
|
|
7220
|
+
setHolder(await getClient().createCardHolder());
|
|
7221
|
+
},
|
|
7222
|
+
"Could not start your card application"
|
|
7223
|
+
);
|
|
7224
|
+
const sendKyc = () => run(
|
|
7225
|
+
"kyc",
|
|
7226
|
+
async () => {
|
|
7227
|
+
const address = { ...kyc.address };
|
|
7228
|
+
if (!address.line2) delete address.line2;
|
|
7229
|
+
setHolder(await getClient().submitCardKyc({ termsAccepted: terms, kyc: { ...kyc, address } }));
|
|
7230
|
+
},
|
|
7231
|
+
"Could not submit your information"
|
|
7232
|
+
);
|
|
7233
|
+
const issue = () => run(
|
|
7234
|
+
"issue",
|
|
7235
|
+
async () => {
|
|
7236
|
+
await getClient().issueCard(nickname.trim() ? { nickname: nickname.trim() } : {});
|
|
7237
|
+
await loadCardData();
|
|
7238
|
+
},
|
|
7239
|
+
"Could not issue your card"
|
|
7240
|
+
);
|
|
7241
|
+
const refresh = () => run(
|
|
7242
|
+
"refresh",
|
|
7243
|
+
async () => {
|
|
7244
|
+
await loadCardData();
|
|
7245
|
+
},
|
|
7246
|
+
"Could not refresh your card"
|
|
7247
|
+
);
|
|
7248
|
+
const reveal = () => run(
|
|
7249
|
+
"reveal",
|
|
7250
|
+
async () => {
|
|
7251
|
+
if (!card) return;
|
|
7252
|
+
const s = await getClient().revealCardSecrets(card.id);
|
|
7253
|
+
setSecrets(s);
|
|
7254
|
+
if (revealTimer.current) clearTimeout(revealTimer.current);
|
|
7255
|
+
revealTimer.current = setTimeout(() => setSecrets(null), REVEAL_MS);
|
|
7256
|
+
},
|
|
7257
|
+
"Could not show the card details"
|
|
7258
|
+
);
|
|
7259
|
+
const openFund = () => run(
|
|
7260
|
+
"fund",
|
|
7261
|
+
async () => {
|
|
7262
|
+
setFundings(await getClient().listCardFundings());
|
|
7263
|
+
setPanel("fund");
|
|
7264
|
+
},
|
|
7265
|
+
"Could not load your fundings"
|
|
7266
|
+
);
|
|
7267
|
+
const fund = () => run(
|
|
7268
|
+
"fund-send",
|
|
7269
|
+
async () => {
|
|
7270
|
+
const outcome = await getClient().fundCard({ amount: fundAmount.trim() });
|
|
7271
|
+
if (outcome.status === "cancelled") {
|
|
7272
|
+
setError("The payment was not signed.");
|
|
7273
|
+
return;
|
|
7274
|
+
}
|
|
7275
|
+
setFundings((cur) => [outcome.funding, ...(cur ?? []).filter((f) => f.id !== outcome.funding.id)]);
|
|
7276
|
+
setFundAmount("");
|
|
7277
|
+
},
|
|
7278
|
+
"Could not fund the card"
|
|
7279
|
+
);
|
|
7280
|
+
const showManualAddress = () => run(
|
|
7281
|
+
"fund-manual",
|
|
7282
|
+
async () => {
|
|
7283
|
+
if (!deposit) setDeposit(await getClient().getCardDepositAddresses());
|
|
7284
|
+
setShowManual(true);
|
|
7285
|
+
},
|
|
7286
|
+
"Could not load the deposit address"
|
|
7287
|
+
);
|
|
7288
|
+
const fundingsInflight = (fundings ?? []).some((f) => FUNDING_INFLIGHT.has(f.status));
|
|
7289
|
+
react.useEffect(() => {
|
|
7290
|
+
if (panel !== "fund" || !fundingsInflight) return;
|
|
7291
|
+
const id = setInterval(() => {
|
|
7292
|
+
getClient().listCardFundings().then((next) => {
|
|
7293
|
+
setFundings((previous) => {
|
|
7294
|
+
const credited = next.some(
|
|
7295
|
+
(f) => f.status === "CREDITED" && previous?.find((p) => p.id === f.id)?.status !== "CREDITED"
|
|
7296
|
+
);
|
|
7297
|
+
if (credited) void loadCardData().catch(() => {
|
|
7298
|
+
});
|
|
7299
|
+
return next;
|
|
7300
|
+
});
|
|
7301
|
+
}).catch(() => {
|
|
7302
|
+
});
|
|
7303
|
+
}, FUNDING_POLL_MS);
|
|
7304
|
+
return () => clearInterval(id);
|
|
7305
|
+
}, [panel, fundingsInflight, getClient, loadCardData]);
|
|
7306
|
+
const field = (key, label, extra = {}) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "pollar-send-field", children: [
|
|
7307
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-label", children: label }),
|
|
7308
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7309
|
+
"input",
|
|
7310
|
+
{
|
|
7311
|
+
className: "pollar-input",
|
|
7312
|
+
value: kyc[key],
|
|
7313
|
+
onChange: (e) => setKyc((k) => ({ ...k, [key]: e.target.value })),
|
|
7314
|
+
...extra
|
|
7315
|
+
}
|
|
7316
|
+
)
|
|
7317
|
+
] });
|
|
7318
|
+
const addressField = (key, label, extra = {}) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "pollar-send-field", children: [
|
|
7319
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-label", children: label }),
|
|
7320
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7321
|
+
"input",
|
|
7322
|
+
{
|
|
7323
|
+
className: "pollar-input",
|
|
7324
|
+
value: kyc.address[key] ?? "",
|
|
7325
|
+
onChange: (e) => setKyc((k) => ({ ...k, address: { ...k.address, [key]: e.target.value } })),
|
|
7326
|
+
...extra
|
|
7327
|
+
}
|
|
7328
|
+
)
|
|
7329
|
+
] });
|
|
7330
|
+
const rangeField = (key, label) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "pollar-send-field", children: [
|
|
7331
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-label", children: label }),
|
|
7332
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7333
|
+
"select",
|
|
7334
|
+
{
|
|
7335
|
+
className: "pollar-input pollar-send-select",
|
|
7336
|
+
value: kyc[key],
|
|
7337
|
+
onChange: (e) => setKyc((k) => ({ ...k, [key]: e.target.value })),
|
|
7338
|
+
children: INCOME_RANGES.map((r) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: r.value, children: r.label }, r.value))
|
|
7339
|
+
}
|
|
7340
|
+
)
|
|
7341
|
+
] });
|
|
7342
|
+
const kycComplete = kyc.firstName && kyc.lastName && /^\d{4}-\d{2}-\d{2}$/.test(kyc.birthDate) && kyc.nationalId && kyc.countryOfIssue.length === 2 && kyc.phoneCountryCode && kyc.phoneNumber && kyc.occupation && kyc.accountPurpose && kyc.address.line1 && kyc.address.city && kyc.address.region && kyc.address.postalCode && kyc.address.countryCode.length === 2;
|
|
7343
|
+
if (pendingStep) {
|
|
7344
|
+
const close = () => {
|
|
7345
|
+
stepAttempt.current = null;
|
|
7346
|
+
setPendingStep(null);
|
|
7347
|
+
};
|
|
7348
|
+
const done = () => {
|
|
7349
|
+
if (stepAttempt.current !== pendingStep) return;
|
|
7350
|
+
close();
|
|
7351
|
+
void afterStep();
|
|
7352
|
+
};
|
|
7353
|
+
const progress = pendingStep.progress ? { progress: pendingStep.progress } : {};
|
|
7354
|
+
if (pendingStep.type === "FORM") {
|
|
7355
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RequirementFormModal, { formId: pendingStep.optionId, ...progress, onClose: close, onSubmitted: done });
|
|
7356
|
+
}
|
|
7357
|
+
if (pendingStep.type === "REGISTRY_CHECK") {
|
|
7358
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RegistryCheckModal, { optionId: pendingStep.optionId, ...progress, onClose: close, onApproved: done });
|
|
7359
|
+
}
|
|
7360
|
+
if (pendingStep.type === "PROVIDER_REGISTRATION") {
|
|
7361
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7362
|
+
ProviderRegistrationModal,
|
|
7363
|
+
{
|
|
7364
|
+
cardProviderId: pendingStep.cardProviderId,
|
|
7365
|
+
...progress,
|
|
7366
|
+
onClose: close,
|
|
7367
|
+
onRegistered: done
|
|
7368
|
+
}
|
|
7369
|
+
);
|
|
7370
|
+
}
|
|
7371
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7372
|
+
KycModal,
|
|
7373
|
+
{
|
|
7374
|
+
cardProviderId: pendingStep.cardProviderId,
|
|
7375
|
+
providerId: pendingStep.optionId,
|
|
7376
|
+
onClose: close,
|
|
7377
|
+
onApproved: done
|
|
7378
|
+
}
|
|
7379
|
+
);
|
|
7380
|
+
}
|
|
7381
|
+
const loading = providers === null || providers.length > 0 && (holder === void 0 || requirements === void 0) || holder?.kycStatus === "APPROVED" && cards === null && !error;
|
|
7382
|
+
const blocked = requirements?.next ? blockedStepMessage(requirements.next) : null;
|
|
7383
|
+
const stepsPending = !!requirements?.next;
|
|
7384
|
+
const title = panel === "fund" ? "Add funds" : card ? card.nickname ?? "Your card" : "Get a card";
|
|
7385
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7386
|
+
"div",
|
|
7387
|
+
{
|
|
7388
|
+
className: "pollar-modal-card pollar-card-modal",
|
|
7389
|
+
"data-theme": theme,
|
|
7390
|
+
style: cssVars,
|
|
7391
|
+
onClick: (e) => e.stopPropagation(),
|
|
7392
|
+
children: [
|
|
7393
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
|
|
7394
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-send-header-left", children: [
|
|
7395
|
+
panel === "fund" && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-modal-close", onClick: () => setPanel("card"), "aria-label": "Back", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 3L5 8l5 5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
|
|
7396
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: title })
|
|
7397
|
+
] }),
|
|
7398
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header-actions", children: [
|
|
7399
|
+
card && panel === "card" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7400
|
+
"button",
|
|
7401
|
+
{
|
|
7402
|
+
type: "button",
|
|
7403
|
+
className: "pollar-modal-close",
|
|
7404
|
+
onClick: () => void refresh(),
|
|
7405
|
+
disabled: busy !== null,
|
|
7406
|
+
"aria-label": "Refresh",
|
|
7407
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7408
|
+
"svg",
|
|
7409
|
+
{
|
|
7410
|
+
className: busy === "refresh" ? "pollar-modal-refresh-icon pollar-spinning" : "pollar-modal-refresh-icon",
|
|
7411
|
+
width: "16",
|
|
7412
|
+
height: "16",
|
|
7413
|
+
viewBox: "0 0 16 16",
|
|
7414
|
+
fill: "none",
|
|
7415
|
+
"aria-hidden": true,
|
|
7416
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7417
|
+
"path",
|
|
7418
|
+
{
|
|
7419
|
+
d: "M13.5 8a5.5 5.5 0 1 1-1.6-3.9M13.5 2v3h-3",
|
|
7420
|
+
stroke: "currentColor",
|
|
7421
|
+
strokeWidth: "1.6",
|
|
7422
|
+
strokeLinecap: "round",
|
|
7423
|
+
strokeLinejoin: "round"
|
|
7424
|
+
}
|
|
7425
|
+
)
|
|
7426
|
+
}
|
|
7427
|
+
)
|
|
7428
|
+
}
|
|
7429
|
+
),
|
|
7430
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
|
|
7431
|
+
] })
|
|
7432
|
+
] }),
|
|
7433
|
+
loading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-loading-block", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-spinner" }) }),
|
|
7434
|
+
!loading && providers?.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: "Cards are not available for this app." }),
|
|
7435
|
+
!loading && provider && !provider.available && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: "Cards are not available right now." }),
|
|
7436
|
+
!loading && provider && provider.available && stage === "steps" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7437
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
|
|
7438
|
+
"Get ",
|
|
7439
|
+
provider.cardLabel ?? `a ${provider.name} card`,
|
|
7440
|
+
" funded from your wallet",
|
|
7441
|
+
wallet ? "" : " once you sign in",
|
|
7442
|
+
". You will verify your identity first; it takes a few minutes."
|
|
7443
|
+
] }),
|
|
7444
|
+
requirements && requirements.total > 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "pollar-card-note", children: [
|
|
7445
|
+
requirements.completed,
|
|
7446
|
+
" of ",
|
|
7447
|
+
requirements.total,
|
|
7448
|
+
" steps done"
|
|
7449
|
+
] }),
|
|
7450
|
+
blocked && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: blocked }),
|
|
7451
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7452
|
+
"button",
|
|
7453
|
+
{
|
|
7454
|
+
type: "button",
|
|
7455
|
+
className: "pollar-btn-primary",
|
|
7456
|
+
onClick: () => void start(),
|
|
7457
|
+
disabled: busy !== null || !wallet || !!blocked,
|
|
7458
|
+
children: busy === "start" ? "Starting..." : stepsPending ? "Continue" : "Start"
|
|
7459
|
+
}
|
|
7460
|
+
) })
|
|
7461
|
+
] }),
|
|
7462
|
+
!loading && provider && stage === "provider-form" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7463
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-card-section-title", children: "About you" }),
|
|
7464
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-card-grid", children: [
|
|
7465
|
+
field("firstName", "First name", { autoComplete: "given-name" }),
|
|
7466
|
+
field("lastName", "Last name", { autoComplete: "family-name" }),
|
|
7467
|
+
field("birthDate", "Birth date", { placeholder: "YYYY-MM-DD", autoComplete: "bday" }),
|
|
7468
|
+
field("nationalId", "ID number"),
|
|
7469
|
+
field("countryOfIssue", "ID country (2 letters)", { maxLength: 2, placeholder: "AR" }),
|
|
7470
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "pollar-send-field", children: [
|
|
7471
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-label", children: "Occupation" }),
|
|
7472
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7473
|
+
"select",
|
|
7474
|
+
{
|
|
7475
|
+
className: "pollar-input pollar-send-select",
|
|
7476
|
+
value: kyc.occupation,
|
|
7477
|
+
onChange: (e) => setKyc((k) => ({ ...k, occupation: e.target.value })),
|
|
7478
|
+
children: [
|
|
7479
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Select..." }),
|
|
7480
|
+
occupations.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.code, children: o.label }, o.code))
|
|
7481
|
+
]
|
|
7482
|
+
}
|
|
7483
|
+
)
|
|
7484
|
+
] }),
|
|
7485
|
+
field("phoneCountryCode", "Phone country code", { placeholder: "54", inputMode: "numeric" }),
|
|
7486
|
+
field("phoneNumber", "Phone number", { placeholder: "91155551234", inputMode: "numeric" }),
|
|
7487
|
+
rangeField("annualSalary", "Annual income"),
|
|
7488
|
+
rangeField("expectedMonthlyVolume", "Expected monthly spend"),
|
|
7489
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-card-grid-full", children: field("accountPurpose", "What will you use the card for?") })
|
|
7490
|
+
] }),
|
|
7491
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-card-section-title", children: "Address" }),
|
|
7492
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-card-grid", children: [
|
|
7493
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-card-grid-full", children: addressField("line1", "Street and number", { autoComplete: "address-line1" }) }),
|
|
7494
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-card-grid-full", children: addressField("line2", "Apartment, floor (optional)", { autoComplete: "address-line2" }) }),
|
|
7495
|
+
addressField("city", "City", { autoComplete: "address-level2" }),
|
|
7496
|
+
addressField("region", "State or province", { autoComplete: "address-level1" }),
|
|
7497
|
+
addressField("postalCode", "Postal code", { autoComplete: "postal-code" }),
|
|
7498
|
+
addressField("countryCode", "Country (2 letters)", { maxLength: 2, placeholder: "AR" })
|
|
7499
|
+
] }),
|
|
7500
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "pollar-card-terms", children: [
|
|
7501
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked: terms, onChange: (e) => setTerms(e.target.checked) }),
|
|
7502
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
7503
|
+
"I have read and accept the",
|
|
7504
|
+
" ",
|
|
7505
|
+
/* @__PURE__ */ jsxRuntime.jsxs("a", { className: "pollar-card-link", href: provider.termsUrl ?? "#", target: "_blank", rel: "noreferrer", children: [
|
|
7506
|
+
provider.name,
|
|
7507
|
+
" terms of service"
|
|
7508
|
+
] }),
|
|
7509
|
+
provider.termsUrl ? "" : " (demo: the final terms link is pending)",
|
|
7510
|
+
"."
|
|
7511
|
+
] })
|
|
7512
|
+
] }),
|
|
7513
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7514
|
+
"button",
|
|
7515
|
+
{
|
|
7516
|
+
type: "button",
|
|
7517
|
+
className: "pollar-btn-primary",
|
|
7518
|
+
onClick: () => void sendKyc(),
|
|
7519
|
+
disabled: busy !== null || !terms || !kycComplete,
|
|
7520
|
+
children: busy === "kyc" ? "Sending..." : "Continue"
|
|
7521
|
+
}
|
|
7522
|
+
) })
|
|
7523
|
+
] }),
|
|
7524
|
+
!loading && holder && holder.kycStatus in KYC_PENDING_COPY && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7525
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: KYC_PENDING_COPY[holder.kycStatus] }),
|
|
7526
|
+
holder.kycReason && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-card-note", children: holder.kycReason }),
|
|
7527
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-actions", children: [
|
|
7528
|
+
holder.verificationLink && /* @__PURE__ */ jsxRuntime.jsx("a", { className: "pollar-btn-primary", href: holder.verificationLink, target: "_blank", rel: "noreferrer", children: "Verify my identity" }),
|
|
7529
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: () => void loadHolder().catch(() => {
|
|
7530
|
+
}), children: "I am done" })
|
|
7531
|
+
] }),
|
|
7532
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-card-note", children: "This screen updates on its own once the verification comes back." })
|
|
7533
|
+
] }),
|
|
7534
|
+
!loading && holder && holder.kycStatus in KYC_FINAL_COPY && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-error", children: [
|
|
7535
|
+
KYC_FINAL_COPY[holder.kycStatus],
|
|
7536
|
+
holder.kycReason ? ` ${holder.kycReason}` : ""
|
|
7537
|
+
] }),
|
|
7538
|
+
!loading && provider && holder?.kycStatus === "APPROVED" && cards !== null && !card && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7539
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Your identity is verified. Issue your virtual card to start." }),
|
|
7540
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "pollar-send-field", children: [
|
|
7541
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-label", children: "Card name (optional)" }),
|
|
7542
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7543
|
+
"input",
|
|
7544
|
+
{
|
|
7545
|
+
className: "pollar-input",
|
|
7546
|
+
value: nickname,
|
|
7547
|
+
maxLength: 40,
|
|
7548
|
+
onChange: (e) => setNickname(e.target.value),
|
|
7549
|
+
placeholder: "Everyday card"
|
|
7550
|
+
}
|
|
7551
|
+
)
|
|
7552
|
+
] }),
|
|
7553
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", onClick: () => void issue(), disabled: busy !== null, children: busy === "issue" ? "Issuing..." : "Issue my card" }) })
|
|
7554
|
+
] }),
|
|
7555
|
+
!loading && provider && card && panel === "card" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7556
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-card-visual", children: [
|
|
7557
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-card-visual-top", children: [
|
|
7558
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-card-brand", children: [
|
|
7559
|
+
styles.logoUrl && /* @__PURE__ */ jsxRuntime.jsx("img", { src: styles.logoUrl, alt: "", className: "pollar-card-brand-logo" }),
|
|
7560
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: provider.cardLabel ?? provider.name })
|
|
7561
|
+
] }),
|
|
7562
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-card-status", children: card.status.toLowerCase() })
|
|
7563
|
+
] }),
|
|
7564
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-card-visual-chip" }),
|
|
7565
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-card-visual-number", children: secrets ? groupPan(secrets.pan) : `\u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 \u2022\u2022\u2022\u2022 ${card.last4 ?? "\u2022\u2022\u2022\u2022"}` }),
|
|
7566
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-card-visual-bottom", children: [
|
|
7567
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
7568
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Expires" }),
|
|
7569
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: card.expMonth && card.expYear ? `${card.expMonth}/${card.expYear.slice(-2)}` : "--/--" })
|
|
7570
|
+
] }),
|
|
7571
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
7572
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "CVC" }),
|
|
7573
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: secrets ? secrets.cvc : "\u2022\u2022\u2022" })
|
|
7574
|
+
] }),
|
|
7575
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
7576
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: card.type.toLowerCase() }),
|
|
7577
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: card.currency })
|
|
7578
|
+
] })
|
|
7579
|
+
] })
|
|
7580
|
+
] }),
|
|
7581
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-card-balance", children: [
|
|
7582
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
7583
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Available" }),
|
|
7584
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: usd(balance?.spendingPowerCents) })
|
|
7585
|
+
] }),
|
|
7586
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
7587
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Limit" }),
|
|
7588
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: usd(balance?.creditLimitCents) })
|
|
7589
|
+
] }),
|
|
7590
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
7591
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "To pay" }),
|
|
7592
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: usd(balance?.balanceDueCents) })
|
|
7593
|
+
] })
|
|
7594
|
+
] }),
|
|
7595
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-actions", children: [
|
|
7596
|
+
provider.supports.revealSecrets && (secrets ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: () => setSecrets(null), children: "Hide details" }) : /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: () => void reveal(), disabled: busy !== null, children: busy === "reveal" ? "Loading..." : "Show details" })),
|
|
7597
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", onClick: () => void openFund(), disabled: busy !== null, children: "Add funds" })
|
|
7598
|
+
] }),
|
|
7599
|
+
secrets && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-card-note", children: "The details hide on their own in 30 seconds. Do not share them." }),
|
|
7600
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-card-section-title", children: "Recent activity" }),
|
|
7601
|
+
transactions === null && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-card-note", children: "Loading..." }),
|
|
7602
|
+
transactions?.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-card-note", children: "No movements yet." }),
|
|
7603
|
+
transactions?.map((tx) => {
|
|
7604
|
+
const purchase = tx.purchase;
|
|
7605
|
+
const local = purchase?.localAmount && purchase.localCurrency && purchase.localCurrency !== "USD" ? money(String(purchase.localAmount), purchase.localCurrency) : null;
|
|
7606
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-card-tx", children: [
|
|
7607
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
7608
|
+
tx.merchantName ?? TX_LABELS[tx.type] ?? tx.type,
|
|
7609
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-card-tx-meta", children: [
|
|
7610
|
+
new Date(tx.occurredAt).toLocaleDateString(),
|
|
7611
|
+
tx.merchantName ? ` \xB7 ${TX_LABELS[tx.type] ?? tx.type}` : "",
|
|
7612
|
+
purchase?.status && purchase.status !== "completed" ? ` \xB7 ${purchase.status}` : ""
|
|
7613
|
+
] })
|
|
7614
|
+
] }),
|
|
7615
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-card-tx-amount", "data-direction": tx.direction ?? void 0, children: [
|
|
7616
|
+
tx.direction === "credit" ? "+" : tx.direction === "debit" ? "-" : "",
|
|
7617
|
+
money(tx.amount, tx.currency),
|
|
7618
|
+
local && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-card-tx-meta", children: local })
|
|
7619
|
+
] })
|
|
7620
|
+
] }, tx.id);
|
|
7621
|
+
})
|
|
7622
|
+
] }),
|
|
7623
|
+
!loading && provider && card && panel === "fund" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7624
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
|
|
7625
|
+
"Move ",
|
|
7626
|
+
provider.fundingAssets.join(" or ") || "USDC",
|
|
7627
|
+
" from your wallet to your card. It takes a few minutes to cross to the card network."
|
|
7628
|
+
] }),
|
|
7629
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "pollar-send-field", children: [
|
|
7630
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-send-label", children: "Amount (USDC)" }),
|
|
7631
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7632
|
+
"input",
|
|
7633
|
+
{
|
|
7634
|
+
className: "pollar-input",
|
|
7635
|
+
inputMode: "decimal",
|
|
7636
|
+
placeholder: "10",
|
|
7637
|
+
value: fundAmount,
|
|
7638
|
+
onChange: (e) => setFundAmount(e.target.value.replace(/[^0-9.]/g, ""))
|
|
7639
|
+
}
|
|
7640
|
+
)
|
|
7641
|
+
] }),
|
|
7642
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-actions", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7643
|
+
"button",
|
|
7644
|
+
{
|
|
7645
|
+
type: "button",
|
|
7646
|
+
className: "pollar-btn-primary",
|
|
7647
|
+
onClick: () => void fund(),
|
|
7648
|
+
disabled: busy !== null || !(Number(fundAmount) >= 1),
|
|
7649
|
+
children: busy === "fund-send" ? "Sending..." : "Fund from my wallet"
|
|
7650
|
+
}
|
|
7651
|
+
) }),
|
|
7652
|
+
fundings && fundings.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7653
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-card-section-title", children: "Your fundings" }),
|
|
7654
|
+
fundings.map((f) => {
|
|
7655
|
+
const copy = FUNDING_COPY[f.status];
|
|
7656
|
+
const inflight = FUNDING_INFLIGHT.has(f.status);
|
|
7657
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-card-tx", "aria-busy": inflight, children: [
|
|
7658
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
7659
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-card-funding-title", children: [
|
|
7660
|
+
inflight && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-spinner pollar-spinner-sm", "aria-hidden": true }),
|
|
7661
|
+
copy?.title ?? f.status
|
|
7662
|
+
] }),
|
|
7663
|
+
inflight && copy?.step && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-card-tx-meta", role: "status", children: [
|
|
7664
|
+
"Step ",
|
|
7665
|
+
copy.step,
|
|
7666
|
+
" of ",
|
|
7667
|
+
FUNDING_STEPS,
|
|
7668
|
+
" \xB7 ",
|
|
7669
|
+
copy.hint
|
|
7670
|
+
] }),
|
|
7671
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-card-tx-meta", children: [
|
|
7672
|
+
new Date(f.createdAt).toLocaleString(),
|
|
7673
|
+
f.status === "FAILED" && f.error ? ` \xB7 ${f.error}` : ""
|
|
7674
|
+
] })
|
|
7675
|
+
] }),
|
|
7676
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-card-tx-amount", "data-direction": f.status === "CREDITED" ? "credit" : void 0, children: money(f.amount, "USD") })
|
|
7677
|
+
] }, f.id);
|
|
7678
|
+
}),
|
|
7679
|
+
fundingsInflight && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-card-note", children: "You can close this window: the funding keeps going and your card is credited when it finishes." })
|
|
7680
|
+
] }),
|
|
7681
|
+
!showManual && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "pollar-card-note", children: [
|
|
7682
|
+
"Prefer to send from another wallet?",
|
|
7683
|
+
" ",
|
|
7684
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7685
|
+
"button",
|
|
7686
|
+
{
|
|
7687
|
+
type: "button",
|
|
7688
|
+
className: "pollar-card-link",
|
|
7689
|
+
onClick: () => void showManualAddress(),
|
|
7690
|
+
disabled: busy !== null,
|
|
7691
|
+
children: "Show the deposit address"
|
|
7692
|
+
}
|
|
7693
|
+
)
|
|
7694
|
+
] }),
|
|
7695
|
+
showManual && deposit?.map((d) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-card-deposit", children: [
|
|
7696
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: d.network }),
|
|
7697
|
+
" (chain ",
|
|
7698
|
+
d.chainId,
|
|
7699
|
+
")",
|
|
7700
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { children: d.address }),
|
|
7701
|
+
/* @__PURE__ */ jsxRuntime.jsx(CopyButton, { value: d.address, label: "Copy address" }),
|
|
7702
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "pollar-card-note", children: [
|
|
7703
|
+
"Send only ",
|
|
7704
|
+
d.tokens.map((t) => (t.currency ?? "token").toUpperCase()).join(" or "),
|
|
7705
|
+
" on ",
|
|
7706
|
+
d.network,
|
|
7707
|
+
"; anything else can be lost."
|
|
7708
|
+
] })
|
|
7709
|
+
] }, d.network)),
|
|
7710
|
+
showManual && deposit?.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: "The provider returned no deposit address." }),
|
|
7711
|
+
showManual && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-card-note", children: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-card-link", onClick: () => setShowManual(false), children: "Hide the deposit address" }) })
|
|
7712
|
+
] }),
|
|
7713
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: error }),
|
|
7714
|
+
/* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
|
|
7715
|
+
]
|
|
7716
|
+
}
|
|
7717
|
+
) });
|
|
7718
|
+
}
|
|
6781
7719
|
function describeDevice(s) {
|
|
6782
7720
|
if (s.deviceLabel) return normalizeDeviceLabel(s.deviceLabel);
|
|
6783
7721
|
if (!s.userAgent) return "Unknown device";
|
|
@@ -7741,7 +8679,7 @@ function PollarProvider({
|
|
|
7741
8679
|
triggered = false;
|
|
7742
8680
|
return;
|
|
7743
8681
|
}
|
|
7744
|
-
if (triggered || sessionRef.current
|
|
8682
|
+
if (triggered || sessionRef.current) return;
|
|
7745
8683
|
triggered = true;
|
|
7746
8684
|
pollarClient.login({ provider: id });
|
|
7747
8685
|
})
|
|
@@ -7794,11 +8732,33 @@ function PollarProvider({
|
|
|
7794
8732
|
const [sendModalKey, setSendModalKey] = react.useState(0);
|
|
7795
8733
|
const [swapModalKey, setSwapModalKey] = react.useState(0);
|
|
7796
8734
|
const [earnModalKey, setEarnModalKey] = react.useState(0);
|
|
8735
|
+
const [cardModalOpen, setCardModalOpen] = react.useState(false);
|
|
8736
|
+
const [cardModalKey, setCardModalKey] = react.useState(0);
|
|
7797
8737
|
const [receiveModalOpen, setReceiveModalOpen] = react.useState(false);
|
|
7798
8738
|
const [sessionsModalOpen, setSessionsModalOpen] = react.useState(false);
|
|
7799
8739
|
const [distributionRulesModalOpen, setDistributionRulesModalOpen] = react.useState(false);
|
|
8740
|
+
react.useEffect(
|
|
8741
|
+
() => pollarClient.onAuthStateChange((authState) => {
|
|
8742
|
+
if (authState.step !== "idle") return;
|
|
8743
|
+
setTransactionModalOpen(false);
|
|
8744
|
+
setKycModalOpen(false);
|
|
8745
|
+
setRampModalOpen(false);
|
|
8746
|
+
setTxHistoryModalOpen(false);
|
|
8747
|
+
setWalletBalanceModalOpen(false);
|
|
8748
|
+
setEnabledAssetsModalOpen(false);
|
|
8749
|
+
setSendModalOpen(false);
|
|
8750
|
+
setSwapModalOpen(false);
|
|
8751
|
+
setEarnModalOpen(false);
|
|
8752
|
+
setCardModalOpen(false);
|
|
8753
|
+
setReceiveModalOpen(false);
|
|
8754
|
+
setSessionsModalOpen(false);
|
|
8755
|
+
setDistributionRulesModalOpen(false);
|
|
8756
|
+
}),
|
|
8757
|
+
[pollarClient]
|
|
8758
|
+
);
|
|
7800
8759
|
const walletAddress = sessionState?.wallet?.address || "";
|
|
7801
8760
|
const walletProvisioning = sessionState?.wallet?.provisioning;
|
|
8761
|
+
const hasSession = sessionState !== null;
|
|
7802
8762
|
const getClient = react.useCallback(() => pollarClient, [pollarClient]);
|
|
7803
8763
|
const refreshWalletBalance = react.useCallback(() => pollarClient.refreshBalance(), [pollarClient, walletAddress]);
|
|
7804
8764
|
const refreshAssets = react.useCallback(() => pollarClient.refreshAssets(), [pollarClient, walletAddress]);
|
|
@@ -7808,7 +8768,9 @@ function PollarProvider({
|
|
|
7808
8768
|
// session
|
|
7809
8769
|
wallet: pollarClient.getWallet(),
|
|
7810
8770
|
wallets: pollarClient.getWallets(),
|
|
7811
|
-
isAuthenticated:
|
|
8771
|
+
isAuthenticated: hasSession,
|
|
8772
|
+
hasWallet: pollarClient.hasWallet(),
|
|
8773
|
+
createWallet: () => pollarClient.createWallet(),
|
|
7812
8774
|
verified,
|
|
7813
8775
|
// client
|
|
7814
8776
|
getClient,
|
|
@@ -7866,6 +8828,11 @@ function PollarProvider({
|
|
|
7866
8828
|
setEarnModalKey((k) => k + 1);
|
|
7867
8829
|
setEarnModalOpen(true);
|
|
7868
8830
|
},
|
|
8831
|
+
// cards
|
|
8832
|
+
openCardModal: () => {
|
|
8833
|
+
setCardModalKey((k) => k + 1);
|
|
8834
|
+
setCardModalOpen(true);
|
|
8835
|
+
},
|
|
7869
8836
|
// sessions
|
|
7870
8837
|
sessions,
|
|
7871
8838
|
openSessionsModal: () => setSessionsModalOpen(true),
|
|
@@ -7891,6 +8858,7 @@ function PollarProvider({
|
|
|
7891
8858
|
}, [
|
|
7892
8859
|
walletAddress,
|
|
7893
8860
|
walletProvisioning,
|
|
8861
|
+
hasSession,
|
|
7894
8862
|
verified,
|
|
7895
8863
|
pollarClient,
|
|
7896
8864
|
getClient,
|
|
@@ -7940,6 +8908,8 @@ function PollarProvider({
|
|
|
7940
8908
|
sendModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setSendModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(SendModal, { onClose: () => setSendModalOpen(false) }) }, sendModalKey),
|
|
7941
8909
|
swapModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setSwapModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(SwapModal, { onClose: () => setSwapModalOpen(false) }) }, swapModalKey),
|
|
7942
8910
|
earnModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setEarnModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(EarnModal, { onClose: () => setEarnModalOpen(false) }) }, earnModalKey),
|
|
8911
|
+
cardModalOpen && // Keyed by the wallet too: a different user, or signing in with it open, starts it from scratch.
|
|
8912
|
+
/* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setCardModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(CardModal, { onClose: () => setCardModalOpen(false) }) }, `${cardModalKey}:${walletAddress}`),
|
|
7943
8913
|
receiveModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setReceiveModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(ReceiveModal, { onClose: () => setReceiveModalOpen(false) }) }),
|
|
7944
8914
|
sessionsModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setSessionsModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(SessionsModal, { onClose: () => setSessionsModalOpen(false) }) }),
|
|
7945
8915
|
distributionRulesModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ModalErrorBoundary, { onClose: () => setDistributionRulesModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(DistributionRulesModal, { onClose: () => setDistributionRulesModalOpen(false) }) })
|
|
@@ -8004,8 +8974,54 @@ function WalletButtonTemplate({
|
|
|
8004
8974
|
onRamp,
|
|
8005
8975
|
onDistributionRules,
|
|
8006
8976
|
onLogout,
|
|
8007
|
-
onLogin
|
|
8977
|
+
onLogin,
|
|
8978
|
+
signedIn,
|
|
8979
|
+
creatingWallet,
|
|
8980
|
+
createWalletError,
|
|
8981
|
+
onCreateWallet
|
|
8008
8982
|
}) {
|
|
8983
|
+
if (!walletAddress && signedIn) {
|
|
8984
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-wallet-wrapper", ref: wrapperRef, children: [
|
|
8985
|
+
/* @__PURE__ */ jsxRuntime.jsxs("button", { className: "pollar-wallet-btn", style: { backgroundColor: accentColor }, onClick: onToggleOpen, children: [
|
|
8986
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-wallet-btn-label", children: onCreateWallet ? "No wallet" : "Signed in" }),
|
|
8987
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8988
|
+
"svg",
|
|
8989
|
+
{
|
|
8990
|
+
className: `pollar-wallet-chevron${open ? " pollar-open" : ""}`,
|
|
8991
|
+
viewBox: "0 0 12 12",
|
|
8992
|
+
fill: "none",
|
|
8993
|
+
stroke: "currentColor",
|
|
8994
|
+
strokeWidth: "2",
|
|
8995
|
+
strokeLinecap: "round",
|
|
8996
|
+
strokeLinejoin: "round",
|
|
8997
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "2,4 6,8 10,4" })
|
|
8998
|
+
}
|
|
8999
|
+
)
|
|
9000
|
+
] }),
|
|
9001
|
+
open && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-wallet-dropdown", style: { backgroundColor: dropdownBg, borderColor: dropdownBorder }, children: [
|
|
9002
|
+
createWalletError && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9003
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-wallet-dropdown-notice", style: { color: itemColor }, role: "status", children: createWalletError }),
|
|
9004
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-wallet-dropdown-divider" })
|
|
9005
|
+
] }),
|
|
9006
|
+
onCreateWallet && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9007
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9008
|
+
"button",
|
|
9009
|
+
{
|
|
9010
|
+
className: "pollar-wallet-dropdown-item",
|
|
9011
|
+
style: { color: itemColor },
|
|
9012
|
+
onClick: onCreateWallet,
|
|
9013
|
+
disabled: creatingWallet,
|
|
9014
|
+
children: creatingWallet ? "Creating wallet\u2026" : "Create wallet"
|
|
9015
|
+
}
|
|
9016
|
+
),
|
|
9017
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-wallet-dropdown-divider" })
|
|
9018
|
+
] }),
|
|
9019
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-wallet-dropdown-item", style: { color: itemColor }, onClick: onSessions, children: "Active sessions" }),
|
|
9020
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-wallet-dropdown-divider" }),
|
|
9021
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-wallet-dropdown-item pollar-danger", onClick: onLogout, children: "Log out" })
|
|
9022
|
+
] })
|
|
9023
|
+
] });
|
|
9024
|
+
}
|
|
8009
9025
|
if (!walletAddress) {
|
|
8010
9026
|
return /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "pollar-wallet-login-btn", style: { backgroundColor: accentColor }, onClick: onLogin, children: [
|
|
8011
9027
|
/* @__PURE__ */ jsxRuntime.jsx(ButtonLogo, {}),
|
|
@@ -8326,7 +9342,10 @@ function WalletButton() {
|
|
|
8326
9342
|
openKycModal,
|
|
8327
9343
|
openRampModal,
|
|
8328
9344
|
openDistributionRulesModal,
|
|
8329
|
-
tx: transaction
|
|
9345
|
+
tx: transaction,
|
|
9346
|
+
isAuthenticated,
|
|
9347
|
+
createWallet,
|
|
9348
|
+
appConfig
|
|
8330
9349
|
} = usePollar();
|
|
8331
9350
|
const { primaryChain, primaryAddress } = useChains();
|
|
8332
9351
|
const walletAddress = primaryAddress || (wallet?.address ?? "");
|
|
@@ -8334,6 +9353,8 @@ function WalletButton() {
|
|
|
8334
9353
|
const [copied, setCopied] = react.useState(false);
|
|
8335
9354
|
const [creating, setCreating] = react.useState(false);
|
|
8336
9355
|
const [created, setCreated] = react.useState(false);
|
|
9356
|
+
const [creatingWallet, setCreatingWallet] = react.useState(false);
|
|
9357
|
+
const [createWalletError, setCreateWalletError] = react.useState(null);
|
|
8337
9358
|
const wrapperRef = react.useRef(null);
|
|
8338
9359
|
const copyTimerRef = react.useRef(null);
|
|
8339
9360
|
const isInProgress = transaction.step === "building" || transaction.step === "signing";
|
|
@@ -8387,6 +9408,21 @@ function WalletButton() {
|
|
|
8387
9408
|
setCreating(false);
|
|
8388
9409
|
}
|
|
8389
9410
|
}
|
|
9411
|
+
async function handleCreateWallet() {
|
|
9412
|
+
if (creatingWallet) return;
|
|
9413
|
+
setCreatingWallet(true);
|
|
9414
|
+
setCreateWalletError(null);
|
|
9415
|
+
try {
|
|
9416
|
+
await createWallet();
|
|
9417
|
+
setOpen(false);
|
|
9418
|
+
} catch (err) {
|
|
9419
|
+
setCreateWalletError(
|
|
9420
|
+
core.isPollarApiError(err) && err.code === "SDK_WALLET_PROVISIONING_DISABLED" ? "This app does not create wallets." : "Could not create the wallet. Try again."
|
|
9421
|
+
);
|
|
9422
|
+
} finally {
|
|
9423
|
+
setCreatingWallet(false);
|
|
9424
|
+
}
|
|
9425
|
+
}
|
|
8390
9426
|
function handleWalletBalance() {
|
|
8391
9427
|
setOpen(false);
|
|
8392
9428
|
openWalletBalanceModal();
|
|
@@ -8432,6 +9468,10 @@ function WalletButton() {
|
|
|
8432
9468
|
wrapperRef,
|
|
8433
9469
|
isInProgress,
|
|
8434
9470
|
showCreateAccount: canCreateAccount,
|
|
9471
|
+
signedIn: isAuthenticated,
|
|
9472
|
+
creatingWallet,
|
|
9473
|
+
createWalletError,
|
|
9474
|
+
...appConfig.application?.walletProvisioning === "NONE" ? {} : { onCreateWallet: handleCreateWallet },
|
|
8435
9475
|
notReadyReason,
|
|
8436
9476
|
creatingAccount: creating,
|
|
8437
9477
|
onToggleOpen: () => setOpen((v) => !v),
|
|
@@ -8451,6 +9491,7 @@ function WalletButton() {
|
|
|
8451
9491
|
);
|
|
8452
9492
|
}
|
|
8453
9493
|
|
|
9494
|
+
exports.CardModal = CardModal;
|
|
8454
9495
|
exports.ChainSelect = ChainSelect;
|
|
8455
9496
|
exports.DistributionRulesModal = DistributionRulesModal;
|
|
8456
9497
|
exports.DistributionRulesModalTemplate = DistributionRulesModalTemplate;
|