@@ -12,17 +12,29 @@ use chainhook_event_observer::chainhooks::types::{
12
12
StacksChainhookFullSpecification , StacksChainhookNetworkSpecification , StacksPredicate ,
13
13
StacksPrintEventBasedPredicate ,
14
14
} ;
15
+ use chainhook_event_observer:: dashmap:: DashMap ;
16
+ use chainhook_event_observer:: fxhash:: FxBuildHasher ;
15
17
use chainhook_event_observer:: hord:: db:: {
16
18
delete_blocks_in_block_range_sqlite, delete_data_in_hord_db, fetch_and_cache_blocks_in_hord_db,
17
19
find_block_at_block_height, find_block_at_block_height_sqlite,
18
- find_inscriptions_at_wached_outpoint, find_last_block_inserted, initialize_hord_db,
19
- insert_entry_in_blocks, open_readonly_hord_db_conn, open_readonly_hord_db_conn_rocks_db,
20
- open_readwrite_hord_db_conn, open_readwrite_hord_db_conn_rocks_db,
21
- retrieve_satoshi_point_using_local_storage,
20
+ find_inscriptions_at_wached_outpoint, find_last_block_inserted,
21
+ find_watched_satpoint_for_inscription, initialize_hord_db, insert_entry_in_blocks,
22
+ open_readonly_hord_db_conn, open_readonly_hord_db_conn_rocks_db, open_readwrite_hord_db_conn,
23
+ open_readwrite_hord_db_conn_rocks_db, retrieve_satoshi_point_using_local_storage,
24
+ } ;
25
+ use chainhook_event_observer:: hord:: {
26
+ retrieve_inscribed_satoshi_points_from_block,
27
+ update_storage_and_augment_bitcoin_block_with_inscription_transfer_data, Storage ,
28
+ } ;
29
+ use chainhook_event_observer:: indexer;
30
+ use chainhook_event_observer:: indexer:: bitcoin:: {
31
+ download_and_parse_block_with_retry, retrieve_block_hash_with_retry,
22
32
} ;
23
33
use chainhook_event_observer:: observer:: BitcoinConfig ;
24
34
use chainhook_event_observer:: utils:: Context ;
25
- use chainhook_types:: { BitcoinNetwork , BlockIdentifier , StacksNetwork , TransactionIdentifier } ;
35
+ use chainhook_types:: {
36
+ BitcoinBlockData , BitcoinNetwork , BlockIdentifier , StacksNetwork , TransactionIdentifier ,
37
+ } ;
26
38
use clap:: { Parser , Subcommand } ;
27
39
use ctrlc;
28
40
use hiro_system_kit;
@@ -31,6 +43,7 @@ use std::io::{BufReader, Read};
31
43
use std:: path:: PathBuf ;
32
44
use std:: process;
33
45
use std:: sync:: mpsc:: Sender ;
46
+ use std:: sync:: Arc ;
34
47
35
48
#[ derive( Parser , Debug ) ]
36
49
#[ clap( author, version, about, long_about = None ) ]
@@ -186,7 +199,7 @@ enum HordCommand {
186
199
Db ( DbCommand ) ,
187
200
/// Db maintenance related commands
188
201
#[ clap( subcommand) ]
189
- Find ( FindCommand ) ,
202
+ Scan ( ScanCommand ) ,
190
203
}
191
204
192
205
#[ derive( Subcommand , PartialEq , Clone , Debug ) ]
@@ -212,21 +225,21 @@ enum DbCommand {
212
225
}
213
226
214
227
#[ derive( Subcommand , PartialEq , Clone , Debug ) ]
215
- enum FindCommand {
216
- /// Init hord db
217
- #[ clap( name = "satoshi " , bin_name = "satoshi " ) ]
218
- SatPoint ( FindSatPointCommand ) ,
219
- /// Update hord db
220
- #[ clap( name = "inscription " , bin_name = "inscription " ) ]
221
- Inscription ( FindInscriptionCommand ) ,
228
+ enum ScanCommand {
229
+ /// Compute ordinal number of the 1st satoshi of the 1st input of a given transaction
230
+ #[ clap( name = "inscriptions " , bin_name = "inscriptions " ) ]
231
+ Inscriptions ( ScanInscriptionsCommand ) ,
232
+ /// Retrieve all the transfers for a given inscription
233
+ #[ clap( name = "transfers " , bin_name = "transfers " ) ]
234
+ Transfers ( ScanTransfersCommand ) ,
222
235
}
223
236
224
237
#[ derive( Parser , PartialEq , Clone , Debug ) ]
225
- struct FindSatPointCommand {
238
+ struct ScanInscriptionsCommand {
226
239
/// Block height
227
240
pub block_height : u64 ,
228
241
/// Txid
229
- pub txid : String ,
242
+ pub txid : Option < String > ,
230
243
/// Target Devnet network
231
244
#[ clap(
232
245
long = "devnet" ,
@@ -259,12 +272,40 @@ struct FindSatPointCommand {
259
272
}
260
273
261
274
#[ derive( Parser , PartialEq , Clone , Debug ) ]
262
- struct FindInscriptionCommand {
263
- /// Outpoint
264
- pub outpoint : String ,
275
+ struct ScanTransfersCommand {
276
+ /// Inscription ID
277
+ pub inscription_id : String ,
278
+ /// Block height
279
+ pub block_height : Option < u64 > ,
280
+ /// Target Devnet network
281
+ #[ clap(
282
+ long = "devnet" ,
283
+ conflicts_with = "testnet" ,
284
+ conflicts_with = "mainnet"
285
+ ) ]
286
+ pub devnet : bool ,
287
+ /// Target Testnet network
288
+ #[ clap(
289
+ long = "testnet" ,
290
+ conflicts_with = "devnet" ,
291
+ conflicts_with = "mainnet"
292
+ ) ]
293
+ pub testnet : bool ,
294
+ /// Target Mainnet network
295
+ #[ clap(
296
+ long = "mainnet" ,
297
+ conflicts_with = "testnet" ,
298
+ conflicts_with = "devnet"
299
+ ) ]
300
+ pub mainnet : bool ,
265
301
/// Load config file path
266
- #[ clap( long = "db-path" ) ]
267
- pub db_path : Option < String > ,
302
+ #[ clap(
303
+ long = "config-path" ,
304
+ conflicts_with = "mainnet" ,
305
+ conflicts_with = "testnet" ,
306
+ conflicts_with = "devnet"
307
+ ) ]
308
+ pub config_path : Option < String > ,
268
309
}
269
310
270
311
#[ derive( Parser , PartialEq , Clone , Debug ) ]
@@ -569,8 +610,8 @@ async fn handle_command(opts: Opts, ctx: Context) -> Result<(), String> {
569
610
}
570
611
}
571
612
} ,
572
- Command :: Hord ( HordCommand :: Find ( subcmd) ) => match subcmd {
573
- FindCommand :: SatPoint ( cmd) => {
613
+ Command :: Hord ( HordCommand :: Scan ( subcmd) ) => match subcmd {
614
+ ScanCommand :: Inscriptions ( cmd) => {
574
615
let config =
575
616
Config :: default ( cmd. devnet , cmd. testnet , cmd. mainnet , & cmd. config_path ) ?;
576
617
@@ -583,12 +624,52 @@ async fn handle_command(opts: Opts, ctx: Context) -> Result<(), String> {
583
624
perform_hord_db_update ( tip_height, cmd. block_height , 8 , & config, & ctx) . await ?;
584
625
}
585
626
586
- let transaction_identifier = TransactionIdentifier {
587
- hash : cmd. txid . clone ( ) ,
588
- } ;
589
- let block_identifier = BlockIdentifier {
590
- index : cmd. block_height ,
591
- hash : "" . into ( ) ,
627
+ match cmd. txid {
628
+ Some ( txid) => {
629
+ // let global_block_cache = HashMap::new();
630
+ let block_identifier = BlockIdentifier {
631
+ index : cmd. block_height ,
632
+ hash : "" . into ( ) ,
633
+ } ;
634
+
635
+ let transaction_identifier = TransactionIdentifier { hash : txid. clone ( ) } ;
636
+ let hasher = FxBuildHasher :: default ( ) ;
637
+ let cache = Arc :: new ( DashMap :: with_hasher ( hasher) ) ;
638
+ let traversal = retrieve_satoshi_point_using_local_storage (
639
+ & hord_db_conn,
640
+ & block_identifier,
641
+ & transaction_identifier,
642
+ 0 ,
643
+ cache,
644
+ & ctx,
645
+ ) ?;
646
+ info ! (
647
+ ctx. expect_logger( ) ,
648
+ "Satoshi #{} was minted in block #{} at offset {} and was transferred {} times." ,
649
+ traversal. ordinal_number, traversal. get_ordinal_coinbase_height( ) , traversal. get_ordinal_coinbase_offset( ) , traversal. transfers
650
+ ) ;
651
+ }
652
+ None => {
653
+ let bitcoin_config =
654
+ config. get_event_observer_config ( ) . get_bitcoin_config ( ) ;
655
+ let block =
656
+ fetch_and_standardize_block ( cmd. block_height , & bitcoin_config, & ctx)
657
+ . await ?;
658
+ let traversals = retrieve_inscribed_satoshi_points_from_block (
659
+ & block,
660
+ None ,
661
+ & config. expected_cache_path ( ) ,
662
+ & ctx,
663
+ ) ;
664
+ // info!(
665
+ // ctx.expect_logger(),
666
+ // "Satoshi #{} was minted in block #{} at offset {} and was transferred {} times.",
667
+ // traversal.ordinal_number, traversal.get_ordinal_coinbase_height(), traversal.get_ordinal_coinbase_offset(), traversal.transfers
668
+ // );
669
+ }
670
+ }
671
+ }
672
+ ScanCommand :: Transfers ( cmd) => {
592
673
} ;
593
674
// let global_block_cache = HashMap::new();
594
675
let traversal = retrieve_satoshi_point_using_local_storage (
@@ -914,3 +995,15 @@ pub fn load_predicate_from_path(
914
995
. map_err ( |e| format ! ( "unable to parse json file {}\n {:?}" , predicate_path, e) ) ?;
915
996
Ok ( predicate)
916
997
}
998
+
999
+ pub async fn fetch_and_standardize_block (
1000
+ block_height : u64 ,
1001
+ bitcoin_config : & BitcoinConfig ,
1002
+ ctx : & Context ,
1003
+ ) -> Result < BitcoinBlockData , String > {
1004
+ let block_hash = retrieve_block_hash_with_retry ( & block_height, & bitcoin_config, & ctx) . await ?;
1005
+ let block_breakdown =
1006
+ download_and_parse_block_with_retry ( & block_hash, & bitcoin_config, & ctx) . await ?;
1007
+
1008
+ indexer:: bitcoin:: standardize_bitcoin_block ( block_breakdown, & bitcoin_config. network , & ctx)
1009
+ }
0 commit comments