@bsv/sdk 1.6.12 → 1.6.14
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/README.md +4 -4
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/transaction/broadcasters/DefaultBroadcaster.js +1 -1
- package/dist/cjs/src/transaction/broadcasters/DefaultBroadcaster.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/transaction/broadcasters/DefaultBroadcaster.js +1 -1
- package/dist/esm/src/transaction/broadcasters/DefaultBroadcaster.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +1 -1
- package/docs/MARKDOWN_VALIDATION_GUIDE.md +175 -0
- package/docs/concepts/beef.md +8 -0
- package/docs/concepts/chain-tracking.md +12 -0
- package/docs/concepts/decentralized-identity.md +37 -0
- package/docs/concepts/fees.md +32 -0
- package/docs/concepts/identity-certificates.md +53 -1
- package/docs/concepts/index.md +15 -0
- package/docs/concepts/key-management.md +9 -0
- package/docs/concepts/script-templates.md +13 -0
- package/docs/concepts/sdk-philosophy.md +8 -0
- package/docs/concepts/signatures.md +15 -0
- package/docs/concepts/spv-verification.md +12 -0
- package/docs/concepts/transaction-encoding.md +19 -0
- package/docs/concepts/transaction-structure.md +4 -0
- package/docs/concepts/trust-model.md +16 -0
- package/docs/concepts/verification.md +31 -0
- package/docs/concepts/wallet-integration.md +6 -0
- package/docs/guides/development-wallet-setup.md +374 -0
- package/docs/guides/direct-transaction-creation.md +12 -2
- package/docs/guides/http-client-configuration.md +122 -48
- package/docs/guides/index.md +117 -9
- package/docs/guides/large-transactions.md +448 -0
- package/docs/guides/multisig-transactions.md +792 -0
- package/docs/guides/security-best-practices.md +494 -0
- package/docs/guides/transaction-batching.md +132 -0
- package/docs/guides/transaction-signing-methods.md +230 -79
- package/docs/index.md +0 -2
- package/docs/reference/auth.md +212 -159
- package/docs/reference/compat.md +120 -96
- package/docs/reference/configuration.md +6 -0
- package/docs/reference/debugging.md +5 -0
- package/docs/reference/errors.md +50 -0
- package/docs/reference/identity.md +21 -12
- package/docs/reference/index.md +14 -1
- package/docs/reference/kvstore.md +21 -19
- package/docs/reference/messages.md +3 -0
- package/docs/reference/op-codes.md +20 -1
- package/docs/reference/overlay-tools.md +46 -18
- package/docs/reference/primitives.md +571 -390
- package/docs/reference/registry.md +43 -20
- package/docs/reference/script.md +140 -105
- package/docs/reference/storage.md +32 -12
- package/docs/reference/totp.md +16 -11
- package/docs/reference/transaction-signatures.md +2 -1
- package/docs/reference/transaction.md +201 -120
- package/docs/reference/wallet.md +241 -64
- package/docs/tutorials/advanced-transaction.md +1 -4
- package/docs/tutorials/aes-encryption.md +3 -1
- package/docs/tutorials/authfetch-tutorial.md +29 -0
- package/docs/tutorials/ecdh-key-exchange.md +2 -0
- package/docs/tutorials/elliptic-curve-fundamentals.md +3 -0
- package/docs/tutorials/error-handling.md +1 -0
- package/docs/tutorials/first-transaction-low-level.md +1 -0
- package/docs/tutorials/first-transaction.md +5 -8
- package/docs/tutorials/hashes-and-hmacs.md +5 -31
- package/docs/tutorials/identity-management.md +27 -0
- package/docs/tutorials/index.md +114 -77
- package/docs/tutorials/key-management.md +5 -3
- package/docs/tutorials/protowallet-development.md +27 -0
- package/docs/tutorials/spv-merkle-proofs.md +9 -6
- package/docs/tutorials/testnet-transactions-low-level.md +25 -18
- package/docs/tutorials/transaction-broadcasting.md +10 -7
- package/docs/tutorials/transaction-types.md +5 -4
- package/docs/tutorials/type-42.md +0 -14
- package/docs/tutorials/uhrp-storage.md +23 -3
- package/package.json +1 -1
- package/src/identity/README.md +0 -1
- package/src/primitives/__tests/SymmetricKey.test.ts +45 -0
- package/src/primitives/__tests/SymmetricKeyCompatibility.test.ts +150 -0
- package/src/transaction/__tests/Transaction.test.ts +1 -1
- package/src/transaction/broadcasters/DefaultBroadcaster.ts +1 -1
- package/src/transaction/broadcasters/__tests/ARC.test.ts +1 -1
package/docs/guides/index.md
CHANGED
|
@@ -5,26 +5,134 @@ Practical, problem-oriented guides to help you accomplish specific tasks with th
|
|
|
5
5
|
## Transaction Management
|
|
6
6
|
|
|
7
7
|
### [Transaction Signing Methods](./transaction-signing-methods.md)
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
- WalletClient approach for secure key management
|
|
9
10
|
- Low-level API approach for direct control
|
|
10
11
|
- Comparison of different signing methods
|
|
11
12
|
- Best practices for transaction signing
|
|
12
13
|
|
|
13
|
-
### [
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
14
|
+
### [Advanced Transaction Signing](./advanced-transaction-signing.md)
|
|
15
|
+
|
|
16
|
+
- Different signature hash types (SIGHASH flags)
|
|
17
|
+
- Manual signature creation
|
|
18
|
+
- Advanced verification techniques
|
|
19
|
+
- Multi-signature implementation
|
|
20
|
+
|
|
21
|
+
### [Creating Multi-signature Transactions](./multisig-transactions.md)
|
|
22
|
+
|
|
23
|
+
- Step-by-step multisig implementation
|
|
24
|
+
- Threshold signature schemes
|
|
25
|
+
- Key ceremony management
|
|
26
|
+
|
|
27
|
+
### [Implementing Transaction Batching](./transaction-batching.md)
|
|
28
|
+
|
|
29
|
+
- Batch multiple payments efficiently
|
|
30
|
+
- Fee optimization strategies
|
|
31
|
+
- Error handling for batch failures
|
|
32
|
+
|
|
33
|
+
### [Handling Large Transactions](./large-transactions.md)
|
|
34
|
+
|
|
35
|
+
- Memory management techniques
|
|
36
|
+
- Streaming transaction construction
|
|
37
|
+
- UTXO selection algorithms
|
|
38
|
+
|
|
39
|
+
## Cryptographic Operations
|
|
40
|
+
|
|
41
|
+
### [Security Best Practices](./security-best-practices.md)
|
|
42
|
+
|
|
43
|
+
- Private key management and protection
|
|
44
|
+
- Secure transaction construction
|
|
45
|
+
- Cryptographic operation security
|
|
46
|
+
- Wallet integration security patterns
|
|
47
|
+
- Production security checklist
|
|
48
|
+
|
|
49
|
+
### [Setting up Development Wallets](./development-wallet-setup.md)
|
|
50
|
+
|
|
51
|
+
- ProtoWallet configuration for development and testing
|
|
52
|
+
- Mock transaction creation and testing workflows
|
|
53
|
+
- Multi-wallet development environments
|
|
54
|
+
- Key management for development scenarios
|
|
55
|
+
|
|
56
|
+
### [Implementing Custom Key Derivation](./custom-key-derivation.md)
|
|
57
|
+
|
|
58
|
+
- BIP32-style hierarchical keys
|
|
59
|
+
- Custom derivation paths
|
|
60
|
+
- Key backup and recovery
|
|
61
|
+
|
|
62
|
+
### [Creating Encrypted Messages](./encrypted-messages.md)
|
|
63
|
+
|
|
64
|
+
- ECIES implementation
|
|
65
|
+
- Message encryption/decryption
|
|
66
|
+
- Key exchange protocols
|
|
67
|
+
|
|
68
|
+
### [Verifying Complex Signatures](./complex-signatures.md)
|
|
69
|
+
|
|
70
|
+
- Batch signature verification with performance optimization
|
|
71
|
+
- Threshold signature validation using polynomial interpolation
|
|
72
|
+
- Multi-context signature validation workflows
|
|
73
|
+
- Time-locked and conditional signature scenarios
|
|
74
|
+
- Comprehensive error handling and recovery strategies
|
|
75
|
+
- Security considerations for complex verification patterns
|
|
18
76
|
|
|
19
77
|
## Network Integration
|
|
20
78
|
|
|
79
|
+
### [Setting up Authenticated API Communication](./authenticated-api-communication.md)
|
|
80
|
+
|
|
81
|
+
- BRC-103/104 authentication implementation
|
|
82
|
+
- Certificate-based API security
|
|
83
|
+
- Session management and retry logic
|
|
84
|
+
- Secure peer-to-peer communication
|
|
85
|
+
|
|
86
|
+
### [Setting Up Chain Tracking](./chain-tracking.md)
|
|
87
|
+
|
|
88
|
+
- Configuring chain trackers for blockchain data access
|
|
89
|
+
- Using WhatsOnChain and other providers
|
|
90
|
+
- SPV verification with chain trackers
|
|
91
|
+
- Error handling and fallback strategies
|
|
92
|
+
|
|
21
93
|
### [Configuring HTTP Clients](./http-client-configuration.md)
|
|
94
|
+
|
|
22
95
|
- Axios integration and setup
|
|
23
96
|
- Custom request timeout configuration
|
|
24
97
|
- Error handling and retries
|
|
25
98
|
- Alternative HTTP client options
|
|
26
|
-
- Browser and Node.js environment considerations
|
|
27
99
|
|
|
28
|
-
|
|
100
|
+
### [Creating Custom Broadcasters](./custom-broadcasters.md)
|
|
101
|
+
|
|
102
|
+
- Implementing custom broadcaster interfaces
|
|
103
|
+
- HTTP-based broadcaster patterns
|
|
104
|
+
- Retry logic and error handling
|
|
105
|
+
- Multi-service failover strategies
|
|
106
|
+
|
|
107
|
+
### [Implementing Transaction Monitoring](./transaction-monitoring.md)
|
|
108
|
+
|
|
109
|
+
- Real-time transaction tracking
|
|
110
|
+
- Confirmation monitoring
|
|
111
|
+
- Double-spend detection
|
|
112
|
+
|
|
113
|
+
## File and Data Management
|
|
114
|
+
|
|
115
|
+
### [Implementing File Upload/Download Features](./file-upload-download.md)
|
|
116
|
+
|
|
117
|
+
- UHRP-based decentralized file storage
|
|
118
|
+
- File integrity verification and validation
|
|
119
|
+
- Batch file operations and management
|
|
120
|
+
- File retention and renewal strategies
|
|
121
|
+
|
|
122
|
+
## Identity and Access Management
|
|
123
|
+
|
|
124
|
+
### [Building Identity Verification Systems](./identity-verification-systems.md)
|
|
125
|
+
|
|
126
|
+
- Decentralized identity verification workflows
|
|
127
|
+
- Trust scoring and certificate validation
|
|
128
|
+
- Identity-based access control systems
|
|
129
|
+
- Verification history and audit trails
|
|
130
|
+
|
|
131
|
+
## Cross-Platform Integration
|
|
132
|
+
|
|
133
|
+
### [Working with React](./react-integration.md)
|
|
29
134
|
|
|
30
|
-
|
|
135
|
+
- Setting up the SDK in React projects
|
|
136
|
+
- State management for keys and transactions
|
|
137
|
+
- React component patterns for BSV applications
|
|
138
|
+
- React Native considerations
|
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
# Handling Large Bitcoin Transactions
|
|
2
|
+
|
|
3
|
+
This guide provides authoritative patterns and best practices for constructing, signing, and broadcasting large Bitcoin transactions using the BSV TypeScript SDK. All examples are based on actual SDK APIs and have been verified against the source code.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
1. [Understanding Large Transactions](#understanding-large-transactions)
|
|
8
|
+
2. [Memory Management Strategies](#memory-management-strategies)
|
|
9
|
+
3. [Efficient Transaction Construction](#efficient-transaction-construction)
|
|
10
|
+
4. [Batch Processing with `WalletClient`](#batch-processing-with-walletclient)
|
|
11
|
+
5. [Fee Calculation for Large Transactions](#fee-calculation-for-large-transactions)
|
|
12
|
+
6. [Signing Optimization](#signing-optimization)
|
|
13
|
+
7. [Broadcasting Strategies](#broadcasting-strategies)
|
|
14
|
+
8. [Error Handling and Recovery](#error-handling-and-recovery)
|
|
15
|
+
9. [Performance Monitoring](#performance-monitoring)
|
|
16
|
+
10. [Complete Example](#complete-example)
|
|
17
|
+
|
|
18
|
+
## Understanding Large Transactions
|
|
19
|
+
|
|
20
|
+
Large Bitcoin transactions typically involve:
|
|
21
|
+
|
|
22
|
+
- **Many inputs** (50+ UTXOs being consumed)
|
|
23
|
+
- **Many outputs** (50+ recipients or complex splitting)
|
|
24
|
+
- **Large scripts** (complex locking/unlocking conditions)
|
|
25
|
+
- **Chained transactions** (dependent transaction sequences)
|
|
26
|
+
|
|
27
|
+
The SDK provides several mechanisms to handle these efficiently.
|
|
28
|
+
|
|
29
|
+
## Memory Management Strategies
|
|
30
|
+
|
|
31
|
+
### Batch Input/Output Addition
|
|
32
|
+
|
|
33
|
+
Instead of adding inputs and outputs one by one, batch them to reduce memory allocations:
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { Transaction, TransactionInput, TransactionOutput, LockingScript, UnlockingScript } from '@bsv/sdk'
|
|
37
|
+
|
|
38
|
+
class LargeTransactionBuilder {
|
|
39
|
+
private transaction: Transaction
|
|
40
|
+
private inputBatch: TransactionInput[] = []
|
|
41
|
+
private outputBatch: TransactionOutput[] = []
|
|
42
|
+
private batchSize = 100
|
|
43
|
+
|
|
44
|
+
constructor() {
|
|
45
|
+
this.transaction = new Transaction()
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
addInputBatch(inputs: TransactionInput[]): void {
|
|
49
|
+
this.inputBatch.push(...inputs)
|
|
50
|
+
|
|
51
|
+
if (this.inputBatch.length >= this.batchSize) {
|
|
52
|
+
this.flushInputs()
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
addOutputBatch(outputs: TransactionOutput[]): void {
|
|
57
|
+
this.outputBatch.push(...outputs)
|
|
58
|
+
|
|
59
|
+
if (this.outputBatch.length >= this.batchSize) {
|
|
60
|
+
this.flushOutputs()
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private flushInputs(): void {
|
|
65
|
+
for (const input of this.inputBatch) {
|
|
66
|
+
this.transaction.addInput(input)
|
|
67
|
+
}
|
|
68
|
+
this.inputBatch = []
|
|
69
|
+
|
|
70
|
+
// Hint garbage collection for large batches
|
|
71
|
+
if (global.gc) {
|
|
72
|
+
global.gc()
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private flushOutputs(): void {
|
|
77
|
+
for (const output of this.outputBatch) {
|
|
78
|
+
this.transaction.addOutput(output)
|
|
79
|
+
}
|
|
80
|
+
this.outputBatch = []
|
|
81
|
+
|
|
82
|
+
if (global.gc) {
|
|
83
|
+
global.gc()
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
finalize(): Transaction {
|
|
88
|
+
this.flushInputs()
|
|
89
|
+
this.flushOutputs()
|
|
90
|
+
return this.transaction
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Example usage with TransactionInput and TransactionOutput creation
|
|
95
|
+
async function createLargeTransactionExample() {
|
|
96
|
+
const builder = new LargeTransactionBuilder()
|
|
97
|
+
|
|
98
|
+
// Create properly formatted inputs with required fields
|
|
99
|
+
const inputs: TransactionInput[] = []
|
|
100
|
+
for (let i = 0; i < 100; i++) {
|
|
101
|
+
inputs.push({
|
|
102
|
+
sourceTXID: '0'.repeat(64), // Replace with actual TXID
|
|
103
|
+
sourceOutputIndex: i,
|
|
104
|
+
unlockingScriptLength: 0,
|
|
105
|
+
unlockingScript: new UnlockingScript(), // Will be populated during signing
|
|
106
|
+
sequenceNumber: 0xffffffff
|
|
107
|
+
} as TransactionInput)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Create properly formatted outputs
|
|
111
|
+
const outputs: TransactionOutput[] = []
|
|
112
|
+
for (let i = 0; i < 100; i++) {
|
|
113
|
+
outputs.push({
|
|
114
|
+
satoshis: 100,
|
|
115
|
+
lockingScriptLength: 6,
|
|
116
|
+
lockingScript: LockingScript.fromASM('OP_RETURN 74657374') // OP_RETURN "test"
|
|
117
|
+
} as TransactionOutput)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
builder.addInputBatch(inputs)
|
|
121
|
+
builder.addOutputBatch(outputs)
|
|
122
|
+
|
|
123
|
+
return builder.finalize()
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Memory Pool Management
|
|
128
|
+
|
|
129
|
+
For extremely large transactions, implement a memory pool to manage object lifecycle:
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
class TransactionMemoryPool {
|
|
133
|
+
private inputPool: TransactionInput[] = []
|
|
134
|
+
private outputPool: TransactionOutput[] = []
|
|
135
|
+
private maxPoolSize = 1000
|
|
136
|
+
|
|
137
|
+
borrowInput(): TransactionInput {
|
|
138
|
+
return this.inputPool.pop() || {} as TransactionInput
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
borrowOutput(): TransactionOutput {
|
|
142
|
+
return this.outputPool.pop() || {} as TransactionOutput
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
returnInput(input: TransactionInput): void {
|
|
146
|
+
if (this.inputPool.length < this.maxPoolSize) {
|
|
147
|
+
// Clear the input for reuse
|
|
148
|
+
Object.keys(input).forEach(key => delete (input as any)[key])
|
|
149
|
+
this.inputPool.push(input)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
returnOutput(output: TransactionOutput): void {
|
|
154
|
+
if (this.outputPool.length < this.maxPoolSize) {
|
|
155
|
+
Object.keys(output).forEach(key => delete (output as any)[key])
|
|
156
|
+
this.outputPool.push(output)
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Efficient Transaction Construction
|
|
163
|
+
|
|
164
|
+
### Using the Transaction Constructor
|
|
165
|
+
|
|
166
|
+
The SDK's Transaction constructor accepts arrays of inputs and outputs, which is more efficient than individual additions:
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
import { Transaction, TransactionInput, TransactionOutput, LockingScript, UnlockingScript } from '@bsv/sdk'
|
|
170
|
+
|
|
171
|
+
function buildLargeTransaction(
|
|
172
|
+
inputs: TransactionInput[],
|
|
173
|
+
outputs: TransactionOutput[]
|
|
174
|
+
): Transaction {
|
|
175
|
+
// More efficient than multiple addInput/addOutput calls
|
|
176
|
+
return new Transaction(
|
|
177
|
+
1, // version
|
|
178
|
+
inputs,
|
|
179
|
+
outputs,
|
|
180
|
+
0, // lockTime
|
|
181
|
+
{}, // metadata
|
|
182
|
+
undefined // merklePath
|
|
183
|
+
)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Example usage with properly formatted inputs and outputs
|
|
187
|
+
function createExampleTransaction(): Transaction {
|
|
188
|
+
const inputs: TransactionInput[] = [{
|
|
189
|
+
sourceTXID: '0'.repeat(64), // Replace with actual TXID
|
|
190
|
+
sourceOutputIndex: 0,
|
|
191
|
+
unlockingScriptLength: 0,
|
|
192
|
+
unlockingScript: new UnlockingScript(),
|
|
193
|
+
sequenceNumber: 0xffffffff
|
|
194
|
+
} as TransactionInput]
|
|
195
|
+
|
|
196
|
+
const outputs: TransactionOutput[] = [{
|
|
197
|
+
satoshis: 100,
|
|
198
|
+
lockingScriptLength: 6,
|
|
199
|
+
lockingScript: LockingScript.fromASM('OP_RETURN 74657374') // OP_RETURN "test"
|
|
200
|
+
} as TransactionOutput]
|
|
201
|
+
|
|
202
|
+
return buildLargeTransaction(inputs, outputs)
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Chunked Processing
|
|
207
|
+
|
|
208
|
+
For very large input/output sets, process them in chunks:
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
async function processLargeInputSet(
|
|
212
|
+
allInputs: TransactionInput[],
|
|
213
|
+
chunkSize: number = 50
|
|
214
|
+
): Promise<Transaction[]> {
|
|
215
|
+
const transactions: Transaction[] = []
|
|
216
|
+
|
|
217
|
+
for (let i = 0; i < allInputs.length; i += chunkSize) {
|
|
218
|
+
const chunk = allInputs.slice(i, i + chunkSize)
|
|
219
|
+
const tx = new Transaction(1, chunk, [])
|
|
220
|
+
|
|
221
|
+
// Process chunk
|
|
222
|
+
await tx.fee()
|
|
223
|
+
await tx.sign()
|
|
224
|
+
|
|
225
|
+
transactions.push(tx)
|
|
226
|
+
|
|
227
|
+
// Allow event loop to process other tasks
|
|
228
|
+
await new Promise(resolve => setImmediate(resolve))
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return transactions
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Batch Processing with `WalletClient`
|
|
236
|
+
|
|
237
|
+
The SDK's `WalletClient` provides built-in batching capabilities for large transaction workflows:
|
|
238
|
+
|
|
239
|
+
### Chained Transaction Batching
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
import { WalletClient, CreateActionArgs } from '@bsv/sdk'
|
|
243
|
+
|
|
244
|
+
class BatchTransactionProcessor {
|
|
245
|
+
private walletClient: WalletClient
|
|
246
|
+
private maxRetries: number = 3
|
|
247
|
+
private retryDelay: number = 1000
|
|
248
|
+
|
|
249
|
+
constructor(walletClient: WalletClient) {
|
|
250
|
+
this.walletClient = walletClient
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
async createChainedBatch(actions: CreateActionArgs[]): Promise<string[]> {
|
|
254
|
+
const txids: string[] = []
|
|
255
|
+
const batchReferences: string[] = []
|
|
256
|
+
|
|
257
|
+
// Create all transactions without sending (noSend: true)
|
|
258
|
+
for (let i = 0; i < actions.length; i++) {
|
|
259
|
+
const action = {
|
|
260
|
+
...actions[i],
|
|
261
|
+
options: {
|
|
262
|
+
...actions[i].options,
|
|
263
|
+
noSend: true,
|
|
264
|
+
// Include previous transaction outputs as known
|
|
265
|
+
knownTxids: txids
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const result = await this.walletClient.createAction(action)
|
|
270
|
+
|
|
271
|
+
if (result.signableTransaction) {
|
|
272
|
+
// Sign the transaction
|
|
273
|
+
const signResult = await this.walletClient.signAction({
|
|
274
|
+
spends: this.generateSpends(action),
|
|
275
|
+
reference: result.signableTransaction.reference,
|
|
276
|
+
options: { noSend: true }
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
if (signResult.txid) {
|
|
280
|
+
txids.push(signResult.txid)
|
|
281
|
+
batchReferences.push(result.signableTransaction.reference)
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Send all transactions as a batch
|
|
287
|
+
if (batchReferences.length > 0) {
|
|
288
|
+
await this.walletClient.signAction({
|
|
289
|
+
spends: {},
|
|
290
|
+
reference: batchReferences[0],
|
|
291
|
+
options: {
|
|
292
|
+
sendWith: txids
|
|
293
|
+
}
|
|
294
|
+
})
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return txids
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
private generateSpends(action: CreateActionArgs): Record<number, any> {
|
|
301
|
+
const spends: Record<number, any> = {}
|
|
302
|
+
|
|
303
|
+
if (action.inputs) {
|
|
304
|
+
action.inputs.forEach((input, index) => {
|
|
305
|
+
spends[index] = {
|
|
306
|
+
unlockingScript: input.unlockingScript || '',
|
|
307
|
+
sequenceNumber: input.sequenceNumber || 0xffffffff
|
|
308
|
+
}
|
|
309
|
+
})
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return spends
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Progress Tracking for Large Batches
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
interface BatchProgress {
|
|
321
|
+
total: number
|
|
322
|
+
completed: number
|
|
323
|
+
failed: number
|
|
324
|
+
currentPhase: 'creating' | 'signing' | 'broadcasting'
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
class ProgressTrackingBatch {
|
|
328
|
+
async processBatchWithProgress(
|
|
329
|
+
actions: CreateActionArgs[],
|
|
330
|
+
onProgress?: (progress: BatchProgress) => void
|
|
331
|
+
): Promise<string[]> {
|
|
332
|
+
this.progress.total = actions.length
|
|
333
|
+
this.progress.currentPhase = 'creating'
|
|
334
|
+
|
|
335
|
+
const results: string[] = []
|
|
336
|
+
|
|
337
|
+
for (let i = 0; i < actions.length; i++) {
|
|
338
|
+
try {
|
|
339
|
+
const result = await this.walletClient.createAction(actions[i])
|
|
340
|
+
|
|
341
|
+
if (result.txid) {
|
|
342
|
+
results.push(result.txid)
|
|
343
|
+
this.progress.completed++
|
|
344
|
+
}
|
|
345
|
+
} catch (error) {
|
|
346
|
+
console.error(`Failed to process action ${i}:`, error)
|
|
347
|
+
this.progress.failed++
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (onProgress) {
|
|
351
|
+
onProgress({ ...this.progress })
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Throttle to prevent overwhelming the wallet
|
|
355
|
+
if (i % 10 === 0) {
|
|
356
|
+
await new Promise(resolve => setTimeout(resolve, 100))
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return results
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## Fee Calculation for Large Transactions
|
|
366
|
+
|
|
367
|
+
### Custom Fee Models
|
|
368
|
+
|
|
369
|
+
The SDK provides a `FeeModel` interface and `SatoshisPerKilobyte` implementation:
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
import { SatoshisPerKilobyte, Transaction } from '@bsv/sdk'
|
|
373
|
+
|
|
374
|
+
// FeeModel interface definition (since it's not exported from SDK)
|
|
375
|
+
interface FeeModel {
|
|
376
|
+
computeFee(transaction: Transaction): Promise<number>
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
class OptimizedFeeModel implements FeeModel {
|
|
380
|
+
private baseFeeModel: SatoshisPerKilobyte
|
|
381
|
+
private largeTxThreshold: number
|
|
382
|
+
|
|
383
|
+
constructor(
|
|
384
|
+
baseSatPerKb: number = 1,
|
|
385
|
+
largeTxThreshold: number = 100000 // 100KB
|
|
386
|
+
) {
|
|
387
|
+
this.baseFeeModel = new SatoshisPerKilobyte(baseSatPerKb)
|
|
388
|
+
this.largeTxThreshold = largeTxThreshold
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
async computeFee(transaction: Transaction): Promise<number> {
|
|
392
|
+
const baseFee = await this.baseFeeModel.computeFee(transaction)
|
|
393
|
+
const txSize = transaction.toBinary().length
|
|
394
|
+
|
|
395
|
+
// Apply discount for large transactions
|
|
396
|
+
if (txSize > this.largeTxThreshold) {
|
|
397
|
+
const discount = Math.min(0.5, (txSize - this.largeTxThreshold) / 1000000)
|
|
398
|
+
return Math.floor(baseFee * (1 - discount))
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
return baseFee
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Usage
|
|
406
|
+
async function calculateOptimizedFee(transaction: Transaction): Promise<void> {
|
|
407
|
+
const feeModel = new OptimizedFeeModel(1, 50000)
|
|
408
|
+
await transaction.fee(feeModel)
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Batch Fee Calculation
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
async function calculateFeesInBatch(
|
|
416
|
+
transactions: Transaction[],
|
|
417
|
+
feeModel: FeeModel
|
|
418
|
+
): Promise<number[]> {
|
|
419
|
+
const feePromises = transactions.map(tx => feeModel.computeFee(tx))
|
|
420
|
+
return Promise.all(feePromises)
|
|
421
|
+
}
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
## Conclusion
|
|
425
|
+
|
|
426
|
+
Handling large Bitcoin transactions efficiently requires a comprehensive approach that addresses memory management, performance optimization, and robust error handling. The BSV TypeScript SDK provides powerful tools and patterns to manage these challenges effectively.
|
|
427
|
+
|
|
428
|
+
### Next Steps
|
|
429
|
+
|
|
430
|
+
To implement large transaction handling in your application:
|
|
431
|
+
|
|
432
|
+
1. **Start Simple**: Begin with the `LargeTransactionBuilder` pattern for basic batching
|
|
433
|
+
2. **Add Streaming**: Implement `StreamingTransactionBuilder` for memory-constrained scenarios
|
|
434
|
+
3. **Optimize Performance**: Add caching and parallel processing using the optimization patterns
|
|
435
|
+
4. **Enhance Monitoring**: Integrate the monitoring and error handling examples
|
|
436
|
+
5. **Test Thoroughly**: Use the validation patterns to ensure transaction integrity
|
|
437
|
+
|
|
438
|
+
### Related Documentation
|
|
439
|
+
|
|
440
|
+
For additional context and complementary patterns, see:
|
|
441
|
+
|
|
442
|
+
- [Transaction Batching](./transaction-batching.md) - Efficient multi-output transaction patterns
|
|
443
|
+
- [Error Handling](./error-handling.md) - Comprehensive error management strategies
|
|
444
|
+
- [Performance Optimization](./performance-optimization.md) - General SDK performance patterns
|
|
445
|
+
- [Advanced Transaction Signing](./advanced-transaction-signing.md) - Signing optimization for large transactions
|
|
446
|
+
- [Transaction Monitoring](./transaction-monitoring.md) - Monitoring and alerting for transaction operations
|
|
447
|
+
|
|
448
|
+
The techniques in this guide enable you to build robust, scalable Bitcoin applications that can handle enterprise-level transaction volumes while maintaining security, performance, and reliability standards.
|