@blocklet/payment-react 1.19.0 → 1.19.2

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.
Files changed (75) hide show
  1. package/es/components/blockchain/tx.d.ts +1 -1
  2. package/es/components/blockchain/tx.js +9 -11
  3. package/es/components/country-select.d.ts +1 -1
  4. package/es/components/date-range-picker.d.ts +13 -0
  5. package/es/components/date-range-picker.js +279 -0
  6. package/es/components/input.d.ts +5 -2
  7. package/es/components/input.js +6 -2
  8. package/es/components/label.d.ts +7 -0
  9. package/es/components/label.js +50 -0
  10. package/es/components/loading-button.d.ts +1 -1
  11. package/es/history/credit/grants-list.d.ts +14 -0
  12. package/es/history/credit/grants-list.js +215 -0
  13. package/es/history/credit/transactions-list.d.ts +13 -0
  14. package/es/history/credit/transactions-list.js +254 -0
  15. package/es/history/invoice/list.js +21 -1
  16. package/es/index.d.ts +5 -1
  17. package/es/index.js +10 -1
  18. package/es/libs/util.d.ts +2 -0
  19. package/es/libs/util.js +12 -0
  20. package/es/locales/en.js +20 -2
  21. package/es/locales/zh.js +20 -2
  22. package/es/payment/form/address.js +2 -1
  23. package/es/payment/form/index.js +46 -7
  24. package/es/payment/index.js +18 -3
  25. package/es/payment/product-item.d.ts +8 -1
  26. package/es/payment/product-item.js +137 -5
  27. package/es/payment/summary.d.ts +3 -1
  28. package/es/payment/summary.js +9 -0
  29. package/lib/components/blockchain/tx.d.ts +1 -1
  30. package/lib/components/blockchain/tx.js +9 -8
  31. package/lib/components/country-select.d.ts +1 -1
  32. package/lib/components/date-range-picker.d.ts +13 -0
  33. package/lib/components/date-range-picker.js +329 -0
  34. package/lib/components/input.d.ts +5 -2
  35. package/lib/components/input.js +8 -4
  36. package/lib/components/label.d.ts +7 -0
  37. package/lib/components/label.js +62 -0
  38. package/lib/components/loading-button.d.ts +1 -1
  39. package/lib/history/credit/grants-list.d.ts +14 -0
  40. package/lib/history/credit/grants-list.js +277 -0
  41. package/lib/history/credit/transactions-list.d.ts +13 -0
  42. package/lib/history/credit/transactions-list.js +300 -0
  43. package/lib/history/invoice/list.js +24 -0
  44. package/lib/index.d.ts +5 -1
  45. package/lib/index.js +39 -0
  46. package/lib/libs/util.d.ts +2 -0
  47. package/lib/libs/util.js +14 -0
  48. package/lib/locales/en.js +20 -2
  49. package/lib/locales/zh.js +20 -2
  50. package/lib/payment/form/address.js +6 -5
  51. package/lib/payment/form/index.js +49 -9
  52. package/lib/payment/index.js +20 -2
  53. package/lib/payment/product-item.d.ts +8 -1
  54. package/lib/payment/product-item.js +144 -4
  55. package/lib/payment/summary.d.ts +3 -1
  56. package/lib/payment/summary.js +9 -0
  57. package/package.json +3 -3
  58. package/src/components/blockchain/tx.tsx +9 -15
  59. package/src/components/country-select.tsx +2 -2
  60. package/src/components/date-range-picker.tsx +310 -0
  61. package/src/components/input.tsx +14 -3
  62. package/src/components/label.tsx +59 -0
  63. package/src/components/loading-button.tsx +1 -1
  64. package/src/history/credit/grants-list.tsx +276 -0
  65. package/src/history/credit/transactions-list.tsx +316 -0
  66. package/src/history/invoice/list.tsx +18 -1
  67. package/src/index.ts +9 -0
  68. package/src/libs/util.ts +14 -0
  69. package/src/locales/en.tsx +20 -0
  70. package/src/locales/zh.tsx +19 -0
  71. package/src/payment/form/address.tsx +4 -3
  72. package/src/payment/form/index.tsx +112 -53
  73. package/src/payment/index.tsx +17 -1
  74. package/src/payment/product-item.tsx +152 -4
  75. package/src/payment/summary.tsx +13 -2
