payment-kit 1.21.16 → 1.22.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.
Files changed (65) hide show
  1. package/api/src/index.ts +3 -1
  2. package/api/src/integrations/blocklet/user.ts +2 -2
  3. package/api/src/integrations/ethereum/token.ts +4 -5
  4. package/api/src/integrations/stripe/handlers/invoice.ts +31 -26
  5. package/api/src/integrations/stripe/handlers/payment-intent.ts +1 -1
  6. package/api/src/integrations/stripe/handlers/setup-intent.ts +231 -0
  7. package/api/src/integrations/stripe/handlers/subscription.ts +31 -9
  8. package/api/src/integrations/stripe/resource.ts +30 -1
  9. package/api/src/integrations/stripe/setup.ts +1 -1
  10. package/api/src/libs/auth.ts +7 -6
  11. package/api/src/libs/env.ts +1 -1
  12. package/api/src/libs/notification/template/subscription-trial-will-end.ts +1 -0
  13. package/api/src/libs/notification/template/subscription-will-renew.ts +1 -1
  14. package/api/src/libs/payment.ts +11 -6
  15. package/api/src/libs/refund.ts +1 -1
  16. package/api/src/libs/remote-signer.ts +93 -0
  17. package/api/src/libs/security.ts +1 -1
  18. package/api/src/libs/subscription.ts +4 -7
  19. package/api/src/libs/util.ts +18 -1
  20. package/api/src/libs/vendor-util/adapters/didnames-adapter.ts +17 -9
  21. package/api/src/libs/vendor-util/adapters/launcher-adapter.ts +11 -6
  22. package/api/src/queues/payment.ts +2 -2
  23. package/api/src/queues/payout.ts +1 -1
  24. package/api/src/queues/refund.ts +2 -2
  25. package/api/src/queues/subscription.ts +1 -1
  26. package/api/src/queues/usage-record.ts +1 -1
  27. package/api/src/queues/vendors/status-check.ts +1 -1
  28. package/api/src/queues/webhook.ts +1 -1
  29. package/api/src/routes/auto-recharge-configs.ts +1 -1
  30. package/api/src/routes/checkout-sessions.ts +4 -6
  31. package/api/src/routes/connect/change-payer.ts +148 -0
  32. package/api/src/routes/connect/collect-batch.ts +1 -1
  33. package/api/src/routes/connect/collect.ts +1 -1
  34. package/api/src/routes/connect/pay.ts +1 -1
  35. package/api/src/routes/connect/recharge-account.ts +1 -1
  36. package/api/src/routes/connect/recharge.ts +1 -1
  37. package/api/src/routes/connect/shared.ts +62 -23
  38. package/api/src/routes/customers.ts +1 -1
  39. package/api/src/routes/integrations/stripe.ts +1 -1
  40. package/api/src/routes/invoices.ts +141 -2
  41. package/api/src/routes/meter-events.ts +9 -12
  42. package/api/src/routes/payment-currencies.ts +1 -1
  43. package/api/src/routes/payment-intents.ts +2 -2
  44. package/api/src/routes/payment-links.ts +2 -1
  45. package/api/src/routes/payouts.ts +1 -1
  46. package/api/src/routes/products.ts +1 -0
  47. package/api/src/routes/subscriptions.ts +130 -3
  48. package/api/src/store/models/types.ts +1 -1
  49. package/api/tests/setup.ts +11 -0
  50. package/api/third.d.ts +0 -2
  51. package/blocklet.yml +1 -1
  52. package/jest.config.js +2 -2
  53. package/package.json +26 -26
  54. package/src/components/invoice/table.tsx +2 -2
  55. package/src/components/invoice-pdf/template.tsx +30 -0
  56. package/src/components/subscription/payment-method-info.tsx +222 -0
  57. package/src/global.css +4 -0
  58. package/src/libs/util.ts +1 -1
  59. package/src/locales/en.tsx +13 -0
  60. package/src/locales/zh.tsx +13 -0
  61. package/src/pages/admin/billing/invoices/detail.tsx +5 -3
  62. package/src/pages/admin/billing/subscriptions/detail.tsx +16 -0
  63. package/src/pages/admin/overview.tsx +14 -14
  64. package/src/pages/customer/invoice/detail.tsx +59 -17
  65. package/src/pages/customer/subscription/detail.tsx +21 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payment-kit",
