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

decentraland / lamb2 / 18364533347

09 Oct 2025 03:23AM UTC coverage: 82.749% (+0.1%) from 82.603%
18364533347

Pull #434

github

AndresMorelos
feat: add support for smart wearables in explorer handler and related components
Pull Request #434: feat: add support for smart wearables in explorer handler and related components

453 of 599 branches covered (75.63%)

Branch coverage included in aggregate %.

25 of 26 new or added lines in 4 files covered. (96.15%)

13 existing lines in 3 files now uncovered.

1389 of 1627 relevant lines covered (85.37%)

54.48 hits per line

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

86.87
/src/components.ts
1
import { l1Contracts, L1Network, L2Network } from '@dcl/catalyst-contracts'
15✔
2
import { createDotEnvConfigComponent } from '@well-known-components/env-config-provider'
15✔
3
import {
15✔
4
  createServerComponent,
5
  createStatusCheckComponent,
6
  instrumentHttpServerWithPromClientRegistry
7
} from '@well-known-components/http-server'
8
import { createLogComponent } from '@well-known-components/logger'
15✔
9
import { createMetricsComponent } from '@well-known-components/metrics'
15✔
10
import { createContentClient } from 'dcl-catalyst-client'
15✔
11
import { HTTPProvider } from 'eth-connect'
15✔
12
import { createCatalystsFetcher } from './adapters/catalysts-fetcher'
15✔
13
import { createContentServerUrl } from './adapters/content-server-url'
15✔
14
import {
15✔
15
  createEmoteDefinitionsFetcherComponent,
16
  createWearableDefinitionsFetcherComponent
17
} from './adapters/definitions-fetcher'
18
import { createElementsFetcherComponent } from './adapters/elements-fetcher'
15✔
19
import { createEntitiesFetcherComponent } from './adapters/entities-fetcher'
15✔
20
import { createNameDenylistFetcher } from './adapters/name-denylist-fetcher'
15✔
21
import { createPOIsFetcher } from './adapters/pois-fetcher'
15✔
22
import { createResourcesStatusComponent } from './adapters/resource-status'
15✔
23
import { createStatusComponent } from './adapters/status'
15✔
24
import { fetchAllBaseWearables } from './logic/fetch-elements/fetch-base-items'
15✔
25
import { fetchAllEmotes, fetchAllWearables, fetchAllSmartWearables } from './logic/fetch-elements/fetch-items'
15✔
26
import { fetchAllLANDs } from './logic/fetch-elements/fetch-lands'
15✔
27
import { fetchAllNames } from './logic/fetch-elements/fetch-names'
15✔
28
import { fetchAllThirdPartyWearables } from './logic/fetch-elements/fetch-third-party-wearables'
15✔
29
import { metricDeclarations } from './metrics'
15✔
30
import { createFetchComponent } from './ports/fetch'
15✔
31
import { createOwnershipCachesComponent } from './ports/ownership-caches'
15✔
32
import { createTheGraphComponent, TheGraphComponent } from './ports/the-graph'
15✔
33
import { AppComponents, BaseWearable, GlobalContext } from './types'
34
import { createThirdPartyProvidersGraphFetcherComponent } from './adapters/third-party-providers-graph-fetcher'
15✔
35
import { createThirdPartyProvidersStorage } from './logic/third-party-providers-storage'
15✔
36
import { createProfilesComponent } from './adapters/profiles'
15✔
37
import { IFetchComponent } from '@well-known-components/interfaces'
38
import { createAlchemyNftFetcher } from './adapters/alchemy-nft-fetcher'
15✔
39
import { createThirdPartyContractRegistry } from './ports/ownership-checker/third-party-contract-registry'
15✔
40
import { createThirdPartyItemChecker } from './ports/ownership-checker/third-party-item-checker'
15✔
41
import { createParcelRightsComponent } from './adapters/parcel-rights-fetcher'
15✔
42
import { fetchNameOwner } from './logic/fetch-elements/fetch-name-owner'
15✔
43
import { fetchAllPermissions } from './logic/fetch-elements/fetch-permissions'
15✔
44

