payment-kit 1.16.19 → 1.17.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/blocklet.yml CHANGED
@@ -14,7 +14,7 @@ repository:
14
14
  type: git
15
15
  url: git+https://github.com/blocklet/payment-kit.git
16
16
  specVersion: 1.2.8
17
- version: 1.16.19
17
+ version: 1.17.1
18
18
  logo: logo.png
19
19
  files:
20
20
  - dist
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payment-kit",
3
- "version": "1.16.19",
3
+ "version": "1.17.1",
4
4
  "scripts": {
5
5
  "dev": "blocklet dev --open",
6
6
  "eject": "vite eject",
@@ -53,7 +53,7 @@
53
53
  "@arcblock/validator": "^1.18.165",
54
54
  "@blocklet/js-sdk": "^1.16.36",
55
55
  "@blocklet/logger": "^1.16.36",
56
- "@blocklet/payment-react": "1.16.19",
56
+ "@blocklet/payment-react": "1.17.1",
57
57
  "@blocklet/sdk": "^1.16.36",
58
58
  "@blocklet/ui-react": "^2.11.15",
59
59
  "@blocklet/uploader": "^0.1.60",
@@ -120,7 +120,7 @@
120
120
  "devDependencies": {
121
121
  "@abtnode/types": "^1.16.36",
122
122
  "@arcblock/eslint-config-ts": "^0.3.3",
123
- "@blocklet/payment-types": "1.16.19",
123
+ "@blocklet/payment-types": "1.17.1",
124
124
  "@types/cookie-parser": "^1.4.7",
125
125
  "@types/cors": "^2.8.17",
126
126
  "@types/debug": "^4.1.12",
@@ -166,5 +166,5 @@
166
166
  "parser": "typescript"
167
167
  }
168
168
  },
169
- "gitHead": "a033985b46d5c80b56f2ed9dc86d808fb60d9db1"
169
+ "gitHead": "fe7302197bbf98d5490f8bc0d6738d9c51c53646"
170
170
  }
@@ -19,9 +19,9 @@ import {
19
19
  } from '@mui/material';
20
20
  import Dialog from '@arcblock/ux/lib/Dialog';
21
21
  import { EventHandler, useState } from 'react';
22
- import { api, Switch, useMobile } from '@blocklet/payment-react';
22
+ import { api, formatAmountPrecisionLimit, Switch, useMobile } from '@blocklet/payment-react';
23
23
  import { useRequest } from 'ahooks';
24
- import { BN, fromUnitToToken } from '@ocap/util';
24
+ import { BN, fromTokenToUnit, fromUnitToToken } from '@ocap/util';
25
25
  import type { TPaymentCurrency, TSubscriptionExpanded } from '@blocklet/payment-types';
26
26
  import Currency from '../currency';
27
27
 
@@ -32,6 +32,21 @@ const fetchCycleAmount = (
32
32
  return api.get(`/api/subscriptions/${subscriptionId}/cycle-amount`, { params }).then((res) => res.data);
33
33
  };
34
34
 
35
+ function safeAdd(currency: { decimal: number }, ...numbers: string[]) {
36
+ if (!numbers.length) return '0';
37
+ if (!numbers.every((n) => /^-?\d*\.?\d*$/.test(n))) {
38
+ throw new Error('Invalid number format');
39
+ }
40
+
41
+ const decimal = currency?.decimal || 18;
42
+ const sum = numbers.reduce((total, num) => {
43
+ const unitAmount = fromTokenToUnit(num, decimal);
44
+ return new BN(total).add(new BN(unitAmount));
45
+ }, new BN(0));
46
+
47
+ return fromUnitToToken(sum.toString(), decimal);
48
+ }
49
+
35
50
  type OverdraftProtectionDialogProps = {
36
51
  value: {
37
52
  enabled: boolean;
@@ -48,6 +63,7 @@ type OverdraftProtectionDialogProps = {
48
63
  symbol: string;
49
64
  logo: string;
50
65
  decimal: number;
66
+ maximum_precision?: number;
51
67
  };
52
68
  subscription: TSubscriptionExpanded;
53
69
  };
@@ -66,7 +82,7 @@ export default function OverdraftProtectionDialog({
66
82
  currency,
67
83
  subscription,
68
84
  }: OverdraftProtectionDialogProps) {
69
- const { t } = useLocaleContext();
85
+ const { t, locale } = useLocaleContext();
70
86
  const { isMobile } = useMobile();
71
87
  const [customAmount, setCustomAmount] = useState(false);
72
88
  const [presetAmounts, setPresetAmounts] = useState<{ amount: string; cycles: number }[]>([]);
@@ -298,6 +314,14 @@ export default function OverdraftProtectionDialog({
298
314
  symbol: currency.symbol,
299
315
  });
300
316
  }
317
+ const validPrecision = formatAmountPrecisionLimit(
318
+ val.toString(),
319
+ locale,
320
+ currency?.maximum_precision || 6
321
+ );
322
+ if (validPrecision) {
323
+ return validPrecision;
324
+ }
301
325
  return true;
302
326
  },
303
327
  })}
