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