1
- import { useState , useEffect } from ' react'
1
+ import { useState , useEffect } from " react" ;
2
2
import {
3
3
Table ,
4
4
TableHead ,
@@ -8,46 +8,56 @@ import {
8
8
TextField ,
9
9
Select ,
10
10
MenuItem ,
11
- Box
12
- } from '@mui/material'
13
- import { HermesClient } from '@pythnetwork/hermes-client'
11
+ Box ,
12
+ Snackbar ,
13
+ } from "@mui/material" ;
14
+ import { HermesClient } from "@pythnetwork/hermes-client" ;
15
+ import copy from "copy-to-clipboard" ;
14
16
15
17
interface PriceFeed {
16
- id : string
17
- name : string
18
- assetType : string
18
+ id : string ;
19
+ name : string ;
20
+ assetType : string ;
19
21
}
20
22
21
23
export function PriceFeedTable ( ) {
22
- const [ priceFeeds , setPriceFeeds ] = useState < PriceFeed [ ] > ( [ ] )
23
- const [ searchTerm , setSearchTerm ] = useState ( "" )
24
- const [ selectedAssetType , setSelectedAssetType ] = useState ( "All" )
24
+ const [ priceFeeds , setPriceFeeds ] = useState < PriceFeed [ ] > ( [ ] ) ;
25
+ const [ searchTerm , setSearchTerm ] = useState ( "" ) ;
26
+ const [ selectedAssetType , setSelectedAssetType ] = useState ( "All" ) ;
27
+ const [ openSnackbar , setOpenSnackbar ] = useState ( false ) ;
25
28
26
29
useEffect ( ( ) => {
27
30
const fetchPriceFeeds = async ( ) => {
28
- const hermesClient = new HermesClient ( "https://hermes.pyth.network" )
29
- const feeds = await hermesClient . getPriceFeeds ( )
30
- const transformedFeeds = feeds . map ( feed => ( {
31
+ const hermesClient = new HermesClient ( "https://hermes.pyth.network" ) ;
32
+ const feeds = await hermesClient . getPriceFeeds ( ) ;
33
+ const transformedFeeds = feeds . map ( ( feed ) => ( {
31
34
id : feed . id ,
32
- name : feed . attributes . display_symbol || '' ,
33
- assetType : feed . attributes . asset_type || ''
34
- } ) )
35
- setPriceFeeds ( transformedFeeds )
36
- }
37
-
38
- fetchPriceFeeds ( )
39
- } , [ ] )
35
+ name : feed . attributes . display_symbol || "" ,
36
+ assetType : feed . attributes . asset_type || "" ,
37
+ } ) ) ;
38
+ setPriceFeeds ( transformedFeeds ) ;
39
+ } ;
40
40
41
- const filteredData = priceFeeds . filter ( feed => {
42
- const matchesSearch = feed . id . toLowerCase ( ) . includes ( searchTerm . toLowerCase ( ) ) ||
43
- feed . name . toLowerCase ( ) . includes ( searchTerm . toLowerCase ( ) )
44
- const matchesAssetType = selectedAssetType === "All" || feed . assetType === selectedAssetType
45
- return matchesSearch && matchesAssetType
46
- } )
41
+ fetchPriceFeeds ( ) ;
42
+ } , [ ] ) ;
43
+
44
+ const filteredData = priceFeeds . filter ( ( feed ) => {
45
+ const matchesSearch =
46
+ feed . id . toLowerCase ( ) . includes ( searchTerm . toLowerCase ( ) ) ||
47
+ feed . name . toLowerCase ( ) . includes ( searchTerm . toLowerCase ( ) ) ;
48
+ const matchesAssetType =
49
+ selectedAssetType === "All" || feed . assetType === selectedAssetType ;
50
+ return matchesSearch && matchesAssetType ;
51
+ } ) ;
52
+
53
+ const handleCopy = ( id : string ) => {
54
+ copy ( id ) ;
55
+ setOpenSnackbar ( true ) ;
56
+ } ;
47
57
48
58
return (
49
59
< Box >
50
- < Box sx = { { mb : 3 , display : ' flex' , gap : 2 } } >
60
+ < Box sx = { { mb : 3 , display : " flex" , gap : 2 } } >
51
61
< TextField
52
62
label = "Search price feeds"
53
63
variant = "outlined"
@@ -63,11 +73,13 @@ export function PriceFeedTable() {
63
73
sx = { { width : 200 } }
64
74
>
65
75
< MenuItem value = "All" > All Asset Types</ MenuItem >
66
- { Array . from ( new Set ( priceFeeds . map ( feed => feed . assetType ) ) ) . map ( type => (
67
- < MenuItem key = { type } value = { type } >
68
- { type || 'Uncategorized' }
69
- </ MenuItem >
70
- ) ) }
76
+ { Array . from ( new Set ( priceFeeds . map ( ( feed ) => feed . assetType ) ) ) . map (
77
+ ( type ) => (
78
+ < MenuItem key = { type } value = { type } >
79
+ { type || "Uncategorized" }
80
+ </ MenuItem >
81
+ )
82
+ ) }
71
83
</ Select >
72
84
</ Box >
73
85
@@ -84,11 +96,28 @@ export function PriceFeedTable() {
84
96
< TableRow key = { feed . id } >
85
97
< TableCell > { feed . name } </ TableCell >
86
98
< TableCell > { feed . assetType } </ TableCell >
87
- < TableCell > { feed . id } </ TableCell >
99
+ < TableCell
100
+ onClick = { ( ) => handleCopy ( feed . id ) }
101
+ sx = { {
102
+ cursor : "pointer" ,
103
+ "&:hover" : {
104
+ backgroundColor : "#BB86FC" ,
105
+ } ,
106
+ } }
107
+ >
108
+ { feed . id }
109
+ </ TableCell >
88
110
</ TableRow >
89
111
) ) }
90
112
</ TableBody >
91
113
</ Table >
114
+
115
+ < Snackbar
116
+ open = { openSnackbar }
117
+ autoHideDuration = { 2000 }
118
+ onClose = { ( ) => setOpenSnackbar ( false ) }
119
+ message = "Feed ID copied to clipboard"
120
+ />
92
121
</ Box >
93
- )
94
- }
122
+ ) ;
123
+ }
0 commit comments