@@ -325,11 +349,11 @@ export default function OverdraftProtectionDialog({
325
349
  {amount && Number(amount) > 0 && !methods.formState.errors.amount && (
326
350
  <Typography variant="body2" sx={{ color: 'text.lighter', mt: '8px !important' }} fontSize={12}>
327
351
  {t('customer.overdraftProtection.total', {
328
- total: Number(amount) + Number(availableAmount),
352
+ total: safeAdd(currency, amount, availableAmount),
329
353
  symbol: currency.symbol,
330
354
  })}
331
355
  {formatEstimatedDuration(
332
- Math.floor((Number(amount) + Number(availableAmount)) / Number(estimateAmount))
356
+ Math.floor(Number(safeAdd(currency, amount, availableAmount)) / Number(estimateAmount))
333
357
  )}
334
358
  </Typography>
335
359
  )}
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable react/no-unstable-nested-components */
2
2
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
3
+ import DidAddress from '@arcblock/ux/lib/DID';
3
4
  import {
4
5
  Status,
5
6
  api,
@@ -10,6 +11,7 @@ import {
10
11
  formatTime,
11
12
  formatToDate,
12
13
  formatToDatetime,
14
+ getCustomerAvatar,
13
15
  getDidConnectQueryParams,
14
16
  getInvoiceDescriptionAndReason,
15
17
  getInvoiceStatusColor,
@@ -37,6 +39,8 @@ import { useRequest } from 'ahooks';
37
39
  import { useMemo } from 'react';
38
40
  import { joinURL, withQuery } from 'ufo';
39
41
  import prettyMs from 'pretty-ms-i18n';
42
+ import InfoRow from '../../../components/info-row';
43
+ import InfoCard from '../../../components/info-card';
40
44
 
41
45
  const fetchInvoiceData = (params: Record<string, any> = {}): Promise<Paginated<TInvoiceExpanded>> => {
42
46
  const search = new URLSearchParams();
@@ -110,7 +114,7 @@ export default function SubscriptionEmbed() {
110
114
 
111
115
  const invoices = data?.list || [];
112
116
 
113
- const infoList = [
117
+ const infoList: { name: string; value: React.ReactNode }[] = [
114
118
  {
115
119
  name: t('payment.customer.subscriptions.plan'),
116
120
  value: (
@@ -167,11 +171,25 @@ export default function SubscriptionEmbed() {
167
171
  </Typography>
168
172
  ),
169
173
  });
174
+
175
+ infoList.push({
176
+ name: t('payment.customer.subscriptions.owner'),
177
+ value: (
178
+ <InfoCard
179
+ logo={getCustomerAvatar(
180
+ subscription.customer.did,
181
+ subscription.customer.updated_at ? new Date(subscription.customer.updated_at).toISOString() : '',
182
+ 48
183
+ )}
184
+ name={subscription.customer.email}
185
+ description={<DidAddress did={subscription.customer.did} responsive />}
186
+ />
187
+ ),
188
+ });
170
189
  }
171
190
 
172
191
  return (
173
192
  <Position>
174
- <Typography title={t('payment.checkout.subscription')} />
175
193
  <Box
176
194
  className="mini-invoice-wrap"
177
195
  sx={{
@@ -179,27 +197,21 @@ export default function SubscriptionEmbed() {
179
197
  flexDirection: 'column',
180
198
  alignItem: 'center',
181
199
  justifyContent: 'flex-start',
182
- padding: '16px',
200
+ padding: '8px',
201
+ gap: '12px',
183
202
  width: '100%',
184
203
  height: '100%',
185
204
  }}>
186
- <Typography component="h3" sx={{ textAlign: 'center', fontWeight: 500 }} variant="h5" gutterBottom>
205
+ <Typography component="h2" sx={{ textAlign: 'center' }} variant="h3" gutterBottom>
187
206
  {t('payment.customer.subscriptions.current')}
188
207
  </Typography>
189
- <Box sx={{ marginTop: '12px' }}>
190
- <List>
191
- {infoList.map(({ name, value }) => {
192
- return (
193
- <ListItem key={name} disableGutters sx={{ display: 'flex', justifyContent: 'space-between' }}>
194
- <Typography component="span">{name}</Typography>
195
- <Typography component="span">{value}</Typography>
196
- </ListItem>
197
- );
198
- })}
199
- </List>
208
+ <Box sx={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
209
+ {infoList.map(({ name, value }) => {
210
+ return <InfoRow label={name} value={value} direction="column" alignItems="flex-start" sx={{ mb: 0 }} />;
211
+ })}
200
212
  </Box>
201
213
  <Divider />
202
- <Box sx={{ marginTop: '12px', flex: 1, overflow: 'hidden' }}>
214
+ <Box sx={{ flex: 1, overflow: 'hidden' }}>
203
215
  <List sx={{ height: '100%', display: 'flex', flexDirection: 'column' }} className="mini-invoice-list">
204
216
  <ListSubheader disableGutters sx={{ padding: 0 }}>
205
217
  <Typography component="h2" variant="h6" fontSize="16px">
@@ -273,7 +285,7 @@ function Position({ children }: any) {
273
285
  maxWidth: '500px',
274
286
  background: '#fff',
275
287
  margin: '0 auto',
276
- height: '100%',
288
+ height: '100vh',
277
289
  }}>
278
290
  {children}
279
291
  </Box>