45
// Initialize all the components of the app
46
export async function initComponents(
15✔
47
  fetchComponent?: IFetchComponent,
48
  theGraphComponent?: TheGraphComponent
49
): Promise<AppComponents> {
50
  const config = await createDotEnvConfigComponent({ path: ['.env.default', '.env'] })
36✔
51
  const logs = await createLogComponent({})
36✔
52
  const server = await createServerComponent<GlobalContext>(
36✔
53
    { config, logs },
54
    {
55
      cors: {
56
        maxAge: 36000
57
      }
58
    }
59
  )
60
  const statusChecks = await createStatusCheckComponent({ server, config })
36✔
61
  const fetch = fetchComponent ? fetchComponent : await createFetchComponent()
36!
62
  const metrics = await createMetricsComponent(metricDeclarations, { config })
36✔
63
  await instrumentHttpServerWithPromClientRegistry({ server, metrics, config, registry: metrics.registry! })
36✔
64

65
  const contentServerUrl = await createContentServerUrl({ config })
36✔
66
  const content = createContentClient({ url: contentServerUrl, fetcher: fetch })
36✔
67

68
  const theGraph = theGraphComponent
36!
69
    ? theGraphComponent
70
    : await createTheGraphComponent({ config, logs, fetch, metrics })
71

72
  const ownershipCaches = await createOwnershipCachesComponent({ config })
36✔
73

74
  const wearableDefinitionsFetcher = await createWearableDefinitionsFetcherComponent({
36✔
75
    config,
76
    logs,
77
    content,
78
    contentServerUrl
79
  })
80

81
  // TODO: use content client for collection items fetching. prevent injecting contentServerUrl and fetch components.
82
  const entitiesFetcher = await createEntitiesFetcherComponent({ config, logs, content, contentServerUrl, fetch })
36✔
83

84
  const emoteDefinitionsFetcher = await createEmoteDefinitionsFetcherComponent({
36✔
85
    config,
86
    logs,
87
    content,
88
    contentServerUrl
89
  })
90
  const baseWearablesFetcher = createElementsFetcherComponent<BaseWearable>({ logs }, async (_address) =>
36✔
91
    fetchAllBaseWearables({ entitiesFetcher })
×
92
  )
93
  const wearablesFetcher = createElementsFetcherComponent({ logs }, async (address) =>
36✔
94
    fetchAllWearables({ theGraph }, address)
×
95
  )
96
  const smartWearablesFetcher = createElementsFetcherComponent({ logs }, async (address) =>
36✔
97
    fetchAllSmartWearables({ theGraph }, address)
1✔
98
  )
99
  const emotesFetcher = createElementsFetcherComponent({ logs }, async (address) =>
36✔
UNCOV
100
    fetchAllEmotes({ theGraph }, address)
×
101
  )
102
  const namesFetcher = createElementsFetcherComponent({ logs }, async (address) => fetchAllNames({ theGraph }, address))
36✔
103
  const landsFetcher = createElementsFetcherComponent({ logs }, async (address) => fetchAllLANDs({ theGraph }, address))
36✔
104
  const landsPermissionsFetcher = createElementsFetcherComponent({ logs }, async (address) =>
36✔
105
    fetchAllPermissions({ theGraph }, address)
7✔
106
  )
107

108
  const resourcesStatusCheck = createResourcesStatusComponent({ logs })
36✔
109
  const status = await createStatusComponent({ logs, fetch })
36✔
110

111
  const l1Network: L1Network = ((await config.getString('ETH_NETWORK')) ?? 'mainnet') as L1Network
36✔
112
  const contracts = l1Contracts[l1Network]
36✔
113
  if (!contracts) {
36!
UNCOV
114
    throw new Error(`Invalid ETH_NETWORK ${l1Network}`)
×
115
  }
116
  const l2Network: L2Network = l1Network === 'mainnet' ? 'polygon' : 'amoy'
36!
117
  const l1Provider = new HTTPProvider(`https://rpc.decentraland.org/${encodeURIComponent(l1Network)}?project=lamb2`, {
36✔
118
    fetch: fetch.fetch
119
  })
120
  const l2Provider = new HTTPProvider(`https://rpc.decentraland.org/${encodeURIComponent(l2Network)}?project=lamb2`, {
36✔
121
    fetch: fetch.fetch
122
  })
123
  const catalystsFetcher = await createCatalystsFetcher({ l1Provider }, l1Network)
36✔
124
  const poisFetcher = await createPOIsFetcher({ l2Provider }, l2Network)
36✔
125
  const nameDenylistFetcher = await createNameDenylistFetcher({ l1Provider }, l1Network)
36✔
126
  const parcelRightsFetcher = await createParcelRightsComponent(
36✔
127
    {
128
      logs,
129
      theGraph
130
    },
131
    l1Network
132
  )
133

134
  const l1ThirdPartyContractRegistry = await createThirdPartyContractRegistry(logs, l1Provider, l1Network as any, '.')
36✔
135
  const l2ThirdPartyContractRegistry = await createThirdPartyContractRegistry(logs, l2Provider, l2Network as any, '.')
36✔
136
  const l1ThirdPartyItemChecker = await createThirdPartyItemChecker(
36✔
137
    { entitiesFetcher, logs },
138
    l1Provider,
139
    l1ThirdPartyContractRegistry
140
  )
141
  const l2ThirdPartyItemChecker = await createThirdPartyItemChecker(
36✔
142
    { entitiesFetcher, logs },
143
    l2Provider,
144
    l2ThirdPartyContractRegistry
145
  )
146

147
  const thirdPartyProvidersGraphFetcher = createThirdPartyProvidersGraphFetcherComponent({ theGraph })
36✔
148
  const thirdPartyProvidersStorage = await createThirdPartyProvidersStorage({
36✔
149
    logs,
150
    thirdPartyProvidersGraphFetcher
151
  })
152
  const thirdPartyWearablesFetcher = createElementsFetcherComponent({ logs }, async (address) =>
36✔
UNCOV
153
    fetchAllThirdPartyWearables(
×
154
      {
155
        alchemyNftFetcher,
156
        contentServerUrl,
157
        thirdPartyProvidersStorage,
158
        fetch,
159
        entitiesFetcher,
160
        metrics
161
      },
162
      address
163
    )
164
  )
165

166
  const alchemyNftFetcher = await createAlchemyNftFetcher({ config, logs, fetch })
36✔
167

168
  const nameOwnerFetcher = createElementsFetcherComponent({ logs }, async (name) => {
36✔
UNCOV
169
    const result = await fetchNameOwner({ theGraph }, name)
×
UNCOV
170
    return result ? [result] : []
×
171
  })
172

173
  const profiles = await createProfilesComponent({
36✔
174
    alchemyNftFetcher,
175
    metrics,
176
    content,
177
    contentServerUrl,
178
    entitiesFetcher,
179
    theGraph,
180
    config,
181
    fetch,
182
    ownershipCaches,
183
    thirdPartyProvidersStorage,
184
    logs,
185
    wearablesFetcher,
186
    emotesFetcher,
187
    namesFetcher,
188
    l1ThirdPartyItemChecker,
189
    l2ThirdPartyItemChecker
190
  })
191

192
  return {
36✔
193
    config,
194
    logs,
195
    server,
196
    statusChecks,
197
    fetch,
198
    metrics,
199
    content,
200
    theGraph,
201
    ownershipCaches,
202
    baseWearablesFetcher,
203
    wearablesFetcher,
204
    smartWearablesFetcher,
205
    wearableDefinitionsFetcher,
206
    emoteDefinitionsFetcher,
207
    entitiesFetcher,
208
    thirdPartyWearablesFetcher,
209
    emotesFetcher,
210
    namesFetcher,
211
    landsFetcher,
212
    landsPermissionsFetcher,
213
    parcelRightsFetcher,
214
    thirdPartyProvidersGraphFetcher,
215
    thirdPartyProvidersStorage,
216
    contentServerUrl,
217
    resourcesStatusCheck,
218
    status,
219
    l1Provider,
220
    l2Provider,
221
    catalystsFetcher,
222
    poisFetcher,
223
    nameDenylistFetcher,
224
    profiles,
225
    alchemyNftFetcher,
226
    l1ThirdPartyItemChecker,
227
    l2ThirdPartyItemChecker,
228
    nameOwnerFetcher
229
  }
230
}
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

© 2026 Coveralls, Inc