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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payment-kit",
|
|
3
|
-
"version": "1.
|
|
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.
|
|
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.
|
|
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": "
|
|
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:
|
|
352
|
+
total: safeAdd(currency, amount, availableAmount),
|
|
329
353
|
symbol: currency.symbol,
|
|
330
354
|
})}
|
|
331
355
|
{formatEstimatedDuration(
|
|
332
|
-
Math.floor(
|
|
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: '
|
|
200
|
+
padding: '8px',
|
|
201
|
+
gap: '12px',
|
|
183
202
|
width: '100%',
|
|
184
203
|
height: '100%',
|
|
185
204
|
}}>
|
|
186
|
-
<Typography component="
|
|
205
|
+
<Typography component="h2" sx={{ textAlign: 'center' }} variant="h3" gutterBottom>
|
|
187
206
|
{t('payment.customer.subscriptions.current')}
|
|
188
207
|
</Typography>
|
|
189
|
-
<Box sx={{
|
|
190
|
-
|
|
191
|
-
{
|
|
192
|
-
|
|
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={{
|
|
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: '
|
|
288
|
+
height: '100vh',
|
|
277
289
|
}}>
|
|
278
290
|
{children}
|
|
279
291
|
</Box>
|