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

JWWEB-687 Add tests for merge assets function #1119

Open
wants to merge 5 commits into
base: feature/cicd-tests
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
11 changes: 11 additions & 0 deletions src/data/assets/getAssets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// @flow strict

export function getAssetsMainnet(): Promise<DigitalAsset[]> {
return import(/* webpackChunkName: "mainnet" */ '../../../assets/mainnet/assets.json')
.then(({ default: mainnet }) => mainnet)
}

export function getAssetsRopsten(): Promise<DigitalAsset[]> {
return import(/* webpackChunkName: "ropsten" */ '../../../assets/ropsten/assets.json')
.then(({ default: ropsten }) => ropsten)
}
17 changes: 3 additions & 14 deletions src/data/assets/index.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,8 @@
// @flow
// @flow strict

import ethereum from './ethereum'

function getAssetsMainnet(): Promise<DigitalAsset[]> {
return import(/* webpackChunkName: "mainnet" */ '../../../assets/mainnet/assets.json')
.then(({ default: mainnet }) => mainnet)
}

function getAssetsRopsten(): Promise<DigitalAsset[]> {
return import(/* webpackChunkName: "ropsten" */ '../../../assets/ropsten/assets.json')
.then(({ default: ropsten }) => ropsten)
}
export { default as ethereum } from './ethereum'

export {
ethereum,
getAssetsMainnet,
getAssetsRopsten,
}
} from './getAssets'
157 changes: 32 additions & 125 deletions src/store/sagas/digitalAssets/core.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
// @flow

import { mapKeys } from 'lodash-es'
// @flow strict

import { delay } from 'redux-saga'

Expand All @@ -13,136 +11,32 @@ import {
} from 'redux-saga/effects'

import {
ethereum,
getAssetsMainnet,
} from 'data/assets'
addETHAsset,
mergeDigitalAssets,
} from 'utils/digitalAssets'

import {
selectDigitalAsset,
selectDigitalAssetsItems,
} from 'store/selectors/digitalAssets'
import { getAddressChecksum } from 'utils/address'

import * as blocks from 'store/modules/blocks'
import * as ticker from 'store/modules/ticker'
import * as digitalAssets from 'store/modules/digitalAssets'

function mergeItems(
items: DigitalAssets,
assetsMainnet: DigitalAsset[],
): DigitalAssets {
// FIXME: use current network id instead
const defaultItems: DigitalAssets = assetsMainnet.reduce((
reduceResult: DigitalAssets,
item: DigitalAsset,
): DigitalAssets => {
const { address }: DigitalAssetBlockchainParams = item.blockchainParams

if (!address) {
return reduceResult
}

const addressWithChecksum: AssetAddress = getAddressChecksum(address)

reduceResult[addressWithChecksum] = {
...item,
isActive: false,
blockchainParams: {
...item.blockchainParams,
address: addressWithChecksum,
},
}

return reduceResult
}, {})

const itemsWithChecksum: DigitalAssets = mapKeys(
items,
(item, address) => getAddressChecksum(address),
)

const existingItems: DigitalAssets = Object.keys(itemsWithChecksum).reduce((
reduceResult: DigitalAssets,
addressWithChecksum: AssetAddress,
): DigitalAssets => {
const foundExistingItem: ?DigitalAsset = items[addressWithChecksum]
const foundDefaultItem: ?DigitalAsset = defaultItems[addressWithChecksum]

// Ignore nonexistent items
if (!foundExistingItem) {
return reduceResult
}

// Update from default item if it exists
if (foundDefaultItem) {
reduceResult[addressWithChecksum] = {
...foundExistingItem,
...foundDefaultItem,
isCustom: false,
isActive: !!foundExistingItem.isActive,
}

return reduceResult
}

// Remove (ignore) inactive items that are not in default list and not marked as custom
if (!foundExistingItem.isActive && !foundExistingItem.isCustom) {
return reduceResult
}

// Active items that are not in default list are converted to custom
reduceResult[addressWithChecksum] = {
...foundExistingItem,
isCustom: true,
}

return reduceResult
}, {})

return {
...defaultItems,
...existingItems,
}
}

function addETHAsset(
items: DigitalAssets,
assetsMainnet: DigitalAsset[],
): DigitalAssets {
const defaultETHAddress: AssetAddress = ethereum.blockchainParams.address

const foundETHAsset: ?DigitalAsset = assetsMainnet
.find((item: DigitalAsset) => (item.blockchainParams.type === 'ethereum'))

if (!foundETHAsset) {
return {
...items,
[defaultETHAddress]: ethereum,
}
}

const { blockchainParams }: DigitalAsset = foundETHAsset

return {
...items,
[defaultETHAddress]: {
...foundETHAsset,
blockchainParams: {
...blockchainParams,
address: defaultETHAddress,
},
isActive: true,
},
}
}

