Skip to content

Commit 611c79c

Browse files
author
Ludo Galabru
committed
feat: introduce new predicate + refactor schemas
1 parent fcb87b6 commit 611c79c

File tree

5 files changed

+220
-150
lines changed

5 files changed

+220
-150
lines changed

components/chainhook-cli/src/cli/mod.rs

+80-46
Original file line numberDiff line numberDiff line change
@@ -47,32 +47,45 @@ struct Opts {
4747

4848
#[derive(Subcommand, PartialEq, Clone, Debug)]
4949
enum Command {
50+
/// Manage predicates
51+
#[clap(subcommand)]
52+
Predicates(PredicatesCommand),
5053
/// Start chainhook-cli
5154
#[clap(subcommand)]
5255
Node(NodeCommand),
5356
/// Start chainhook-cli in replay mode
5457
#[clap(name = "replay", bin_name = "replay")]
5558
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),
5667
/// Scan blocks (one-off) from specified network and apply provided predicate
5768
#[clap(name = "scan", bin_name = "scan")]
58-
Scan(ScanCommand),
69+
Scan(ScanPredicate),
5970
}
6071

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,
6685
}
6786

6887
#[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 {
7689
pub devnet: bool,
7790
/// Target Testnet network
7891
#[clap(
@@ -96,10 +109,26 @@ struct StartCommand {
96109
conflicts_with = "devnet"
97110
)]
98111
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),
99122
}
100123

101124
#[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+
)]
103132
pub devnet: bool,
104133
/// Target Testnet network
105134
#[clap(
@@ -123,16 +152,10 @@ struct ReplayCommand {
123152
conflicts_with = "devnet"
124153
)]
125154
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>,
132155
}
133156

134157
#[derive(Parser, PartialEq, Clone, Debug)]
135-
struct ScanCommand {
158+
struct ReplayCommand {
136159
pub devnet: bool,
137160
/// Target Testnet network
138161
#[clap(
@@ -156,12 +179,12 @@ struct ScanCommand {
156179
conflicts_with = "devnet"
157180
)]
158181
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>,
165188
}
166189

167190
pub fn main() {
@@ -194,6 +217,30 @@ pub fn main() {
194217
start_node(config, ctx);
195218
}
196219
},
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+
},
197244
Command::Replay(cmd) => {
198245
let mut config =
199246
match Config::default(cmd.devnet, cmd.testnet, cmd.mainnet, &cmd.config_path) {
@@ -230,41 +277,28 @@ pub fn main() {
230277
}
231278
start_replay(config, cmd.apply_trigger, ctx);
232279
}
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-
}
244280
}
245281
}
246282

247-
248283
pub fn install_ctrlc_handler(terminate_tx: Sender<DigestingCommand>, ctx: Context) {
249284
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");
254286
terminate_tx
255287
.send(DigestingCommand::Kill)
256288
.expect("Unable to terminate service");
257-
}).expect("Error setting Ctrl-C handler");
289+
})
290+
.expect("Error setting Ctrl-C handler");
258291
}
259292

260-
261293
pub fn download_dataset_if_required(config: &mut Config, ctx: &Context) -> bool {
262294
if config.is_initial_ingestion_required() {
263295
// Download default tsv.
264296
if config.rely_on_remote_tsv() && config.should_download_remote_tsv() {
265297
let url = config.expected_remote_tsv_url();
266298
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+
));
268302
// Download archive if not already present in cache
269303
if !destination_path.exists() {
270304
info!(ctx.expect_logger(), "Downloading {}", url);

0 commit comments

Comments
 (0)