@@ -11,13 +11,97 @@ import { Tooltip } from "../../components/Tooltip";
1111import useAccount from "../../hooks/useAccount" ;
1212import { Popover , PopoverDisclosure , usePopoverStore } from "@ariakit/react/popover" ;
1313
14+ // Test functions for trace and archive support
15+ const testTraceSupport = async ( rpcUrl ) => {
16+ const payload = {
17+ jsonrpc : "2.0" ,
18+ method : "debug_traceTransaction" ,
19+ params : [
20+ "0x5a5efc6dd80fd85b291d0c2f79a1c88f2cb36aa9e5bd1951972e8b4cf5d9b17b"
21+ ] ,
22+ id : 1 ,
23+ } ;
24+
25+ try {
26+ const response = await fetch ( rpcUrl , {
27+ method : "POST" ,
28+ headers : { "Content-Type" : "application/json" } ,
29+ body : JSON . stringify ( payload ) ,
30+ } ) ;
31+
32+ const data = await response . json ( ) ;
33+ return data . result ? "supported" : "not-supported" ;
34+ } catch ( error ) {
35+ return "error" ;
36+ }
37+ } ;
38+
39+ const testArchiveSupport = async ( rpcUrl ) => {
40+ const payload = {
41+ jsonrpc : "2.0" ,
42+ method : "eth_getBalance" ,
43+ params : [
44+ "0x742d35Cc6634C0532925a3b844Bc454e4438f44e" ,
45+ "0x0"
46+ ] ,
47+ id : 1 ,
48+ } ;
49+
50+ try {
51+ const response = await fetch ( rpcUrl , {
52+ method : "POST" ,
53+ headers : { "Content-Type" : "application/json" } ,
54+ body : JSON . stringify ( payload ) ,
55+ } ) ;
56+
57+ const data = await response . json ( ) ;
58+ return data . result ? "supported" : "not-supported" ;
59+ } catch ( error ) {
60+ return "error" ;
61+ }
62+ } ;
63+
1464export default function RPCList ( { chain, lang } ) {
1565 const [ sortChains , setSorting ] = useState ( true ) ;
66+ const [ supportCache , setSupportCache ] = useState ( { } ) ;
1667
1768 const urlToData = chain . rpc . reduce ( ( all , c ) => ( { ...all , [ c . url ] : c } ) , { } ) ;
1869
1970 const chains = useRPCData ( chain . rpc ) ;
2071
72+ // Test trace and archive support for each RPC
73+ useEffect ( ( ) => {
74+ const testSupport = async ( ) => {
75+ const newCache = { ...supportCache } ;
76+
77+ for ( const chain of chains || [ ] ) {
78+ if ( chain . data ?. url && ! supportCache [ chain . data . url ] ) {
79+ newCache [ chain . data . url ] = {
80+ trace : "testing" ,
81+ archive : "testing"
82+ } ;
83+
84+ // Test both features in parallel
85+ const [ traceResult , archiveResult ] = await Promise . all ( [
86+ testTraceSupport ( chain . data . url ) ,
87+ testArchiveSupport ( chain . data . url )
88+ ] ) ;
89+
90+ newCache [ chain . data . url ] = {
91+ trace : traceResult ,
92+ archive : archiveResult
93+ } ;
94+ }
95+ }
96+
97+ setSupportCache ( newCache ) ;
98+ } ;
99+
100+ if ( chains ?. length > 0 ) {
101+ testSupport ( ) ;
102+ }
103+ } , [ chains ] ) ;
104+
21105 const data = useMemo ( ( ) => {
22106 const sortedData = sortChains
23107 ? chains ?. sort ( ( a , b ) => {
@@ -70,12 +154,23 @@ export default function RPCList({ chain, lang }) {
70154
71155 const lat = latency ? ( latency / 1000 ) . toFixed ( 3 ) + "s" : null ;
72156
157+ // Add trace and archive support data
158+ const support = supportCache [ url ] || { trace : "unknown" , archive : "unknown" } ;
159+
73160 return {
74161 ...rest ,
75- data : { ...data , height, latency : lat , trust, disableConnect } ,
162+ data : {
163+ ...data ,
164+ height,
165+ latency : lat ,
166+ trust,
167+ disableConnect,
168+ traceSupport : support . trace ,
169+ archiveSupport : support . archive
170+ } ,
76171 } ;
77172 } ) ;
78- } , [ chains ] ) ;
173+ } , [ chains , supportCache ] ) ;
79174
80175 const { rpcData, hasLlamaNodesRpc } = useLlamaNodesRpcData ( chain . chainId , data ) ;
81176
@@ -113,6 +208,8 @@ export default function RPCList({ chain, lang }) {
113208 < th className = "px-3 py-1 font-medium border" > Latency</ th >
114209 < th className = "px-3 py-1 font-medium border" > Score</ th >
115210 < th className = "px-3 py-1 font-medium border" > Privacy</ th >
211+ < th className = "px-3 py-1 font-medium border" > Trace</ th >
212+ < th className = "px-3 py-1 font-medium border" > Archive</ th >
116213 < th className = "px-3 py-1 font-medium border" > </ th >
117214 </ tr >
118215 </ thead >
@@ -163,6 +260,21 @@ function PrivacyIcon({ tracking, isOpenSource = false }) {
163260 return < EmptyIcon /> ;
164261}
165262
263+ function SupportIcon ( { support } ) {
264+ switch ( support ) {
265+ case "supported" :
266+ return < GreenIcon /> ;
267+ case "not-supported" :
268+ return < RedIcon /> ;
269+ case "error" :
270+ return < OrangeIcon /> ;
271+ case "testing" :
272+ return < div className = "w-4 h-4 mx-auto animate-spin rounded-full border-2 border-gray-300 border-t-blue-600" > </ div > ;
273+ default :
274+ return < EmptyIcon /> ;
275+ }
276+ }
277+
166278const Row = ( { values, chain, privacy, lang, className } ) => {
167279 const t = useTranslations ( "Common" , lang ) ;
168280 const { data, isLoading, refetch } = values ;
@@ -184,6 +296,21 @@ const Row = ({ values, chain, privacy, lang, className }) => {
184296
185297 const { mutate : addToNetwork } = useAddToNetwork ( ) ;
186298
299+ const getTooltipContent = ( support , type ) => {
300+ switch ( support ) {
301+ case "supported" :
302+ return `${ type } methods are supported` ;
303+ case "not-supported" :
304+ return `${ type } methods are not supported` ;
305+ case "error" :
306+ return `Error testing ${ type } support` ;
307+ case "testing" :
308+ return `Testing ${ type } support...` ;
309+ default :
310+ return `${ type } support unknown` ;
311+ }
312+ } ;
313+
187314 return (
188315 < tr className = { className } >
189316 < td className = "border px-3 py-1 max-w-[40ch]" >
@@ -211,6 +338,16 @@ const Row = ({ values, chain, privacy, lang, className }) => {
211338 { isLoading ? < Shimmer /> : < PrivacyIcon tracking = { privacy ?. tracking } isOpenSource = { privacy ?. isOpenSource } /> }
212339 </ Tooltip >
213340 </ td >
341+ < td className = "px-3 py-1 text-sm border" >
342+ < Tooltip content = { getTooltipContent ( data ?. traceSupport , "Trace" ) } >
343+ { isLoading ? < Shimmer /> : < SupportIcon support = { data ?. traceSupport } /> }
344+ </ Tooltip >
345+ </ td >
346+ < td className = "px-3 py-1 text-sm border" >
347+ < Tooltip content = { getTooltipContent ( data ?. archiveSupport , "Archive" ) } >
348+ { isLoading ? < Shimmer /> : < SupportIcon support = { data ?. archiveSupport } /> }
349+ </ Tooltip >
350+ </ td >
214351 < td className = "px-3 py-1 text-sm text-center border" >
215352 { isLoading ? (
216353 < Shimmer />
0 commit comments