• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

decentraland / realm-provider / 18787135118

24 Oct 2025 05:20PM UTC coverage: 16.438% (-22.7%) from 39.12%
18787135118

Pull #75

github

kevinszuchet
chore: Remove output-directory from docs workflow
Pull Request #75: docs: Add API spec

13 of 50 branches covered (26.0%)

Branch coverage included in aggregate %.

35 of 242 relevant lines covered (14.46%)

0.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/adapters/realm-provider.ts
1
import { AppComponents } from '../types'
2
import { About } from '@dcl/catalyst-api-specs/lib/client'
3
import RequestManager, { bytesToHex, ContractFactory, HTTPProvider } from 'eth-connect'
×
4
import {
×
5
  catalystAbi,
6
  CatalystByIdResult,
7
  CatalystContract,
8
  getCatalystServersFromDAO,
9
  l1Contracts,
10
  L1Network
11
} from '@dcl/catalyst-contracts'
12
import { LRUCache } from 'lru-cache'
×
13

14
export type RealmInfo = {
15
  about: About
16
  url: string
17
}
18

19
export type CatalystsProvider = {
20
  getHealhtyCatalysts(): Promise<RealmInfo[]>
21
}
22

23
async function createContract(address: string, provider: HTTPProvider): Promise<CatalystContract> {
24
  const requestManager = new RequestManager(provider)
×
25
  const factory = new ContractFactory(requestManager, catalystAbi)
×
26
  const contract = (await factory.at(address)) as any
×
27
  return {
×
28
    async catalystCount(): Promise<number> {
29
      return contract.catalystCount()
×
30
    },
31
    async catalystIds(i: number): Promise<string> {
32
      return contract.catalystIds(i)
×
33
    },
34
    async catalystById(catalystId: string): Promise<CatalystByIdResult> {
35
      const [id, owner, domain] = await contract.catalystById(catalystId)
×
36
      return { id: '0x' + bytesToHex(id), owner, domain }
×
37
    }
38
  }
39
}
40

41
export async function createCatalystsProvider({
×
42
  logs,
43
  fetch,
44
  config
45
}: Pick<AppComponents, 'logs' | 'fetch' | 'config'>): Promise<CatalystsProvider> {
46
  const logger = logs.getLogger('realm-provider')
×
47

48
  const network: L1Network = ((await config.getString('ETH_NETWORK')) ?? 'mainnet') as L1Network
×
49
  const contracts = l1Contracts[network]
×
50
  if (!contracts) {
×
51
    throw new Error(`Invalid ETH_NETWORK ${network}`)
×
52
  }
53

54
  const opts = { fetch: fetch.fetch }
×
55
  const mainnet = new HTTPProvider(`https://rpc.decentraland.org/${network}?project=realm-provider`, opts)
×
56

57
  const contract = await createContract(contracts.catalyst, mainnet)
×
58

59
  const daoCache = new LRUCache<number, string[]>({
×
60
    max: 12,
61
    ttl: 1000 * 60 * 60 * 24, // 1 day
62
    fetchMethod: async function (_: number, staleValue: string[] | undefined) {
63
      try {
×
64
        const servers = await getCatalystServersFromDAO(contract)
×
65
        return servers.map((s) => s.address)
×
66
      } catch (err: any) {
67
        logger.error(err)
×
68
        return staleValue
×
69
      }
70
    }
71
  })
72

73
  async function getHealhtyCatalysts(): Promise<RealmInfo[]> {
74
    const catalysts = await daoCache.fetch(1)
×
75
    if (!catalysts || catalysts.length === 0) {
×
76
      console.warn('No catalysts found in daoCache.')
×
77
      return []
×
78
    }
79

80
    const catalystsInfo = await Promise.all(
×
81
      catalysts.map(async (catalyst) => {
82
        try {
×
83
          logger.info(`Fetching /about from ${catalyst}`)
×
84
          const response = await opts.fetch(`${catalyst}/about`, { timeout: 1000 })
×
85
          if (!response.ok) {
×
86
            logger.warn(`Failed to fetch /about from ${catalyst}: ${response.statusText}`)
×
87
            return null
×
88
          }
89
          const info = await response.json()
×
90
          if (info.healthy && info.acceptingUsers) {
×
91
            return { about: info, url: catalyst }
×
92
          } else {
93
            logger.info(`Catalyst ${catalyst} is not healthy or not accepting users`)
×
94
            return null
×
95
          }
96
        } catch (error) {
97
          logger.error(`Error fetching /about from ${catalyst}: ${error}`)
×
98
          return null
×
99
        }
100
      })
101
    )
102
    // Filter out any null values (unhealthy or failed fetches) and return
103
    return catalystsInfo.filter(Boolean) as RealmInfo[]
×
104
  }
105

106
  return {
×
107
    getHealhtyCatalysts
108
  }
109
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc