Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: multi currency support #1873

Merged
merged 57 commits into from
Jul 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
0ebecab
chore: update packages
0xdef1cafe May 20, 2022
2223141
chore: add new headers
0xdef1cafe May 20, 2022
7378dde
feat: add new translations
0xdef1cafe May 20, 2022
39e429f
feat: add fiat market data
0xdef1cafe May 20, 2022
caaca76
feat: fetch fiat market data in app context
0xdef1cafe May 20, 2022
425ac00
chore: blacklist large things from redux store
0xdef1cafe May 20, 2022
d1e2814
fix: more correct type defs and balance chart fixes
0xdef1cafe May 20, 2022
bc599ae
chore: fix headers comment
0xdef1cafe May 20, 2022
aca507e
chore: consolidate to priceAtDate
0xdef1cafe May 20, 2022
c4a4fba
chore: only upgrade market service package
0xdef1cafe May 20, 2022
6e28f9f
chore: use same source of truth for mock test data as real data struc…
0xdef1cafe May 20, 2022
0dba950
fix: optimizations and bug fixes
0xdef1cafe May 20, 2022
844a4c5
fix: market data refetch
0xdef1cafe May 21, 2022
bbf9c8e
chore: merge develop
0xdef1cafe May 21, 2022
f69d726
Merge branch 'develop' into fiat-market-data-slice
0xdef1cafe May 24, 2022
15c5d6c
chore: rename booleans for readability
0xdef1cafe May 24, 2022
61d58f4
chore: tighter type def for setFiatMarketData
0xdef1cafe May 24, 2022
a855abf
chore: freeze initial price history for safety
0xdef1cafe May 24, 2022
56382a4
chore: uppercase const
0xdef1cafe May 24, 2022
bd4e5a0
chore: consistent market data selector naming
0xdef1cafe May 24, 2022
149fa31
feat: view layer changes to support multi currency display
0xdef1cafe May 24, 2022
4e7e823
feat: add currency selection to settings modal
0xdef1cafe May 24, 2022
fd2cfae
chore: add multi currency feature flag
0xdef1cafe May 24, 2022
0bf62f0
feat: balance chart changes
0xdef1cafe May 24, 2022
4017fc3
chore: delete duplicate test with wrong file extension
0xdef1cafe May 24, 2022
8e0b91d
chore: merge develop
0xdef1cafe May 24, 2022
dfcd3d0
chore: cache fee asset selector
0xdef1cafe May 24, 2022
a8e8570
chore: merge develop
0xdef1cafe May 25, 2022
9e4197a
Merge branch 'develop' into multi-currency-support
0xdef1cafe May 25, 2022
eb84a7c
Revert "chore: cache fee asset selector"
0xdef1cafe May 25, 2022
5978a6e
fix: revert chart loading behaviour
0xdef1cafe May 25, 2022
e117314
chore: merge develop
0xdef1cafe Jun 3, 2022
ee284b5
chore: merge develop
0xdef1cafe Jun 9, 2022
76f6679
fix: default fiatType to USD
0xdef1cafe Jun 9, 2022
55cfc75
test: fix useLocaleFormatter test
0xdef1cafe Jun 9, 2022
f67893d
Merge branch 'develop' into multi-currency-support
0xdef1cafe Jun 9, 2022
95080f9
chore: delete unnecessary locale renderers
0xdef1cafe Jun 9, 2022
2eb9195
chore: revert unnecessary changes to locale formatter
0xdef1cafe Jun 9, 2022
f434b70
chore: merge develop
0xdef1cafe Jun 9, 2022
cfe318a
chore: merge develop
0xdef1cafe Jun 16, 2022
aafd3e4
chore: merge develop
0xdef1cafe Jul 11, 2022
439ecda
Merge remote-tracking branch 'origin' into multi-currency-support
stackedq Jul 14, 2022
9b4574c
fix: improved number formatting
stackedq Jul 19, 2022
f0bdbdf
feat: currency format settings
stackedq Jul 20, 2022
c66b400
fix: conflicts resolved
stackedq Jul 20, 2022
d486238
fix: test case fixed
stackedq Jul 20, 2022
fbc6036
fix: improved input parsing
stackedq Jul 20, 2022
8e6d4bf
chore: fix typo
0xdef1cafe Jul 20, 2022
ea60e8e
feat: walletconnect wallet (#1733)
GMSteuart Jul 20, 2022
0a2be2e
chore(deps): bump terser from 4.8.0 to 4.8.1 (#2197)
dependabot[bot] Jul 20, 2022
97c1c76
feat: dogecoin (#2185)
asamere Jul 21, 2022
2535512
fix: typo and lodash import
stackedq Jul 21, 2022
9a4018b
fix: conflict resolved
stackedq Jul 21, 2022
8cab0f6
fix: conflict resolved
stackedq Jul 21, 2022
7d0b929
Merge branch 'develop' into multi-currency-support
reallybeard Jul 22, 2022
c4f1981
feat: keeping order of fiat currencies and currency formats
stackedq Jul 23, 2022
cbd8ff4
fix: applying suggested changes
stackedq Jul 24, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sample.env
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ REACT_APP_MIDGARD_URL=https://midgard.thorchain.info/v2

REACT_APP_FRIENDLY_CAPTCHA_SITE_KEY=FCMM7AFC0S6A8NUK

REACT_APP_FEATURE_MULTI_CURRENCY=false
REACT_APP_FEATURE_OSMOSIS=false
REACT_APP_FEATURE_WALLETCONNECT_WALLET=false
REACT_APP_FEATURE_AVALANCHE=false
Expand Down
1 change: 1 addition & 0 deletions src/assets/translations/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,7 @@
"settings": {
"settings": "Settings",
"currency": "Currency",
"currencyFormat": "Currency Format",
"language": "Language",
"balanceThreshold": "Balance Threshold",
"balanceThresholdTooltip": "Hide balances below this value",
Expand Down
48 changes: 29 additions & 19 deletions src/components/Amount/Amount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,28 @@ type AmountProps = {
value: number | string
prefix?: string
suffix?: string
omitDecimalTrailingZeros?: boolean
abbreviated?: boolean
maximumFractionDigits?: number
} & TextProps

export function Amount({
value,
prefix = '',
suffix = '',
maximumFractionDigits,
omitDecimalTrailingZeros = false,
abbreviated = false,
...props
}: any): React.ReactElement {
const {
number: { toString },
} = useLocaleFormatter({ fiatType: 'USD' })
} = useLocaleFormatter()

return (
<RawText {...props}>
{prefix}
{toString(value, { maximumFractionDigits })}
{toString(value, { maximumFractionDigits, omitDecimalTrailingZeros, abbreviated })}
{suffix}
</RawText>
)
Expand Down Expand Up @@ -56,13 +61,14 @@ const Crypto = ({
maximumFractionDigits = 8,
prefix,
suffix,
omitDecimalTrailingZeros = false,
...props
}: CryptoAmountProps) => {
const {
number: { toCrypto, toParts },
} = useLocaleFormatter({ fiatType: 'USD' })
} = useLocaleFormatter()

const crypto = toCrypto(value, symbol, { maximumFractionDigits })
const crypto = toCrypto(value, symbol, { maximumFractionDigits, omitDecimalTrailingZeros })

if (!cryptoSymbolStyle) {
return (
Expand Down Expand Up @@ -93,12 +99,27 @@ const Crypto = ({
)
}

const Fiat = ({ value, fiatSymbolStyle, fiatType, prefix, suffix, ...props }: FiatAmountProps) => {
const Fiat = ({
value,
fiatSymbolStyle,
fiatType,
prefix,
suffix,
maximumFractionDigits,
omitDecimalTrailingZeros = false,
abbreviated = false,
...props
}: FiatAmountProps) => {
const {
number: { toFiat, toParts },
} = useLocaleFormatter({ fiatType: fiatType || 'USD' })
} = useLocaleFormatter({ fiatType })

const fiat = toFiat(value, { fiatType })
const fiat = toFiat(value, {
fiatType,
omitDecimalTrailingZeros,
abbreviated,
maximumFractionDigits,
})

if (!fiatSymbolStyle) {
return (
Expand Down Expand Up @@ -132,7 +153,7 @@ const Fiat = ({ value, fiatSymbolStyle, fiatType, prefix, suffix, ...props }: Fi
const Percent = ({ value, autoColor, options, prefix, suffix, ...props }: PercentAmountProps) => {
const {
number: { toPercent },
} = useLocaleFormatter({ fiatType: 'USD' })
} = useLocaleFormatter()
const formattedNumber = toPercent(value, options)

const color = useMemo(() => {
Expand All @@ -155,17 +176,6 @@ const Percent = ({ value, autoColor, options, prefix, suffix, ...props }: Percen
)
}

const Supply = ({ value, ...props }: AmountProps) => {
const {
number: { toSupply },
} = useLocaleFormatter({ fiatType: 'USD' })

const volume = toSupply(value)

return <RawText {...props}>{volume}</RawText>
}

Amount.Crypto = Crypto
Amount.Fiat = Fiat
Amount.Percent = Percent
Amount.Supply = Supply
2 changes: 1 addition & 1 deletion src/components/Approval/Approval.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const Approval = () => {
const { approveInfinite, checkApprovalNeeded, updateTrade } = useSwapper()
const {
number: { toCrypto, toFiat },
} = useLocaleFormatter({ fiatType: 'USD' })
} = useLocaleFormatter()
const {
state: { isConnected },
dispatch,
Expand Down
2 changes: 1 addition & 1 deletion src/components/AssetHeader/AssetChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ type AssetChartProps = {
export const AssetChart = ({ accountId, assetId, isLoaded }: AssetChartProps) => {
const {
number: { toFiat },
} = useLocaleFormatter({ fiatType: 'USD' })
} = useLocaleFormatter()
const [percentChange, setPercentChange] = useState(0)
const alertIconColor = useColorModeValue('blue.500', 'blue.200')
const [timeframe, setTimeframe] = useState(DEFAULT_HISTORY_TIMEFRAME)
Expand Down
8 changes: 6 additions & 2 deletions src/components/AssetHeader/AssetMarketData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export const AssetMarketData: React.FC<AssetMarketDataProps> = ({ assetId }) =>
<Text translation='assets.assetDetails.assetHeader.maxTotalSupply' />
</StatLabel>
<StatValue isLoaded={isLoaded}>
<Amount.Supply value={marketData?.maxSupply ?? 0} />
<Amount value={marketData?.maxSupply ?? 0} abbreviated omitDecimalTrailingZeros />
</StatValue>
</StatRow>
)}
Expand All @@ -114,7 +114,11 @@ export const AssetMarketData: React.FC<AssetMarketDataProps> = ({ assetId }) =>
<Text translation='assets.assetDetails.assetHeader.availableSupply' />
</StatLabel>
<StatValue isLoaded={isLoaded}>
<Amount.Supply value={marketData?.supply} />
<Amount
value={Math.round(Number(marketData?.supply ?? 0))}
abbreviated
omitDecimalTrailingZeros
/>
</StatValue>
</StatRow>
)}
Expand Down
2 changes: 1 addition & 1 deletion src/components/DeFi/components/AssetInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export const AssetInput: React.FC<AssetInputProps> = ({
}) => {
const {
number: { localeParts },
} = useLocaleFormatter({ fiatType: 'USD' })
} = useLocaleFormatter()
const translate = useTranslate()
const amountRef = useRef<string | null>(null)
const [isFiat, setIsFiat] = useState<boolean>(false)
Expand Down
2 changes: 1 addition & 1 deletion src/components/Graph/PrimaryChart/PrimaryChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const PrimaryChart = ({

const {
number: { toFiat },
} = useLocaleFormatter({ fiatType: 'USD' })
} = useLocaleFormatter()

const [chartColor] = useToken('colors', [color])
const tooltipBg = useColorModeValue('white', colors.gray[800])
Expand Down
7 changes: 4 additions & 3 deletions src/components/Modals/Send/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
import { SelectAssetRoutes } from 'components/SelectAssets/SelectAssetCommon'
import { SelectAssetRouter } from 'components/SelectAssets/SelectAssetRouter'
import { AccountSpecifier } from 'state/slices/accountSpecifiersSlice/accountSpecifiersSlice'
import { selectMarketDataById } from 'state/slices/selectors'
import { selectMarketDataById, selectSelectedCurrency } from 'state/slices/selectors'
import { useAppSelector } from 'state/store'

import { useFormSend } from './hooks/useFormSend/useFormSend'
Expand Down Expand Up @@ -50,6 +50,7 @@ export const Form = ({ asset: initialAsset, accountId }: SendFormProps) => {
const location = useLocation()
const history = useHistory()
const { handleSend } = useFormSend()
const selectedCurrency = useAppSelector(selectSelectedCurrency)
const marketData = useAppSelector(state => selectMarketDataById(state, initialAsset.assetId))

const methods = useForm<SendInput>({
Expand All @@ -63,7 +64,7 @@ export const Form = ({ asset: initialAsset, accountId }: SendFormProps) => {
cryptoAmount: '',
cryptoSymbol: initialAsset?.symbol,
fiatAmount: '',
fiatSymbol: 'USD', // TODO: use user preferences to get default fiat currency
fiatSymbol: selectedCurrency,
},
})

Expand All @@ -72,7 +73,7 @@ export const Form = ({ asset: initialAsset, accountId }: SendFormProps) => {
methods.setValue(SendFormFields.CryptoAmount, '')
methods.setValue(SendFormFields.CryptoSymbol, asset.symbol)
methods.setValue(SendFormFields.FiatAmount, '')
methods.setValue(SendFormFields.FiatSymbol, 'USD')
methods.setValue(SendFormFields.FiatSymbol, selectedCurrency)
methods.setValue(SendFormFields.AccountId, accountId)

history.push(SendRoutes.Address)
Expand Down
2 changes: 1 addition & 1 deletion src/components/Modals/Settings/BalanceThresholdInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const BalanceThresholdInput = () => {
const dispatch = useAppDispatch()
const {
number: { localeParts },
} = useLocaleFormatter({ fiatType: 'USD' })
} = useLocaleFormatter()
const onChange = (value: string) => {
dispatch(preferences.actions.setBalanceThreshold({ threshold: value }))
}
Expand Down
82 changes: 82 additions & 0 deletions src/components/Modals/Settings/CurrencyFormat.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { ArrowBackIcon } from '@chakra-ui/icons'
import { Button, Flex, Icon, IconButton, ModalBody, ModalHeader } from '@chakra-ui/react'
import identity from 'lodash/identity'
import sortBy from 'lodash/sortBy'
import { FaCheck } from 'react-icons/fa'
import { useTranslate } from 'react-polyglot'
import { useHistory } from 'react-router-dom'
import { SlideTransition } from 'components/SlideTransition'
import { RawText } from 'components/Text'
import { CurrencyFormats, preferences } from 'state/slices/preferencesSlice/preferencesSlice'
import { selectCurrencyFormat } from 'state/slices/selectors'
import { useAppDispatch, useAppSelector } from 'state/store'

import { currencyFormatsRepresenter } from './SettingsCommon'

export const CurrencyFormat = () => {
const dispatch = useAppDispatch()
const currentCurrencyFormat = useAppSelector(selectCurrencyFormat)
const translate = useTranslate()
const history = useHistory()
const { goBack } = history
const formats = sortBy(CurrencyFormats, identity)
const { setCurrencyFormat } = preferences.actions

return (
<SlideTransition>
<IconButton
variant='ghost'
icon={<ArrowBackIcon />}
aria-label={translate('common.back')}
position='absolute'
top={2}
left={3}
fontSize='xl'
size='sm'
isRound
onClick={goBack}
/>
<ModalHeader textAlign='center'>{translate('modals.settings.currencyFormat')}</ModalHeader>
<>
<ModalBody
alignItems='center'
justifyContent='center'
textAlign='center'
maxHeight='400'
overflowY='auto'
overflowX='hidden'
>
{formats.map(currencyFormat => {
const active = currencyFormat === currentCurrencyFormat
const buttonProps = active
? {
disabled: true,
_disabled: { opacity: 1 },
}
: {
pl: 8,
variant: 'ghost',
onClick: () => dispatch(setCurrencyFormat({ currencyFormat })),
}
return (
<Button
mb={2}
width='full'
justifyContent='flexStart'
key={currencyFormat}
{...buttonProps}
>
<Flex alignItems='center' textAlign='left'>
{active && <Icon as={FaCheck} color='blue.500' />}
<Flex ml={4}>
<RawText>{currencyFormatsRepresenter[currencyFormat]}</RawText>
</Flex>
</Flex>
</Button>
)
})}
</ModalBody>
</>
</SlideTransition>
)
}
87 changes: 87 additions & 0 deletions src/components/Modals/Settings/FiatCurrencies.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { ArrowBackIcon } from '@chakra-ui/icons'
import { Button, Flex, Icon, IconButton, ModalBody, ModalHeader } from '@chakra-ui/react'
import { SupportedFiatCurrencies, SupportedFiatCurrenciesList } from '@shapeshiftoss/market-service'
import identity from 'lodash/identity'
import sortBy from 'lodash/sortBy'
import { FaCheck } from 'react-icons/fa'
import { useTranslate } from 'react-polyglot'
import { useHistory } from 'react-router-dom'
import { SlideTransition } from 'components/SlideTransition'
import { RawText, Text } from 'components/Text'
import { preferences } from 'state/slices/preferencesSlice/preferencesSlice'
import { selectSelectedCurrency } from 'state/slices/selectors'
import { useAppDispatch, useAppSelector } from 'state/store'

export const FiatCurrencies = () => {
const dispatch = useAppDispatch()
const selectedCurrency = useAppSelector(selectSelectedCurrency)
const translate = useTranslate()
const history = useHistory()
const { goBack } = history
const defaultCurrency: SupportedFiatCurrencies = 'USD'
const allFiatCurrencies = sortBy(SupportedFiatCurrenciesList, item =>
// keep default currency at the top of the list
item === defaultCurrency ? defaultCurrency : identity,
)
const { setSelectedCurrency } = preferences.actions

return (
<SlideTransition>
<IconButton
variant='ghost'
icon={<ArrowBackIcon />}
aria-label={translate('common.back')}
position='absolute'
top={2}
left={3}
fontSize='xl'
size='sm'
isRound
onClick={goBack}
/>
<ModalHeader textAlign='center'>{translate('modals.settings.currency')}</ModalHeader>
<>
<ModalBody
alignItems='center'
justifyContent='center'
textAlign='center'
maxHeight='400'
overflowY='auto'
overflowX='hidden'
>
{allFiatCurrencies.map(currency => {
const active = currency === selectedCurrency
const buttonProps = active
? {
disabled: true,
_disabled: { opacity: 1 },
}
: {
pl: 8,
variant: 'ghost',
onClick: () => dispatch(setSelectedCurrency({ currency })),
}
return (
<Button
width='full'
justifyContent='flexStart'
key={currency}
mb={2}
{...buttonProps}
>
<Flex alignItems='center' textAlign='left'>
{active && <Icon as={FaCheck} color='blue.500' />}
<Flex ml={4}>
<RawText>{currency}</RawText>
<RawText mx={2}>-</RawText>
<Text translation={`modals.settings.currencies.${currency}`} />
</Flex>
</Flex>
</Button>
)
})}
</ModalBody>
</>
</SlideTransition>
)
}
Loading