function* init(): Saga<void> {
const existingItems: ExtractReturn<typeof selectDigitalAssetsItems> =
const items: ExtractReturn<typeof selectDigitalAssetsItems> =
yield select(selectDigitalAssetsItems)

const assetsMainnet: DigitalAsset[] = yield call(getAssetsMainnet)
const mergedItems: DigitalAssets = mergeItems(existingItems, assetsMainnet)
const itemsWithETH: DigitalAssets = addETHAsset(mergedItems, assetsMainnet)
const mergedItems: DigitalAssets = yield call(
mergeDigitalAssets,
items,
)

const itemsWithETH: DigitalAssets = yield call(
addETHAsset,
mergedItems,
)

yield put(digitalAssets.setInitialItems(itemsWithETH))
}
Expand All @@ -158,8 +52,10 @@ function* deleteCustomAsset(
): Saga<void> {
const { assetAddress } = action.payload

const foundAsset: ExtractReturn<typeof selectDigitalAssetsItems> =
yield select(selectDigitalAsset, assetAddress)
const foundAsset: ExtractReturn<typeof selectDigitalAssetsItems> = yield select(
selectDigitalAsset,
assetAddress,
)

if (!(foundAsset && foundAsset.isCustom)) {
return
Expand All @@ -169,7 +65,18 @@ function* deleteCustomAsset(
}

export function* digitalAssetsRootSaga(): Saga<void> {
yield takeEvery(digitalAssets.INIT, init)
yield takeLatest(digitalAssets.SET_ASSET_IS_ACTIVE, setAssetIsActive)
yield takeEvery(digitalAssets.DELETE_CUSTOM_ASSET, deleteCustomAsset)
yield takeEvery(
digitalAssets.INIT,
init,
)

yield takeLatest(
digitalAssets.SET_ASSET_IS_ACTIVE,
setAssetIsActive,
)

yield takeEvery(
digitalAssets.DELETE_CUSTOM_ASSET,
deleteCustomAsset,
)
}
35 changes: 35 additions & 0 deletions src/utils/digitalAssets/addETHAsset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// @flow strict

import {
ethereum,
getAssetsMainnet,
} from 'data/assets'

export default async function addETHAsset(items: DigitalAssets): DigitalAssets {
const itemsMainnet: DigitalAsset[] = await getAssetsMainnet()
const defaultETHAddress: AssetAddress = ethereum.blockchainParams.address

const foundETHAsset: ?DigitalAsset = itemsMainnet
.find((item: DigitalAsset) => (item.blockchainParams.type === 'ethereum'))

if (!foundETHAsset) {
return {
...items,
[defaultETHAddress]: ethereum,
}
}

const { blockchainParams }: DigitalAsset = foundETHAsset

return {
...items,
[defaultETHAddress]: {
...foundETHAsset,
blockchainParams: {
...blockchainParams,
address: defaultETHAddress,
},
isActive: true,
},
}
}
3 changes: 3 additions & 0 deletions src/utils/digitalAssets/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import compareDigitalAssetsByBalance from './compareDigitalAssetsByBalance'
export { sortAssets } from './sortAssets'
export { getFiatBalance } from './getFiatBalance'

export { default as addETHAsset } from './addETHAsset'
export { default as mergeDigitalAssets } from './mergeDigitalAssets'

export {
checkETH,
checkJNT,
Expand Down
86 changes: 86 additions & 0 deletions src/utils/digitalAssets/mergeDigitalAssets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// @flow strict

import { getAssetsMainnet } from 'data/assets'
import { getAddressChecksum } from 'utils/address'

export default async function mergeDigitalAssets(items: DigitalAssets): DigitalAssets {
const itemsMainnet: DigitalAsset[] = await getAssetsMainnet()

// FIXME: use current network id instead
const defaultItems: DigitalAssets = itemsMainnet.reduce((
reduceResult: DigitalAssets,
item: DigitalAsset,
): DigitalAssets => {
const { address }: DigitalAssetBlockchainParams = item.blockchainParams

if (!address) {
return reduceResult
}

const addressWithChecksum: AssetAddress = getAddressChecksum(address)

reduceResult[addressWithChecksum] = {
...item,
isActive: false,
blockchainParams: {
...item.blockchainParams,
address: addressWithChecksum,
},
}

return reduceResult
}, {})

const itemsWithChecksum: DigitalAssets = Object.keys(items).reduce((
reduceResult: DigitalAssets,
address: AssetAddress,
): DigitalAssets => {
const addressWithChecksum: AssetAddress = getAddressChecksum(address)
reduceResult[addressWithChecksum] = items[address]

return reduceResult
}, {})

const existingItems: DigitalAssets = Object.keys(itemsWithChecksum).reduce((
reduceResult: DigitalAssets,
addressWithChecksum: AssetAddress,
): DigitalAssets => {
const foundDefaultItem: ?DigitalAsset = defaultItems[addressWithChecksum]
const foundExistingItem: ?DigitalAsset = itemsWithChecksum[addressWithChecksum]

// Ignore nonexistent items
if (!foundExistingItem) {
return reduceResult
}

// Update from default item if it exists
if (foundDefaultItem) {
reduceResult[addressWithChecksum] = {
...foundExistingItem,
...foundDefaultItem,
isCustom: false,
isActive: !!foundExistingItem.isActive,
}

return reduceResult
}

// Remove (ignore) inactive items that are not in default list and not marked as custom
if (!foundExistingItem.isActive && !foundExistingItem.isCustom) {
return reduceResult
}

// Active items that are not in default list are converted to custom
reduceResult[addressWithChecksum] = {
...foundExistingItem,
isCustom: true,
}

return reduceResult
}, {})

return {
...defaultItems,
...existingItems,
}
}
Loading