@@ -13,6 +13,7 @@ import {
1313 type OmnichainIndexingStatusSnapshot ,
1414 validateEnsIndexerPublicConfigCompatibility ,
1515} from "@ensnode/ensnode-sdk" ;
16+ import type { LocalPonderClient } from "@ensnode/ponder-sdk" ;
1617
1718import "@/lib/__test__/mockLogger" ;
1819
@@ -92,6 +93,28 @@ function createMockStackInfoBuilder(
9293 } as unknown as StackInfoBuilder ;
9394}
9495
96+ function createMockLocalPonderClient ( options : { isInDevMode ?: boolean } = { } ) : LocalPonderClient {
97+ return {
98+ isInDevMode : options . isInDevMode ?? false ,
99+ } as unknown as LocalPonderClient ;
100+ }
101+
102+ function createIndexingMetadataContextBuilder (
103+ overrides : {
104+ ensDbClient ?: EnsDbReader ;
105+ indexingStatusBuilder ?: IndexingStatusBuilder ;
106+ stackInfoBuilder ?: StackInfoBuilder ;
107+ localPonderClient ?: LocalPonderClient ;
108+ } = { } ,
109+ ) : IndexingMetadataContextBuilder {
110+ return new IndexingMetadataContextBuilder (
111+ overrides . ensDbClient ?? createMockEnsDbReader ( ) ,
112+ overrides . indexingStatusBuilder ?? createMockIndexingStatusBuilder ( ) ,
113+ overrides . stackInfoBuilder ?? createMockStackInfoBuilder ( ) ,
114+ overrides . localPonderClient ?? createMockLocalPonderClient ( ) ,
115+ ) ;
116+ }
117+
95118describe ( "IndexingMetadataContextBuilder" , ( ) => {
96119 beforeEach ( ( ) => {
97120 vi . clearAllMocks ( ) ;
@@ -109,11 +132,11 @@ describe("IndexingMetadataContextBuilder", () => {
109132 const indexingStatusBuilder = createMockIndexingStatusBuilder ( omnichainSnapshotUnstarted ) ;
110133 const stackInfoBuilder = createMockStackInfoBuilder ( ) ;
111134
112- const builder = new IndexingMetadataContextBuilder (
135+ const builder = createIndexingMetadataContextBuilder ( {
113136 ensDbClient,
114137 indexingStatusBuilder,
115138 stackInfoBuilder,
116- ) ;
139+ } ) ;
117140 const result = await builder . getIndexingMetadataContext ( ) ;
118141
119142 expect ( ensDbClient . getIndexingMetadataContext ) . toHaveBeenCalledOnce ( ) ;
@@ -133,11 +156,9 @@ describe("IndexingMetadataContextBuilder", () => {
133156 it ( "throws when indexing status is not unstarted" , async ( ) => {
134157 const indexingStatusBuilder = createMockIndexingStatusBuilder ( omnichainSnapshotFollowing ) ;
135158
136- const builder = new IndexingMetadataContextBuilder (
137- createMockEnsDbReader ( ) ,
159+ const builder = createIndexingMetadataContextBuilder ( {
138160 indexingStatusBuilder,
139- createMockStackInfoBuilder ( ) ,
140- ) ;
161+ } ) ;
141162
142163 await expect ( builder . getIndexingMetadataContext ( ) ) . rejects . toThrow (
143164 / O m n i c h a i n i n d e x i n g s t a t u s m u s t b e " u n s t a r t e d " / ,
@@ -146,18 +167,20 @@ describe("IndexingMetadataContextBuilder", () => {
146167 } ) ;
147168
148169 describe ( "when stored context is Initialized" , ( ) => {
149- it ( "builds and returns initialized context after validating compatibility " , async ( ) => {
170+ it ( "validates compatibility when not in dev mode " , async ( ) => {
150171 const ensDbClient = createMockEnsDbReader ( {
151172 getIndexingMetadataContext : vi . fn ( ) . mockResolvedValue ( indexingMetadataContextInitialized ) ,
152173 } ) ;
153174 const indexingStatusBuilder = createMockIndexingStatusBuilder ( omnichainSnapshotFollowing ) ;
154175 const stackInfoBuilder = createMockStackInfoBuilder ( ) ;
176+ const localPonderClient = createMockLocalPonderClient ( { isInDevMode : false } ) ;
155177
156- const builder = new IndexingMetadataContextBuilder (
178+ const builder = createIndexingMetadataContextBuilder ( {
157179 ensDbClient,
158180 indexingStatusBuilder,
159181 stackInfoBuilder,
160- ) ;
182+ localPonderClient,
183+ } ) ;
161184 const result = await builder . getIndexingMetadataContext ( ) ;
162185
163186 expect ( validateEnsIndexerPublicConfigCompatibility ) . toHaveBeenCalledWith (
@@ -172,7 +195,32 @@ describe("IndexingMetadataContextBuilder", () => {
172195 expect ( result ) . toBe ( indexingMetadataContextInitialized ) ;
173196 } ) ;
174197
175- it ( "throws when stored and in-memory configs are incompatible" , async ( ) => {
198+ it ( "skips compatibility validation when in dev mode" , async ( ) => {
199+ const ensDbClient = createMockEnsDbReader ( {
200+ getIndexingMetadataContext : vi . fn ( ) . mockResolvedValue ( indexingMetadataContextInitialized ) ,
201+ } ) ;
202+ const indexingStatusBuilder = createMockIndexingStatusBuilder ( omnichainSnapshotFollowing ) ;
203+ const stackInfoBuilder = createMockStackInfoBuilder ( ) ;
204+ const localPonderClient = createMockLocalPonderClient ( { isInDevMode : true } ) ;
205+
206+ const builder = createIndexingMetadataContextBuilder ( {
207+ ensDbClient,
208+ indexingStatusBuilder,
209+ stackInfoBuilder,
210+ localPonderClient,
211+ } ) ;
212+ const result = await builder . getIndexingMetadataContext ( ) ;
213+
214+ // Compatibility validation should NOT be called in dev mode
215+ expect ( validateEnsIndexerPublicConfigCompatibility ) . not . toHaveBeenCalled ( ) ;
216+ expect ( buildIndexingMetadataContextInitialized ) . toHaveBeenCalledWith (
217+ crossChainSnapshot ,
218+ stackInfo ,
219+ ) ;
220+ expect ( result ) . toBe ( indexingMetadataContextInitialized ) ;
221+ } ) ;
222+
223+ it ( "throws when stored and in-memory configs are incompatible (not in dev mode)" , async ( ) => {
176224 vi . mocked ( validateEnsIndexerPublicConfigCompatibility ) . mockImplementation ( ( ) => {
177225 throw new Error ( "Incompatible ENSIndexer config" ) ;
178226 } ) ;
@@ -181,16 +229,34 @@ describe("IndexingMetadataContextBuilder", () => {
181229 getIndexingMetadataContext : vi . fn ( ) . mockResolvedValue ( indexingMetadataContextInitialized ) ,
182230 } ) ;
183231
184- const builder = new IndexingMetadataContextBuilder (
232+ const builder = createIndexingMetadataContextBuilder ( {
185233 ensDbClient,
186- createMockIndexingStatusBuilder ( omnichainSnapshotFollowing ) ,
187- createMockStackInfoBuilder ( ) ,
188- ) ;
234+ indexingStatusBuilder : createMockIndexingStatusBuilder ( omnichainSnapshotFollowing ) ,
235+ localPonderClient : createMockLocalPonderClient ( { isInDevMode : false } ) ,
236+ } ) ;
189237
190238 await expect ( builder . getIndexingMetadataContext ( ) ) . rejects . toThrow (
191239 "Incompatible ENSIndexer config" ,
192240 ) ;
193241 } ) ;
242+
243+ it ( "does not throw on incompatible configs when in dev mode" , async ( ) => {
244+ vi . mocked ( validateEnsIndexerPublicConfigCompatibility ) . mockImplementation ( ( ) => {
245+ throw new Error ( "Incompatible ENSIndexer config" ) ;
246+ } ) ;
247+
248+ const ensDbClient = createMockEnsDbReader ( {
249+ getIndexingMetadataContext : vi . fn ( ) . mockResolvedValue ( indexingMetadataContextInitialized ) ,
250+ } ) ;
251+
252+ const builder = createIndexingMetadataContextBuilder ( {
253+ ensDbClient,
254+ indexingStatusBuilder : createMockIndexingStatusBuilder ( omnichainSnapshotFollowing ) ,
255+ localPonderClient : createMockLocalPonderClient ( { isInDevMode : true } ) ,
256+ } ) ;
257+
258+ await expect ( builder . getIndexingMetadataContext ( ) ) . resolves . toBeDefined ( ) ;
259+ } ) ;
194260 } ) ;
195261
196262 it ( "fetches all three data sources in parallel" , async ( ) => {
@@ -215,11 +281,11 @@ describe("IndexingMetadataContextBuilder", () => {
215281 return stackInfo ;
216282 } ) ;
217283
218- const builder = new IndexingMetadataContextBuilder (
284+ const builder = createIndexingMetadataContextBuilder ( {
219285 ensDbClient,
220286 indexingStatusBuilder,
221287 stackInfoBuilder,
222- ) ;
288+ } ) ;
223289 await builder . getIndexingMetadataContext ( ) ;
224290
225291 // All three should have been called (ordering is not deterministic for parallel)
0 commit comments