@bsv/sdk 1.9.2 → 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.
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/kvstore/GlobalKVStore.js +116 -98
- package/dist/cjs/src/kvstore/GlobalKVStore.js.map +1 -1
- package/dist/cjs/src/kvstore/types.js.map +1 -1
- package/dist/cjs/src/overlay-tools/index.js +1 -0
- package/dist/cjs/src/overlay-tools/index.js.map +1 -1
- package/dist/cjs/src/overlay-tools/withDoubleSpendRetry.js +55 -0
- package/dist/cjs/src/overlay-tools/withDoubleSpendRetry.js.map +1 -0
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/kvstore/GlobalKVStore.js +117 -99
- package/dist/esm/src/kvstore/GlobalKVStore.js.map +1 -1
- package/dist/esm/src/kvstore/types.js.map +1 -1
- package/dist/esm/src/overlay-tools/index.js +1 -0
- package/dist/esm/src/overlay-tools/index.js.map +1 -1
- package/dist/esm/src/overlay-tools/withDoubleSpendRetry.js +48 -0
- package/dist/esm/src/overlay-tools/withDoubleSpendRetry.js.map +1 -0
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/kvstore/GlobalKVStore.d.ts.map +1 -1
- package/dist/types/src/kvstore/types.d.ts +2 -0
- package/dist/types/src/kvstore/types.d.ts.map +1 -1
- package/dist/types/src/overlay-tools/index.d.ts +1 -0
- package/dist/types/src/overlay-tools/index.d.ts.map +1 -1
- package/dist/types/src/overlay-tools/withDoubleSpendRetry.d.ts +14 -0
- package/dist/types/src/overlay-tools/withDoubleSpendRetry.d.ts.map +1 -0
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +2 -2
- package/dist/umd/bundle.js.map +1 -1
- package/docs/fast-docs.png +0 -0
- package/docs/index.md +49 -44
- package/docs/reference/kvstore.md +9 -0
- package/docs/reference/overlay-tools.md +32 -0
- package/docs/swagger.png +0 -0
- package/package.json +1 -1
- package/src/kvstore/GlobalKVStore.ts +134 -114
- package/src/kvstore/__tests/GlobalKVStore.test.ts +11 -1
- package/src/kvstore/types.ts +2 -0
- package/src/overlay-tools/index.ts +1 -0
- package/src/overlay-tools/withDoubleSpendRetry.ts +71 -0
- package/docs/MARKDOWN_VALIDATION_GUIDE.md +0 -175
- package/docs/concepts/beef.md +0 -92
- package/docs/concepts/chain-tracking.md +0 -134
- package/docs/concepts/decentralized-identity.md +0 -221
- package/docs/concepts/fees.md +0 -249
- package/docs/concepts/identity-certificates.md +0 -307
- package/docs/concepts/index.md +0 -77
- package/docs/concepts/key-management.md +0 -185
- package/docs/concepts/script-templates.md +0 -176
- package/docs/concepts/sdk-philosophy.md +0 -80
- package/docs/concepts/signatures.md +0 -194
- package/docs/concepts/spv-verification.md +0 -118
- package/docs/concepts/transaction-encoding.md +0 -167
- package/docs/concepts/transaction-structure.md +0 -67
- package/docs/concepts/trust-model.md +0 -139
- package/docs/concepts/verification.md +0 -250
- package/docs/concepts/wallet-integration.md +0 -101
- package/docs/guides/development-wallet-setup.md +0 -374
- package/docs/guides/direct-transaction-creation.md +0 -147
- package/docs/guides/http-client-configuration.md +0 -488
- package/docs/guides/index.md +0 -138
- package/docs/guides/large-transactions.md +0 -448
- package/docs/guides/multisig-transactions.md +0 -792
- package/docs/guides/security-best-practices.md +0 -494
- package/docs/guides/transaction-batching.md +0 -132
- package/docs/guides/transaction-signing-methods.md +0 -419
- package/docs/reference/arc-config.md +0 -698
- package/docs/reference/brc-100.md +0 -33
- package/docs/reference/configuration.md +0 -835
- package/docs/reference/debugging.md +0 -705
- package/docs/reference/errors.md +0 -597
- package/docs/reference/index.md +0 -111
- package/docs/reference/network-config.md +0 -914
- package/docs/reference/op-codes.md +0 -325
- package/docs/reference/transaction-signatures.md +0 -95
- package/docs/tutorials/advanced-transaction.md +0 -572
- package/docs/tutorials/aes-encryption.md +0 -949
- package/docs/tutorials/authfetch-tutorial.md +0 -986
- package/docs/tutorials/ecdh-key-exchange.md +0 -549
- package/docs/tutorials/elliptic-curve-fundamentals.md +0 -606
- package/docs/tutorials/error-handling.md +0 -1216
- package/docs/tutorials/first-transaction-low-level.md +0 -205
- package/docs/tutorials/first-transaction.md +0 -275
- package/docs/tutorials/hashes-and-hmacs.md +0 -788
- package/docs/tutorials/identity-management.md +0 -729
- package/docs/tutorials/index.md +0 -219
- package/docs/tutorials/key-management.md +0 -538
- package/docs/tutorials/protowallet-development.md +0 -743
- package/docs/tutorials/script-construction.md +0 -690
- package/docs/tutorials/spv-merkle-proofs.md +0 -685
- package/docs/tutorials/testnet-transactions-low-level.md +0 -359
- package/docs/tutorials/transaction-broadcasting.md +0 -538
- package/docs/tutorials/transaction-types.md +0 -420
- package/docs/tutorials/type-42.md +0 -568
- package/docs/tutorials/uhrp-storage.md +0 -599
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
# Creating Transactions with Direct Interfaces
|
|
2
|
-
|
|
3
|
-
This guide demonstrates how to create Bitcoin SV transactions using the lower-level direct interfaces provided by the BSV TypeScript SDK. This approach gives you more control over transaction construction and is useful for specialized use cases where the `WalletClient` abstraction isn't suitable.
|
|
4
|
-
|
|
5
|
-
## When to Use Direct Interfaces
|
|
6
|
-
|
|
7
|
-
- When creating custom transaction types not supported by `WalletClient`
|
|
8
|
-
- When you need precise control over UTXO selection
|
|
9
|
-
- When building specialized applications like data storage services that require custom optimization
|
|
10
|
-
- When integrating with systems that require direct management of transactions
|
|
11
|
-
- For educational purposes to understand the underlying transaction structure
|
|
12
|
-
|
|
13
|
-
## Basic Transaction Construction
|
|
14
|
-
|
|
15
|
-
```typescript
|
|
16
|
-
import { PrivateKey, P2PKH, Transaction } from '@bsv/sdk'
|
|
17
|
-
|
|
18
|
-
async function createBasicTransaction() {
|
|
19
|
-
// Create a private key
|
|
20
|
-
const privateKey = PrivateKey.fromRandom()
|
|
21
|
-
console.log(`Private key WIF: ${privateKey.toWif()}`)
|
|
22
|
-
|
|
23
|
-
// Derive the address
|
|
24
|
-
const address = privateKey.toAddress()
|
|
25
|
-
console.log(`Address: ${address.toString()}`)
|
|
26
|
-
|
|
27
|
-
// Create a new transaction
|
|
28
|
-
const tx = new Transaction()
|
|
29
|
-
|
|
30
|
-
// Add an output
|
|
31
|
-
tx.addOutput({
|
|
32
|
-
lockingScript: new P2PKH().lock(address),
|
|
33
|
-
satoshis: 1000
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
// Serialize the transaction
|
|
37
|
-
const txHex = tx.toHex()
|
|
38
|
-
console.log(`Transaction (hex): ${txHex}`)
|
|
39
|
-
|
|
40
|
-
// Get transaction ID as a hex string
|
|
41
|
-
const txid = Buffer.from(tx.id()).toString('hex')
|
|
42
|
-
console.log(`Transaction ID: ${txid}`)
|
|
43
|
-
}
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Complete Transaction with Inputs and Outputs
|
|
47
|
-
|
|
48
|
-
For a complete transaction that can be broadcast, you need to add inputs, calculate fees, and sign it:
|
|
49
|
-
|
|
50
|
-
```typescript
|
|
51
|
-
import { Transaction, PrivateKey, P2PKH, ARC } from '@bsv/sdk'
|
|
52
|
-
|
|
53
|
-
async function createCompleteTransaction() {
|
|
54
|
-
// Set up your wallet
|
|
55
|
-
const privateKey = PrivateKey.fromWif('your_private_key_here')
|
|
56
|
-
const myAddress = privateKey.toAddress()
|
|
57
|
-
const recipientAddress = 'recipient_address_here'
|
|
58
|
-
|
|
59
|
-
// You need the hex of the source transaction
|
|
60
|
-
const sourceTxHex = '...' // Hex string of the source transaction
|
|
61
|
-
|
|
62
|
-
// Create a transaction
|
|
63
|
-
const tx = new Transaction()
|
|
64
|
-
|
|
65
|
-
// Add the input
|
|
66
|
-
tx.addInput({
|
|
67
|
-
sourceTransaction: Transaction.fromHex(sourceTxHex),
|
|
68
|
-
sourceOutputIndex: 0, // The output index you want to spend
|
|
69
|
-
unlockingScriptTemplate: new P2PKH().unlock(privateKey)
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
// Add the recipient output
|
|
73
|
-
tx.addOutput({
|
|
74
|
-
lockingScript: new P2PKH().lock(recipientAddress),
|
|
75
|
-
satoshis: 100 // Amount to send
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
// Add the change output back to our address
|
|
79
|
-
tx.addOutput({
|
|
80
|
-
lockingScript: new P2PKH().lock(myAddress),
|
|
81
|
-
change: true // SDK will automatically calculate the change amount
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
// Calculate fee and sign the transaction
|
|
85
|
-
await tx.fee()
|
|
86
|
-
await tx.sign()
|
|
87
|
-
|
|
88
|
-
// Get the transaction hex ready for broadcasting
|
|
89
|
-
const signedTxHex = tx.toHex()
|
|
90
|
-
console.log(`Signed transaction hex: ${signedTxHex}`)
|
|
91
|
-
|
|
92
|
-
// Get the transaction ID
|
|
93
|
-
const txid = Buffer.from(tx.id()).toString('hex')
|
|
94
|
-
console.log(`Transaction ID: ${txid}`)
|
|
95
|
-
}
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## Broadcasting the Transaction
|
|
99
|
-
|
|
100
|
-
To broadcast your signed transaction:
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
import { ARC, NodejsHttpClient } from '@bsv/sdk'
|
|
104
|
-
import https from 'https'
|
|
105
|
-
|
|
106
|
-
async function broadcastTransaction(signedTx) {
|
|
107
|
-
// Create an HTTP client
|
|
108
|
-
const httpClient = new NodejsHttpClient(https)
|
|
109
|
-
|
|
110
|
-
// Initialize the ARC client
|
|
111
|
-
const arc = new ARC('https://api.arc.taal.com', {
|
|
112
|
-
apiKey: 'your_api_key_here',
|
|
113
|
-
httpClient,
|
|
114
|
-
deploymentId: 'your-deployment-id'
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
// Broadcast the transaction
|
|
118
|
-
const result = await signedTx.broadcast(arc)
|
|
119
|
-
console.log('Broadcast result:', result)
|
|
120
|
-
}
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
## Key Implementation Details
|
|
124
|
-
|
|
125
|
-
When working with direct interfaces, remember these important details:
|
|
126
|
-
|
|
127
|
-
1. Use `toWif()` (lowercase 'f') not `toWIF()` for private key WIF format
|
|
128
|
-
2. Use `toHex()` instead of `toString()` for transaction serialization
|
|
129
|
-
3. Transaction IDs need to be converted from byte arrays: `Buffer.from(tx.id()).toString('hex')`
|
|
130
|
-
4. For script objects, use `toHex()` or `toASM()` rather than `toString()`
|
|
131
|
-
5. Method chaining doesn't work well with current API - use separate method calls
|
|
132
|
-
|
|
133
|
-
## Direct Creation vs `WalletClient` Approach
|
|
134
|
-
|
|
135
|
-
| Feature | Direct Creation | `WalletClient` |
|
|
136
|
-
| --- | --- | --- |
|
|
137
|
-
| Control over transaction structure | High | Low |
|
|
138
|
-
| Complexity | High | Low |
|
|
139
|
-
| Recommended use case | Specialized applications | Production applications |
|
|
140
|
-
|
|
141
|
-
This guide focuses on direct transaction creation using low-level APIs, which gives you complete control over every aspect of the transaction. For simpler applications, consider using the `WalletClient` approach covered in other tutorials.
|
|
142
|
-
|
|
143
|
-
## Related Resources
|
|
144
|
-
|
|
145
|
-
- For simpler implementations, see the [Creating Transactions with WalletClient](../tutorials/first-transaction.md) tutorial
|
|
146
|
-
- Learn about [Advanced Transaction Signing](./advanced-transaction-signing.md)
|
|
147
|
-
- Explore [HTTP Client Configuration](./http-client-configuration.md) for optimizing API requests
|
|
@@ -1,488 +0,0 @@
|
|
|
1
|
-
# Configuring HTTP Clients
|
|
2
|
-
|
|
3
|
-
This guide covers how to configure HTTP clients for use with the BSV TypeScript SDK, focusing on Axios and alternatives for general HTTP operations, transaction broadcasting, and SDK infrastructure.
|
|
4
|
-
|
|
5
|
-
## When to Use This Guide
|
|
6
|
-
|
|
7
|
-
**Use this guide when you need:**
|
|
8
|
-
|
|
9
|
-
- Custom HTTP client setup for SDK operations (Axios, fetch, etc.)
|
|
10
|
-
- Transaction broadcasting via ARC endpoints
|
|
11
|
-
- Environment-specific HTTP configuration (timeouts, retries, headers)
|
|
12
|
-
- Testing and mocking HTTP clients for SDK functionality
|
|
13
|
-
- Integration with existing HTTP infrastructure
|
|
14
|
-
|
|
15
|
-
**For authenticated peer-to-peer communication, use [AuthFetch Tutorial](../tutorials/authfetch-tutorial.md) instead:**
|
|
16
|
-
|
|
17
|
-
- BRC-103/104 cryptographic authentication
|
|
18
|
-
- Wallet-signed HTTP requests
|
|
19
|
-
- Certificate-based peer verification
|
|
20
|
-
- Secure application-to-application communication
|
|
21
|
-
|
|
22
|
-
> **📚 Related Concepts**: This guide relates to [Chain Tracking](../concepts/chain-tracking.md) and [SDK Design Philosophy](../concepts/sdk-philosophy.md) for understanding network interaction patterns.
|
|
23
|
-
|
|
24
|
-
## Using Axios with the SDK
|
|
25
|
-
|
|
26
|
-
The BSV TypeScript SDK allows you to provide your own HTTP client implementation for network requests. This is particularly useful when you need custom configuration for transaction broadcasting, network queries, or when working in specific environments.
|
|
27
|
-
|
|
28
|
-
### Basic Axios Setup
|
|
29
|
-
|
|
30
|
-
```typescript
|
|
31
|
-
import axios from 'axios'
|
|
32
|
-
import { BSV } from '@bsv/sdk'
|
|
33
|
-
|
|
34
|
-
// Create a configured Axios instance
|
|
35
|
-
const customAxios = axios.create({
|
|
36
|
-
timeout: 10000, // 10 seconds
|
|
37
|
-
headers: {
|
|
38
|
-
'Content-Type': 'application/json',
|
|
39
|
-
'Accept': 'application/json'
|
|
40
|
-
}
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
// Use the custom client when broadcasting transactions
|
|
44
|
-
const broadcastTransaction = async (tx) => {
|
|
45
|
-
try {
|
|
46
|
-
// Create a simple transaction with P2PKH output
|
|
47
|
-
const tx = new Transaction()
|
|
48
|
-
const privateKey = PrivateKey.fromRandom()
|
|
49
|
-
const publicKey = privateKey.toPublicKey()
|
|
50
|
-
const address = publicKey.toAddress()
|
|
51
|
-
|
|
52
|
-
// Add an output using P2PKH (instantiate the class first)
|
|
53
|
-
const p2pkh = new P2PKH()
|
|
54
|
-
const lockingScript = p2pkh.lock(address)
|
|
55
|
-
tx.addOutput({
|
|
56
|
-
satoshis: 100,
|
|
57
|
-
lockingScript
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
// Convert the transaction to hex format
|
|
61
|
-
const txHex = tx.toHex()
|
|
62
|
-
|
|
63
|
-
// Use your custom axios instance for the request
|
|
64
|
-
const response = await customAxios.post('https://api.example.com/v1/tx/broadcast', {
|
|
65
|
-
rawTx: txHex
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
return response.data
|
|
69
|
-
} catch (error) {
|
|
70
|
-
console.error('Error broadcasting transaction:', error)
|
|
71
|
-
throw error
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### Using Axios with ARC Broadcaster
|
|
77
|
-
|
|
78
|
-
The ARC (Alternative Revenue Channel) broadcaster can be configured with a custom HTTP client:
|
|
79
|
-
|
|
80
|
-
```typescript
|
|
81
|
-
import axios from 'axios'
|
|
82
|
-
import { ARC } from '@bsv/sdk'
|
|
83
|
-
|
|
84
|
-
// Configure Axios
|
|
85
|
-
const customAxios = axios.create({
|
|
86
|
-
timeout: 15000,
|
|
87
|
-
headers: {
|
|
88
|
-
'Authorization': 'Bearer YOUR_API_KEY',
|
|
89
|
-
'Content-Type': 'application/json'
|
|
90
|
-
}
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
// Create an adapter to make Axios compatible with HttpClient interface
|
|
94
|
-
class AxiosAdapter {
|
|
95
|
-
constructor(private axiosInstance: any) {}
|
|
96
|
-
|
|
97
|
-
async request(url: string, options: any = {}) {
|
|
98
|
-
const response = await this.axiosInstance({
|
|
99
|
-
url,
|
|
100
|
-
method: options.method || 'GET',
|
|
101
|
-
data: options.body,
|
|
102
|
-
headers: options.headers
|
|
103
|
-
})
|
|
104
|
-
return response.data
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Create an ARC instance with custom HTTP client
|
|
109
|
-
const httpClient = new AxiosAdapter(customAxios)
|
|
110
|
-
const arc = new ARC('https://api.taal.com/arc', {
|
|
111
|
-
apiKey: 'YOUR_API_KEY',
|
|
112
|
-
httpClient
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
// Use the configured ARC instance to broadcast a transaction
|
|
116
|
-
const broadcastWithARC = async (tx) => {
|
|
117
|
-
try {
|
|
118
|
-
// ARC expects hex format
|
|
119
|
-
const txid = await arc.broadcast(tx.toHex())
|
|
120
|
-
return txid
|
|
121
|
-
} catch (error) {
|
|
122
|
-
console.error('ARC broadcast error:', error)
|
|
123
|
-
throw error
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
## Advanced HTTP Client Configuration
|
|
129
|
-
|
|
130
|
-
### Handling Timeouts and Retries
|
|
131
|
-
|
|
132
|
-
```typescript
|
|
133
|
-
import axios from 'axios'
|
|
134
|
-
import axiosRetry from 'axios-retry'
|
|
135
|
-
|
|
136
|
-
// Create a custom Axios instance
|
|
137
|
-
const client = axios.create({
|
|
138
|
-
timeout: 30000 // 30 seconds
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
// Configure automatic retries
|
|
142
|
-
axiosRetry(client, {
|
|
143
|
-
retries: 3,
|
|
144
|
-
retryDelay: axiosRetry.exponentialDelay,
|
|
145
|
-
retryCondition: (error: any) => {
|
|
146
|
-
// Retry on network errors or 5xx responses
|
|
147
|
-
return axiosRetry.isNetworkOrIdempotentRequestError(error) ||
|
|
148
|
-
(error.response && error.response.status >= 500)
|
|
149
|
-
}
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
// Add request interceptor for logging
|
|
153
|
-
client.interceptors.request.use((request: any) => {
|
|
154
|
-
console.log('Starting request:', request.url)
|
|
155
|
-
return request
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
// Add response interceptor for error handling
|
|
159
|
-
client.interceptors.response.use(
|
|
160
|
-
response => response,
|
|
161
|
-
error => {
|
|
162
|
-
if (error.response) {
|
|
163
|
-
console.error('Server responded with error:', error.response.status, error.response.data)
|
|
164
|
-
} else if (error.request) {
|
|
165
|
-
console.error('No response received:', error.request)
|
|
166
|
-
} else {
|
|
167
|
-
console.error('Error setting up request:', error.message)
|
|
168
|
-
}
|
|
169
|
-
return Promise.reject(error)
|
|
170
|
-
}
|
|
171
|
-
)
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
### Environment-specific Configuration
|
|
175
|
-
|
|
176
|
-
```typescript
|
|
177
|
-
import axios from 'axios'
|
|
178
|
-
|
|
179
|
-
const getConfiguredClient = (environment: 'production' | 'staging' | 'development' = 'production') => {
|
|
180
|
-
const baseURLs: Record<string, string> = {
|
|
181
|
-
production: 'https://api.taal.com',
|
|
182
|
-
staging: 'https://api-staging.taal.com',
|
|
183
|
-
development: 'http://localhost:3000'
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const timeouts: Record<string, number> = {
|
|
187
|
-
production: 10000,
|
|
188
|
-
staging: 15000,
|
|
189
|
-
development: 30000
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return axios.create({
|
|
193
|
-
baseURL: baseURLs[environment],
|
|
194
|
-
timeout: timeouts[environment],
|
|
195
|
-
headers: {
|
|
196
|
-
'Content-Type': 'application/json'
|
|
197
|
-
}
|
|
198
|
-
})
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
const productionClient = getConfiguredClient('production')
|
|
202
|
-
const developmentClient = getConfiguredClient('development')
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
## SDK Built-in HTTP Clients
|
|
206
|
-
|
|
207
|
-
The BSV TypeScript SDK comes with built-in HTTP client implementations that you can use directly. The SDK automatically selects the appropriate client based on your environment through the `defaultHttpClient()` function.
|
|
208
|
-
|
|
209
|
-
### Using NodejsHttpClient
|
|
210
|
-
|
|
211
|
-
The SDK includes a Node.js-specific HTTP client implementation that uses the Node.js `https` module:
|
|
212
|
-
|
|
213
|
-
```typescript
|
|
214
|
-
import { NodejsHttpClient } from '@bsv/sdk'
|
|
215
|
-
import https from 'https'
|
|
216
|
-
|
|
217
|
-
// Create a NodejsHttpClient instance
|
|
218
|
-
const nodeClient = new NodejsHttpClient(https)
|
|
219
|
-
|
|
220
|
-
// Use with ARC
|
|
221
|
-
const arc = new ARC('https://api.taal.com/arc', {
|
|
222
|
-
apiKey: 'your-api-key',
|
|
223
|
-
httpClient: nodeClient
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
// Example of broadcasting a transaction
|
|
227
|
-
const broadcastTx = async (tx) => {
|
|
228
|
-
try {
|
|
229
|
-
const txid = await arc.broadcast(tx)
|
|
230
|
-
console.log('Transaction broadcast successful. TXID:', txid)
|
|
231
|
-
return txid
|
|
232
|
-
} catch (error) {
|
|
233
|
-
console.error('Error broadcasting transaction:', error)
|
|
234
|
-
throw error
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
### Using Built-in FetchHttpClient
|
|
240
|
-
|
|
241
|
-
In browser environments, the SDK provides a `FetchHttpClient` implementation that uses the Fetch API:
|
|
242
|
-
|
|
243
|
-
```typescript
|
|
244
|
-
import { FetchHttpClient, ARC } from '@bsv/sdk'
|
|
245
|
-
|
|
246
|
-
// Create a FetchHttpClient instance with custom fetch options
|
|
247
|
-
const fetchClient = new FetchHttpClient(window.fetch.bind(window))
|
|
248
|
-
|
|
249
|
-
// Use with ARC
|
|
250
|
-
const arc = new ARC('https://api.taal.com/arc', {
|
|
251
|
-
apiKey: 'your-api-key',
|
|
252
|
-
httpClient: fetchClient
|
|
253
|
-
})
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
### Using defaultHttpClient
|
|
257
|
-
|
|
258
|
-
The SDK provides a `defaultHttpClient()` function that automatically selects the appropriate HTTP client based on the environment:
|
|
259
|
-
|
|
260
|
-
```typescript
|
|
261
|
-
import { defaultHttpClient, ARC } from '@bsv/sdk'
|
|
262
|
-
|
|
263
|
-
// Get the default HTTP client for the current environment
|
|
264
|
-
const client = defaultHttpClient()
|
|
265
|
-
|
|
266
|
-
// Use with ARC
|
|
267
|
-
const arc = new ARC('https://api.taal.com/arc', {
|
|
268
|
-
apiKey: 'your-api-key',
|
|
269
|
-
httpClient: client
|
|
270
|
-
})
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
## Alternative HTTP Clients
|
|
274
|
-
|
|
275
|
-
While the SDK provides built-in HTTP clients and Axios is commonly used, you can implement your own HTTP clients with the BSV TypeScript SDK:
|
|
276
|
-
|
|
277
|
-
### Using Fetch API
|
|
278
|
-
|
|
279
|
-
```typescript
|
|
280
|
-
import { ARC } from '@bsv/sdk'
|
|
281
|
-
|
|
282
|
-
// Create a fetch-based HTTP client that implements HttpClient interface
|
|
283
|
-
class CustomFetchClient {
|
|
284
|
-
async request(url: string, options: any = {}) {
|
|
285
|
-
const response = await fetch(url, {
|
|
286
|
-
method: options.method || 'GET',
|
|
287
|
-
headers: {
|
|
288
|
-
'Content-Type': 'application/json',
|
|
289
|
-
'Accept': 'application/json',
|
|
290
|
-
...options.headers
|
|
291
|
-
},
|
|
292
|
-
body: options.body ? JSON.stringify(options.body) : undefined
|
|
293
|
-
})
|
|
294
|
-
|
|
295
|
-
if (!response.ok) {
|
|
296
|
-
const errorText = await response.text()
|
|
297
|
-
throw new Error(`HTTP error ${response.status}: ${errorText}`)
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
return await response.json()
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// Use with ARC
|
|
305
|
-
const fetchClient = new CustomFetchClient()
|
|
306
|
-
const arc = new ARC('https://api.taal.com/arc', {
|
|
307
|
-
apiKey: 'your-api-key',
|
|
308
|
-
httpClient: fetchClient
|
|
309
|
-
})
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
## Testing and Mocking HTTP Clients
|
|
313
|
-
|
|
314
|
-
When testing your application, you may want to mock HTTP responses:
|
|
315
|
-
|
|
316
|
-
```typescript
|
|
317
|
-
import { ARC } from '@bsv/sdk'
|
|
318
|
-
|
|
319
|
-
// Create a mock HTTP client for testing that implements HttpClient interface
|
|
320
|
-
class MockHttpClient {
|
|
321
|
-
request = jest.fn().mockImplementation(async (url: string, options: any = {}) => {
|
|
322
|
-
if (options.method === 'POST' && url.includes('/tx')) {
|
|
323
|
-
return { txid: '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' }
|
|
324
|
-
}
|
|
325
|
-
return { status: 'confirmed' }
|
|
326
|
-
})
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
// Create an ARC instance with the mock client
|
|
330
|
-
const mockClient = new MockHttpClient()
|
|
331
|
-
const arc = new ARC('https://api.example.com/arc', {
|
|
332
|
-
apiKey: 'test-api-key',
|
|
333
|
-
httpClient: mockClient
|
|
334
|
-
})
|
|
335
|
-
|
|
336
|
-
// Test transaction broadcasting
|
|
337
|
-
const testBroadcast = async () => {
|
|
338
|
-
const mockTxHex = '0100000001...'
|
|
339
|
-
const result = await arc.broadcast(mockTxHex)
|
|
340
|
-
|
|
341
|
-
// Verify the mock was called correctly
|
|
342
|
-
expect(mockClient.request).toHaveBeenCalledWith(
|
|
343
|
-
expect.stringContaining('/tx'),
|
|
344
|
-
expect.objectContaining({
|
|
345
|
-
method: 'POST',
|
|
346
|
-
body: expect.objectContaining({ rawTx: mockTxHex })
|
|
347
|
-
})
|
|
348
|
-
)
|
|
349
|
-
|
|
350
|
-
return result
|
|
351
|
-
}
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
## Implementing a Custom HTTP Client
|
|
355
|
-
|
|
356
|
-
You can create your own HTTP client implementation by implementing the `HttpClient` interface from the SDK. This gives you complete control over how HTTP requests are handled:
|
|
357
|
-
|
|
358
|
-
```typescript
|
|
359
|
-
import { HttpClient, HttpClientResponse, HttpClientRequestOptions, ARC, Transaction, PrivateKey, P2PKH } from '@bsv/sdk'
|
|
360
|
-
|
|
361
|
-
// Implement the HttpClient interface
|
|
362
|
-
class CustomHttpClient implements HttpClient {
|
|
363
|
-
constructor(private readonly options: { timeout?: number } = {}) {}
|
|
364
|
-
|
|
365
|
-
async request<T = any>(
|
|
366
|
-
url: string,
|
|
367
|
-
options: HttpClientRequestOptions
|
|
368
|
-
): Promise<HttpClientResponse<T>> {
|
|
369
|
-
console.log(`Making ${options.method} request to ${url}`)
|
|
370
|
-
|
|
371
|
-
try {
|
|
372
|
-
// Set up timeout
|
|
373
|
-
const timeout = this.options.timeout || 10000
|
|
374
|
-
const controller = new AbortController()
|
|
375
|
-
const timeoutId = setTimeout(() => controller.abort(), timeout)
|
|
376
|
-
|
|
377
|
-
// Prepare fetch options
|
|
378
|
-
const fetchOptions: RequestInit = {
|
|
379
|
-
method: options.method || 'GET',
|
|
380
|
-
headers: options.headers,
|
|
381
|
-
signal: controller.signal,
|
|
382
|
-
body: options.data ? JSON.stringify(options.data) : undefined
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
// Make the request
|
|
386
|
-
const response = await fetch(url, fetchOptions)
|
|
387
|
-
clearTimeout(timeoutId)
|
|
388
|
-
|
|
389
|
-
// Parse response
|
|
390
|
-
let data: any
|
|
391
|
-
const contentType = response.headers.get('content-type')
|
|
392
|
-
if (contentType && contentType.includes('application/json')) {
|
|
393
|
-
data = await response.json()
|
|
394
|
-
} else {
|
|
395
|
-
data = await response.text()
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// Return formatted response
|
|
399
|
-
return {
|
|
400
|
-
status: response.status,
|
|
401
|
-
statusText: response.statusText,
|
|
402
|
-
ok: response.ok,
|
|
403
|
-
data
|
|
404
|
-
}
|
|
405
|
-
} catch (error) {
|
|
406
|
-
console.error('Request failed:', error)
|
|
407
|
-
return {
|
|
408
|
-
status: 500,
|
|
409
|
-
statusText: error.message || 'Request failed',
|
|
410
|
-
ok: false,
|
|
411
|
-
data: { error: error.message }
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
// Use the custom client with ARC
|
|
418
|
-
const customClient = new CustomHttpClient({ timeout: 15000 })
|
|
419
|
-
const arc = new ARC('https://api.taal.com/arc', {
|
|
420
|
-
apiKey: 'your-api-key',
|
|
421
|
-
httpClient: customClient
|
|
422
|
-
})
|
|
423
|
-
|
|
424
|
-
// Example broadcasting a transaction with the custom client
|
|
425
|
-
const broadcastTx = async () => {
|
|
426
|
-
try {
|
|
427
|
-
// Create a simple transaction with P2PKH output
|
|
428
|
-
const tx = new Transaction()
|
|
429
|
-
const privateKey = PrivateKey.fromRandom()
|
|
430
|
-
const publicKey = privateKey.toPublicKey()
|
|
431
|
-
const address = publicKey.toAddress()
|
|
432
|
-
|
|
433
|
-
// Add an output using P2PKH (instantiate the class first)
|
|
434
|
-
const p2pkh = new P2PKH()
|
|
435
|
-
const lockingScript = p2pkh.lock(address)
|
|
436
|
-
tx.addOutput({
|
|
437
|
-
satoshis: 100,
|
|
438
|
-
lockingScript
|
|
439
|
-
})
|
|
440
|
-
|
|
441
|
-
// Broadcast the transaction
|
|
442
|
-
const result = await arc.broadcast(tx)
|
|
443
|
-
|
|
444
|
-
// Transaction ID needs specific handling
|
|
445
|
-
console.log('Transaction broadcast successful. TXID:', result.txid)
|
|
446
|
-
return result
|
|
447
|
-
} catch (error) {
|
|
448
|
-
console.error('Error broadcasting transaction:', error)
|
|
449
|
-
throw error
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
```
|
|
453
|
-
|
|
454
|
-
## Best Practices
|
|
455
|
-
|
|
456
|
-
1. **Always set timeouts** - Network requests can hang indefinitely without proper timeouts
|
|
457
|
-
2. **Implement retries** - Especially for transaction broadcasting, retries can improve reliability
|
|
458
|
-
3. **Add proper error handling** - Parse and handle HTTP errors appropriately
|
|
459
|
-
4. **Configure request logging** - Log requests and responses for debugging purposes
|
|
460
|
-
5. **Use environment variables** - Store API keys and endpoints in environment variables
|
|
461
|
-
6. **Consider rate limiting** - Implement backoff strategies for rate-limited APIs
|
|
462
|
-
7. **Use the built-in clients** - The SDK's `defaultHttpClient()` handles environment detection automatically
|
|
463
|
-
|
|
464
|
-
## Related Documentation
|
|
465
|
-
|
|
466
|
-
### For Authenticated Communication
|
|
467
|
-
|
|
468
|
-
- **[AuthFetch Tutorial](../tutorials/authfetch-tutorial.md)** - Use for BRC-103/104 cryptographic authentication, wallet-signed requests, and secure peer-to-peer communication
|
|
469
|
-
|
|
470
|
-
### For Advanced HTTP Scenarios
|
|
471
|
-
|
|
472
|
-
- **[Error Handling Guide](error-handling.md)** - Comprehensive error handling patterns for HTTP operations
|
|
473
|
-
- **[Chain Tracking](../concepts/chain-tracking.md)** - Understanding network interaction patterns
|
|
474
|
-
- **[SDK Design Philosophy](../concepts/sdk-philosophy.md)** - Core principles behind SDK HTTP client design
|
|
475
|
-
|
|
476
|
-
### For Transaction Broadcasting
|
|
477
|
-
|
|
478
|
-
- **[Transaction Broadcasting Tutorial](../tutorials/transaction-broadcasting.md)** - Step-by-step transaction broadcasting examples
|
|
479
|
-
|
|
480
|
-
---
|
|
481
|
-
|
|
482
|
-
**Summary**: This guide covers infrastructure-level HTTP client configuration for SDK operations. For application-level authenticated communication using BSV cryptographic protocols, see the [AuthFetch Tutorial](../tutorials/authfetch-tutorial.md).
|
|
483
|
-
|
|
484
|
-
## Related Resources
|
|
485
|
-
|
|
486
|
-
- [Axios Documentation](https://axios-http.com/docs/intro)
|
|
487
|
-
- [ARC API Reference](../reference/arc.md)
|
|
488
|
-
- [Transaction Broadcasting Guide](./transaction-monitoring.md)
|