@@ -47,32 +47,45 @@ struct Opts {
47
47
48
48
#[ derive( Subcommand , PartialEq , Clone , Debug ) ]
49
49
enum Command {
50
+ /// Manage predicates
51
+ #[ clap( subcommand) ]
52
+ Predicates ( PredicatesCommand ) ,
50
53
/// Start chainhook-cli
51
54
#[ clap( subcommand) ]
52
55
Node ( NodeCommand ) ,
53
56
/// Start chainhook-cli in replay mode
54
57
#[ clap( name = "replay" , bin_name = "replay" ) ]
55
58
Replay ( ReplayCommand ) ,
59
+ }
60
+
61
+ #[ derive( Subcommand , PartialEq , Clone , Debug ) ]
62
+ #[ clap( bin_name = "predicate" , aliases = & [ "predicate" ] ) ]
63
+ enum PredicatesCommand {
64
+ /// Generate new predicate
65
+ #[ clap( name = "new" , bin_name = "new" , aliases = & [ "generate" ] ) ]
66
+ New ( NewPredicate ) ,
56
67
/// Scan blocks (one-off) from specified network and apply provided predicate
57
68
#[ clap( name = "scan" , bin_name = "scan" ) ]
58
- Scan ( ScanCommand ) ,
69
+ Scan ( ScanPredicate ) ,
59
70
}
60
71
61
- #[ derive( Subcommand , PartialEq , Clone , Debug ) ]
62
- enum NodeCommand {
63
- /// Start chainhook-cli
64
- #[ clap( name = "start" , bin_name = "start" ) ]
65
- Start ( StartCommand ) ,
72
+ #[ derive( Parser , PartialEq , Clone , Debug ) ]
73
+ struct NewPredicate {
74
+ /// Predicate's name
75
+ pub name : String ,
76
+ /// Path to Clarinet.toml
77
+ #[ clap( long = "manifest-path" ) ]
78
+ pub manifest_path : Option < String > ,
79
+ /// Generate a Bitcoin chainhook
80
+ #[ clap( long = "bitcoin" , conflicts_with = "stacks" ) ]
81
+ pub bitcoin : bool ,
82
+ /// Generate a Stacks chainhook
83
+ #[ clap( long = "stacks" , conflicts_with = "bitcoin" ) ]
84
+ pub stacks : bool ,
66
85
}
67
86
68
87
#[ derive( Parser , PartialEq , Clone , Debug ) ]
69
- struct StartCommand {
70
- /// Target Devnet network
71
- #[ clap(
72
- long = "devnet" ,
73
- conflicts_with = "testnet" ,
74
- conflicts_with = "mainnet"
75
- ) ]
88
+ struct ScanPredicate {
76
89
pub devnet : bool ,
77
90
/// Target Testnet network
78
91
#[ clap(
@@ -96,10 +109,26 @@ struct StartCommand {
96
109
conflicts_with = "devnet"
97
110
) ]
98
111
pub config_path : Option < String > ,
112
+ /// Load chainhook file path (yaml format)
113
+ #[ clap( long = "predicate-path" , short = 'p' ) ]
114
+ pub chainhook_spec_path : String ,
115
+ }
116
+
117
+ #[ derive( Subcommand , PartialEq , Clone , Debug ) ]
118
+ enum NodeCommand {
119
+ /// Start chainhook-cli
120
+ #[ clap( name = "start" , bin_name = "start" ) ]
121
+ Start ( StartCommand ) ,
99
122
}
100
123
101
124
#[ derive( Parser , PartialEq , Clone , Debug ) ]
102
- struct ReplayCommand {
125
+ struct StartCommand {
126
+ /// Target Devnet network
127
+ #[ clap(
128
+ long = "devnet" ,
129
+ conflicts_with = "testnet" ,
130
+ conflicts_with = "mainnet"
131
+ ) ]
103
132
pub devnet : bool ,
104
133
/// Target Testnet network
105
134
#[ clap(
@@ -123,16 +152,10 @@ struct ReplayCommand {
123
152
conflicts_with = "devnet"
124
153
) ]
125
154
pub config_path : Option < String > ,
126
- /// Apply chainhook action (false by default)
127
- #[ clap( long = "apply-trigger" ) ]
128
- pub apply_trigger : bool ,
129
- /// Bitcoind node url override
130
- #[ clap( long = "bitcoind-rpc-url" ) ]
131
- pub bitcoind_rpc_url : Option < String > ,
132
155
}
133
156
134
157
#[ derive( Parser , PartialEq , Clone , Debug ) ]
135
- struct ScanCommand {
158
+ struct ReplayCommand {
136
159
pub devnet : bool ,
137
160
/// Target Testnet network
138
161
#[ clap(
@@ -156,12 +179,12 @@ struct ScanCommand {
156
179
conflicts_with = "devnet"
157
180
) ]
158
181
pub config_path : Option < String > ,
159
- /// Load chainhook file path (yaml format )
160
- #[ clap(
161
- long = "chainhook-spec-path" ,
162
- short = 'p'
163
- ) ]
164
- pub chainhook_spec_path : String ,
182
+ /// Apply chainhook action (false by default )
183
+ #[ clap( long = "apply-trigger" ) ]
184
+ pub apply_trigger : bool ,
185
+ /// Bitcoind node url override
186
+ # [ clap ( long = "bitcoind-rpc-url" ) ]
187
+ pub bitcoind_rpc_url : Option < String > ,
165
188
}
166
189
167
190
pub fn main ( ) {
@@ -194,6 +217,30 @@ pub fn main() {
194
217
start_node ( config, ctx) ;
195
218
}
196
219
} ,
220
+ Command :: Predicates ( subcmd) => match subcmd {
221
+ PredicatesCommand :: New ( cmd) => {
222
+ // Predicates can either be generated manually by letting developers
223
+ // craft their own json payload, or using the interactive approach.
224
+ // A list of contracts is displayed, then list of methods, then list of events detected
225
+ // 3 files are generated:
226
+ // predicates/simnet/name.json
227
+ // predicates/devnet/name.json
228
+ // predicates/testnet/name.json
229
+ // predicates/mainnet/name.json
230
+ let manifest = clarinet_files:: get_manifest_location ( None ) ;
231
+ }
232
+ PredicatesCommand :: Scan ( cmd) => {
233
+ let config =
234
+ match Config :: default ( cmd. devnet , cmd. testnet , cmd. mainnet , & cmd. config_path ) {
235
+ Ok ( config) => config,
236
+ Err ( e) => {
237
+ println ! ( "{e}" ) ;
238
+ process:: exit ( 1 ) ;
239
+ }
240
+ } ;
241
+ start_scan ( config, ctx) ;
242
+ }
243
+ } ,
197
244
Command :: Replay ( cmd) => {
198
245
let mut config =
199
246
match Config :: default ( cmd. devnet , cmd. testnet , cmd. mainnet , & cmd. config_path ) {
@@ -230,41 +277,28 @@ pub fn main() {
230
277
}
231
278
start_replay ( config, cmd. apply_trigger , ctx) ;
232
279
}
233
- Command :: Scan ( cmd) => {
234
- let config =
235
- match Config :: default ( cmd. devnet , cmd. testnet , cmd. mainnet , & cmd. config_path ) {
236
- Ok ( config) => config,
237
- Err ( e) => {
238
- println ! ( "{e}" ) ;
239
- process:: exit ( 1 ) ;
240
- }
241
- } ;
242
- start_scan ( config, ctx) ;
243
- }
244
280
}
245
281
}
246
282
247
-
248
283
pub fn install_ctrlc_handler ( terminate_tx : Sender < DigestingCommand > , ctx : Context ) {
249
284
ctrlc:: set_handler ( move || {
250
- warn ! (
251
- & ctx. expect_logger( ) ,
252
- "Manual interruption signal received"
253
- ) ;
285
+ warn ! ( & ctx. expect_logger( ) , "Manual interruption signal received" ) ;
254
286
terminate_tx
255
287
. send ( DigestingCommand :: Kill )
256
288
. expect ( "Unable to terminate service" ) ;
257
- } ) . expect ( "Error setting Ctrl-C handler" ) ;
289
+ } )
290
+ . expect ( "Error setting Ctrl-C handler" ) ;
258
291
}
259
292
260
-
261
293
pub fn download_dataset_if_required ( config : & mut Config , ctx : & Context ) -> bool {
262
294
if config. is_initial_ingestion_required ( ) {
263
295
// Download default tsv.
264
296
if config. rely_on_remote_tsv ( ) && config. should_download_remote_tsv ( ) {
265
297
let url = config. expected_remote_tsv_url ( ) ;
266
298
let mut destination_path = config. expected_cache_path ( ) ;
267
- destination_path. push ( archive:: default_tsv_file_path ( & config. network . stacks_network ) ) ;
299
+ destination_path. push ( archive:: default_tsv_file_path (
300
+ & config. network . stacks_network ,
301
+ ) ) ;
268
302
// Download archive if not already present in cache
269
303
if !destination_path. exists ( ) {
270
304
info ! ( ctx. expect_logger( ) , "Downloading {}" , url) ;
0 commit comments