@@ -2,99 +2,106 @@ interface Network {
22 name : string ;
33 symbol : string ;
44 decimals : number ;
5- explorer ?: string ; // Opcional para evitar erros
5+ explorer ?: string ;
66 rpcUrl ?: string ;
77 endpoint ?: string ;
88}
99
10- export const buildSubscanUrl = (
11- network : Network ,
12- type : 'block' | 'extrinsic' | 'account' | 'runtime' ,
10+ type UrlType = 'block' | 'extrinsic' | 'account' | 'runtime' ;
11+
12+
13+ const SUBSCAN_DOMAIN = 'subscan.io' ;
14+ const DEFAULT_NETWORK = 'polkadot' ;
15+ const DEFAULT_FALLBACK_URL = `https://${ DEFAULT_NETWORK } .${ SUBSCAN_DOMAIN } ` ;
16+
17+
18+ const URL_PATHS : Record < UrlType , { singular : string ; plural : string } > = {
19+ block : { singular : 'block' , plural : 'blocks' } ,
20+ extrinsic : { singular : 'extrinsic' , plural : 'extrinsics' } ,
21+ account : { singular : 'account' , plural : '' } ,
22+ runtime : { singular : '' , plural : '' }
23+ } as const ;
24+
25+
26+ const isValidExplorerUrl = ( explorerUrl ?: string ) : explorerUrl is string => {
27+ return Boolean (
28+ explorerUrl ?. trim ( ) &&
29+ explorerUrl !== 'undefined' &&
30+ explorerUrl !== 'null'
31+ ) ;
32+ } ;
33+
34+
35+ const normalizeNetworkName = ( name ?: string ) : string =>
36+ name ?. toLowerCase ( ) . replace ( / \s + / g, '-' ) || DEFAULT_NETWORK ;
37+
38+
39+ const extractNetworkFromUrl = ( url : string , fallbackName ?: string ) : string => {
40+ try {
41+ const { hostname } = new URL ( url ) ;
42+ return hostname . split ( '.' ) [ 0 ] || normalizeNetworkName ( fallbackName ) ;
43+ } catch {
44+ return normalizeNetworkName ( fallbackName ) ;
45+ }
46+ } ;
47+
48+
49+ const buildUrlPath = ( type : UrlType , identifier ?: string | number ) : string => {
50+ const { singular, plural } = URL_PATHS [ type ] ;
51+
52+ if ( ! identifier ) {
53+ return plural ? `/${ plural } ` : '' ;
54+ }
55+
56+ return singular ? `/${ singular } /${ identifier } ` : '' ;
57+ } ;
58+
59+
60+ const createFallbackUrl = (
61+ networkName : string ,
62+ type : UrlType ,
1363 identifier ?: string | number
1464) : string => {
15- // Verificação de segurança inicial
16- if ( ! network ) {
17- console . warn ( 'Network object is null or undefined' ) ;
18- return `https://polkadot.subscan.io/${ type } ${ identifier ? `/${ identifier } ` : '' } ` ;
19- }
65+ const baseUrl = `https://${ networkName } .${ SUBSCAN_DOMAIN } ` ;
66+ return `${ baseUrl } ${ buildUrlPath ( type , identifier ) } ` ;
67+ } ;
68+
2069
21- // Validação robusta do explorer URL
22- const explorerUrl = network . explorer ;
23-
24- // Verifica se o explorer URL é válido
25- if ( ! explorerUrl ||
26- typeof explorerUrl !== 'string' ||
27- explorerUrl . trim ( ) === '' ||
28- explorerUrl === 'undefined' ||
29- explorerUrl === 'null' ) {
30-
31- console . debug ( 'Using fallback explorer URL for network:' , network . name , 'explorer was:' , explorerUrl ) ;
32-
33- // Fallback usando o nome da rede
34- const networkName = network . name ?. toLowerCase ( ) ?. replace ( / \s + / g, '-' ) || 'polkadot' ;
35- const fallbackUrl = `https://${ networkName } .subscan.io` ;
36-
37- // Retorna URL baseado no tipo
38- switch ( type ) {
39- case 'block' :
40- return identifier ? `${ fallbackUrl } /block/${ identifier } ` : `${ fallbackUrl } /blocks` ;
41- case 'extrinsic' :
42- return identifier ? `${ fallbackUrl } /extrinsic/${ identifier } ` : `${ fallbackUrl } /extrinsics` ;
43- case 'account' :
44- return identifier ? `${ fallbackUrl } /account/${ identifier } ` : fallbackUrl ;
45- case 'runtime' :
46- return fallbackUrl ;
47- default :
48- return fallbackUrl ;
49- }
70+ const resolveBaseUrl = ( network : Network ) : string => {
71+ if ( ! isValidExplorerUrl ( network . explorer ) ) {
72+ console . debug ( 'Using fallback explorer URL for network:' , network . name , 'explorer was:' , network . explorer ) ;
73+ return `https://${ normalizeNetworkName ( network . name ) } .${ SUBSCAN_DOMAIN } ` ;
5074 }
5175
52- // Remove barra final do URL base
53- const baseUrl = explorerUrl . replace ( / \/ $ / , '' ) ;
76+ const baseUrl = network . explorer . replace ( / \/ $ / , '' ) ;
5477
55- // Verifica se é um URL válido do Subscan
56- if ( ! baseUrl . includes ( 'subscan.io' ) ) {
78+ if ( ! baseUrl . includes ( SUBSCAN_DOMAIN ) ) {
5779 console . debug ( 'Explorer URL is not a Subscan URL, creating fallback:' , baseUrl ) ;
58-
59- // Tenta extrair o nome da rede do URL ou usa o nome da rede
60- let networkName = 'polkadot' ;
61-
62- try {
63- const urlObj = new URL ( baseUrl ) ;
64- const subdomain = urlObj . hostname . split ( '.' ) [ 0 ] ;
65- networkName = subdomain || network . name ?. toLowerCase ( ) ?. replace ( / \s + / g, '-' ) || 'polkadot' ;
66- } catch {
67- networkName = network . name ?. toLowerCase ( ) ?. replace ( / \s + / g, '-' ) || 'polkadot' ;
68- }
69-
70- const fallbackUrl = `https://${ networkName } .subscan.io` ;
71-
72- // Retorna URL baseado no tipo
73- switch ( type ) {
74- case 'block' :
75- return identifier ? `${ fallbackUrl } /block/${ identifier } ` : `${ fallbackUrl } /blocks` ;
76- case 'extrinsic' :
77- return identifier ? `${ fallbackUrl } /extrinsic/${ identifier } ` : `${ fallbackUrl } /extrinsics` ;
78- case 'account' :
79- return identifier ? `${ fallbackUrl } /account/${ identifier } ` : fallbackUrl ;
80- case 'runtime' :
81- return fallbackUrl ;
82- default :
83- return fallbackUrl ;
84- }
80+ const networkName = extractNetworkFromUrl ( baseUrl , network . name ) ;
81+ return `https://${ networkName } .${ SUBSCAN_DOMAIN } ` ;
8582 }
8683
87- // URL válido do Subscan - constrói o URL final
88- switch ( type ) {
89- case 'block' :
90- return identifier ? `${ baseUrl } /block/${ identifier } ` : `${ baseUrl } /blocks` ;
91- case 'extrinsic' :
92- return identifier ? `${ baseUrl } /extrinsic/${ identifier } ` : `${ baseUrl } /extrinsics` ;
93- case 'account' :
94- return identifier ? `${ baseUrl } /account/${ identifier } ` : baseUrl ;
95- case 'runtime' :
96- return baseUrl ;
97- default :
98- return baseUrl ;
84+ return baseUrl ;
85+ } ;
86+
87+ /**
88+ * Builds Subscan URL for different resource types
89+ *
90+ * @param network - Network configuration object
91+ * @param type - Type of resource to link to
92+ * @param identifier - Optional identifier for the resource
93+ * @returns Complete Subscan URL
94+ */
95+ export const buildSubscanUrl = (
96+ network : Network | null | undefined ,
97+ type : UrlType ,
98+ identifier ?: string | number
99+ ) : string => {
100+ if ( ! network ) {
101+ console . warn ( 'Network object is null or undefined' ) ;
102+ return `${ DEFAULT_FALLBACK_URL } ${ buildUrlPath ( type , identifier ) } ` ;
99103 }
104+
105+ const baseUrl = resolveBaseUrl ( network ) ;
106+ return `${ baseUrl } ${ buildUrlPath ( type , identifier ) } ` ;
100107} ;
0 commit comments