@bsv/sdk 1.9.3 → 1.9.4

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 (60) hide show
  1. package/dist/cjs/package.json +1 -1
  2. package/docs/fast-docs.png +0 -0
  3. package/docs/index.md +49 -44
  4. package/docs/swagger.png +0 -0
  5. package/package.json +1 -1
  6. package/docs/MARKDOWN_VALIDATION_GUIDE.md +0 -175
  7. package/docs/concepts/beef.md +0 -92
  8. package/docs/concepts/chain-tracking.md +0 -134
  9. package/docs/concepts/decentralized-identity.md +0 -221
  10. package/docs/concepts/fees.md +0 -249
  11. package/docs/concepts/identity-certificates.md +0 -307
  12. package/docs/concepts/index.md +0 -77
  13. package/docs/concepts/key-management.md +0 -185
  14. package/docs/concepts/script-templates.md +0 -176
  15. package/docs/concepts/sdk-philosophy.md +0 -80
  16. package/docs/concepts/signatures.md +0 -194
  17. package/docs/concepts/spv-verification.md +0 -118
  18. package/docs/concepts/transaction-encoding.md +0 -167
  19. package/docs/concepts/transaction-structure.md +0 -67
  20. package/docs/concepts/trust-model.md +0 -139
  21. package/docs/concepts/verification.md +0 -250
  22. package/docs/concepts/wallet-integration.md +0 -101
  23. package/docs/guides/development-wallet-setup.md +0 -374
  24. package/docs/guides/direct-transaction-creation.md +0 -147
  25. package/docs/guides/http-client-configuration.md +0 -488
  26. package/docs/guides/index.md +0 -138
  27. package/docs/guides/large-transactions.md +0 -448
  28. package/docs/guides/multisig-transactions.md +0 -792
  29. package/docs/guides/security-best-practices.md +0 -494
  30. package/docs/guides/transaction-batching.md +0 -132
  31. package/docs/guides/transaction-signing-methods.md +0 -419
  32. package/docs/reference/arc-config.md +0 -698
  33. package/docs/reference/brc-100.md +0 -33
  34. package/docs/reference/configuration.md +0 -835
  35. package/docs/reference/debugging.md +0 -705
  36. package/docs/reference/errors.md +0 -597
  37. package/docs/reference/index.md +0 -111
  38. package/docs/reference/network-config.md +0 -914
  39. package/docs/reference/op-codes.md +0 -325
  40. package/docs/reference/transaction-signatures.md +0 -95
  41. package/docs/tutorials/advanced-transaction.md +0 -572
  42. package/docs/tutorials/aes-encryption.md +0 -949
  43. package/docs/tutorials/authfetch-tutorial.md +0 -986
  44. package/docs/tutorials/ecdh-key-exchange.md +0 -549
  45. package/docs/tutorials/elliptic-curve-fundamentals.md +0 -606
  46. package/docs/tutorials/error-handling.md +0 -1216
  47. package/docs/tutorials/first-transaction-low-level.md +0 -205
  48. package/docs/tutorials/first-transaction.md +0 -275
  49. package/docs/tutorials/hashes-and-hmacs.md +0 -788
  50. package/docs/tutorials/identity-management.md +0 -729
  51. package/docs/tutorials/index.md +0 -219
  52. package/docs/tutorials/key-management.md +0 -538
  53. package/docs/tutorials/protowallet-development.md +0 -743
  54. package/docs/tutorials/script-construction.md +0 -690
  55. package/docs/tutorials/spv-merkle-proofs.md +0 -685
  56. package/docs/tutorials/testnet-transactions-low-level.md +0 -359
  57. package/docs/tutorials/transaction-broadcasting.md +0 -538
  58. package/docs/tutorials/transaction-types.md +0 -420
  59. package/docs/tutorials/type-42.md +0 -568
  60. package/docs/tutorials/uhrp-storage.md +0 -599
