@blocklet/payment-react 1.24.3 → 1.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/components/auto-topup/modal.d.ts +2 -0
- package/es/components/auto-topup/modal.js +48 -6
- package/es/components/auto-topup/product-card.d.ts +16 -1
- package/es/components/auto-topup/product-card.js +97 -15
- package/es/components/dynamic-pricing-unavailable.d.ts +9 -0
- package/es/components/dynamic-pricing-unavailable.js +58 -0
- package/es/components/loading-amount.d.ts +17 -0
- package/es/components/loading-amount.js +46 -0
- package/es/components/price-change-confirm.d.ts +18 -0
- package/es/components/price-change-confirm.js +107 -0
- package/es/components/quote-details-panel.d.ts +21 -0
- package/es/components/quote-details-panel.js +170 -0
- package/es/components/quote-lock-banner.d.ts +7 -0
- package/es/components/quote-lock-banner.js +79 -0
- package/es/components/slippage-config.d.ts +20 -0
- package/es/components/slippage-config.js +261 -0
- package/es/history/credit/transactions-list.js +11 -1
- package/es/history/invoice/list.js +125 -15
- package/es/hooks/dynamic-pricing.d.ts +102 -0
- package/es/hooks/dynamic-pricing.js +393 -0
- package/es/index.d.ts +6 -1
- package/es/index.js +9 -1
- package/es/libs/util.d.ts +42 -5
- package/es/libs/util.js +345 -57
- package/es/locales/en.js +114 -3
- package/es/locales/zh.js +114 -3
- package/es/payment/form/index.d.ts +4 -1
- package/es/payment/form/index.js +454 -22
- package/es/payment/index.d.ts +1 -1
- package/es/payment/index.js +279 -16
- package/es/payment/product-item.d.ts +26 -1
- package/es/payment/product-item.js +330 -51
- package/es/payment/summary-section/promotion-section.d.ts +32 -0
- package/es/payment/summary-section/promotion-section.js +143 -0
- package/es/payment/summary-section/total-section.d.ts +39 -0
- package/es/payment/summary-section/total-section.js +83 -0
- package/es/payment/summary.d.ts +17 -2
- package/es/payment/summary.js +300 -253
- package/es/types/index.d.ts +11 -0
- package/lib/components/auto-topup/modal.d.ts +2 -0
- package/lib/components/auto-topup/modal.js +54 -6
- package/lib/components/auto-topup/product-card.d.ts +16 -1
- package/lib/components/auto-topup/product-card.js +75 -7
- package/lib/components/dynamic-pricing-unavailable.d.ts +9 -0
- package/lib/components/dynamic-pricing-unavailable.js +81 -0
- package/lib/components/loading-amount.d.ts +17 -0
- package/lib/components/loading-amount.js +53 -0
- package/lib/components/price-change-confirm.d.ts +18 -0
- package/lib/components/price-change-confirm.js +157 -0
- package/lib/components/quote-details-panel.d.ts +21 -0
- package/lib/components/quote-details-panel.js +226 -0
- package/lib/components/quote-lock-banner.d.ts +7 -0
- package/lib/components/quote-lock-banner.js +93 -0
- package/lib/components/slippage-config.d.ts +20 -0
- package/lib/components/slippage-config.js +316 -0
- package/lib/history/credit/transactions-list.js +11 -1
- package/lib/history/invoice/list.js +167 -27
- package/lib/hooks/dynamic-pricing.d.ts +102 -0
- package/lib/hooks/dynamic-pricing.js +390 -0
- package/lib/index.d.ts +6 -1
- package/lib/index.js +32 -0
- package/lib/libs/util.d.ts +42 -5
- package/lib/libs/util.js +367 -49
- package/lib/locales/en.js +114 -3
- package/lib/locales/zh.js +114 -3
- package/lib/payment/form/index.d.ts +4 -1
- package/lib/payment/form/index.js +476 -20
- package/lib/payment/index.d.ts +1 -1
- package/lib/payment/index.js +308 -14
- package/lib/payment/product-item.d.ts +26 -1
- package/lib/payment/product-item.js +270 -35
- package/lib/payment/summary-section/promotion-section.d.ts +32 -0
- package/lib/payment/summary-section/promotion-section.js +133 -0
- package/lib/payment/summary-section/total-section.d.ts +39 -0
- package/lib/payment/summary-section/total-section.js +117 -0
- package/lib/payment/summary.d.ts +17 -2
- package/lib/payment/summary.js +205 -127
- package/lib/types/index.d.ts +11 -0
- package/package.json +3 -3
- package/src/components/auto-topup/modal.tsx +59 -6
- package/src/components/auto-topup/product-card.tsx +118 -11
- package/src/components/dynamic-pricing-unavailable.tsx +69 -0
- package/src/components/loading-amount.tsx +66 -0
- package/src/components/price-change-confirm.tsx +136 -0
- package/src/components/quote-details-panel.tsx +218 -0
- package/src/components/quote-lock-banner.tsx +99 -0
- package/src/components/slippage-config.tsx +336 -0
- package/src/history/credit/transactions-list.tsx +14 -1
- package/src/history/invoice/list.tsx +143 -9
- package/src/hooks/dynamic-pricing.ts +617 -0
- package/src/index.ts +9 -0
- package/src/libs/util.ts +473 -58
- package/src/locales/en.tsx +117 -0
- package/src/locales/zh.tsx +111 -0
- package/src/payment/form/index.tsx +561 -19
- package/src/payment/index.tsx +349 -10
- package/src/payment/product-item.tsx +451 -37
- package/src/payment/summary-section/promotion-section.tsx +172 -0
- package/src/payment/summary-section/total-section.tsx +141 -0
- package/src/payment/summary.tsx +334 -192
- package/src/types/index.ts +15 -0
package/lib/libs/util.js
CHANGED
|
@@ -14,7 +14,10 @@ exports.formatCouponTerms = void 0;
|
|
|
14
14
|
exports.formatCreditAmount = formatCreditAmount;
|
|
15
15
|
exports.formatCreditForCheckout = formatCreditForCheckout;
|
|
16
16
|
exports.formatDateTime = formatDateTime;
|
|
17
|
+
exports.formatDynamicPrice = formatDynamicPrice;
|
|
17
18
|
exports.formatError = void 0;
|
|
19
|
+
exports.formatExchangeRate = formatExchangeRate;
|
|
20
|
+
exports.formatExchangeRateDisplay = formatExchangeRateDisplay;
|
|
18
21
|
exports.formatLineItemPricing = formatLineItemPricing;
|
|
19
22
|
exports.formatLinkWithLocale = formatLinkWithLocale;
|
|
20
23
|
exports.formatLocale = void 0;
|
|
@@ -26,16 +29,19 @@ exports.formatQuantityInventory = formatQuantityInventory;
|
|
|
26
29
|
exports.formatRecurring = formatRecurring;
|
|
27
30
|
exports.formatSubscriptionProduct = formatSubscriptionProduct;
|
|
28
31
|
exports.formatSubscriptionStatus = formatSubscriptionStatus;
|
|
32
|
+
exports.formatThenValue = formatThenValue;
|
|
29
33
|
exports.formatTime = formatTime;
|
|
30
34
|
exports.formatToDate = formatToDate;
|
|
31
35
|
exports.formatToDatetime = formatToDatetime;
|
|
32
36
|
exports.formatTotalPrice = formatTotalPrice;
|
|
33
37
|
exports.formatUpsellSaving = formatUpsellSaving;
|
|
38
|
+
exports.formatUsdAmount = formatUsdAmount;
|
|
34
39
|
exports.getCheckoutAmount = getCheckoutAmount;
|
|
35
40
|
exports.getCustomerAvatar = getCustomerAvatar;
|
|
36
41
|
exports.getFreeTrialTime = getFreeTrialTime;
|
|
37
42
|
exports.getInvoiceDescriptionAndReason = getInvoiceDescriptionAndReason;
|
|
38
43
|
exports.getInvoiceStatusColor = getInvoiceStatusColor;
|
|
44
|
+
exports.getLineItemAmounts = getLineItemAmounts;
|
|
39
45
|
exports.getLineTimeInfo = void 0;
|
|
40
46
|
exports.getPaymentIntentStatusColor = getPaymentIntentStatusColor;
|
|
41
47
|
exports.getPaymentKitComponent = getPaymentKitComponent;
|
|
@@ -44,6 +50,7 @@ exports.getPrefix = void 0;
|
|
|
44
50
|
exports.getPriceCurrencyOptions = getPriceCurrencyOptions;
|
|
45
51
|
exports.getPriceUintAmountByCurrency = getPriceUintAmountByCurrency;
|
|
46
52
|
exports.getQueryParams = getQueryParams;
|
|
53
|
+
exports.getQuoteLockInfo = getQuoteLockInfo;
|
|
47
54
|
exports.getRecurringPeriod = getRecurringPeriod;
|
|
48
55
|
exports.getRefundStatusColor = getRefundStatusColor;
|
|
49
56
|
exports.getStatementDescriptor = getStatementDescriptor;
|
|
@@ -52,6 +59,8 @@ exports.getSubscriptionStatusColor = getSubscriptionStatusColor;
|
|
|
52
59
|
exports.getSubscriptionTimeSummary = void 0;
|
|
53
60
|
exports.getTokenBalanceLink = getTokenBalanceLink;
|
|
54
61
|
exports.getTxLink = void 0;
|
|
62
|
+
exports.getUsdAmountFromBaseAmount = getUsdAmountFromBaseAmount;
|
|
63
|
+
exports.getUsdAmountFromTokenUnits = getUsdAmountFromTokenUnits;
|
|
55
64
|
exports.getUserProfileLink = getUserProfileLink;
|
|
56
65
|
exports.getWebhookStatusColor = getWebhookStatusColor;
|
|
57
66
|
exports.getWordBreakStyle = getWordBreakStyle;
|
|
@@ -256,6 +265,87 @@ function formatNumber(n, precision = 6, trim = true, thousandSeparated = true) {
|
|
|
256
265
|
const [left, right] = result.split(".");
|
|
257
266
|
return right ? [left, (0, _trimEnd.default)(right, "0")].filter(Boolean).join(".") : left;
|
|
258
267
|
}
|
|
268
|
+
function formatDynamicPrice(n, isDynamic, precision = 6, trim = true, thousandSeparated = true) {
|
|
269
|
+
if (!isDynamic) {
|
|
270
|
+
return formatNumber(n, precision, trim, thousandSeparated);
|
|
271
|
+
}
|
|
272
|
+
const num = Number(n);
|
|
273
|
+
if (!Number.isFinite(num)) {
|
|
274
|
+
return formatNumber(n, precision, trim, thousandSeparated);
|
|
275
|
+
}
|
|
276
|
+
const abs = Math.abs(num);
|
|
277
|
+
const targetPrecision = abs > 0 && abs < 0.01 ? precision : 2;
|
|
278
|
+
return formatNumber(n, targetPrecision, trim, thousandSeparated);
|
|
279
|
+
}
|
|
280
|
+
const USD_DECIMALS = 8;
|
|
281
|
+
function getUsdAmountFromBaseAmount(amount, quantity, scale = BASE_AMOUNT_SCALE) {
|
|
282
|
+
if (amount === void 0 || amount === null || !quantity || quantity <= 0) {
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
const scaled = toScaledBaseAmount(amount, quantity, scale);
|
|
286
|
+
return formatScaledAmount(scaled, scale);
|
|
287
|
+
}
|
|
288
|
+
function getUsdAmountFromTokenUnits(tokenAmount, tokenDecimals, exchangeRate) {
|
|
289
|
+
if (!exchangeRate && exchangeRate !== "0") {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
if (tokenDecimals === void 0 || tokenDecimals === null) {
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
try {
|
|
296
|
+
const amountBN = tokenAmount instanceof _util.BN ? tokenAmount : new _util.BN(tokenAmount || "0");
|
|
297
|
+
const tokenScale = new _util.BN(10).pow(new _util.BN(tokenDecimals));
|
|
298
|
+
if (tokenScale.isZero()) {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
const rateBN = new _util.BN(exchangeRate.replace(".", ""));
|
|
302
|
+
const rateDecimalPlaces = exchangeRate.includes(".") ? exchangeRate.split(".")[1]?.length || 0 : 0;
|
|
303
|
+
const rateScale = new _util.BN(10).pow(new _util.BN(rateDecimalPlaces));
|
|
304
|
+
const usdPrecisionScale = new _util.BN(10).pow(new _util.BN(USD_DECIMALS));
|
|
305
|
+
const usdUnit = amountBN.mul(rateBN).mul(usdPrecisionScale).div(tokenScale.mul(rateScale));
|
|
306
|
+
return (0, _util.fromUnitToToken)(usdUnit.toString(), USD_DECIMALS);
|
|
307
|
+
} catch {
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
function formatUsdAmount(amount, locale = "en") {
|
|
312
|
+
if (!amount && amount !== "0") {
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
const num = Number(amount);
|
|
316
|
+
if (!Number.isFinite(num)) {
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
return new Intl.NumberFormat(locale, {
|
|
320
|
+
minimumFractionDigits: 2,
|
|
321
|
+
maximumFractionDigits: 2
|
|
322
|
+
}).format(num);
|
|
323
|
+
}
|
|
324
|
+
function formatExchangeRate(amount) {
|
|
325
|
+
if (!amount && amount !== "0") {
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
const value = String(amount);
|
|
329
|
+
const num = Number(value);
|
|
330
|
+
if (!Number.isFinite(num)) {
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
return value;
|
|
334
|
+
}
|
|
335
|
+
function formatExchangeRateDisplay(rate, currency = "USD", decimals = 2) {
|
|
336
|
+
if (rate === null || rate === void 0) {
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
const num = Number(rate);
|
|
340
|
+
if (!Number.isFinite(num)) {
|
|
341
|
+
return null;
|
|
342
|
+
}
|
|
343
|
+
const formattedValue = num.toFixed(decimals);
|
|
344
|
+
if (currency === "USD") {
|
|
345
|
+
return `$${formattedValue}`;
|
|
346
|
+
}
|
|
347
|
+
return `${formattedValue} ${currency}`;
|
|
348
|
+
}
|
|
259
349
|
const formatPrice = (price, currency, unit_label, quantity = 1, bn = true, locale = "en") => {
|
|
260
350
|
if (!currency) {
|
|
261
351
|
return "";
|
|
@@ -263,6 +353,22 @@ const formatPrice = (price, currency, unit_label, quantity = 1, bn = true, local
|
|
|
263
353
|
if (price.custom_unit_amount) {
|
|
264
354
|
return `Custom (${currency.symbol})`;
|
|
265
355
|
}
|
|
356
|
+
if (price.pricing_type === "dynamic" && price.base_amount && price.base_currency === "USD") {
|
|
357
|
+
const baseAmount = price.base_amount;
|
|
358
|
+
const usdAmount = Number(baseAmount) * quantity;
|
|
359
|
+
const formattedUsd = formatUsdAmount(usdAmount.toString(), locale);
|
|
360
|
+
if (price?.type === "recurring" && price.recurring) {
|
|
361
|
+
const recurring = formatRecurring(price.recurring, false, "slash", locale);
|
|
362
|
+
if (unit_label) {
|
|
363
|
+
return `$${formattedUsd} / ${unit_label} ${recurring}`;
|
|
364
|
+
}
|
|
365
|
+
if (price.recurring.usage_type === "metered") {
|
|
366
|
+
return `$${formattedUsd} / unit ${recurring}`;
|
|
367
|
+
}
|
|
368
|
+
return `$${formattedUsd} ${recurring}`;
|
|
369
|
+
}
|
|
370
|
+
return `$${formattedUsd}`;
|
|
371
|
+
}
|
|
266
372
|
const unit = getPriceUintAmountByCurrency(price, currency);
|
|
267
373
|
const amount = bn ? (0, _util.fromUnitToToken)(new _util.BN(unit).mul(new _util.BN(quantity)), currency.decimal).toString() : +unit * quantity;
|
|
268
374
|
if (price?.type === "recurring" && price.recurring) {
|
|
@@ -278,10 +384,25 @@ const formatPrice = (price, currency, unit_label, quantity = 1, bn = true, local
|
|
|
278
384
|
return `${amount} ${currency.symbol}`;
|
|
279
385
|
};
|
|
280
386
|
exports.formatPrice = formatPrice;
|
|
281
|
-
const formatPriceAmount = (price, currency, unit_label, quantity = 1, bn = true) => {
|
|
387
|
+
const formatPriceAmount = (price, currency, unit_label, quantity = 1, bn = true, locale = "en") => {
|
|
282
388
|
if (!currency) {
|
|
283
389
|
return "";
|
|
284
390
|
}
|
|
391
|
+
if (price.pricing_type === "dynamic" && price.base_amount && price.base_currency === "USD") {
|
|
392
|
+
const baseAmount = price.base_amount;
|
|
393
|
+
const usdAmount = Number(baseAmount) * quantity;
|
|
394
|
+
const formattedUsd = formatUsdAmount(usdAmount.toString(), locale);
|
|
395
|
+
if (price?.type === "recurring" && price.recurring) {
|
|
396
|
+
if (unit_label) {
|
|
397
|
+
return `$${formattedUsd} / ${unit_label}`;
|
|
398
|
+
}
|
|
399
|
+
if (price.recurring.usage_type === "metered") {
|
|
400
|
+
return `$${formattedUsd} / unit`;
|
|
401
|
+
}
|
|
402
|
+
return `$${formattedUsd}`;
|
|
403
|
+
}
|
|
404
|
+
return `$${formattedUsd}`;
|
|
405
|
+
}
|
|
285
406
|
const unit = getPriceUintAmountByCurrency(price, currency);
|
|
286
407
|
const amount = bn ? (0, _util.fromUnitToToken)(new _util.BN(unit).mul(new _util.BN(quantity)), currency.decimal).toString() : +unit * quantity;
|
|
287
408
|
if (price?.type === "recurring" && price.recurring) {
|
|
@@ -363,9 +484,113 @@ function getPriceCurrencyOptions(price) {
|
|
|
363
484
|
tiers: null
|
|
364
485
|
}];
|
|
365
486
|
}
|
|
487
|
+
const BASE_AMOUNT_SCALE = 8;
|
|
488
|
+
function formatScaledAmount(value, scale = BASE_AMOUNT_SCALE) {
|
|
489
|
+
const isNegative = value.isNeg();
|
|
490
|
+
const absValue = value.abs();
|
|
491
|
+
const str = absValue.toString().padStart(scale + 1, "0");
|
|
492
|
+
const integerPart = str.slice(0, str.length - scale) || "0";
|
|
493
|
+
const fraction = str.slice(-scale).replace(/0+$/, "");
|
|
494
|
+
const formatted = fraction ? `${integerPart}.${fraction}` : integerPart;
|
|
495
|
+
return isNegative ? `-${formatted}` : formatted;
|
|
496
|
+
}
|
|
497
|
+
function toScaledBaseAmount(amount, quantity, scale = BASE_AMOUNT_SCALE) {
|
|
498
|
+
if (!amount || !quantity) {
|
|
499
|
+
return new _util.BN(0);
|
|
500
|
+
}
|
|
501
|
+
const normalized = String(amount);
|
|
502
|
+
const [integer = "0", fraction = ""] = normalized.split(".");
|
|
503
|
+
const frac = `${fraction}`.padEnd(scale, "0").slice(0, scale);
|
|
504
|
+
const digits = `${integer.replace("-", "")}${frac}` || "0";
|
|
505
|
+
const scaled = new _util.BN(digits).mul(new _util.BN(quantity));
|
|
506
|
+
return normalized.startsWith("-") ? scaled.neg() : scaled;
|
|
507
|
+
}
|
|
508
|
+
function getLineItemAmounts(item, currency, {
|
|
509
|
+
useUpsell = true,
|
|
510
|
+
exchangeRate = null
|
|
511
|
+
} = {}) {
|
|
512
|
+
if (!currency) {
|
|
513
|
+
return {
|
|
514
|
+
unitAmount: new _util.BN(0),
|
|
515
|
+
totalAmount: new _util.BN(0),
|
|
516
|
+
isDynamicQuote: false
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
const price = useUpsell ? item.upsell_price || item.price : item.price;
|
|
520
|
+
const quantity = new _util.BN(item.quantity || 0);
|
|
521
|
+
const quoteAmount = item?.quoted_amount;
|
|
522
|
+
const quoteCurrencyId = item?.quote_currency_id;
|
|
523
|
+
const isDynamicPrice = price?.pricing_type === "dynamic";
|
|
524
|
+
const isQuoteValidForCurrency = isDynamicPrice && quoteAmount && quoteCurrencyId === currency.id;
|
|
525
|
+
if (isQuoteValidForCurrency) {
|
|
526
|
+
const totalAmount = new _util.BN(quoteAmount || "0");
|
|
527
|
+
const unitAmount2 = quantity.gt(new _util.BN(0)) ? totalAmount.add(quantity).sub(new _util.BN(1)).div(quantity) : new _util.BN(0);
|
|
528
|
+
return {
|
|
529
|
+
unitAmount: unitAmount2,
|
|
530
|
+
totalAmount,
|
|
531
|
+
isDynamicQuote: true
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
if (isDynamicPrice && exchangeRate && price?.base_amount) {
|
|
535
|
+
const rate = Number(exchangeRate);
|
|
536
|
+
if (rate > 0 && Number.isFinite(rate)) {
|
|
537
|
+
const baseAmountUsd = Number(price.base_amount);
|
|
538
|
+
if (baseAmountUsd > 0 && Number.isFinite(baseAmountUsd)) {
|
|
539
|
+
const tokenAmount = baseAmountUsd / rate;
|
|
540
|
+
const unitAmount2 = (0, _util.fromTokenToUnit)(tokenAmount.toFixed(currency.decimal || 8), currency.decimal || 8);
|
|
541
|
+
return {
|
|
542
|
+
unitAmount: unitAmount2,
|
|
543
|
+
totalAmount: unitAmount2.mul(quantity),
|
|
544
|
+
isDynamicQuote: false
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
const unitAmount = new _util.BN(getPriceUintAmountByCurrency(price, currency));
|
|
550
|
+
return {
|
|
551
|
+
unitAmount,
|
|
552
|
+
totalAmount: unitAmount.mul(quantity),
|
|
553
|
+
isDynamicQuote: false
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
function getQuoteLockInfo(items, currency) {
|
|
557
|
+
if (!items?.length || !currency) {
|
|
558
|
+
return null;
|
|
559
|
+
}
|
|
560
|
+
const dynamicItems = items.filter(item => {
|
|
561
|
+
const price = item.upsell_price || item.price;
|
|
562
|
+
return price?.pricing_type === "dynamic" && item?.quoted_amount;
|
|
563
|
+
});
|
|
564
|
+
if (!dynamicItems.length) {
|
|
565
|
+
return null;
|
|
566
|
+
}
|
|
567
|
+
let totalBaseAmount = new _util.BN(0);
|
|
568
|
+
let totalTokenAmount = new _util.BN(0);
|
|
569
|
+
let expiresAt = null;
|
|
570
|
+
dynamicItems.forEach(item => {
|
|
571
|
+
const price = item.upsell_price || item.price;
|
|
572
|
+
const quoteAmount = new _util.BN(item?.quoted_amount || "0");
|
|
573
|
+
totalTokenAmount = totalTokenAmount.add(quoteAmount);
|
|
574
|
+
const baseAmount = price?.base_amount;
|
|
575
|
+
if (baseAmount) {
|
|
576
|
+
totalBaseAmount = totalBaseAmount.add(toScaledBaseAmount(baseAmount, item.quantity));
|
|
577
|
+
}
|
|
578
|
+
if (item?.expires_at) {
|
|
579
|
+
expiresAt = expiresAt === null ? item?.expires_at : Math.min(expiresAt, item?.expires_at);
|
|
580
|
+
}
|
|
581
|
+
});
|
|
582
|
+
return {
|
|
583
|
+
baseAmount: formatScaledAmount(totalBaseAmount, BASE_AMOUNT_SCALE),
|
|
584
|
+
baseCurrency: (dynamicItems[0]?.upsell_price || dynamicItems[0]?.price)?.base_currency || "USD",
|
|
585
|
+
tokenAmount: (0, _util.fromUnitToToken)(totalTokenAmount, currency.decimal).toString(),
|
|
586
|
+
tokenSymbol: currency.symbol,
|
|
587
|
+
expiresAt
|
|
588
|
+
};
|
|
589
|
+
}
|
|
366
590
|
function formatLineItemPricing(item, currency, {
|
|
367
591
|
trialEnd,
|
|
368
|
-
trialInDays
|
|
592
|
+
trialInDays,
|
|
593
|
+
exchangeRate = null
|
|
369
594
|
}, locale = "en") {
|
|
370
595
|
if (!currency) {
|
|
371
596
|
return {
|
|
@@ -375,15 +600,32 @@ function formatLineItemPricing(item, currency, {
|
|
|
375
600
|
};
|
|
376
601
|
}
|
|
377
602
|
const price = item.upsell_price || item.price;
|
|
603
|
+
if (!price) {
|
|
604
|
+
return {
|
|
605
|
+
primary: "",
|
|
606
|
+
secondary: "",
|
|
607
|
+
quantity: ""
|
|
608
|
+
};
|
|
609
|
+
}
|
|
378
610
|
let quantity = (0, _locales.t)("common.qty", locale, {
|
|
379
611
|
count: item.quantity
|
|
380
612
|
});
|
|
381
613
|
if (price.recurring?.usage_type === "metered" || +item.quantity === 1) {
|
|
382
614
|
quantity = "";
|
|
383
615
|
}
|
|
384
|
-
const
|
|
385
|
-
|
|
386
|
-
|
|
616
|
+
const {
|
|
617
|
+
unitAmount,
|
|
618
|
+
totalAmount
|
|
619
|
+
} = getLineItemAmounts(item, currency, {
|
|
620
|
+
exchangeRate
|
|
621
|
+
});
|
|
622
|
+
const isDynamic = price?.pricing_type === "dynamic";
|
|
623
|
+
const formatLineItemAmount = bn => {
|
|
624
|
+
const value = (0, _util.fromUnitToToken)(bn, currency.decimal);
|
|
625
|
+
return formatDynamicPrice(value, isDynamic, 6);
|
|
626
|
+
};
|
|
627
|
+
const total = `${formatLineItemAmount(totalAmount)} ${currency.symbol}`;
|
|
628
|
+
const unit = `${formatLineItemAmount(unitAmount)} ${currency.symbol}`;
|
|
387
629
|
const trialResult = getFreeTrialTime({
|
|
388
630
|
trialInDays,
|
|
389
631
|
trialEnd
|
|
@@ -505,8 +747,13 @@ function getWebhookStatusColor(status) {
|
|
|
505
747
|
return "default";
|
|
506
748
|
}
|
|
507
749
|
}
|
|
508
|
-
function getCheckoutAmount(items, currency, trialing = false, upsell = true
|
|
509
|
-
|
|
750
|
+
function getCheckoutAmount(items, currency, trialing = false, upsell = true, {
|
|
751
|
+
exchangeRate = null
|
|
752
|
+
} = {}) {
|
|
753
|
+
if (items.find(x => {
|
|
754
|
+
const price = upsell ? x.upsell_price || x.price : x.price;
|
|
755
|
+
return price?.custom_unit_amount;
|
|
756
|
+
}) && items.length > 1) {
|
|
510
757
|
throw new Error("Multiple items with custom unit amount are not supported");
|
|
511
758
|
}
|
|
512
759
|
let renew = new _util.BN(0);
|
|
@@ -514,18 +761,20 @@ function getCheckoutAmount(items, currency, trialing = false, upsell = true) {
|
|
|
514
761
|
const price = upsell ? x.upsell_price || x.price : x.price;
|
|
515
762
|
return price != null;
|
|
516
763
|
}).reduce((acc, x) => {
|
|
517
|
-
|
|
764
|
+
const quoteCurrencyId = x?.quote_currency_id;
|
|
765
|
+
const isQuoteForDifferentCurrency = quoteCurrencyId && quoteCurrencyId !== currency.id;
|
|
766
|
+
if (x.custom_amount && !isQuoteForDifferentCurrency) {
|
|
518
767
|
return acc.add(new _util.BN(x.custom_amount));
|
|
519
768
|
}
|
|
520
769
|
const price = upsell ? x.upsell_price || x.price : x.price;
|
|
521
|
-
const
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
}
|
|
770
|
+
const {
|
|
771
|
+
totalAmount
|
|
772
|
+
} = getLineItemAmounts(x, currency, {
|
|
773
|
+
useUpsell: upsell,
|
|
774
|
+
exchangeRate
|
|
775
|
+
});
|
|
527
776
|
if (price?.type === "recurring") {
|
|
528
|
-
renew = renew.add(
|
|
777
|
+
renew = renew.add(totalAmount);
|
|
529
778
|
if (trialing) {
|
|
530
779
|
return acc;
|
|
531
780
|
}
|
|
@@ -533,12 +782,12 @@ function getCheckoutAmount(items, currency, trialing = false, upsell = true) {
|
|
|
533
782
|
return acc;
|
|
534
783
|
}
|
|
535
784
|
}
|
|
536
|
-
return acc.add(
|
|
785
|
+
return acc.add(totalAmount);
|
|
537
786
|
}, new _util.BN(0)).toString();
|
|
538
787
|
return {
|
|
539
788
|
subtotal: total,
|
|
540
789
|
total,
|
|
541
|
-
renew: renew.toString(),
|
|
790
|
+
renew: formatDynamicPrice(renew.toString(), !!exchangeRate),
|
|
542
791
|
discount: "0",
|
|
543
792
|
shipping: "0",
|
|
544
793
|
tax: "0"
|
|
@@ -569,7 +818,7 @@ function formatUpsellSaving(items, currency) {
|
|
|
569
818
|
if (items[0]?.upsell_price_id) {
|
|
570
819
|
return "0";
|
|
571
820
|
}
|
|
572
|
-
if (!items[0]?.price
|
|
821
|
+
if (!items[0]?.price?.upsell?.upsells_to) {
|
|
573
822
|
return "0";
|
|
574
823
|
}
|
|
575
824
|
const from = getCheckoutAmount(items, currency, false, false);
|
|
@@ -600,6 +849,14 @@ function formatMeteredThen(subscription, recurring, hasMetered, locale = "en") {
|
|
|
600
849
|
recurring
|
|
601
850
|
});
|
|
602
851
|
}
|
|
852
|
+
function formatThenValue(subscription, recurring, hasMetered, locale = "en") {
|
|
853
|
+
if (hasMetered) {
|
|
854
|
+
return (0, _locales.t)("payment.checkout.metered", locale, {
|
|
855
|
+
recurring
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
return [subscription, recurring].filter(Boolean).join(" ");
|
|
859
|
+
}
|
|
603
860
|
function formatPriceDisplay({
|
|
604
861
|
amount,
|
|
605
862
|
then,
|
|
@@ -665,11 +922,15 @@ function getFreeTrialTime({
|
|
|
665
922
|
function formatCheckoutHeadlines(items, currency, {
|
|
666
923
|
trialInDays,
|
|
667
924
|
trialEnd
|
|
668
|
-
}, locale = "en"
|
|
925
|
+
}, locale = "en", {
|
|
926
|
+
exchangeRate = null
|
|
927
|
+
} = {}) {
|
|
669
928
|
const brand = getStatementDescriptor(items);
|
|
670
929
|
const {
|
|
671
930
|
total
|
|
672
|
-
} = getCheckoutAmount(items, currency, trialInDays > 0
|
|
931
|
+
} = getCheckoutAmount(items, currency, trialInDays > 0, true, {
|
|
932
|
+
exchangeRate
|
|
933
|
+
});
|
|
673
934
|
const actualAmount = (0, _util.fromUnitToToken)(total, currency.decimal);
|
|
674
935
|
const amount = `${(0, _util.fromUnitToToken)(total, currency.decimal)} ${currency.symbol}`;
|
|
675
936
|
const trialResult = getFreeTrialTime({
|
|
@@ -687,10 +948,10 @@ function formatCheckoutHeadlines(items, currency, {
|
|
|
687
948
|
}
|
|
688
949
|
const {
|
|
689
950
|
name
|
|
690
|
-
} = items[0]?.price
|
|
951
|
+
} = items[0]?.price?.product || {
|
|
691
952
|
name: ""
|
|
692
953
|
};
|
|
693
|
-
if (items.every(x => x.price
|
|
954
|
+
if (items.every(x => x.price?.type === "one_time")) {
|
|
694
955
|
const action = (0, _locales.t)("payment.checkout.pay", locale, {
|
|
695
956
|
payee: brand
|
|
696
957
|
});
|
|
@@ -710,19 +971,24 @@ function formatCheckoutHeadlines(items, currency, {
|
|
|
710
971
|
priceDisplay: amount
|
|
711
972
|
};
|
|
712
973
|
}
|
|
713
|
-
const item = items.find(x => x.price
|
|
974
|
+
const item = items.find(x => x.price?.type === "recurring");
|
|
714
975
|
const recurring = formatRecurring((item?.upsell_price || item?.price)?.recurring, false, "per", locale);
|
|
715
|
-
const hasMetered = items.some(x => x.price
|
|
976
|
+
const hasMetered = items.some(x => x.price?.type === "recurring" && x.price?.recurring?.usage_type === "metered");
|
|
716
977
|
const differentRecurring = hasMultipleRecurringIntervals(items);
|
|
717
|
-
if (items.every(x => x.price
|
|
718
|
-
const subscription2 = [hasMetered ? (0, _locales.t)("payment.checkout.least", locale) : "", (0, _util.fromUnitToToken)(items.reduce((acc, x) => {
|
|
719
|
-
|
|
978
|
+
if (items.every(x => x.price?.type === "recurring")) {
|
|
979
|
+
const subscription2 = [hasMetered ? (0, _locales.t)("payment.checkout.least", locale) : "", formatDynamicPrice((0, _util.fromUnitToToken)(items.reduce((acc, x) => {
|
|
980
|
+
const price = x.upsell_price || x.price;
|
|
981
|
+
if (price?.recurring?.usage_type === "metered") {
|
|
720
982
|
return acc;
|
|
721
983
|
}
|
|
722
|
-
return acc.add(
|
|
723
|
-
|
|
984
|
+
return acc.add(getLineItemAmounts(x, currency, {
|
|
985
|
+
exchangeRate
|
|
986
|
+
}).totalAmount);
|
|
987
|
+
}, new _util.BN(0)), currency.decimal), !!exchangeRate), currency.symbol].filter(Boolean).join(" ");
|
|
724
988
|
if (items.length > 1) {
|
|
725
989
|
if (trialResult.count > 0) {
|
|
990
|
+
const thenDisplay4 = formatMeteredThen(subscription2, recurring, hasMetered && Number(subscription2) === 0, locale);
|
|
991
|
+
const thenValue4 = formatThenValue(subscription2, recurring, hasMetered && Number(subscription2) === 0, locale);
|
|
726
992
|
const result4 = {
|
|
727
993
|
action: (0, _locales.t)("payment.checkout.try2", locale, {
|
|
728
994
|
name,
|
|
@@ -732,33 +998,51 @@ function formatCheckoutHeadlines(items, currency, {
|
|
|
732
998
|
count: trialResult.count,
|
|
733
999
|
interval: trialResult.interval
|
|
734
1000
|
}),
|
|
735
|
-
then:
|
|
1001
|
+
then: thenDisplay4,
|
|
1002
|
+
thenValue: thenValue4,
|
|
736
1003
|
showThen: true,
|
|
737
1004
|
actualAmount: "0"
|
|
738
1005
|
};
|
|
739
1006
|
return {
|
|
740
1007
|
...result4,
|
|
741
|
-
priceDisplay: formatPriceDisplay(
|
|
1008
|
+
priceDisplay: formatPriceDisplay({
|
|
1009
|
+
amount: result4.amount,
|
|
1010
|
+
then: thenDisplay4,
|
|
1011
|
+
actualAmount: result4.actualAmount,
|
|
1012
|
+
showThen: result4.showThen
|
|
1013
|
+
}, recurring, hasMetered, locale)
|
|
742
1014
|
};
|
|
743
1015
|
}
|
|
1016
|
+
const thenDisplay3 = hasMetered ? (0, _locales.t)("payment.checkout.meteredThen", locale, {
|
|
1017
|
+
recurring
|
|
1018
|
+
}) : recurring;
|
|
1019
|
+
const thenValue3 = hasMetered ? (0, _locales.t)("payment.checkout.metered", locale, {
|
|
1020
|
+
recurring
|
|
1021
|
+
}) : recurring;
|
|
744
1022
|
const result3 = {
|
|
745
1023
|
action: (0, _locales.t)("payment.checkout.sub2", locale, {
|
|
746
1024
|
name,
|
|
747
1025
|
count: items.length - 1
|
|
748
1026
|
}),
|
|
749
1027
|
amount,
|
|
750
|
-
then:
|
|
751
|
-
|
|
752
|
-
}) : recurring,
|
|
1028
|
+
then: thenDisplay3,
|
|
1029
|
+
thenValue: thenValue3,
|
|
753
1030
|
showThen: hasMetered,
|
|
754
1031
|
actualAmount
|
|
755
1032
|
};
|
|
756
1033
|
return {
|
|
757
1034
|
...result3,
|
|
758
|
-
priceDisplay: formatPriceDisplay(
|
|
1035
|
+
priceDisplay: formatPriceDisplay({
|
|
1036
|
+
amount: result3.amount,
|
|
1037
|
+
then: thenDisplay3,
|
|
1038
|
+
actualAmount: result3.actualAmount,
|
|
1039
|
+
showThen: result3.showThen
|
|
1040
|
+
}, recurring, hasMetered, locale)
|
|
759
1041
|
};
|
|
760
1042
|
}
|
|
761
1043
|
if (trialResult.count > 0) {
|
|
1044
|
+
const thenDisplay3 = formatMeteredThen(subscription2, recurring, hasMetered && Number(subscription2) === 0, locale);
|
|
1045
|
+
const thenValue3 = formatThenValue(subscription2, recurring, hasMetered && Number(subscription2) === 0, locale);
|
|
762
1046
|
const result3 = {
|
|
763
1047
|
action: (0, _locales.t)("payment.checkout.try1", locale, {
|
|
764
1048
|
name
|
|
@@ -767,53 +1051,87 @@ function formatCheckoutHeadlines(items, currency, {
|
|
|
767
1051
|
count: trialResult.count,
|
|
768
1052
|
interval: trialResult.interval
|
|
769
1053
|
}),
|
|
770
|
-
then:
|
|
1054
|
+
then: thenDisplay3,
|
|
1055
|
+
thenValue: thenValue3,
|
|
771
1056
|
showThen: true,
|
|
772
1057
|
actualAmount: "0"
|
|
773
1058
|
};
|
|
774
1059
|
return {
|
|
775
1060
|
...result3,
|
|
776
|
-
priceDisplay: formatPriceDisplay(
|
|
1061
|
+
priceDisplay: formatPriceDisplay({
|
|
1062
|
+
amount: result3.amount,
|
|
1063
|
+
then: thenDisplay3,
|
|
1064
|
+
actualAmount: result3.actualAmount,
|
|
1065
|
+
showThen: result3.showThen
|
|
1066
|
+
}, recurring, hasMetered, locale)
|
|
777
1067
|
};
|
|
778
1068
|
}
|
|
1069
|
+
const thenDisplay2 = hasMetered ? (0, _locales.t)("payment.checkout.meteredThen", locale, {
|
|
1070
|
+
recurring
|
|
1071
|
+
}) : recurring;
|
|
1072
|
+
const thenValue2 = hasMetered ? (0, _locales.t)("payment.checkout.metered", locale, {
|
|
1073
|
+
recurring
|
|
1074
|
+
}) : recurring;
|
|
779
1075
|
const result2 = {
|
|
780
1076
|
action: (0, _locales.t)("payment.checkout.sub1", locale, {
|
|
781
1077
|
name
|
|
782
1078
|
}),
|
|
783
1079
|
amount,
|
|
784
|
-
then:
|
|
785
|
-
|
|
786
|
-
}) : recurring,
|
|
1080
|
+
then: thenDisplay2,
|
|
1081
|
+
thenValue: thenValue2,
|
|
787
1082
|
showThen: hasMetered && !differentRecurring,
|
|
788
1083
|
actualAmount
|
|
789
1084
|
};
|
|
790
1085
|
return {
|
|
791
1086
|
...result2,
|
|
792
|
-
priceDisplay: formatPriceDisplay(
|
|
1087
|
+
priceDisplay: formatPriceDisplay({
|
|
1088
|
+
amount: result2.amount,
|
|
1089
|
+
then: thenDisplay2,
|
|
1090
|
+
actualAmount: result2.actualAmount,
|
|
1091
|
+
showThen: result2.showThen
|
|
1092
|
+
}, recurring, hasMetered, locale)
|
|
793
1093
|
};
|
|
794
1094
|
}
|
|
795
|
-
const subscription = (0, _util.fromUnitToToken)(items.filter(x => x.price
|
|
796
|
-
if (x.price
|
|
1095
|
+
const subscription = (0, _util.fromUnitToToken)(items.filter(x => x.price?.type === "recurring").reduce((acc, x) => {
|
|
1096
|
+
if (x.price?.recurring?.usage_type === "metered") {
|
|
797
1097
|
return acc;
|
|
798
1098
|
}
|
|
799
|
-
return acc.add(
|
|
1099
|
+
return acc.add(getLineItemAmounts(x, currency, {
|
|
1100
|
+
useUpsell: false,
|
|
1101
|
+
exchangeRate
|
|
1102
|
+
}).totalAmount);
|
|
800
1103
|
}, new _util.BN(0)), currency.decimal);
|
|
1104
|
+
const thenDisplay = formatMeteredThen(`${subscription} ${currency.symbol}`, recurring, hasMetered && Number(subscription) === 0, locale);
|
|
1105
|
+
const thenValue = formatThenValue(`${subscription} ${currency.symbol}`, recurring, hasMetered && Number(subscription) === 0, locale);
|
|
801
1106
|
const result = {
|
|
802
1107
|
action: (0, _locales.t)("payment.checkout.pay", locale, {
|
|
803
1108
|
payee: brand
|
|
804
1109
|
}),
|
|
805
1110
|
amount,
|
|
806
|
-
then:
|
|
1111
|
+
then: thenDisplay,
|
|
1112
|
+
thenValue,
|
|
807
1113
|
showThen: !differentRecurring,
|
|
808
1114
|
actualAmount
|
|
809
1115
|
};
|
|
810
1116
|
return {
|
|
811
1117
|
...result,
|
|
812
|
-
priceDisplay: formatPriceDisplay(
|
|
1118
|
+
priceDisplay: formatPriceDisplay({
|
|
1119
|
+
amount: result.amount,
|
|
1120
|
+
then: thenDisplay,
|
|
1121
|
+
actualAmount: result.actualAmount,
|
|
1122
|
+
showThen: result.showThen
|
|
1123
|
+
}, recurring, hasMetered, locale)
|
|
813
1124
|
};
|
|
814
1125
|
}
|
|
815
|
-
function formatAmount(amount, decimals) {
|
|
816
|
-
|
|
1126
|
+
function formatAmount(amount, decimals, precision = 2) {
|
|
1127
|
+
const tokenAmount = (0, _util.fromUnitToToken)(amount, decimals);
|
|
1128
|
+
const numericValue = Number(tokenAmount);
|
|
1129
|
+
if (!Number.isFinite(numericValue)) {
|
|
1130
|
+
return formatBNStr(amount, decimals, precision, true, false);
|
|
1131
|
+
}
|
|
1132
|
+
const abs = Math.abs(numericValue);
|
|
1133
|
+
const targetPrecision = abs > 0 && abs < 0.01 ? decimals : 2;
|
|
1134
|
+
return formatNumber(tokenAmount, targetPrecision, true, false);
|
|
817
1135
|
}
|
|
818
1136
|
function findCurrency(methods, currencyId) {
|
|
819
1137
|
for (const method of methods) {
|
|
@@ -1306,7 +1624,7 @@ function showStaking(method, currency, noStake) {
|
|
|
1306
1624
|
if (noStake) {
|
|
1307
1625
|
return false;
|
|
1308
1626
|
}
|
|
1309
|
-
if (method.type === "arcblock") {
|
|
1627
|
+
if (method && method.type === "arcblock") {
|
|
1310
1628
|
return currency.type !== "credit";
|
|
1311
1629
|
}
|
|
1312
1630
|
return false;
|