@@ -10,6 +10,11 @@ import {
1010 getBsnConfig ,
1111 type BsnFilterOption ,
1212} from "@/ui/common/services/bsnService" ;
13+ import {
14+ filterFinalityProvidersByBsn ,
15+ isFinalityProviderRowSelectable ,
16+ type FinalityProviderFilterState ,
17+ } from "@/ui/common/services/finalityProviderService" ;
1318import { Bsn } from "@/ui/common/types/bsn" ;
1419import {
1520 FinalityProviderState as FinalityProviderStateEnum ,
@@ -19,19 +24,12 @@ import { createStateUtils } from "@/ui/common/utils/createStateUtils";
1924
2025import { getBsnLogoUrl } from "../utils/bsnLogo" ;
2126
22- const normalizeHex = ( hex ?: string ) : string =>
23- ( hex ?? "" ) . trim ( ) . toLowerCase ( ) . replace ( / ^ 0 x / , "" ) ;
24-
2527interface SortState {
2628 field ?: string ;
2729 direction ?: "asc" | "desc" ;
2830}
2931
30- interface FilterState {
31- searchTerm : string ;
32- providerStatus : "active" | "inactive" | "" ;
33- allowlistStatus : "allowlisted" | "not-allowlisted" | "" ;
34- }
32+ type FilterState = FinalityProviderFilterState ;
3533
3634const { chainId : BBN_CHAIN_ID } = getNetworkConfigBBN ( ) ;
3735
@@ -90,107 +88,7 @@ const SORT_DIRECTIONS = {
9088 asc : undefined ,
9189} as const ;
9290
93- // BSN-specific status filters to handle different BSN behaviors
94- const BABYLON_STATUS_FILTERS = {
95- active : ( fp : FinalityProvider ) =>
96- fp . state === FinalityProviderStateEnum . ACTIVE ,
97- inactive : ( fp : FinalityProvider ) =>
98- fp . state === FinalityProviderStateEnum . INACTIVE ,
99- jailed : ( fp : FinalityProvider ) =>
100- fp . state === FinalityProviderStateEnum . JAILED ,
101- slashed : ( fp : FinalityProvider ) =>
102- fp . state === FinalityProviderStateEnum . SLASHED ,
103- } ;
104-
105- const COSMOS_STATUS_FILTERS = {
106- active : ( fp : FinalityProvider ) =>
107- fp . state === FinalityProviderStateEnum . ACTIVE ,
108- inactive : ( fp : FinalityProvider ) =>
109- fp . state === FinalityProviderStateEnum . INACTIVE ,
110- } ;
111-
112- const ROLLUP_STATUS_FILTERS = {
113- active : ( fp : FinalityProvider ) =>
114- fp . state === FinalityProviderStateEnum . ACTIVE ,
115- inactive : ( fp : FinalityProvider ) =>
116- fp . state === FinalityProviderStateEnum . INACTIVE ,
117- slashed : ( fp : FinalityProvider ) =>
118- fp . state === FinalityProviderStateEnum . SLASHED ,
119- } ;
120-
121- const BSN_STATUS_FILTERS = {
122- [ BBN_CHAIN_ID ] : BABYLON_STATUS_FILTERS ,
123- COSMOS : COSMOS_STATUS_FILTERS ,
124- ROLLUP : ROLLUP_STATUS_FILTERS ,
125- } ;
126-
127- const createAllowlistFilters = ( selectedBsn : Bsn | undefined ) => {
128- const allowSet = new Set ( ( selectedBsn ?. allowlist || [ ] ) . map ( normalizeHex ) ) ;
129-
130- return {
131- allowlisted : ( fp : FinalityProvider ) => allowSet . has ( normalizeHex ( fp . btcPk ) ) ,
132- "not-allowlisted" : ( fp : FinalityProvider ) =>
133- ! allowSet . has ( normalizeHex ( fp . btcPk ) ) ,
134- } ;
135- } ;
136-
137- const filterFinalityProvidersByBsn = (
138- providers : FinalityProvider [ ] ,
139- filter : FilterState ,
140- selectedBsn : Bsn | undefined ,
141- fpFilterBehavior : "status-based" | "allowlist-based" ,
142- ) : FinalityProvider [ ] => {
143- let filtered = providers ;
144-
145- // Apply BSN-aware filtering based on provider status
146- if ( filter . providerStatus ) {
147- if ( fpFilterBehavior === "allowlist-based" ) {
148- // For rollup BSNs: filter all FPs by allowlist (regardless of active/inactive state)
149- const allowSet = new Set (
150- ( selectedBsn ?. allowlist || [ ] ) . map ( normalizeHex ) ,
151- ) ;
152-
153- filtered = filtered . filter ( ( fp ) => {
154- const isAllowlisted = allowSet . has ( normalizeHex ( fp . btcPk ) ) ;
155-
156- if ( filter . providerStatus === "active" ) {
157- return isAllowlisted ;
158- } else if ( filter . providerStatus === "inactive" ) {
159- return ! isAllowlisted ;
160- } else {
161- // Handle slashed state for rollups
162- return fp . state === FinalityProviderStateEnum . SLASHED ;
163- }
164- } ) ;
165- } else if ( fpFilterBehavior === "status-based" ) {
166- // For status-based BSNs: filter by finality provider state using BSN-specific filters
167- const bsnKey =
168- selectedBsn ?. id === BBN_CHAIN_ID
169- ? BBN_CHAIN_ID
170- : selectedBsn ?. type || BBN_CHAIN_ID ;
171- const bsnStatusFilters =
172- BSN_STATUS_FILTERS [ bsnKey ] || BSN_STATUS_FILTERS [ BBN_CHAIN_ID ] ;
173- const statusFilter =
174- bsnStatusFilters [
175- filter . providerStatus as keyof typeof bsnStatusFilters
176- ] ;
177- if ( statusFilter ) {
178- filtered = filtered . filter ( statusFilter ) ;
179- }
180- }
181- }
182-
183- if ( filter . allowlistStatus ) {
184- const allowlistFilters = createAllowlistFilters ( selectedBsn ) ;
185- const allowlistFilter =
186- allowlistFilters [ filter . allowlistStatus as keyof typeof allowlistFilters ] ;
187- if ( allowlistFilter ) {
188- filtered = filtered . filter ( allowlistFilter ) ;
189- }
190- }
191-
192- return filtered ;
193- } ;
91+ // Component-specific constants remain in the state file
19492
19593const FILTERS = {
19694 searchTerm : ( fp : FinalityProvider , filter : FilterState ) => {
@@ -339,21 +237,8 @@ export function FinalityProviderBsnState({ children }: PropsWithChildren) {
339237 } , [ ] ) ;
340238
341239 const isRowSelectable = useCallback (
342- ( row : FinalityProvider ) => {
343- const statusAllowed =
344- row . state === FinalityProviderStateEnum . ACTIVE ||
345- row . state === FinalityProviderStateEnum . INACTIVE ;
346-
347- // For selection (not filtering), only restrict based on allowlist for non-Babylon BSNs
348- const allowlistAllowed =
349- ! selectedBsnId ||
350- selectedBsnId === BBN_CHAIN_ID ||
351- ( selectedBsn ?. allowlist || [ ] ) . some (
352- ( allowedPk ) => normalizeHex ( allowedPk ) === normalizeHex ( row . btcPk ) ,
353- ) ;
354-
355- return statusAllowed && allowlistAllowed ;
356- } ,
240+ ( row : FinalityProvider ) =>
241+ isFinalityProviderRowSelectable ( row , selectedBsnId , selectedBsn ) ,
357242 [ selectedBsnId , selectedBsn ] ,
358243 ) ;
359244
0 commit comments