3
- "version": "1.21.16",
3
+ "version": "1.22.0",
4
4
  "scripts": {
5
5
  "dev": "blocklet dev --open",
6
6
  "lint": "tsc --noEmit && eslint src api/src --ext .mjs,.js,.jsx,.ts,.tsx",
@@ -44,34 +44,34 @@
44
44
  ]
45
45
  },
46
46
  "dependencies": {
47
- "@abtnode/cron": "^1.16.53-beta-20251011-054719-4ed2f6b7",
48
- "@arcblock/did": "^1.25.6",
49
- "@arcblock/did-connect-react": "^3.1.46",
47
+ "@abtnode/cron": "^1.16.54-beta-20251028-092308-569763e6",
48
+ "@arcblock/did": "^1.26.3",
49
+ "@arcblock/did-connect-react": "^3.1.52",
50
50
  "@arcblock/did-connect-storage-nedb": "^1.8.0",
51
- "@arcblock/did-util": "^1.25.6",
52
- "@arcblock/jwt": "^1.25.6",
53
- "@arcblock/ux": "^3.1.46",
54
- "@arcblock/validator": "^1.25.6",
55
- "@blocklet/did-space-js": "^1.1.32",
51
+ "@arcblock/did-util": "^1.26.3",
52
+ "@arcblock/jwt": "^1.26.3",
53
+ "@arcblock/ux": "^3.1.52",
54
+ "@arcblock/validator": "^1.26.3",
55
+ "@blocklet/did-space-js": "^1.1.35",
56
56
  "@blocklet/error": "^0.2.5",
57
- "@blocklet/js-sdk": "^1.16.53-beta-20251011-054719-4ed2f6b7",
58
- "@blocklet/logger": "^1.16.53-beta-20251011-054719-4ed2f6b7",
59
- "@blocklet/payment-broker-client": "1.21.16",
60
- "@blocklet/payment-react": "1.21.16",
61
- "@blocklet/payment-vendor": "1.21.16",
62
- "@blocklet/sdk": "^1.16.53-beta-20251011-054719-4ed2f6b7",
63
- "@blocklet/ui-react": "^3.1.46",
64
- "@blocklet/uploader": "^0.2.15",
65
- "@blocklet/xss": "^0.2.12",
57
+ "@blocklet/js-sdk": "^1.16.54-beta-20251028-092308-569763e6",
58
+ "@blocklet/logger": "^1.16.54-beta-20251028-092308-569763e6",
59
+ "@blocklet/payment-broker-client": "1.22.0",
60
+ "@blocklet/payment-react": "1.22.0",
61
+ "@blocklet/payment-vendor": "1.22.0",
62
+ "@blocklet/sdk": "^1.16.54-beta-20251028-092308-569763e6",
63
+ "@blocklet/ui-react": "^3.1.52",
64
+ "@blocklet/uploader": "^0.3.1",
65
+ "@blocklet/xss": "^0.3.1",
66
66
  "@mui/icons-material": "^7.1.2",
67
67
  "@mui/lab": "7.0.0-beta.14",
68
68
  "@mui/material": "^7.1.2",
69
69
  "@mui/system": "^7.1.1",
70
- "@ocap/asset": "^1.25.6",
71
- "@ocap/client": "^1.25.6",
72
- "@ocap/mcrypto": "^1.25.6",
73
- "@ocap/util": "^1.25.6",
74
- "@ocap/wallet": "^1.25.6",
70
+ "@ocap/asset": "^1.26.3",
71
+ "@ocap/client": "^1.26.3",
72
+ "@ocap/mcrypto": "^1.26.3",
73
+ "@ocap/util": "^1.26.3",
74
+ "@ocap/wallet": "^1.26.3",
75
75
  "@stripe/react-stripe-js": "^2.9.0",
76
76
  "@stripe/stripe-js": "^2.4.0",
77
77
  "ahooks": "^3.8.5",
@@ -126,9 +126,9 @@
126
126
  "web3": "^4.16.0"
127
127
  },
