Add coin by network (#1505)

* Add coin by network

* Join tests in same file

Co-authored-by: Daniel Sanchez <daniel.sanchez@gnosis.pm>
This commit is contained in:
nicolas 2020-10-23 07:58:46 -03:00 committed by GitHub
parent 56430b5966
commit 8aeb5a1c01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 403 additions and 367 deletions

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 256 255.8" style="enable-background:new 0 0 256 255.8;" xml:space="preserve">
<style type="text/css">
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#48A9A6;}
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
</style>
<title>Group 6</title>
<desc>Created with Sketch.</desc>
<g id="Page-1">
<g id="Artboard">
<g id="Group-6">
<path id="Fill-1" class="st0" d="M128,0c70.6,0,128,57.3,128,127.9s-57.4,127.9-128,127.9S0,198.5,0,127.9S57.4,0,128,0z"/>
<polygon id="Fill-2" class="st1" points="62.3,88.6 114.9,88.6 114.9,62.3 62.3,62.3 "/>
<polygon id="Fill-3" class="st1" points="141.1,88.6 193.7,88.6 193.7,62.3 141.1,62.3 "/>
<polygon id="Fill-4" class="st1" points="193.7,141.1 167.4,141.1 167.4,167.4 141.1,167.4 141.1,193.7 193.7,193.7 "/>
<polygon id="Fill-5" class="st1" points="114.9,193.7 114.9,167.4 88.6,167.4 88.6,141.1 62.3,141.1 62.3,193.7 "/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1,4 +1,4 @@
import EtherLogo from 'src/assets/icons/icon_etherTokens.svg' import EtherLogo from 'src/config/assets/token_eth.svg'
import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkConfig } from 'src/config/networks/network.d' import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkConfig } from 'src/config/networks/network.d'
const baseConfig: EnvironmentSettings = { const baseConfig: EnvironmentSettings = {

View File

@ -1,4 +1,4 @@
import EtherLogo from 'src/assets/icons/icon_etherTokens.svg' import EtherLogo from 'src/config/assets/token_eth.svg'
import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkConfig } from 'src/config/networks/network.d' import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkConfig } from 'src/config/networks/network.d'
const baseConfig: EnvironmentSettings = { const baseConfig: EnvironmentSettings = {

View File

@ -1,4 +1,4 @@
import EtherLogo from 'src/assets/icons/icon_etherTokens.svg' import EtherLogo from 'src/config/assets/token_eth.svg'
import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkConfig } from 'src/config/networks/network.d' import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkConfig } from 'src/config/networks/network.d'
const baseConfig: EnvironmentSettings = { const baseConfig: EnvironmentSettings = {

View File

@ -1,4 +1,5 @@
import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkConfig } from 'src/config/networks/network.d' import { EnvironmentSettings, ETHEREUM_NETWORK, NetworkConfig } from 'src/config/networks/network.d'
import xDaiLogo from 'src/config/assets/token_xdai.svg'
const baseConfig: EnvironmentSettings = { const baseConfig: EnvironmentSettings = {
txServiceUrl: 'https://safe-transaction.xdai.gnosis.io/api/v1', txServiceUrl: 'https://safe-transaction.xdai.gnosis.io/api/v1',
@ -32,7 +33,7 @@ const xDai: NetworkConfig = {
name: 'xDai', name: 'xDai',
symbol: 'xDai', symbol: 'xDai',
decimals: 18, decimals: 18,
logoUri: '', logoUri: xDaiLogo,
}, },
} }
} }

View File

