Custom Templates
Complete examples for creating custom script templates for reusable locking and unlocking patterns.
Overview
The BSV SDK provides a template system that allows you to define custom locking and unlocking script patterns. Templates make it easy to create reusable script patterns without manually constructing Bitcoin Script each time. This is essential for applications that use custom scripts like multisig, time locks, or complex spending conditions.
Related SDK Components:
Basic Template Creation
import {
Transaction,
PrivateKey,
PublicKey,
Script,
OP,
LockingScript,
UnlockingScript
} from '@bsv/sdk'
/**
* Basic Custom Template
*
* Simple template for a password-locked output
*/
class PasswordLockTemplate {
private password: string
constructor(password: string) {
this.password = password
}
/**
* Create locking script
*
* Requires: <password> <signature> <pubkey>
*/
lock(publicKeyHash: number[]): LockingScript {
return {
script: (): Script => {
const script = new Script()
// Password verification
const passwordHash = Buffer.from(this.hashPassword(this.password), 'hex')
script.writeOpCode(OP.OP_HASH256)
script.writeBin(passwordHash)
script.writeOpCode(OP.OP_EQUALVERIFY)
// Standard P2PKH verification
script.writeOpCode(OP.OP_DUP)
script.writeOpCode(OP.OP_HASH160)
script.writeBin(Buffer.from(publicKeyHash))
script.writeOpCode(OP.OP_EQUALVERIFY)
script.writeOpCode(OP.OP_CHECKSIG)
return script
}
}
}
/**
* Create unlocking script
*
* Provides: <password> <signature> <pubkey>
*/
unlock(privateKey: PrivateKey, password: string): UnlockingScript {
return {
sign: async (tx: Transaction, inputIndex: number) => {
const script = new Script()
// Get locking script for this input
const input = tx.inputs[inputIndex]
const lockingScript = input.sourceTransaction?.outputs[input.sourceOutputIndex]?.lockingScript
if (!lockingScript) {
throw new Error('Cannot find locking script for input')
}
// Create signature
const preimage = input.getPreimage(lockingScript)
const signature = privateKey.sign(preimage)
// Build unlocking script: <sig> <pubkey> <password>
script.writeBin(signature.toDER())
script.writeBin(privateKey.toPublicKey().encode())
script.writeBin(Buffer.from(password, 'utf8'))
return script
},
estimateLength: async () => {
return 150 // Approximate length
}
}
}
/**
* Hash password for script
*/
private hashPassword(password: string): string {
const hash = require('crypto')
.createHash('sha256')
.update(password)
.digest()
return require('crypto')
.createHash('sha256')
.update(hash)
.digest('hex')
}
}
/**
* Usage Example
*/
async function basicTemplateExample() {
const template = new PasswordLockTemplate('my-secret-password')
const privateKey = PrivateKey.fromRandom()
// Create a transaction with password-locked output
const tx = new Transaction()
tx.addInput({
sourceTXID: 'funding-tx...',
sourceOutputIndex: 0,
unlockingScriptTemplate: template.unlock(privateKey, 'my-secret-password'),
sequence: 0xffffffff
})
tx.addOutput({
satoshis: 50000,
lockingScript: template.lock(privateKey.toPublicKey().toHash()).script()
})
await tx.sign()
console.log('Password-locked transaction created')
console.log('Transaction ID:', tx.id('hex'))
}Timelock Template
Multisig Template
Conditional Template
Related Examples
See Also
SDK Components:
Script Templates - Template system documentation
Script - Script operations
Transaction - Transaction building
P2PKH - P2PKH template reference
Learning Paths:
Last updated
