1
- import { Chain , config as configs } from '@streamr/config'
1
+ import { Chain , ChainKey , config as configs } from '@streamr/config'
2
2
import { produce } from 'immer'
3
3
import { useMemo } from 'react'
4
4
import { useSearchParams } from 'react-router-dom'
@@ -11,24 +11,64 @@ import {
11
11
} from '~/utils/chainConfigExtension'
12
12
import formatConfigUrl from './formatConfigUrl'
13
13
14
- function getPreferredChainName ( chainName : string ) {
15
- if ( / a m o y / i. test ( chainName ) ) {
16
- return 'amoy'
14
+ const lowerCasedChainKeyToChainKeyMap : Record < string , ChainKey | null | undefined > = { }
15
+
16
+ /**
17
+ * @param candidate Chain key or chain slug (from config extension) or chain number. Defaults
18
+ * to the default chain key (currently 'polygon').
19
+ */
20
+ export function getChainKey ( candidate : string | number ) : ChainKey {
21
+ const key = typeof candidate === 'number' ? candidate : candidate . toLowerCase ( )
22
+
23
+ if ( lowerCasedChainKeyToChainKeyMap [ key ] === null ) {
24
+ return defaultChainKey
17
25
}
18
26
19
- return chainName . toLowerCase ( )
20
- }
27
+ if ( lowerCasedChainKeyToChainKeyMap [ key ] ) {
28
+ return lowerCasedChainKeyToChainKeyMap [ key ]
29
+ }
30
+
31
+ for ( const chainKey in configs ) {
32
+ if ( ! isChainKey ( chainKey ) ) {
33
+ continue
34
+ }
35
+
36
+ if ( typeof key === 'number' ) {
37
+ if ( configs [ chainKey ] . id === key ) {
38
+ lowerCasedChainKeyToChainKeyMap [ key ] = chainKey
39
+
40
+ return chainKey
41
+ }
42
+
43
+ continue
44
+ }
45
+
46
+ if ( chainKey . toLowerCase ( ) === key ) {
47
+ lowerCasedChainKeyToChainKeyMap [ key ] = chainKey
48
+
49
+ return chainKey
50
+ }
51
+
52
+ const slug = parsedChainConfigExtension [ chainKey ] ?. slug ?. toLowerCase ( )
53
+
54
+ if ( key === slug ) {
55
+ lowerCasedChainKeyToChainKeyMap [ key ] = chainKey
56
+
57
+ return chainKey
58
+ }
59
+ }
21
60
22
- function getChainConfigWithFallback ( chainName : string ) : Chain {
23
- try {
24
- return getChainConfig ( chainName )
25
- } catch ( _ ) { }
61
+ console . warn (
62
+ `Could not find a proper chain key for "${ candidate } ". Using default key (${ defaultChainKey } ).` ,
63
+ )
64
+
65
+ lowerCasedChainKeyToChainKeyMap [ key ] = null
26
66
27
- return getChainConfig ( defaultChainKey )
67
+ return defaultChainKey
28
68
}
29
69
30
70
export function getCurrentChain ( ) {
31
- return getChainConfigWithFallback (
71
+ return getChainConfig (
32
72
new URLSearchParams ( window . location . search ) . get ( 'chain' ) || defaultChainKey ,
33
73
)
34
74
}
@@ -40,7 +80,7 @@ export function getCurrentChainId() {
40
80
export function useCurrentChain ( ) {
41
81
const chainName = useSearchParams ( ) [ 0 ] . get ( 'chain' ) || defaultChainKey
42
82
43
- return useMemo ( ( ) => getChainConfigWithFallback ( chainName ) , [ chainName ] )
83
+ return useMemo ( ( ) => getChainConfig ( chainName ) , [ chainName ] )
44
84
}
45
85
46
86
export function useCurrentChainId ( ) {
@@ -61,95 +101,75 @@ export function useCurrentChainFullName() {
61
101
interface ChainEntry {
62
102
config : Chain
63
103
configExtension : ChainConfigExtension
64
- chainKey : string
104
+ chainKey : ChainKey
65
105
}
66
106
67
- const chainEntriesByIdOrName : Partial < Record < string | number , ChainEntry | null > > = { }
68
-
69
- function getChainEntry ( chainIdOrName : string | number ) {
70
- const key =
71
- typeof chainIdOrName === 'string'
72
- ? getPreferredChainName ( chainIdOrName )
73
- : chainIdOrName
74
-
75
- let entry = chainEntriesByIdOrName [ key ]
76
-
77
- if ( typeof entry === 'undefined' ) {
78
- entry = ( ( ) => {
79
- const source = Object . entries < Chain > ( configs ) . find ( ( [ chainKey , config ] ) =>
80
- typeof chainIdOrName === 'string'
81
- ? getPreferredChainName ( chainIdOrName ) ===
82
- getPreferredChainName ( chainKey )
83
- : chainIdOrName === config . id ,
84
- )
85
-
86
- if ( ! source ) {
87
- return null
88
- }
89
-
90
- const [ rawChainKey , config ] = source
91
-
92
- const chainKey = getPreferredChainName ( rawChainKey )
107
+ const chainKeyToChainEntryMap : Partial < Record < ChainKey , ChainEntry | null > > = { }
93
108
94
- const configExtension =
95
- parsedChainConfigExtension [ chainKey ] || fallbackChainConfigExtension
109
+ function getChainEntry ( chainKey : ChainKey ) : ChainEntry {
110
+ if ( chainKeyToChainEntryMap [ chainKey ] ) {
111
+ return chainKeyToChainEntryMap [ chainKey ]
112
+ }
96
113
97
- const { dockerHost } = configExtension
114
+ const config : Chain = configs [ chainKey ]
98
115
99
- const sanitizedConfig = produce ( config , ( draft ) => {
100
- draft . name = ethereumNetworks [ config . id ] || config . name
116
+ const configExtension =
117
+ parsedChainConfigExtension [ chainKey ] || fallbackChainConfigExtension
101
118
102
- for ( const rpc of draft . rpcEndpoints ) {
103
- rpc . url = formatConfigUrl ( rpc . url , {
104
- dockerHost,
105
- } )
106
- }
119
+ const { dockerHost } = configExtension
107
120
108
- if ( draft . entryPoints ) {
109
- for ( const entrypoint of draft . entryPoints ) {
110
- entrypoint . websocket . host = formatConfigUrl (
111
- entrypoint . websocket . host ,
112
- {
113
- dockerHost,
114
- } ,
115
- )
116
- }
117
- }
121
+ const sanitizedConfig = produce ( config , ( draft ) => {
122
+ draft . name = ethereumNetworks [ config . id ] || config . name
118
123
119
- if ( draft . theGraphUrl ) {
120
- draft . theGraphUrl = formatConfigUrl ( draft . theGraphUrl , { dockerHost } )
121
- }
124
+ for ( const rpc of draft . rpcEndpoints ) {
125
+ rpc . url = formatConfigUrl ( rpc . url , {
126
+ dockerHost ,
122
127
} )
128
+ }
123
129
124
- return {
125
- chainKey,
126
- config : sanitizedConfig ,
127
- configExtension,
130
+ if ( draft . entryPoints ) {
131
+ for ( const entrypoint of draft . entryPoints ) {
132
+ entrypoint . websocket . host = formatConfigUrl ( entrypoint . websocket . host , {
133
+ dockerHost,
134
+ } )
128
135
}
129
- } ) ( )
136
+ }
130
137
131
- chainEntriesByIdOrName [ key ] = entry
132
- }
138
+ if ( draft . theGraphUrl ) {
139
+ draft . theGraphUrl = formatConfigUrl ( draft . theGraphUrl , { dockerHost } )
140
+ }
141
+ } )
133
142
134
- if ( ! entry ) {
135
- throw new Error (
136
- `Could not find config for "${ chainIdOrName } " (${
137
- typeof chainIdOrName === 'string' ? 'chain name' : 'chain id'
138
- } )`,
139
- )
143
+ const entry : ChainEntry = {
144
+ chainKey,
145
+ config : sanitizedConfig ,
146
+ configExtension,
140
147
}
141
148
149
+ chainKeyToChainEntryMap [ chainKey ] = entry
150
+
142
151
return entry
143
152
}
144
153
145
154
export function getChainConfig ( chainIdOrChainKey : string | number ) : Chain {
146
- return getChainEntry ( chainIdOrChainKey ) . config
155
+ return getChainEntry ( getChainKey ( chainIdOrChainKey ) ) . config
156
+ }
157
+
158
+ export function getChainConfigExtension ( chainId : number ) : ChainConfigExtension {
159
+ return getChainEntry ( getChainKey ( chainId ) ) . configExtension
147
160
}
148
161
149
- export function getChainKey ( chainId : number ) {
150
- return getChainEntry ( chainId ) . chainKey
162
+ export function getChainSlug ( chainIdOrChainKey : ChainKey | number ) : string {
163
+ const chainEntry = getChainEntry ( getChainKey ( chainIdOrChainKey ) )
164
+
165
+ return chainEntry . configExtension . slug || chainEntry . chainKey
151
166
}
152
167
153
- export function getChainConfigExtension ( chainId : number ) {
154
- return getChainEntry ( chainId ) . configExtension
168
+ /**
169
+ * Checks if a given string is a `ChainKey`.
170
+ * @param candidate Any string.
171
+ * @returns `true` if the given string is config's own key.
172
+ */
173
+ function isChainKey ( candidate : string ) : candidate is ChainKey {
174
+ return Object . prototype . hasOwnProperty . call ( configs , candidate )
155
175
}
0 commit comments