128
128
  "devDependencies": {
129
- "@abtnode/types": "^1.16.53-beta-20251011-054719-4ed2f6b7",
129
+ "@abtnode/types": "^1.16.54-beta-20251028-092308-569763e6",
130
130
  "@arcblock/eslint-config-ts": "^0.3.3",
131
- "@blocklet/payment-types": "1.21.16",
131
+ "@blocklet/payment-types": "1.22.0",
132
132
  "@types/cookie-parser": "^1.4.9",
133
133
  "@types/cors": "^2.8.19",
134
134
  "@types/debug": "^4.1.12",
@@ -175,5 +175,5 @@
175
175
  "parser": "typescript"
176
176
  }
177
177
  },
178
- "gitHead": "16509d9abd2da2f52587972c863c79ba9e4cd49d"
178
+ "gitHead": "d69619c7d669bc6de8620273ff0f3f7b5d56383f"
179
179
  }
@@ -56,9 +56,9 @@ export function getAppliedBalance(invoice: TInvoiceExpanded) {
56
56
  invoice.ending_token_balance &&
57
57
  invoice.ending_token_balance[invoice.paymentCurrency.id]
58
58
  ) {
59
- const starting = toBN(invoice.starting_token_balance[invoice.paymentCurrency.id]);
59
+ const starting = toBN(invoice.starting_token_balance[invoice.paymentCurrency.id] || '0');
60
60
 
61
- const ending = toBN(invoice.ending_token_balance[invoice.paymentCurrency.id]);
61
+ const ending = toBN(invoice.ending_token_balance[invoice.paymentCurrency.id] || '0');
62
62
  return ending.sub(starting).toString();
63
63
  }
64
64
 
@@ -65,6 +65,16 @@ export function InvoiceTemplate({ data, t }: InvoicePDFProps) {
65
65
  <span style={composeStyles('gray')}>{formatTime(data.period_end * 1000)}</span>
66
66
  </div>
67
67
  </div>
68
+ <div style={composeStyles('flex mb-5')}>
69
+ <div style={composeStyles('w-40')}>
70
+ <span style={composeStyles('bold')}>{t('admin.paymentCurrency.name')}</span>
71
+ </div>
72
+ <div style={composeStyles('w-60')}>
73
+ <span style={composeStyles('gray')}>
74
+ {data.paymentCurrency.symbol} ({data.paymentMethod.name})
75
+ </span>
76
+ </div>
77
+ </div>
68
78
  </div>
69
79
  </div>
70
80
 
@@ -137,6 +147,26 @@ export function InvoiceTemplate({ data, t }: InvoicePDFProps) {
137
147
  );
138
148
  })}
139
149
 
150
+ {detail.length === 0 && (
151
+ <div style={composeStyles('row flex')}>
152
+ <div style={composeStyles('w-38 p-4-8 pb-15')}>
153
+ <span style={composeStyles('gray')}>-</span>
154
+ </div>
155
+ <div style={composeStyles('w-15 p-4-8 pb-15')}>
156
+ <span style={composeStyles('gray right')}>-</span>
157
+ </div>
158
+ <div style={composeStyles('w-15 p-4-8 pb-15')}>
159
+ <span style={composeStyles('gray right')}>-</span>
160
+ </div>
161
+ <div style={composeStyles('w-15 p-4-8 pb-15')}>
162
+ <span style={composeStyles('gray right')}>-</span>
163
+ </div>
164
+ <div style={composeStyles('w-17 p-4-8 pb-15')}>
165
+ <span style={composeStyles('gray right')}>-</span>
166
+ </div>
167
+ </div>
168
+ )}
169
+
140
170
  {/* Summary */}
141
171
  <div