@ -1,29 +1,30 @@
import axios from 'axios' import axios from 'axios'
import { EXCHANGE_RATE_URL } from 'src/utils/constants'
import { AVAILABLE_CURRENCIES } from '../store/model/currencyValues'
import { fetchTokenCurrenciesBalances } from './fetchTokenCurrenciesBalances'
import BigNumber from 'bignumber.js' import BigNumber from 'bignumber.js'
import { EXCHANGE_RATE_URL } from 'src/utils/constants'
import { fetchTokenCurrenciesBalances } from './fetchTokenCurrenciesBalances'
import { sameString } from 'src/utils/strings'
import { AVAILABLE_CURRENCIES } from '../store/model/currencyValues'
const fetchCurrenciesRates = async ( const fetchCurrenciesRates = async (
baseCurrency: AVAILABLE_CURRENCIES, baseCurrency: string,
targetCurrencyValue: AVAILABLE_CURRENCIES, targetCurrencyValue: string,
safeAddress: string, safeAddress: string,
): Promise<number> => { ): Promise<number> => {
let rate = 0 let rate = 0
if (sameString(targetCurrencyValue, AVAILABLE_CURRENCIES.NETWORK)) {
if (targetCurrencyValue === AVAILABLE_CURRENCIES.ETH) {
try { try {
const result = await fetchTokenCurrenciesBalances(safeAddress) const result = await fetchTokenCurrenciesBalances(safeAddress)
if (result?.data?.length) { if (result?.data?.length) {
rate = new BigNumber(1).div(result.data[0].fiatConversion).toNumber() rate = new BigNumber(1).div(result.data[0].fiatConversion).toNumber()
} }
} catch (error) { } catch (error) {
console.error('Fetching ETH data from the relayer errored', error) console.error(`Fetching ${AVAILABLE_CURRENCIES.NETWORK} data from the relayer errored`, error)
} }
return rate return rate
} }
// National currencies
try { try {
const url = `${EXCHANGE_RATE_URL}?base=${baseCurrency}&symbols=${targetCurrencyValue}` const url = `${EXCHANGE_RATE_URL}?base=${baseCurrency}&symbols=${targetCurrencyValue}`
const result = await axios.get(url) const result = await axios.get(url)

View File

@ -2,7 +2,6 @@ import axios, { AxiosResponse } from 'axios'
import { getTxServiceUrl } from 'src/config' import { getTxServiceUrl } from 'src/config'
import { TokenProps } from 'src/logic/tokens/store/model/token' import { TokenProps } from 'src/logic/tokens/store/model/token'
import { AVAILABLE_CURRENCIES } from '../store/model/currencyValues'
export type BalanceEndpoint = { export type BalanceEndpoint = {
tokenAddress: string tokenAddress: string
@ -10,7 +9,7 @@ export type BalanceEndpoint = {
balance: string balance: string
fiatBalance: string fiatBalance: string
fiatConversion: string fiatConversion: string
fiatCode: AVAILABLE_CURRENCIES fiatCode: string
} }
export const fetchTokenCurrenciesBalances = ( export const fetchTokenCurrenciesBalances = (

View File

@ -3,7 +3,7 @@ import { setCurrencyRate } from 'src/logic/currencyValues/store/actions/setCurre
import { AVAILABLE_CURRENCIES } from 'src/logic/currencyValues/store/model/currencyValues' import { AVAILABLE_CURRENCIES } from 'src/logic/currencyValues/store/model/currencyValues'
import { Dispatch } from 'redux' import { Dispatch } from 'redux'
const fetchCurrencyRate = (safeAddress: string, selectedCurrency: AVAILABLE_CURRENCIES) => async ( const fetchCurrencyRate = (safeAddress: string, selectedCurrency: string) => async (
dispatch: Dispatch<typeof setCurrencyRate>, dispatch: Dispatch<typeof setCurrencyRate>,
): Promise<void> => { ): Promise<void> => {
if (AVAILABLE_CURRENCIES.USD === selectedCurrency) { if (AVAILABLE_CURRENCIES.USD === selectedCurrency) {

View File

@ -2,20 +2,16 @@ import { createAction } from 'redux-actions'
import { ThunkDispatch } from 'redux-thunk' import { ThunkDispatch } from 'redux-thunk'
import { AnyAction } from 'redux' import { AnyAction } from 'redux'
import { AppReduxState } from 'src/store' import { AppReduxState } from 'src/store'
import { AVAILABLE_CURRENCIES } from '../model/currencyValues'
import fetchCurrencyRate from 'src/logic/currencyValues/store/actions/fetchCurrencyRate' import fetchCurrencyRate from 'src/logic/currencyValues/store/actions/fetchCurrencyRate'
export const SET_CURRENT_CURRENCY = 'SET_CURRENT_CURRENCY' export const SET_CURRENT_CURRENCY = 'SET_CURRENT_CURRENCY'
const setCurrentCurrency = createAction( const setCurrentCurrency = createAction(SET_CURRENT_CURRENCY, (safeAddress: string, selectedCurrency: string) => ({
SET_CURRENT_CURRENCY, safeAddress,
(safeAddress: string, selectedCurrency: AVAILABLE_CURRENCIES) => ({ selectedCurrency,
safeAddress, }))
selectedCurrency,
}),
)
export const setSelectedCurrency = (safeAddress: string, selectedCurrency: AVAILABLE_CURRENCIES) => ( export const setSelectedCurrency = (safeAddress: string, selectedCurrency: string) => (
dispatch: ThunkDispatch<AppReduxState, undefined, AnyAction>, dispatch: ThunkDispatch<AppReduxState, undefined, AnyAction>,
): void => { ): void => {
dispatch(setCurrentCurrency(safeAddress, selectedCurrency)) dispatch(setCurrentCurrency(safeAddress, selectedCurrency))

View File

@ -1,41 +1,45 @@
import { List, Record, RecordOf } from 'immutable' import { List, Record, RecordOf } from 'immutable'
export enum AVAILABLE_CURRENCIES { import { getNetworkInfo } from 'src/config'
ETH = 'ETH',
USD = 'USD', const { nativeCoin } = getNetworkInfo()
EUR = 'EUR',
AUD = 'AUD', export const AVAILABLE_CURRENCIES = {
BGN = 'BGN', NETWORK: nativeCoin.symbol.toLocaleUpperCase(),
BRL = 'BRL', USD: 'USD',
CAD = 'CAD', EUR: 'EUR',
CHF = 'CHF', AUD: 'AUD',
CNY = 'CNY', BGN: 'BGN',
CZK = 'CZK', BRL: 'BRL',
DKK = 'DKK', CAD: 'CAD',
GBP = 'GBP', CHF: 'CHF',
HKD = 'HKD', CNY: 'CNY',
HRK = 'HRK', CZK: 'CZK',
HUF = 'HUF', DKK: 'DKK',
IDR = 'IDR', GBP: 'GBP',
ILS = 'ILS', HKD: 'HKD',
INR = 'INR', HRK: 'HRK',
ISK = 'ISK', HUF: 'HUF',
JPY = 'JPY', IDR: 'IDR',
KRW = 'KRW', ILS: 'ILS',
MXN = 'MXN', INR: 'INR',
MYR = 'MYR', ISK: 'ISK',
NOK = 'NOK', JPY: 'JPY',
NZD = 'NZD', KRW: 'KRW',
PHP = 'PHP', MXN: 'MXN',
PLN = 'PLN', MYR: 'MYR',
RON = 'RON', NOK: 'NOK',
RUB = 'RUB', NZD: 'NZD',
SEK = 'SEK', PHP: 'PHP',
SGD = 'SGD', PLN: 'PLN',
THB = 'THB', RON: 'RON',
TRY = 'TRY', RUB: 'RUB',
ZAR = 'ZAR', SEK: 'SEK',
} SGD: 'SGD',
THB: 'THB',
TRY: 'TRY',
ZAR: 'ZAR',
} as const
export type BalanceCurrencyRecord = { export type BalanceCurrencyRecord = {
currencyName?: string currencyName?: string
@ -57,6 +61,6 @@ export type BalanceCurrencyList = List<CurrencyRateValueRecord>
export interface CurrencyRateValue { export interface CurrencyRateValue {
currencyRate?: number currencyRate?: number
selectedCurrency?: AVAILABLE_CURRENCIES selectedCurrency?: string
currencyBalances?: BalanceCurrencyList currencyBalances?: BalanceCurrencyList
} }

View File

@ -1,8 +1,7 @@
import { loadFromStorage, saveToStorage } from 'src/utils/storage' import { loadFromStorage, saveToStorage } from 'src/utils/storage'
import { AVAILABLE_CURRENCIES } from '../model/currencyValues'
const SELECTED_CURRENCY_STORAGE_KEY = 'SELECTED_CURRENCY' const SELECTED_CURRENCY_STORAGE_KEY = 'SELECTED_CURRENCY'
export const saveSelectedCurrency = async (selectedCurrency: AVAILABLE_CURRENCIES): Promise<void> => { export const saveSelectedCurrency = async (selectedCurrency: string): Promise<void> => {
try { try {
await saveToStorage(SELECTED_CURRENCY_STORAGE_KEY, selectedCurrency) await saveToStorage(SELECTED_CURRENCY_STORAGE_KEY, selectedCurrency)
} catch (err) { } catch (err) {
@ -10,6 +9,6 @@ export const saveSelectedCurrency = async (selectedCurrency: AVAILABLE_CURRENCIE
} }
} }
export const loadSelectedCurrency = async (): Promise<AVAILABLE_CURRENCIES | undefined> => { export const loadSelectedCurrency = async (): Promise<string | undefined> => {
return await loadFromStorage(SELECTED_CURRENCY_STORAGE_KEY) return await loadFromStorage(SELECTED_CURRENCY_STORAGE_KEY)
} }

View File

@ -0,0 +1,285 @@
//@ts-nocheck
import { List } from 'immutable'
import {
isUserAnOwner,
isUserAnOwnerOfAnySafe,
isValidEnsName,
sameAddress,
shortVersionOf,
} from 'src/logic/wallets/ethAddresses'
import makeSafe from 'src/logic/safe/store/models/safe'
import { makeOwner } from 'src/logic/safe/store/models/owner'
describe('src/logic/wallets/ethAddresses', () => {
describe('Utility function: sameAddress', () => {
it('It should return false if no address given', () => {
// given
const safeAddress = null
const safeAddress2 = '0x344B941b1aAE2e4Be73987212FC4741687Bf0503'
// when
const result = sameAddress(safeAddress, safeAddress2)
// then
expect(result).toBe(false)
})
it('It should return false if not second address given', () => {
// given
const safeAddress = '0xdfA693da0D16F5E7E78FdCBeDe8FC6eBEa44f1Cf'
const safeAddress2 = null
// when
const result = sameAddress(safeAddress, safeAddress2)
// then
expect(result).toBe(false)
})
it('It should return true if two equal addresses given', () => {
// given
const safeAddress = '0xdfA693da0D16F5E7E78FdCBeDe8FC6eBEa44f1Cf'
// when
const result = sameAddress(safeAddress, safeAddress.toLowerCase())
// then
expect(result).toBe(true)
})
it('If should return false if two different addresses given', () => {
// given
const safeAddress = '0xdfA693da0D16F5E7E78FdCBeDe8FC6eBEa44f1Cf'
const safeAddress2 = '0x344B941b1aAE2e4Be73987212FC4741687Bf0503'
// when
const result = sameAddress(safeAddress, safeAddress2)
// then
expect(result).toBe(false)
})
})
describe('Utility function: shortVersionOf', () => {
it('It should return Unknown if no address given', () => {
// given
const safeAddress = null
const cut = 5
const expectedResult = 'Unknown'
// when
const result = shortVersionOf(safeAddress, cut)
// then
expect(result).toBe(expectedResult)
})
it('It should return 0x344...f0503 if given 0x344B941b1aAE2e4Be73987212FC4741687Bf0503 and a cut = 5', () => {
// given
const safeAddress = '0x344B941b1aAE2e4Be73987212FC4741687Bf0503'
const cut = 5
const expectedResult = `0x344...f0503`
// when
const result = shortVersionOf(safeAddress, cut)
// then
expect(result).toBe(expectedResult)
})
it('If should return the same address if a cut value bigger than the address length given', () => {
// given
const safeAddress = '0x344B941b1aAE2e4Be73987212FC4741687Bf0503'
const cut = safeAddress.length
const expectedResult = safeAddress
// when
const result = shortVersionOf(safeAddress, cut)
// then
expect(result).toBe(expectedResult)
})
})
describe('Utility function: isUserAnOwner', () => {
it("Should return false if there's no Safe", () => {
// given
const userAddress = 'address1'
const safeInstance = null
const expectedResult = false
// when
const result = isUserAnOwner(safeInstance, userAddress)
// then
expect(result).toBe(expectedResult)
})
it("Should return false if there's no `userAccount`", () => {
// given
const userAddress = null
const owners = List([makeOwner({ address: userAddress })])
const safeInstance = makeSafe({ owners })
const expectedResult = false
// when
const result = isUserAnOwner(safeInstance, userAddress)
// then
expect(result).toBe(expectedResult)
})
it('Should return false if there are no owners for the Safe', () => {
// given
const userAddress = 'address1'
const owners = null
const safeInstance = makeSafe({ owners })
const expectedResult = false
// when
const result = isUserAnOwner(safeInstance, userAddress)
// then
expect(result).toBe(expectedResult)
})
it("Should return true if `userAccount` is not in the list of Safe's owners", () => {
// given
const userAddress = 'address1'
const owners = List([makeOwner({ address: userAddress })])
const safeInstance = makeSafe({ owners })
const expectedResult = true
// when
const result = isUserAnOwner(safeInstance, userAddress)
// then
expect(result).toBe(expectedResult)
})
it("Should return false if `userAccount` is not in the list of Safe's owners", () => {
// given
const userAddress = 'address1'
const userAddress2 = 'address2'
const owners = List([makeOwner({ address: userAddress })])
const safeInstance = makeSafe({ owners })
const expectedResult = false
// when
const result = isUserAnOwner(safeInstance, userAddress2)
// then
expect(result).toBe(expectedResult)
})
})
describe('Utility function: isUserAnOwnerOfAnySafe', () => {
it('Should return true if given a list of safes, one of them has an owner equal to the userAccount', () => {
// given
const userAddress = 'address1'
const userAddress2 = 'address2'
const owners1 = List([makeOwner({ address: userAddress })])
const owners2 = List([makeOwner({ address: userAddress2 })])
const safeInstance = makeSafe({ owners: owners1 })
const safeInstance2 = makeSafe({ owners: owners2 })
const safesList = List([safeInstance, safeInstance2])
const expectedResult = true
// when
const result = isUserAnOwnerOfAnySafe(safesList, userAddress)
// then
expect(result).toBe(expectedResult)
})
it('It should return false if given a list of safes, none of them has an owner equal to the userAccount', () => {
// given
const userAddress = 'address1'
const userAddress2 = 'address2'
const userAddress3 = 'address3'
const owners1 = List([makeOwner({ address: userAddress3 })])
const owners2 = List([makeOwner({ address: userAddress2 })])
const safeInstance = makeSafe({ owners: owners1 })
const safeInstance2 = makeSafe({ owners: owners2 })
const safesList = List([safeInstance, safeInstance2])
const expectedResult = false
// when
const result = isUserAnOwnerOfAnySafe(safesList, userAddress)
// then
expect(result).toBe(expectedResult)
})
})
describe('Utility function: isValidEnsName', () => {
it('If should return false if given no ens name', () => {
// given
const ensName = null
const expectedResult = false
// when
const result = isValidEnsName(ensName)
// then
expect(result).toBe(expectedResult)
})
it('It should return false for an ens without extension in format [value].[eth|test|xyz|luxe]', () => {
// given
const ensName = 'test'
const expectedResult = false
// when
const result = isValidEnsName(ensName)
// then
expect(result).toBe(expectedResult)
})
it('It should return false for an ens without the format [value].[eth|test|xyz|luxe]', () => {
// given
const ensName = 'test.et12312'
const expectedResult = false
// when
const result = isValidEnsName(ensName)
// then
expect(result).toBe(expectedResult)
})
it('It should return true for an ens in format [value].eth', () => {
// given
const ensName = 'test.eth'
const expectedResult = true
// when
const result = isValidEnsName(ensName)
// then
expect(result).toBe(expectedResult)
})
it('It should return true for ens in format [value].test', () => {
// given
const ensName = 'test.test'
const expectedResult = true
// when
const result = isValidEnsName(ensName)
// then
expect(result).toBe(expectedResult)
})
it('It should return true for an ens in the format [value].xyz', () => {
// given
const ensName = 'test.xyz'
const expectedResult = true
// when
const result = isValidEnsName(ensName)
// then
expect(result).toBe(expectedResult)
})
it('It should return true for an ens in format [value].luxe', () => {
// given
const ensName = 'test.luxe'
const expectedResult = true
// when
const result = isValidEnsName(ensName)
// then
expect(result).toBe(expectedResult)
})
})
})

View File

@ -1,17 +1,10 @@
import { List } from 'immutable' import { List } from 'immutable'
import { SafeRecord } from 'src/logic/safe/store/models/safe' import { SafeRecord } from 'src/logic/safe/store/models/safe'
import { sameString } from 'src/utils/strings'
export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
export const sameAddress = (firstAddress: string | undefined, secondAddress: string | undefined): boolean => { export const sameAddress = (firstAddress: string | undefined, secondAddress: string | undefined): boolean => {
if (!firstAddress) { return sameString(firstAddress, secondAddress)
return false
}
if (!secondAddress) {
return false
}
return firstAddress.toLowerCase() === secondAddress.toLowerCase()
} }
export const shortVersionOf = (value: string, cut: number): string => { export const shortVersionOf = (value: string, cut: number): string => {

View File

@ -1,282 +0,0 @@
//@ts-nocheck
import {
isUserAnOwner,
isUserAnOwnerOfAnySafe,
isValidEnsName,
sameAddress,
shortVersionOf,
} from 'src/logic/wallets/ethAddresses'
import makeSafe from 'src/logic/safe/store/models/safe'
import { makeOwner } from 'src/logic/safe/store/models/owner'
import { List } from 'immutable'
describe('Utility function: sameAddress', () => {
it('It should return false if no address given', () => {
// given
const safeAddress = null
const safeAddress2 = '0x344B941b1aAE2e4Be73987212FC4741687Bf0503'
// when
const result = sameAddress(safeAddress, safeAddress2)
// then
expect(result).toBe(false)
})
it('It should return false if not second address given', () => {
// given
const safeAddress = '0xdfA693da0D16F5E7E78FdCBeDe8FC6eBEa44f1Cf'
const safeAddress2 = null
// when
const result = sameAddress(safeAddress, safeAddress2)
// then
expect(result).toBe(false)
})
it('It should return true if two equal addresses given', () => {
// given
const safeAddress = '0xdfA693da0D16F5E7E78FdCBeDe8FC6eBEa44f1Cf'
// when
const result = sameAddress(safeAddress, safeAddress)
// then
expect(result).toBe(true)
})
it('If should return false if two different addresses given', () => {
// given
const safeAddress = '0xdfA693da0D16F5E7E78FdCBeDe8FC6eBEa44f1Cf'
const safeAddress2 = '0x344B941b1aAE2e4Be73987212FC4741687Bf0503'
// when
const result = sameAddress(safeAddress, safeAddress2)
// then
expect(result).toBe(false)
})
})
describe('Utility function: shortVersionOf', () => {
it('It should return Unknown if no address given', () => {
// given
const safeAddress = null
const cut = 5
const expectedResult = 'Unknown'
// when
const result = shortVersionOf(safeAddress, cut)
// then
expect(result).toBe(expectedResult)
})
it('It should return 0x344...f0503 if given 0x344B941b1aAE2e4Be73987212FC4741687Bf0503 and a cut = 5', () => {
// given
const safeAddress = '0x344B941b1aAE2e4Be73987212FC4741687Bf0503'
const cut = 5
const expectedResult = `0x344...f0503`
// when
const result = shortVersionOf(safeAddress, cut)
// then
expect(result).toBe(expectedResult)
})
it('If should return the same address if a cut value bigger than the address length given', () => {
// given
const safeAddress = '0x344B941b1aAE2e4Be73987212FC4741687Bf0503'
const cut = safeAddress.length
const expectedResult = safeAddress
// when
const result = shortVersionOf(safeAddress, cut)
// then
expect(result).toBe(expectedResult)
})
})
describe('Utility function: isUserAnOwner', () => {
it("Should return false if there's no Safe", () => {
// given
const userAddress = 'address1'
const safeInstance = null
const expectedResult = false
// when
const result = isUserAnOwner(safeInstance, userAddress)
// then
expect(result).toBe(expectedResult)
})
it("Should return false if there's no `userAccount`", () => {
// given
const userAddress = null
const owners = List([makeOwner({ address: userAddress })])
const safeInstance = makeSafe({ owners })
const expectedResult = false
// when
const result = isUserAnOwner(safeInstance, userAddress)
// then
expect(result).toBe(expectedResult)
})
it('Should return false if there are no owners for the Safe', () => {
// given
const userAddress = 'address1'
const owners = null
const safeInstance = makeSafe({ owners })
const expectedResult = false
// when
const result = isUserAnOwner(safeInstance, userAddress)
// then
expect(result).toBe(expectedResult)
})
it("Should return true if `userAccount` is not in the list of Safe's owners", () => {
// given
const userAddress = 'address1'
const owners = List([makeOwner({ address: userAddress })])
const safeInstance = makeSafe({ owners })
const expectedResult = true
// when
const result = isUserAnOwner(safeInstance, userAddress)
// then
expect(result).toBe(expectedResult)
})
it("Should return false if `userAccount` is not in the list of Safe's owners", () => {
// given
const userAddress = 'address1'
const userAddress2 = 'address2'
const owners = List([makeOwner({ address: userAddress })])
const safeInstance = makeSafe({ owners })
const expectedResult = false
// when
const result = isUserAnOwner(safeInstance, userAddress2)
// then
expect(result).toBe(expectedResult)
})
})
describe('Utility function: isUserAnOwnerOfAnySafe', () => {
it('Should return true if given a list of safes, one of them has an owner equal to the userAccount', () => {
// given
const userAddress = 'address1'
const userAddress2 = 'address2'
const owners1 = List([makeOwner({ address: userAddress })])
const owners2 = List([makeOwner({ address: userAddress2 })])
const safeInstance = makeSafe({ owners: owners1 })
const safeInstance2 = makeSafe({ owners: owners2 })
const safesList = List([safeInstance, safeInstance2])
const expectedResult = true
// when
const result = isUserAnOwnerOfAnySafe(safesList, userAddress)
// then
expect(result).toBe(expectedResult)
})
it('It should return false if given a list of safes, none of them has an owner equal to the userAccount', () => {
// given
const userAddress = 'address1'
const userAddress2 = 'address2'
const userAddress3 = 'address3'
const owners1 = List([makeOwner({ address: userAddress3 })])
const owners2 = List([makeOwner({ address: userAddress2 })])
const safeInstance = makeSafe({ owners: owners1 })
const safeInstance2 = makeSafe({ owners: owners2 })
const safesList = List([safeInstance, safeInstance2])
const expectedResult = false
// when
const result = isUserAnOwnerOfAnySafe(safesList, userAddress)
// then
expect(result).toBe(expectedResult)
})
})
describe('Utility function: isValidEnsName', () => {
it('If should return false if given no ens name', () => {
// given
const ensName = null
const expectedResult = false
// when
const result = isValidEnsName(ensName)
// then
expect(result).toBe(expectedResult)
})
it('It should return false for an ens without extension in format [value].[eth|test|xyz|luxe]', () => {
// given
const ensName = 'test'
const expectedResult = false
// when
const result = isValidEnsName(ensName)
// then
expect(result).toBe(expectedResult)
})
it('It should return false for an ens without the format [value].[eth|test|xyz|luxe]', () => {
// given
const ensName = 'test.et12312'
const expectedResult = false
// when
const result = isValidEnsName(ensName)
// then
expect(result).toBe(expectedResult)
})
it('It should return true for an ens in format [value].eth', () => {
// given
const ensName = 'test.eth'
const expectedResult = true
// when
const result = isValidEnsName(ensName)
// then
expect(result).toBe(expectedResult)
})
it('It should return true for ens in format [value].test', () => {
// given
const ensName = 'test.test'
const expectedResult = true
// when
const result = isValidEnsName(ensName)
// then
expect(result).toBe(expectedResult)
})
it('It should return true for an ens in the format [value].xyz', () => {
// given
const ensName = 'test.xyz'
const expectedResult = true
// when
const result = isValidEnsName(ensName)
// then
expect(result).toBe(expectedResult)
})
it('It should return true for an ens in format [value].luxe', () => {
// given
const ensName = 'test.luxe'
const expectedResult = true
// when
const result = isValidEnsName(ensName)
// then
expect(result).toBe(expectedResult)
})
})

View File

@ -4,25 +4,25 @@ import { getNetworkInfo } from 'src/config'
import { FIXED } from 'src/components/Table/sorting' import { FIXED } from 'src/components/Table/sorting'
import { formatAmountInUsFormat } from 'src/logic/tokens/utils/formatAmount' import { formatAmountInUsFormat } from 'src/logic/tokens/utils/formatAmount'
import { TableColumn } from 'src/components/Table/types.d' import { TableColumn } from 'src/components/Table/types.d'
import { AVAILABLE_CURRENCIES, BalanceCurrencyList } from 'src/logic/currencyValues/store/model/currencyValues' import { BalanceCurrencyList } from 'src/logic/currencyValues/store/model/currencyValues'
import { Token } from 'src/logic/tokens/store/model/token' import { Token } from 'src/logic/tokens/store/model/token'
export const BALANCE_TABLE_ASSET_ID = 'asset' export const BALANCE_TABLE_ASSET_ID = 'asset'
export const BALANCE_TABLE_BALANCE_ID = 'balance' export const BALANCE_TABLE_BALANCE_ID = 'balance'
export const BALANCE_TABLE_VALUE_ID = 'value' export const BALANCE_TABLE_VALUE_ID = 'value'
const { nativeCoin } = getNetworkInfo()
const getTokenPriceInCurrency = ( const getTokenPriceInCurrency = (
token: Token, token: Token,
currencySelected?: AVAILABLE_CURRENCIES, currencySelected?: string,
currencyValues?: BalanceCurrencyList, currencyValues?: BalanceCurrencyList,
currencyRate?: number, currencyRate?: number,
): string => { ): string => {
if (!currencySelected) { if (!currencySelected) {
return '' return ''
} }
const currencyValue = currencyValues?.find(({ tokenAddress }) => { const currencyValue = currencyValues?.find(({ tokenAddress }) => {
const { nativeCoin } = getNetworkInfo()
if (token.address === nativeCoin.address && !tokenAddress) { if (token.address === nativeCoin.address && !tokenAddress) {
return true return true
} }
@ -51,7 +51,7 @@ export interface BalanceData {
export const getBalanceData = ( export const getBalanceData = (
activeTokens: List<Token>, activeTokens: List<Token>,
currencySelected?: AVAILABLE_CURRENCIES, currencySelected?: string,
currencyValues?: BalanceCurrencyList, currencyValues?: BalanceCurrencyList,
currencyRate?: number, currencyRate?: number,
): List<BalanceData> => { ): List<BalanceData> => {

View File

@ -20,16 +20,20 @@ import { safeParamAddressFromStateSelector } from 'src/logic/safe/store/selector
import { DropdownListTheme } from 'src/theme/mui' import { DropdownListTheme } from 'src/theme/mui'
import { setImageToPlaceholder } from '../Balances/utils' import { setImageToPlaceholder } from '../Balances/utils'
import Img from 'src/components/layout/Img/index' import Img from 'src/components/layout/Img/index'
import etherIcon from 'src/assets/icons/icon_etherTokens.svg' import { getNetworkInfo } from 'src/config'
import { sameString } from 'src/utils/strings'
const { nativeCoin } = getNetworkInfo()
const CurrencyDropdown = (): React.ReactElement | null => { const CurrencyDropdown = (): React.ReactElement | null => {
const currenciesList = Object.values(AVAILABLE_CURRENCIES)
const safeAddress = useSelector(safeParamAddressFromStateSelector) as string const safeAddress = useSelector(safeParamAddressFromStateSelector) as string
const dispatch = useDispatch() const dispatch = useDispatch()
const [anchorEl, setAnchorEl] = useState(null) const [anchorEl, setAnchorEl] = useState(null)
const selectedCurrency = useSelector(currentCurrencySelector) const selectedCurrency = useSelector(currentCurrencySelector)
const [searchParams, setSearchParams] = useState('') const [searchParams, setSearchParams] = useState('')
const currenciesList = Object.values(AVAILABLE_CURRENCIES)
const tokenImage = nativeCoin.logoUri
const classes = useDropdownStyles() const classes = useDropdownStyles()
const currenciesListFiltered = currenciesList.filter((currency) => const currenciesListFiltered = currenciesList.filter((currency) =>
currency.toLowerCase().includes(searchParams.toLowerCase()), currency.toLowerCase().includes(searchParams.toLowerCase()),
@ -103,11 +107,11 @@ const CurrencyDropdown = (): React.ReactElement | null => {
value={currencyName} value={currencyName}
> >
<ListItemIcon className={classes.iconLeft}> <ListItemIcon className={classes.iconLeft}>
{currencyName === AVAILABLE_CURRENCIES.ETH ? ( {sameString(currencyName, nativeCoin.symbol) ? (
<Img <Img
alt="ether" alt={nativeCoin.symbol.toLocaleLowerCase()}
onError={setImageToPlaceholder} onError={setImageToPlaceholder}
src={etherIcon} src={tokenImage}
className={classNames(classes.etherFlag)} className={classNames(classes.etherFlag)}
/> />
) : ( ) : (

View File

@ -44,3 +44,17 @@ export const textShortener = ({ charsEnd = 10, charsStart = 10, ellipsis = '...'
* @returns {string} string without side whitespaces * @returns {string} string without side whitespaces
*/ */
export const trimSpaces = (value: string): string => (value === undefined ? '' : value.trim()) export const trimSpaces = (value: string): string => (value === undefined ? '' : value.trim())
/**
* Util to compare two strings, comparison is case insensitive
* @param str1
* @param str2
* @returns {boolean}
*/
export const sameString = (str1: string | undefined, str2: string | undefined): boolean => {
if (!str1 || !str2) {
return false
}
return str1.toLowerCase() === str2.toLowerCase()
}