Skip to content

Commit efce7de

Browse files
fix: throw when getExplorerLink has no block explorer URL available
1 parent 2dd84b7 commit efce7de

2 files changed

Lines changed: 60 additions & 6 deletions

File tree

src/utils/getExplorerLink.test.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import type { Chain } from 'viem'
2+
import { describe, expect, it } from 'vitest'
3+
import { getExplorerLink } from './getExplorerLink'
4+
5+
const chain: Chain = {
6+
id: 1,
7+
name: 'Mock Chain',
8+
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
9+
rpcUrls: { default: { http: ['https://mock.rpc.url'] } },
10+
blockExplorers: {
11+
default: { name: 'MockExplorer', url: 'https://mock.explorer.url' },
12+
},
13+
} as Chain
14+
15+
const address = '0x71C7656EC7ab88b098defB751B7401B5f6d8976F' as const
16+
const txHash = '0xd85ef8c70dc31a4f8d5bf0331e1eac886935905f15d32e71b348df745cd38e19' as const
17+
18+
describe('getExplorerLink', () => {
19+
it('returns address URL using chain block explorer', () => {
20+
expect(getExplorerLink({ chain, hashOrAddress: address })).toBe(
21+
`https://mock.explorer.url/address/${address}`,
22+
)
23+
})
24+
25+
it('returns tx URL using chain block explorer for a hash', () => {
26+
expect(getExplorerLink({ chain, hashOrAddress: txHash })).toBe(
27+
`https://mock.explorer.url/tx/${txHash}`,
28+
)
29+
})
30+
31+
it('uses custom explorerUrl when provided', () => {
32+
const explorerUrl = 'https://custom.explorer.io'
33+
expect(getExplorerLink({ chain, hashOrAddress: address, explorerUrl })).toBe(
34+
`${explorerUrl}/address/${address}`,
35+
)
36+
})
37+
38+
it('throws when chain has no block explorer and no explorerUrl is provided', () => {
39+
const chainWithoutExplorer: Chain = { ...chain, blockExplorers: undefined }
40+
expect(() => getExplorerLink({ chain: chainWithoutExplorer, hashOrAddress: address })).toThrow(
41+
'No block explorer URL available for this chain',
42+
)
43+
})
44+
45+
it('throws for an invalid hash or address', () => {
46+
expect(() =>
47+
// biome-ignore lint/suspicious/noExplicitAny: intentionally testing invalid input
48+
getExplorerLink({ chain, hashOrAddress: 'not-valid' as any }),
49+
).toThrow('Invalid hash or address')
50+
})
51+
})

src/utils/getExplorerLink.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export type GetExplorerUrlParams = {
1919
* @param {string} [params.explorerUrl] - Optional custom explorer URL to override the chain's default explorer
2020
*
2121
* @throws {Error} Throws an error if the provided hash or address is invalid
22+
* @throws {Error} Throws an error if no explorer URL is available (neither `explorerUrl` nor `chain.blockExplorers`)
2223
*
2324
* @returns {string} The complete explorer URL for the given hash or address
2425
*
@@ -43,15 +44,17 @@ export type GetExplorerUrlParams = {
4344
* ```
4445
*/
4546
export const getExplorerLink = ({ chain, explorerUrl, hashOrAddress }: GetExplorerUrlParams) => {
47+
const baseUrl = explorerUrl ?? chain.blockExplorers?.default.url
48+
49+
if (!baseUrl) {
50+
throw new Error('No block explorer URL available for this chain')
51+
}
52+
4653
if (isAddress(hashOrAddress)) {
47-
return explorerUrl
48-
? `${explorerUrl}/address/${hashOrAddress}`
49-
: `${chain.blockExplorers?.default.url}/address/${hashOrAddress}`
54+
return `${baseUrl}/address/${hashOrAddress}`
5055
}
5156
if (isHash(hashOrAddress)) {
52-
return explorerUrl
53-
? `${explorerUrl}/tx/${hashOrAddress}`
54-
: `${chain.blockExplorers?.default.url}/tx/${hashOrAddress}`
57+
return `${baseUrl}/tx/${hashOrAddress}`
5558
}
5659

5760
throw new Error('Invalid hash or address')

0 commit comments

Comments
 (0)