@dignetwork/chia-block-listener 0.1.9 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +374 -11
  2. package/crate/chia-generator-parser/src/parser.rs +52 -34
  3. package/crate/chia-generator-parser/src/types.rs +25 -117
  4. package/examples/basic-connection-test.js +55 -0
  5. package/examples/block-refusal-test.js +251 -0
  6. package/examples/failover-demo.js +225 -0
  7. package/examples/failover-test.js +122 -0
  8. package/examples/historical-coin-monitor.js +308 -0
  9. package/examples/optimized-performance-test.js +267 -0
  10. package/examples/peer-disconnection-test.js +232 -0
  11. package/examples/peer-discovery-performance-test.js +345 -0
  12. package/examples/peer-pool-events-example.js +164 -0
  13. package/examples/peer-pool-example.js +151 -0
  14. package/examples/peer-pool-parallel-demo.js +61 -0
  15. package/examples/peer-pool-peak-tracking.js +179 -0
  16. package/examples/peer-pool-performance-test.js +274 -0
  17. package/examples/port-test.js +55 -0
  18. package/examples/quick-performance-test.js +112 -0
  19. package/examples/simple-performance-test.js +83 -0
  20. package/examples/test-connection-diagnostic.js +267 -0
  21. package/examples/test-peak-height.js +99 -0
  22. package/index.d.ts +11 -0
  23. package/index.js +2 -1
  24. package/npm/darwin-arm64/package.json +1 -1
  25. package/npm/darwin-x64/package.json +1 -1
  26. package/npm/linux-arm64-gnu/package.json +1 -1
  27. package/npm/linux-x64-gnu/package.json +1 -1
  28. package/npm/win32-x64-msvc/package.json +1 -1
  29. package/package.json +6 -6
  30. package/src/error.rs +15 -8
  31. package/src/event_emitter.rs +21 -14
  32. package/src/lib.rs +17 -4
  33. package/src/peer.rs +9 -9
  34. package/src/peer_pool.rs +971 -0
  35. package/src/peer_pool_napi.rs +221 -0
  36. package/src/protocol.rs +46 -39
  37. package/src/tls.rs +4 -4
package/README.md CHANGED
@@ -6,10 +6,15 @@ A high-performance Chia blockchain listener for Node.js, built with Rust and NAP
6
6
 
7
7
  - **Real-time Block Monitoring**: Listen for new blocks as they're produced on the Chia network
8
8
  - **Peer Management**: Connect to multiple Chia full nodes simultaneously
9
+ - **Automatic Failover**: Intelligent peer failover with automatic retry across multiple peers
10
+ - **Enhanced Error Handling**: Automatic disconnection of peers that refuse blocks or have protocol errors
9
11
  - **Efficient Parsing**: Fast extraction of coin spends, additions, and removals from blocks
10
12
  - **Event-Driven Architecture**: TypeScript-friendly event system with full type safety
11
13
  - **Transaction Analysis**: Parse CLVM puzzles and solutions from coin spends
12
- - **Historical Block Access**: Retrieve blocks by height or ranges
14
+ - **Historical Block Access**: Retrieve blocks by height or ranges with automatic load balancing
15
+ - **Connection Pool**: ChiaPeerPool provides automatic load balancing and rate limiting for historical queries
16
+ - **Peak Height Tracking**: Monitor blockchain sync progress across all connected peers
17
+ - **DNS Peer Discovery**: Automatic peer discovery using Chia network DNS introducers
13
18
  - **Cross-platform Support**: Works on Windows, macOS, and Linux (x64 and ARM64)
14
19
  - **TypeScript Support**: Complete TypeScript definitions with IntelliSense
15
20
 
@@ -33,11 +38,11 @@ const listener = new ChiaBlockListener()
33
38
  // Listen for block events
34
39
  listener.on('blockReceived', (block) => {
35
40
  console.log(`New block received: ${block.height}`)
36
- console.log(`Header hash: ${block.header_hash}`)
41
+ console.log(`Header hash: ${block.headerHash}`)
37
42
  console.log(`Timestamp: ${new Date(block.timestamp * 1000)}`)
38
- console.log(`Coin additions: ${block.coin_additions.length}`)
39
- console.log(`Coin removals: ${block.coin_removals.length}`)
40
- console.log(`Coin spends: ${block.coin_spends.length}`)
43
+ console.log(`Coin additions: ${block.coinAdditions.length}`)
44
+ console.log(`Coin removals: ${block.coinRemovals.length}`)
45
+ console.log(`Coin spends: ${block.coinSpends.length}`)
41
46
  })
