@unifold/ui-react 0.1.70-beta.1 → 0.1.71-beta.1
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/dist/index.js +200 -73
- package/dist/index.mjs +200 -73
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -6702,7 +6702,7 @@ function BankTransfer({
|
|
|
6702
6702
|
subdivision_code: userIpInfo?.subdivisionCode || void 0,
|
|
6703
6703
|
// A provider may advertise multiple rails; default to the first.
|
|
6704
6704
|
// UIs that want per-rail rows would need to render one entry per element.
|
|
6705
|
-
|
|
6705
|
+
payment_method_type: provider.payment_methods[0]
|
|
6706
6706
|
});
|
|
6707
6707
|
setActiveProvider(provider);
|
|
6708
6708
|
const convertedPrefilled = await resolvePrefilledSourceAmount(provider.source_currency);
|
|
@@ -11257,6 +11257,13 @@ function setStoredSelectedToken(customerId, token) {
|
|
|
11257
11257
|
} catch {
|
|
11258
11258
|
}
|
|
11259
11259
|
}
|
|
11260
|
+
function clearStoredSelectedToken(customerId) {
|
|
11261
|
+
try {
|
|
11262
|
+
if (typeof window === "undefined" || !customerId) return;
|
|
11263
|
+
localStorage.removeItem(selectedTokenKey(customerId));
|
|
11264
|
+
} catch {
|
|
11265
|
+
}
|
|
11266
|
+
}
|
|
11260
11267
|
|
|
11261
11268
|
// src/components/deposits/stripe-link/PayWithStripeLink.tsx
|
|
11262
11269
|
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
@@ -11274,6 +11281,31 @@ var STRIPE_SESSION_STATUS = {
|
|
|
11274
11281
|
EXPIRED: "expired"
|
|
11275
11282
|
};
|
|
11276
11283
|
var STRIPE_SESSION_POLL_INTERVAL_MS = 3e3;
|
|
11284
|
+
var STRIPE_CONSUMED_PAYMENT_METHOD_CODE = "payment_method_unexpected_state";
|
|
11285
|
+
function isConsumedPaymentMethodError(err) {
|
|
11286
|
+
return err instanceof import_core21.StripeApiResponseError && (err.errorType === "stripe_onramp_payment_method_consumed" || err.stripeCode === STRIPE_CONSUMED_PAYMENT_METHOD_CODE);
|
|
11287
|
+
}
|
|
11288
|
+
var STRIPE_PAYMENT_FAILURE_MESSAGES = {
|
|
11289
|
+
card_declined: "Your card was declined. Try again or use a different payment method.",
|
|
11290
|
+
insufficient_funds: "Your card has insufficient funds. Try a different payment method.",
|
|
11291
|
+
expired_card: "Your card has expired. Use a different payment method.",
|
|
11292
|
+
incorrect_cvc: "Your card\u2019s security code is incorrect. Try again or use a different card.",
|
|
11293
|
+
incorrect_number: "Your card number is incorrect. Try again or use a different card.",
|
|
11294
|
+
card_not_supported: "This card isn\u2019t supported for this purchase. Try a different payment method.",
|
|
11295
|
+
processing_error: "We couldn\u2019t process your card. Please try again in a moment.",
|
|
11296
|
+
authentication_required: "Your bank requires authentication for this payment. Please try again.",
|
|
11297
|
+
payment_intent_authentication_failure: "Card authentication failed. Try again or use a different card.",
|
|
11298
|
+
payment_method_provider_decline: "Your payment provider declined the charge. Try a different payment method.",
|
|
11299
|
+
payment_failed: "Your payment didn\u2019t go through. Try again or use a different payment method."
|
|
11300
|
+
};
|
|
11301
|
+
function describeStripePaymentFailure(reason) {
|
|
11302
|
+
if (!reason) return null;
|
|
11303
|
+
return STRIPE_PAYMENT_FAILURE_MESSAGES[reason] ?? null;
|
|
11304
|
+
}
|
|
11305
|
+
var PAYMENT_FAILED_LEAD = "We couldn\u2019t complete your payment.";
|
|
11306
|
+
function unmappedPaymentFailureMessage(stripeMessage) {
|
|
11307
|
+
return stripeMessage ? `${PAYMENT_FAILED_LEAD} ${stripeMessage}` : `${PAYMENT_FAILED_LEAD} Please try again.`;
|
|
11308
|
+
}
|
|
11277
11309
|
var NO_AUTOFILL = {
|
|
11278
11310
|
autoComplete: "off",
|
|
11279
11311
|
"data-lpignore": "true",
|
|
@@ -11375,7 +11407,11 @@ function PayWithStripeLink({
|
|
|
11375
11407
|
}, [controlledStep]);
|
|
11376
11408
|
(0, import_react17.useEffect)(() => {
|
|
11377
11409
|
setLoading(false);
|
|
11378
|
-
|
|
11410
|
+
if (preserveErrorOnNextStepRef.current) {
|
|
11411
|
+
preserveErrorOnNextStepRef.current = false;
|
|
11412
|
+
} else {
|
|
11413
|
+
setError(null);
|
|
11414
|
+
}
|
|
11379
11415
|
setKycPendingMessage(null);
|
|
11380
11416
|
setQuoteLoading(false);
|
|
11381
11417
|
if (step !== "checkout") {
|
|
@@ -11464,7 +11500,10 @@ function PayWithStripeLink({
|
|
|
11464
11500
|
const pendingAddPaymentRef = (0, import_react17.useRef)(false);
|
|
11465
11501
|
const autoOpenedAddPaymentRef = (0, import_react17.useRef)(false);
|
|
11466
11502
|
const checkoutGenRef = (0, import_react17.useRef)(0);
|
|
11503
|
+
const preserveErrorOnNextStepRef = (0, import_react17.useRef)(false);
|
|
11504
|
+
const spentSessionIdsRef = (0, import_react17.useRef)(/* @__PURE__ */ new Set());
|
|
11467
11505
|
const [stripePaymentUIReady, setStripePaymentUIReady] = (0, import_react17.useState)(false);
|
|
11506
|
+
const [addPaymentHovered, setAddPaymentHovered] = (0, import_react17.useState)(false);
|
|
11468
11507
|
const [oauthToken, setOauthToken] = (0, import_react17.useState)(null);
|
|
11469
11508
|
const [refreshTokenValue, setRefreshTokenValue] = (0, import_react17.useState)(null);
|
|
11470
11509
|
const [customerId, setCustomerId] = (0, import_react17.useState)(null);
|
|
@@ -11613,7 +11652,7 @@ function PayWithStripeLink({
|
|
|
11613
11652
|
const merged = [
|
|
11614
11653
|
...pmResult.data.map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) })),
|
|
11615
11654
|
...persistedNotInApi ? [persisted] : []
|
|
11616
|
-
];
|
|
11655
|
+
].filter((t13) => !deadPaymentTokenIdsRef.current.has(t13.id));
|
|
11617
11656
|
if (merged.length > 0) {
|
|
11618
11657
|
const preferred = persisted && merged.find((m) => m.id === persisted.id) || merged[0];
|
|
11619
11658
|
selectPaymentToken(preferred);
|
|
@@ -11678,6 +11717,7 @@ function PayWithStripeLink({
|
|
|
11678
11717
|
const [selectedPaymentToken, setSelectedPaymentToken] = (0, import_react17.useState)(null);
|
|
11679
11718
|
const [paymentDisplay, setPaymentDisplay] = (0, import_react17.useState)(null);
|
|
11680
11719
|
const selectedTokenSingleUseRef = (0, import_react17.useRef)(false);
|
|
11720
|
+
const deadPaymentTokenIdsRef = (0, import_react17.useRef)(/* @__PURE__ */ new Set());
|
|
11681
11721
|
const selectPaymentToken = (0, import_react17.useCallback)(
|
|
11682
11722
|
(token) => {
|
|
11683
11723
|
selectedTokenSingleUseRef.current = !!token.singleUse;
|
|
@@ -11705,9 +11745,25 @@ function PayWithStripeLink({
|
|
|
11705
11745
|
setStoredSelectedTokenState(null);
|
|
11706
11746
|
}
|
|
11707
11747
|
}, [customerId]);
|
|
11748
|
+
const forgetSelectedPaymentToken = (0, import_react17.useCallback)(
|
|
11749
|
+
(tokenId) => {
|
|
11750
|
+
selectedTokenSingleUseRef.current = false;
|
|
11751
|
+
if (customerId) {
|
|
11752
|
+
const persisted = getStoredSelectedToken(customerId);
|
|
11753
|
+
if (!tokenId || persisted?.id === tokenId) {
|
|
11754
|
+
clearStoredSelectedToken(customerId);
|
|
11755
|
+
}
|
|
11756
|
+
}
|
|
11757
|
+
setSelectedPaymentToken((prev) => !tokenId || prev === tokenId ? null : prev);
|
|
11758
|
+
setPaymentDisplay((prev) => !tokenId || !prev ? null : prev);
|
|
11759
|
+
setStoredSelectedTokenState((prev) => !tokenId || prev?.id === tokenId ? null : prev);
|
|
11760
|
+
},
|
|
11761
|
+
[customerId]
|
|
11762
|
+
);
|
|
11708
11763
|
const displayPaymentTokens = (() => {
|
|
11709
|
-
const
|
|
11710
|
-
|
|
11764
|
+
const isDead = (id) => deadPaymentTokenIdsRef.current.has(id);
|
|
11765
|
+
const apiDisplay = paymentTokens.filter((t13) => !isDead(t13.id)).map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) }));
|
|
11766
|
+
if (storedSelectedToken && !isDead(storedSelectedToken.id) && !paymentTokens.some((t13) => t13.id === storedSelectedToken.id)) {
|
|
11711
11767
|
return [...apiDisplay, storedSelectedToken];
|
|
11712
11768
|
}
|
|
11713
11769
|
return apiDisplay;
|
|
@@ -12356,7 +12412,7 @@ function PayWithStripeLink({
|
|
|
12356
12412
|
const merged = [
|
|
12357
12413
|
...existing.data.map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) })),
|
|
12358
12414
|
...storedNotInApi ? [stored] : []
|
|
12359
|
-
];
|
|
12415
|
+
].filter((t13) => !deadPaymentTokenIdsRef.current.has(t13.id));
|
|
12360
12416
|
if (merged.length === 0) {
|
|
12361
12417
|
if (!autoOpenedAddPaymentRef.current) {
|
|
12362
12418
|
autoOpenedAddPaymentRef.current = true;
|
|
@@ -12398,6 +12454,9 @@ function PayWithStripeLink({
|
|
|
12398
12454
|
paymentInnerRef.current.replaceChildren();
|
|
12399
12455
|
};
|
|
12400
12456
|
}, [step, oauthToken, customerId, publishableKey, coordinator]);
|
|
12457
|
+
(0, import_react17.useEffect)(() => {
|
|
12458
|
+
if (step !== "payment") setAddPaymentHovered(false);
|
|
12459
|
+
}, [step]);
|
|
12401
12460
|
(0, import_react17.useEffect)(() => {
|
|
12402
12461
|
if (step !== "add_payment") return;
|
|
12403
12462
|
if (!isCustomerVerified(customer)) {
|
|
@@ -12548,6 +12607,17 @@ function PayWithStripeLink({
|
|
|
12548
12607
|
}
|
|
12549
12608
|
if (message) onDepositError?.({ message, error: err });
|
|
12550
12609
|
};
|
|
12610
|
+
const isRetriablePaymentToken = (id) => !!id && paymentTokens.some((t13) => t13.id === id);
|
|
12611
|
+
const dropConsumedToken = (message, cause) => {
|
|
12612
|
+
if (selectedPaymentToken) deadPaymentTokenIdsRef.current.add(selectedPaymentToken);
|
|
12613
|
+
setSessionForCheckout(null);
|
|
12614
|
+
forgetSelectedPaymentToken(selectedPaymentToken);
|
|
12615
|
+
preserveErrorOnNextStepRef.current = true;
|
|
12616
|
+
setError(message);
|
|
12617
|
+
setStep("amount");
|
|
12618
|
+
onDepositError?.({ message, error: cause });
|
|
12619
|
+
};
|
|
12620
|
+
const CONSUMED_TOKEN_MESSAGE = "That payment method can\u2019t be used. Please choose another.";
|
|
12551
12621
|
if (!sessionForCheckout || sessionForCheckout.amount !== amount || sessionForCheckout.paymentToken !== selectedPaymentToken) {
|
|
12552
12622
|
return;
|
|
12553
12623
|
}
|
|
@@ -12555,19 +12625,29 @@ function PayWithStripeLink({
|
|
|
12555
12625
|
setLoading(true);
|
|
12556
12626
|
setError(null);
|
|
12557
12627
|
setStep("checkout");
|
|
12628
|
+
let lastConfirmError = null;
|
|
12558
12629
|
try {
|
|
12559
|
-
const runCheckout = (sid) =>
|
|
12560
|
-
|
|
12561
|
-
|
|
12562
|
-
|
|
12563
|
-
|
|
12564
|
-
|
|
12565
|
-
|
|
12566
|
-
|
|
12567
|
-
|
|
12568
|
-
|
|
12569
|
-
|
|
12570
|
-
|
|
12630
|
+
const runCheckout = (sid) => {
|
|
12631
|
+
spentSessionIdsRef.current.add(sid);
|
|
12632
|
+
return coordinator.performCheckout(sid, async (onrampSessionId) => {
|
|
12633
|
+
try {
|
|
12634
|
+
await withTokenRefresh(
|
|
12635
|
+
(tok) => (0, import_core21.stripeRefreshQuote)(onrampSessionId, tok, publishableKey)
|
|
12636
|
+
);
|
|
12637
|
+
} catch {
|
|
12638
|
+
}
|
|
12639
|
+
try {
|
|
12640
|
+
const confirmResponse = await withTokenRefresh(
|
|
12641
|
+
(tok) => (0, import_core21.stripeConfirmSession)(onrampSessionId, tok, {}, publishableKey)
|
|
12642
|
+
);
|
|
12643
|
+
lastConfirmError = null;
|
|
12644
|
+
return confirmResponse.client_secret ?? "";
|
|
12645
|
+
} catch (confirmErr) {
|
|
12646
|
+
lastConfirmError = confirmErr;
|
|
12647
|
+
throw confirmErr;
|
|
12648
|
+
}
|
|
12649
|
+
});
|
|
12650
|
+
};
|
|
12571
12651
|
const lastErrorFor = async (sid) => {
|
|
12572
12652
|
const sessionState = await withTokenRefresh(
|
|
12573
12653
|
(tok) => (0, import_core21.stripeGetSession)(sid, tok, publishableKey)
|
|
@@ -12627,8 +12707,9 @@ function PayWithStripeLink({
|
|
|
12627
12707
|
setStep("success");
|
|
12628
12708
|
} else if (lastError === "quote_rate_drifted" || lastError === "charged_with_expired_quote") {
|
|
12629
12709
|
setSessionForCheckout(null);
|
|
12630
|
-
|
|
12710
|
+
preserveErrorOnNextStepRef.current = true;
|
|
12631
12711
|
setError("Pricing updated. Please try again.");
|
|
12712
|
+
setStep("amount");
|
|
12632
12713
|
} else if (lastError === "missing_document_verification") {
|
|
12633
12714
|
surfaceStepUpOnAmount(void 0, void 0, "l2");
|
|
12634
12715
|
} else if (lastError === "transaction_limit_reached") {
|
|
@@ -12639,28 +12720,52 @@ function PayWithStripeLink({
|
|
|
12639
12720
|
} else if (lastError === "missing_consumer_wallet") {
|
|
12640
12721
|
setStep("wallet");
|
|
12641
12722
|
setError(null);
|
|
12723
|
+
} else if (isConsumedPaymentMethodError(lastConfirmError)) {
|
|
12724
|
+
dropConsumedToken(CONSUMED_TOKEN_MESSAGE, lastConfirmError);
|
|
12642
12725
|
} else {
|
|
12643
|
-
|
|
12644
|
-
|
|
12645
|
-
|
|
12726
|
+
const confirmErr = lastConfirmError instanceof import_core21.StripeApiResponseError ? lastConfirmError : void 0;
|
|
12727
|
+
const reason = describeStripePaymentFailure(lastError) ?? describeStripePaymentFailure(confirmErr?.stripeCode) ?? unmappedPaymentFailureMessage(confirmErr?.stripeMessage);
|
|
12728
|
+
if (!isRetriablePaymentToken(selectedPaymentToken)) {
|
|
12729
|
+
dropConsumedToken(reason, lastConfirmError ?? void 0);
|
|
12730
|
+
} else {
|
|
12731
|
+
setSessionForCheckout(null);
|
|
12732
|
+
preserveErrorOnNextStepRef.current = true;
|
|
12733
|
+
setError(reason);
|
|
12734
|
+
setStep("amount");
|
|
12735
|
+
onDepositError?.({
|
|
12736
|
+
message: lastError ?? confirmErr?.stripeCode ?? "checkout_failed",
|
|
12737
|
+
error: lastConfirmError ?? void 0
|
|
12738
|
+
});
|
|
12739
|
+
}
|
|
12646
12740
|
}
|
|
12647
12741
|
} catch (err) {
|
|
12648
12742
|
if (isStale()) return;
|
|
12649
|
-
const
|
|
12650
|
-
const
|
|
12651
|
-
|
|
12743
|
+
const stripeErr = lastConfirmError instanceof import_core21.StripeApiResponseError ? lastConfirmError : err instanceof import_core21.StripeApiResponseError ? err : void 0;
|
|
12744
|
+
const effectiveError = stripeErr ?? err;
|
|
12745
|
+
const msg = stripeErr?.message ?? (err instanceof Error ? err.message : "Checkout failed");
|
|
12746
|
+
const errorType = stripeErr?.errorType;
|
|
12747
|
+
if (isConsumedPaymentMethodError(effectiveError)) {
|
|
12748
|
+
dropConsumedToken(CONSUMED_TOKEN_MESSAGE, effectiveError);
|
|
12749
|
+
} else if (errorType === "stripe_onramp_missing_minimum_identity_verification") {
|
|
12652
12750
|
setStep("kyc");
|
|
12653
12751
|
setError(null);
|
|
12654
12752
|
} else if (errorType === "stripe_onramp_missing_identity_verification") {
|
|
12655
|
-
surfaceStepUpOnAmount(
|
|
12753
|
+
surfaceStepUpOnAmount(effectiveError, msg, "l1");
|
|
12656
12754
|
} else if (errorType === "stripe_onramp_missing_document_verification") {
|
|
12657
|
-
surfaceStepUpOnAmount(
|
|
12755
|
+
surfaceStepUpOnAmount(effectiveError, msg, "l2");
|
|
12658
12756
|
} else if (errorType === "stripe_onramp_purchase_limit_reached") {
|
|
12659
|
-
surfaceStepUpOnAmount(
|
|
12757
|
+
surfaceStepUpOnAmount(effectiveError, msg, null);
|
|
12660
12758
|
} else {
|
|
12661
|
-
|
|
12662
|
-
|
|
12663
|
-
|
|
12759
|
+
const reason = describeStripePaymentFailure(stripeErr?.stripeCode) ?? (stripeErr?.stripeMessage ? unmappedPaymentFailureMessage(stripeErr.stripeMessage) : msg || unmappedPaymentFailureMessage());
|
|
12760
|
+
if (!isRetriablePaymentToken(selectedPaymentToken)) {
|
|
12761
|
+
dropConsumedToken(reason, effectiveError);
|
|
12762
|
+
} else {
|
|
12763
|
+
setSessionForCheckout(null);
|
|
12764
|
+
preserveErrorOnNextStepRef.current = true;
|
|
12765
|
+
setError(reason);
|
|
12766
|
+
setStep("amount");
|
|
12767
|
+
onDepositError?.({ message: msg || "checkout_failed", error: effectiveError });
|
|
12768
|
+
}
|
|
12664
12769
|
}
|
|
12665
12770
|
} finally {
|
|
12666
12771
|
setLoading(false);
|
|
@@ -12686,7 +12791,7 @@ function PayWithStripeLink({
|
|
|
12686
12791
|
const merged = [
|
|
12687
12792
|
...existing.data.map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) })),
|
|
12688
12793
|
...stored && !existing.data.some((t13) => t13.id === stored.id) ? [stored] : []
|
|
12689
|
-
];
|
|
12794
|
+
].filter((t13) => !deadPaymentTokenIdsRef.current.has(t13.id));
|
|
12690
12795
|
if (merged.length > 0) {
|
|
12691
12796
|
const preferred = stored && merged.find((m) => m.id === stored.id) || merged[0];
|
|
12692
12797
|
selectPaymentToken(preferred);
|
|
@@ -12765,7 +12870,7 @@ function PayWithStripeLink({
|
|
|
12765
12870
|
(0, import_react17.useEffect)(() => {
|
|
12766
12871
|
if (step === "review") {
|
|
12767
12872
|
const existing = sessionForCheckoutRef.current;
|
|
12768
|
-
const hasFreshSession = !!(existing && existing.amount === amount && existing.paymentToken === selectedPaymentToken);
|
|
12873
|
+
const hasFreshSession = !!(existing && existing.amount === amount && existing.paymentToken === selectedPaymentToken && !spentSessionIdsRef.current.has(existing.id));
|
|
12769
12874
|
if (quoteNonce === quoteNonceAtReviewRef.current && hasFreshSession) return;
|
|
12770
12875
|
quoteNonceAtReviewRef.current = quoteNonce;
|
|
12771
12876
|
} else if (step !== "amount") {
|
|
@@ -12789,7 +12894,9 @@ function PayWithStripeLink({
|
|
|
12789
12894
|
const hasPaymentMethod = !!(isAuthenticated && selectedPaymentToken && onrampWalletAddress && isOnrampWalletRegistered);
|
|
12790
12895
|
if (hasPaymentMethod) {
|
|
12791
12896
|
const existing = sessionForCheckoutRef.current;
|
|
12792
|
-
const canRefreshExisting = step === "review" && existing != null && existing.amount === amount && existing.paymentToken === selectedPaymentToken
|
|
12897
|
+
const canRefreshExisting = step === "review" && existing != null && existing.amount === amount && existing.paymentToken === selectedPaymentToken && // Never refresh (and thereby reuse) a session already checked out —
|
|
12898
|
+
// its PaymentIntent is spent. Build a fresh one instead.
|
|
12899
|
+
!spentSessionIdsRef.current.has(existing.id);
|
|
12793
12900
|
const session = canRefreshExisting ? await withTokenRefresh((tok) => (0, import_core21.stripeRefreshQuote)(existing.id, tok, publishableKey)) : await withTokenRefresh(
|
|
12794
12901
|
(tok) => (0, import_core21.stripeCreateSession)(
|
|
12795
12902
|
{
|
|
@@ -12917,7 +13024,7 @@ function PayWithStripeLink({
|
|
|
12917
13024
|
const exceedsReachedLimit = limitReachedAmount !== null && hasInput && amountNum >= limitReachedAmount;
|
|
12918
13025
|
const exceedsLimit = exceedsKnownLimit || exceedsReachedLimit || requiredStepUp !== null;
|
|
12919
13026
|
const isValidAmount = hasInput && amountNum >= 5 && !exceedsLimit;
|
|
12920
|
-
const hasValidSession = !!(sessionForCheckout && sessionForCheckout.amount === amount && sessionForCheckout.paymentToken === selectedPaymentToken);
|
|
13027
|
+
const hasValidSession = !!(sessionForCheckout && sessionForCheckout.amount === amount && sessionForCheckout.paymentToken === selectedPaymentToken && !spentSessionIdsRef.current.has(sessionForCheckout.id));
|
|
12921
13028
|
const canCheckoutDirectly = !!(oauthToken && customerId && selectedPaymentToken && isOnrampWalletRegistered);
|
|
12922
13029
|
const isPreparingSession = canCheckoutDirectly && isValidAmount && !quoteError && (quoteLoading || !hasValidSession);
|
|
12923
13030
|
const custTiers = customer?.kyc_tiers ?? [];
|
|
@@ -13434,7 +13541,7 @@ function PayWithStripeLink({
|
|
|
13434
13541
|
{
|
|
13435
13542
|
onClick: kycFormMode === "name" ? handleNameNext : handleKycSubmit,
|
|
13436
13543
|
disabled: loading || (kycFormMode === "name" ? !kycForm.givenName || !kycForm.surname : kycFormMode === "address" ? !kycForm.addressLine1 || !kycForm.addressCity || !kycForm.addressState || !kycForm.addressPostalCode : !kycForm.ssn || !kycForm.dob.day || !kycForm.dob.month || !kycForm.dob.year),
|
|
13437
|
-
className: "uf-flex-1 uf-py-3.5 uf-text-white uf-font-medium uf-transition-
|
|
13544
|
+
className: "uf-flex-1 uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
|
|
13438
13545
|
style: {
|
|
13439
13546
|
backgroundColor: components.button.primaryBackground,
|
|
13440
13547
|
fontFamily: fonts.medium,
|
|
@@ -13493,7 +13600,17 @@ function PayWithStripeLink({
|
|
|
13493
13600
|
className: "uf-w-full uf-flex-1 uf-overflow-y-auto uf-overflow-x-hidden"
|
|
13494
13601
|
}
|
|
13495
13602
|
),
|
|
13496
|
-
!stripePaymentUIReady && /* @__PURE__ */ (0, import_jsx_runtime44.
|
|
13603
|
+
!stripePaymentUIReady && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-gap-3 uf-py-10", children: [
|
|
13604
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react25.Loader2, { className: "uf-w-8 uf-h-8 uf-animate-spin", style: { color: colors2.primary } }),
|
|
13605
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
13606
|
+
"p",
|
|
13607
|
+
{
|
|
13608
|
+
className: "uf-text-sm uf-text-center",
|
|
13609
|
+
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
13610
|
+
children: "Setting up secure payment\u2026"
|
|
13611
|
+
}
|
|
13612
|
+
)
|
|
13613
|
+
] }),
|
|
13497
13614
|
error && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
13498
13615
|
"div",
|
|
13499
13616
|
{
|
|
@@ -13600,35 +13717,14 @@ function PayWithStripeLink({
|
|
|
13600
13717
|
isCustomerVerified(customer) && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "uf-px-1", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
13601
13718
|
"button",
|
|
13602
13719
|
{
|
|
13603
|
-
onClick:
|
|
13604
|
-
|
|
13605
|
-
setStep("add_payment");
|
|
13606
|
-
return;
|
|
13607
|
-
}
|
|
13608
|
-
pendingAddPaymentRef.current = true;
|
|
13609
|
-
if (accessTokenRef.current && email) {
|
|
13610
|
-
setLoading(true);
|
|
13611
|
-
try {
|
|
13612
|
-
await withTokenRefresh(
|
|
13613
|
-
(tok) => (0, import_core21.stripeGetCustomer)(customerId, tok, publishableKey)
|
|
13614
|
-
);
|
|
13615
|
-
const sdk = await initialize();
|
|
13616
|
-
if (!sdk) throw new Error("SDK failed to load");
|
|
13617
|
-
const authResult = await (0, import_core21.stripeCreateAuthIntent)(email, publishableKey);
|
|
13618
|
-
setAuthIntentId(authResult.auth_intent_id);
|
|
13619
|
-
setStep("auth");
|
|
13620
|
-
} catch {
|
|
13621
|
-
setStep("email");
|
|
13622
|
-
} finally {
|
|
13623
|
-
setLoading(false);
|
|
13624
|
-
}
|
|
13625
|
-
return;
|
|
13626
|
-
}
|
|
13627
|
-
setStep("email");
|
|
13720
|
+
onClick: () => {
|
|
13721
|
+
setStep("add_payment");
|
|
13628
13722
|
},
|
|
13723
|
+
onMouseEnter: () => setAddPaymentHovered(true),
|
|
13724
|
+
onMouseLeave: () => setAddPaymentHovered(false),
|
|
13629
13725
|
className: "uf-w-full uf-p-3 uf-flex uf-items-center uf-gap-3 uf-transition-colors",
|
|
13630
13726
|
style: {
|
|
13631
|
-
backgroundColor: components.card.backgroundColor,
|
|
13727
|
+
backgroundColor: addPaymentHovered ? colors2.cardHover : components.card.backgroundColor,
|
|
13632
13728
|
borderRadius: components.card.borderRadius,
|
|
13633
13729
|
border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
|
|
13634
13730
|
},
|
|
@@ -13743,7 +13839,7 @@ function PayWithStripeLink({
|
|
|
13743
13839
|
{
|
|
13744
13840
|
onClick: () => handleEmailSubmit(),
|
|
13745
13841
|
disabled: loading || !email.trim(),
|
|
13746
|
-
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-
|
|
13842
|
+
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
|
|
13747
13843
|
style: {
|
|
13748
13844
|
backgroundColor: components.button.primaryBackground,
|
|
13749
13845
|
fontFamily: fonts.medium,
|
|
@@ -13972,7 +14068,7 @@ function PayWithStripeLink({
|
|
|
13972
14068
|
{
|
|
13973
14069
|
onClick: handleRegisterSubmit,
|
|
13974
14070
|
disabled: loading || phone.length !== 10,
|
|
13975
|
-
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-
|
|
14071
|
+
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
|
|
13976
14072
|
style: {
|
|
13977
14073
|
backgroundColor: components.button.primaryBackground,
|
|
13978
14074
|
fontFamily: fonts.medium,
|
|
@@ -14106,7 +14202,9 @@ function PayWithStripeLink({
|
|
|
14106
14202
|
);
|
|
14107
14203
|
}
|
|
14108
14204
|
if (step === "amount") {
|
|
14109
|
-
const
|
|
14205
|
+
const canSelectPaymentMethod = !!(oauthToken && customerId && isCustomerVerified(customer));
|
|
14206
|
+
const needsPaymentMethodSelection = canSelectPaymentMethod && !selectedPaymentToken;
|
|
14207
|
+
const paymentSelector = canSelectPaymentMethod ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
14110
14208
|
"button",
|
|
14111
14209
|
{
|
|
14112
14210
|
onClick: () => setStep("payment"),
|
|
@@ -14180,6 +14278,35 @@ function PayWithStripeLink({
|
|
|
14180
14278
|
style: { backgroundColor: colors2.background },
|
|
14181
14279
|
children: [
|
|
14182
14280
|
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "uf-mb-6 uf-pt-2", children: [
|
|
14281
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
14282
|
+
"div",
|
|
14283
|
+
{
|
|
14284
|
+
className: "uf-flex uf-items-start uf-gap-2 uf-mx-1 uf-mb-4 uf-px-3 uf-py-2.5",
|
|
14285
|
+
role: "alert",
|
|
14286
|
+
style: {
|
|
14287
|
+
backgroundColor: `${colors2.error}14`,
|
|
14288
|
+
border: `1px solid ${colors2.error}40`,
|
|
14289
|
+
borderRadius: components.card.borderRadius
|
|
14290
|
+
},
|
|
14291
|
+
children: [
|
|
14292
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
14293
|
+
import_lucide_react25.AlertTriangle,
|
|
14294
|
+
{
|
|
14295
|
+
className: "uf-w-4 uf-h-4 uf-mt-0.5 uf-shrink-0",
|
|
14296
|
+
style: { color: colors2.error }
|
|
14297
|
+
}
|
|
14298
|
+
),
|
|
14299
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
14300
|
+
"span",
|
|
14301
|
+
{
|
|
14302
|
+
className: "uf-text-xs uf-text-left",
|
|
14303
|
+
style: { color: colors2.error, fontFamily: fonts.regular },
|
|
14304
|
+
children: error
|
|
14305
|
+
}
|
|
14306
|
+
)
|
|
14307
|
+
]
|
|
14308
|
+
}
|
|
14309
|
+
),
|
|
14183
14310
|
paymentSelector,
|
|
14184
14311
|
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "uf-text-center uf-mb-4", children: [
|
|
14185
14312
|
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
@@ -14216,7 +14343,7 @@ function PayWithStripeLink({
|
|
|
14216
14343
|
children: amount && amountNum < 5 && !error ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { style: { color: colors2.error }, children: "Minimum amount is $5" }) : exceedsLimit && canRaiseLimit && !error ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { style: { color: colors2.foregroundMuted }, children: [
|
|
14217
14344
|
purchaseLimit !== null ? `Limit $${purchaseLimit.toLocaleString()} \xB7 ` : "Limit reached \xB7 ",
|
|
14218
14345
|
"Verify to raise"
|
|
14219
|
-
] }) : exceedsLimit && !error ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { style: { color: colors2.error }, children: purchaseLimit !== null ? `Limit $${purchaseLimit.toLocaleString()} \xB7 Try less` : "Limit reached \xB7 Try less" }) :
|
|
14346
|
+
] }) : exceedsLimit && !error ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { style: { color: colors2.error }, children: purchaseLimit !== null ? `Limit $${purchaseLimit.toLocaleString()} \xB7 Try less` : "Limit reached \xB7 Try less" }) : quoteError ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { style: { color: colors2.error }, children: quoteError }) : quoteLoading ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
|
|
14220
14347
|
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
14221
14348
|
import_lucide_react25.Loader2,
|
|
14222
14349
|
{
|
|
@@ -14306,7 +14433,7 @@ function PayWithStripeLink({
|
|
|
14306
14433
|
{
|
|
14307
14434
|
onClick: startLimitStepUp,
|
|
14308
14435
|
disabled: loading,
|
|
14309
|
-
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-
|
|
14436
|
+
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
|
|
14310
14437
|
style: {
|
|
14311
14438
|
backgroundColor: components.button.primaryBackground,
|
|
14312
14439
|
fontFamily: fonts.medium,
|
|
@@ -14318,8 +14445,8 @@ function PayWithStripeLink({
|
|
|
14318
14445
|
"button",
|
|
14319
14446
|
{
|
|
14320
14447
|
onClick: handleAmountContinue,
|
|
14321
|
-
disabled: loading || !isValidAmount || !quote || isPreparingSession,
|
|
14322
|
-
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-
|
|
14448
|
+
disabled: loading || !isValidAmount || !quote || isPreparingSession || needsPaymentMethodSelection,
|
|
14449
|
+
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
|
|
14323
14450
|
style: {
|
|
14324
14451
|
backgroundColor: components.button.primaryBackground,
|
|
14325
14452
|
fontFamily: fonts.medium,
|
|
@@ -14449,7 +14576,7 @@ function PayWithStripeLink({
|
|
|
14449
14576
|
{
|
|
14450
14577
|
onClick: isBuyNow ? handleCheckout : handleReviewContinue,
|
|
14451
14578
|
disabled: loading || !quote || isBuyNow && !hasValidSession,
|
|
14452
|
-
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-
|
|
14579
|
+
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
|
|
14453
14580
|
style: {
|
|
14454
14581
|
backgroundColor: components.button.primaryBackground,
|
|
14455
14582
|
fontFamily: fonts.medium,
|
|
@@ -21246,7 +21373,7 @@ function WalletConnect({
|
|
|
21246
21373
|
const chainType = activeDepositWallet?.chain_type ?? "ethereum";
|
|
21247
21374
|
const recipientAddress = activeDepositWallet?.address ?? "";
|
|
21248
21375
|
const isCheckoutMode = !!checkoutAmountUsd;
|
|
21249
|
-
const supportedChainType = chainType === "algorand" || chainType === "xrpl" || chainType === "cardano" || chainType === "n1" ? "ethereum" : chainType;
|
|
21376
|
+
const supportedChainType = chainType === "algorand" || chainType === "xrpl" || chainType === "cardano" || chainType === "n1" || chainType === "tron" ? "ethereum" : chainType;
|
|
21250
21377
|
const transitionTo = React35.useCallback((nextView) => {
|
|
21251
21378
|
if (nextView === viewRef.current) return;
|
|
21252
21379
|
setIsTransitioning(true);
|
|
@@ -21595,7 +21722,7 @@ function WalletConnect({
|
|
|
21595
21722
|
let cancelled = false;
|
|
21596
21723
|
setIsLoading(true);
|
|
21597
21724
|
setError(null);
|
|
21598
|
-
const sct = activeDepositWallet.chain_type === "algorand" || activeDepositWallet.chain_type === "xrpl" || activeDepositWallet.chain_type === "cardano" || activeDepositWallet.chain_type === "n1" ? "ethereum" : activeDepositWallet.chain_type;
|
|
21725
|
+
const sct = activeDepositWallet.chain_type === "algorand" || activeDepositWallet.chain_type === "xrpl" || activeDepositWallet.chain_type === "cardano" || activeDepositWallet.chain_type === "n1" || activeDepositWallet.chain_type === "tron" ? "ethereum" : activeDepositWallet.chain_type;
|
|
21599
21726
|
(0, import_core37.getAddressBalances)(activeWalletInfo.address, sct, publishableKey).then((response) => {
|
|
21600
21727
|
if (cancelled) return;
|
|
21601
21728
|
const nonZero = response.balances.filter((b) => b.amount !== "0");
|
package/dist/index.mjs
CHANGED
|
@@ -6638,7 +6638,7 @@ function BankTransfer({
|
|
|
6638
6638
|
subdivision_code: userIpInfo?.subdivisionCode || void 0,
|
|
6639
6639
|
// A provider may advertise multiple rails; default to the first.
|
|
6640
6640
|
// UIs that want per-rail rows would need to render one entry per element.
|
|
6641
|
-
|
|
6641
|
+
payment_method_type: provider.payment_methods[0]
|
|
6642
6642
|
});
|
|
6643
6643
|
setActiveProvider(provider);
|
|
6644
6644
|
const convertedPrefilled = await resolvePrefilledSourceAmount(provider.source_currency);
|
|
@@ -11218,6 +11218,13 @@ function setStoredSelectedToken(customerId, token) {
|
|
|
11218
11218
|
} catch {
|
|
11219
11219
|
}
|
|
11220
11220
|
}
|
|
11221
|
+
function clearStoredSelectedToken(customerId) {
|
|
11222
|
+
try {
|
|
11223
|
+
if (typeof window === "undefined" || !customerId) return;
|
|
11224
|
+
localStorage.removeItem(selectedTokenKey(customerId));
|
|
11225
|
+
} catch {
|
|
11226
|
+
}
|
|
11227
|
+
}
|
|
11221
11228
|
|
|
11222
11229
|
// src/components/deposits/stripe-link/PayWithStripeLink.tsx
|
|
11223
11230
|
import { Fragment as Fragment6, jsx as jsx44, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
@@ -11235,6 +11242,31 @@ var STRIPE_SESSION_STATUS = {
|
|
|
11235
11242
|
EXPIRED: "expired"
|
|
11236
11243
|
};
|
|
11237
11244
|
var STRIPE_SESSION_POLL_INTERVAL_MS = 3e3;
|
|
11245
|
+
var STRIPE_CONSUMED_PAYMENT_METHOD_CODE = "payment_method_unexpected_state";
|
|
11246
|
+
function isConsumedPaymentMethodError(err) {
|
|
11247
|
+
return err instanceof StripeApiResponseError && (err.errorType === "stripe_onramp_payment_method_consumed" || err.stripeCode === STRIPE_CONSUMED_PAYMENT_METHOD_CODE);
|
|
11248
|
+
}
|
|
11249
|
+
var STRIPE_PAYMENT_FAILURE_MESSAGES = {
|
|
11250
|
+
card_declined: "Your card was declined. Try again or use a different payment method.",
|
|
11251
|
+
insufficient_funds: "Your card has insufficient funds. Try a different payment method.",
|
|
11252
|
+
expired_card: "Your card has expired. Use a different payment method.",
|
|
11253
|
+
incorrect_cvc: "Your card\u2019s security code is incorrect. Try again or use a different card.",
|
|
11254
|
+
incorrect_number: "Your card number is incorrect. Try again or use a different card.",
|
|
11255
|
+
card_not_supported: "This card isn\u2019t supported for this purchase. Try a different payment method.",
|
|
11256
|
+
processing_error: "We couldn\u2019t process your card. Please try again in a moment.",
|
|
11257
|
+
authentication_required: "Your bank requires authentication for this payment. Please try again.",
|
|
11258
|
+
payment_intent_authentication_failure: "Card authentication failed. Try again or use a different card.",
|
|
11259
|
+
payment_method_provider_decline: "Your payment provider declined the charge. Try a different payment method.",
|
|
11260
|
+
payment_failed: "Your payment didn\u2019t go through. Try again or use a different payment method."
|
|
11261
|
+
};
|
|
11262
|
+
function describeStripePaymentFailure(reason) {
|
|
11263
|
+
if (!reason) return null;
|
|
11264
|
+
return STRIPE_PAYMENT_FAILURE_MESSAGES[reason] ?? null;
|
|
11265
|
+
}
|
|
11266
|
+
var PAYMENT_FAILED_LEAD = "We couldn\u2019t complete your payment.";
|
|
11267
|
+
function unmappedPaymentFailureMessage(stripeMessage) {
|
|
11268
|
+
return stripeMessage ? `${PAYMENT_FAILED_LEAD} ${stripeMessage}` : `${PAYMENT_FAILED_LEAD} Please try again.`;
|
|
11269
|
+
}
|
|
11238
11270
|
var NO_AUTOFILL = {
|
|
11239
11271
|
autoComplete: "off",
|
|
11240
11272
|
"data-lpignore": "true",
|
|
@@ -11336,7 +11368,11 @@ function PayWithStripeLink({
|
|
|
11336
11368
|
}, [controlledStep]);
|
|
11337
11369
|
useEffect24(() => {
|
|
11338
11370
|
setLoading(false);
|
|
11339
|
-
|
|
11371
|
+
if (preserveErrorOnNextStepRef.current) {
|
|
11372
|
+
preserveErrorOnNextStepRef.current = false;
|
|
11373
|
+
} else {
|
|
11374
|
+
setError(null);
|
|
11375
|
+
}
|
|
11340
11376
|
setKycPendingMessage(null);
|
|
11341
11377
|
setQuoteLoading(false);
|
|
11342
11378
|
if (step !== "checkout") {
|
|
@@ -11425,7 +11461,10 @@ function PayWithStripeLink({
|
|
|
11425
11461
|
const pendingAddPaymentRef = useRef9(false);
|
|
11426
11462
|
const autoOpenedAddPaymentRef = useRef9(false);
|
|
11427
11463
|
const checkoutGenRef = useRef9(0);
|
|
11464
|
+
const preserveErrorOnNextStepRef = useRef9(false);
|
|
11465
|
+
const spentSessionIdsRef = useRef9(/* @__PURE__ */ new Set());
|
|
11428
11466
|
const [stripePaymentUIReady, setStripePaymentUIReady] = useState29(false);
|
|
11467
|
+
const [addPaymentHovered, setAddPaymentHovered] = useState29(false);
|
|
11429
11468
|
const [oauthToken, setOauthToken] = useState29(null);
|
|
11430
11469
|
const [refreshTokenValue, setRefreshTokenValue] = useState29(null);
|
|
11431
11470
|
const [customerId, setCustomerId] = useState29(null);
|
|
@@ -11574,7 +11613,7 @@ function PayWithStripeLink({
|
|
|
11574
11613
|
const merged = [
|
|
11575
11614
|
...pmResult.data.map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) })),
|
|
11576
11615
|
...persistedNotInApi ? [persisted] : []
|
|
11577
|
-
];
|
|
11616
|
+
].filter((t13) => !deadPaymentTokenIdsRef.current.has(t13.id));
|
|
11578
11617
|
if (merged.length > 0) {
|
|
11579
11618
|
const preferred = persisted && merged.find((m) => m.id === persisted.id) || merged[0];
|
|
11580
11619
|
selectPaymentToken(preferred);
|
|
@@ -11639,6 +11678,7 @@ function PayWithStripeLink({
|
|
|
11639
11678
|
const [selectedPaymentToken, setSelectedPaymentToken] = useState29(null);
|
|
11640
11679
|
const [paymentDisplay, setPaymentDisplay] = useState29(null);
|
|
11641
11680
|
const selectedTokenSingleUseRef = useRef9(false);
|
|
11681
|
+
const deadPaymentTokenIdsRef = useRef9(/* @__PURE__ */ new Set());
|
|
11642
11682
|
const selectPaymentToken = useCallback6(
|
|
11643
11683
|
(token) => {
|
|
11644
11684
|
selectedTokenSingleUseRef.current = !!token.singleUse;
|
|
@@ -11666,9 +11706,25 @@ function PayWithStripeLink({
|
|
|
11666
11706
|
setStoredSelectedTokenState(null);
|
|
11667
11707
|
}
|
|
11668
11708
|
}, [customerId]);
|
|
11709
|
+
const forgetSelectedPaymentToken = useCallback6(
|
|
11710
|
+
(tokenId) => {
|
|
11711
|
+
selectedTokenSingleUseRef.current = false;
|
|
11712
|
+
if (customerId) {
|
|
11713
|
+
const persisted = getStoredSelectedToken(customerId);
|
|
11714
|
+
if (!tokenId || persisted?.id === tokenId) {
|
|
11715
|
+
clearStoredSelectedToken(customerId);
|
|
11716
|
+
}
|
|
11717
|
+
}
|
|
11718
|
+
setSelectedPaymentToken((prev) => !tokenId || prev === tokenId ? null : prev);
|
|
11719
|
+
setPaymentDisplay((prev) => !tokenId || !prev ? null : prev);
|
|
11720
|
+
setStoredSelectedTokenState((prev) => !tokenId || prev?.id === tokenId ? null : prev);
|
|
11721
|
+
},
|
|
11722
|
+
[customerId]
|
|
11723
|
+
);
|
|
11669
11724
|
const displayPaymentTokens = (() => {
|
|
11670
|
-
const
|
|
11671
|
-
|
|
11725
|
+
const isDead = (id) => deadPaymentTokenIdsRef.current.has(id);
|
|
11726
|
+
const apiDisplay = paymentTokens.filter((t13) => !isDead(t13.id)).map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) }));
|
|
11727
|
+
if (storedSelectedToken && !isDead(storedSelectedToken.id) && !paymentTokens.some((t13) => t13.id === storedSelectedToken.id)) {
|
|
11672
11728
|
return [...apiDisplay, storedSelectedToken];
|
|
11673
11729
|
}
|
|
11674
11730
|
return apiDisplay;
|
|
@@ -12317,7 +12373,7 @@ function PayWithStripeLink({
|
|
|
12317
12373
|
const merged = [
|
|
12318
12374
|
...existing.data.map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) })),
|
|
12319
12375
|
...storedNotInApi ? [stored] : []
|
|
12320
|
-
];
|
|
12376
|
+
].filter((t13) => !deadPaymentTokenIdsRef.current.has(t13.id));
|
|
12321
12377
|
if (merged.length === 0) {
|
|
12322
12378
|
if (!autoOpenedAddPaymentRef.current) {
|
|
12323
12379
|
autoOpenedAddPaymentRef.current = true;
|
|
@@ -12359,6 +12415,9 @@ function PayWithStripeLink({
|
|
|
12359
12415
|
paymentInnerRef.current.replaceChildren();
|
|
12360
12416
|
};
|
|
12361
12417
|
}, [step, oauthToken, customerId, publishableKey, coordinator]);
|
|
12418
|
+
useEffect24(() => {
|
|
12419
|
+
if (step !== "payment") setAddPaymentHovered(false);
|
|
12420
|
+
}, [step]);
|
|
12362
12421
|
useEffect24(() => {
|
|
12363
12422
|
if (step !== "add_payment") return;
|
|
12364
12423
|
if (!isCustomerVerified(customer)) {
|
|
@@ -12509,6 +12568,17 @@ function PayWithStripeLink({
|
|
|
12509
12568
|
}
|
|
12510
12569
|
if (message) onDepositError?.({ message, error: err });
|
|
12511
12570
|
};
|
|
12571
|
+
const isRetriablePaymentToken = (id) => !!id && paymentTokens.some((t13) => t13.id === id);
|
|
12572
|
+
const dropConsumedToken = (message, cause) => {
|
|
12573
|
+
if (selectedPaymentToken) deadPaymentTokenIdsRef.current.add(selectedPaymentToken);
|
|
12574
|
+
setSessionForCheckout(null);
|
|
12575
|
+
forgetSelectedPaymentToken(selectedPaymentToken);
|
|
12576
|
+
preserveErrorOnNextStepRef.current = true;
|
|
12577
|
+
setError(message);
|
|
12578
|
+
setStep("amount");
|
|
12579
|
+
onDepositError?.({ message, error: cause });
|
|
12580
|
+
};
|
|
12581
|
+
const CONSUMED_TOKEN_MESSAGE = "That payment method can\u2019t be used. Please choose another.";
|
|
12512
12582
|
if (!sessionForCheckout || sessionForCheckout.amount !== amount || sessionForCheckout.paymentToken !== selectedPaymentToken) {
|
|
12513
12583
|
return;
|
|
12514
12584
|
}
|
|
@@ -12516,19 +12586,29 @@ function PayWithStripeLink({
|
|
|
12516
12586
|
setLoading(true);
|
|
12517
12587
|
setError(null);
|
|
12518
12588
|
setStep("checkout");
|
|
12589
|
+
let lastConfirmError = null;
|
|
12519
12590
|
try {
|
|
12520
|
-
const runCheckout = (sid) =>
|
|
12521
|
-
|
|
12522
|
-
|
|
12523
|
-
|
|
12524
|
-
|
|
12525
|
-
|
|
12526
|
-
|
|
12527
|
-
|
|
12528
|
-
|
|
12529
|
-
|
|
12530
|
-
|
|
12531
|
-
|
|
12591
|
+
const runCheckout = (sid) => {
|
|
12592
|
+
spentSessionIdsRef.current.add(sid);
|
|
12593
|
+
return coordinator.performCheckout(sid, async (onrampSessionId) => {
|
|
12594
|
+
try {
|
|
12595
|
+
await withTokenRefresh(
|
|
12596
|
+
(tok) => stripeRefreshQuote(onrampSessionId, tok, publishableKey)
|
|
12597
|
+
);
|
|
12598
|
+
} catch {
|
|
12599
|
+
}
|
|
12600
|
+
try {
|
|
12601
|
+
const confirmResponse = await withTokenRefresh(
|
|
12602
|
+
(tok) => stripeConfirmSession(onrampSessionId, tok, {}, publishableKey)
|
|
12603
|
+
);
|
|
12604
|
+
lastConfirmError = null;
|
|
12605
|
+
return confirmResponse.client_secret ?? "";
|
|
12606
|
+
} catch (confirmErr) {
|
|
12607
|
+
lastConfirmError = confirmErr;
|
|
12608
|
+
throw confirmErr;
|
|
12609
|
+
}
|
|
12610
|
+
});
|
|
12611
|
+
};
|
|
12532
12612
|
const lastErrorFor = async (sid) => {
|
|
12533
12613
|
const sessionState = await withTokenRefresh(
|
|
12534
12614
|
(tok) => stripeGetSession(sid, tok, publishableKey)
|
|
@@ -12588,8 +12668,9 @@ function PayWithStripeLink({
|
|
|
12588
12668
|
setStep("success");
|
|
12589
12669
|
} else if (lastError === "quote_rate_drifted" || lastError === "charged_with_expired_quote") {
|
|
12590
12670
|
setSessionForCheckout(null);
|
|
12591
|
-
|
|
12671
|
+
preserveErrorOnNextStepRef.current = true;
|
|
12592
12672
|
setError("Pricing updated. Please try again.");
|
|
12673
|
+
setStep("amount");
|
|
12593
12674
|
} else if (lastError === "missing_document_verification") {
|
|
12594
12675
|
surfaceStepUpOnAmount(void 0, void 0, "l2");
|
|
12595
12676
|
} else if (lastError === "transaction_limit_reached") {
|
|
@@ -12600,28 +12681,52 @@ function PayWithStripeLink({
|
|
|
12600
12681
|
} else if (lastError === "missing_consumer_wallet") {
|
|
12601
12682
|
setStep("wallet");
|
|
12602
12683
|
setError(null);
|
|
12684
|
+
} else if (isConsumedPaymentMethodError(lastConfirmError)) {
|
|
12685
|
+
dropConsumedToken(CONSUMED_TOKEN_MESSAGE, lastConfirmError);
|
|
12603
12686
|
} else {
|
|
12604
|
-
|
|
12605
|
-
|
|
12606
|
-
|
|
12687
|
+
const confirmErr = lastConfirmError instanceof StripeApiResponseError ? lastConfirmError : void 0;
|
|
12688
|
+
const reason = describeStripePaymentFailure(lastError) ?? describeStripePaymentFailure(confirmErr?.stripeCode) ?? unmappedPaymentFailureMessage(confirmErr?.stripeMessage);
|
|
12689
|
+
if (!isRetriablePaymentToken(selectedPaymentToken)) {
|
|
12690
|
+
dropConsumedToken(reason, lastConfirmError ?? void 0);
|
|
12691
|
+
} else {
|
|
12692
|
+
setSessionForCheckout(null);
|
|
12693
|
+
preserveErrorOnNextStepRef.current = true;
|
|
12694
|
+
setError(reason);
|
|
12695
|
+
setStep("amount");
|
|
12696
|
+
onDepositError?.({
|
|
12697
|
+
message: lastError ?? confirmErr?.stripeCode ?? "checkout_failed",
|
|
12698
|
+
error: lastConfirmError ?? void 0
|
|
12699
|
+
});
|
|
12700
|
+
}
|
|
12607
12701
|
}
|
|
12608
12702
|
} catch (err) {
|
|
12609
12703
|
if (isStale()) return;
|
|
12610
|
-
const
|
|
12611
|
-
const
|
|
12612
|
-
|
|
12704
|
+
const stripeErr = lastConfirmError instanceof StripeApiResponseError ? lastConfirmError : err instanceof StripeApiResponseError ? err : void 0;
|
|
12705
|
+
const effectiveError = stripeErr ?? err;
|
|
12706
|
+
const msg = stripeErr?.message ?? (err instanceof Error ? err.message : "Checkout failed");
|
|
12707
|
+
const errorType = stripeErr?.errorType;
|
|
12708
|
+
if (isConsumedPaymentMethodError(effectiveError)) {
|
|
12709
|
+
dropConsumedToken(CONSUMED_TOKEN_MESSAGE, effectiveError);
|
|
12710
|
+
} else if (errorType === "stripe_onramp_missing_minimum_identity_verification") {
|
|
12613
12711
|
setStep("kyc");
|
|
12614
12712
|
setError(null);
|
|
12615
12713
|
} else if (errorType === "stripe_onramp_missing_identity_verification") {
|
|
12616
|
-
surfaceStepUpOnAmount(
|
|
12714
|
+
surfaceStepUpOnAmount(effectiveError, msg, "l1");
|
|
12617
12715
|
} else if (errorType === "stripe_onramp_missing_document_verification") {
|
|
12618
|
-
surfaceStepUpOnAmount(
|
|
12716
|
+
surfaceStepUpOnAmount(effectiveError, msg, "l2");
|
|
12619
12717
|
} else if (errorType === "stripe_onramp_purchase_limit_reached") {
|
|
12620
|
-
surfaceStepUpOnAmount(
|
|
12718
|
+
surfaceStepUpOnAmount(effectiveError, msg, null);
|
|
12621
12719
|
} else {
|
|
12622
|
-
|
|
12623
|
-
|
|
12624
|
-
|
|
12720
|
+
const reason = describeStripePaymentFailure(stripeErr?.stripeCode) ?? (stripeErr?.stripeMessage ? unmappedPaymentFailureMessage(stripeErr.stripeMessage) : msg || unmappedPaymentFailureMessage());
|
|
12721
|
+
if (!isRetriablePaymentToken(selectedPaymentToken)) {
|
|
12722
|
+
dropConsumedToken(reason, effectiveError);
|
|
12723
|
+
} else {
|
|
12724
|
+
setSessionForCheckout(null);
|
|
12725
|
+
preserveErrorOnNextStepRef.current = true;
|
|
12726
|
+
setError(reason);
|
|
12727
|
+
setStep("amount");
|
|
12728
|
+
onDepositError?.({ message: msg || "checkout_failed", error: effectiveError });
|
|
12729
|
+
}
|
|
12625
12730
|
}
|
|
12626
12731
|
} finally {
|
|
12627
12732
|
setLoading(false);
|
|
@@ -12647,7 +12752,7 @@ function PayWithStripeLink({
|
|
|
12647
12752
|
const merged = [
|
|
12648
12753
|
...existing.data.map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) })),
|
|
12649
12754
|
...stored && !existing.data.some((t13) => t13.id === stored.id) ? [stored] : []
|
|
12650
|
-
];
|
|
12755
|
+
].filter((t13) => !deadPaymentTokenIdsRef.current.has(t13.id));
|
|
12651
12756
|
if (merged.length > 0) {
|
|
12652
12757
|
const preferred = stored && merged.find((m) => m.id === stored.id) || merged[0];
|
|
12653
12758
|
selectPaymentToken(preferred);
|
|
@@ -12726,7 +12831,7 @@ function PayWithStripeLink({
|
|
|
12726
12831
|
useEffect24(() => {
|
|
12727
12832
|
if (step === "review") {
|
|
12728
12833
|
const existing = sessionForCheckoutRef.current;
|
|
12729
|
-
const hasFreshSession = !!(existing && existing.amount === amount && existing.paymentToken === selectedPaymentToken);
|
|
12834
|
+
const hasFreshSession = !!(existing && existing.amount === amount && existing.paymentToken === selectedPaymentToken && !spentSessionIdsRef.current.has(existing.id));
|
|
12730
12835
|
if (quoteNonce === quoteNonceAtReviewRef.current && hasFreshSession) return;
|
|
12731
12836
|
quoteNonceAtReviewRef.current = quoteNonce;
|
|
12732
12837
|
} else if (step !== "amount") {
|
|
@@ -12750,7 +12855,9 @@ function PayWithStripeLink({
|
|
|
12750
12855
|
const hasPaymentMethod = !!(isAuthenticated && selectedPaymentToken && onrampWalletAddress && isOnrampWalletRegistered);
|
|
12751
12856
|
if (hasPaymentMethod) {
|
|
12752
12857
|
const existing = sessionForCheckoutRef.current;
|
|
12753
|
-
const canRefreshExisting = step === "review" && existing != null && existing.amount === amount && existing.paymentToken === selectedPaymentToken
|
|
12858
|
+
const canRefreshExisting = step === "review" && existing != null && existing.amount === amount && existing.paymentToken === selectedPaymentToken && // Never refresh (and thereby reuse) a session already checked out —
|
|
12859
|
+
// its PaymentIntent is spent. Build a fresh one instead.
|
|
12860
|
+
!spentSessionIdsRef.current.has(existing.id);
|
|
12754
12861
|
const session = canRefreshExisting ? await withTokenRefresh((tok) => stripeRefreshQuote(existing.id, tok, publishableKey)) : await withTokenRefresh(
|
|
12755
12862
|
(tok) => stripeCreateSession(
|
|
12756
12863
|
{
|
|
@@ -12878,7 +12985,7 @@ function PayWithStripeLink({
|
|
|
12878
12985
|
const exceedsReachedLimit = limitReachedAmount !== null && hasInput && amountNum >= limitReachedAmount;
|
|
12879
12986
|
const exceedsLimit = exceedsKnownLimit || exceedsReachedLimit || requiredStepUp !== null;
|
|
12880
12987
|
const isValidAmount = hasInput && amountNum >= 5 && !exceedsLimit;
|
|
12881
|
-
const hasValidSession = !!(sessionForCheckout && sessionForCheckout.amount === amount && sessionForCheckout.paymentToken === selectedPaymentToken);
|
|
12988
|
+
const hasValidSession = !!(sessionForCheckout && sessionForCheckout.amount === amount && sessionForCheckout.paymentToken === selectedPaymentToken && !spentSessionIdsRef.current.has(sessionForCheckout.id));
|
|
12882
12989
|
const canCheckoutDirectly = !!(oauthToken && customerId && selectedPaymentToken && isOnrampWalletRegistered);
|
|
12883
12990
|
const isPreparingSession = canCheckoutDirectly && isValidAmount && !quoteError && (quoteLoading || !hasValidSession);
|
|
12884
12991
|
const custTiers = customer?.kyc_tiers ?? [];
|
|
@@ -13395,7 +13502,7 @@ function PayWithStripeLink({
|
|
|
13395
13502
|
{
|
|
13396
13503
|
onClick: kycFormMode === "name" ? handleNameNext : handleKycSubmit,
|
|
13397
13504
|
disabled: loading || (kycFormMode === "name" ? !kycForm.givenName || !kycForm.surname : kycFormMode === "address" ? !kycForm.addressLine1 || !kycForm.addressCity || !kycForm.addressState || !kycForm.addressPostalCode : !kycForm.ssn || !kycForm.dob.day || !kycForm.dob.month || !kycForm.dob.year),
|
|
13398
|
-
className: "uf-flex-1 uf-py-3.5 uf-text-white uf-font-medium uf-transition-
|
|
13505
|
+
className: "uf-flex-1 uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
|
|
13399
13506
|
style: {
|
|
13400
13507
|
backgroundColor: components.button.primaryBackground,
|
|
13401
13508
|
fontFamily: fonts.medium,
|
|
@@ -13454,7 +13561,17 @@ function PayWithStripeLink({
|
|
|
13454
13561
|
className: "uf-w-full uf-flex-1 uf-overflow-y-auto uf-overflow-x-hidden"
|
|
13455
13562
|
}
|
|
13456
13563
|
),
|
|
13457
|
-
!stripePaymentUIReady && /* @__PURE__ */
|
|
13564
|
+
!stripePaymentUIReady && /* @__PURE__ */ jsxs41("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-gap-3 uf-py-10", children: [
|
|
13565
|
+
/* @__PURE__ */ jsx44(Loader25, { className: "uf-w-8 uf-h-8 uf-animate-spin", style: { color: colors2.primary } }),
|
|
13566
|
+
/* @__PURE__ */ jsx44(
|
|
13567
|
+
"p",
|
|
13568
|
+
{
|
|
13569
|
+
className: "uf-text-sm uf-text-center",
|
|
13570
|
+
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
13571
|
+
children: "Setting up secure payment\u2026"
|
|
13572
|
+
}
|
|
13573
|
+
)
|
|
13574
|
+
] }),
|
|
13458
13575
|
error && /* @__PURE__ */ jsx44(
|
|
13459
13576
|
"div",
|
|
13460
13577
|
{
|
|
@@ -13561,35 +13678,14 @@ function PayWithStripeLink({
|
|
|
13561
13678
|
isCustomerVerified(customer) && /* @__PURE__ */ jsx44("div", { className: "uf-px-1", children: /* @__PURE__ */ jsxs41(
|
|
13562
13679
|
"button",
|
|
13563
13680
|
{
|
|
13564
|
-
onClick:
|
|
13565
|
-
|
|
13566
|
-
setStep("add_payment");
|
|
13567
|
-
return;
|
|
13568
|
-
}
|
|
13569
|
-
pendingAddPaymentRef.current = true;
|
|
13570
|
-
if (accessTokenRef.current && email) {
|
|
13571
|
-
setLoading(true);
|
|
13572
|
-
try {
|
|
13573
|
-
await withTokenRefresh(
|
|
13574
|
-
(tok) => stripeGetCustomer(customerId, tok, publishableKey)
|
|
13575
|
-
);
|
|
13576
|
-
const sdk = await initialize();
|
|
13577
|
-
if (!sdk) throw new Error("SDK failed to load");
|
|
13578
|
-
const authResult = await stripeCreateAuthIntent(email, publishableKey);
|
|
13579
|
-
setAuthIntentId(authResult.auth_intent_id);
|
|
13580
|
-
setStep("auth");
|
|
13581
|
-
} catch {
|
|
13582
|
-
setStep("email");
|
|
13583
|
-
} finally {
|
|
13584
|
-
setLoading(false);
|
|
13585
|
-
}
|
|
13586
|
-
return;
|
|
13587
|
-
}
|
|
13588
|
-
setStep("email");
|
|
13681
|
+
onClick: () => {
|
|
13682
|
+
setStep("add_payment");
|
|
13589
13683
|
},
|
|
13684
|
+
onMouseEnter: () => setAddPaymentHovered(true),
|
|
13685
|
+
onMouseLeave: () => setAddPaymentHovered(false),
|
|
13590
13686
|
className: "uf-w-full uf-p-3 uf-flex uf-items-center uf-gap-3 uf-transition-colors",
|
|
13591
13687
|
style: {
|
|
13592
|
-
backgroundColor: components.card.backgroundColor,
|
|
13688
|
+
backgroundColor: addPaymentHovered ? colors2.cardHover : components.card.backgroundColor,
|
|
13593
13689
|
borderRadius: components.card.borderRadius,
|
|
13594
13690
|
border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
|
|
13595
13691
|
},
|
|
@@ -13704,7 +13800,7 @@ function PayWithStripeLink({
|
|
|
13704
13800
|
{
|
|
13705
13801
|
onClick: () => handleEmailSubmit(),
|
|
13706
13802
|
disabled: loading || !email.trim(),
|
|
13707
|
-
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-
|
|
13803
|
+
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
|
|
13708
13804
|
style: {
|
|
13709
13805
|
backgroundColor: components.button.primaryBackground,
|
|
13710
13806
|
fontFamily: fonts.medium,
|
|
@@ -13933,7 +14029,7 @@ function PayWithStripeLink({
|
|
|
13933
14029
|
{
|
|
13934
14030
|
onClick: handleRegisterSubmit,
|
|
13935
14031
|
disabled: loading || phone.length !== 10,
|
|
13936
|
-
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-
|
|
14032
|
+
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
|
|
13937
14033
|
style: {
|
|
13938
14034
|
backgroundColor: components.button.primaryBackground,
|
|
13939
14035
|
fontFamily: fonts.medium,
|
|
@@ -14067,7 +14163,9 @@ function PayWithStripeLink({
|
|
|
14067
14163
|
);
|
|
14068
14164
|
}
|
|
14069
14165
|
if (step === "amount") {
|
|
14070
|
-
const
|
|
14166
|
+
const canSelectPaymentMethod = !!(oauthToken && customerId && isCustomerVerified(customer));
|
|
14167
|
+
const needsPaymentMethodSelection = canSelectPaymentMethod && !selectedPaymentToken;
|
|
14168
|
+
const paymentSelector = canSelectPaymentMethod ? /* @__PURE__ */ jsxs41(
|
|
14071
14169
|
"button",
|
|
14072
14170
|
{
|
|
14073
14171
|
onClick: () => setStep("payment"),
|
|
@@ -14141,6 +14239,35 @@ function PayWithStripeLink({
|
|
|
14141
14239
|
style: { backgroundColor: colors2.background },
|
|
14142
14240
|
children: [
|
|
14143
14241
|
/* @__PURE__ */ jsxs41("div", { className: "uf-mb-6 uf-pt-2", children: [
|
|
14242
|
+
error && /* @__PURE__ */ jsxs41(
|
|
14243
|
+
"div",
|
|
14244
|
+
{
|
|
14245
|
+
className: "uf-flex uf-items-start uf-gap-2 uf-mx-1 uf-mb-4 uf-px-3 uf-py-2.5",
|
|
14246
|
+
role: "alert",
|
|
14247
|
+
style: {
|
|
14248
|
+
backgroundColor: `${colors2.error}14`,
|
|
14249
|
+
border: `1px solid ${colors2.error}40`,
|
|
14250
|
+
borderRadius: components.card.borderRadius
|
|
14251
|
+
},
|
|
14252
|
+
children: [
|
|
14253
|
+
/* @__PURE__ */ jsx44(
|
|
14254
|
+
AlertTriangle2,
|
|
14255
|
+
{
|
|
14256
|
+
className: "uf-w-4 uf-h-4 uf-mt-0.5 uf-shrink-0",
|
|
14257
|
+
style: { color: colors2.error }
|
|
14258
|
+
}
|
|
14259
|
+
),
|
|
14260
|
+
/* @__PURE__ */ jsx44(
|
|
14261
|
+
"span",
|
|
14262
|
+
{
|
|
14263
|
+
className: "uf-text-xs uf-text-left",
|
|
14264
|
+
style: { color: colors2.error, fontFamily: fonts.regular },
|
|
14265
|
+
children: error
|
|
14266
|
+
}
|
|
14267
|
+
)
|
|
14268
|
+
]
|
|
14269
|
+
}
|
|
14270
|
+
),
|
|
14144
14271
|
paymentSelector,
|
|
14145
14272
|
/* @__PURE__ */ jsxs41("div", { className: "uf-text-center uf-mb-4", children: [
|
|
14146
14273
|
/* @__PURE__ */ jsx44(
|
|
@@ -14177,7 +14304,7 @@ function PayWithStripeLink({
|
|
|
14177
14304
|
children: amount && amountNum < 5 && !error ? /* @__PURE__ */ jsx44("span", { style: { color: colors2.error }, children: "Minimum amount is $5" }) : exceedsLimit && canRaiseLimit && !error ? /* @__PURE__ */ jsxs41("span", { style: { color: colors2.foregroundMuted }, children: [
|
|
14178
14305
|
purchaseLimit !== null ? `Limit $${purchaseLimit.toLocaleString()} \xB7 ` : "Limit reached \xB7 ",
|
|
14179
14306
|
"Verify to raise"
|
|
14180
|
-
] }) : exceedsLimit && !error ? /* @__PURE__ */ jsx44("span", { style: { color: colors2.error }, children: purchaseLimit !== null ? `Limit $${purchaseLimit.toLocaleString()} \xB7 Try less` : "Limit reached \xB7 Try less" }) :
|
|
14307
|
+
] }) : exceedsLimit && !error ? /* @__PURE__ */ jsx44("span", { style: { color: colors2.error }, children: purchaseLimit !== null ? `Limit $${purchaseLimit.toLocaleString()} \xB7 Try less` : "Limit reached \xB7 Try less" }) : quoteError ? /* @__PURE__ */ jsx44("span", { style: { color: colors2.error }, children: quoteError }) : quoteLoading ? /* @__PURE__ */ jsxs41(Fragment6, { children: [
|
|
14181
14308
|
/* @__PURE__ */ jsx44(
|
|
14182
14309
|
Loader25,
|
|
14183
14310
|
{
|
|
@@ -14267,7 +14394,7 @@ function PayWithStripeLink({
|
|
|
14267
14394
|
{
|
|
14268
14395
|
onClick: startLimitStepUp,
|
|
14269
14396
|
disabled: loading,
|
|
14270
|
-
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-
|
|
14397
|
+
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
|
|
14271
14398
|
style: {
|
|
14272
14399
|
backgroundColor: components.button.primaryBackground,
|
|
14273
14400
|
fontFamily: fonts.medium,
|
|
@@ -14279,8 +14406,8 @@ function PayWithStripeLink({
|
|
|
14279
14406
|
"button",
|
|
14280
14407
|
{
|
|
14281
14408
|
onClick: handleAmountContinue,
|
|
14282
|
-
disabled: loading || !isValidAmount || !quote || isPreparingSession,
|
|
14283
|
-
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-
|
|
14409
|
+
disabled: loading || !isValidAmount || !quote || isPreparingSession || needsPaymentMethodSelection,
|
|
14410
|
+
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
|
|
14284
14411
|
style: {
|
|
14285
14412
|
backgroundColor: components.button.primaryBackground,
|
|
14286
14413
|
fontFamily: fonts.medium,
|
|
@@ -14410,7 +14537,7 @@ function PayWithStripeLink({
|
|
|
14410
14537
|
{
|
|
14411
14538
|
onClick: isBuyNow ? handleCheckout : handleReviewContinue,
|
|
14412
14539
|
disabled: loading || !quote || isBuyNow && !hasValidSession,
|
|
14413
|
-
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-
|
|
14540
|
+
className: "uf-w-full uf-py-3.5 uf-text-white uf-font-medium uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-40",
|
|
14414
14541
|
style: {
|
|
14415
14542
|
backgroundColor: components.button.primaryBackground,
|
|
14416
14543
|
fontFamily: fonts.medium,
|
|
@@ -21278,7 +21405,7 @@ function WalletConnect({
|
|
|
21278
21405
|
const chainType = activeDepositWallet?.chain_type ?? "ethereum";
|
|
21279
21406
|
const recipientAddress = activeDepositWallet?.address ?? "";
|
|
21280
21407
|
const isCheckoutMode = !!checkoutAmountUsd;
|
|
21281
|
-
const supportedChainType = chainType === "algorand" || chainType === "xrpl" || chainType === "cardano" || chainType === "n1" ? "ethereum" : chainType;
|
|
21408
|
+
const supportedChainType = chainType === "algorand" || chainType === "xrpl" || chainType === "cardano" || chainType === "n1" || chainType === "tron" ? "ethereum" : chainType;
|
|
21282
21409
|
const transitionTo = React35.useCallback((nextView) => {
|
|
21283
21410
|
if (nextView === viewRef.current) return;
|
|
21284
21411
|
setIsTransitioning(true);
|
|
@@ -21627,7 +21754,7 @@ function WalletConnect({
|
|
|
21627
21754
|
let cancelled = false;
|
|
21628
21755
|
setIsLoading(true);
|
|
21629
21756
|
setError(null);
|
|
21630
|
-
const sct = activeDepositWallet.chain_type === "algorand" || activeDepositWallet.chain_type === "xrpl" || activeDepositWallet.chain_type === "cardano" || activeDepositWallet.chain_type === "n1" ? "ethereum" : activeDepositWallet.chain_type;
|
|
21757
|
+
const sct = activeDepositWallet.chain_type === "algorand" || activeDepositWallet.chain_type === "xrpl" || activeDepositWallet.chain_type === "cardano" || activeDepositWallet.chain_type === "n1" || activeDepositWallet.chain_type === "tron" ? "ethereum" : activeDepositWallet.chain_type;
|
|
21631
21758
|
getAddressBalances2(activeWalletInfo.address, sct, publishableKey).then((response) => {
|
|
21632
21759
|
if (cancelled) return;
|
|
21633
21760
|
const nonZero = response.balances.filter((b) => b.amount !== "0");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unifold/ui-react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.71-beta.1",
|
|
4
4
|
"description": "Unifold UI React - Deposit and onramp components for React applications",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"mipd": "^0.0.7",
|
|
43
43
|
"qr-code-styling": "^1.6.0-rc.1",
|
|
44
44
|
"tailwind-merge": "^2.0.0",
|
|
45
|
-
"@unifold/core": "0.1.
|
|
45
|
+
"@unifold/core": "0.1.71-beta.1"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@solana/web3.js": "^1.87.0",
|