forked from Uniswap/interface
-
Notifications
You must be signed in to change notification settings - Fork 1
/
hooks.ts
112 lines (98 loc) · 3.94 KB
/
hooks.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import { ChainTokenMap, tokensToChainTokenMap } from 'lib/hooks/useTokenList/utils'
import { useMemo } from 'react'
import { useAppSelector } from 'state/hooks'
import sortByListPriority from 'utils/listSort'
import BROKEN_LIST from '../../constants/tokenLists/broken.tokenlist.json'
import UNSUPPORTED_TOKEN_LIST from '../../constants/tokenLists/unsupported.tokenlist.json'
import { AppState } from '../index'
import { UNSUPPORTED_LIST_URLS } from './../../constants/lists'
export type TokenAddressMap = ChainTokenMap
type Mutable<T> = {
-readonly [P in keyof T]: Mutable<T[P]>
}
export function useAllLists(): AppState['lists']['byUrl'] {
return useAppSelector((state) => state.lists.byUrl)
}
/**
* Combine the tokens in map2 with the tokens on map1, where tokens on map1 take precedence
* @param map1 the base token map
* @param map2 the map of additioanl tokens to add to the base map
*/
export function combineMaps(map1: TokenAddressMap, map2: TokenAddressMap): TokenAddressMap {
const chainIds = Object.keys(
Object.keys(map1)
.concat(Object.keys(map2))
.reduce<{ [chainId: string]: true }>((memo, value) => {
memo[value] = true
return memo
}, {})
).map((id) => parseInt(id))
return chainIds.reduce<Mutable<TokenAddressMap>>((memo, chainId) => {
memo[chainId] = {
...map2[chainId],
// map1 takes precedence
...map1[chainId],
}
return memo
}, {}) as TokenAddressMap
}
// merge tokens contained within lists from urls
function useCombinedTokenMapFromUrls(urls: string[] | undefined): TokenAddressMap {
const lists = useAllLists()
return useMemo(() => {
if (!urls) return {}
return (
urls
.slice()
// sort by priority so top priority goes last
.sort(sortByListPriority)
.reduce((allTokens, currentUrl) => {
const current = lists[currentUrl]?.current
if (!current) return allTokens
try {
return combineMaps(allTokens, tokensToChainTokenMap(current))
} catch (error) {
console.error('Could not show token list due to error', error)
return allTokens
}
}, {})
)
}, [lists, urls])
}
// filter out unsupported lists
export function useActiveListUrls(): string[] | undefined {
const activeListUrls = useAppSelector((state) => state.lists.activeListUrls)
return useMemo(() => activeListUrls?.filter((url) => !UNSUPPORTED_LIST_URLS.includes(url)), [activeListUrls])
}
export function useInactiveListUrls(): string[] {
const lists = useAllLists()
const allActiveListUrls = useActiveListUrls()
return useMemo(
() => Object.keys(lists).filter((url) => !allActiveListUrls?.includes(url) && !UNSUPPORTED_LIST_URLS.includes(url)),
[lists, allActiveListUrls]
)
}
// get all the tokens from active lists, combine with local default tokens
export function useCombinedActiveList(): TokenAddressMap {
const activeListUrls = useActiveListUrls()
const activeTokens = useCombinedTokenMapFromUrls(activeListUrls)
return activeTokens
}
// list of tokens not supported on interface for various reasons, used to show warnings and prevent swaps and adds
export function useUnsupportedTokenList(): TokenAddressMap {
// get hard-coded broken tokens
const brokenListMap = useMemo(() => tokensToChainTokenMap(BROKEN_LIST), [])
// get hard-coded list of unsupported tokens
const localUnsupportedListMap = useMemo(() => tokensToChainTokenMap(UNSUPPORTED_TOKEN_LIST), [])
// get dynamic list of unsupported tokens
const loadedUnsupportedListMap = useCombinedTokenMapFromUrls(UNSUPPORTED_LIST_URLS)
// format into one token address map
return useMemo(
() => combineMaps(brokenListMap, combineMaps(localUnsupportedListMap, loadedUnsupportedListMap)),
[brokenListMap, localUnsupportedListMap, loadedUnsupportedListMap]
)
}
export function useIsListActive(url: string): boolean {
const activeListUrls = useActiveListUrls()
return Boolean(activeListUrls?.includes(url))
}