payment-kit 1.17.5 → 1.17.7
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/api/src/libs/product.ts +1 -1
- package/api/src/routes/payment-currencies.ts +60 -0
- package/api/src/routes/payment-methods.ts +2 -2
- package/api/src/store/models/payment-currency.ts +31 -0
- package/blocklet.yml +1 -1
- package/package.json +4 -4
- package/src/components/payment-currency/add.tsx +131 -8
- package/src/components/payment-currency/edit.tsx +73 -0
- package/src/components/payment-currency/form.tsx +12 -1
- package/src/components/payment-currency/tokenList.json +8158 -0
- package/src/locales/en.tsx +8 -1
- package/src/locales/zh.tsx +7 -0
- package/src/pages/admin/settings/payment-methods/index.tsx +83 -11
package/api/src/libs/product.ts
CHANGED
|
@@ -78,7 +78,7 @@ export async function checkCurrencySupportRecurring(currencyIds: string[] | stri
|
|
|
78
78
|
include: [{ model: PaymentMethod, as: 'payment_method' }],
|
|
79
79
|
})) as (PaymentCurrency & { payment_method: PaymentMethod })[];
|
|
80
80
|
const notSupportCurrencies = currencies.filter(
|
|
81
|
-
(c) => EVM_CHAIN_TYPES.includes(c.payment_method?.type) && c.
|
|
81
|
+
(c) => EVM_CHAIN_TYPES.includes(c.payment_method?.type) && c.payment_method?.default_currency_id === c.id
|
|
82
82
|
);
|
|
83
83
|
return {
|
|
84
84
|
notSupportCurrencies,
|
|
@@ -2,6 +2,7 @@ import { fromTokenToUnit } from '@ocap/util';
|
|
|
2
2
|
import { Router } from 'express';
|
|
3
3
|
import { InferAttributes, Op, WhereOptions } from 'sequelize';
|
|
4
4
|
|
|
5
|
+
import Joi from 'joi';
|
|
5
6
|
import { fetchErc20Meta } from '../integrations/ethereum/token';
|
|
6
7
|
import logger from '../libs/logger';
|
|
7
8
|
import { authenticate } from '../libs/security';
|
|
@@ -151,4 +152,63 @@ router.get('/:id', auth, async (req, res) => {
|
|
|
151
152
|
}
|
|
152
153
|
});
|
|
153
154
|
|
|
155
|
+
const updateCurrencySchema = Joi.object({
|
|
156
|
+
name: Joi.string().empty('').optional(),
|
|
157
|
+
description: Joi.string().empty('').optional(),
|
|
158
|
+
logo: Joi.string().empty('').optional(),
|
|
159
|
+
}).unknown(true);
|
|
160
|
+
router.put('/:id', auth, async (req, res) => {
|
|
161
|
+
const { id } = req.params;
|
|
162
|
+
const raw: Partial<TPaymentCurrency> = req.body;
|
|
163
|
+
|
|
164
|
+
const { error } = updateCurrencySchema.validate(raw);
|
|
165
|
+
if (error) {
|
|
166
|
+
return res.status(400).json({ error: error.message });
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const currency = await PaymentCurrency.findByPk(id);
|
|
170
|
+
if (!currency) {
|
|
171
|
+
return res.status(404).json({ error: 'Payment currency not found' });
|
|
172
|
+
}
|
|
173
|
+
if (raw.contract && raw.contract !== currency.contract) {
|
|
174
|
+
return res.status(400).json({ error: 'contract cannot be updated' });
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const method = await PaymentMethod.findByPk(currency.payment_method_id);
|
|
178
|
+
if (!method) {
|
|
179
|
+
return res.status(400).json({ error: 'Payment method not found' });
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const updatedCurrency = await currency.update({
|
|
183
|
+
name: raw.name || currency.name,
|
|
184
|
+
description: raw.description || currency.description,
|
|
185
|
+
logo: raw.logo || method.logo,
|
|
186
|
+
});
|
|
187
|
+
return res.json(updatedCurrency);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
router.delete('/:id', auth, async (req, res) => {
|
|
191
|
+
const { id } = req.params;
|
|
192
|
+
|
|
193
|
+
const currency = await PaymentCurrency.findByPk(id);
|
|
194
|
+
if (!currency) {
|
|
195
|
+
return res.status(404).json({ error: 'Payment currency not found' });
|
|
196
|
+
}
|
|
197
|
+
const isLocked = await currency.isLocked();
|
|
198
|
+
if (isLocked) {
|
|
199
|
+
return res.status(400).json({ error: 'Can not delete locked payment currency' });
|
|
200
|
+
}
|
|
201
|
+
const isUsed = await currency.isUsed();
|
|
202
|
+
if (isUsed) {
|
|
203
|
+
return res.status(400).json({ error: 'Can not delete payment currency used by other resources' });
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
await currency.destroy();
|
|
207
|
+
return res.status(200).end();
|
|
208
|
+
} catch (err) {
|
|
209
|
+
logger.error('delete payment currency error', err);
|
|
210
|
+
return res.status(400).json({ error: 'Delete payment currency failed' });
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
|
|
154
214
|
export default router;
|
|
@@ -68,7 +68,7 @@ router.post('/', auth, async (req, res) => {
|
|
|
68
68
|
const currency = await PaymentCurrency.create({
|
|
69
69
|
livemode: method.livemode,
|
|
70
70
|
active: method.active,
|
|
71
|
-
locked:
|
|
71
|
+
locked: true,
|
|
72
72
|
is_base_currency: false,
|
|
73
73
|
payment_method_id: method.id,
|
|
74
74
|
|
|
@@ -144,7 +144,7 @@ router.post('/', auth, async (req, res) => {
|
|
|
144
144
|
const currency = await PaymentCurrency.create({
|
|
145
145
|
livemode: method.livemode,
|
|
146
146
|
active: method.active,
|
|
147
|
-
locked:
|
|
147
|
+
locked: true,
|
|
148
148
|
is_base_currency: false,
|
|
149
149
|
payment_method_id: method.id,
|
|
150
150
|
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
InferCreationAttributes,
|
|
8
8
|
Model,
|
|
9
9
|
Op,
|
|
10
|
+
QueryTypes,
|
|
10
11
|
} from 'sequelize';
|
|
11
12
|
|
|
12
13
|
import { createIdGenerator } from '../../libs/util';
|
|
@@ -145,6 +146,36 @@ export class PaymentCurrency extends Model<InferAttributes<PaymentCurrency>, Inf
|
|
|
145
146
|
...options,
|
|
146
147
|
});
|
|
147
148
|
}
|
|
149
|
+
|
|
150
|
+
public async isLocked(): Promise<boolean> {
|
|
151
|
+
const { PaymentMethod } = this.sequelize.models;
|
|
152
|
+
const method = (await PaymentMethod!.findByPk(this.payment_method_id)) as any;
|
|
153
|
+
return this.locked || method?.default_currency_id === this.id;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
public async isUsed(): Promise<boolean> {
|
|
157
|
+
const { Price } = this.sequelize.models;
|
|
158
|
+
const price = await Price!.findOne({
|
|
159
|
+
where: {
|
|
160
|
+
currency_id: this.id,
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
if (price) {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
// @ts-ignore
|
|
167
|
+
const [{ count }] = await this.sequelize.query(
|
|
168
|
+
`SELECT count(p.id) AS count
|
|
169
|
+
FROM prices AS p
|
|
170
|
+
JOIN json_each(p.currency_options) AS option
|
|
171
|
+
ON json_extract(option.value, '$.currency_id') = ?`,
|
|
172
|
+
{
|
|
173
|
+
replacements: [this.id],
|
|
174
|
+
type: QueryTypes.SELECT,
|
|
175
|
+
}
|
|
176
|
+
);
|
|
177
|
+
return count > 0;
|
|
178
|
+
}
|
|
148
179
|
}
|
|
149
180
|
|
|
150
181
|
export type TPaymentCurrency = InferAttributes<PaymentCurrency>;
|
package/blocklet.yml
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payment-kit",
|
|
3
|
-
"version": "1.17.
|
|
3
|
+
"version": "1.17.7",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "blocklet dev --open",
|
|
6
6
|
"eject": "vite eject",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"@arcblock/validator": "^1.19.3",
|
|
54
54
|
"@blocklet/js-sdk": "^1.16.37",
|
|
55
55
|
"@blocklet/logger": "^1.16.37",
|
|
56
|
-
"@blocklet/payment-react": "1.17.
|
|
56
|
+
"@blocklet/payment-react": "1.17.7",
|
|
57
57
|
"@blocklet/sdk": "^1.16.37",
|
|
58
58
|
"@blocklet/ui-react": "^2.11.27",
|
|
59
59
|
"@blocklet/uploader": "^0.1.64",
|
|
@@ -120,7 +120,7 @@
|
|
|
120
120
|
"devDependencies": {
|
|
121
121
|
"@abtnode/types": "^1.16.37",
|
|
122
122
|
"@arcblock/eslint-config-ts": "^0.3.3",
|
|
123
|
-
"@blocklet/payment-types": "1.17.
|
|
123
|
+
"@blocklet/payment-types": "1.17.7",
|
|
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": "f2a439af19e405746a6663b4dbef8a96231a1076"
|
|
170
170
|
}
|
|
@@ -1,20 +1,57 @@
|
|
|
1
|
-
/* eslint-disable no-nested-ternary */
|
|
2
1
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
3
2
|
import Toast from '@arcblock/ux/lib/Toast';
|
|
4
3
|
import { api, formatError } from '@blocklet/payment-react';
|
|
5
|
-
import type { TPaymentCurrency,
|
|
4
|
+
import type { TPaymentCurrency, TPaymentMethodExpanded } from '@blocklet/payment-types';
|
|
6
5
|
import { AddOutlined } from '@mui/icons-material';
|
|
7
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
Button,
|
|
8
|
+
CircularProgress,
|
|
9
|
+
TextField,
|
|
10
|
+
Autocomplete,
|
|
11
|
+
Box,
|
|
12
|
+
Typography,
|
|
13
|
+
Avatar,
|
|
14
|
+
Stack,
|
|
15
|
+
Divider,
|
|
16
|
+
} from '@mui/material';
|
|
8
17
|
import { useSetState } from 'ahooks';
|
|
9
18
|
import { FormProvider, useForm } from 'react-hook-form';
|
|
10
19
|
import { dispatch } from 'use-bus';
|
|
11
|
-
|
|
20
|
+
import { useEffect } from 'react';
|
|
12
21
|
import DrawerForm from '../drawer-form';
|
|
13
22
|
import PaymentCurrencyForm from './form';
|
|
14
23
|
|
|
15
|
-
|
|
24
|
+
const loadTokenList = () =>
|
|
25
|
+
import(
|
|
26
|
+
/* webpackChunkName: "payment-token-list" */
|
|
27
|
+
'./tokenList.json'
|
|
28
|
+
);
|
|
29
|
+
interface TokenInfo {
|
|
30
|
+
address: string;
|
|
31
|
+
chainId: number;
|
|
32
|
+
decimals: number;
|
|
33
|
+
name: string;
|
|
34
|
+
symbol: string;
|
|
35
|
+
logoURI?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export default function PaymentCurrencyAdd({
|
|
39
|
+
method,
|
|
40
|
+
onClose,
|
|
41
|
+
}: {
|
|
42
|
+
method: TPaymentMethodExpanded;
|
|
43
|
+
onClose: () => void;
|
|
44
|
+
}) {
|
|
16
45
|
const { t } = useLocaleContext();
|
|
17
|
-
const [state, setState] = useSetState
|
|
46
|
+
const [state, setState] = useSetState<{
|
|
47
|
+
loading: boolean;
|
|
48
|
+
tokenListLoading: boolean;
|
|
49
|
+
availableTokens: TokenInfo[];
|
|
50
|
+
}>({
|
|
51
|
+
loading: false,
|
|
52
|
+
tokenListLoading: false,
|
|
53
|
+
availableTokens: [],
|
|
54
|
+
});
|
|
18
55
|
|
|
19
56
|
const methods = useForm<TPaymentCurrency>({
|
|
20
57
|
defaultValues: {
|
|
@@ -25,7 +62,39 @@ export default function PaymentCurrencyAdd({ method, onClose }: { method: TPayme
|
|
|
25
62
|
contract: '',
|
|
26
63
|
},
|
|
27
64
|
});
|
|
28
|
-
const { handleSubmit } = methods;
|
|
65
|
+
const { handleSubmit, setValue } = methods;
|
|
66
|
+
|
|
67
|
+
const showTokenSelect = ['ethereum', 'base'].includes(method.type);
|
|
68
|
+
|
|
69
|
+
// @ts-ignore
|
|
70
|
+
const chainId = method?.settings?.[method.type]?.chain_id || '';
|
|
71
|
+
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
if (showTokenSelect && !state.availableTokens.length) {
|
|
74
|
+
setState({ tokenListLoading: true });
|
|
75
|
+
loadTokenList().then((module) => {
|
|
76
|
+
const availableTokens = showTokenSelect
|
|
77
|
+
? // @ts-ignore
|
|
78
|
+
((module.default?.[chainId] as TokenInfo[]) || []).filter(
|
|
79
|
+
(token: TokenInfo) => !(method.payment_currencies || []).find((c: any) => c.contract === token.address)
|
|
80
|
+
)
|
|
81
|
+
: [];
|
|
82
|
+
setState({
|
|
83
|
+
availableTokens,
|
|
84
|
+
tokenListLoading: false,
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}, [showTokenSelect, chainId]);
|
|
89
|
+
|
|
90
|
+
const handleTokenSelect = (token: TokenInfo | null) => {
|
|
91
|
+
if (token) {
|
|
92
|
+
setValue('name', token.name);
|
|
93
|
+
setValue('description', `${token.name} (${token.symbol})`);
|
|
94
|
+
setValue('logo', token.logoURI || '');
|
|
95
|
+
setValue('contract', token.address);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
29
98
|
|
|
30
99
|
const onSubmit = (data: TPaymentCurrency) => {
|
|
31
100
|
setState({ loading: true });
|
|
@@ -54,10 +123,64 @@ export default function PaymentCurrencyAdd({ method, onClose }: { method: TPayme
|
|
|
54
123
|
width={640}
|
|
55
124
|
addons={
|
|
56
125
|
<Button variant="contained" size="small" onClick={handleSubmit(onSubmit)} disabled={state.loading}>
|
|
57
|
-
{state.loading ? <CircularProgress size=
|
|
126
|
+
{state.loading ? <CircularProgress size={20} /> : t('admin.paymentCurrency.save')}
|
|
58
127
|
</Button>
|
|
59
128
|
}>
|
|
60
129
|
<FormProvider {...methods}>
|
|
130
|
+
{showTokenSelect && (
|
|
131
|
+
<Box sx={{ mb: 3 }}>
|
|
132
|
+
<Autocomplete
|
|
133
|
+
disablePortal
|
|
134
|
+
options={state.availableTokens}
|
|
135
|
+
loading={state.tokenListLoading}
|
|
136
|
+
getOptionLabel={(option: TokenInfo) => option.symbol}
|
|
137
|
+
onChange={(_, value) => handleTokenSelect(value)}
|
|
138
|
+
renderInput={(params) => (
|
|
139
|
+
<TextField
|
|
140
|
+
{...params}
|
|
141
|
+
label={t('admin.paymentCurrency.quickAdd')}
|
|
142
|
+
placeholder={t('admin.paymentCurrency.searchToken')}
|
|
143
|
+
fullWidth
|
|
144
|
+
/>
|
|
145
|
+
)}
|
|
146
|
+
renderOption={(props, option) => (
|
|
147
|
+
<Box
|
|
148
|
+
component="li"
|
|
149
|
+
{...props}
|
|
150
|
+
sx={{
|
|
151
|
+
display: 'flex',
|
|
152
|
+
alignItems: 'center',
|
|
153
|
+
gap: 1,
|
|
154
|
+
cursor: 'pointer',
|
|
155
|
+
'&:hover': {
|
|
156
|
+
backgroundColor: 'action.hover',
|
|
157
|
+
},
|
|
158
|
+
}}>
|
|
159
|
+
<Avatar
|
|
160
|
+
src={option.logoURI || option.symbol}
|
|
161
|
+
alt={option.symbol}
|
|
162
|
+
sx={{
|
|
163
|
+
width: 24,
|
|
164
|
+
height: 24,
|
|
165
|
+
}}
|
|
166
|
+
/>
|
|
167
|
+
<Stack>
|
|
168
|
+
<Typography fontWeight={500}>{option.name}</Typography>
|
|
169
|
+
<Typography variant="caption" color="text.secondary">
|
|
170
|
+
{option.symbol}
|
|
171
|
+
</Typography>
|
|
172
|
+
</Stack>
|
|
173
|
+
</Box>
|
|
174
|
+
)}
|
|
175
|
+
isOptionEqualToValue={(option, value) => option.address === value.address}
|
|
176
|
+
/>
|
|
177
|
+
<Divider sx={{ my: 3 }}>
|
|
178
|
+
<Typography variant="caption" color="text.secondary">
|
|
179
|
+
{t('admin.paymentCurrency.orManualInput')}
|
|
180
|
+
</Typography>
|
|
181
|
+
</Divider>
|
|
182
|
+
</Box>
|
|
183
|
+
)}
|
|
61
184
|
<PaymentCurrencyForm />
|
|
62
185
|
</FormProvider>
|
|
63
186
|
</DrawerForm>
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/* eslint-disable no-nested-ternary */
|
|
2
|
+
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
3
|
+
import Toast from '@arcblock/ux/lib/Toast';
|
|
4
|
+
import { api, formatError } from '@blocklet/payment-react';
|
|
5
|
+
import type { TPaymentCurrency, TPaymentMethod } from '@blocklet/payment-types';
|
|
6
|
+
import { AddOutlined } from '@mui/icons-material';
|
|
7
|
+
import { Button, CircularProgress } from '@mui/material';
|
|
8
|
+
import { useSetState } from 'ahooks';
|
|
9
|
+
import { FormProvider, useForm } from 'react-hook-form';
|
|
10
|
+
import { dispatch } from 'use-bus';
|
|
11
|
+
|
|
12
|
+
import DrawerForm from '../drawer-form';
|
|
13
|
+
import PaymentCurrencyForm from './form';
|
|
14
|
+
|
|
15
|
+
export default function PaymentCurrencyEdit({
|
|
16
|
+
method,
|
|
17
|
+
onClose,
|
|
18
|
+
value,
|
|
19
|
+
}: {
|
|
20
|
+
method: TPaymentMethod;
|
|
21
|
+
onClose: () => void;
|
|
22
|
+
value: TPaymentCurrency;
|
|
23
|
+
}) {
|
|
24
|
+
const { t } = useLocaleContext();
|
|
25
|
+
const [state, setState] = useSetState({ loading: false });
|
|
26
|
+
|
|
27
|
+
const methods = useForm<TPaymentCurrency>({
|
|
28
|
+
defaultValues: {
|
|
29
|
+
payment_method_id: method.id,
|
|
30
|
+
name: value?.name,
|
|
31
|
+
description: value?.description,
|
|
32
|
+
logo: value?.logo,
|
|
33
|
+
contract: value?.contract,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
const { handleSubmit } = methods;
|
|
37
|
+
|
|
38
|
+
const onSubmit = (data: TPaymentCurrency) => {
|
|
39
|
+
setState({ loading: true });
|
|
40
|
+
api
|
|
41
|
+
.put(`/api/payment-currencies/${value.id}`, data)
|
|
42
|
+
.then(() => {
|
|
43
|
+
setState({ loading: false });
|
|
44
|
+
Toast.success(t('admin.paymentCurrency.saved'));
|
|
45
|
+
methods.reset();
|
|
46
|
+
dispatch('drawer.submitted');
|
|
47
|
+
dispatch('paymentCurrency.updated');
|
|
48
|
+
})
|
|
49
|
+
.catch((err) => {
|
|
50
|
+
setState({ loading: false });
|
|
51
|
+
console.error(err);
|
|
52
|
+
Toast.error(formatError(err));
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<DrawerForm
|
|
58
|
+
open
|
|
59
|
+
icon={<AddOutlined />}
|
|
60
|
+
onClose={onClose}
|
|
61
|
+
text={t('admin.paymentCurrency.edit')}
|
|
62
|
+
width={640}
|
|
63
|
+
addons={
|
|
64
|
+
<Button variant="contained" size="small" onClick={handleSubmit(onSubmit)} disabled={state.loading}>
|
|
65
|
+
{state.loading ? <CircularProgress size="small" /> : t('admin.paymentCurrency.save')}
|
|
66
|
+
</Button>
|
|
67
|
+
}>
|
|
68
|
+
<FormProvider {...methods}>
|
|
69
|
+
<PaymentCurrencyForm disableKeys={['contract']} />
|
|
70
|
+
</FormProvider>
|
|
71
|
+
</DrawerForm>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
@@ -6,7 +6,15 @@ import { useFormContext, useWatch } from 'react-hook-form';
|
|
|
6
6
|
|
|
7
7
|
import Uploader from '../uploader';
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
type TPaymentCurrencyFormProps = {
|
|
10
|
+
disableKeys?: string[];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
PaymentCurrencyForm.defaultProps = {
|
|
14
|
+
disableKeys: [],
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default function PaymentCurrencyForm({ disableKeys = [] }: TPaymentCurrencyFormProps) {
|
|
10
18
|
const { t } = useLocaleContext();
|
|
11
19
|
const { control, setValue } = useFormContext();
|
|
12
20
|
const logo = useWatch({ control, name: 'logo' });
|
|
@@ -29,6 +37,7 @@ export default function PaymentCurrencyForm() {
|
|
|
29
37
|
rules={{ required: true }}
|
|
30
38
|
label={t('admin.paymentMethod.name.label')}
|
|
31
39
|
placeholder={t('admin.paymentMethod.name.tip')}
|
|
40
|
+
disabled={disableKeys.includes('name')}
|
|
32
41
|
/>
|
|
33
42
|
<FormInput
|
|
34
43
|
key="description"
|
|
@@ -37,6 +46,7 @@ export default function PaymentCurrencyForm() {
|
|
|
37
46
|
rules={{ required: true }}
|
|
38
47
|
label={t('admin.paymentMethod.description.label')}
|
|
39
48
|
placeholder={t('admin.paymentMethod.description.tip')}
|
|
49
|
+
disabled={disableKeys.includes('description')}
|
|
40
50
|
/>
|
|
41
51
|
<FormInput
|
|
42
52
|
key="contract"
|
|
@@ -45,6 +55,7 @@ export default function PaymentCurrencyForm() {
|
|
|
45
55
|
rules={{ required: true }}
|
|
46
56
|
label={t('admin.paymentCurrency.contract.label')}
|
|
47
57
|
placeholder={t('admin.paymentCurrency.contract.tip')}
|
|
58
|
+
disabled={disableKeys.includes('contract')}
|
|
48
59
|
/>
|
|
49
60
|
<Stack direction="column">
|
|
50
61
|
<Typography mb={1}>{t('admin.paymentCurrency.logo.label')}</Typography>
|