@@ -1,538 +0,0 @@
1
- # Transaction Broadcasting
2
-
3
- **Duration**: 25 minutes
4
- **Prerequisites**: Completed "Your First BSV Transaction" tutorial, Node.js, basic TypeScript knowledge
5
-
6
- ## Learning Goals
7
-
8
- - Understand how transaction broadcasting works in BSV
9
- - Learn the difference between `WalletClient` and direct broadcasting approaches
10
- - Configure broadcasting for testnet vs mainnet
11
- - Implement custom broadcasters for different services (ARC, WhatsOnChain)
12
- - Handle broadcasting errors and responses
13
-
14
- > **📚 Related Concepts**: Review [Chain Tracking](../concepts/chain-tracking.md), [Transaction Fees](../concepts/fees.md), and [Wallet Integration](../concepts/wallet-integration.md) for background on network interaction.
15
-
16
- ## Introduction
17
-
18
- Transaction broadcasting is the process of submitting your signed transaction to the Bitcoin SV network so it can be included in a block. The BSV TypeScript SDK provides multiple approaches for broadcasting transactions, each suited for different use cases and deployment scenarios.
19
-
20
- In this tutorial, you'll learn about the two main broadcasting approaches:
21
-
22
- 1. **WalletClient Broadcasting**: Uses a BRC-100 compliant wallet as a proxy (such as the MetaNet Desktop Wallet)
23
- 2. **Direct Broadcasting**: Connects directly to mining services and APIs
24
-
25
- ## Understanding Broadcasting Architecture
26
-
27
- ### WalletClient Broadcasting Flow
28
-
29
- When you use `WalletClient`, the broadcasting flow looks like this:
30
-
31
- ```
32
- Your App → WalletClient → Wallet → Mining Services → BSV Network
33
- ```
34
-
35
- The Wallet acts as a proxy that:
36
-
37
- - Manages your broadcasting preferences
38
- - Handles fallback logic between different services
39
- - Provides a consistent API regardless of the underlying service
40
-
41
- Due to its simplicity, this is the recommended approach.
42
-
43
- ### Direct Broadcasting Flow
44
-
45
- With direct broadcasting, your application connects directly to mining services:
46
-
47
- ```
48
- Your App → Custom Broadcaster → Mining Service API → BSV Network
49
- ```
50
-
51
- This approach gives you:
52
-
53
- - Full control over which service to use
54
- - Direct error handling and response processing
55
- - Ability to implement custom retry logic
56
- - No dependency on external wallet software
57
-
58
- Due to its complexity and need to handle the low-level details of the broadcasting process, this is the less recommended approach.
59
-
60
- ## Step 1: WalletClient Broadcasting
61
-
62
- Let's start with the `WalletClient` approach, which is the simplest for most applications. This is the same approach we have seen in the previous tutorials, where we used the `WalletClient` to create and broadcast transactions.
63
-
64
- ### Basic WalletClient Setup
65
-
66
- First, create a new project for our broadcasting examples:
67
-
68
- ```bash
69
- # Create a new directory
70
- mkdir bsv-broadcasting-tutorial
71
- cd bsv-broadcasting-tutorial
72
-
73
- # Initialize project
74
- npm init -y
75
-
76
- # Install dependencies
77
- npm install typescript ts-node @types/node --save-dev
78
- npm install @bsv/sdk
79
- ```
80
-
81
- Create a basic TypeScript configuration (`tsconfig.json`):
82
-
83
- ```json
84
- {
85
- "compilerOptions": {
86
- "target": "es2020",
87
- "module": "commonjs",
88
- "esModuleInterop": true,
89
- "strict": true,
90
- "outDir": "./dist"
91
- }
92
- }
93
- ```
94
-
95
- ### WalletClient Broadcasting Example
96
-
97
- Create `wallet-broadcasting.ts`:
98
-
99
- ```typescript
100
- import { WalletClient } from '@bsv/sdk'
101
-
102
- async function walletClientBroadcasting() {
103
- try {
104
- // Initialize the `WalletClient`, using localhost as wallet substrate
105
- const wallet = new WalletClient('auto', 'localhost')
106
-
107
- // Check if we're authenticated with the wallet
108
- const { authenticated } = await wallet.isAuthenticated()
109
- if (!authenticated) {
110
- console.log('Please authenticate with your wallet')
111
- await wallet.waitForAuthentication()
112
- console.log('Successfully authenticated!')
113
- }
114
-
115
- // Get wallet version
116
- const { version } = await wallet.getVersion()
117
- console.log(`Wallet version: ${version}`)
118
-
119
- // For this tutorial, we'll create a transaction with a simple OP_RETURN data output
120
- // The wallet will handle input selection, change outputs and fees
121
- console.log('\n🚀 Creating transaction...')
122
- const actionResult = await wallet.createAction({
123
- description: 'Broadcasting tutorial transaction',
124
- outputs: [
125
- {
126
- satoshis: 100, // Amount in satoshis (very small amount)
127
- // For this basic example, we'll use a standard OP_RETURN script
128
- // Here we use a pre-defined script for simplicity (OP_RETURN with simple data)
129
- lockingScript: '006a0461626364', // OP_RETURN with data 'abcd'
130
- outputDescription: 'Broadcasting tutorial data'
131
- }
132
- ]
133
- })
134
-
135
- console.log('Transaction created:')
136
-
137
- if (actionResult.txid) {
138
- // If the wallet auto-signed and broadcast the transaction
139
- console.log('Full action result:', JSON.stringify(actionResult, null, 2))
140
- console.log(`Transaction ID: ${actionResult.txid}`)
141
- console.log(`View on explorer: https://whatsonchain.com/tx/${actionResult.txid}`)
142
- console.log('Transaction was automatically signed and broadcast!')
143
- }
144
- else if (actionResult.signableTransaction) {
145
- console.log('Created transaction that needs signing')
146
- // Get the reference needed for signing
147
- const txReference = actionResult.signableTransaction.reference
148
-
149
- // Now sign the transaction
150
- // Note: In a real application, you might prompt the user to sign
151
- const signResult = await wallet.signAction({
152
- // The wallet knows which inputs need to be spent based on the reference
153
- spends: {},
154
- // Use the reference from the createAction result
155
- reference: txReference,
156
- options: {
157
- acceptDelayedBroadcast: true
158
- }
159
- })
160
-
161
- console.log(`Transaction signed and broadcast!`)
162
- console.log(`Transaction ID: ${signResult.txid}`)
163
- console.log(`View on explorer: https://whatsonchain.com/tx/${signResult.txid}`)
164
- }
165
- else {
166
- console.log('Transaction created but no actionable result returned')
167
- }
168
-
169
- } catch (error) {
170
- console.error('❌ Broadcasting failed:', error)
171
- console.log('Note: Make sure you have a compatible wallet running and are authenticated.')
172
- }
173
- }
174
-
175
- // Run the example
176
- walletClientBroadcasting()
177
- ```
178
-
179
- ### How `WalletClient` Broadcasting Works
180
-
181
- When you use `WalletClient`:
182
-
183
- 1. **Connection**: Your app connects to the BRC-100 wallet's local HTTP API (usually `http://localhost:3321` for MetaNet Desktop Wallet)
184
- 2. **Transaction Creation**: The wallet helps construct the transaction using your available UTXOs
185
- 3. **Signing**: The wallet signs the transaction with your private keys
186
- 4. **Broadcasting**: The wallet submits the transaction to whatever broadcast service is configured in its settings
187
- 5. **Response**: You receive either a transaction ID (success) or an error message
188
-
189
- The key advantage is that **you don't control the broadcasting directly** - the BRC-100 wallet handles it based on its configuration. This means:
190
-
191
- - ✅ Easy to use - no need to manage API keys or endpoints
192
- - ✅ Fallback logic built-in
193
- - ✅ User can configure preferred services through the wallet UI
194
-
195
- ## Step 2: Direct Broadcasting with Custom Broadcasters
196
-
197
- The `WalletClient` approach in step 1 is the recommended approach. However, if you need more control, you can broadcast transactions directly using custom broadcaster implementations. We will demonstrate the main broadcaster implementations in the SDK: ARC and WhatsOnChain.
198
-
199
- ### Automatic vs Manual Broadcasting
200
-
201
- **Important**: By default, `wallet.createAction()` automatically broadcasts transactions through the wallet's configured broadcaster. To demonstrate manual broadcasting with specific services, you need to:
202
-
203
- 1. **Prevent automatic broadcast**: Use `options: { noSend: true }` in `createAction()`
204
- 2. **Convert to Transaction**: Convert the returned `AtomicBEEF` to a `Transaction` object
205
- 3. **Manual broadcast**: Use your chosen broadcaster to submit the transaction
206
-
207
- This approach is useful when you need to:
208
-
209
- - Use a specific broadcasting service (ARC, WhatsOnChain, etc.)
210
- - Implement custom retry logic or error handling
211
- - Broadcast to multiple services for redundancy
212
- - Control exactly when and how transactions are broadcast
213
-
214
- ### Understanding Broadcaster Interface
215
-
216
- All broadcasters in the SDK implement the `Broadcaster` interface:
217
-
218
- ```typescript
219
- interface Broadcaster {
220
- broadcast(tx: Transaction): Promise<BroadcastResponse | BroadcastFailure>
221
- }
222
- ```
223
-
224
- The response types are:
225
-
226
- ```typescript
227
- interface BroadcastResponse {
228
- status: 'success'
229
- txid: string
230
- message?: string
231
- }
232
-
233
- interface BroadcastFailure {
234
- status: 'error'
235
- code: string
236
- description: string
237
- }
238
- ```
239
-
240
- ### ARC Broadcasting
241
-
242
- ARC (Application Resource Component) is TAAL's enterprise-grade transaction processing service. Create `arc-broadcasting.ts`:
243
-
244
- ```typescript
245
- import { WalletClient, ARC, NodejsHttpClient, Transaction } from '@bsv/sdk'
246
- import https from 'https'
247
-
248
- async function arcBroadcasting() {
249
- try {
250
- // 1. Set up wallet connection
251
- const wallet = new WalletClient('auto', 'localhost')
252
-
253
- // Check if wallet is connected
254
- const isAuthenticated = await wallet.isAuthenticated()
255
- if (!isAuthenticated) {
256
- console.log('Please authenticate with your BRC-100 wallet first')
257
- return
258
- }
259
-
260
- // 2. Create a transaction action WITHOUT automatic broadcasting
261
- const actionResult = await wallet.createAction({
262
- description: 'ARC broadcasting tutorial transaction',
263
- outputs: [
264
- {
265
- satoshis: 100, // Small payment amount
266
- lockingScript: '76a914f1c075a01882ae0972f95d3a4177c86c852b7d9188ac', // P2PKH script to a test address
267
- outputDescription: 'ARC broadcasting tutorial payment'
268
- }
269
- ],
270
- options: {
271
- noSend: true // Prevent automatic broadcasting - we'll broadcast manually with ARC
272
- }
273
- })
274
-
275
- console.log('Transaction created successfully (not broadcast yet)')
276
- console.log(`Transaction ID: ${actionResult.txid}`)
277
-
278
- // 3. Convert AtomicBEEF to Transaction for manual broadcasting
279
- if (!actionResult.tx) {
280
- throw new Error('Transaction creation failed - no transaction returned')
281
- }
282
- const tx = Transaction.fromAtomicBEEF(actionResult.tx)
283
-
284
- // 4. Set up ARC broadcaster for testnet
285
- // You need to provide your Taal API key here
286
- // Get it by signing up at https://console.taal.com
287
- const apiKey = process.env.TAAL_API_KEY || 'your_taal_api_key_here'
288
- const httpClient = new NodejsHttpClient(https)
289
-
290
- const arc = new ARC('https://arc.taal.com', {
291
- apiKey,
292
- httpClient,
293
- deploymentId: 'broadcasting-tutorial'
294
- })
295
-
296
- // 5. Manually broadcast the transaction using ARC
297
- console.log('Broadcasting transaction with ARC...')
298
- const result = await tx.broadcast(arc)
299
-
300
- if (result.status === 'success') {
301
- console.log('✅ Transaction broadcast successful!')
302
- console.log(`Transaction ID: ${result.txid}`)
303
- console.log(`View on explorer: https://www.whatsonchain.com/tx/${result.txid}`)
304
- } else {
305
- console.log('❌ Broadcasting failed:', result)
306
- }
307
-
308
- } catch (error: any) {
309
- console.error('❌ Error during ARC broadcasting:', error)
310
-
311
- // Common troubleshooting
312
- if (error.message?.includes('Insufficient funds')) {
313
- console.log('💡 Make sure your wallet has sufficient testnet coins')
314
- } else if (error.message?.includes('no header should have returned false')) {
315
- console.log('💡 Try restarting your wallet application and ensure it is fully synced')
316
- }
317
- }
318
- }
319
-
320
- // Run the example
321
- arcBroadcasting()
322
- ```
323
-
324
- ### WhatsOnChain Broadcasting
325
-
326
- WhatsOnChain provides a free broadcasting service. Create `whatsonchain-broadcasting.ts`:
327
-
328
- ```typescript
329
- import { WalletClient, WhatsOnChainBroadcaster, NodejsHttpClient, Transaction } from '@bsv/sdk'
330
- import https from 'https'
331
-
332
- async function whatsOnChainBroadcasting() {
333
- try {
334
- // 1. Set up wallet connection
335
- const wallet = new WalletClient('auto', 'localhost')
336
-
337
- // Check if wallet is connected
338
- const isAuthenticated = await wallet.isAuthenticated()
339
- if (!isAuthenticated) {
340
- console.log('Please authenticate with your BRC-100 wallet first')
341
- return
342
- }
343
-
344
- // 2. Create a transaction action WITHOUT automatic broadcasting
345
- const actionResult = await wallet.createAction({
346
- description: 'WhatsOnChain broadcasting tutorial transaction',
347
- outputs: [
348
- {
349
- satoshis: 100, // Small payment amount
350
- lockingScript: '76a914f1c075a01882ae0972f95d3a4177c86c852b7d9188ac', // P2PKH script to a test address
351
- outputDescription: 'WhatsOnChain broadcasting tutorial payment'
352
- }
353
- ],
354
- options: {
355
- noSend: true // Prevent automatic broadcasting - we'll broadcast manually with WhatsOnChain
356
- }
357
- })
358
-
359
- console.log('Transaction created successfully (not broadcast yet)')
360
- console.log(`Transaction ID: ${actionResult.txid}`)
361
-
362
- // 3. Convert AtomicBEEF to Transaction for manual broadcasting
363
- if (!actionResult.tx) {
364
- throw new Error('Transaction creation failed - no transaction returned')
365
- }
366
- const tx = Transaction.fromAtomicBEEF(actionResult.tx)
367
-
368
- // 4. Set up WhatsOnChain broadcaster for mainnet
369
- const httpClient = new NodejsHttpClient(https)
370
- const broadcaster = new WhatsOnChainBroadcaster('main', httpClient)
371
-
372
- // 5. Manually broadcast the transaction using WhatsOnChain
373
- console.log('Broadcasting transaction with WhatsOnChain...')
374
- const result = await tx.broadcast(broadcaster)
375
-
376
- if (result.status === 'success') {
377
- console.log('✅ Transaction broadcast successful!')
378
- console.log(`Transaction ID: ${result.txid}`)
379
- console.log(`View on explorer: https://www.whatsonchain.com/tx/${result.txid}`)
380
- } else {
381
- console.log('❌ Broadcasting failed:', result)
382
- }
383
-
384
- } catch (error: any) {
385
- console.error('❌ Error during WhatsOnChain broadcasting:', error)
386
-
387
- // Common troubleshooting
388
- if (error.message?.includes('Insufficient funds')) {
389
- console.log('💡 Make sure your wallet has sufficient mainnet coins')
390
- } else if (error.message?.includes('no header should have returned false')) {
391
- console.log('💡 Try restarting your wallet application and ensure it is fully synced')
392
- }
393
- }
394
- }
395
-
396
- // Run the example
397
- whatsOnChainBroadcasting()
398
- ```
399
-
400
- ## Step 3: Network Configuration (Testnet vs Mainnet)
401
-
402
- For advanced broadcasting scenarios like custom broadcaster implementations, see the [Custom Broadcasters Guide](../guides/custom-broadcasters.md).
403
-
404
- **Important**: When using manual broadcasting, ensure your wallet and broadcasters are configured for the same network. If your BRC-100 wallet is connected to testnet, use testnet broadcasters. If it's on mainnet, use mainnet broadcasters. Mismatched networks will cause broadcasting failures.
405
-
406
- Different networks require different broadcaster configurations:
407
-
408
- ```typescript
409
- import { ARC, WhatsOnChainBroadcaster, Broadcaster } from '@bsv/sdk'
410
-
411
- interface NetworkConfig {
412
- name: string
413
- arc: Broadcaster
414
- whatsOnChain: Broadcaster
415
- }
416
-
417
- // Network configurations
418
- const networks: Record<string, NetworkConfig> = {
419
- testnet: {
420
- name: 'BSV Testnet',
421
- arc: new ARC('https://arc-test.taal.com'),
422
- whatsOnChain: new WhatsOnChainBroadcaster('test')
423
- },
424
-
425
- mainnet: {
426
- name: 'BSV Mainnet',
427
- arc: new ARC('https://arc.taal.com', {
428
- apiKey: process.env.TAAL_API_KEY // Use environment variable for production
429
- }),
430
- whatsOnChain: new WhatsOnChainBroadcaster('main')
431
- }
432
- }
433
- ```
434
-
435
- ## Step 4: Monitoring and Verification
436
-
437
- After broadcasting, you should verify that your transaction was accepted:
438
-
439
- ```typescript
440
- import { Transaction } from '@bsv/sdk'
441
-
442
- async function verifyTransaction(txid: string, network: 'test' | 'main' = 'test') {
443
- const baseUrl = network === 'test'
444
- ? 'https://api.whatsonchain.com/v1/bsv/test'
445
- : 'https://api.whatsonchain.com/v1/bsv/main'
446
-
447
- try {
448
- // Check if transaction exists
449
- const response = await fetch(`${baseUrl}/tx/${txid}`)
450
-
451
- if (response.ok) {
452
- const txData = await response.json()
453
-
454
- console.log('✅ Transaction found on network')
455
- console.log('Transaction ID:', txData.txid)
456
- console.log('Block height:', txData.blockheight || 'Unconfirmed')
457
- console.log('Confirmations:', txData.confirmations || 0)
458
-
459
- return txData
460
- } else if (response.status === 404) {
461
- console.log('⏳ Transaction not yet visible on network')
462
- return null
463
- } else {
464
- throw new Error(`API error: ${response.status}`)
465
- }
466
-
467
- } catch (error) {
468
- console.error('❌ Error verifying transaction:', error)
469
- throw error
470
- }
471
- }
472
-
473
- async function waitForTransaction(
474
- txid: string,
475
- network: 'test' | 'main' = 'test',
476
- timeoutMs: number = 30000
477
- ): Promise<any> {
478
- const startTime = Date.now()
479
-
480
- while (Date.now() - startTime < timeoutMs) {
481
- const txData = await verifyTransaction(txid, network)
482
-
483
- if (txData) {
484
- return txData
485
- }
486
-
487
- // Transactions can take a few seconds to show up in WhatsOnChain
488
- // Wait 2 seconds before checking again
489
- await new Promise(resolve => setTimeout(resolve, 2000))
490
- }
491
-
492
- throw new Error(`Transaction ${txid} not found within ${timeoutMs}ms`)
493
- }
494
-
495
- // Example usage
496
- async function monitoringExample(txid: string) {
497
- try {
498
- console.log('Waiting for transaction to appear on network...')
499
- const txData = await waitForTransaction(txid, 'main')
500
-
501
- console.log('✅ Transaction confirmed:', txData)
502
-
503
- } catch (error) {
504
- console.error('❌ Transaction monitoring failed:', error)
505
- }
506
- }
507
-
508
- // Run the example
509
- monitoringExample('your-transaction-id-here')
510
- ```
511
-
512
- ## Summary
513
-
514
- In this tutorial, you learned about the two main approaches to transaction broadcasting in BSV:
515
-
516
- ### `WalletClient` Approach
517
-
518
- - ✅ **Simple**: Easy to use with BRC-100 wallets
519
- - ✅ **Managed**: Wallet handles service selection and fallbacks
520
- - ✅ **User Control**: Users can configure preferred services
521
-
522
- ### Direct Broadcasting Approach
523
-
524
- - ✅ **Full Control**: Choose exactly which service to use
525
- - ✅ **No Dependencies**: Works without external wallet software
526
- - ✅ **Custom Logic**: Implement your own retry and fallback logic
527
- - ✅ **Error Handling**: Direct access to service responses
528
- - ❌ **More Complex**: Requires more setup and configuration
529
-
530
- ### Next Steps
531
-
532
- - Experiment with different broadcaster configurations
533
- - Implement custom broadcasters for other services
534
- - Build monitoring dashboards for your applications
535
- - Explore advanced features like batch broadcasting
536
- - Implement robust error handling: See the [Error Handling and Edge Cases Tutorial](./error-handling.md) for comprehensive patterns and the [Custom Broadcasters Guide](../guides/custom-broadcasters.md) for advanced retry logic and failover strategies
537
-
538
- The broadcasting approach you choose depends on your application's requirements, deployment environment, and control needs. Both approaches are valid and can be used effectively in different scenarios.