@dignetwork/chia-block-listener 0.1.14 → 0.1.16
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.
- package/Cargo.toml +1 -0
- package/DNS_DISCOVERY_USAGE.md +291 -0
- package/README.md +263 -1
- package/crate/dns-discovery/Cargo.toml +16 -0
- package/crate/dns-discovery/README.md +151 -0
- package/crate/dns-discovery/examples/discover_peers.rs +84 -0
- package/crate/dns-discovery/package-lock.json +2382 -0
- package/crate/dns-discovery/src/lib.rs +325 -0
- package/dns-discovery.d.ts +84 -0
- package/examples/dns-discovery-example.js +165 -0
- package/index.d.ts +44 -2
- package/index.js +2 -1
- package/npm/darwin-arm64/package.json +1 -1
- package/npm/darwin-x64/package.json +1 -1
- package/npm/linux-arm64-gnu/package.json +1 -1
- package/npm/linux-x64-gnu/package.json +1 -1
- package/npm/win32-x64-msvc/package.json +1 -1
- package/package.json +6 -6
- package/src/dns_discovery_napi.rs +227 -0
- package/src/lib.rs +2 -0
- package/src/peer.rs +4 -2
- package/src/peer_pool.rs +41 -28
package/Cargo.toml
CHANGED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
# DNS Discovery NAPI Interface
|
|
2
|
+
|
|
3
|
+
A comprehensive Node.js interface for discovering Chia network peers using DNS introducers with proper IPv4/IPv6 support.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The DNS Discovery NAPI interface exposes the functionality of the isolated `dns-discovery` Rust crate to JavaScript/TypeScript applications. It provides separate IPv4 (A records) and IPv6 (AAAA records) lookups, returning well-structured results that can be used directly with the IPv6-capable peer connection system.
|
|
8
|
+
|
|
9
|
+
## Key Features
|
|
10
|
+
|
|
11
|
+
- ✅ **Dual Stack Support**: Separate IPv4 and IPv6 peer discovery
|
|
12
|
+
- ✅ **Proper DNS Lookups**: Uses A records for IPv4, AAAA records for IPv6
|
|
13
|
+
- ✅ **Built-in Networks**: Ready-to-use configurations for mainnet and testnet11
|
|
14
|
+
- ✅ **Custom Introducers**: Support for custom DNS introducers
|
|
15
|
+
- ✅ **Type Safety**: Full TypeScript definitions included
|
|
16
|
+
- ✅ **Multiple Interfaces**: Both class-based and functional APIs
|
|
17
|
+
- ✅ **IPv6 URL Formatting**: Automatic bracket formatting for IPv6 addresses
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
The DNS discovery interface is included in the main chia-block-listener package:
|
|
22
|
+
|
|
23
|
+
```javascript
|
|
24
|
+
const {
|
|
25
|
+
DnsDiscoveryClient
|
|
26
|
+
} = require('chia-block-listener');
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## API Reference
|
|
30
|
+
|
|
31
|
+
### Class-Based Interface
|
|
32
|
+
|
|
33
|
+
#### `DnsDiscoveryClient`
|
|
34
|
+
|
|
35
|
+
Main class for DNS discovery operations:
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
const client = new DnsDiscoveryClient();
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Methods:**
|
|
42
|
+
|
|
43
|
+
- `discoverMainnetPeers()` → `Promise<DiscoveryResultJS>`
|
|
44
|
+
- `discoverTestnet11Peers()` → `Promise<DiscoveryResultJS>`
|
|
45
|
+
- `discoverPeers(introducers: string[], port: number)` → `Promise<DiscoveryResultJS>`
|
|
46
|
+
- `resolveIpv4(hostname: string)` → `Promise<AddressResult>`
|
|
47
|
+
- `resolveIpv6(hostname: string)` → `Promise<AddressResult>`
|
|
48
|
+
- `resolveBoth(hostname: string, port: number)` → `Promise<DiscoveryResultJS>`
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
## Data Types
|
|
53
|
+
|
|
54
|
+
### `DiscoveryResultJS`
|
|
55
|
+
|
|
56
|
+
Main result type for peer discovery:
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
interface DiscoveryResultJS {
|
|
60
|
+
ipv4Peers: PeerAddressJS[]; // IPv4 peer addresses
|
|
61
|
+
ipv6Peers: PeerAddressJS[]; // IPv6 peer addresses
|
|
62
|
+
totalCount: number; // Total peers found
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### `PeerAddressJS`
|
|
67
|
+
|
|
68
|
+
Individual peer address:
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
interface PeerAddressJS {
|
|
72
|
+
host: string; // IP address as string
|
|
73
|
+
port: number; // Port number
|
|
74
|
+
isIpv6: boolean; // Protocol indicator
|
|
75
|
+
displayAddress: string; // Formatted for display/URLs
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### `AddressResult`
|
|
80
|
+
|
|
81
|
+
Result for individual hostname resolution:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
interface AddressResult {
|
|
85
|
+
addresses: string[]; // List of IP addresses
|
|
86
|
+
count: number; // Number of addresses
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Usage Examples
|
|
91
|
+
|
|
92
|
+
### Basic Peer Discovery
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
const { DnsDiscoveryClient } = require('chia-block-listener');
|
|
96
|
+
|
|
97
|
+
async function discoverPeers() {
|
|
98
|
+
const client = new DnsDiscoveryClient();
|
|
99
|
+
|
|
100
|
+
// Discover mainnet peers
|
|
101
|
+
const result = await client.discoverMainnetPeers();
|
|
102
|
+
|
|
103
|
+
console.log(`Found ${result.totalCount} total peers:`);
|
|
104
|
+
console.log(` IPv4: ${result.ipv4Peers.length}`);
|
|
105
|
+
console.log(` IPv6: ${result.ipv6Peers.length}`);
|
|
106
|
+
|
|
107
|
+
// Use with peer connections
|
|
108
|
+
for (const peer of result.ipv4Peers) {
|
|
109
|
+
console.log(`IPv4 peer: ${peer.displayAddress}`);
|
|
110
|
+
// Connect using: peer.host, peer.port
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
for (const peer of result.ipv6Peers) {
|
|
114
|
+
console.log(`IPv6 peer: ${peer.displayAddress}`); // [2001:db8::1]:8444
|
|
115
|
+
// Connect using: peer.host, peer.port
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Simple Discovery
|
|
121
|
+
|
|
122
|
+
```javascript
|
|
123
|
+
const { DnsDiscoveryClient } = require('chia-block-listener');
|
|
124
|
+
|
|
125
|
+
// Simple mainnet discovery
|
|
126
|
+
const client = new DnsDiscoveryClient();
|
|
127
|
+
const peers = await client.discoverMainnetPeers();
|
|
128
|
+
console.log(`Found ${peers.ipv4Peers.length + peers.ipv6Peers.length} peers`);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Custom Introducers
|
|
132
|
+
|
|
133
|
+
```javascript
|
|
134
|
+
const client = new DnsDiscoveryClient();
|
|
135
|
+
|
|
136
|
+
// Use custom introducers
|
|
137
|
+
const customIntroducers = [
|
|
138
|
+
'seeder.dexie.space',
|
|
139
|
+
'chia.hoffmang.com'
|
|
140
|
+
];
|
|
141
|
+
|
|
142
|
+
const result = await client.discoverPeers(customIntroducers, 8444);
|
|
143
|
+
console.log(`Custom discovery found ${result.totalCount} peers`);
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Individual DNS Resolution
|
|
147
|
+
|
|
148
|
+
```javascript
|
|
149
|
+
const client = new DnsDiscoveryClient();
|
|
150
|
+
|
|
151
|
+
// Resolve specific protocols
|
|
152
|
+
const hostname = 'dns-introducer.chia.net';
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
const ipv4 = await client.resolveIpv4(hostname);
|
|
156
|
+
console.log(`IPv4 addresses: ${ipv4.addresses.join(', ')}`);
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.log(`IPv4 resolution failed: ${error.message}`);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
const ipv6 = await client.resolveIpv6(hostname);
|
|
163
|
+
console.log(`IPv6 addresses: ${ipv6.addresses.join(', ')}`);
|
|
164
|
+
} catch (error) {
|
|
165
|
+
console.log(`IPv6 resolution failed: ${error.message}`);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Or resolve both at once
|
|
169
|
+
const both = await client.resolveBoth(hostname, 8444);
|
|
170
|
+
console.log(`Combined: ${both.totalCount} addresses`);
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Integration with Existing Peer Pool
|
|
174
|
+
|
|
175
|
+
```javascript
|
|
176
|
+
const { ChiaPeerPool, DnsDiscoveryClient } = require('chia-block-listener');
|
|
177
|
+
|
|
178
|
+
async function setupPeerPool() {
|
|
179
|
+
const pool = new ChiaPeerPool();
|
|
180
|
+
const discovery = new DnsDiscoveryClient();
|
|
181
|
+
|
|
182
|
+
// Discover peers
|
|
183
|
+
const peers = await discovery.discoverMainnetPeers();
|
|
184
|
+
|
|
185
|
+
// Add IPv4 peers to pool
|
|
186
|
+
for (const peer of peers.ipv4Peers.slice(0, 5)) {
|
|
187
|
+
await pool.addPeer(peer.host, peer.port, 'mainnet');
|
|
188
|
+
console.log(`Added IPv4 peer: ${peer.displayAddress}`);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Add IPv6 peers to pool
|
|
192
|
+
for (const peer of peers.ipv6Peers.slice(0, 5)) {
|
|
193
|
+
await pool.addPeer(peer.host, peer.port, 'mainnet');
|
|
194
|
+
console.log(`Added IPv6 peer: ${peer.displayAddress}`);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return pool;
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Error Handling
|
|
202
|
+
|
|
203
|
+
```javascript
|
|
204
|
+
const client = new DnsDiscoveryClient();
|
|
205
|
+
|
|
206
|
+
try {
|
|
207
|
+
const result = await client.discoverMainnetPeers();
|
|
208
|
+
// Handle success
|
|
209
|
+
} catch (error) {
|
|
210
|
+
console.error('Discovery failed:', error.message);
|
|
211
|
+
|
|
212
|
+
// Error types: 'ResolutionFailed', 'NoPeersFound', 'ResolverCreationFailed'
|
|
213
|
+
if (error.message.includes('NoPeersFound')) {
|
|
214
|
+
console.log('No peers found from any introducer');
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### TypeScript Usage
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
import {
|
|
223
|
+
DnsDiscoveryClient,
|
|
224
|
+
DiscoveryResultJS,
|
|
225
|
+
PeerAddressJS
|
|
226
|
+
} from 'chia-block-listener';
|
|
227
|
+
|
|
228
|
+
async function typedDiscovery(): Promise<void> {
|
|
229
|
+
const client = new DnsDiscoveryClient();
|
|
230
|
+
|
|
231
|
+
const result: DiscoveryResultJS = await client.discoverMainnetPeers();
|
|
232
|
+
|
|
233
|
+
// Type-safe access
|
|
234
|
+
result.ipv4Peers.forEach((peer: PeerAddressJS) => {
|
|
235
|
+
console.log(`IPv4: ${peer.host}:${peer.port}`);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
result.ipv6Peers.forEach((peer: PeerAddressJS) => {
|
|
239
|
+
console.log(`IPv6: ${peer.displayAddress}`);
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Performance Considerations
|
|
245
|
+
|
|
246
|
+
- **Caching**: DNS results are not cached; implement your own caching if needed
|
|
247
|
+
- **Concurrency**: All DNS lookups are performed concurrently for maximum speed
|
|
248
|
+
- **Timeout**: DNS queries have built-in timeouts (configured in the Rust crate)
|
|
249
|
+
- **Randomization**: Peer lists are automatically shuffled for load distribution
|
|
250
|
+
|
|
251
|
+
## Troubleshooting
|
|
252
|
+
|
|
253
|
+
### Common Issues
|
|
254
|
+
|
|
255
|
+
1. **No peers found**: Check network connectivity and DNS resolution
|
|
256
|
+
2. **IPv6 resolution fails**: IPv6 may not be available in all environments
|
|
257
|
+
3. **Timeout errors**: Network or DNS server issues
|
|
258
|
+
|
|
259
|
+
### Debug Logging
|
|
260
|
+
|
|
261
|
+
Enable debug logging to see DNS resolution details:
|
|
262
|
+
|
|
263
|
+
```javascript
|
|
264
|
+
const { initTracing } = require('chia-block-listener');
|
|
265
|
+
|
|
266
|
+
// Initialize tracing for debug output
|
|
267
|
+
initTracing();
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Comparison with JavaScript Version
|
|
271
|
+
|
|
272
|
+
The Rust-based DNS discovery provides several advantages over the JavaScript version in `coin-monitor.js`:
|
|
273
|
+
|
|
274
|
+
| Feature | JavaScript Version | Rust NAPI Version |
|
|
275
|
+
|---------|-------------------|------------------|
|
|
276
|
+
| **DNS Lookups** | Generic `dns.lookup()` | Explicit A/AAAA records |
|
|
277
|
+
| **IPv6 Support** | Manual detection | Built-in IPv6 handling |
|
|
278
|
+
| **Type Safety** | Runtime checks | Compile-time guarantees |
|
|
279
|
+
| **Performance** | Single-threaded | Concurrent resolution |
|
|
280
|
+
| **Error Handling** | Basic try/catch | Detailed error types |
|
|
281
|
+
| **Address Formatting** | Manual brackets | Automatic formatting |
|
|
282
|
+
|
|
283
|
+
## Future Enhancements
|
|
284
|
+
|
|
285
|
+
Planned improvements:
|
|
286
|
+
|
|
287
|
+
- [ ] DNS caching with TTL support
|
|
288
|
+
- [ ] Custom DNS server configuration
|
|
289
|
+
- [ ] Peer health checking integration
|
|
290
|
+
- [ ] Metrics and monitoring hooks
|
|
291
|
+
- [ ] IPv6 preference configuration
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ A high-performance Chia blockchain listener for Node.js, built with Rust and NAP
|
|
|
14
14
|
- **Historical Block Access**: Retrieve blocks by height or ranges with automatic load balancing
|
|
15
15
|
- **Connection Pool**: ChiaPeerPool provides automatic load balancing and rate limiting for historical queries
|
|
16
16
|
- **Peak Height Tracking**: Monitor blockchain sync progress across all connected peers
|
|
17
|
-
- **DNS Peer Discovery**: Automatic peer discovery using Chia network DNS introducers
|
|
17
|
+
- **DNS Peer Discovery**: Automatic peer discovery using Chia network DNS introducers with IPv4/IPv6 support
|
|
18
18
|
- **Cross-platform Support**: Works on Windows, macOS, and Linux (x64 and ARM64)
|
|
19
19
|
- **TypeScript Support**: Complete TypeScript definitions with IntelliSense
|
|
20
20
|
|
|
@@ -249,6 +249,70 @@ Fired when a new highest blockchain peak is discovered.
|
|
|
249
249
|
|
|
250
250
|
**Callback:** `(event: NewPeakHeightEvent) => void`
|
|
251
251
|
|
|
252
|
+
### DnsDiscoveryClient Class
|
|
253
|
+
|
|
254
|
+
The `DnsDiscoveryClient` provides automatic peer discovery using Chia network DNS introducers with full IPv4 and IPv6 support.
|
|
255
|
+
|
|
256
|
+
#### Constructor
|
|
257
|
+
|
|
258
|
+
```javascript
|
|
259
|
+
const client = new DnsDiscoveryClient()
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Creates a new DNS discovery client instance.
|
|
263
|
+
|
|
264
|
+
#### Methods
|
|
265
|
+
|
|
266
|
+
##### `discoverMainnetPeers(): Promise<DiscoveryResultJS>`
|
|
267
|
+
|
|
268
|
+
Discovers peers for Chia mainnet using built-in DNS introducers.
|
|
269
|
+
|
|
270
|
+
**Returns:** Promise resolving to discovery results with separate IPv4 and IPv6 peer lists
|
|
271
|
+
|
|
272
|
+
##### `discoverTestnet11Peers(): Promise<DiscoveryResultJS>`
|
|
273
|
+
|
|
274
|
+
Discovers peers for Chia testnet11 using built-in DNS introducers.
|
|
275
|
+
|
|
276
|
+
**Returns:** Promise resolving to discovery results
|
|
277
|
+
|
|
278
|
+
##### `discoverPeers(introducers, port): Promise<DiscoveryResultJS>`
|
|
279
|
+
|
|
280
|
+
Discovers peers using custom DNS introducers.
|
|
281
|
+
|
|
282
|
+
**Parameters:**
|
|
283
|
+
- `introducers` (string[]): Array of DNS introducer hostnames
|
|
284
|
+
- `port` (number): Default port for discovered peers
|
|
285
|
+
|
|
286
|
+
**Returns:** Promise resolving to discovery results
|
|
287
|
+
|
|
288
|
+
##### `resolveIpv4(hostname): Promise<AddressResult>`
|
|
289
|
+
|
|
290
|
+
Resolves IPv4 addresses (A records) for a hostname.
|
|
291
|
+
|
|
292
|
+
**Parameters:**
|
|
293
|
+
- `hostname` (string): Hostname to resolve
|
|
294
|
+
|
|
295
|
+
**Returns:** Promise resolving to IPv4 addresses
|
|
296
|
+
|
|
297
|
+
##### `resolveIpv6(hostname): Promise<AddressResult>`
|
|
298
|
+
|
|
299
|
+
Resolves IPv6 addresses (AAAA records) for a hostname.
|
|
300
|
+
|
|
301
|
+
**Parameters:**
|
|
302
|
+
- `hostname` (string): Hostname to resolve
|
|
303
|
+
|
|
304
|
+
**Returns:** Promise resolving to IPv6 addresses
|
|
305
|
+
|
|
306
|
+
##### `resolveBoth(hostname, port): Promise<DiscoveryResultJS>`
|
|
307
|
+
|
|
308
|
+
Resolves both IPv4 and IPv6 addresses for a hostname.
|
|
309
|
+
|
|
310
|
+
**Parameters:**
|
|
311
|
+
- `hostname` (string): Hostname to resolve
|
|
312
|
+
- `port` (number): Port for the peer addresses
|
|
313
|
+
|
|
314
|
+
**Returns:** Promise resolving to discovery results
|
|
315
|
+
|
|
252
316
|
### Event Data Types
|
|
253
317
|
|
|
254
318
|
#### `BlockReceivedEvent`
|
|
@@ -321,6 +385,36 @@ interface CoinSpend {
|
|
|
321
385
|
}
|
|
322
386
|
```
|
|
323
387
|
|
|
388
|
+
#### `DiscoveryResultJS`
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
interface DiscoveryResultJS {
|
|
392
|
+
ipv4Peers: PeerAddressJS[] // IPv4 peer addresses
|
|
393
|
+
ipv6Peers: PeerAddressJS[] // IPv6 peer addresses
|
|
394
|
+
totalCount: number // Total peers found
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
#### `PeerAddressJS`
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
interface PeerAddressJS {
|
|
402
|
+
host: string // IP address as string
|
|
403
|
+
port: number // Port number
|
|
404
|
+
isIpv6: boolean // Protocol indicator
|
|
405
|
+
displayAddress: string // Formatted for display/URLs
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
#### `AddressResult`
|
|
410
|
+
|
|
411
|
+
```typescript
|
|
412
|
+
interface AddressResult {
|
|
413
|
+
addresses: string[] // List of IP addresses
|
|
414
|
+
count: number // Number of addresses
|
|
415
|
+
}
|
|
416
|
+
```
|
|
417
|
+
|
|
324
418
|
## ChiaPeerPool Usage
|
|
325
419
|
|
|
326
420
|
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.
|
|
@@ -524,16 +618,159 @@ setInterval(async () => {
|
|
|
524
618
|
|
|
525
619
|
Both classes can be used together in the same application for different purposes.
|
|
526
620
|
|
|
621
|
+
## DNS Discovery Usage
|
|
622
|
+
|
|
623
|
+
The `DnsDiscoveryClient` enables automatic discovery of Chia network peers using DNS introducers, with full support for both IPv4 and IPv6 addresses.
|
|
624
|
+
|
|
625
|
+
### Basic DNS Discovery
|
|
626
|
+
|
|
627
|
+
```javascript
|
|
628
|
+
const { DnsDiscoveryClient, initTracing } = require('@dignetwork/chia-block-listener')
|
|
629
|
+
|
|
630
|
+
async function discoverPeers() {
|
|
631
|
+
// Initialize tracing
|
|
632
|
+
initTracing()
|
|
633
|
+
|
|
634
|
+
// Create DNS discovery client
|
|
635
|
+
const client = new DnsDiscoveryClient()
|
|
636
|
+
|
|
637
|
+
// Discover mainnet peers
|
|
638
|
+
const result = await client.discoverMainnetPeers()
|
|
639
|
+
|
|
640
|
+
console.log(`Found ${result.totalCount} total peers:`)
|
|
641
|
+
console.log(` IPv4 peers: ${result.ipv4Peers.length}`)
|
|
642
|
+
console.log(` IPv6 peers: ${result.ipv6Peers.length}`)
|
|
643
|
+
|
|
644
|
+
// Use with peer connections
|
|
645
|
+
for (const peer of result.ipv4Peers.slice(0, 3)) {
|
|
646
|
+
console.log(`IPv4 peer: ${peer.displayAddress}`)
|
|
647
|
+
// peer.host and peer.port can be used with addPeer()
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
for (const peer of result.ipv6Peers.slice(0, 3)) {
|
|
651
|
+
console.log(`IPv6 peer: ${peer.displayAddress}`) // [2001:db8::1]:8444
|
|
652
|
+
// IPv6 addresses are properly formatted with brackets
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
discoverPeers().catch(console.error)
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
### Integration with Peer Pool
|
|
660
|
+
|
|
661
|
+
```javascript
|
|
662
|
+
const { ChiaPeerPool, DnsDiscoveryClient } = require('@dignetwork/chia-block-listener')
|
|
663
|
+
|
|
664
|
+
async function setupPoolWithDnsDiscovery() {
|
|
665
|
+
const pool = new ChiaPeerPool()
|
|
666
|
+
const discovery = new DnsDiscoveryClient()
|
|
667
|
+
|
|
668
|
+
// Discover peers automatically
|
|
669
|
+
const peers = await discovery.discoverMainnetPeers()
|
|
670
|
+
|
|
671
|
+
// Add discovered peers to pool (both IPv4 and IPv6)
|
|
672
|
+
const allPeers = [...peers.ipv4Peers, ...peers.ipv6Peers]
|
|
673
|
+
for (const peer of allPeers.slice(0, 5)) {
|
|
674
|
+
await pool.addPeer(peer.host, peer.port, 'mainnet')
|
|
675
|
+
console.log(`Added peer: ${peer.displayAddress}`)
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// Now use the pool for block retrieval
|
|
679
|
+
const block = await pool.getBlockByHeight(5000000)
|
|
680
|
+
console.log(`Retrieved block ${block.height}`)
|
|
681
|
+
|
|
682
|
+
await pool.shutdown()
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
setupPoolWithDnsDiscovery().catch(console.error)
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
### Custom DNS Introducers
|
|
689
|
+
|
|
690
|
+
```javascript
|
|
691
|
+
const client = new DnsDiscoveryClient()
|
|
692
|
+
|
|
693
|
+
// Use custom introducers
|
|
694
|
+
const customIntroducers = [
|
|
695
|
+
'seeder.dexie.space',
|
|
696
|
+
'chia.hoffmang.com'
|
|
697
|
+
]
|
|
698
|
+
|
|
699
|
+
const result = await client.discoverPeers(customIntroducers, 8444)
|
|
700
|
+
console.log(`Found ${result.totalCount} peers from custom introducers`)
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
### Individual DNS Resolution
|
|
704
|
+
|
|
705
|
+
```javascript
|
|
706
|
+
const client = new DnsDiscoveryClient()
|
|
707
|
+
const hostname = 'dns-introducer.chia.net'
|
|
708
|
+
|
|
709
|
+
// Resolve specific protocols
|
|
710
|
+
try {
|
|
711
|
+
const ipv4 = await client.resolveIpv4(hostname)
|
|
712
|
+
console.log(`IPv4 addresses: ${ipv4.addresses.join(', ')}`)
|
|
713
|
+
} catch (error) {
|
|
714
|
+
console.log(`IPv4 resolution failed: ${error.message}`)
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
try {
|
|
718
|
+
const ipv6 = await client.resolveIpv6(hostname)
|
|
719
|
+
console.log(`IPv6 addresses: ${ipv6.addresses.join(', ')}`)
|
|
720
|
+
} catch (error) {
|
|
721
|
+
console.log(`IPv6 resolution failed: ${error.message}`)
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
// Or resolve both at once
|
|
725
|
+
const both = await client.resolveBoth(hostname, 8444)
|
|
726
|
+
console.log(`Combined: ${both.totalCount} addresses`)
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
|
|
730
|
+
|
|
731
|
+
### Error Handling
|
|
732
|
+
|
|
733
|
+
```javascript
|
|
734
|
+
const client = new DnsDiscoveryClient()
|
|
735
|
+
|
|
736
|
+
try {
|
|
737
|
+
const result = await client.discoverMainnetPeers()
|
|
738
|
+
console.log(`Discovery successful: ${result.totalCount} peers`)
|
|
739
|
+
} catch (error) {
|
|
740
|
+
console.error('Discovery failed:', error.message)
|
|
741
|
+
|
|
742
|
+
// Handle different error types
|
|
743
|
+
if (error.message.includes('NoPeersFound')) {
|
|
744
|
+
console.log('No peers found from any introducer')
|
|
745
|
+
} else if (error.message.includes('ResolutionFailed')) {
|
|
746
|
+
console.log('DNS resolution failed')
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
### Key Features
|
|
752
|
+
|
|
753
|
+
- **Dual Stack Support**: Separate IPv4 and IPv6 peer lists
|
|
754
|
+
- **Proper DNS Lookups**: Uses A records for IPv4, AAAA records for IPv6
|
|
755
|
+
- **Built-in Networks**: Ready configurations for mainnet and testnet11
|
|
756
|
+
- **Custom Introducers**: Support for any DNS introducers
|
|
757
|
+
- **IPv6 URL Formatting**: Automatic bracket formatting for IPv6 addresses
|
|
758
|
+
- **Type Safety**: Full TypeScript support with detailed type definitions
|
|
759
|
+
|
|
527
760
|
## TypeScript Usage
|
|
528
761
|
|
|
529
762
|
```typescript
|
|
530
763
|
import {
|
|
531
764
|
ChiaBlockListener,
|
|
532
765
|
ChiaPeerPool,
|
|
766
|
+
DnsDiscoveryClient,
|
|
533
767
|
BlockReceivedEvent,
|
|
534
768
|
PeerConnectedEvent,
|
|
535
769
|
PeerDisconnectedEvent,
|
|
536
770
|
NewPeakHeightEvent,
|
|
771
|
+
DiscoveryResultJS,
|
|
772
|
+
PeerAddressJS,
|
|
773
|
+
AddressResult,
|
|
537
774
|
CoinRecord,
|
|
538
775
|
CoinSpend,
|
|
539
776
|
initTracing,
|
|
@@ -617,6 +854,29 @@ async function fetchHistoricalData() {
|
|
|
617
854
|
console.log(`Pool has ${peers.length} active peers`)
|
|
618
855
|
console.log(`Current peak: ${peak || 'No peak yet'}`)
|
|
619
856
|
}
|
|
857
|
+
|
|
858
|
+
// TypeScript DNS Discovery
|
|
859
|
+
async function typedDnsDiscovery(): Promise<void> {
|
|
860
|
+
const client = new DnsDiscoveryClient()
|
|
861
|
+
|
|
862
|
+
// Type-safe discovery
|
|
863
|
+
const result: DiscoveryResultJS = await client.discoverMainnetPeers()
|
|
864
|
+
|
|
865
|
+
// Access with full type safety
|
|
866
|
+
result.ipv4Peers.forEach((peer: PeerAddressJS) => {
|
|
867
|
+
console.log(`IPv4: ${peer.host}:${peer.port} (${peer.displayAddress})`)
|
|
868
|
+
})
|
|
869
|
+
|
|
870
|
+
result.ipv6Peers.forEach((peer: PeerAddressJS) => {
|
|
871
|
+
console.log(`IPv6: ${peer.displayAddress} (isIpv6: ${peer.isIpv6})`)
|
|
872
|
+
})
|
|
873
|
+
|
|
874
|
+
// Individual resolution with types
|
|
875
|
+
const ipv4Result: AddressResult = await client.resolveIpv4('dns-introducer.chia.net')
|
|
876
|
+
const ipv6Result: AddressResult = await client.resolveIpv6('dns-introducer.chia.net')
|
|
877
|
+
|
|
878
|
+
console.log(`IPv4 count: ${ipv4Result.count}, IPv6 count: ${ipv6Result.count}`)
|
|
879
|
+
}
|
|
620
880
|
```
|
|
621
881
|
|
|
622
882
|
## Advanced Usage
|
|
@@ -689,6 +949,8 @@ console.log(eventTypes)
|
|
|
689
949
|
// Output: { blockReceived: "blockReceived", peerConnected: "peerConnected", peerDisconnected: "peerDisconnected" }
|
|
690
950
|
```
|
|
691
951
|
|
|
952
|
+
|
|
953
|
+
|
|
692
954
|
## Performance Tips
|
|
693
955
|
|
|
694
956
|
1. **Use specific event handlers**: Only listen for the events you need
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "dns-discovery"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
|
|
6
|
+
[dependencies]
|
|
7
|
+
tokio = { version = "1.0", features = ["full"] }
|
|
8
|
+
trust-dns-resolver = "0.23"
|
|
9
|
+
serde = { version = "1.0", features = ["derive"] }
|
|
10
|
+
thiserror = "1.0"
|
|
11
|
+
tracing = "0.1"
|
|
12
|
+
rand = "0.8"
|
|
13
|
+
|
|
14
|
+
[dev-dependencies]
|
|
15
|
+
tokio-test = "0.4"
|
|
16
|
+
tracing-subscriber = "0.3"
|