142
172
  style={{
@@ -0,0 +1,222 @@
1
+ import { Button } from '@arcblock/ux';
2
+ import DID from '@arcblock/ux/lib/DID';
3
+ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
4
+ import Toast from '@arcblock/ux/lib/Toast';
5
+ import { StripeForm, api, formatError, usePaymentContext } from '@blocklet/payment-react';
6
+ import type { TCustomer } from '@blocklet/payment-types';
7
+ import { CreditCard, Email, AccountBalance } from '@mui/icons-material';
8
+ import { Box, Stack, Typography } from '@mui/material';
9
+ import { useSetState } from 'ahooks';
10
+ import { useEffect } from 'react';
11
+
12
+ interface PaymentMethodData {
13
+ id?: string;
14
+ type: string;
15
+ // Stripe payment methods
16
+ card?: {
17
+ brand: string;
18
+ last4: string;
19
+ exp_month: number;
20
+ exp_year: number;
21
+ };
22
+ link?: {
23
+ email: string;
24
+ };
25
+ us_bank_account?: {
26
+ account_type: string;
27
+ bank_name: string;
28
+ last4: string;
29
+ };
30
+ billing_details?: {
31
+ name?: string;
32
+ email?: string;
33
+ phone?: string;
34
+ };
35
+ // On-chain payment methods (arcblock/ethereum/base)
36
+ payer?: string;
37
+ }
38
+
39
+ interface Props {
40
+ subscriptionId: string;
41
+ customer: TCustomer;
42
+ paymentMethodDetails: PaymentMethodData | null;
43
+ editable?: boolean;
44
+ paymentMethodType: string;
45
+ onUpdate?: () => void;
46
+ }
47
+
48
+ export default function PaymentMethodInfo({
49
+ subscriptionId,
50
+ customer,
51
+ paymentMethodDetails,
52
+ editable = false,
53
+ onUpdate = () => {},
54
+ paymentMethodType,
55
+ }: Props) {
56
+ const { t, locale } = useLocaleContext();
57
+ const { connect } = usePaymentContext();
58
+
59
+ const [state, setState] = useSetState<{
60
+ editing: boolean;
61
+ submitting: boolean;
62
+ setupIntentId: string | null;
63
+ clientSecret: string | null;
64
+ publishableKey: string | null;
65
+ }>({
66
+ editing: false,
67
+ submitting: false,
68
+ setupIntentId: null,
69
+ clientSecret: null,
70
+ publishableKey: null,
71
+ });
72
+
73
+ useEffect(() => {
74
+ if (!state.editing) {
75
+ setState({ clientSecret: null, publishableKey: null, setupIntentId: null });
76
+ }
77
+ }, [state.editing, setState]);
78
+
79
+ const handleEdit = async () => {
80
+ if (paymentMethodType === 'stripe') {
81
+ try {
82
+ setState({ submitting: true });
83
+ const { data } = await api.post(`/api/subscriptions/${subscriptionId}/update-stripe-payment-method`);
84
+ setState({
85
+ editing: true,
86
+ clientSecret: data.client_secret,
87
+ publishableKey: data.publishable_key,
88
+ setupIntentId: data.setup_intent_id,
89
+ submitting: false,
90
+ });
91
+ } catch (err) {
92
+ Toast.error(formatError(err));
93
+ setState({ submitting: false });
94
+ }
95
+ } else {
96
+ connect.open({
97
+ action: 'change-payer',
98
+ saveConnect: false,
99
+ locale: locale as 'en' | 'zh',
100
+ useSocket: true,
101
+ messages: {
102
+ scan: '',
103
+ title: t('admin.subscription.changePayer.connect.title'),
104
+ success: t('admin.subscription.changePayer.connect.success'),
105
+ error: t('admin.subscription.changePayer.connect.error'),
106
+ confirm: '',
107
+ } as any,
108
+ extraParams: { subscriptionId },
109
+ onSuccess: () => {
110
+ connect.close();
111
+ Toast.success(t('admin.subscription.changePayer.connect.success'));
112
+ onUpdate?.();
113
+ },
114
+ onClose: () => {
115
+ connect.close();
116
+ },
117
+ onError: (err: any) => {
118
+ Toast.error(formatError(err));
119
+ },
120
+ });
121
+ }
122
+ };
123
+
124
+ const handleConfirm = () => {
125
+ setTimeout(() => {
126
+ Toast.success(t('admin.subscription.changePayer.connect.success'));
127
+ setState({ editing: false, submitting: false });
128
+ onUpdate?.();
129
+ }, 2000);
130
+ };
131
+
132
+ const handleCancel = () => {
133
+ setState({ editing: false, clientSecret: null, publishableKey: null, setupIntentId: null });
134
+ };
135
+
136
+ if (!paymentMethodDetails) {
137
+ return null;
138
+ }
139
+
140
+ const { card, link, us_bank_account: usBankAccount, payer, type } = paymentMethodDetails;
141
+
142
+ if (state.editing && state.clientSecret && state.publishableKey) {
143
+ return (
144
+ <Box>
145
+ <StripeForm
146
+ clientSecret={state.clientSecret}
147
+ intentType="setup_intent"
148
+ publicKey={state.publishableKey}
149
+ customer={customer}
150
+ mode="setup"
151
+ onConfirm={handleConfirm}
152
+ onCancel={handleCancel}
153
+ returnUrl={window.location.href}
154
+ />
155
+ </Box>
156
+ );
157
+ }
158
+
159
+ const renderPaymentMethodInfo = () => {
160
+ if (type === 'card' && card) {
161
+ return (
162
+ <Stack direction="row" spacing={1} sx={{ alignItems: 'center' }}>
163
+ <CreditCard sx={{ fontSize: 16, color: 'text.secondary' }} />
164
+ <Typography variant="body2">
165
+ {card.brand.toUpperCase()} •••• {card.last4}
166
+ </Typography>
167
+ </Stack>
168
+ );
169
+ }
170
+
171
+ if (type === 'link' && link) {
172
+ return (
173
+ <Stack direction="row" spacing={1} sx={{ alignItems: 'center' }}>
174
+ <Email sx={{ fontSize: 16, color: 'text.secondary' }} />
175
+ <Typography variant="body2">
176
+ {t('admin.subscription.changePayer.stripe.linkType')} ({link.email})
177
+ </Typography>
178
+ </Stack>
179
+ );
180
+ }
181
+
182
+ if (type === 'us_bank_account' && usBankAccount) {
183
+ return (
184
+ <Stack direction="row" spacing={1} sx={{ alignItems: 'center' }}>
185
+ <AccountBalance sx={{ fontSize: 16, color: 'text.secondary' }} />
186
+ <Typography variant="body2">
187
+ {usBankAccount.bank_name || t('admin.subscription.changePayer.stripe.bankAccount')} ••••{' '}
188
+ {usBankAccount.last4}
189
+ </Typography>
190
+ </Stack>
191
+ );
192
+ }
193
+
194
+ if (['arcblock', 'ethereum', 'base'].includes(type) && payer) {
195
+ return <DID did={payer} responsive={false} compact copyable={false} />;
196
+ }
197
+
198
+ return (
199
+ <Typography variant="body2" sx={{ color: 'text.secondary' }}>
200
+ {type || '-'}
201
+ </Typography>
202
+ );
203
+ };
204
+
205
+ return (
206
+ <Stack direction="row" spacing={1} sx={{ alignItems: 'center', flex: 1 }}>
207
+ {renderPaymentMethodInfo()}
208
+ {editable && (
209
+ <Button
210
+ variant="text"
211
+ size="small"
212
+ sx={{
213
+ color: 'text.link',
214
+ }}
215
+ loading={state.submitting}
216
+ onClick={handleEdit}>
217
+ {t('admin.subscription.changePayer.btn')}
218
+ </Button>
219
+ )}
220
+ </Stack>
221
+ );
222
+ }
package/src/global.css CHANGED
@@ -79,3 +79,7 @@ th.MuiTableCell-head {
79
79
  .MuiTooltip-tooltip {
80
80
  max-width: 500px;
81
81
  }
82
+
83
+ .date-range-picker .MuiListItem-root {
84
+ cursor: pointer;
85
+ }
package/src/libs/util.ts CHANGED
@@ -252,7 +252,7 @@ export function stringToColor(str: string) {
252
252
 
253
253
  // @ts-ignore
254
254
  const hash = Hasher.SHA3.hash256(str).slice(-12);
255
-
255
+ // @ts-ignore
256
256
  const index = Math.abs(hexToNumber(hash)) % colors.length;
257
257
  return colors[index];
258
258
  }
@@ -1421,6 +1421,19 @@ export default flat({
1421
1421
  batchPay: {
1422
1422
  button: 'Pay due invoices',
1423
1423
  },
1424
+ payerAddress: 'Payment Address',
1425
+ changePayer: {
1426
+ btn: 'Change',
1427
+ stripe: {
1428
+ linkType: 'Stripe Link',
1429
+ bankAccount: 'Bank Account',
1430
+ },
1431
+ connect: {
1432
+ title: 'Change Payment Address',
1433
+ success: 'Payment Address changed successfully',
1434
+ error: 'Failed to change payment Address',
1435
+ },
1436
+ },
1424
1437
  },
1425
1438
  customer: {
1426
1439
  view: 'View customer',
@@ -1387,6 +1387,19 @@ export default flat({
1387
1387
  batchPay: {
1388
1388
  button: '批量付款',
1389
1389
  },
1390
+ payerAddress: '扣费地址',
1391
+ changePayer: {
1392
+ btn: '变更',
1393
+ stripe: {
1394
+ linkType: 'Stripe Link',
1395
+ bankAccount: '银行账户',
1396
+ },
1397
+ connect: {
1398
+ title: '变更扣费地址',
1399
+ success: '扣费地址变更成功',
1400
+ error: '扣费地址变更失败',
1401
+ },
1402
+ },
1390
1403
  },
1391
1404
  customer: {
1392
1405
  view: '查看客户',
@@ -55,7 +55,7 @@ const fetchData = (
55
55
  relatedCreditGrants?: TCreditGrantExpanded[];
56
56
  }
57
57
  > => {
58
- return api.get(`/api/invoices/${id}`).then((res) => res.data);
58
+ return api.get(`/api/invoices/${id}?sync=true`).then((res: any) => res.data);
59
59
  };
60
60
 
61
61
  const InfoDirection = 'column';
@@ -92,7 +92,7 @@ export default function InvoiceDetail(props: { id: string }) {
92
92
  const createUpdater = (key: string) => async (updates: TInvoice) => {
93
93
  try {
94
94
  setState((prev) => ({ loading: { ...prev.loading, [key]: true } }));
95
- await api.put(`/api/invoices/${props.id}`, updates).then((res) => res.data);
95
+ await api.put(`/api/invoices/${props.id}`, updates).then((res: any) => res.data);
96
96
  Toast.success(t('common.saved'));
97
97
  runAsync();
98
98
  } catch (err) {
@@ -120,6 +120,8 @@ export default function InvoiceDetail(props: { id: string }) {
120
120
  };
121
121
  // @ts-ignore
122
122
  const isDonation = data?.checkoutSession?.submit_type === 'donate';
123
+ const showDownloadButton =
124
+ ['open', 'paid', 'uncollectible'].includes(data.status) && !isDonation && !isEmpty(data.lines);
123
125
  return (
124
126
  <Root direction="column" spacing={2.5} sx={{ mb: 4 }}>
125
127
  <Box>
@@ -144,7 +146,7 @@ export default function InvoiceDetail(props: { id: string }) {
144
146
  </Typography>
145
147
  </Stack>
146
148
  <Box style={{ display: 'flex', gap: '10px' }}>
147
- <Download data={data} />
149
+ {showDownloadButton && <Download data={data} />}
148
150
  <InvoiceActions data={data} onChange={runAsync} variant="normal" />
149
151
  </Box>
150
152
  </Stack>
@@ -35,6 +35,7 @@ import { goBackOrFallback } from '../../../../libs/util';
35
35
  import InfoRowGroup from '../../../../components/info-row-group';
36
36
  import VendorServiceList from '../../../../components/subscription/vendor-service-list';
37
37
  import { useSessionContext } from '../../../../contexts/session';
38
+ import PaymentMethodInfo from '../../../../components/subscription/payment-method-info';
38
39
 
39
40
  const fetchData = (id: string): Promise<TSubscriptionExpanded> => {
40
41
  return api.get(`/api/subscriptions/${id}`).then((res) => res.data);
@@ -285,6 +286,21 @@ export default function SubscriptionDetail(props: { id: string }) {
285
286
  />
286
287
  }
287
288
  />
289
+
290
+ {(data as any).paymentMethodDetails && (
291
+ <InfoRow
292
+ label={t('admin.subscription.payerAddress')}
293
+ value={
294
+ <PaymentMethodInfo
295
+ subscriptionId={data.id}
296
+ customer={data.customer}
297
+ paymentMethodDetails={(data as any).paymentMethodDetails}
298
+ editable={false}
299
+ paymentMethodType={data.paymentMethod?.type}
300
+ />
301
+ }
302
+ />
303
+ )}
288
304
  {data.payment_details && hasDelegateTxHash(data.payment_details, data.paymentMethod) && (
289
305
  <InfoRow
290
306
  label={t('common.delegateTxHash')}
@@ -3,7 +3,7 @@ import DID from '@arcblock/ux/lib/DID';
3
3
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
4
4
  import { api, formatBNStr, formatToDate, usePaymentContext } from '@blocklet/payment-react';
5
5
  import { BN } from '@ocap/util';
6
- import type { GroupedBN, TPaymentMethod, TPaymentStat } from '@blocklet/payment-types';
6
+ import type { GroupedBN, TPaymentCurrency, TPaymentMethod, TPaymentStat } from '@blocklet/payment-types';
7
7
  import {
8
8
  Avatar,
9
9
  Box,
@@ -175,8 +175,8 @@ export default function Overview() {
175
175
 
176
176
  const currencies: TCurrencyMap = useMemo(() => {
177
177
  const map: TCurrencyMap = {};
178
- (settings.paymentMethods || []).forEach((method) => {
179
- (method.payment_currencies || []).forEach((currency) => {
178
+ (settings.paymentMethods || []).forEach((method: { payment_currencies: TPaymentCurrency[] }) => {
179
+ (method.payment_currencies || []).forEach((currency: TPaymentCurrency) => {
180
180
  if (!map[currency.id]) {
181
181
  map[currency.id] = {
182
182
  ...currency,
@@ -1105,10 +1105,12 @@ export default function Overview() {
1105
1105
  sx={{
1106
1106
  p: 1.5,
1107
1107
  flex: '1 1 calc(50% - 8px)',
1108
+ minWidth: 0,
1108
1109
  borderRadius: 1,
1109
1110
  backgroundColor: theme.mode === 'dark' ? 'grey.100' : 'grey.50',
1110
1111
  border: 'none',
1111
1112
  boxShadow: 'none',
1113
+ containerType: 'inline-size',
1112
1114
  }}>
1113
1115
  <Box>
1114
1116
  <Typography
@@ -1124,13 +1126,11 @@ export default function Overview() {
1124
1126
  sx={{
1125
1127
  gap: 1.5,
1126
1128
  flexWrap: 'wrap',
1127
- flexDirection: {
1128
- xs: 'column',
1129
- md: 'row',
1130
- },
1131
- alignItems: {
1132
- xs: 'flex-start',
1133
- md: 'baseline',
1129
+ flexDirection: 'row',
1130
+ alignItems: 'baseline',
1131
+ '@container (max-width: 220px)': {
1132
+ flexDirection: 'column',
1133
+ alignItems: 'flex-start',
1134
1134
  },
1135
1135
  }}>
1136
1136
  <Typography
@@ -1239,14 +1239,14 @@ export default function Overview() {
1239
1239
 
1240
1240
  <Grid
1241
1241
  container
1242
+ spacing={{ xs: 3, lg: 6 }}
1242
1243
  sx={{
1243
- gap: { xs: 3, md: 6 },
1244
1244
  mb: 4,
1245
1245
  }}>
1246
1246
  <Grid
1247
1247
  size={{
1248
1248
  xs: 12,
1249
- md: 8,
1249
+ lg: 8,
1250
1250
  }}>
1251
1251
  {renderFinancialSection()}
1252
1252
  </Grid>
@@ -1254,7 +1254,7 @@ export default function Overview() {
1254
1254
  <Grid
1255
1255
  size={{
1256
1256
  xs: 12,
1257
- md: 3,
1257
+ lg: 4,
1258
1258
  }}>
1259
1259
  {renderBusinessMonitoringSection()}
1260
1260
  </Grid>
@@ -1265,7 +1265,7 @@ export default function Overview() {
1265
1265
  open={open}
1266
1266
  anchorEl={state.anchorEl}
1267
1267
  onClose={() => setState({ anchorEl: null })}
1268
- anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}>
1268
+ anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}>
1269
1269
  <DateRangePicker
1270
1270
  open
1271
1271
  toggle={onTogglePicker as any}