42
47
 
43
48
  // Listen for peer connection events
@@ -64,6 +69,30 @@ process.on('SIGINT', () => {
64
69
  })
65
70
  ```
66
71
 
72
+ ## Recent Enhancements 🚀
73
+
74
+ This library includes several powerful enhancements for production use:
75
+
76
+ ### Automatic Failover System
77
+ - **Intelligent Retry Logic**: Automatically tries up to 3 different peers when block requests fail
78
+ - **Smart Peer Selection**: Chooses the best available peer for each request based on response times
79
+ - **Transparent Operation**: Failover happens automatically without user intervention
80
+
81
+ ### Enhanced Error Handling
82
+ - **Protocol Error Detection**: Automatically detects and disconnects peers that refuse blocks or send invalid data
83
+ - **Connection Health Monitoring**: Tracks peer connection health and removes problematic peers
84
+ - **Error Classification**: Distinguishes between temporary issues and permanent peer problems
85
+
86
+ ### Performance Optimizations
87
+ - **Aggressive Rate Limiting**: 50ms rate limiting per peer for maximum throughput
88
+ - **Persistent Connections**: Reuses WebSocket connections for optimal performance
89
+ - **Parallel Processing**: Efficient handling of multiple concurrent block requests
90
+
91
+ ### Developer Experience
92
+ - **camelCase API**: All JavaScript methods use proper camelCase naming conventions
93
+ - **Comprehensive Events**: Detailed event system for monitoring peer lifecycle and errors
94
+ - **TypeScript Support**: Full type safety with complete TypeScript definitions
95
+
67
96
  ## API Reference
68
97
 
69
98
  ### ChiaBlockListener Class
@@ -127,6 +156,80 @@ Retrieves a range of blocks from a connected peer.
127
156
 
128
157
  **Returns:** An array of `BlockReceivedEvent` objects
129
158
 
159
+ ### ChiaPeerPool Class
160
+
161
+ The `ChiaPeerPool` provides a managed pool of peer connections for retrieving historical blocks with automatic load balancing and intelligent failover across multiple peers. When a peer fails to provide a block or experiences protocol errors, the pool automatically tries alternative peers and removes problematic peers from the pool.
162
+
163
+ #### Constructor
164
+
165
+ ```javascript
166
+ const pool = new ChiaPeerPool()
167
+ ```
168
+
169
+ Creates a new peer pool instance with built-in rate limiting (500ms per peer).
170
+
171
+ #### Methods
172
+
173
+ ##### `addPeer(host, port, networkId): Promise<string>`
174
+
175
+ Adds a peer to the connection pool.
176
+
177
+ **Parameters:**
178
+ - `host` (string): The hostname or IP address of the Chia node
179
+ - `port` (number): The port number (typically 8444 for mainnet)
180
+ - `networkId` (string): The network identifier ('mainnet', 'testnet', etc.)
181
+
182
+ **Returns:** A Promise that resolves to a unique peer ID string
183
+
184
+ ##### `getBlockByHeight(height): Promise<BlockReceivedEvent>`
185
+
186
+ Retrieves a specific block by height using automatic peer selection and load balancing.
187
+
188
+ **Parameters:**
189
+ - `height` (number): The block height to retrieve
190
+
191
+ **Returns:** A Promise that resolves to a `BlockReceivedEvent` object
192
+
193
+ ##### `removePeer(peerId): Promise<boolean>`
194
+
195
+ Removes a peer from the pool.
196
+
197
+ **Parameters:**
198
+ - `peerId` (string): The peer ID to remove
199
+
200
+ **Returns:** A Promise that resolves to `true` if the peer was removed, `false` otherwise
201
+
202
+ ##### `shutdown(): Promise<void>`
203
+
204
+ Shuts down the pool and disconnects all peers.
205
+
206
+ ##### `getConnectedPeers(): Promise<string[]>`
207
+
208
+ Gets the list of currently connected peer IDs.
209
+
210
+ **Returns:** Array of peer ID strings (format: "host:port")
211
+
212
+ ##### `getPeakHeight(): Promise<number | null>`
213
+
214
+ Gets the highest blockchain peak height seen across all connected peers.
215
+
216
+ **Returns:** The highest peak height as a number, or null if no peaks have been received yet
217
+
218
+ ##### `on(event, callback): void`
219
+
220
+ Registers an event handler for pool events.
221
+
222
+ **Parameters:**
223
+ - `event` (string): The event name ('peerConnected' or 'peerDisconnected')
224
+ - `callback` (function): The event handler function
225
+
226
+ ##### `off(event, callback): void`
227
+
228
+ Removes an event handler.
229
+
230
+ **Parameters:**
231
+ - `event` (string): The event name to stop listening for
232
+
130
233
  ### Events
131
234
 
132
235
  The `ChiaBlockListener` emits the following events:
@@ -149,6 +252,28 @@ Fired when a peer connection is lost.
149
252
 
150
253
  **Callback:** `(event: PeerDisconnectedEvent) => void`
151
254
 
255
+ ### ChiaPeerPool Events
256
+
257
+ The `ChiaPeerPool` emits the following events:
258
+
259
+ #### `peerConnected`
260
+
261
+ Fired when a peer is successfully added to the pool.
262
+
263
+ **Callback:** `(event: PeerConnectedEvent) => void`
264
+
265
+ #### `peerDisconnected`
266
+
267
+ Fired when a peer is removed from the pool or disconnects.
268
+
269
+ **Callback:** `(event: PeerDisconnectedEvent) => void`
270
+
271
+ #### `newPeakHeight`
272
+
273
+ Fired when a new highest blockchain peak is discovered.
274
+
275
+ **Callback:** `(event: NewPeakHeightEvent) => void`
276
+
152
277
  ### Event Data Types
153
278
 
154
279
  #### `BlockReceivedEvent`
@@ -190,6 +315,16 @@ interface PeerDisconnectedEvent {
190
315
  }
191
316
  ```
