@@ -2,17 +2,54 @@ import { useState } from "react";
2
2
import CopyIcon from "./icons/CopyIcon" ;
3
3
import { mapValues } from "../utils/ObjectHelpers" ;
4
4
5
+ interface UpdateParameters {
6
+ heartbeatLength : number ;
7
+ heartbeatUnit : "second" | "minute" | "hour" ;
8
+ priceDeviation : number ;
9
+ }
10
+
5
11
interface SponsoredFeed {
6
12
name : string ;
7
13
priceFeedId : string ;
8
- updateParameters : string ;
14
+ updateParameters : UpdateParameters ;
9
15
}
10
16
11
17
interface SponsoredFeedsTableProps {
12
18
feeds : SponsoredFeed [ ] ;
13
19
networkName : string ;
14
20
}
15
21
22
+ /**
23
+ * Helper functions
24
+ */
25
+
26
+ // Format update parameters as a string for grouping
27
+ const formatUpdateParams = ( params : UpdateParameters ) : string => {
28
+ return `${ params . heartbeatLength } ${ params . heartbeatUnit } heartbeat / ${ params . priceDeviation } % price deviation` ;
29
+ } ;
30
+
31
+ // Render update parameters with proper styling
32
+ const renderUpdateParams = ( params : UpdateParameters , isDefault : boolean ) => (
33
+ < div className = "flex items-start gap-1.5" >
34
+ < div
35
+ className = { `w-1.5 h-1.5 rounded-full mt-1 flex-shrink-0 ${
36
+ isDefault ? "bg-green-500" : "bg-orange-500"
37
+ } `}
38
+ > </ div >
39
+ < span
40
+ className = { `text-xs leading-relaxed font-medium ${
41
+ isDefault
42
+ ? "text-gray-700 dark:text-gray-300"
43
+ : "text-orange-600 dark:text-orange-400"
44
+ } `}
45
+ >
46
+ < strong > { params . heartbeatLength } </ strong > { params . heartbeatUnit } heartbeat
47
+ < br />
48
+ < strong > { params . priceDeviation } %</ strong > price deviation
49
+ </ span >
50
+ </ div >
51
+ ) ;
52
+
16
53
export const SponsoredFeedsTable = ( {
17
54
feeds,
18
55
networkName,
@@ -28,16 +65,14 @@ export const SponsoredFeedsTable = ({
28
65
29
66
// Calculate parameter statistics
30
67
const paramCounts = mapValues (
31
- Object . groupBy ( feeds , ( feed ) => feed . updateParameters ) ,
68
+ Object . groupBy ( feeds , ( feed ) => formatUpdateParams ( feed . updateParameters ) ) ,
32
69
( feeds : SponsoredFeed [ ] ) => feeds . length
33
70
) ;
34
71
35
72
const defaultParams = Object . entries ( paramCounts ) . sort (
36
73
( [ , a ] , [ , b ] ) => b - a
37
74
) [ 0 ] [ 0 ] ;
38
75
39
- // CSS max-h-96 will handle scrolling automatically
40
-
41
76
return (
42
77
< div className = "my-6" >
43
78
< p className = "mb-3" >
@@ -52,11 +87,7 @@ export const SponsoredFeedsTable = ({
52
87
< div className = "flex items-center gap-1.5" >
53
88
< div className = "w-1.5 h-1.5 bg-green-500 rounded-full flex-shrink-0" > </ div >
54
89
< span className = "font-medium" > Default:</ span >
55
- < span
56
- dangerouslySetInnerHTML = { {
57
- __html : defaultParams . replace ( "<br/>" , " / " ) ,
58
- } }
59
- />
90
+ < span > { defaultParams } </ span >
60
91
< span className = "text-gray-500" >
61
92
({ paramCounts [ defaultParams ] } )
62
93
</ span >
@@ -67,11 +98,7 @@ export const SponsoredFeedsTable = ({
67
98
< div key = { params } className = "flex items-center gap-1.5" >
68
99
< div className = "w-1.5 h-1.5 bg-orange-500 rounded-full flex-shrink-0" > </ div >
69
100
< span className = "font-medium" > Exception:</ span >
70
- < span
71
- dangerouslySetInnerHTML = { {
72
- __html : params . replace ( "<br/>" , " / " ) ,
73
- } }
74
- />
101
+ < span > { params } </ span >
75
102
< span className = "text-gray-500" > ({ count } )</ span >
76
103
</ div >
77
104
) ) }
@@ -97,11 +124,15 @@ export const SponsoredFeedsTable = ({
97
124
</ thead >
98
125
< tbody className = "bg-white dark:bg-gray-900" >
99
126
{ feeds . map ( ( feed , index ) => {
100
- const isDefault = feed . updateParameters === defaultParams ;
127
+ const formattedParams = formatUpdateParams (
128
+ feed . updateParameters
129
+ ) ;
130
+ const isDefault = formattedParams === defaultParams ;
101
131
const prevFeed = feeds [ index - 1 ] ;
102
132
const isFirstInGroup =
103
133
! prevFeed ||
104
- prevFeed . updateParameters !== feed . updateParameters ;
134
+ formatUpdateParams ( prevFeed . updateParameters ) !==
135
+ formattedParams ;
105
136
106
137
return (
107
138
< tr
@@ -139,23 +170,7 @@ export const SponsoredFeedsTable = ({
139
170
</ td >
140
171
< td className = "px-3 py-2 align-top" >
141
172
{ isFirstInGroup ? (
142
- < div className = "flex items-start gap-1.5" >
143
- < div
144
- className = { `w-1.5 h-1.5 rounded-full mt-1 flex-shrink-0 ${
145
- isDefault ? "bg-green-500" : "bg-orange-500"
146
- } `}
147
- > </ div >
148
- < span
149
- className = { `text-xs leading-relaxed font-medium ${
150
- isDefault
151
- ? "text-gray-700 dark:text-gray-300"
152
- : "text-orange-600 dark:text-orange-400"
153
- } `}
154
- dangerouslySetInnerHTML = { {
155
- __html : feed . updateParameters ,
156
- } }
157
- />
158
- </ div >
173
+ renderUpdateParams ( feed . updateParameters , isDefault )
159
174
) : (
160
175
< div className = "flex items-start gap-1.5 text-gray-400 text-xs" >
161
176
< div className = "w-1.5 h-1.5 bg-green-500 rounded-full mt-1 flex-shrink-0" > </ div >
0 commit comments