From 43e51322e5066c9ad691afc232a689b10c518280 Mon Sep 17 00:00:00 2001 From: OneEuroQuestion Date: Thu, 30 Jan 2025 22:33:25 +0100 Subject: [PATCH] done --- PUBLICAPI.md | 4 +- src/lib/chain-mapping/chains.ts | 112 +++++ src/lib/icons/data/chain-icons.ts | 171 +++++++ src/lib/icons/data/gateway-icons.json | 422 ++++++++++++++++++ src/lib/icons/icons.ts | 49 ++ .../handlers/ajax/allProviderAprHandler.ts | 126 +----- .../ajax/providerPerfomanceHandler.ts | 216 +++++++++ src/query/queryRoutes.ts | 7 +- .../resources/ajax/AllProviderAprResource.ts | 1 - .../resources/ajax/ListProvidersResource.ts | 117 +---- 10 files changed, 992 insertions(+), 233 deletions(-) create mode 100644 src/lib/chain-mapping/chains.ts create mode 100644 src/lib/icons/data/chain-icons.ts create mode 100644 src/lib/icons/data/gateway-icons.json create mode 100644 src/lib/icons/icons.ts create mode 100644 src/query/handlers/ajax/providerPerfomanceHandler.ts diff --git a/PUBLICAPI.md b/PUBLICAPI.md index 9c2eac2..c24acee 100644 --- a/PUBLICAPI.md +++ b/PUBLICAPI.md @@ -171,7 +171,7 @@ This endpoint returns a list of all providers along with their APR, commission r // [same as on the rewards website](https://rewards.lavanet.xyz/provider_rewards) // but return spec to { - "chain": "lava mainnet", + "chain": "Lava Mainnet", "spec": "LAVA", "tokens": [ { @@ -196,7 +196,7 @@ This endpoint returns a list of all providers along with their APR, commission r "delegateCommission": "50", // Delegation commission "delegateTotal": "94912424429", // Total delegations "moniker": "Protofire DAO" // Provider name for this spec - "icon": + "icon": "url" ... }, { "chain": "fvm mainnet", diff --git a/src/lib/chain-mapping/chains.ts b/src/lib/chain-mapping/chains.ts new file mode 100644 index 0000000..a706b76 --- /dev/null +++ b/src/lib/chain-mapping/chains.ts @@ -0,0 +1,112 @@ +const chainMapping: Record = { + ETH1: "Ethereum Mainnet", + EVMOS: "Evmos Mainnet", + NEAR: "NEAR Mainnet", + NEART: "NEAR Testnet", + EVMOST: "Evmos Testnet", + ARB1: "Arbitrum Mainnet", + POLYGON: "Polygon Mainnet", + POLYGON1: "Polygon Mainnet", + CELO: "Celo Mainnet", + STRK: "Starknet Mainnet", + STRKS: "Starknet Sepolia Testnet", + LAVA: "Lava Mainnet", + AVAX: "Avalanche Mainnet", + AVAXT: "Avalanche Testnet", + OSMOSIS: "Osmosis Mainnet", + OSMOSIST: "Osmosis Testnet", + SUIT: "Sui Devnet", + FUELNETWORK: "Fuel Network GraphQL", + COSMOSSDK45DEP: "Cosmos SDK Deprecated APIs", + SOLANA: "Solana Mainnet", + SOLANAT: "Solana Testnet", + SCROLL: "Scroll Mainnet", + SCROLLS: "Scroll Sepolia Testnet", + TENDERMINT: "Tendermint", + CANTO: "Canto Mainnet", + COSMOSHUB: "Cosmos Hub Mainnet", + COSMOSHUBT: "Cosmos Hub Testnet", + COSMOSWASM: "CosmWasm", + FVM: "Filecoin Mainnet", + FTM250: "Fantom Mainnet", + FTM4002: "Fantom Testnet", + SQDSUBGRAPH: "Subsquid Powered Subgraph", + BERAT: "Berachain Testnet", + MOVEMENT: "Movement Mainnet", + MANTAPACIFIC: "Manta Pacific Mainnet", + MANTAPACIFICT: "Manta Pacific Testnet", + SEP1: "Ethereum Sepolia Testnet", + HOL1: "Ethereum Holesky Testnet", + JUN1: "Juno Mainnet", + JUNT1: "Juno Testnet", + BSC: "Binance Smart Chain Mainnet", + BSCT: "Binance Smart Chain Testnet", + COSMOSSDKFULL: "Cosmos SDK Full", + IBC: "Inter-Blockchain Communication", + SIDET: "Side Testnet", + MORALIS: "Moralis Advanced API", + CELESTIA: "Celestia Mainnet", + CELESTIATM: "Celestia Mocha Testnet", + CELESTIATA: "Celestia Arabica Testnet", + KOII: "Koii Mainnet", + KOIIT: "Koii Testnet", + MANTLE: "Mantle Testnet", + LAV1: "Lava Testnet", + AXELAR: "Axelar Mainnet", + AXELART: "Axelar Testnet", + AGR: "Agoric Mainnet", + AGRT: "Agoric Testnet", + ETHBEACON: "Ethereum Beacon Mainnet", + BASE: "Base Mainnet", + BASES: "Base Sepolia Testnet", + BASET: "Base Sepolia Testnet", + ZKSYNC: "zkSync Era Mainnet", + ZKSYNCSP: "zkSync Era Sepolia Testnet", + ETHERMINT: "Ethermint", + SECRET: "Secret Mainnet", + SECRETP: "Secret Testnet", + APT1: "Aptos Mainnet", + OPTM: "Optimism Mainnet", + OPTMS: "Optimism Sepolia Testnet", + ARBN: "Arbitrum Nova Testnet", + ARBS: "Arbitrum Sepolia Testnet", + KAKAROTT: "Kakarot Sepolia Testnet", + BLAST: "Blast Mainnet", + BLASTSP: "Blast Special", + ALFAJORES: "Celo Alfajores Testnet", + UNIONT: "Union Testnet", + STRGZ: "Stargaze Mainnet", + STRGZT: "Stargaze Testnet", + NAMTSE: "Namada SE Testnet", + COSMOSSDK: "Cosmos SDK", + POLYGON1A: "Polygon Amoy Testnet", + COS3: "Osmosis Mainnet", + COS4: "Osmosis Testnet", + COS5: "Cosmos Hub Mainnet", + COS5T: "Cosmos Hub Testnet", + COSHUB: "Cosmos Hub Mainnet", + COSHUBT: "Cosmos Hub Testnet", + GTH1: "Ethereum Goerli Testnet", + OPTMT: "Optimism Goerli Testnet", + OSMO: "Osmosis Mainnet", + OSMOT: "Osmosis Testnet", + POLYGON1T: "Polygon Testnet", + STRKT: "Starknet Testnet", + SUI: "Sui Devnet", + FUSET: "Fuse Testnet", + UNION: "Union Mainnet" +}; + +/** + * Converts a chain abbreviation to its full name + * @param abbreviation The chain abbreviation (e.g. "ETH1", "EVMOS") + * @returns The full chain name or empty string if not found + */ +export function ConvertToChainName(abbreviation: string): string { + if (typeof abbreviation !== 'string') { + return ''; + } + return chainMapping[abbreviation.toUpperCase()] || ''; +} + +export default chainMapping; \ No newline at end of file diff --git a/src/lib/icons/data/chain-icons.ts b/src/lib/icons/data/chain-icons.ts new file mode 100644 index 0000000..2407db7 --- /dev/null +++ b/src/lib/icons/data/chain-icons.ts @@ -0,0 +1,171 @@ +// src/lib/chain-dictionary.tsx + +export interface ChainInfo { + name: string; + icon: string; +} + +export const chainDictionary: { [key: string]: ChainInfo } = { + near: { name: "Near", icon: "/icons/near.svg" }, + neart: { name: "Near Testnet", icon: "/icons/near.svg" }, + osmosis: { name: "Osmosis", icon: "/icons/osmosis.svg" }, + osmosist: { name: "Osmosis Testnet", icon: "/icons/osmosis.svg" }, + strk: { name: "Starknet", icon: "/icons/starknet.svg" }, + strkt: { name: "Starknet Testnet", icon: "/icons/starknet.svg" }, + strks: { name: "Starknet Sepolia", icon: "/icons/starknet.svg" }, + polygon: { name: "Polygon", icon: "/icons/polygon-pos.svg" }, + polygon1: { name: "Polygon", icon: "/icons/polygon-pos.svg" }, + solana: { name: "Solana", icon: "/icons/solana.svg" }, + solanat: { name: "Solana Testnet", icon: "/icons/solana.svg" }, + eth1: { name: "Ethereum", icon: "/icons/ethereum.svg" }, + eth: { name: "Ethereum", icon: "/icons/ethereum.svg" }, + sep1: { name: "Sepolia", icon: "/icons/ethereum.svg" }, + strgz: { name: "Stargaze", icon: "/icons/stargaze.webp" }, + strgzt: { name: "Stargaze Testnet", icon: "/icons/stargaze.webp" }, + optm: { name: "Optimism", icon: "/icons/optimism.svg" }, + optms: { name: "Optimism", icon: "/icons/optimism.svg" }, + lava: { name: "Lava Network", icon: "/icons/lava.svg" }, + lav1: { name: "Lava Testnet", icon: "/icons/lava.svg" }, + axelar: { name: "Axelar", icon: "/icons/axelar.svg" }, + axelart: { name: "Axelar Testnet", icon: "/icons/axelar.svg" }, + base: { name: "Base", icon: "/icons/base.svg" }, + bases: { name: "Base Sepolia Testnet", icon: "/icons/base.svg" }, + baset: { name: "Base Testnet", icon: "/icons/base.svg" }, + evmos: { name: "Evmos", icon: "/icons/evmos.svg" }, + evmost: { name: "Evmos Testnet", icon: "/icons/evmos.svg" }, + arb1: { name: "Arbitrum", icon: "/icons/arbitrum-one.svg" }, + arbitrum: { name: "Arbitrum", icon: "/icons/arbitrum-one.svg" }, + arbitrumt: { name: "Arbitrum Testnet", icon: "/icons/arbitrum-one.svg" }, + arbitrumn: { name: "Arbitrum Nova", icon: "/icons/arbitrum-nova.svg" }, + arbitrums: { name: "Arbitrum Sepolia Testnet", icon: "/icons/arbitrum-nova.svg" }, + arbn: { name: "Arbitrum Nova", icon: "/icons/arbitrum-nova.svg" }, + ftm250: { name: "Fantom", icon: "/icons/fantom.svg" }, + abstract: { name: "Abstract", icon: "/icons/abstract.svg" }, + acala: { name: "Acala", icon: "/icons/acala.svg" }, + apex: { name: "Apex Layer", icon: "/icons/apex-layer.svg" }, + aptos: { name: "Aptos", icon: "/icons/aptos.svg" }, + astar: { name: "Astar", icon: "/icons/astar.svg" }, + aurora: { name: "Aurora", icon: "/icons/aurora.svg" }, + avax: { name: "Avalanche", icon: "/icons/avalanche.svg" }, + beam: { name: "Beam", icon: "/icons/beam.svg" }, + bsc: { name: "Binance Smart Chain", icon: "/icons/binance-smart-chain.svg" }, + bsct: { name: "Binance Smart Chain Testnet", icon: "/icons/binance-smart-chain.svg" }, + btc: { name: "Bitcoin", icon: "/icons/bitcoin.svg" }, + bitkub: { name: "Bitkub Chain", icon: "/icons/bitkub-chain.svg" }, + blast: { name: "Blast", icon: "/icons/blast.svg" }, + blastt: { name: "Blast Testnet", icon: "/icons/blast.svg" }, + blastsp: { name: "Blast Sepolia Testnet", icon: "/icons/blast.svg" }, + boba: { name: "Boba", icon: "/icons/boba.svg" }, + bouncebit: { name: "BounceBit", icon: "/icons/bouncebit.svg" }, + cardano: { name: "Cardano", icon: "/icons/cardano.svg" }, + celo: { name: "Celo", icon: "/icons/celo.svg" }, + alfajores: { name: "Celo Alfajores Testnet", icon: "/icons/celo.svg" }, + chiliz: { name: "Chiliz", icon: "/icons/chiliz.svg" }, + clover: { name: "Clover", icon: "/icons/clover.svg" }, + csc: { name: "CoinEx Smart Chain", icon: "/icons/coinex-smart-chain.svg" }, + conflux: { name: "Conflux", icon: "/icons/conflux.svg" }, + cos5: { name: "Cosmos Hub", icon: "/icons/cosmos-hub.svg" }, + cosmos: { name: "Cosmos Hub", icon: "/icons/cosmos-hub.svg" }, + cosmoshub: { name: "Cosmos Hub", icon: "/icons/cosmos-hub.svg" }, + cosmoshubt: { name: "Cosmos Hub", icon: "/icons/cosmos-hub.svg" }, + cronos: { name: "Cronos", icon: "/icons/cronos.svg" }, + cronosZkEvm: { name: "Cronos zkEVM", icon: "/icons/cronos-zkevm.svg" }, + dogechain: { name: "Dogechain", icon: "/icons/dogechain.svg" }, + elastos: { name: "Elastos", icon: "/icons/elastos.svg" }, + energyWeb: { name: "Energy Web", icon: "/icons/energy-web.svg" }, + enuls: { name: "ENULS", icon: "/icons/enuls.svg" }, + etc: { name: "Ethereum Classic", icon: "/icons/ethereum-classic.svg" }, + etherlink: { name: "Etherlink", icon: "/icons/etherlink.svg" }, + filecoin: { name: "Filecoin", icon: "/icons/filecoin.svg" }, + fio: { name: "FIO", icon: "/icons/fio.svg" }, + flare: { name: "Flare", icon: "/icons/flare.svg" }, + fraxtal: { name: "Fraxtal", icon: "/icons/fraxtal.svg" }, + fuse: { name: "Fuse", icon: "/icons/fuse.svg" }, + gnosis: { name: "Gnosis", icon: "/icons/gnosis.svg" }, + gravity: { name: "Gravity", icon: "/icons/gravity.svg" }, + hedera: { name: "Hedera Hashgraph", icon: "/icons/hedera-hashgraph.svg" }, + hubble: { name: "Hubble Exchange", icon: "/icons/hubble-exchange.svg" }, + immutable: { name: "Immutable", icon: "/icons/immutable.svg" }, + injective: { name: "Injective", icon: "/icons/injective.svg" }, + iotex: { name: "IoTeX", icon: "/icons/iotex.svg" }, + juno: { name: "Juno", icon: "/icons/juno.svg" }, + jun1: { name: "Juno", icon: "/icons/juno.svg" }, + kardia: { name: "Kardia", icon: "/icons/kardia.svg" }, + kava: { name: "Kava", icon: "/icons/kava.svg" }, + kucoin: { name: "KuCoin", icon: "/icons/kucoin.svg" }, + kujira: { name: "Kujira", icon: "/icons/kujira.svg" }, + linea: { name: "Linea", icon: "/icons/linea.svg" }, + litecoin: { name: "Litecoin", icon: "/icons/litecoin.svg" }, + loopring: { name: "Loopring", icon: "/icons/loopring.svg" }, + lukso: { name: "LUKSO", icon: "/icons/lukso.svg" }, + lyra: { name: "Lyra", icon: "/icons/lyra.svg" }, + manta: { name: "Manta Pacific", icon: "/icons/manta-pacific.svg" }, + mantle: { name: "Mantle", icon: "/icons/mantle.svg" }, + matic: { name: "Matic", icon: "/icons/matic.svg" }, + meter: { name: "Meter", icon: "/icons/meter.svg" }, + metis: { name: "Metis Andromeda", icon: "/icons/metis-andromeda.svg" }, + milkomedaA1: { name: "Milkomeda A1", icon: "/icons/milkomeda-a1.svg" }, + milkomedaC1: { name: "Milkomeda C1", icon: "/icons/milkomeda-c1.svg" }, + mode: { name: "Mode", icon: "/icons/mode.svg" }, + moonbeam: { name: "Moonbeam", icon: "/icons/moonbeam.svg" }, + moonriver: { name: "Moonriver", icon: "/icons/moonriver.svg" }, + multiversx: { name: "MultiversX", icon: "/icons/multiversx.svg" }, + nahmii: { name: "Nahmii", icon: "/icons/nahmii.svg" }, + neoX: { name: "Neo X", icon: "/icons/neo-x.svg" }, + neonEvm: { name: "Neon EVM", icon: "/icons/neon-evm.svg" }, + oasys: { name: "Oasys", icon: "/icons/oasys.svg" }, + okex: { name: "OKEx", icon: "/icons/okex.svg" }, + polkadot: { name: "Polkadot", icon: "/icons/polkadot.svg" }, + polygonZkEvm: { name: "Polygon zkEVM", icon: "/icons/polygon-zkevm.svg" }, + rari: { name: "Rari", icon: "/icons/rari.svg" }, + reya: { name: "Reya", icon: "/icons/reya.svg" }, + rollux: { name: "Rollux", icon: "/icons/rollux.svg" }, + ronin: { name: "Ronin", icon: "/icons/ronin.svg" }, + rootstock: { name: "Rootstock", icon: "/icons/rootstock.svg" }, + scroll: { name: "Scroll", icon: "/icons/scroll.svg" }, + sei: { name: "Sei Network", icon: "/icons/sei-network.svg" }, + shiden: { name: "Shiden", icon: "/icons/shiden.svg" }, + shimmer: { name: "Shimmer EVM", icon: "/icons/shimmer-evm.svg" }, + songbird: { name: "Songbird", icon: "/icons/songbird.svg" }, + stellar: { name: "Stellar", icon: "/icons/stellar.svg" }, + step: { name: "Step", icon: "/icons/step.svg" }, + sui: { name: "Sui", icon: "/icons/sui.svg" }, + syscoin: { name: "Syscoin", icon: "/icons/sys.svg" }, + telos: { name: "Telos", icon: "/icons/telos.svg" }, + tenet: { name: "Tenet", icon: "/icons/tenet.svg" }, + theta: { name: "Theta", icon: "/icons/theta.svg" }, + thundercore: { name: "ThunderCore", icon: "/icons/thundercore.svg" }, + tombchain: { name: "TombChain", icon: "/icons/tombchain.svg" }, + tron: { name: "Tron", icon: "/icons/tron.svg" }, + ubiq: { name: "Ubiq", icon: "/icons/ubiq.svg" }, + ultron: { name: "Ultron", icon: "/icons/ultron.svg" }, + velas: { name: "Velas", icon: "/icons/velas.svg" }, + viction: { name: "Viction", icon: "/icons/viction.svg" }, + wemix: { name: "WEMIX", icon: "/icons/wemix.svg" }, + xLayer: { name: "X Layer", icon: "/icons/x-layer.svg" }, + xai: { name: "Xai", icon: "/icons/xai.svg" }, + xdc: { name: "XDC", icon: "/icons/xdc.svg" }, + zetachain: { name: "ZetaChain", icon: "/icons/zeta-chain.svg" }, + zilliqa: { name: "Zilliqa", icon: "/icons/zilliqa.svg" }, + zksync: { name: "zkSync", icon: "/icons/zksync.svg" }, + zora: { name: "Zora", icon: "/icons/zora.svg" }, + zyx: { name: "ZYX", icon: "/icons/zyx.svg" }, + berat2: { name: "Berachain", icon: "/icons/berachain-icon.webp" }, + canto: { name: "Canto Network", icon: "/icons/canto-network.webp" }, + agr: { name: "Agoric", icon: "/icons/agoric.png" }, + agrt: { name: "Agoric Testnet", icon: "/icons/agoric.png" }, + celestia: { name: "Celestia", icon: "/icons/celestia.webp" }, + celestiat: { name: "Celestia Testnet", icon: "/icons/celestia.webp" }, + celestiatm: { name: "Celestia Mocha Testnet", icon: "/icons/celestia.webp" }, + arbs: { name: "Arbitrum Staging", icon: "/icons/arbitrum-icon.webp" }, + fvm: { name: "Filecoin", icon: "/icons/filecoin.webp" }, + fvmt: { name: "Filecoin", icon: "/icons/filecoin.webp" }, + hol1: { name: "Holesky", icon: "/icons/ethereum-icon.webp" }, + gth1: { name: "Goerli", icon: "/icons/ethereum-icon.webp" }, + ethbeacon: { name: "Beacon", icon: "/icons/ethereum-icon.webp" }, + apt1: { name: "Aptos", icon: "/icons/aptos-icon.webp" }, + kakarot: { name: "Kakarot", icon: "/icons/kakarot.webp" }, + kakarott: { name: "Kakarot Testnet", icon: "/icons/kakarot.webp" }, + movement: { name: "Movement", icon: "/icons/movement3.webp" }, + movementt: { name: "Movement Testnet", icon: "/icons/movement3.svg" }, +}; diff --git a/src/lib/icons/data/gateway-icons.json b/src/lib/icons/data/gateway-icons.json new file mode 100644 index 0000000..71a819e --- /dev/null +++ b/src/lib/icons/data/gateway-icons.json @@ -0,0 +1,422 @@ +[ + { + "id": "Evmos", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/evmos.webp", + "services": [ + { + "name": "Evmos Testnet (EVMOST)", + "type": "Testnet", + "onChainId": "EVMOST" + }, + { + "name": "Evmos Mainnet (EVMOS)", + "type": "Mainnet", + "onChainId": "EVMOS" + } + ] + }, + { + "id": "Canto", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/canto-network.webp", + "services": [ + { + "name": "Canto Mainnet (CANTO)", + "type": "Mainnet", + "onChainId": "CANTO" + } + ] + }, + { + "id": "Subsquid", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/subsquid2.png", + "services": [ + { + "name": "Subsquid subgraphs (SQDSUBGRAPH)", + "type": "Mainnet", + "onChainId": "SQDSUBGRAPH" + } + ] + }, + { + "id": "Avalanche", + "thumbnail": "https://gateway-fe-public-assets.s3.amazonaws.com/icons/avalanche-icon.png", + "services": [ + { + "name": "Avalanche Mainnet (AVAX)", + "type": "Mainnet", + "onChainId": "AVAX" + } + ] + }, + { + "id": "Starknet", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/starknet-icon.png", + "services": [ + { + "name": "Starknet (STRK)", + "type": "Mainnet", + "onChainId": "STRK" + }, + { + "name": "Starknet Sepolia Testnet (STRKS)", + "type": "Testnet", + "onChainId": "STRKS" + } + ] + }, + { + "id": "Aptos", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/aptos-icon.png", + "services": [ + { + "name": "Aptos Mainnet (APT1)", + "type": "Mainnet", + "onChainId": "APT1" + } + ] + }, + { + "id": "Near", + "thumbnail": "https://gateway-fe-public-assets.s3.amazonaws.com/icons/near-icon.png", + "services": [ + { + "name": "Near Testnet (NEART)", + "type": "Testnet", + "onChainId": "NEART" + }, + { + "name": "Near Mainnet (NEAR)", + "type": "Mainnet", + "onChainId": "NEAR" + } + ] + }, + { + "id": "Movement", + "thumbnail": "https://gateway-fe-public-assets.s3.amazonaws.com/icons/movement.png", + "services": [ + { + "name": "Movement Mainnet (MOVEMENT)", + "type": "Mainnet", + "onChainId": "MOVEMENT" + } + ] + }, + { + "id": "Stargaze", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/stargaze.png", + "services": [ + { + "name": "Stargaze mainnet (STRGZ)", + "type": "Mainnet", + "onChainId": "STRGZ" + }, + { + "name": "Stargaze testnet (STRGZT)", + "type": "Testnet", + "onChainId": "STRGZT" + } + ] + }, + { + "id": "Juno", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/juno-icon.png", + "services": [ + { + "name": "Juno (JUN1)", + "type": "Mainnet", + "onChainId": "JUN1" + }, + { + "name": "Juno Testnet (JUNT1)", + "type": "Testnet", + "onChainId": "JUNT1" + } + ] + }, + { + "id": "Osmosis", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/osmosis-icon.png", + "services": [ + { + "name": "Osmosis Testnet (OSMOSIST)", + "type": "Testnet", + "onChainId": "OSMOSIST" + }, + { + "name": "Osmosis (OSMOSIS)", + "type": "Mainnet", + "onChainId": "OSMOSIS" + } + ] + }, + { + "id": "Cosmos Hub", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/atom-icon.png", + "services": [ + { + "name": "Cosmos Hub (COSMOSHUB)", + "type": "Mainnet", + "onChainId": "COSMOSHUB" + }, + { + "name": "Cosmos Hub Testnet (COSMOSHUBT)", + "type": "Testnet", + "onChainId": "COSMOSHUBT" + } + ] + }, + { + "id": "Celestia", + "thumbnail": "https://gateway-fe-public-assets.s3.amazonaws.com/icons/celestia.png", + "services": [ + { + "name": "Celestia mainnet (CELESTIA)", + "type": "Mainnet", + "onChainId": "CELESTIA" + }, + { + "name": "Celestia mocha testnet (CELESTIAT)", + "type": "Testnet", + "onChainId": "CELESTIAT" + } + ] + }, + { + "id": "Axelar", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/axelar-icon.png", + "services": [ + { + "name": "Axelar Testnet (AXELART)", + "type": "Testnet", + "onChainId": "AXELART" + }, + { + "name": "Axelar Mainnet (AXELAR)", + "type": "Mainnet", + "onChainId": "AXELAR" + } + ] + }, + { + "id": "Agoric", + "thumbnail": "https://gateway-fe-public-assets.s3.amazonaws.com/icons/agoric.png", + "services": [ + { + "name": "Agoric Mainnet (AGR)", + "type": "Mainnet", + "onChainId": "AGR" + }, + { + "name": "Agoric Testnet (AGRT)", + "type": "Testnet", + "onChainId": "AGRT" + } + ] + }, + { + "id": "Lava", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/lava-icon.png", + "services": [ + { + "name": "Lava (LAV1)", + "type": "Mainnet", + "onChainId": "LAV1" + } + ] + }, + { + "id": "Koii", + "thumbnail": "https://gateway-fe-public-assets.s3.amazonaws.com/icons/koii-icon.png", + "services": [ + { + "name": "Koii Testnet (KOIIT)", + "type": "Testnet", + "onChainId": "KOIIT" + } + ] + }, + { + "id": "Solana", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/solana-icon.png", + "services": [ + { + "name": "Solana Mainnet (SOLANA)", + "type": "Mainnet", + "onChainId": "SOLANA" + }, + { + "name": "Solana Testnet (SOLANAT)", + "type": "Testnet", + "onChainId": "SOLANAT" + } + ] + }, + { + "id": "Base", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/base-icon.png", + "services": [ + { + "name": "Base Testnet (BASET)", + "type": "Testnet", + "onChainId": "BASET" + }, + { + "name": "Base Mainnet (BASE)", + "type": "Mainnet", + "onChainId": "BASE" + } + ] + }, + { + "id": "Fuse", + "thumbnail": "https://gateway-fe-public-assets.s3.us-east-1.amazonaws.com/icons/fuse_round.png", + "services": [ + { + "name": "Fuse Mainnet", + "type": "Mainnet", + "onChainId": "FUSE" + } + ] + }, + { + "id": "Ethereum", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/ethereum-icon.png", + "services": [ + { + "name": "Ethereum (ETH1)", + "type": "Mainnet", + "onChainId": "ETH1" + }, + { + "name": "Sepolia (SEP1)", + "type": "Testnet", + "onChainId": "SEP1" + }, + { + "name": "Holesky (HOL1)", + "type": "Testnet", + "onChainId": "HOL1" + }, + { + "name": "Beacon (ETHBEACON)", + "type": "Testnet", + "onChainId": "ETHBEACON" + } + ] + }, + { + "id": "Fantom", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/fantom-icon.png", + "services": [ + { + "name": "Fantom (FTM250)", + "type": "Mainnet", + "onChainId": "FTM250" + } + ] + }, + { + "id": "Polygon", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/polygon-icon.png", + "services": [ + { + "name": "Polygon (POLYGON1)", + "type": "Mainnet", + "onChainId": "POLYGON1" + } + ] + }, + { + "id": "Filecoin", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/filecoin.png", + "services": [ + { + "name": "Filecoin Mainnet (FVM)", + "type": "Mainnet", + "onChainId": "FVM" + } + ] + }, + { + "id": "Celo", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/celo-icon.png", + "services": [ + { + "name": "Celo (CELO)", + "type": "Mainnet", + "onChainId": "CELO" + }, + { + "name": "Celo - Alfajores (ALFAJORES)", + "type": "Testnet", + "onChainId": "ALFAJORES" + } + ] + }, + { + "id": "Arbitrum", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/arbitrum-icon.png", + "services": [ + { + "name": "Arbitrum (ARB1)", + "type": "Mainnet", + "onChainId": "ARB1" + }, + { + "name": "Arbitrum-Nova (ARBN)", + "type": "Mainnet", + "onChainId": "ARBN" + }, + { + "name": "Arbitrum Sepolia Testnet (ARBS)", + "type": "Testnet", + "onChainId": "ARBS" + } + ] + }, + { + "id": "Optimism", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/optimism.webp", + "services": [ + { + "name": "Optimism Mainnet (OPTM)", + "type": "Mainnet", + "onChainId": "OPTM" + } + ] + }, + { + "id": "Blast", + "thumbnail": "https://gateway-fe-public-staging-assets.s3.amazonaws.com/icons/blast.png", + "services": [ + { + "name": "Blast mainnet (BLAST)", + "type": "Mainnet", + "onChainId": "BLAST" + } + ] + }, + { + "id": "Kakarot", + "thumbnail": "https://gateway-fe-public-assets.s3.amazonaws.com/icons/kakarot.png", + "services": [ + { + "name": "Kakarot Sepolia Testnet (KAKAROTT)", + "type": "Testnet", + "onChainId": "KAKAROTT" + } + ] + }, + { + "id": "Berachain", + "thumbnail": "https://gateway-fe-public-assets.s3.amazonaws.com/icons/berachain-icon.png", + "services": [ + { + "name": "Berachain bArtio (BERAT2)", + "type": "Testnet", + "onChainId": "BERAT2" + } + ] + } +] \ No newline at end of file diff --git a/src/lib/icons/icons.ts b/src/lib/icons/icons.ts new file mode 100644 index 0000000..8fa90fe --- /dev/null +++ b/src/lib/icons/icons.ts @@ -0,0 +1,49 @@ +import icons from './data/gateway-icons.json'; +import { chainDictionary } from './data/chain-icons'; + +interface IconService { + name: string; + type: string; + onChainId: string; +} + +interface IconData { + id: string; + thumbnail: string; + services: IconService[]; +} + +const iconMap = new Map(); + +// Initialize the map with both ID and onChainId mappings +(icons as IconData[]).forEach(icon => { + iconMap.set(icon.id.toLowerCase(), icon.thumbnail); + icon.services.forEach(service => { + iconMap.set(service.onChainId.toLowerCase(), icon.thumbnail); + }); +}); + +/** + * Gets the icon URL for a given spec ID + * @param spec The spec identifier (e.g. "EVMOS", "CANTO") + * @returns The icon URL if found, undefined otherwise + */ +export function GetIconForSpec(spec: string | null): string | undefined { + if (!spec) return undefined; + + const specLower = spec.toLowerCase(); + + // First try the main icon map + const mainIcon = iconMap.get(specLower); + if (mainIcon) return mainIcon; + + // If not found, try chain-icons + const chainIcon = chainDictionary[specLower]; + if (chainIcon) { + return `https://info.lavanet.xyz/${chainIcon.icon}.svg`; + } + + return undefined; +} + +export default GetIconForSpec; \ No newline at end of file diff --git a/src/query/handlers/ajax/allProviderAprHandler.ts b/src/query/handlers/ajax/allProviderAprHandler.ts index 1b759af..0519ecb 100644 --- a/src/query/handlers/ajax/allProviderAprHandler.ts +++ b/src/query/handlers/ajax/allProviderAprHandler.ts @@ -1,125 +1 @@ -import { FastifyRequest, FastifyReply, RouteShorthandOptions } from 'fastify'; -import { AllProviderAPRResource, AllAprProviderData } from '@jsinfo/redis/resources/ajax/AllProviderAprResource'; -import { ListProvidersResource, ProviderEntry } from '@jsinfo/redis/resources/ajax/ListProvidersResource'; -import { JSONStringify } from '@jsinfo/utils/fmt'; -import { logger } from '@jsinfo/utils/logger'; - -interface RewardToken { - denom: string; - amount: string; -} - -interface ProviderAPRData extends Omit { - '30_days_cu_served': string; - rewards: RewardToken[]; - '30_days_relays_served': string; - specs?: ProviderEntry['specs']; - stake?: string; - stakestatus?: string; - addons?: string; - extensions?: string; - delegateTotal?: string; -} - -export const AllProviderAPRRawHandlerOpts: RouteShorthandOptions = { - schema: { - response: { - 200: { - type: 'array', - items: { - type: 'object', - properties: { - address: { type: 'string' }, - moniker: { type: 'string' }, - apr: { type: 'string' }, - commission: { type: 'string' }, - '30_days_cu_served': { type: 'string' }, - rewards: { - type: 'array', - items: { - type: 'object', - properties: { - denom: { type: 'string' }, - amount: { type: 'string' } - } - } - }, - stake: { type: 'string' }, - stakestatus: { type: 'string' }, - addons: { type: 'string' }, - extensions: { type: 'string' }, - delegateTotal: { type: 'string' }, - '30_days_relays_served': { type: 'string' }, - specs: { - type: 'array', - items: { - type: 'object', - properties: { - spec: { type: 'string' }, - chain: { type: 'string' }, - stakestatus: { type: 'string' }, - stake: { type: 'string' }, - addons: { type: 'string' }, - extensions: { type: 'string' }, - delegateCommission: { type: 'string' }, - delegateTotal: { type: 'string' } - } - } - } - } - } - }, - 400: { - type: 'object', - properties: { - error: { type: 'string' } - } - } - } - } -}; - -export async function AllProviderAPRRawHandler(request: FastifyRequest, reply: FastifyReply) { - try { - const [aprResource, providersResource] = await Promise.all([ - new AllProviderAPRResource().fetch(), - new ListProvidersResource().fetch() - ]); - - if (!aprResource || !providersResource) { - return reply.status(400).send({ error: 'Failed to fetch provider data' }); - } - - // Create a map of providers for quick lookup - const providersMap = new Map( - providersResource.providers.map(p => [p.provider, p]) - ); - - // Combine the data - const combinedData = aprResource.map(apr => { - const provider = providersMap.get(apr.address); - const result: ProviderAPRData = { - ...apr, - '30_days_cu_served': apr['30_days_cu_served'] || '', - rewards: Object.values(apr.rewards).map(reward => ({ - denom: reward.denom, - amount: reward.amount - })), - '30_days_relays_served': apr['30_days_relays_served'] || '', - specs: provider?.specs || [], - stake: provider?.specs?.[0]?.stake || '', - stakestatus: provider?.specs?.[0]?.stakestatus || '', - addons: provider?.specs?.[0]?.addons || '', - extensions: provider?.specs?.[0]?.extensions || '', - delegateTotal: provider?.specs?.[0]?.delegateTotal || '' - }; - return result; - }); - - reply.header('Content-Type', 'application/json'); - return reply.send(JSONStringify(combinedData)); - } catch (error) { - logger.error('Error in AllProviderAPRRawHandler:', error); - return reply.status(500).send({ error: 'Internal server error' }); - } -} \ No newline at end of file + \ No newline at end of file diff --git a/src/query/handlers/ajax/providerPerfomanceHandler.ts b/src/query/handlers/ajax/providerPerfomanceHandler.ts new file mode 100644 index 0000000..f9f5c7e --- /dev/null +++ b/src/query/handlers/ajax/providerPerfomanceHandler.ts @@ -0,0 +1,216 @@ +import { FastifyRequest, FastifyReply, RouteShorthandOptions } from 'fastify'; +import { AllProviderAPRResource, AllAprProviderData } from '@jsinfo/redis/resources/ajax/AllProviderAprResource'; +import { ListProvidersResource, ProviderEntry } from '@jsinfo/redis/resources/ajax/ListProvidersResource'; +import { MainnetProviderEstimatedRewardsGetService } from '@jsinfo/redis/resources/MainnetProviderEstimatedRewards/MainnetProviderEstimatedRewardsGetResource'; +import { JSONStringify } from '@jsinfo/utils/fmt'; +import { logger } from '@jsinfo/utils/logger'; +import GetIconForSpec from '@jsinfo/lib/icons/icons'; +import { ConvertToChainName } from '@jsinfo/lib/chain-mapping/chains'; + +interface RewardToken { + denom: string; + amount: string; +} + +interface ProviderPerformanceData extends Omit { + '30_days_cu_served': string; + rewards_10k_lava_delegation: RewardToken[]; + '30_days_relays_served': string; + specs?: Array; + stake?: string; + stakestatus?: string; + addons?: string; + extensions?: string; + delegateTotal?: string; + rewards_last_month: Array<{ + chain: string; + spec: string; + tokens: Array<{ + amount: string; + denom: string; + original_denom: string; + value_usd: string; + }>; + total_usd: number; + icon?: string; + }>; +} + +export const ProviderPerformanceHandlerOpts: RouteShorthandOptions = { + schema: { + response: { + 200: { + type: 'array', + items: { + type: 'object', + properties: { + address: { type: 'string' }, + moniker: { type: 'string' }, + apr: { type: 'string' }, + commission: { type: 'string' }, + '30_days_cu_served': { type: 'string' }, + rewards_10k_lava_delegation: { + type: 'array', + items: { + type: 'object', + properties: { + denom: { type: 'string' }, + amount: { type: 'string' } + } + } + }, + rewards_last_month: { + type: 'array', + items: { + type: 'object', + properties: { + chain: { type: 'string' }, + spec: { type: 'string' }, + tokens: { + type: 'array', + items: { + type: 'object', + properties: { + amount: { type: 'string' }, + denom: { type: 'string' }, + original_denom: { type: 'string' }, + value_usd: { type: 'string' } + } + } + }, + total_usd: { type: 'number' }, + icon: { type: 'string' } + } + } + }, + '30_days_relays_served': { type: 'string' }, + specs: { + type: 'array', + items: { + type: 'object', + properties: { + chain: { type: 'string' }, + spec: { type: 'string' }, + stakestatus: { type: 'string' }, + stake: { type: 'string' }, + addons: { type: 'string' }, + extensions: { type: 'string' }, + delegateCommission: { type: 'string' }, + delegateTotal: { type: 'string' }, + moniker: { type: 'string' }, + icon: { type: 'string' } + } + } + }, + stake: { type: 'string' }, + stakestatus: { type: 'string' }, + addons: { type: 'string' }, + extensions: { type: 'string' }, + delegateTotal: { type: 'string' } + } + } + }, + 400: { + type: 'object', + properties: { + error: { type: 'string' } + } + } + } + } +}; + +function processRewardsBySpec(rewardsByBlock: any): Array<{ chain: string; spec: string; tokens: any[]; total_usd: number; icon?: string }> { + if (!rewardsByBlock) return []; + + const specRewards = new Map(); + const block = Object.keys(rewardsByBlock)[0]; + const info = rewardsByBlock[block]?.info || []; + + info.forEach((reward: any) => { + const [type, spec] = reward.source.toLowerCase().split(': '); + if (!spec) return; + + const key = spec; + const existing = specRewards.get(key) || { tokens: [], total_usd: 0 }; + + // Sum up the tokens + reward.amount.tokens.forEach((token: any) => { + const existingToken = existing.tokens.find(t => t.denom === token.denom); + if (existingToken) { + existingToken.amount = (parseFloat(existingToken.amount) + parseFloat(token.amount)).toString(); + existingToken.value_usd = `$${(parseFloat(existingToken.value_usd.slice(1)) + parseFloat(token.value_usd.slice(1))).toFixed(2)}`; + } else { + existing.tokens.push({ ...token }); + } + }); + + existing.total_usd += reward.amount.total_usd; + specRewards.set(key, existing); + }); + + return Array.from(specRewards.entries()).map(([spec, data]) => ({ + chain: ConvertToChainName(spec), + spec: spec.toUpperCase(), + tokens: data.tokens, + total_usd: data.total_usd, + icon: GetIconForSpec(spec) + })); +} + +export async function ProviderPerformanceRawHandler(request: FastifyRequest, reply: FastifyReply) { + try { + const [aprResource, providersResource, rewardsLastMonth] = await Promise.all([ + new AllProviderAPRResource().fetch(), + new ListProvidersResource().fetch(), + MainnetProviderEstimatedRewardsGetService.fetch({ block: 2044223 }) + ]); + + if (!aprResource || !providersResource) { + return reply.status(400).send({ error: 'Failed to fetch provider data' }); + } + + // Create a map of providers for quick lookup + const providersMap = new Map( + providersResource.providers.map(p => [p.provider, p]) + ); + + // Create a map of rewards for quick lookup + const rewardsMap = new Map( + (rewardsLastMonth?.data?.providers || []).map(p => [p.address, p.rewards_by_block]) + ); + + // Combine the data + const combinedData = aprResource.map(apr => { + const provider = providersMap.get(apr.address); + const rewards_last_month = processRewardsBySpec(rewardsMap.get(apr.address)); + + const result: ProviderPerformanceData = { + ...apr, + '30_days_cu_served': apr['30_days_cu_served'] || '', + rewards_10k_lava_delegation: Object.values(apr.rewards).map(reward => ({ + denom: reward.denom, + amount: reward.amount + })), + rewards_last_month, + '30_days_relays_served': apr['30_days_relays_served'] || '', + specs: provider?.specs || [], + stake: provider?.specs?.[0]?.stake || '', + stakestatus: provider?.specs?.[0]?.stakestatus || '', + addons: provider?.specs?.[0]?.addons || '', + extensions: provider?.specs?.[0]?.extensions || '', + delegateTotal: provider?.specs?.[0]?.delegateTotal || '' + }; + + delete (result as any).rewards; + + return result; + }); + + reply.header('Content-Type', 'application/json'); + return reply.send(JSONStringify(combinedData)); + } catch (error) { + logger.error('Error in ProviderPerformanceRawHandler:', error); + return reply.status(500).send({ error: 'Internal server error' }); + } +} \ No newline at end of file diff --git a/src/query/queryRoutes.ts b/src/query/queryRoutes.ts index f3a1624..10a415f 100644 --- a/src/query/queryRoutes.ts +++ b/src/query/queryRoutes.ts @@ -15,7 +15,7 @@ import { SupplyHistoryHandlerOpts, supplyHistoryHandler } from './handlers/ajax/ // -- Server apr ajax -- import { APRRawHandlerOpts, APRRawHandler } from './handlers/ajax/aprHandler'; import { APRFullHandler, APRFullHandlerOpts } from './handlers/ajax/aprFullHandler'; -import { AllProviderAPRRawHandlerOpts, AllProviderAPRRawHandler } from './handlers/ajax/allProviderAprHandler'; +import { ProviderPerformanceHandlerOpts, ProviderPerformanceRawHandler } from './handlers/ajax/providerPerfomanceHandler'; // -- list all providers and monikers endpoint --- import { ListProvidersRawHandlerOpts, ListProvidersRawHandler } from './handlers/ajax/listProvidersHandler'; @@ -131,7 +131,10 @@ GetServerInstance().get('/lava_chain_restakers', ChainWalletApiHandlerOpts, Lava // -- Server APR ajax -- GetServerInstance().get('/apr', APRRawHandlerOpts, APRRawHandler); GetServerInstance().get('/apr_full', APRFullHandlerOpts, APRFullHandler); -GetServerInstance().get('/all_providers_apr', AllProviderAPRRawHandlerOpts, AllProviderAPRRawHandler); + +// -- providers_performance -- +GetServerInstance().get('/providers_performance', ProviderPerformanceHandlerOpts, ProviderPerformanceRawHandler); +GetServerInstance().get('/all_providers_apr', ProviderPerformanceHandlerOpts, ProviderPerformanceRawHandler); // -- list all providers and monikers endpoint --- GetServerInstance().get('/listProviders', ListProvidersRawHandlerOpts, ListProvidersRawHandler); diff --git a/src/redis/resources/ajax/AllProviderAprResource.ts b/src/redis/resources/ajax/AllProviderAprResource.ts index 9f43d38..70c6365 100644 --- a/src/redis/resources/ajax/AllProviderAprResource.ts +++ b/src/redis/resources/ajax/AllProviderAprResource.ts @@ -7,7 +7,6 @@ import * as JsinfoProviderAgrSchema from '@jsinfo/schemas/jsinfoSchema/providerR import { EstimatedRewardsResponse } from '@jsinfo/restRpc/lavaRpcOnDemandEndpointCache'; import { IsMeaningfulText } from '@jsinfo/utils/fmt'; import { ConvertToBaseDenom } from '@jsinfo/restRpc/CurrencyConverstionUtils'; -import * as JsinfoSchema from '@jsinfo/schemas/jsinfoSchema/jsinfoSchema'; export interface AllAprProviderData { address: string; diff --git a/src/redis/resources/ajax/ListProvidersResource.ts b/src/redis/resources/ajax/ListProvidersResource.ts index f282bcf..ad566f0 100644 --- a/src/redis/resources/ajax/ListProvidersResource.ts +++ b/src/redis/resources/ajax/ListProvidersResource.ts @@ -3,7 +3,8 @@ import * as JsinfoSchema from '@jsinfo/schemas/jsinfoSchema/jsinfoSchema'; import { ProviderMonikerService } from '@jsinfo/redis/resources/global/ProviderMonikerSpecResource'; import { desc, inArray } from 'drizzle-orm'; import { queryJsinfo } from '@jsinfo/utils/db'; - +import getIconForSpec from '@jsinfo/lib/icons/icons'; +import { ConvertToChainName } from '@jsinfo/lib/chain-mapping/chains'; export interface ProviderEntry { provider: string; specs: { @@ -16,6 +17,7 @@ export interface ProviderEntry { delegateCommission: string | null; delegateTotal: string | null; moniker: string; + icon?: string; }[]; } @@ -25,105 +27,6 @@ export interface ProvidersData { providers: ProviderEntry[]; } -const chainMapping: Record = { - FUSE: "fuse mainnet", - STRK: "starknet mainnet", - STRKS: "starknet sepolia testnet", - LAVA: "lava mainnet", - AVAX: "avalanche mainnet", - AVAXT: "avalanche testnet", - OSMOSIS: "osmosis mainnet", - OSMOSIST: "osmosis testnet", - NEAR: "near mainnet", - NEART: "near testnet", - SUIT: "sui devnet", - FUELNETWORK: "fuel network graphql", - COSMOSSDK45DEP: "cosmos sdk deprecated apis", - SOLANA: "solana main net", - SOLANAT: "solana test net", - SCROLL: "scroll mainnet", - SCROLLS: "scroll sepolia testnet", - EVMOS: "evmos mainnet", - EVMOST: "evmos testnet", - TENDERMINT: "tendermint", - CANTO: "canto mainnet", - COSMOSHUB: "cosmos hub mainnet", - COSMOSHUBT: "cosmos hub testnet", - COSMOSWASM: "cosmos wasm", - FVM: "fvm mainnet", - FTM250: "fantom mainnet", - FTM4002: "fantom testnet", - SQDSUBGRAPH: "subsquid powered subgraph", - BERAT: "berachain testnet", - MOVEMENT: "movement mainnet", - MANTAPACIFIC: "manta pacific mainnet", - MANTAPACIFICT: "manta pacific testnet", - ETH1: "ethereum mainnet", - SEP1: "ethereum testnet sepolia", - HOL1: "ethereum testnet holesky", - JUN1: "juno mainnet", - JUNT1: "juno testnet", - BSC: "bsc mainnet", - BSCT: "bsc testnet", - COSMOSSDKFULL: "full cosmos sdk", - IBC: "ibc", - SIDET: "side testnet", - MORALIS: "moralis advanced api", - CELESTIA: "celestia mainnet", - CELESTIATM: "celestia mocha testnet", - CELESTIATA: "celestia arabica testnet", - KOII: "koii main net", - KOIIT: "koii test net", - MANTLE: "mantle testnet", - LAV1: "lava testnet", - AXELAR: "axelar mainnet", - AXELART: "axelar testnet", - AGR: "agoric mainnet", - AGRT: "agoric testnet", - ETHBEACON: "ethereum beacon mainnet", - BASE: "base mainnet", - BASES: "base sepolia testnet", - BASET: "base sepolia testnet", - ZKSYNC: "zksync era mainnet", - ZKSYNCSP: "zksync era sepolia testnet", - ETHERMINT: "ethermint", - SECRET: "secret mainnet", - SECRETP: "secret testnet", - APT1: "aptos mainnet", - OPTM: "optimism mainnet", - OPTMS: "optimism sepolia testnet", - ARB1: "arbitrum mainnet", - ARBN: "arbitrum nova testnet", - ARBS: "arbitrum sepolia testnet", - KAKAROTT: "kakarot sepolia testnet", - BLAST: "blast mainnet", - BLASTSP: "blast sepolia testnet", - CELO: "celo mainnet", - ALFAJORES: "celo alfajores testnet", - UNIONT: "union testnet", - STRGZ: "stargaze mainnet", - STRGZT: "stargaze testnet", - NAMTSE: "namada se testnet", - COSMOSSDK: "cosmos sdk", - POLYGON1: "polygon mainnet", - POLYGON1A: "polygon amoy testnet", - COS3: "osmosis mainnet", - COS4: "osmosis testnet", - COS5: "cosmos hub mainnet", - COS5T: "cosmos hub testnet", - COSHUB: "cosmos hub mainnet", - COSHUBT: "cosmos hub testnet", - GTH1: "ethereum testnet goerli", - OPTMT: "optimism goerli testnet", - OSMO: "osmosis mainnet", - OSMOT: "osmosis testnet", - POLYGON1T: "polygon testnet", - STRKT: "starknet testnet", - SUI: "sui devnet", - FUSET: "fuse testnet", - UNION: "union mainnet", -}; - const LavaProviderStakeStatusDict: { [key: number]: string } = { [JsinfoSchema.LavaProviderStakeStatus.Active]: "Active", [JsinfoSchema.LavaProviderStakeStatus.Frozen]: "Frozen", @@ -131,6 +34,7 @@ const LavaProviderStakeStatusDict: { [key: number]: string } = { [JsinfoSchema.LavaProviderStakeStatus.Inactive]: "Inactive", [JsinfoSchema.LavaProviderStakeStatus.Jailed]: "Jailed", }; + export class ListProvidersResource extends RedisResourceBase { protected redisKey = 'listProviders'; protected cacheExpirySeconds = 300; // 5 minutes cache @@ -160,8 +64,8 @@ export class ListProvidersResource extends RedisResourceBase // Then use them in reduce const providers = stakesRes.reduce((acc, stake, index) => { const providerEntry = acc.find(entry => entry.provider === stake.provider); - const specEntry = { - chain: stake.specId ? chainMapping[stake.specId] || "" : "", + const specEntry: ProviderEntry['specs'][0] = { + chain: stake.specId ? ConvertToChainName(stake.specId) || "" : "", spec: stake.specId || '', stakestatus: stake.status ? LavaProviderStakeStatusDict[stake.status] || "" : "", stake: stake.stake?.toString() ?? '', @@ -169,8 +73,15 @@ export class ListProvidersResource extends RedisResourceBase extensions: stake.extensions || '', delegateCommission: stake.delegateCommission?.toString() ?? '', delegateTotal: stake.delegateTotal?.toString() ?? '', - moniker: monikers[index], + moniker: monikers[index] }; + + // Get the icon + const icon = getIconForSpec(stake.specId); + if (icon) { + specEntry.icon = icon; + } + if (providerEntry) { providerEntry.specs.push(specEntry); } else {