Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
frontend
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
frontend
Commits
0d75bac8
Commit
0d75bac8
authored
May 09, 2023
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
network explorers popover
parent
e0d2882e
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
86 additions
and
29 deletions
+86
-29
.env.goerli
configs/envs/.env.goerli
+1
-1
networks.ts
types/networks.ts
+1
-0
Token.tsx
ui/pages/Token.tsx
+3
-2
Transaction.tsx
ui/pages/Transaction.tsx
+2
-20
NetworkExplorers.tsx
ui/shared/NetworkExplorers.tsx
+68
-0
TokenVerifiedInfo.tsx
ui/token/TokenVerifiedInfo.tsx
+11
-6
No files found.
configs/envs/.env.goerli
View file @
0d75bac8
# ui config
NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/eth-goerli.json
NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'
Anyblock','baseUrl':'https://explorer.anyblock.tools','paths':{'tx':'/ethereum/ethereum/goerli/transaction','address':'/ethereum/ethereum/goerli/address'}},{'title':'Etherscan','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address
'}}]
NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'
Bitquery','baseUrl':'https://explorer.bitquery.io/','paths':{'tx':'/goerli/tx','address':'/goerli/address','token':'/goerli/token'}},{'title':'Etherscan','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token
'}}]
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d
# network config
...
...
types/networks.ts
View file @
0d75bac8
...
...
@@ -15,6 +15,7 @@ export interface NetworkExplorer {
paths
:
{
tx
?:
string
;
address
?:
string
;
token
?:
string
;
};
}
...
...
ui/pages/Token.tsx
View file @
0d75bac8
...
...
@@ -14,6 +14,7 @@ import { useAppContext } from 'lib/appContext';
import
useContractTabs
from
'
lib/hooks/useContractTabs
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
useQueryWithPages
from
'
lib/hooks/useQueryWithPages
'
;
import
getQueryParamString
from
'
lib/router/getQueryParamString
'
;
import
useSocketChannel
from
'
lib/socket/useSocketChannel
'
;
import
useSocketMessage
from
'
lib/socket/useSocketMessage
'
;
import
trimTokenSymbol
from
'
lib/token/trimTokenSymbol
'
;
...
...
@@ -45,7 +46,7 @@ const TokenPageContent = () => {
const
scrollRef
=
React
.
useRef
<
HTMLDivElement
>
(
null
);
const
hashString
=
router
.
query
.
hash
?.
toString
(
);
const
hashString
=
getQueryParamString
(
router
.
query
.
hash
);
const
queryClient
=
useQueryClient
();
...
...
@@ -252,7 +253,7 @@ const TokenPageContent = () => {
</>
) }
<TokenContractInfo tokenQuery={ tokenQuery }/>
<TokenVerifiedInfo verifiedInfoQuery={ verifiedInfoQuery } isVerifiedInfoEnabled={ isVerifiedInfoEnabled }/>
<TokenVerifiedInfo
hash={ hashString }
verifiedInfoQuery={ verifiedInfoQuery } isVerifiedInfoEnabled={ isVerifiedInfoEnabled }/>
<TokenDetails tokenQuery={ tokenQuery }/>
{ /* should stay before tabs to scroll up with pagination */ }
<Box ref={ scrollRef }></Box>
...
...
ui/pages/Transaction.tsx
View file @
0d75bac8
...
...
@@ -6,10 +6,9 @@ import type { RoutedTab } from 'ui/shared/RoutedTabs/types';
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
useAppContext
}
from
'
lib/appContext
'
;
import
networkExplorers
from
'
lib/networks/networkExplorers
'
;
import
getQueryParamString
from
'
lib/router/getQueryParamString
'
;
import
TextAd
from
'
ui/shared/ad/TextAd
'
;
import
LinkExternal
from
'
ui/shared/LinkExternal
'
;
import
NetworkExplorers
from
'
ui/shared/NetworkExplorers
'
;
import
Page
from
'
ui/shared/Page/Page
'
;
import
PageTitle
from
'
ui/shared/Page/PageTitle
'
;
import
RoutedTabs
from
'
ui/shared/RoutedTabs/RoutedTabs
'
;
...
...
@@ -40,27 +39,10 @@ const TransactionPageContent = () => {
queryOptions
:
{
enabled
:
Boolean
(
hash
)
},
});
const
explorersLinks
=
networkExplorers
.
filter
((
explorer
)
=>
explorer
.
paths
.
tx
)
.
map
((
explorer
)
=>
{
const
url
=
new
URL
(
explorer
.
paths
.
tx
+
'
/
'
+
hash
,
explorer
.
baseUrl
);
return
<
LinkExternal
key=
{
explorer
.
baseUrl
}
href=
{
url
.
toString
()
}
>
Open in
{
explorer
.
title
}
</
LinkExternal
>;
});
const
additionals
=
(
<
Flex
justifyContent=
"space-between"
alignItems=
"center"
flexGrow=
{
1
}
flexWrap=
"wrap"
>
{
data
?.
tx_tag
&&
<
Tag
my=
{
2
}
>
{
data
.
tx_tag
}
</
Tag
>
}
{
explorersLinks
.
length
>
0
&&
(
<
Flex
alignItems=
"center"
flexWrap=
"wrap"
columnGap=
{
6
}
rowGap=
{
3
}
ml=
{
{
base
:
'
initial
'
,
lg
:
'
auto
'
}
}
>
{
explorersLinks
}
</
Flex
>
)
}
<
NetworkExplorers
type=
"tx"
pathParam=
{
hash
}
ml=
{
{
base
:
'
initial
'
,
lg
:
'
auto
'
}
}
/>
</
Flex
>
);
...
...
ui/shared/NetworkExplorers.tsx
0 → 100644
View file @
0d75bac8
import
{
Flex
,
Button
,
Icon
,
chakra
,
Popover
,
PopoverTrigger
,
PopoverBody
,
PopoverContent
,
useDisclosure
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
NetworkExplorer
as
TNetworkExplorer
}
from
'
types/networks
'
;
import
arrowIcon
from
'
icons/arrows/east-mini.svg
'
;
import
searchIcon
from
'
icons/search.svg
'
;
import
networkExplorers
from
'
lib/networks/networkExplorers
'
;
import
LinkExternal
from
'
ui/shared/LinkExternal
'
;
interface
Props
{
className
?:
string
;
type
:
keyof
TNetworkExplorer
[
'
paths
'
];
pathParam
:
string
;
}
const
NetworkExplorers
=
({
className
,
type
,
pathParam
}:
Props
)
=>
{
const
{
isOpen
,
onToggle
,
onClose
}
=
useDisclosure
();
const
explorersLinks
=
networkExplorers
.
filter
((
explorer
)
=>
explorer
.
paths
[
type
])
.
map
((
explorer
)
=>
{
const
url
=
new
URL
(
explorer
.
paths
[
type
]
+
'
/
'
+
pathParam
,
explorer
.
baseUrl
);
return
<
LinkExternal
key=
{
explorer
.
baseUrl
}
href=
{
url
.
toString
()
}
>
{
explorer
.
title
}
</
LinkExternal
>;
});
if
(
explorersLinks
.
length
===
0
)
{
return
null
;
}
return
(
<
Popover
isOpen=
{
isOpen
}
onClose=
{
onClose
}
placement=
"bottom-start"
isLazy
>
<
PopoverTrigger
>
<
Button
className=
{
className
}
size=
"sm"
variant=
"outline"
colorScheme=
"gray"
onClick=
{
onToggle
}
aria
-
label=
"Verify in other explorers"
fontWeight=
{
500
}
px=
{
2
}
h=
"30px"
>
<
Icon
as=
{
searchIcon
}
boxSize=
{
4
}
mr=
{
1
}
/>
<
span
>
Explorers
</
span
>
<
Icon
as=
{
arrowIcon
}
transform=
{
isOpen
?
'
rotate(90deg)
'
:
'
rotate(-90deg)
'
}
transitionDuration=
"faster"
boxSize=
{
5
}
ml=
{
1
}
/>
</
Button
>
</
PopoverTrigger
>
<
PopoverContent
w=
"240px"
>
<
PopoverBody
>
<
chakra
.
span
color=
"text_secondary"
fontSize=
"xs"
>
Verify with other explorers
</
chakra
.
span
>
<
Flex
alignItems=
"center"
flexWrap=
"wrap"
columnGap=
{
6
}
rowGap=
{
3
}
mt=
{
3
}
>
{
explorersLinks
}
</
Flex
>
</
PopoverBody
>
</
PopoverContent
>
</
Popover
>
);
};
export
default
React
.
memo
(
chakra
(
NetworkExplorers
));
ui/token/TokenVerifiedInfo.tsx
View file @
0d75bac8
import
{
Flex
,
Skeleton
}
from
'
@chakra-ui/react
'
;
import
{
Flex
,
Skeleton
,
useColorModeValue
}
from
'
@chakra-ui/react
'
;
import
type
{
UseQueryResult
}
from
'
@tanstack/react-query
'
;
import
React
from
'
react
'
;
import
type
{
TokenVerifiedInfo
as
TTokenVerifiedInfo
}
from
'
types/api/token
'
;
import
LinkExternal
from
'
ui/shared/LinkExternal
'
;
import
NetworkExplorers
from
'
ui/shared/NetworkExplorers
'
;
interface
Props
{
verifiedInfoQuery
:
UseQueryResult
<
TTokenVerifiedInfo
>
;
isVerifiedInfoEnabled
:
boolean
;
hash
:
string
;
}
const
TokenVerifiedInfo
=
({
verifiedInfoQuery
,
isVerifiedInfoEnabled
}:
Props
)
=>
{
const
TokenVerifiedInfo
=
({
verifiedInfoQuery
,
isVerifiedInfoEnabled
,
hash
}:
Props
)
=>
{
const
{
data
,
isLoading
,
isError
}
=
verifiedInfoQuery
;
const
websiteLinkBg
=
useColorModeValue
(
'
gray.100
'
,
'
gray.700
'
);
const
content
=
(()
=>
{
const
explorers
=
<
NetworkExplorers
type=
"token"
pathParam=
{
hash
}
/>;
if
(
!
isVerifiedInfoEnabled
)
{
return
<
span
>
explorers
</
span
>
;
return
explorers
;
}
if
(
isLoading
)
{
...
...
@@ -38,7 +43,7 @@ const TokenVerifiedInfo = ({ verifiedInfoQuery, isVerifiedInfoEnabled }: Props)
try
{
const
url
=
new
URL
(
data
.
projectWebsite
);
return
(
<
LinkExternal
href=
{
data
.
projectWebsite
}
px=
"10px"
py=
"5px"
bgColor=
"gray.100"
borderRadius=
"base"
>
{
url
.
host
}
</
LinkExternal
>
<
LinkExternal
href=
{
data
.
projectWebsite
}
px=
"10px"
py=
"5px"
bgColor=
{
websiteLinkBg
}
borderRadius=
"base"
>
{
url
.
host
}
</
LinkExternal
>
);
}
catch
(
error
)
{
return
null
;
...
...
@@ -49,12 +54,12 @@ const TokenVerifiedInfo = ({ verifiedInfoQuery, isVerifiedInfoEnabled }: Props)
<>
{
websiteLink
}
<
Skeleton
w=
"130px"
h=
"30px"
borderRadius=
"base"
/>
<
Skeleton
w=
"120px"
h=
"30px"
borderRadius=
"base"
/>
{
explorers
}
</>
);
})();
return
<
Flex
columnGap=
{
3
}
mt=
{
5
}
>
{
content
}
</
Flex
>;
return
<
Flex
columnGap=
{
3
}
rowGap=
{
3
}
mt=
{
5
}
flexWrap=
"wrap"
_empty=
{
{
display
:
'
none
'
}
}
>
{
content
}
</
Flex
>;
};
export
default
React
.
memo
(
TokenVerifiedInfo
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment