From 36194c981250080d3908f2ad2fc446d0e59c5f46 Mon Sep 17 00:00:00 2001 From: gabaldon Date: Tue, 28 Jan 2025 12:37:15 +0100 Subject: [PATCH] feat: filter by witnet network and pair --- packages/api/src/index.ts | 1 + packages/api/src/repository/Feed.ts | 118 ++++++++++++++++--- packages/api/src/repository/ResultRequest.ts | 19 +++ packages/api/src/repository/feedState.ts | 10 ++ packages/api/src/resolvers.ts | 6 +- packages/api/src/typeDefs.ts | 2 +- packages/api/types.ts | 10 ++ packages/ui/api/index.ts | 12 +- packages/ui/api/queries/feeds.ts | 4 +- packages/ui/components/DataFeeds.vue | 4 +- packages/ui/stores/index.ts | 12 +- 11 files changed, 173 insertions(+), 25 deletions(-) diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts index 146d4875..246b5894 100644 --- a/packages/api/src/index.ts +++ b/packages/api/src/index.ts @@ -82,6 +82,7 @@ class DataFeedsExplorer { } this.repositories.feedRepository.setLegacyFeeds(legacyFeeds) this.repositories.feedRepository.setV2Feeds(v2Feeds) + this.repositories.feedRepository.setConfiguration(this.configuration) const web3Middleware = new Web3Middleware( this.configuration, diff --git a/packages/api/src/repository/Feed.ts b/packages/api/src/repository/Feed.ts index d0d284f0..5c546d9a 100644 --- a/packages/api/src/repository/Feed.ts +++ b/packages/api/src/repository/Feed.ts @@ -1,9 +1,16 @@ import { FeedsState } from './feedState' -import { PaginatedFeedsObject, FeedInfo, ConfigByFullName } from '../../types' +import { + PaginatedFeedsObject, + FeedInfo, + ConfigByFullName, + Network, + FeedsFilters, +} from '../../types' +import { Configuration } from '../web3Middleware/Configuration' export class FeedRepository { feedsState: FeedsState - // TODO: replace string with Network + dataFeeds: Record>> dataFeedsByNetwork: Record> configByFullName: ConfigByFullName @@ -15,15 +22,43 @@ export class FeedRepository { initialize() { const feeds = this.feedsState.listFeeds() + this.dataFeeds = feeds.reduce( + ( + acc: Record>>, + feedInfo: FeedInfo, + ) => { + let value + const isPairKeyPresent: boolean = !!acc[feedInfo.name] + const isNetworkAndPairKeyPresent: boolean = + isPairKeyPresent && !!acc[feedInfo.name][feedInfo.network] + if (isNetworkAndPairKeyPresent) { + value = [...acc[feedInfo.name][feedInfo.network], feedInfo] + } else { + value = [feedInfo] + } + return { + ...acc, + [feedInfo.name]: { + ...acc[feedInfo.name], + [feedInfo.network]: value, + }, + } + }, + {}, + ) + this.dataFeedsByNetwork = feeds.reduce( - (acc: Record>, feedInfo: FeedInfo) => ({ - ...acc, - [feedInfo.network]: acc[feedInfo.network] - ? [...acc[feedInfo.network], feedInfo] - : [feedInfo], - }), + (acc: Record>, feedInfo: FeedInfo) => { + return { + ...acc, + [feedInfo.network]: acc[feedInfo.network] + ? [...acc[feedInfo.network], feedInfo] + : [feedInfo], + } + }, {}, ) + this.configByFullName = feeds.reduce( (acc, feedInfo) => ({ ...acc, @@ -43,19 +78,63 @@ export class FeedRepository { .find((feed) => feed.feedFullName === feedFullName) } - async getFeedsByNetwork( - // starts in 1 - network: string, - ): Promise { - let feeds: Array + async getFilteredFeeds({ + network, + pair, + mainnet, + }: FeedsFilters): Promise { + let feeds: Array = [] if (network === 'all') { - feeds = Object.values(this.dataFeedsByNetwork).flat() + feeds = this.feedsState.listFeeds() + } else { + if (network && pair) { + feeds = this.dataFeeds[pair][network] + } else if (network) { + feeds = this.dataFeedsByNetwork[network] + } else if (pair) { + feeds = Object.values(this.dataFeeds[pair]).flat() + } + } + return this.getPaginatedFeedsByEnv(feeds, mainnet) + } + + getPaginatedFeedsByEnv(feeds: FeedInfo[], mainnet: boolean | null) { + if (mainnet === null) { + return { + feeds: feeds || [], + total: feeds ? feeds.length : 0, + } + } + if (mainnet) { + return this.getMainnetFeeds(feeds) } else { - feeds = this.dataFeedsByNetwork[network] + return this.getTestnetFeeds(feeds) } + } + + getConfigurationFromNetwork(network: Network) { + return this.feedsState.getConfiguration().getNetworkConfiguration(network) + } + + getTestnetFeeds(feeds: Array): PaginatedFeedsObject { + const filteredFeeds: FeedInfo[] = + feeds?.filter( + (feed) => !this.getConfigurationFromNetwork(feed.network).mainnet, + ) ?? [] return { - feeds: feeds || [], - total: feeds ? feeds.length : 0, + feeds: filteredFeeds, + total: filteredFeeds.length, + } + } + + getMainnetFeeds(feeds: Array): PaginatedFeedsObject { + const filteredFeeds: FeedInfo[] = + feeds?.filter( + (feed) => this.getConfigurationFromNetwork(feed.network).mainnet, + ) ?? [] + return { + feeds: filteredFeeds, + total: filteredFeeds.length, } } @@ -98,4 +177,9 @@ export class FeedRepository { this.feedsState.setV2Feeds(v2Feeds) this.initialize() } + + setConfiguration(configuration: Configuration) { + this.feedsState.setConfiguration(configuration) + this.initialize() + } } diff --git a/packages/api/src/repository/ResultRequest.ts b/packages/api/src/repository/ResultRequest.ts index 15fadf04..2d88db8f 100644 --- a/packages/api/src/repository/ResultRequest.ts +++ b/packages/api/src/repository/ResultRequest.ts @@ -48,6 +48,25 @@ export class ResultRequestRepository { .map(this.normalizeId) } + async getFeedRequestsPageByPair( + pair: string, + page: number, + size: number, + ): Promise { + const query = { feedFullName: { $regex: pair } } + return { + requests: ( + await this.collection + .find(query) + .sort({ timestamp: -1 }) + .skip(size * (page - 1)) + .limit(size) + .toArray() + ).map(this.normalizeId), + total: (await this.collection.find(query).toArray()).length, + } + } + async getFeedRequestsPage( feedFullName: string, page: number, diff --git a/packages/api/src/repository/feedState.ts b/packages/api/src/repository/feedState.ts index af3ec8eb..2cf50b97 100644 --- a/packages/api/src/repository/feedState.ts +++ b/packages/api/src/repository/feedState.ts @@ -1,8 +1,10 @@ import { FeedInfo } from '../../types' +import { Configuration } from '../web3Middleware/Configuration' export class FeedsState { private legacyFeeds: Array private v2Feeds: Array + private configuration: Configuration constructor() { this.legacyFeeds = [] @@ -17,10 +19,18 @@ export class FeedsState { this.legacyFeeds = legacyFeeds } + setConfiguration(configuration: Configuration) { + this.configuration = configuration + } + getV2Feeds(): Array { return this.v2Feeds } + getConfiguration(): Configuration { + return this.configuration + } + getLegacyFeeds(): Array { return this.legacyFeeds } diff --git a/packages/api/src/resolvers.ts b/packages/api/src/resolvers.ts index 777cd805..26483884 100644 --- a/packages/api/src/resolvers.ts +++ b/packages/api/src/resolvers.ts @@ -3,7 +3,11 @@ import { Context } from '../types' const resolvers = { Query: { feeds: async (_parent, args, { feedRepository }: Context) => { - return await feedRepository.getFeedsByNetwork(args.network) + return await feedRepository.getFilteredFeeds({ + network: args.network, + pair: args.pair, + mainnet: args.mainnet, + }) }, networks: (_parent, _args, { config }: Context) => { diff --git a/packages/api/src/typeDefs.ts b/packages/api/src/typeDefs.ts index 7de93235..687363bc 100644 --- a/packages/api/src/typeDefs.ts +++ b/packages/api/src/typeDefs.ts @@ -63,7 +63,7 @@ const typeDefs = gql` type Query { feed(feedFullName: String!): Feed - feeds(network: String): FeedsPage! + feeds(network: String, mainnet: Boolean, pair: String): FeedsPage! requests( feedFullName: String! page: Int! diff --git a/packages/api/types.ts b/packages/api/types.ts index 2fc6c998..4e56a879 100644 --- a/packages/api/types.ts +++ b/packages/api/types.ts @@ -40,6 +40,10 @@ export type ConfigByFullName = { [key: string]: FeedInfo } +export type NetworkConfigByNetwork = { + [key: string]: Configuration +} + export enum Network { ArbitrumOne = 'arbitrum-one', ArbitrumGoerli = 'arbitrum-goerli', @@ -259,6 +263,12 @@ export type LegacyRouterDataFeedsConfig = { chains: Record } +export type FeedsFilters = { + network: string | null + pair: string | null + mainnet: boolean +} + export type FeedInfosWithoutAbis = Array< Omit > diff --git a/packages/ui/api/index.ts b/packages/ui/api/index.ts index 1d987b5f..555de3ab 100644 --- a/packages/ui/api/index.ts +++ b/packages/ui/api/index.ts @@ -10,12 +10,22 @@ function getApiEndpoint() { return useRuntimeConfig().public.apiBase } -export const getAllFeedsRequests = async ({ network }: { network: string }) => +export const getAllFeedsRequests = async ({ + network, + mainnet, + pair, +}: { + network: string | null + mainnet: boolean | null + pair: string | null +}) => (await request( getApiEndpoint(), feedsQuery, { network, + mainnet, + pair, }, { accept: 'application/json' }, )) as { diff --git a/packages/ui/api/queries/feeds.ts b/packages/ui/api/queries/feeds.ts index 9b813c63..a6b3640d 100644 --- a/packages/ui/api/queries/feeds.ts +++ b/packages/ui/api/queries/feeds.ts @@ -1,8 +1,8 @@ import { gql } from 'graphql-request' export default gql` - query feeds($network: String!) { - feeds(network: $network) { + query feeds($network: String, $mainnet: Boolean, $pair: String) { + feeds(network: $network, mainnet: $mainnet, pair: $pair) { feeds { isRouted feedFullName diff --git a/packages/ui/components/DataFeeds.vue b/packages/ui/components/DataFeeds.vue index 1758362e..60f8a080 100644 --- a/packages/ui/components/DataFeeds.vue +++ b/packages/ui/components/DataFeeds.vue @@ -94,9 +94,11 @@ watch(networkFeeds, () => { } }) onMounted(async () => { - networkFeeds.value = await store.fetchFeeds({ + const fetchedNetworks = await store.fetchFeeds({ network: props.network.key.toLowerCase(), + mainnet: null, }) + networkFeeds.value = fetchedNetworks }) diff --git a/packages/ui/stores/index.ts b/packages/ui/stores/index.ts index a0314229..ab40da7b 100644 --- a/packages/ui/stores/index.ts +++ b/packages/ui/stores/index.ts @@ -30,8 +30,16 @@ export const useStore = defineStore('data', { this.networks = (await getNetworks()).networks return this.networks }, - async fetchFeeds({ network }: { network: any }) { - return (await getAllFeedsRequests({ network })).feeds + async fetchFeeds({ + network = null, + mainnet, + pair = null, + }: { + network?: string | null + mainnet: boolean | null + pair?: string | null + }) { + return (await getAllFeedsRequests({ network, mainnet, pair })).feeds }, async fetchFeedInfo({ feedFullName,