192
317
 
318
+ #### `NewPeakHeightEvent`
319
+
320
+ ```typescript
321
+ interface NewPeakHeightEvent {
322
+ oldPeak: number | null // Previous highest peak (null if first peak)
323
+ newPeak: number // New highest peak height
324
+ peerId: string // Peer that discovered this peak
325
+ }
326
+ ```
327
+
193
328
  #### `CoinRecord`
194
329
 
195
330
  ```typescript
@@ -211,14 +346,219 @@ interface CoinSpend {
211
346
  }
212
347
  ```
213
348
 
349
+ ## ChiaPeerPool Usage
350
+
351
+ The `ChiaPeerPool` is designed for efficiently retrieving historical blocks with automatic load balancing and intelligent failover across multiple peers. When a peer fails to provide a block or experiences protocol errors, the pool automatically tries alternative peers and removes problematic peers from the pool.
352
+
353
+ ### Basic Usage
354
+
355
+ ```javascript
356
+ const { ChiaPeerPool, initTracing } = require('@dignetwork/chia-block-listener')
357
+
358
+ async function main() {
359
+ // Initialize tracing
360
+ initTracing()
361
+
362
+ // Create a peer pool
363
+ const pool = new ChiaPeerPool()
364
+
365
+ // Listen for pool events
366
+ pool.on('peerConnected', (event) => {
367
+ console.log(`Peer connected to pool: ${event.peerId}`)
368
+ })
369
+
370
+ pool.on('peerDisconnected', (event) => {
371
+ console.log(`Peer disconnected from pool: ${event.peerId}`)
372
+ })
373
+
374
+ pool.on('newPeakHeight', (event) => {
375
+ console.log(`New blockchain peak detected!`)
376
+ console.log(` Previous: ${event.oldPeak || 'None'}`)
377
+ console.log(` New: ${event.newPeak}`)
378
+ console.log(` Discovered by: ${event.peerId}`)
379
+ })
380
+
381
+ // Add multiple peers
382
+ await pool.addPeer('node1.chia.net', 8444, 'mainnet')
383
+ await pool.addPeer('node2.chia.net', 8444, 'mainnet')
384
+ await pool.addPeer('node3.chia.net', 8444, 'mainnet')
385
+
386
+ // Fetch blocks with automatic load balancing
387
+ const block1 = await pool.getBlockByHeight(5000000)
388
+ const block2 = await pool.getBlockByHeight(5000001)
389
+ const block3 = await pool.getBlockByHeight(5000002)
390
+
391
+ console.log(`Block ${block1.height}: ${block1.coinSpends.length} spends`)
392
+ console.log(`Block ${block2.height}: ${block2.coinSpends.length} spends`)
393
+ console.log(`Block ${block3.height}: ${block3.coinSpends.length} spends`)
394
+
395
+ // Shutdown the pool
396
+ await pool.shutdown()
397
+ }
398
+
399
+ main().catch(console.error)
400
+ ```
401
+
402
+ ### Advanced Pool Features
403
+
404
+ #### Rate Limiting
405
+
406
+ The pool automatically enforces a 50ms rate limit per peer for maximum performance while preventing node overload:
407
+
408
+ ```javascript
409
+ // Rapid requests are automatically queued and distributed
410
+ const promises = []
411
+ for (let i = 5000000; i < 5000100; i++) {
412
+ promises.push(pool.getBlockByHeight(i))
413
+ }
414
+
415
+ // All requests will be processed efficiently across all peers
416
+ // with automatic load balancing and rate limiting
417
+ const blocks = await Promise.all(promises)
418
+ console.log(`Retrieved ${blocks.length} blocks`)
419
+ ```
420
+
421
+ #### Automatic Failover and Error Handling
422
+
423
+ The pool provides robust error handling with automatic failover:
424
+
425
+ ```javascript
426
+ // The pool automatically handles various error scenarios:
427
+
428
+ // 1. Connection failures - automatically tries other peers
429
+ try {
430
+ const block = await pool.getBlockByHeight(5000000)
431
+ console.log(`Retrieved block ${block.height}`)
432
+ } catch (error) {
433
+ // If all peers fail, you'll get an error after all retry attempts
434
+ console.error('All peers failed:', error.message)
435
+ }
436
+
437
+ // 2. Protocol errors - peers that refuse blocks are automatically disconnected
438
+ pool.on('peerDisconnected', (event) => {
439
+ console.log(`Peer ${event.peerId} disconnected: ${event.reason}`)
440
+ // Reasons include: "Block request rejected", "Protocol error", "Connection timeout"
441
+ })
442
+
443
+ // 3. Automatic peer cleanup - problematic peers are removed from the pool
444
+ console.log('Active peers before:', await pool.getConnectedPeers())
445
+ await pool.getBlockByHeight(5000000) // May trigger peer removal
446
+ console.log('Active peers after:', await pool.getConnectedPeers())
447
+
448
+ // 4. Multiple retry attempts - tries up to 3 different peers per request
449
+ // This happens automatically and transparently
450
+ const block = await pool.getBlockByHeight(5000000) // Will try multiple peers if needed
451
+ ```
452
+
453
+ **Error Types Handled Automatically:**
454
+ - **Connection Errors**: Timeouts, network failures, WebSocket errors
455
+ - **Protocol Errors**: Block rejections, parsing failures, handshake failures
456
+ - **Peer Misbehavior**: Unexpected responses, invalid data formats
457
+
458
+ #### Dynamic Peer Management
459
+
460
+ ```javascript
461
+ // Monitor pool health
462
+ const peers = await pool.getConnectedPeers()
463
+ console.log(`Active peers in pool: ${peers.length}`)
464
+
465
+ // Remove underperforming peers
466
+ if (slowPeer) {
467
+ await pool.removePeer(slowPeer)
468
+ console.log('Removed slow peer from pool')
469
+ }
470
+
471
+ // Add new peers dynamically
472
+ if (peers.length < 3) {
473
+ await pool.addPeer('backup-node.chia.net', 8444, 'mainnet')
474
+ }
475
+ ```
476
+
477
+ #### Error Handling
478
+
479
+ ```javascript
480
+ try {
481
+ const block = await pool.getBlockByHeight(5000000)
482
+ console.log(`Retrieved block ${block.height}`)
483
+ } catch (error) {
484
+ console.error('Failed to retrieve block:', error)
485
+
486
+ // The pool will automatically try other peers
487
+ // You can also add more peers if needed
488
+ const peers = await pool.getConnectedPeers()
489
+ if (peers.length === 0) {
490
+ console.log('No peers available, adding new ones...')
491
+ await pool.addPeer('node1.chia.net', 8444, 'mainnet')
492
+ }
493
+ }
494
+ ```
495
+
496
+ #### Peak Height Tracking
497
+
498
+ ```javascript
499
+ // Monitor blockchain sync progress
500
+ const pool = new ChiaPeerPool()
501
+
502
+ // Track peak changes
503
+ let currentPeak = null
504
+ pool.on('newPeakHeight', (event) => {
505
+ currentPeak = event.newPeak
506
+ const progress = event.oldPeak
507
+ ? `+${event.newPeak - event.oldPeak} blocks`
508
+ : 'Initial peak'
509
+ console.log(`Peak update: ${event.newPeak} (${progress})`)
510
+ })
511
+
512
+ // Add peers
513
+ await pool.addPeer('node1.chia.net', 8444, 'mainnet')
514
+ await pool.addPeer('node2.chia.net', 8444, 'mainnet')
515
+
516
+ // Check current peak
517
+ const peak = await pool.getPeakHeight()
518
+ console.log(`Current highest peak: ${peak || 'None yet'}`)
519
+
520
+ // Fetch some blocks to trigger peak updates
521
+ await pool.getBlockByHeight(5000000)
522
+ await pool.getBlockByHeight(5100000)
523
+ await pool.getBlockByHeight(5200000)
524
+
525
+ // Monitor sync status
526
+ setInterval(async () => {
527
+ const peak = await pool.getPeakHeight()
528
+ if (peak) {
529
+ const estimatedCurrent = 5200000 + Math.floor((Date.now() / 1000 - 1700000000) / 18.75)
530
+ const syncPercentage = (peak / estimatedCurrent * 100).toFixed(2)
531
+ console.log(`Sync status: ${syncPercentage}% (peak: ${peak})`)
532
+ }
533
+ }, 60000) // Check every minute
534
+ ```
535
+
536
+ ### When to Use ChiaPeerPool vs ChiaBlockListener
537
+
538
+ - **Use ChiaPeerPool when:**
539
+ - You need to fetch historical blocks
540
+ - You want automatic load balancing across multiple peers
541
+ - You're making many block requests and need rate limiting
542
+ - You don't need real-time block notifications
543
+
544
+ - **Use ChiaBlockListener when:**
545
+ - You need real-time notifications of new blocks
546
+ - You want to monitor the blockchain as it grows
547
+ - You need to track specific addresses or puzzle hashes in real-time
548
+ - You're building applications that react to blockchain events
549
+
550
+ Both classes can be used together in the same application for different purposes.
551
+
214
552
  ## TypeScript Usage
