1- import { Chain , config as configs } from '@streamr/config'
1+ import { Chain , ChainKey , config as configs } from '@streamr/config'
22import { produce } from 'immer'
33import { useMemo } from 'react'
44import { useSearchParams } from 'react-router-dom'
@@ -11,24 +11,64 @@ import {
1111} from '~/utils/chainConfigExtension'
1212import formatConfigUrl from './formatConfigUrl'
1313
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
1725 }
1826
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+ }
2160
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
2666
27- return getChainConfig ( defaultChainKey )
67+ return defaultChainKey
2868}
2969
3070export function getCurrentChain ( ) {
31- return getChainConfigWithFallback (
71+ return getChainConfig (
3272 new URLSearchParams ( window . location . search ) . get ( 'chain' ) || defaultChainKey ,
3373 )
3474}
@@ -40,7 +80,7 @@ export function getCurrentChainId() {
4080export function useCurrentChain ( ) {
4181 const chainName = useSearchParams ( ) [ 0 ] . get ( 'chain' ) || defaultChainKey
4282
43- return useMemo ( ( ) => getChainConfigWithFallback ( chainName ) , [ chainName ] )
83+ return useMemo ( ( ) => getChainConfig ( chainName ) , [ chainName ] )
4484}
4585
4686export function useCurrentChainId ( ) {
@@ -61,95 +101,75 @@ export function useCurrentChainFullName() {
61101interface ChainEntry {
62102 config : Chain
63103 configExtension : ChainConfigExtension
64- chainKey : string
104+ chainKey : ChainKey
65105}
66106
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 > > = { }
93108
94- const configExtension =
95- parsedChainConfigExtension [ chainKey ] || fallbackChainConfigExtension
109+ function getChainEntry ( chainKey : ChainKey ) : ChainEntry {
110+ if ( chainKeyToChainEntryMap [ chainKey ] ) {
111+ return chainKeyToChainEntryMap [ chainKey ]
112+ }
96113
97- const { dockerHost } = configExtension
114+ const config : Chain = configs [ chainKey ]
98115
99- const sanitizedConfig = produce ( config , ( draft ) => {
100- draft . name = ethereumNetworks [ config . id ] || config . name
116+ const configExtension =
117+ parsedChainConfigExtension [ chainKey ] || fallbackChainConfigExtension
101118
102- for ( const rpc of draft . rpcEndpoints ) {
103- rpc . url = formatConfigUrl ( rpc . url , {
104- dockerHost,
105- } )
106- }
119+ const { dockerHost } = configExtension
107120
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
118123
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 ,
122127 } )
128+ }
123129
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+ } )
128135 }
129- } ) ( )
136+ }
130137
131- chainEntriesByIdOrName [ key ] = entry
132- }
138+ if ( draft . theGraphUrl ) {
139+ draft . theGraphUrl = formatConfigUrl ( draft . theGraphUrl , { dockerHost } )
140+ }
141+ } )
133142
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,
140147 }
141148
149+ chainKeyToChainEntryMap [ chainKey ] = entry
150+
142151 return entry
143152}
144153
145154export 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
147160}
148161
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
151166}
152167
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 )
155175}
0 commit comments