@bsv/sdk
Version:
BSV Blockchain Software Development Kit
148 lines (110 loc) • 5.07 kB
Markdown
# Creating Transactions with Direct Interfaces
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.
## When to Use Direct Interfaces
- When creating custom transaction types not supported by `WalletClient`
- When you need precise control over UTXO selection
- When building specialized applications like data storage services that require custom optimization
- When integrating with systems that require direct management of transactions
- For educational purposes to understand the underlying transaction structure
## Basic Transaction Construction
```typescript
import { PrivateKey, P2PKH, Transaction } from '@bsv/sdk'
async function createBasicTransaction() {
// Create a private key
const privateKey = PrivateKey.fromRandom()
console.log(`Private key WIF: ${privateKey.toWif()}`)
// Derive the address
const address = privateKey.toAddress()
console.log(`Address: ${address.toString()}`)
// Create a new transaction
const tx = new Transaction()
// Add an output
tx.addOutput({
lockingScript: new P2PKH().lock(address),
satoshis: 1000
})
// Serialize the transaction
const txHex = tx.toHex()
console.log(`Transaction (hex): ${txHex}`)
// Get transaction ID as a hex string
const txid = Buffer.from(tx.id()).toString('hex')
console.log(`Transaction ID: ${txid}`)
}
```
## Complete Transaction with Inputs and Outputs
For a complete transaction that can be broadcast, you need to add inputs, calculate fees, and sign it:
```typescript
import { Transaction, PrivateKey, P2PKH, ARC } from '@bsv/sdk'
async function createCompleteTransaction() {
// Set up your wallet
const privateKey = PrivateKey.fromWif('your_private_key_here')
const myAddress = privateKey.toAddress()
const recipientAddress = 'recipient_address_here'
// You need the hex of the source transaction
const sourceTxHex = '...' // Hex string of the source transaction
// Create a transaction
const tx = new Transaction()
// Add the input
tx.addInput({
sourceTransaction: Transaction.fromHex(sourceTxHex),
sourceOutputIndex: 0, // The output index you want to spend
unlockingScriptTemplate: new P2PKH().unlock(privateKey)
})
// Add the recipient output
tx.addOutput({
lockingScript: new P2PKH().lock(recipientAddress),
satoshis: 100 // Amount to send
})
// Add the change output back to our address
tx.addOutput({
lockingScript: new P2PKH().lock(myAddress),
change: true // SDK will automatically calculate the change amount
})
// Calculate fee and sign the transaction
await tx.fee()
await tx.sign()
// Get the transaction hex ready for broadcasting
const signedTxHex = tx.toHex()
console.log(`Signed transaction hex: ${signedTxHex}`)
// Get the transaction ID
const txid = Buffer.from(tx.id()).toString('hex')
console.log(`Transaction ID: ${txid}`)
}
```
## Broadcasting the Transaction
To broadcast your signed transaction:
```typescript
import { ARC, NodejsHttpClient } from '@bsv/sdk'
import https from 'https'
async function broadcastTransaction(signedTx) {
// Create an HTTP client
const httpClient = new NodejsHttpClient(https)
// Initialize the ARC client
const arc = new ARC('https://api.arc.taal.com', {
apiKey: 'your_api_key_here',
httpClient,
deploymentId: 'your-deployment-id'
})
// Broadcast the transaction
const result = await signedTx.broadcast(arc)
console.log('Broadcast result:', result)
}
```
## Key Implementation Details
When working with direct interfaces, remember these important details:
1. Use `toWif()` (lowercase 'f') not `toWIF()` for private key WIF format
2. Use `toHex()` instead of `toString()` for transaction serialization
3. Transaction IDs need to be converted from byte arrays: `Buffer.from(tx.id()).toString('hex')`
4. For script objects, use `toHex()` or `toASM()` rather than `toString()`
5. Method chaining doesn't work well with current API - use separate method calls
## Direct Creation vs `WalletClient` Approach
| Feature | Direct Creation | `WalletClient` |
| --- | --- | --- |
| Control over transaction structure | High | Low |
| Complexity | High | Low |
| Recommended use case | Specialized applications | Production applications |
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.
## Related Resources
- For simpler implementations, see the [Creating Transactions with WalletClient](../tutorials/first-transaction.md) tutorial
- Learn about [Advanced Transaction Signing](./advanced-transaction-signing.md)
- Explore [HTTP Client Configuration](./http-client-configuration.md) for optimizing API requests