215
553
 
216
554
  ```typescript
217
555
  import {
218
556
  ChiaBlockListener,
557
+ ChiaPeerPool,
219
558
  BlockReceivedEvent,
220
559
  PeerConnectedEvent,
221
560
  PeerDisconnectedEvent,
561
+ NewPeakHeightEvent,
222
562
  CoinRecord,
223
563
  CoinSpend,
224
564
  initTracing,
@@ -236,14 +576,14 @@ listener.on('blockReceived', (block: BlockReceivedEvent) => {
236
576
  console.log(`Block ${block.height} from peer ${block.peerId}`)
237
577
 
238
578
  // Process coin additions
239
- block.coin_additions.forEach((coin: CoinRecord) => {
579
+ block.coinAdditions.forEach((coin: CoinRecord) => {
240
580
  console.log(`New coin: ${coin.amount} mojos`)
241
581
  })
242
582
 
243
583
  // Process coin spends
244
- block.coin_spends.forEach((spend: CoinSpend) => {
584
+ block.coinSpends.forEach((spend: CoinSpend) => {
245
585
  console.log(`Spend: ${spend.coin.amount} mojos`)
246
- console.log(`Puzzle: ${spend.puzzle_reveal}`)
586
+ console.log(`Puzzle: ${spend.puzzleReveal}`)
247
587
  console.log(`Solution: ${spend.solution}`)
248
588
  })
249
589
  })
@@ -267,7 +607,7 @@ const testnetPeer = listener.addPeer('testnet-node.chia.net', 58444, 'testnet')
267
607
  async function getHistoricalBlocks() {
268
608
  try {
269
609
  const block = listener.getBlockByHeight(mainnetPeer, 1000000)
270
- console.log(`Block 1000000 hash: ${block.header_hash}`)
610
+ console.log(`Block 1000000 hash: ${block.headerHash}`)
271
611
 
272
612
  const blocks = listener.getBlocksRange(mainnetPeer, 1000000, 1000010)
273
613
  console.log(`Retrieved ${blocks.length} blocks`)
@@ -279,6 +619,29 @@ async function getHistoricalBlocks() {
279
619
  // Get event type constants
280
620
  const eventTypes = getEventTypes()
281
621
  console.log('Available events:', eventTypes)
622
+
623
+ // TypeScript support for ChiaPeerPool
624
+ const pool = new ChiaPeerPool()
625
+
626
+ // Type-safe event handling
627
+ pool.on('peerConnected', (event: PeerConnectedEvent) => {
628
+ console.log(`Pool peer connected: ${event.peerId}`)
629
+ })
630
+
631
+ pool.on('newPeakHeight', (event: NewPeakHeightEvent) => {
632
+ console.log(`New peak: ${event.oldPeak} → ${event.newPeak}`)
633
+ })
634
+
635
+ // Async/await with proper typing
636
+ async function fetchHistoricalData() {
637
+ const block: BlockReceivedEvent = await pool.getBlockByHeight(5000000)
638
+ const peers: string[] = await pool.getConnectedPeers()
639
+ const peak: number | null = await pool.getPeakHeight()
640
+
641
+ console.log(`Block ${block.height} has ${block.coinSpends.length} spends`)
642
+ console.log(`Pool has ${peers.length} active peers`)
643
+ console.log(`Current peak: ${peak || 'No peak yet'}`)
644
+ }
282
645
  ```
