diff --git a/components/settings/AccountSettings.tsx b/components/settings/AccountSettings.tsx new file mode 100644 index 00000000..aede51b9 --- /dev/null +++ b/components/settings/AccountSettings.tsx @@ -0,0 +1,168 @@ +import Button from '@components/shared/Button' +import InlineNotification from '@components/shared/InlineNotification' +import Loading from '@components/shared/Loading' +import Tooltip from '@components/shared/Tooltip' +import mangoStore from '@store/mangoStore' +import useMangoAccount from 'hooks/useMangoAccount' +import { useTranslation } from 'next-i18next' +import { useCallback, useEffect, useState } from 'react' +import NumberFormat, { + NumberFormatValues, + SourceInfo, +} from 'react-number-format' +import { isMangoError } from 'types' +import { notify } from 'utils/notifications' + +type FormErrors = Partial> + +type AccountSettingsForm = { + tokenAccounts: string | undefined +} + +const DEFAULT_FORM = { + tokenAccounts: '', +} + +const AccountSettings = () => { + const { t } = useTranslation(['common', 'settings']) + const { mangoAccount, mangoAccountAddress } = useMangoAccount() + const [accountSettingsForm, setAccountSettingsForm] = + useState(DEFAULT_FORM) + const [formErrors, setFormErrors] = useState() + const [submitting, setSubmitting] = useState(false) + + useEffect(() => { + if (mangoAccountAddress) { + setAccountSettingsForm({ + tokenAccounts: mangoAccount?.tokens.length.toString(), + }) + } + }, [mangoAccountAddress]) + + const isFormValid = (form: AccountSettingsForm) => { + const mangoAccount = mangoStore.getState().mangoAccount.current + const invalidFields: FormErrors = {} + setFormErrors({}) + const tokenAccounts: (keyof AccountSettingsForm)[] = ['tokenAccounts'] + for (const key of tokenAccounts) { + const value = form[key] as string + const minLength = mangoAccount?.tokens.length || 8 + if (parseInt(value) <= minLength) { + invalidFields[key] = t('settings:error-amount', { + type: t('settings:token-accounts'), + greaterThan: mangoAccount?.tokens.length, + lessThan: '17', + }) + } + } + if (Object.keys(invalidFields).length) { + setFormErrors(invalidFields) + } + return invalidFields + } + + const handleSetForm = ( + propertyName: string, + e: NumberFormatValues, + info: SourceInfo, + ) => { + if (info.source !== 'event') return + setFormErrors({}) + setAccountSettingsForm((prevState) => ({ + ...prevState, + [propertyName]: e.value, + })) + } + + const handleUpdateAccountSize = useCallback(async () => { + const invalidFields = isFormValid(accountSettingsForm) + if (Object.keys(invalidFields).length) { + return + } + const client = mangoStore.getState().client + const group = mangoStore.getState().group + const mangoAccount = mangoStore.getState().mangoAccount.current + const actions = mangoStore.getState().actions + const { tokenAccounts } = accountSettingsForm + if (!mangoAccount || !group || !tokenAccounts) return + setSubmitting(true) + try { + const tx = await client.accountExpandV2( + group, + mangoAccount, + parseInt(tokenAccounts), + mangoAccount.serum3.length, + mangoAccount.perps.length, + mangoAccount.perpOpenOrders.length, + mangoAccount.tokenConditionalSwaps.length, + ) + notify({ + title: 'Transaction confirmed', + type: 'success', + txid: tx, + }) + await actions.reloadMangoAccount() + setSubmitting(false) + } catch (e) { + console.error(e) + if (!isMangoError(e)) return + notify({ + title: 'Transaction failed', + description: e.message, + txid: e.txid, + type: 'error', + }) + } finally { + setSubmitting(false) + } + }, [accountSettingsForm]) + + return ( + <> +

{t('account')}

+
+ +

+ {t('settings:increase-token-accounts')} +

+
+
+
+ + handleSetForm('tokenAccounts', e, sourceInfo) + } + /> + +
+ {formErrors?.tokenAccounts ? ( +
+ +
+ ) : null} +
+
+ + ) +} + +export default AccountSettings diff --git a/components/settings/SettingsPage.tsx b/components/settings/SettingsPage.tsx index fc812e27..d4ea3380 100644 --- a/components/settings/SettingsPage.tsx +++ b/components/settings/SettingsPage.tsx @@ -7,6 +7,7 @@ import PreferredExplorerSettings from './PreferredExplorerSettings' import RpcSettings from './RpcSettings' import SoundSettings from './SoundSettings' import { breakpoints } from 'utils/theme' +import AccountSettings from './AccountSettings' const SettingsPage = () => { const { width } = useViewport() @@ -16,6 +17,9 @@ const SettingsPage = () => {
+
+ +
diff --git a/public/locales/en/settings.json b/public/locales/en/settings.json index 93bc9057..78fbd0f6 100644 --- a/public/locales/en/settings.json +++ b/public/locales/en/settings.json @@ -22,6 +22,7 @@ "dark": "Dark", "display": "Display", "error-alphanumeric-only": "Alphanumeric characters only", + "error-amount": "{{type}} must be greater than {{greaterThan}} and less than {{lessThan}}", "error-key-in-use": "Hot key already in use. Choose a unique key", "error-key-limit-reached": "You've reached the maximum number of hot keys", "error-must-be-above-zero": "Must be greater than zero", @@ -34,9 +35,11 @@ "high-contrast": "High Contrast", "hot-keys": "Hot Keys", "hot-keys-desc": "Use hot keys to place orders on the trade page. They execute on the market you're viewing and are not market specific.", + "increase-token-accounts": "Increase Token Accounts", "key-sequence": "Key Sequence", "language": "Language", "light": "Light", + "limit-order-filled": "Limit Order Fills", "lychee": "Lychee", "mango": "Mango", "mango-classic": "Mango Classic", @@ -44,11 +47,13 @@ "new-hot-key": "New Hot Key", "no-hot-keys": "Create your first hot key", "notification-position": "Notification Position", + "notifications": "Notifications", "notional": "Notional", "number-scroll": "Number Scroll", "olive": "Olive", "options": "Options", "oracle": "Oracle", + "orderbook-bandwidth-saving": "Orderbook Bandwidth Saving", "orderbook-flash": "Orderbook Flash", "order-side": "Order Side", "order-size-type": "Order Size Type", @@ -73,9 +78,12 @@ "swap-success": "Swap/Trade Success", "swap-trade-size-selector": "Swap/Trade Size Selector", "theme": "Theme", + "token-accounts": "Token Accounts", "tooltip-hot-key-notional-size": "Set size as a USD value.", "tooltip-hot-key-percentage-size": "Set size as a percentage of your max leverage.", "tooltip-hot-key-price": "Set a price as a percentage change from the oracle price.", + "tooltip-increase-token-accounts": "Increase the amount of tokens you can hold in your account. The SOL required can be recovered if you close your account", + "tooltip-orderbook-bandwidth-saving": "Use an off-chain service for Orderbook updates to decrease data usage by ~1000x. Disable this if open orders are not highlighted in the book correctly.", "top-left": "Top-Left", "top-right": "Top-Right", "trade-layout": "Trade Layout", @@ -83,9 +91,5 @@ "transaction-success": "Transaction Success", "trade-chart": "Trade Chart", "trading-view": "Trading View", - "trigger-key": "Trigger Key", - "notifications": "Notifications", - "limit-order-filled": "Limit Order Fills", - "orderbook-bandwidth-saving": "Orderbook Bandwidth Saving", - "tooltip-orderbook-bandwidth-saving": "Use an off-chain service for Orderbook updates to decrease data usage by ~1000x. Disable this if open orders are not highlighted in the book correctly." + "trigger-key": "Trigger Key" } \ No newline at end of file diff --git a/public/locales/es/settings.json b/public/locales/es/settings.json index 93bc9057..78fbd0f6 100644 --- a/public/locales/es/settings.json +++ b/public/locales/es/settings.json @@ -22,6 +22,7 @@ "dark": "Dark", "display": "Display", "error-alphanumeric-only": "Alphanumeric characters only", + "error-amount": "{{type}} must be greater than {{greaterThan}} and less than {{lessThan}}", "error-key-in-use": "Hot key already in use. Choose a unique key", "error-key-limit-reached": "You've reached the maximum number of hot keys", "error-must-be-above-zero": "Must be greater than zero", @@ -34,9 +35,11 @@ "high-contrast": "High Contrast", "hot-keys": "Hot Keys", "hot-keys-desc": "Use hot keys to place orders on the trade page. They execute on the market you're viewing and are not market specific.", + "increase-token-accounts": "Increase Token Accounts", "key-sequence": "Key Sequence", "language": "Language", "light": "Light", + "limit-order-filled": "Limit Order Fills", "lychee": "Lychee", "mango": "Mango", "mango-classic": "Mango Classic", @@ -44,11 +47,13 @@ "new-hot-key": "New Hot Key", "no-hot-keys": "Create your first hot key", "notification-position": "Notification Position", + "notifications": "Notifications", "notional": "Notional", "number-scroll": "Number Scroll", "olive": "Olive", "options": "Options", "oracle": "Oracle", + "orderbook-bandwidth-saving": "Orderbook Bandwidth Saving", "orderbook-flash": "Orderbook Flash", "order-side": "Order Side", "order-size-type": "Order Size Type", @@ -73,9 +78,12 @@ "swap-success": "Swap/Trade Success", "swap-trade-size-selector": "Swap/Trade Size Selector", "theme": "Theme", + "token-accounts": "Token Accounts", "tooltip-hot-key-notional-size": "Set size as a USD value.", "tooltip-hot-key-percentage-size": "Set size as a percentage of your max leverage.", "tooltip-hot-key-price": "Set a price as a percentage change from the oracle price.", + "tooltip-increase-token-accounts": "Increase the amount of tokens you can hold in your account. The SOL required can be recovered if you close your account", + "tooltip-orderbook-bandwidth-saving": "Use an off-chain service for Orderbook updates to decrease data usage by ~1000x. Disable this if open orders are not highlighted in the book correctly.", "top-left": "Top-Left", "top-right": "Top-Right", "trade-layout": "Trade Layout", @@ -83,9 +91,5 @@ "transaction-success": "Transaction Success", "trade-chart": "Trade Chart", "trading-view": "Trading View", - "trigger-key": "Trigger Key", - "notifications": "Notifications", - "limit-order-filled": "Limit Order Fills", - "orderbook-bandwidth-saving": "Orderbook Bandwidth Saving", - "tooltip-orderbook-bandwidth-saving": "Use an off-chain service for Orderbook updates to decrease data usage by ~1000x. Disable this if open orders are not highlighted in the book correctly." + "trigger-key": "Trigger Key" } \ No newline at end of file diff --git a/public/locales/ru/settings.json b/public/locales/ru/settings.json index 93bc9057..78fbd0f6 100644 --- a/public/locales/ru/settings.json +++ b/public/locales/ru/settings.json @@ -22,6 +22,7 @@ "dark": "Dark", "display": "Display", "error-alphanumeric-only": "Alphanumeric characters only", + "error-amount": "{{type}} must be greater than {{greaterThan}} and less than {{lessThan}}", "error-key-in-use": "Hot key already in use. Choose a unique key", "error-key-limit-reached": "You've reached the maximum number of hot keys", "error-must-be-above-zero": "Must be greater than zero", @@ -34,9 +35,11 @@ "high-contrast": "High Contrast", "hot-keys": "Hot Keys", "hot-keys-desc": "Use hot keys to place orders on the trade page. They execute on the market you're viewing and are not market specific.", + "increase-token-accounts": "Increase Token Accounts", "key-sequence": "Key Sequence", "language": "Language", "light": "Light", + "limit-order-filled": "Limit Order Fills", "lychee": "Lychee", "mango": "Mango", "mango-classic": "Mango Classic", @@ -44,11 +47,13 @@ "new-hot-key": "New Hot Key", "no-hot-keys": "Create your first hot key", "notification-position": "Notification Position", + "notifications": "Notifications", "notional": "Notional", "number-scroll": "Number Scroll", "olive": "Olive", "options": "Options", "oracle": "Oracle", + "orderbook-bandwidth-saving": "Orderbook Bandwidth Saving", "orderbook-flash": "Orderbook Flash", "order-side": "Order Side", "order-size-type": "Order Size Type", @@ -73,9 +78,12 @@ "swap-success": "Swap/Trade Success", "swap-trade-size-selector": "Swap/Trade Size Selector", "theme": "Theme", + "token-accounts": "Token Accounts", "tooltip-hot-key-notional-size": "Set size as a USD value.", "tooltip-hot-key-percentage-size": "Set size as a percentage of your max leverage.", "tooltip-hot-key-price": "Set a price as a percentage change from the oracle price.", + "tooltip-increase-token-accounts": "Increase the amount of tokens you can hold in your account. The SOL required can be recovered if you close your account", + "tooltip-orderbook-bandwidth-saving": "Use an off-chain service for Orderbook updates to decrease data usage by ~1000x. Disable this if open orders are not highlighted in the book correctly.", "top-left": "Top-Left", "top-right": "Top-Right", "trade-layout": "Trade Layout", @@ -83,9 +91,5 @@ "transaction-success": "Transaction Success", "trade-chart": "Trade Chart", "trading-view": "Trading View", - "trigger-key": "Trigger Key", - "notifications": "Notifications", - "limit-order-filled": "Limit Order Fills", - "orderbook-bandwidth-saving": "Orderbook Bandwidth Saving", - "tooltip-orderbook-bandwidth-saving": "Use an off-chain service for Orderbook updates to decrease data usage by ~1000x. Disable this if open orders are not highlighted in the book correctly." + "trigger-key": "Trigger Key" } \ No newline at end of file diff --git a/public/locales/zh/settings.json b/public/locales/zh/settings.json index 8c8d348c..bdef92c2 100644 --- a/public/locales/zh/settings.json +++ b/public/locales/zh/settings.json @@ -22,6 +22,7 @@ "dark": "暗", "display": "显示", "error-alphanumeric-only": "Alphanumeric characters only", + "error-amount": "{{type}} must be greater than {{greaterThan}} and less than {{lessThan}}", "error-key-in-use": "Hot key already in use. Choose a unique key", "error-key-limit-reached": "You've reached the maximum number of hot keys", "error-must-be-above-zero": "Must be greater than zero", @@ -34,6 +35,7 @@ "high-contrast": "高对比度", "hot-keys": "Hot Keys", "hot-keys-desc": "Use hot keys to place orders on the trade page. They execute on the market you're viewing and are not market specific.", + "increase-token-accounts": "Increase Token Accounts", "key-sequence": "Key Sequence", "language": "语言", "light": "光", @@ -76,9 +78,11 @@ "swap-success": "换币/交易成功", "swap-trade-size-selector": "换币/交易大小选择器", "theme": "模式", + "token-accounts": "Token Accounts", "tooltip-hot-key-notional-size": "Set size as a USD value.", "tooltip-hot-key-percentage-size": "Set size as a percentage of your max leverage.", "tooltip-hot-key-price": "Set a price as a percentage change from the oracle price.", + "tooltip-increase-token-accounts": "Increase the amount of tokens you can hold in your account. The SOL required can be recovered if you close your account", "top-left": "左上", "top-right": "右上", "trade-chart": "交易图表", diff --git a/public/locales/zh_tw/settings.json b/public/locales/zh_tw/settings.json index 01355004..001c6fa5 100644 --- a/public/locales/zh_tw/settings.json +++ b/public/locales/zh_tw/settings.json @@ -22,6 +22,7 @@ "dark": "暗", "display": "顯示", "error-alphanumeric-only": "Alphanumeric characters only", + "error-amount": "{{type}} must be greater than {{greaterThan}} and less than {{lessThan}}", "error-key-in-use": "Hot key already in use. Choose a unique key", "error-key-limit-reached": "You've reached the maximum number of hot keys", "error-must-be-above-zero": "Must be greater than zero", @@ -34,6 +35,7 @@ "high-contrast": "高對比度", "hot-keys": "Hot Keys", "hot-keys-desc": "Use hot keys to place orders on the trade page. They execute on the market you're viewing and are not market specific.", + "increase-token-accounts": "Increase Token Accounts", "key-sequence": "Key Sequence", "language": "語言", "light": "光", @@ -76,9 +78,11 @@ "swap-success": "換幣/交易成功", "swap-trade-size-selector": "換幣/交易大小選擇器", "theme": "模式", + "token-accounts": "Token Accounts", "tooltip-hot-key-notional-size": "Set size as a USD value.", "tooltip-hot-key-percentage-size": "Set size as a percentage of your max leverage.", "tooltip-hot-key-price": "Set a price as a percentage change from the oracle price.", + "tooltip-increase-token-accounts": "Increase the amount of tokens you can hold in your account. The SOL required can be recovered if you close your account", "top-left": "左上", "top-right": "右上", "trade-chart": "交易圖表",