Skip to content

Commit

Permalink
f
Browse files Browse the repository at this point in the history
  • Loading branch information
Tommytrg committed Jun 19, 2024
1 parent 09b0724 commit d19d931
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 89 deletions.
57 changes: 24 additions & 33 deletions packages/api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import {
Repositories,
FeedInfo,
NetworksConfig,
Db,
} from '../types'
import { Web3Middleware } from './web3Middleware/index'
import { normalizeNetworkConfig } from './utils/index'
import { fetchFeedsLegacy, fetchDataFeedsRouterConfig } from './readDataFeeds'
import { SvgCache } from './svgCache'
import { NetworkRouter } from './web3Middleware/NetworkRouter'
import { Configuration } from './web3Middleware/Configuration'
import { FeedsState } from './repository/feedState'

class DataFeedsExplorer {
routers: Array<NetworkRouter>
Expand All @@ -26,8 +26,18 @@ class DataFeedsExplorer {
configuration: Configuration
networksConfig

svgCache: SvgCache
mongoManager: MongoManager
feedsState: FeedsState

constructor() {
this.svgCache = new SvgCache()
this.mongoManager = new MongoManager()
this.feedsState = new FeedsState()
}

async initializeNetworkRouters() {
this.routers = this.configuration
return this.configuration
.listNetworksUsingPriceFeedsContract()
.filter((config) => {
if (!config.provider) {
Expand All @@ -46,14 +56,6 @@ class DataFeedsExplorer {
)
}

initializeRepositories(feeds: FeedInfo[], db: Db) {
const repositories: Repositories = {
feedRepository: new FeedRepository(feeds),
resultRequestRepository: new ResultRequestRepository(db),
}
this.repositories = repositories
}

async initializeConfiguration(svgCache: SvgCache) {
this.configurationFile = await fetchDataFeedsRouterConfig()
this.configuration = new Configuration(this.configurationFile)
Expand All @@ -64,20 +66,22 @@ class DataFeedsExplorer {
}

async start() {
const svgCache = new SvgCache()
const mongoManager = new MongoManager()
const db = await mongoManager.start()
const db = await this.mongoManager.start()

await this.initializeConfiguration(svgCache)
await this.initializeNetworkRouters()
await this.initializeConfiguration(this.svgCache)
this.routers = await this.initializeNetworkRouters()

const legacyFeeds: Array<FeedInfo> = fetchFeedsLegacy(
this.configurationFile,
)
const newFeeds: Array<FeedInfo> = await fetchFeedsV2(this.routers)
const feeds = [...legacyFeeds, ...newFeeds]
const v2Feeds: Array<FeedInfo> = await fetchFeedsV2(this.routers)

this.initializeRepositories(feeds, db)
this.repositories = {
feedRepository: new FeedRepository(this.feedsState),
resultRequestRepository: new ResultRequestRepository(db),
}
this.repositories.feedRepository.setLegacyFeeds(legacyFeeds)
this.repositories.feedRepository.setV2Feeds(v2Feeds)

const web3Middleware = new Web3Middleware(
this.configuration,
Expand All @@ -87,24 +91,10 @@ class DataFeedsExplorer {

web3Middleware.listen()

await createServer(this.repositories, svgCache, {
dataFeedsConfig: feeds,
await createServer(this.repositories, this.svgCache, {
networksConfig: this.networksConfig,
configuration: this.configuration,
})

// Refresh list of available feeds in the feedRepository
this.initializeV2FeedsRefreshInterval()
}

initializeV2FeedsRefreshInterval() {
setInterval(
async () => {
const feeds = await fetchFeedsV2(this.routers)
this.repositories.feedRepository.initialize(feeds)
},
1000 * 60 * 60,
)
}
}

Expand Down Expand Up @@ -140,3 +130,4 @@ async function fetchNetworkConfigurations(
const dfe = new DataFeedsExplorer()

dfe.start()
export { FeedsState }
81 changes: 58 additions & 23 deletions packages/api/src/repository/Feed.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import { PaginatedFeedsObject, FeedInfo } from '../../types'
import { FeedsState } from '..'
import { PaginatedFeedsObject, FeedInfo, ConfigByFullName } from '../../types'

export class FeedRepository {
dataFeeds: Array<FeedInfo>
feedsState: FeedsState
// TODO: replace string with Network
dataFeedsByNetwork: Record<string, Array<FeedInfo>>
configByFullName: ConfigByFullName

constructor(dataFeeds: Array<FeedInfo>) {
this.initialize(dataFeeds)
constructor(feedState: FeedsState) {
this.feedsState = feedState
this.initialize()
}

initialize(dataFeeds: Array<FeedInfo>) {
this.dataFeedsByNetwork = dataFeeds.reduce(
initialize() {
const feeds = this.feedsState.listFeeds()

this.dataFeedsByNetwork = feeds.reduce(
(acc: Record<string, Array<FeedInfo>>, feedInfo: FeedInfo) => ({
...acc,
[feedInfo.network]: acc[feedInfo.network]
Expand All @@ -19,11 +24,23 @@ export class FeedRepository {
}),
{},
)
this.dataFeeds = dataFeeds
this.configByFullName = feeds.reduce(
(acc, feedInfo) => ({
...acc,
[`${feedInfo.feedFullName}`]: feedInfo,
}),
{},
)
}

getConfigByFullName() {
return this.configByFullName
}

get(feedFullName: string): FeedInfo {
return this.dataFeeds.find((feed) => feed.feedFullName === feedFullName)
return this.feedsState
.listFeeds()
.find((feed) => feed.feedFullName === feedFullName)
}

async getFeedsByNetwork(
Expand All @@ -49,20 +66,38 @@ export class FeedRepository {
const hasSameFeedFullName = (feed: FeedInfo) =>
feed.feedFullName === feedFullName

// Update address in sortedDataFeeds
const sortedDataFeedIndex = this.dataFeeds.findIndex(hasSameFeedFullName)
const feed = this.dataFeeds[sortedDataFeedIndex]
feed.address = address
feed.contractId = contractId
// Update address in dataFeedsByNetwork cache
const dataFeedsByNetworkIndex =
this.dataFeedsByNetwork[feed.network].findIndex(hasSameFeedFullName)
this.dataFeedsByNetwork[feed.network][dataFeedsByNetworkIndex].address =
address
// Update contractId in dataFeedsByNetwork cache
this.dataFeedsByNetwork[feed.network][dataFeedsByNetworkIndex].contractId =
contractId

return feed
const legacyFeeds = this.feedsState.getLegacyFeeds()
const index = legacyFeeds.findIndex(hasSameFeedFullName)
const updatedFeed = { ...legacyFeeds[index], address, contractId }
legacyFeeds[index] = updatedFeed
this.feedsState.setLegacyFeeds(legacyFeeds)

this.initialize()

return updatedFeed
}

refreshV2NetworkFeeds(network: string, feedInfos: Array<FeedInfo>) {
const v2Feeds = this.feedsState.getV2Feeds()

const newV2Feeds = v2Feeds
.filter((feed) => {
feed.network !== network
})
.concat(feedInfos)

this.feedsState.setV2Feeds(newV2Feeds)

this.initialize()
}

setLegacyFeeds(legacyFeeds: Array<FeedInfo>) {
this.feedsState.setLegacyFeeds(legacyFeeds)
this.initialize()
}

setV2Feeds(v2Feeds: Array<FeedInfo>) {
this.feedsState.setV2Feeds(v2Feeds)
this.initialize()
}
}
31 changes: 31 additions & 0 deletions packages/api/src/repository/feedState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { FeedInfo } from '../../types'

export class FeedsState {
private legacyFeeds: Array<FeedInfo>
private v2Feeds: Array<FeedInfo>

constructor() {
this.legacyFeeds = []
this.v2Feeds = []
}

setV2Feeds(v2Feeds: Array<FeedInfo>) {
this.v2Feeds = v2Feeds
}

setLegacyFeeds(legacyFeeds: Array<FeedInfo>) {
this.legacyFeeds = legacyFeeds
}

getV2Feeds(): Array<FeedInfo> {
return this.v2Feeds
}

getLegacyFeeds(): Array<FeedInfo> {
return this.legacyFeeds
}

listFeeds(): Array<FeedInfo> {
return [...this.legacyFeeds, ...this.v2Feeds]
}
}
46 changes: 32 additions & 14 deletions packages/api/src/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,28 +43,46 @@ const resolvers = {
lastResultTimestamp: async (parent, _args, { loaders }: Context) => {
return (await loaders.lastResult.load(parent.feedFullName))?.timestamp
},
isRouted: async (parent, _args, { config }: Context) => {
return !!config.feedsConfig[parent.feedFullName]?.isRouted
isRouted: async (parent, _args, { feedRepository }: Context) => {
return !!feedRepository.getConfigByFullName()[parent.feedFullName]
?.isRouted
},
color: async (parent, _args, { config }: Context) => {
return config.feedsConfig[parent.feedFullName]?.color || ''
color: async (parent, _args, { feedRepository }: Context) => {
return (
feedRepository.getConfigByFullName()[parent.feedFullName]?.color || ''
)
},
blockExplorer: async (parent, _args, { config }: Context) => {
return config.feedsConfig[parent.feedFullName]?.blockExplorer || ''
blockExplorer: async (parent, _args, { feedRepository }: Context) => {
return (
feedRepository.getConfigByFullName()[parent.feedFullName]
?.blockExplorer || ''
)
},
proxyAddress: async (parent, _args, { config }: Context) => {
return config.feedsConfig[parent.feedFullName]?.routerAddress || ''
proxyAddress: async (parent, _args, { feedRepository }: Context) => {
return (
feedRepository.getConfigByFullName()[parent.feedFullName]
?.routerAddress || ''
)
},
deviation: async (parent, _args, { config }: Context) => {
return config.feedsConfig[parent.feedFullName]?.deviation || ''
deviation: async (parent, _args, { feedRepository }: Context) => {
return (
feedRepository.getConfigByFullName()[parent.feedFullName]?.deviation ||
''
)
},
heartbeat: async (parent, _args, { config }: Context) => {
heartbeat: async (parent, _args, { feedRepository }: Context) => {
// Heartbeat plus aproximate time in milliseconds that takes to resolve the witnet dr
return config.feedsConfig[parent.feedFullName]?.heartbeat || ''
return (
feedRepository.getConfigByFullName()[parent.feedFullName]?.heartbeat ||
''
)
},
finality: async (parent, _args, { config }: Context) => {
finality: async (parent, _args, { feedRepository }: Context) => {
// Heartbeat plus aproximate time in milliseconds that takes to resolve the witnet dr
return config.feedsConfig[parent.feedFullName]?.finality || ''
return (
feedRepository.getConfigByFullName()[parent.feedFullName]?.finality ||
''
)
},
address: async (parent, _args, { config }: Context) => {
return parent.address || config.configuration.getDefaultAddress()
Expand Down
19 changes: 1 addition & 18 deletions packages/api/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,7 @@ import { ApolloServer } from '@apollo/server'
import typeDefs from './typeDefs'
import { DIRECTIVES } from '@graphql-codegen/typescript-mongodb'
import resolvers from './resolvers'
import {
ConfigByFullName,
Context,
FeedInfo,
Loaders,
NetworksConfig,
Repositories,
} from '../types'
import { Context, Loaders, NetworksConfig, Repositories } from '../types'
import { startStandaloneServer } from '@apollo/server/standalone'
import { LoadersFactory } from './loaders'
import SvgCache from './svgCache'
Expand All @@ -19,7 +12,6 @@ export async function createServer(
repositories: Repositories,
svgCache: SvgCache,
config: {
dataFeedsConfig: Array<FeedInfo>
networksConfig: Array<NetworksConfig>
configuration: Configuration
},
Expand All @@ -32,14 +24,6 @@ export async function createServer(
const { url } = await startStandaloneServer<Context>(server, {
listen: { host: '0.0.0.0', port: Number(process.env.SERVER_PORT) },
context: async () => {
const configByFullName: ConfigByFullName = config.dataFeedsConfig.reduce(
(acc, feedInfo) => ({
...acc,
[`${feedInfo.feedFullName}`]: feedInfo,
}),
{},
)

const loaders: Loaders = new LoadersFactory(
repositories,
svgCache,
Expand All @@ -49,7 +33,6 @@ export async function createServer(
feedRepository: repositories.feedRepository,
resultRequestRepository: repositories.resultRequestRepository,
config: {
feedsConfig: configByFullName,
networksConfig: config.networksConfig,
configuration: config.configuration,
},
Expand Down
13 changes: 13 additions & 0 deletions packages/api/src/web3Middleware/NetworkRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export class NetworkRouter {
private address: string
private configuration: Configuration
private provider: string
private lastSupportedFeedsID = ''

constructor(
configuration: Configuration,
Expand Down Expand Up @@ -109,6 +110,18 @@ export class NetworkRouter {

async getSnapshot(): Promise<NetworkSnapshot> {
const supportedFeeds = await this.getSupportedFeeds()

const lastSupportedFeedsID = JSON.stringify(supportedFeeds)

if (this.lastSupportedFeedsID !== lastSupportedFeedsID) {
this.repositories.feedRepository.refreshV2NetworkFeeds(
this.network,
await this.getFeedInfos(),
)
}

this.lastSupportedFeedsID = JSON.stringify(supportedFeeds)

const feedIds = supportedFeeds.map((feed) => feed.id)
const latestPrices = await this.latestPrices(feedIds)

Expand Down
1 change: 0 additions & 1 deletion packages/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export interface Context {
feedRepository: FeedRepository
resultRequestRepository: ResultRequestRepository
config: {
feedsConfig: ConfigByFullName
networksConfig: Array<NetworksConfig>
configuration: Configuration
}
Expand Down

0 comments on commit d19d931

Please sign in to comment.