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

[Wallet] Use the country of the phone number for determining the default local currency #1684

Merged
merged 2 commits into from
Nov 13, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
47 changes: 47 additions & 0 deletions packages/mobile/src/localCurrency/selectors.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { getLocalCurrencyCode } from 'src/localCurrency/selectors'

describe(getLocalCurrencyCode, () => {
describe('when no preferred currency is set', () => {
it('returns the first supported local currency for the country of the phone number', () => {
const state: any = {
account: { e164PhoneNumber: '+231881551952' },
localCurrency: { preferredCurrencyCode: undefined },
}
expect(getLocalCurrencyCode(state)).toEqual('LRD')
})

it('returns null for US phone numbers', () => {
const state: any = {
account: { e164PhoneNumber: '+14155552671' },
localCurrency: { preferredCurrencyCode: undefined },
}
expect(getLocalCurrencyCode(state)).toBeNull()
})

it('returns CAD for CA phone numbers', () => {
const state: any = {
account: { e164PhoneNumber: '+18192216929' },
localCurrency: { preferredCurrencyCode: undefined },
}
expect(getLocalCurrencyCode(state)).toEqual('CAD')
})
})

describe('when a preferred currency is set', () => {
it('returns the preferred currency', () => {
const state: any = {
account: { e164PhoneNumber: '+231881551952' },
localCurrency: { preferredCurrencyCode: 'MXN' },
}
expect(getLocalCurrencyCode(state)).toEqual('MXN')
})

it('returns null when USD is the preferred currency', () => {
const state: any = {
account: { e164PhoneNumber: '+14155552671' },
localCurrency: { preferredCurrencyCode: 'USD' },
}
expect(getLocalCurrencyCode(state)).toBeNull()
})
})
})
48 changes: 32 additions & 16 deletions packages/mobile/src/localCurrency/selectors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import * as RNLocalize from 'react-native-localize'
import { getRegionCode } from '@celo/utils/src/phoneNumbers'
import CountryData from 'country-data'
import { createSelector } from 'reselect'
import { e164NumberSelector } from 'src/account/reducer'
import {
LOCAL_CURRENCY_CODES,
LocalCurrencyCode,
Expand All @@ -8,25 +11,37 @@ import { RootState } from 'src/redux/reducers'

const MIN_UPDATE_INTERVAL = 12 * 3600 * 1000 // 12 hours

// Returns the best currency possible (it respects the user preferred currencies list order).
function findBestAvailableCurrency(supportedCurrencyCodes: LocalCurrencyCode[]) {
const deviceCurrencies = RNLocalize.getCurrencies()
const supportedCurrenciesSet = new Set(supportedCurrencyCodes)
function getCountryCurrencies(e164PhoneNumber: string) {
const regionCode = getRegionCode(e164PhoneNumber)
const countries = CountryData.lookup.countries({ alpha2: regionCode })
const country = countries.length > 0 ? countries[0] : undefined

for (const deviceCurrency of deviceCurrencies) {
if (supportedCurrenciesSet.has(deviceCurrency as LocalCurrencyCode)) {
return deviceCurrency as LocalCurrencyCode
}
}

return null
return country ? country.currencies : []
}

// TODO(jean): listen to locale changes so this stays accurate when changed while the app is running
const DEVICE_BEST_CURRENCY_CODE = findBestAvailableCurrency(LOCAL_CURRENCY_CODES)
const getDefaultLocalCurrencyCode = createSelector(
e164NumberSelector,
(e164PhoneNumber): LocalCurrencyCode | null => {
// Note: we initially tried using the device locale for getting the currencies (`RNLocalize.getCurrencies()`)
// but the problem is some Android versions don't make it possible to select the appropriate language/country
// from the device settings.
// So here we use the country of the phone number
const countryCurrencies = getCountryCurrencies(e164PhoneNumber)
const supportedCurrenciesSet = new Set(LOCAL_CURRENCY_CODES)

for (const countryCurrency of countryCurrencies) {
if (supportedCurrenciesSet.has(countryCurrency as LocalCurrencyCode)) {
return countryCurrency as LocalCurrencyCode
}
}

return LocalCurrencyCode.USD
}
)

export function getLocalCurrencyCode(state: RootState): LocalCurrencyCode | null {
const currencyCode = state.localCurrency.preferredCurrencyCode || DEVICE_BEST_CURRENCY_CODE
const currencyCode =
state.localCurrency.preferredCurrencyCode || getDefaultLocalCurrencyCode(state)
if (!currencyCode || currencyCode === LocalCurrencyCode.USD) {
// This disables local currency display
return null
Expand All @@ -36,7 +51,8 @@ export function getLocalCurrencyCode(state: RootState): LocalCurrencyCode | null
}

export function getLocalCurrencySymbol(state: RootState): LocalCurrencySymbol | null {
const currencyCode = state.localCurrency.preferredCurrencyCode || DEVICE_BEST_CURRENCY_CODE
const currencyCode =
state.localCurrency.preferredCurrencyCode || getDefaultLocalCurrencyCode(state)

return currencyCode ? LocalCurrencySymbol[currencyCode] : null
}
Expand Down