@@ -13,9 +13,13 @@ import {
1313 Network ,
1414 DecomConfig ,
1515 DecommissionedNetwork ,
16+ VerifiersConfig ,
17+ Verifier ,
18+ VerifierType ,
1619} from "./types.ts"
1720import { determineTokenMechanism } from "./utils.ts"
1821import { ExplorerInfo , SupportedChain , ChainType } from "@config/types.ts"
22+ import { VERIFIER_LOGOS_PATH } from "@config/cdn.ts"
1923import {
2024 directoryToSupportedChain ,
2125 getChainIcon ,
@@ -42,6 +46,10 @@ import tokensTestnetv120 from "@config/data/ccip/v1_2_0/testnet/tokens.json" wit
4246import decomMainnetv120 from "@config/data/ccip/v1_2_0/mainnet/decom.json" with { type : "json" }
4347import decomTestnetv120 from "@config/data/ccip/v1_2_0/testnet/decom.json" with { type : "json" }
4448
49+ // For verifiers
50+ import verifiersMainnetv120 from "@config/data/ccip/v1_2_0/mainnet/verifiers.json" with { type : "json" }
51+ import verifiersTestnetv120 from "@config/data/ccip/v1_2_0/testnet/verifiers.json" with { type : "json" }
52+
4553// Import errors by version
4654// eslint-disable-next-line camelcase
4755import * as errors_v1_5_0 from "./errors/v1_5_0/index.ts"
@@ -815,3 +823,233 @@ export const getDecommissionedNetwork = ({ chain, filter }: { chain: string; fil
815823 const decommissionedChains = getAllDecommissionedNetworks ( { filter } )
816824 return decommissionedChains . find ( ( network ) => network . chain === chain )
817825}
826+
827+ // ============================================================================
828+ // Verifier utilities
829+ // ============================================================================
830+
831+ /**
832+ * Load verifiers data for a specific environment and version
833+ */
834+ export const loadVerifiersData = ( { environment, version } : { environment : Environment ; version : Version } ) => {
835+ let verifiersReferenceData : VerifiersConfig
836+
837+ if ( environment === Environment . Mainnet && version === Version . V1_2_0 ) {
838+ verifiersReferenceData = verifiersMainnetv120 as unknown as VerifiersConfig
839+ } else if ( environment === Environment . Testnet && version === Version . V1_2_0 ) {
840+ verifiersReferenceData = verifiersTestnetv120 as unknown as VerifiersConfig
841+ } else {
842+ throw new Error ( `Invalid environment/version combination for verifiers: ${ environment } /${ version } ` )
843+ }
844+
845+ return { verifiersReferenceData }
846+ }
847+
848+ /**
849+ * Get logo URL for a verifier by ID
850+ * Uses CloudFront CDN, same infrastructure as token icons
851+ */
852+ export const getVerifierLogoUrl = ( verifierId : string ) : string => {
853+ return `${ VERIFIER_LOGOS_PATH } /${ verifierId } .svg`
854+ }
855+
856+ /**
857+ * Map verifier type to display-friendly name
858+ */
859+ export const getVerifierTypeDisplay = ( type : VerifierType ) : string => {
860+ const VERIFIER_TYPE_DISPLAY : Record < VerifierType , string > = {
861+ committee : "Committee" ,
862+ api : "API" ,
863+ }
864+
865+ return VERIFIER_TYPE_DISPLAY [ type ] || type
866+ }
867+
868+ /**
869+ * Get all verifiers for a specific environment as a flattened list
870+ */
871+ export const getAllVerifiers = ( {
872+ environment,
873+ version = Version . V1_2_0 ,
874+ } : {
875+ environment : Environment
876+ version ?: Version
877+ } ) : Verifier [ ] => {
878+ const { verifiersReferenceData } = loadVerifiersData ( { environment, version } )
879+
880+ const verifiers : Verifier [ ] = [ ]
881+
882+ // Flatten the network -> address -> metadata structure
883+ for ( const [ networkId , addressMap ] of Object . entries ( verifiersReferenceData ) ) {
884+ for ( const [ address , metadata ] of Object . entries ( addressMap ) ) {
885+ verifiers . push ( {
886+ ...metadata ,
887+ network : networkId ,
888+ address,
889+ logo : getVerifierLogoUrl ( metadata . id ) ,
890+ } )
891+ }
892+ }
893+
894+ // Sort by verifier name, then by network
895+ return verifiers . sort ( ( a , b ) => {
896+ const nameComparison = a . name . localeCompare ( b . name )
897+ if ( nameComparison !== 0 ) return nameComparison
898+ return a . network . localeCompare ( b . network )
899+ } )
900+ }
901+
902+ /**
903+ * Get all verifiers for a specific network
904+ */
905+ export const getVerifiersByNetwork = ( {
906+ networkId,
907+ environment,
908+ version = Version . V1_2_0 ,
909+ } : {
910+ networkId : string
911+ environment : Environment
912+ version ?: Version
913+ } ) : Verifier [ ] => {
914+ const { verifiersReferenceData } = loadVerifiersData ( { environment, version } )
915+
916+ const addressMap = verifiersReferenceData [ networkId ]
917+ if ( ! addressMap ) {
918+ return [ ]
919+ }
920+
921+ const verifiers : Verifier [ ] = [ ]
922+ for ( const [ address , metadata ] of Object . entries ( addressMap ) ) {
923+ verifiers . push ( {
924+ ...metadata ,
925+ network : networkId ,
926+ address,
927+ logo : getVerifierLogoUrl ( metadata . id ) ,
928+ } )
929+ }
930+
931+ return verifiers . sort ( ( a , b ) => a . name . localeCompare ( b . name ) )
932+ }
933+
934+ /**
935+ * Get all verifiers of a specific type (committee or api)
936+ */
937+ export const getVerifiersByType = ( {
938+ type,
939+ environment,
940+ version = Version . V1_2_0 ,
941+ } : {
942+ type : VerifierType
943+ environment : Environment
944+ version ?: Version
945+ } ) : Verifier [ ] => {
946+ const allVerifiers = getAllVerifiers ( { environment, version } )
947+ return allVerifiers . filter ( ( verifier ) => verifier . type === type )
948+ }
949+
950+ /**
951+ * Get all networks where a specific verifier exists (by verifier ID)
952+ */
953+ export const getVerifierById = ( {
954+ id,
955+ environment,
956+ version = Version . V1_2_0 ,
957+ } : {
958+ id : string
959+ environment : Environment
960+ version ?: Version
961+ } ) : Verifier [ ] => {
962+ const allVerifiers = getAllVerifiers ( { environment, version } )
963+ return allVerifiers . filter ( ( verifier ) => verifier . id === id )
964+ }
965+
966+ /**
967+ * Get a specific verifier by network and address
968+ */
969+ export const getVerifier = ( {
970+ networkId,
971+ address,
972+ environment,
973+ version = Version . V1_2_0 ,
974+ } : {
975+ networkId : string
976+ address : string
977+ environment : Environment
978+ version ?: Version
979+ } ) : Verifier | undefined => {
980+ const { verifiersReferenceData } = loadVerifiersData ( { environment, version } )
981+
982+ const addressMap = verifiersReferenceData [ networkId ]
983+ if ( ! addressMap ) {
984+ return undefined
985+ }
986+
987+ const metadata = addressMap [ address ]
988+ if ( ! metadata ) {
989+ return undefined
990+ }
991+
992+ return {
993+ ...metadata ,
994+ network : networkId ,
995+ address,
996+ logo : getVerifierLogoUrl ( metadata . id ) ,
997+ }
998+ }
999+
1000+ /**
1001+ * Get all network IDs where a specific verifier exists
1002+ * Similar to getChainsOfToken for tokens
1003+ */
1004+ export const getNetworksOfVerifier = ( {
1005+ id,
1006+ environment,
1007+ version = Version . V1_2_0 ,
1008+ } : {
1009+ id : string
1010+ environment : Environment
1011+ version ?: Version
1012+ } ) : string [ ] => {
1013+ const verifiers = getVerifierById ( { id, environment, version } )
1014+ return verifiers . map ( ( v ) => v . network )
1015+ }
1016+
1017+ /**
1018+ * Get unique verifiers for display (deduplicated by ID)
1019+ * Returns one entry per verifier with totalNetworks count
1020+ * Useful for landing page display where each verifier should appear once
1021+ */
1022+ export const getAllUniqueVerifiers = ( {
1023+ environment,
1024+ version = Version . V1_2_0 ,
1025+ } : {
1026+ environment : Environment
1027+ version ?: Version
1028+ } ) : Array < {
1029+ id : string
1030+ name : string
1031+ type : VerifierType
1032+ logo : string
1033+ totalNetworks : number
1034+ } > => {
1035+ const allVerifiers = getAllVerifiers ( { environment, version } )
1036+
1037+ // Get unique verifier IDs
1038+ const uniqueIds = Array . from ( new Set ( allVerifiers . map ( ( v ) => v . id ) ) )
1039+
1040+ // Map to display format with network count
1041+ return uniqueIds
1042+ . map ( ( id ) => {
1043+ const instances = allVerifiers . filter ( ( v ) => v . id === id )
1044+ const firstInstance = instances [ 0 ]
1045+
1046+ return {
1047+ id,
1048+ name : firstInstance . name ,
1049+ type : firstInstance . type ,
1050+ logo : firstInstance . logo ,
1051+ totalNetworks : instances . length ,
1052+ }
1053+ } )
1054+ . sort ( ( a , b ) => a . name . localeCompare ( b . name ) )
1055+ }
0 commit comments