1
- import * as fs from 'fs' ;
1
+ import * as fs from 'fs/promises ' ;
2
2
import * as path from 'path' ;
3
3
import { logger } from './util/logger' ;
4
4
import {
@@ -17,17 +17,32 @@ const RegisteredPredicates = new Map<string, Predicate>();
17
17
18
18
const CompiledPredicateSchema = TypeCompiler . Compile ( PredicateSchema ) ;
19
19
20
+ // Async version of fs.existsSync
21
+ async function pathExists ( path : string ) : Promise < boolean > {
22
+ try {
23
+ await fs . access ( path ) ;
24
+ return true ;
25
+ } catch ( error ) {
26
+ if ( ( error as NodeJS . ErrnoException ) . code === 'ENOENT' ) {
27
+ return false ;
28
+ }
29
+ throw error ; // Re-throw other errors (e.g., permission issues)
30
+ }
31
+ }
32
+
20
33
/**
21
34
* Looks on disk and returns a map of registered Predicates, where the key is the predicate `name`
22
35
* as defined by the user.
23
36
*/
24
- export function recallPersistedPredicatesFromDisk ( basePath : string ) : Map < string , Predicate > {
37
+ export async function recallPersistedPredicatesFromDisk (
38
+ basePath : string
39
+ ) : Promise < Map < string , Predicate > > {
25
40
RegisteredPredicates . clear ( ) ;
26
41
try {
27
- if ( ! fs . existsSync ( basePath ) ) return RegisteredPredicates ;
28
- for ( const file of fs . readdirSync ( basePath ) ) {
42
+ if ( ! ( await pathExists ( basePath ) ) ) return RegisteredPredicates ;
43
+ for ( const file of await fs . readdir ( basePath ) ) {
29
44
if ( file . endsWith ( '.json' ) ) {
30
- const text = fs . readFileSync ( path . join ( basePath , file ) , 'utf-8' ) ;
45
+ const text = await fs . readFile ( path . join ( basePath , file ) , 'utf-8' ) ;
31
46
const predicate = JSON . parse ( text ) as JSON ;
32
47
if ( CompiledPredicateSchema . Check ( predicate ) ) {
33
48
logger . info (
@@ -44,11 +59,11 @@ export function recallPersistedPredicatesFromDisk(basePath: string): Map<string,
44
59
return RegisteredPredicates ;
45
60
}
46
61
47
- export function savePredicateToDisk ( basePath : string , predicate : Predicate ) {
62
+ export async function savePredicateToDisk ( basePath : string , predicate : Predicate ) {
48
63
const predicatePath = `${ basePath } /predicate-${ encodeURIComponent ( predicate . name ) } .json` ;
49
64
try {
50
- fs . mkdirSync ( basePath , { recursive : true } ) ;
51
- fs . writeFileSync ( predicatePath , JSON . stringify ( predicate , null , 2 ) ) ;
65
+ await fs . mkdir ( basePath , { recursive : true } ) ;
66
+ await fs . writeFile ( predicatePath , JSON . stringify ( predicate , null , 2 ) ) ;
52
67
logger . info (
53
68
`ChainhookEventObserver persisted predicate '${ predicate . name } ' (${ predicate . uuid } ) to disk`
54
69
) ;
@@ -60,13 +75,18 @@ export function savePredicateToDisk(basePath: string, predicate: Predicate) {
60
75
}
61
76
}
62
77
63
- function deletePredicateFromDisk ( basePath : string , predicate : Predicate ) {
78
+ async function deletePredicateFromDisk ( basePath : string , predicate : Predicate ) {
64
79
const predicatePath = `${ basePath } /predicate-${ encodeURIComponent ( predicate . name ) } .json` ;
65
- if ( fs . existsSync ( predicatePath ) ) {
66
- fs . rmSync ( predicatePath ) ;
80
+ try {
81
+ await fs . rm ( predicatePath ) ;
67
82
logger . info (
68
83
`ChainhookEventObserver deleted predicate '${ predicate . name } ' (${ predicate . uuid } ) from disk`
69
84
) ;
85
+ } catch ( error : unknown ) {
86
+ // ignore if the file doesn't exist
87
+ if ( ( error as NodeJS . ErrnoException ) . code !== 'ENOENT' ) {
88
+ logger . error ( error , `Failed to delete predicate` ) ;
89
+ }
70
90
}
71
91
}
72
92
@@ -146,11 +166,15 @@ async function registerPredicate(
146
166
authorization_header : `Bearer ${ observer . auth_token } ` ,
147
167
} ,
148
168
} ;
149
- const newPredicate = pendingPredicate as Predicate ;
169
+ let newPredicate = pendingPredicate as Predicate ;
150
170
newPredicate . uuid = randomUUID ( ) ;
151
171
if ( newPredicate . networks . mainnet ) newPredicate . networks . mainnet . then_that = thenThat ;
152
172
if ( newPredicate . networks . testnet ) newPredicate . networks . testnet . then_that = thenThat ;
153
173
174
+ if ( observer . predicate_re_register_callback ) {
175
+ newPredicate = await observer . predicate_re_register_callback ( newPredicate ) ;
176
+ }
177
+
154
178
const path = observer . node_type === 'chainhook' ? `/v1/chainhooks` : `/v1/observers` ;
155
179
await request ( `${ chainhook . base_url } ${ path } ` , {
156
180
method : 'POST' ,
@@ -161,7 +185,7 @@ async function registerPredicate(
161
185
logger . info (
162
186
`ChainhookEventObserver registered '${ newPredicate . name } ' predicate (${ newPredicate . uuid } )`
163
187
) ;
164
- savePredicateToDisk ( observer . predicate_disk_file_path , newPredicate ) ;
188
+ await savePredicateToDisk ( observer . predicate_disk_file_path , newPredicate ) ;
165
189
RegisteredPredicates . set ( newPredicate . name , newPredicate ) ;
166
190
} catch ( error ) {
167
191
logger . error ( error , `ChainhookEventObserver unable to register predicate` ) ;
@@ -186,7 +210,7 @@ async function removePredicate(
186
210
throwOnError : true ,
187
211
} ) ;
188
212
logger . info ( `ChainhookEventObserver removed predicate '${ predicate . name } ' (${ predicate . uuid } )` ) ;
189
- deletePredicateFromDisk ( observer . predicate_disk_file_path , predicate ) ;
213
+ await deletePredicateFromDisk ( observer . predicate_disk_file_path , predicate ) ;
190
214
} catch ( error ) {
191
215
logger . error ( error , `ChainhookEventObserver unable to deregister predicate` ) ;
192
216
}
@@ -203,7 +227,7 @@ export async function registerAllPredicatesOnObserverReady(
203
227
logger . info ( `ChainhookEventObserver does not have predicates to register` ) ;
204
228
return ;
205
229
}
206
- const diskPredicates = recallPersistedPredicatesFromDisk ( observer . predicate_disk_file_path ) ;
230
+ const diskPredicates = await recallPersistedPredicatesFromDisk ( observer . predicate_disk_file_path ) ;
207
231
for ( const predicate of predicates )
208
232
await registerPredicate ( predicate , diskPredicates , observer , chainhook ) ;
209
233
}
@@ -213,7 +237,7 @@ export async function removeAllPredicatesOnObserverClose(
213
237
observer : EventObserverOptions ,
214
238
chainhook : ChainhookNodeOptions
215
239
) {
216
- const diskPredicates = recallPersistedPredicatesFromDisk ( observer . predicate_disk_file_path ) ;
240
+ const diskPredicates = await recallPersistedPredicatesFromDisk ( observer . predicate_disk_file_path ) ;
217
241
if ( diskPredicates . size === 0 ) {
218
242
logger . info ( `ChainhookEventObserver does not have predicates to close` ) ;
219
243
return ;
0 commit comments