|
| 1 | +import { GetLimits } from '@deriv/api-types'; |
| 2 | +import { FormatUtils } from '@deriv-com/utils'; |
| 3 | +import { TAccountLimitValues, TCurrency } from '../types'; |
| 4 | + |
| 5 | +export const CATEGORY = { |
| 6 | + footer: 'footer', |
| 7 | + header: 'header', |
| 8 | + submarket: 'submarket', |
| 9 | +} as const; |
| 10 | + |
| 11 | +type TMarketSpecific = GetLimits['market_specific']; |
| 12 | +type TMarketSpecificData = Exclude<TMarketSpecific, undefined>[string]; |
| 13 | + |
| 14 | +const markets = ['commodities', 'forex', 'indices', 'synthetic_index']; |
| 15 | + |
| 16 | +const getTradingLimitsTableData = ( |
| 17 | + currency: TCurrency, |
| 18 | + payout: number, |
| 19 | + openPositions?: number, |
| 20 | + accountBalance?: number | null |
| 21 | +): TAccountLimitValues[] => [ |
| 22 | + { |
| 23 | + category: CATEGORY.header, |
| 24 | + title: 'Trading limits', |
| 25 | + value: 'Limit', |
| 26 | + }, |
| 27 | + { |
| 28 | + hintInfo: |
| 29 | + 'Represents the maximum number of outstanding contracts in your portfolio. Each line in your portfolio counts for one open position. Once the maximum is reached, you will not be able to open new positions without closing an existing position first.', |
| 30 | + title: '*Maximum number of open positions', |
| 31 | + value: openPositions, |
| 32 | + }, |
| 33 | + { |
| 34 | + hintInfo: |
| 35 | + 'Represents the maximum amount of cash that you may hold in your account. If the maximum is reached, you will be asked to withdraw funds.', |
| 36 | + title: '*Maximum account cash balance', |
| 37 | + value: accountBalance ? FormatUtils.formatMoney(accountBalance, { currency }) : 'Not set', |
| 38 | + }, |
| 39 | + { |
| 40 | + hintInfo: |
| 41 | + 'Represents the maximum aggregate payouts on outstanding contracts in your portfolio. If the maximum is attained, you may not purchase additional contracts without first closing out existing positions.', |
| 42 | + title: 'Maximum aggregate payouts on open positions', |
| 43 | + value: FormatUtils.formatMoney(payout, { currency }), |
| 44 | + }, |
| 45 | + { |
| 46 | + category: CATEGORY.footer, |
| 47 | + title: '*Any limits in your Self-exclusion settings will override these default limits.', |
| 48 | + }, |
| 49 | +]; |
| 50 | + |
| 51 | +const getMarketValues = (collection: TMarketSpecificData, currency: TCurrency) => { |
| 52 | + const formattedCollection = collection?.slice().sort((a, b) => ((a?.level || '') > (b?.level || '') ? 1 : -1)); |
| 53 | + return formattedCollection?.map(data => ({ |
| 54 | + category: data?.level, |
| 55 | + title: data?.name, |
| 56 | + value: FormatUtils.formatMoney(data?.turnover_limit ?? 0, { currency }), |
| 57 | + })); |
| 58 | +}; |
| 59 | + |
| 60 | +const getMaximumDailyLimiitsTableData = (marketSpecific: TMarketSpecific, currency: TCurrency) => { |
| 61 | + if (!marketSpecific) return []; |
| 62 | + return [ |
| 63 | + { |
| 64 | + category: CATEGORY.header, |
| 65 | + hintInfo: 'Represents the maximum volume of contracts that you may purchase in any given trading day.', |
| 66 | + title: 'Maximum daily turnover', |
| 67 | + value: 'Limit', |
| 68 | + }, |
| 69 | + ...markets.flatMap(market => (marketSpecific[market] ? getMarketValues(marketSpecific[market], currency) : [])), |
| 70 | + ]; |
| 71 | +}; |
| 72 | + |
| 73 | +const getWithdrawalLimitsTableData = ( |
| 74 | + isAuthenticated: boolean, |
| 75 | + currency: TCurrency, |
| 76 | + numberOfDaysLimit?: number, |
| 77 | + withdrawalSinceInceptionMonetary?: number, |
| 78 | + remainder?: number |
| 79 | +) => [ |
| 80 | + { |
| 81 | + category: CATEGORY.header, |
| 82 | + title: 'Withdrawal limits', |
| 83 | + value: 'Limit', |
| 84 | + }, |
| 85 | + ...(!isAuthenticated |
| 86 | + ? [ |
| 87 | + { |
| 88 | + title: 'Total withdrawal allowed', |
| 89 | + value: FormatUtils.formatMoney(numberOfDaysLimit ?? 0, { currency }), |
| 90 | + }, |
| 91 | + { |
| 92 | + title: 'Total withdrawn', |
| 93 | + value: FormatUtils.formatMoney(withdrawalSinceInceptionMonetary ?? 0, { currency }), |
| 94 | + }, |
| 95 | + { |
| 96 | + title: 'Maximum withdrawal remaining', |
| 97 | + value: FormatUtils.formatMoney(remainder ?? 0, { currency }), |
| 98 | + }, |
| 99 | + ] |
| 100 | + : []), |
| 101 | + { |
| 102 | + category: CATEGORY.footer, |
| 103 | + isLessProminent: true, |
| 104 | + title: isAuthenticated |
| 105 | + ? 'Your account is fully authenticated and your withdrawal limits have been lifted' |
| 106 | + : 'Stated limits are subject to change without prior notice.', |
| 107 | + }, |
| 108 | +]; |
| 109 | + |
| 110 | +export const getAccountLimitValues = (accountLimits: GetLimits, currency: TCurrency, isAuthenticated = false) => { |
| 111 | + const { |
| 112 | + account_balance: accountBalance, |
| 113 | + market_specific: marketSpecific, |
| 114 | + num_of_days_limit: numberOfDaysLimit, |
| 115 | + open_positions: openPositions, |
| 116 | + payout = 0, |
| 117 | + remainder, |
| 118 | + withdrawal_since_inception_monetary: withdrawalSinceInceptionMonetary, |
| 119 | + } = accountLimits; |
| 120 | + |
| 121 | + return [ |
| 122 | + ...getTradingLimitsTableData(currency, payout, openPositions, accountBalance), |
| 123 | + ...getMaximumDailyLimiitsTableData(marketSpecific, currency), |
| 124 | + ...getWithdrawalLimitsTableData( |
| 125 | + isAuthenticated, |
| 126 | + currency, |
| 127 | + numberOfDaysLimit, |
| 128 | + withdrawalSinceInceptionMonetary, |
| 129 | + remainder |
| 130 | + ), |
| 131 | + ]; |
| 132 | +}; |
0 commit comments