@@ -8,7 +8,7 @@ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
8
8
  import Toast from '@arcblock/ux/lib/Toast';
9
9
  import type { Paginated, TInvoiceExpanded, TSubscription } from '@blocklet/payment-types';
10
10
  import { OpenInNewOutlined } from '@mui/icons-material';
11
- import { Box, Button, CircularProgress, Stack, Typography, Tooltip } from '@mui/material';
11
+ import { Box, Button, CircularProgress, Stack, Typography, Tooltip, Avatar } from '@mui/material';
12
12
  import { styled } from '@mui/system';
13
13
  import { useInfiniteScroll, useRequest, useSetState } from 'ahooks';
14
14
  import React, { useEffect, useRef, useState } from 'react';
@@ -207,6 +207,23 @@ const InvoiceTable = React.memo((props: Props & { onPay: (invoiceId: string) =>
207
207
  },
208
208
  },
209
209
  },
210
+ {
211
+ label: t('common.paymentMethod'),
212
+ name: 'paymentMethod',
213
+ options: {
214
+ customBodyRenderLite: (_: string, index: number) => {
215
+ const invoice = data?.list[index] as TInvoiceExpanded;
216
+ return (
217
+ <Typography
218
+ sx={{ display: 'flex', alignItems: 'center', whiteSpace: 'nowrap' }}
219
+ onClick={(e) => handleLinkClick(e, invoice)}>
220
+ <Avatar src={invoice.paymentMethod.logo} sx={{ width: 18, height: 18, mr: 1 }} />
221
+ {invoice.paymentMethod.name}
222
+ </Typography>
223
+ );
224
+ },
225
+ },
226
+ },
210
227
  {
211
228
  label: t('common.type'),
212
229
  name: 'billing_reason',
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ import TxGas from './components/blockchain/gas';
5
5
  import TxLink from './components/blockchain/tx';
6
6
  import ConfirmDialog from './components/confirm';
7
7
  import FormInput from './components/input';
8
+ import FormLabel from './components/label';
8
9
  import Livemode from './components/livemode';
9
10
  import PricingTable from './components/pricing-table';
10
11
  import Table from './components/table';
@@ -13,6 +14,8 @@ import Status from './components/status';
13
14
  import Switch from './components/switch-button';
14
15
  import CustomerInvoiceList from './history/invoice/list';
15
16
  import CustomerPaymentList from './history/payment/list';
17
+ import CreditGrantsList, { StatusChip as CreditStatusChip } from './history/credit/grants-list';
18
+ import CreditTransactionsList from './history/credit/transactions-list';
16
19
  import api from './libs/api';
17
20
  import dayjs from './libs/dayjs';
18
21
  import Amount from './payment/amount';
@@ -32,6 +35,7 @@ import OverdueInvoicePayment from './components/over-due-invoice-payment';
32
35
  import PaymentBeneficiaries from './components/payment-beneficiaries';
33
36
  import LoadingButton from './components/loading-button';
34
37
  import ResumeSubscription from './components/resume-subscription';
38
+ import DateRangePicker from './components/date-range-picker';
35
39
 
36
40
  export { PaymentThemeProvider } from './theme';
37
41
 
@@ -55,6 +59,7 @@ export {
55
59
  api,
56
60
  dayjs,
57
61
  FormInput,
62
+ FormLabel,
58
63
  PhoneInput,
59
64
  AddressForm,
60
65
  StripeForm,
@@ -86,4 +91,8 @@ export {
86
91
  LoadingButton,
87
92
  DonateDetails,
88
93
  ResumeSubscription,
94
+ CreditGrantsList,
95
+ CreditTransactionsList,
96
+ DateRangePicker,
97
+ CreditStatusChip,
89
98
  };
package/src/libs/util.ts CHANGED
@@ -1283,3 +1283,17 @@ export function getTokenBalanceLink(method: TPaymentMethod, address: string) {
1283
1283
  }
1284
1284
  return '';
1285
1285
  }
1286
+
1287
+ export function isCreditMetered(price: TPrice): boolean {
1288
+ return !!(price.type === 'recurring' && price.recurring?.usage_type === 'metered' && price.recurring?.meter_id);
1289
+ }
1290
+
1291
+ export function showStaking(method: TPaymentMethod, currency: TPaymentCurrency, noStake: boolean) {
1292
+ if (noStake) {
1293
+ return false;
1294
+ }
1295
+ if (method.type === 'arcblock') {
1296
+ return currency.type !== 'credit';
1297
+ }
1298
+ return true;
1299
+ }
@@ -30,6 +30,10 @@ export default flat({
30
30
  remove: 'Remove',
31
31
  removed: 'Resource removed',
32
32
  confirm: 'Confirm',
33
+ clear: 'Clear',
34
+ selectTimeRange: 'Select time range',
35
+ startDate: 'Start date',
36
+ endDate: 'End date',
33
37
  upload: 'Upload',
34
38
  change: 'Change',
35
39
  cancel: 'Cancel',
@@ -103,6 +107,7 @@ export default flat({
103
107
  confirm: 'Confirm',
104
108
  cancel: 'Cancel',
105
109
  },
110
+ paymentMethod: 'Payment Method',
106
111
  },
107
112
  payment: {
108
113
  checkout: {
@@ -209,6 +214,11 @@ export default flat({
209
214
  add: 'Add to order',
210
215
  remove: 'Remove from order',
211
216
  },
217
+ credit: {
218
+ oneTimeInfo: 'You will receive {amount} {symbol} credits after payment',
219
+ recurringInfo: 'You will receive {amount} {symbol} credits {period}',
220
+ expiresIn: 'credits have a validity period of {duration} {unit}',
221
+ },
212
222
  expired: {
213
223
  title: 'Expired Link',
214
224
  description:
@@ -241,6 +251,16 @@ export default flat({
241
251
  amount: 'Amount',
242
252
  failed: 'Account changed, please pay manually.',
243
253
  balanceLink: 'View Balance',
254
+ credit: {
255
+ title: 'Confirm Credit Payment',
256
+ availableAmount: 'Available Credit: {amount}',
257
+ confirmMessage: 'You will use {amount} credits to subscribe to this service.',
258
+ meteringSubscriptionMessage:
259
+ 'This subscription service will deduct credits in real-time based on actual usage. You currently have {available} credits available. Confirm to continue?',
260
+ insufficientTitle: 'Insufficient Credit',
261
+ insufficientMessage:
262
+ 'This subscription service will deduct credits in real-time based on actual usage. You currently have insufficient credits. Please top up your credits first.',
263
+ },
244
264
  },
245
265
  },
246
266
  customer: {
@@ -33,6 +33,10 @@ export default flat({
33
33
  change: '更换',
34
34
  confirm: '确认',
35
35
  cancel: '取消',
36
+ clear: '清空',
37
+ selectTimeRange: '选择时间范围',
38
+ startDate: '开始日期',
39
+ endDate: '结束日期',
36
40
  close: '关闭',
37
41
  back: '返回',
38
42
  every: '每',
@@ -103,6 +107,7 @@ export default flat({
103
107
  confirm: '确认',
104
108
  cancel: '取消',
105
109
  },
110
+ paymentMethod: '支付方式',
106
111
  },
107
112
  payment: {
108
113
  checkout: {
@@ -215,6 +220,11 @@ export default flat({
215
220
  add: '添加到订单',
216
221
  remove: '从订单移除',
217
222
  },
223
+ credit: {
224
+ oneTimeInfo: '付款完成后您将获得 {amount} {symbol} 额度',
225
+ recurringInfo: '您将{period}获得 {amount} {symbol} 额度',
226
+ expiresIn: '额度有效期为 {duration} {unit}',
227
+ },
218
228
  emptyItems: {
219
229
  title: '没有任何购买项目',
220
230
  description: '可能这个付款链接没有正确配置',
@@ -236,6 +246,15 @@ export default flat({
236
246
  amount: '支付金额',
237
247
  failed: '账户发生变化,无法自动完成支付,请手动支付。',
238
248
  balanceLink: '查看余额',
249
+ credit: {
250
+ title: '确认额度支付',
251
+ availableAmount: '可用额度:{amount}',
252
+ confirmMessage: '您将使用 {amount} 额度来订阅此服务。',
253
+ meteringSubscriptionMessage:
254
+ '此订阅服务将根据实际使用情况实时扣除额度。您当前可用额度为 {available},确认是否继续?',
255
+ insufficientTitle: '额度不足',
256
+ insufficientMessage: '此订阅服务将根据实际使用情况实时扣除额度。您当前可用额度不足,请先充值额度。',
257
+ },
239
258
  },
240
259
  },
241
260
  customer: {
@@ -1,8 +1,9 @@
1
1
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
2
- import { Fade, FormLabel, InputAdornment, Stack } from '@mui/material';
2
+ import { Fade, InputAdornment, Stack } from '@mui/material';
3
3
  import type { SxProps } from '@mui/material';
4
4
  import { Controller, useFormContext, useWatch } from 'react-hook-form';
5
5
  import FormInput from '../../components/input';
6
+ import FormLabel from '../../components/label';
6
7
  import CountrySelect from '../../components/country-select';
7
8
  import { getFieldValidation, validatePostalCode } from '../../libs/validator';
8
9
 
@@ -79,7 +80,7 @@ export default function AddressForm({ mode, stripe, sx = {}, fieldValidation = {
79
80
  render={({ field }) => (
80
81
  <CountrySelect
81
82
  {...field}
82
- ref={field.ref as unknown as React.RefObject<HTMLDivElement>}
83
+ ref={field.ref as unknown as React.RefObject<HTMLDivElement | null>}
83
84
  sx={{
84
85
  '&.Mui-focused .MuiOutlinedInput-notchedOutline': {
85
86
  borderColor: 'transparent',
@@ -127,7 +128,7 @@ export default function AddressForm({ mode, stripe, sx = {}, fieldValidation = {
127
128
  render={({ field }) => (
128
129
  <CountrySelect
129
130
  {...field}
130
- ref={field.ref as unknown as React.RefObject<HTMLDivElement>}
131
+ ref={field.ref as unknown as React.RefObject<HTMLDivElement | null>}
131
132
  sx={{
132
133
  '.MuiOutlinedInput-notchedOutline': {
133
134
  borderColor: 'transparent !important',
@@ -5,7 +5,7 @@ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
5
5
  // import { useTheme } from '@arcblock/ux/lib/Theme';
6
6
  import Toast from '@arcblock/ux/lib/Toast';
7
7
  import type { TCheckoutSession, TCustomer, TPaymentIntent, TPaymentMethodExpanded } from '@blocklet/payment-types';
8
- import { Box, Button, CircularProgress, Divider, Fade, FormLabel, Stack, Tooltip, Typography } from '@mui/material';
8
+ import { Box, Button, CircularProgress, Divider, Fade, Stack, Tooltip, Typography } from '@mui/material';
9
9
  import { useMemoizedFn, useSetState } from 'ahooks';
10
10
  import pWaitFor from 'p-wait-for';
11
11
  import { useEffect, useMemo, useRef } from 'react';
@@ -19,6 +19,7 @@ import DID from '@arcblock/ux/lib/DID';
19
19
  import isEmpty from 'lodash/isEmpty';
20
20
  import { HelpOutline, OpenInNew } from '@mui/icons-material';
21
21
  import FormInput from '../../components/input';
22
+ import FormLabel from '../../components/label';
22
23
  import { usePaymentContext } from '../../contexts/payment';
23
24
  import { useSubscription } from '../../hooks/subscription';
24
25
  import api from '../../libs/api';
@@ -110,9 +111,11 @@ type UserInfo = {
110
111
  type FastCheckoutInfo = {
111
112
  open: boolean;
112
113
  loading: boolean;
113
- sourceType: 'balance' | 'delegation';
114
+ sourceType: 'balance' | 'delegation' | 'credit';
114
115
  amount: string;
115
116
  payer?: string;
117
+ availableCredit?: string;
118
+ balance?: string;
116
119
  };
117
120
 
118
121
  const setUserFormValues = (
@@ -206,6 +209,9 @@ export default function PaymentForm({
206
209
  customerLimited?: boolean;
207
210
  stripePaying: boolean;
208
211
  fastCheckoutInfo: FastCheckoutInfo | null;
212
+ creditInsufficientInfo: {
213
+ open: boolean;
214
+ } | null;
209
215
  }>({
210
216
  submitting: false,
211
217
  paying: false,
@@ -216,6 +222,7 @@ export default function PaymentForm({
216
222
  customerLimited: false,
217
223
  stripePaying: false,
218
224
  fastCheckoutInfo: null,
225
+ creditInsufficientInfo: null,
219
226
  });
220
227
 
221
228
  const currencies = flattenPaymentMethods(paymentMethods);
@@ -418,6 +425,10 @@ export default function PaymentForm({
418
425
  setState({ fastCheckoutInfo: null });
419
426
  };
420
427
 
428
+ const handleCreditInsufficientClose = () => {
429
+ setState({ creditInsufficientInfo: null });
430
+ };
431
+
421
432
  const openConnect = () => {
422
433
  try {
423
434
  if (!['arcblock', 'ethereum', 'base'].includes(method.type)) {
@@ -476,7 +487,30 @@ export default function PaymentForm({
476
487
  });
477
488
 
478
489
  if (['arcblock', 'ethereum', 'base'].includes(method.type)) {
479
- if (
490
+ // 优先判断 credit 支付
491
+ if (paymentCurrency?.type === 'credit') {
492
+ if (result.data.creditSufficient === true) {
493
+ // 如果是 credit 支付且有足够额度,显示 credit 确认弹窗
494
+ setState({
495
+ fastCheckoutInfo: {
496
+ open: true,
497
+ loading: false,
498
+ sourceType: 'credit',
499
+ amount: result.data.fastPayInfo?.amount || '0',
500
+ payer: result.data.fastPayInfo?.payer,
501
+ availableCredit: result.data.fastPayInfo?.amount || '0',
502
+ balance: result.data.fastPayInfo?.token?.balance || '0',
503
+ },
504
+ });
505
+ } else {
506
+ // 如果是 credit 支付但额度不足,显示额度不足弹窗
507
+ setState({
508
+ creditInsufficientInfo: {
509
+ open: true,
510
+ },
511
+ });
512
+ }
513
+ } else if (
480
514
  (result.data.balance?.sufficient || result.data.delegation?.sufficient) &&
481
515
  !isDonationMode &&
482
516
  result.data.fastPayInfo
@@ -581,73 +615,96 @@ export default function PaymentForm({
581
615
  }, [state.submitting, state.paying, state.stripePaying, quantityInventoryStatus, payable]); // eslint-disable-line react-hooks/exhaustive-deps
582
616
 
583
617
  const balanceLink = getTokenBalanceLink(method, state.fastCheckoutInfo?.payer || '');
618
+
584
619
  const FastCheckoutConfirmDialog = state.fastCheckoutInfo && (
585
620
  <ConfirmDialog
586
621
  onConfirm={handleFastCheckoutConfirm}
587
622
  onCancel={handleFastCheckoutCancel}
588
- title={t('payment.checkout.fastPay.title')}
623
+ title={
624
+ state.fastCheckoutInfo.sourceType === 'credit'
625
+ ? t('payment.checkout.fastPay.credit.title')
626
+ : t('payment.checkout.fastPay.title')
627
+ }
589
628
  message={
590
- <Stack>
591
- <Typography>{t('payment.checkout.fastPay.autoPaymentReason')}</Typography>
592
- <Divider sx={{ mt: 1.5, mb: 1.5 }} />
593
- <Stack spacing={1}>
594
- <Stack
595
- sx={{
596
- flexDirection: 'row',
597
- alignItems: 'center',
598
- justifyContent: 'space-between',
599
- }}>
600
- <Typography
629
+ state.fastCheckoutInfo.sourceType === 'credit' ? (
630
+ <Typography>
631
+ {t('payment.checkout.fastPay.credit.meteringSubscriptionMessage', {
632
+ available: `${fromUnitToToken(state.fastCheckoutInfo?.balance || '0', paymentCurrency?.decimal || 18).toString()} ${paymentCurrency?.symbol}`,
633
+ })}
634
+ </Typography>
635
+ ) : (
636
+ <Stack>
637
+ <Typography>{t('payment.checkout.fastPay.autoPaymentReason')}</Typography>
638
+ <Divider sx={{ mt: 1.5, mb: 1.5 }} />
639
+ <Stack spacing={1}>
640
+ <Stack
601
641
  sx={{
602
- color: 'text.primary',
603
- whiteSpace: 'nowrap',
642
+ flexDirection: 'row',
643
+ alignItems: 'center',
644
+ justifyContent: 'space-between',
604
645
  }}>
605
- {t('payment.checkout.fastPay.payer')}
606
- </Typography>
607
- <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
608
- <DID did={state.fastCheckoutInfo.payer || ''} compact responsive={false} />
609
- {balanceLink && (
610
- <Tooltip title={t('payment.checkout.fastPay.balanceLink')} placement="top">
611
- <OpenInNew
612
- sx={{
613
- color: 'text.lighter',
614
- fontSize: '0.85rem',
615
- cursor: 'pointer',
616
- '&:hover': { color: 'text.primary' },
617
- }}
618
- onClick={() => {
619
- window.open(balanceLink, '_blank');
620
- }}
621
- />
622
- </Tooltip>
623
- )}
624
- </Box>
625
- </Stack>
626
- <Stack
627
- sx={{
628
- flexDirection: 'row',
629
- alignItems: 'center',
630
- justifyContent: 'space-between',
631
- }}>
632
- <Typography
646
+ <Typography
647
+ sx={{
648
+ color: 'text.primary',
649
+ whiteSpace: 'nowrap',
650
+ }}>
651
+ {t('payment.checkout.fastPay.payer')}
652
+ </Typography>
653
+ <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
654
+ <DID did={state.fastCheckoutInfo.payer || ''} compact responsive={false} />
655
+ {balanceLink && (
656
+ <Tooltip title={t('payment.checkout.fastPay.balanceLink')} placement="top">
657
+ <OpenInNew
658
+ sx={{
659
+ color: 'text.lighter',
660
+ fontSize: '0.85rem',
661
+ cursor: 'pointer',
662
+ '&:hover': { color: 'text.primary' },
663
+ }}
664
+ onClick={() => {
665
+ window.open(balanceLink, '_blank');
666
+ }}
667
+ />
668
+ </Tooltip>
669
+ )}
670
+ </Box>
671
+ </Stack>
672
+ <Stack
633
673
  sx={{
634
- color: 'text.primary',
674
+ flexDirection: 'row',
675
+ alignItems: 'center',
676
+ justifyContent: 'space-between',
635
677
  }}>
636
- {t('payment.checkout.fastPay.amount')}
637
- </Typography>
638
- <Typography>
639
- {fromUnitToToken(state.fastCheckoutInfo.amount, paymentCurrency?.decimal || 18).toString()}{' '}
640
- {paymentCurrency?.symbol}
641
- </Typography>
678
+ <Typography
679
+ sx={{
680
+ color: 'text.primary',
681
+ }}>
682
+ {t('payment.checkout.fastPay.amount')}
683
+ </Typography>
684
+ <Typography>
685
+ {fromUnitToToken(state.fastCheckoutInfo.amount, paymentCurrency?.decimal || 18).toString()}{' '}
686
+ {paymentCurrency?.symbol}
687
+ </Typography>
688
+ </Stack>
642
689
  </Stack>
643
690
  </Stack>
644
- </Stack>
691
+ )
645
692
  }
646
693
  loading={state.fastCheckoutInfo.loading}
647
694
  color="primary"
648
695
  />
649
696
  );
650
697
 
698
+ const CreditInsufficientDialog = state.creditInsufficientInfo && (
699
+ <ConfirmDialog
700
+ onConfirm={handleCreditInsufficientClose}
701
+ onCancel={handleCreditInsufficientClose}
702
+ title={t('payment.checkout.fastPay.credit.insufficientTitle')}
703
+ message={<Typography>{t('payment.checkout.fastPay.credit.insufficientMessage')}</Typography>}
704
+ confirm={t('common.confirm')}
705
+ />
706
+ );
707
+
651
708
  if (onlyShowBtn) {
652
709
  return (
653
710
  <>
@@ -700,6 +757,7 @@ export default function PaymentForm({
700
757
  />
701
758
  )}
702
759
  {FastCheckoutConfirmDialog}
760
+ {CreditInsufficientDialog}
703
761
  </>
704
762
  );
705
763
  }
@@ -890,6 +948,7 @@ export default function PaymentForm({
890
948
  />
891
949
  )}
892
950
  {FastCheckoutConfirmDialog}
951
+ {CreditInsufficientDialog}
893
952
  </>
894
953
  );
895
954
  }
@@ -30,6 +30,7 @@ import {
30
30
  getStatementDescriptor,
31
31
  isMobileSafari,
32
32
  isValidCountry,
33
+ showStaking,
33
34
  } from '../libs/util';
34
35
  import type { CheckoutCallbacks, CheckoutContext, CheckoutFormData } from '../types';
35
36
  import PaymentError from './error';
@@ -208,6 +209,19 @@ function PaymentInner({
208
209
  }
209
210
  };
210
211
 
212
+ const onQuantityChange = async (itemId: string, quantity: number) => {
213
+ try {
214
+ const { data } = await api.put(`/api/checkout-sessions/${state.checkoutSession.id}/adjust-quantity`, {
215
+ itemId,
216
+ quantity,
217
+ });
218
+ setState({ checkoutSession: data });
219
+ } catch (err) {
220
+ console.error(err);
221
+ Toast.error(formatError(err));
222
+ }
223
+ };
224
+
211
225
  const onCancelCrossSell = async () => {
212
226
  try {
213
227
  const { data } = await api.delete(`/api/checkout-sessions/${state.checkoutSession.id}/cross-sell`);
@@ -263,10 +277,11 @@ function PaymentInner({
263
277
  // @ts-ignore
264
278
  state.checkoutSession.subscription_data?.min_stake_amount || 0
265
279
  )}
266
- showStaking={method.type === 'arcblock' && !state.checkoutSession.subscription_data?.no_stake}
280
+ showStaking={showStaking(method, currency, !!state.checkoutSession.subscription_data?.no_stake)}
267
281
  currency={currency}
268
282
  onUpsell={onUpsell}
269
283
  onDownsell={onDownsell}
284
+ onQuantityChange={onQuantityChange}
270
285
  onApplyCrossSell={onApplyCrossSell}
271
286
  onCancelCrossSell={onCancelCrossSell}
272
287
  onChangeAmount={onChangeAmount}
@@ -274,6 +289,7 @@ function PaymentInner({
274
289
  crossSellBehavior={state.checkoutSession.cross_sell_behavior}
275
290
  donationSettings={paymentLink?.donation_settings}
276
291
  action={action}
292
+ completed={completed}
277
293
  />
278
294
  {mode === 'standalone' && !isMobile && (
279
295
  <CheckoutFooter className="cko-footer" sx={{ color: 'text.lighter' }} />