283
646
 
284
647
  ## Advanced Usage
@@ -290,8 +653,8 @@ console.log('Available events:', eventTypes)
290
653
  listener.on('blockReceived', (block) => {
291
654
  const targetPuzzleHash = '0x1234...' // Your puzzle hash
292
655
 
293
- block.coin_spends.forEach((spend) => {
294
- if (spend.coin.puzzle_hash === targetPuzzleHash) {
656
+ block.coinSpends.forEach((spend) => {
657
+ if (spend.coin.puzzleHash === targetPuzzleHash) {
295
658
  console.log('Found spend for our puzzle!')
296
659
  console.log('Amount:', spend.coin.amount)
297
660
  console.log('Solution:', spend.solution)
@@ -1,9 +1,6 @@
1
1
  use crate::{
2
2
  error::{GeneratorParserError, Result},
3
- types::{
4
- BlockHeightInfo, CoinInfo, CoinSpendInfo, GeneratorAnalysis, GeneratorBlockInfo,
5
- ParsedBlock, ParsedGenerator,
6
- },
3
+ types::{BlockHeightInfo, CoinInfo, CoinSpendInfo, GeneratorBlockInfo, ParsedBlock},
7
4
  };
8
5
  use chia_bls::Signature;
9
6
  use chia_consensus::{
@@ -14,7 +11,7 @@ use chia_consensus::{
14
11
  run_block_generator::{run_block_generator2, setup_generator_args},
15
12
  validation_error::{atom, first, next, rest, ErrorCode},
16
13
  };
17
- use chia_protocol::{Bytes32, FullBlock};
14
+ use chia_protocol::FullBlock;
18
15
  use chia_traits::streamable::Streamable;
19
16
  use clvm_utils::tree_hash;
20
17
  use clvmr::{
@@ -63,7 +60,7 @@ impl BlockParser {
63
60
  .map(|g| g.len() as u32);
64
61
 
65
62
  // Extract generator info
66
- let generator_info = block
63
+ let _generator_info = block
67
64
  .transactions_generator
68
65
  .as_ref()
69
66
  .map(|gen| GeneratorBlockInfo {
@@ -101,7 +98,6 @@ impl BlockParser {
101
98
  coin_creations,
102
99
  has_transactions_generator,
103
100
  generator_size,
104
- generator_info,
105
101
  })
106
102
  }
107
103
 
@@ -373,15 +369,15 @@ impl BlockParser {
373
369
  // Get created coins from conditions
374
370
  let created_coins = self.extract_created_coins(spend_index, spend_bundle_conditions);
375
371
 
376
- Some(CoinSpendInfo {
377
- coin: coin_info,
378
- puzzle_reveal,
379
- solution: solution_bytes,
380
- real_data: true,
381
- parsing_method: "clvm_execution".to_string(),
382
- offset: 0,
372
+ Some(CoinSpendInfo::new(
373
+ coin_info,
374
+ hex::encode(puzzle_reveal),
375
+ hex::encode(solution_bytes),
376
+ true,
377
+ "From transaction generator".to_string(),
378
+ 0,
383
379
  created_coins,
384
- })
380
+ ))
385
381
  }
386
382
 
387
383
  /// Extract parent coin info from a coin spend node
@@ -464,42 +460,62 @@ impl BlockParser {
464
460
  })
465
461
  }
466
462
 
463
+ /*
467
464
  /// Parse generator from hex string
468
465
  pub fn parse_generator_from_hex(&self, generator_hex: &str) -> Result<ParsedGenerator> {
469
466
  let generator_bytes =
470
- hex::decode(generator_hex).map_err(|e| GeneratorParserError::HexDecodingError(e))?;
467
+ hex::decode(generator_hex).map_err(|e| ParseError::HexDecodingError(e))?;
471
468
  self.parse_generator_from_bytes(&generator_bytes)
472
469
  }
473
470
 
474
471
  /// Parse generator from bytes
475
472
  pub fn parse_generator_from_bytes(&self, generator_bytes: &[u8]) -> Result<ParsedGenerator> {
476
- let analysis = self.analyze_generator(generator_bytes)?;
477
-
473
+ // Create a dummy GeneratorBlockInfo for now
478
474
  Ok(ParsedGenerator {
479
- block_info: GeneratorBlockInfo {
480
- prev_header_hash: Bytes32::default(),
481
- transactions_generator: Some(generator_bytes.to_vec()),
482
- transactions_generator_ref_list: Vec::new(),
483
- },
475
+ block_info: GeneratorBlockInfo::new(
476
+ [0u8; 32].into(),
477
+ Some(generator_bytes.to_vec()),
478
+ vec![],
479
+ ),
484
480
  generator_hex: Some(hex::encode(generator_bytes)),
485
- analysis,
481
+ analysis: self.analyze_generator(generator_bytes)?,
486
482
  })
487
483
  }
488
484
 
489
485
  /// Analyze generator bytecode
490
486
  pub fn analyze_generator(&self, generator_bytes: &[u8]) -> Result<GeneratorAnalysis> {
491
487
  let size_bytes = generator_bytes.len();
492
- let is_empty = size_bytes == 0;
493
-
494
- // Check for CLVM patterns
495
- let contains_clvm_patterns = generator_bytes
496
- .windows(2)
497
- .any(|w| matches!(w, [0xff, _] | [_, 0xff]));
498
-
499
- // Check for coin patterns (CREATE_COIN opcode)
500
- let contains_coin_patterns = generator_bytes.windows(1).any(|w| w[0] == 0x33);
488
+ let is_empty = generator_bytes.is_empty();
489
+
490
+ // Check for common CLVM patterns
491
+ let contains_clvm_patterns = generator_bytes.windows(2).any(|w| {
492
+ w == [0x01, 0x00] || // pair
493
+ w == [0x02, 0x00] || // cons
494
+ w == [0x03, 0x00] || // first
495
+ w == [0x04, 0x00] // rest
496
+ });
497
+
498
+ // Check for coin patterns (32-byte sequences)
499
+ let contains_coin_patterns = generator_bytes.len() >= 32;
500
+
501
+ // Calculate simple entropy
502
+ let mut byte_counts = [0u64; 256];
503
+ for &byte in generator_bytes {
504
+ byte_counts[byte as usize] += 1;
505
+ }
501
506
 
502
- let entropy = self.calculate_entropy(generator_bytes);
507
+ let total = generator_bytes.len() as f64;
508
+ let entropy = if total > 0.0 {
509
+ byte_counts.iter()
510
+ .filter(|&&count| count > 0)
511
+ .map(|&count| {
512
+ let p = count as f64 / total;
513
+ -p * p.log2()
514
+ })
515
+ .sum()
516
+ } else {
517
+ 0.0
518
+ };
503
519
 
504
520
  Ok(GeneratorAnalysis {
505
521
  size_bytes,
@@ -509,8 +525,10 @@ impl BlockParser {
509
525
  entropy,
510
526
  })
511
527
  }
528
+ */
512
529
 
513
530
  /// Calculate Shannon entropy of data
531
+ #[allow(dead_code)]
514
532
  fn calculate_entropy(&self, data: &[u8]) -> f64 {
515
533
  if data.is_empty() {
516
534
  return 0.0;