Duration: 15 minutes
Prerequisites: Node.js, basic TypeScript knowledge
In this tutorial, you’ll learn how to create your first Bitcoin SV transaction using the TypeScript SDK. By the end, you’ll understand the basic components of a BSV transaction and how to construct, sign, and broadcast one.
First, create a new Node.js project and install the BSV SDK:
# Create a new directory for your project
mkdir my-first-bsv-tx
cd my-first-bsv-tx
# Initialize a new Node.js project
npm init -y
# Install TypeScript and ts-node (TypeScript execution engine)
npm install typescript ts-node @types/node --save-dev
# ts-node allows you to run TypeScript files directly without compiling them first
# Install the BSV SDK
npm install @bsv/sdk
Create a basic TypeScript configuration file (tsconfig.json
):
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"esModuleInterop": true,
"strict": true,
"outDir": "./dist"
}
}
Before we write any code, let’s understand the basic components of a Bitcoin transaction:
For a deeper understanding of Bitcoin transactions, check out these official resources:
Create a new file called first-transaction.ts
:
import { PrivateKey, P2PKH, Transaction } from '@bsv/sdk'
async function createTransaction() {
// Create a private key (in production, you'd use proper key management)
const privateKey = PrivateKey.fromRandom()
console.log(`Private key WIF: ${privateKey.toWif()}`)
// Derive the public key and address
const address = privateKey.toAddress()
console.log(`Address: ${address.toString()}`)
// For a real transaction, you would have a source UTXO
// For this example, we'll create a transaction without inputs (cannot be broadcast)
const tx = new Transaction()
// Add an output
tx.addOutput({
lockingScript: new P2PKH().lock(address),
satoshis: 100
})
// Serialize the transaction
const txHex = tx.toHex() // Use toHex() instead of toString()
console.log(`Transaction (hex): ${txHex}`)
// Get transaction ID as a hex string
const txid = Buffer.from(tx.id()).toString('hex') // Convert the byte array to hex string
console.log(`Transaction ID: ${txid}`)
// Display the transaction structure
console.log('\nTransaction Structure:')
console.log(`Version: ${tx.version}`)
console.log(`Input Count: ${tx.inputs.length}`)
console.log(`Output Count: ${tx.outputs.length}`)
for (let i = 0; i < tx.outputs.length; i++) {
const output = tx.outputs[i]
console.log(`\nOutput #${i}:`)
console.log(` Satoshis: ${output.satoshis}`)
console.log(` Locking Script: ${output.lockingScript.toHex()}`)
console.log(` Locking Script (ASM): ${output.lockingScript.toASM()}`)
}
}
createTransaction().catch(console.error)
Execute your code with the following command:
npx ts-node first-transaction.ts
You should see output showing your private key, address, and transaction details.
The transaction we created in the previous step doesn’t have any inputs, so it can’t be broadcast to the network. It serves as a conceptual introduction to transaction structure.
In the next tutorial, “Working with Testnet Transactions (Low-Level)”, you’ll learn how to:
Here’s a simplified preview of what a complete transaction looks like. Don’t worry about understanding all the details yet - this is just to give you a sense of the structure you’ll work with in the next tutorial:
// A complete transaction typically follows this structure:
const tx = new Transaction()
// Add an input (where the money comes from)
tx.addInput({
sourceTransaction: /* previous transaction containing your funds */,
sourceOutputIndex: /* which output from that transaction */,
unlockingScriptTemplate: /* script to unlock those funds */
})
// Add an output (where the money goes)
tx.addOutput({
lockingScript: /* script that locks funds to recipient */,
satoshis: /* amount to send */
})
// Add change output (remaining funds returned to you)
tx.addOutput({
lockingScript: /* script that locks funds to you */,
change: true // Automatically handles change amount
})
// Calculate fee and sign
await tx.fee()
await tx.sign()
// Broadcast to the network
const result = await tx.broadcast()
Bitcoin transactions require fees to be included in a block by miners. The BSV SDK simplifies fee calculation with the fee()
method, which:
change: true
parameter to automatically handle change outputsYou’ll get hands-on experience with transaction fees in the testnet tutorial.
Congratulations! You’ve learned the basics of creating a BSV transaction using the TypeScript SDK. In this tutorial, you’ve: