@starkware-bitcoin/spv-verify
v0.1.8
Published
Raito SPV verification SDK (WASM + TypeScript)
Downloads
26
Readme
Raito SPV Verify SDK
A comprehensive TypeScript SDK for fetching and verifying compressed SPV (Simplified Payment Verification) proofs. Built on WebAssembly for high performance in both web browsers and Node.js environments.
Usage
Quick Start
Using the Singleton Pattern (Recommended)
import { getRaitoSpvSdk } from '@starkware-bitcoin/spv-verify';
async function main() {
const sdk = getRaitoSpvSdk(); // Gets singleton instance
await sdk.init();
const recentHeight = await sdk.fetchRecentProvenHeight();
console.log('Most recent proven block height:', recentHeight);
const chainStateResult = await sdk.verifyRecentChainState();
console.log('MMR root:', chainStateResult.mmrRoot);
console.log('Chain state height:', chainStateResult.chainState.block_height);
const blockHeader = await sdk.verifyBlockHeader(
chainStateResult.chainState.block_height
);
console.log('Verified block header prev hash:', blockHeader.prev_blockhash);
const txid = '4f1b987645e596329b985064b1ce33046e4e293a08fd961193c8ddbb1ca219cc';
const transaction = await sdk.verifyTransaction(txid);
console.log('First output value (sats):', transaction.output[0]?.value);
}
main().catch(console.error);Using Direct Instantiation
import { createRaitoSpvSdk } from '@starkware-bitcoin/spv-verify';
async function main() {
const sdk = createRaitoSpvSdk(); // Creates new instance
await sdk.init();
const recentHeight = await sdk.fetchRecentProvenHeight();
console.log('Most recent proven block height:', recentHeight);
const chainStateResult = await sdk.verifyRecentChainState();
console.log('MMR root:', chainStateResult.mmrRoot);
console.log('Chain state height:', chainStateResult.chainState.block_height);
const blockHeader = await sdk.verifyBlockHeader(
chainStateResult.chainState.block_height
);
console.log('Verified block header prev hash:', blockHeader.prev_blockhash);
const txid = '4f1b987645e596329b985064b1ce33046e4e293a08fd961193c8ddbb1ca219cc';
const transaction = await sdk.verifyTransaction(txid);
console.log('First output value (sats):', transaction.output[0]?.value);
}
main().catch(console.error);Custom RPC URL and Verifier Configuration
You can direct the SDK to another bridge endpoint or tweak the verifier configuration that is passed to the WASM backend:
Using Singleton with Custom Configuration
// Configuration is only used when creating the singleton instance
const sdk = getRaitoSpvSdk({
raitoRpcUrl: 'https://api.raito.wtf',
verifierConfig: {
min_work: '1813388729421943762059264',
bootloader_hash:
'0x0001837d8b77b6368e0129ce3f65b5d63863cfab93c47865ee5cbe62922ab8f3',
task_program_hash:
'0x00f0876bb47895e8c4a6e7043829d7886e3b135e3ef30544fb688ef4e25663ca',
task_output_size: 8,
}
});Using Direct Instantiation with Custom Configuration
const sdk = createRaitoSpvSdk({
raitoRpcUrl: 'https://api.raito.wtf',
verifierConfig: {
min_work: '1813388729421943762059264',
bootloader_hash:
'0x0001837d8b77b6368e0129ce3f65b5d63863cfab93c47865ee5cbe62922ab8f3',
task_program_hash:
'0x00f0876bb47895e8c4a6e7043829d7886e3b135e3ef30544fb688ef4e25663ca',
task_output_size: 8,
}
});All fields in the configuration object are optional; omitted values fall back to the defaults shown above.
Singleton Pattern Benefits
The singleton pattern is recommended for most use cases because it:
- Prevents multiple WASM initializations: Avoids the overhead of loading the WASM module multiple times
- Maintains state consistency: Ensures all parts of your application use the same SDK instance with shared cache
- Reduces memory usage: Only one instance exists throughout your application lifecycle
- Simplifies configuration: Set up the SDK once and use it everywhere
Use resetRaitoSpvSdk() if you need to reinitialize with different parameters or for testing purposes.
Verifying Recent Chain State
verifyRecentChainState()downloads the latest recursive proof from the Raito bridge RPC, verifies it with WASM, and caches the result.- The returned object contains both the verified
mmrRootand the parsedchainStatesnapshot (including the most recent provenblock_height). - Subsequent calls reuse the cached result until a new instance of the SDK is created.
Verifying Block Headers
- Call
verifyBlockHeader(blockHeight)to fetch the inclusion proof and block header for that height. The SDK matches the MMR root with the previously verified chain state before returning the header. - You can supply a
blockHeaderobject as the second argument if you already have the header; the SDK will skip the fetch and only verify the proof.
Verifying Transactions
verifyTransaction(txid)retrieves the merkle proof from the bridge, verifies it with WASM, and ensures the enclosing block header is part of the verified MMR tree.- The method returns the decoded transaction object, which is cached so repeated
checks of the same
txidare free.
API Reference
getRaitoSpvSdk(config?)
Gets the singleton instance of RaitoSpvSdk. If no instance exists, creates one with the provided parameters.
config(optional):Partial<RaitoSpvSdkConfig>configuration object. Contains:raitoRpcUrl(optional): custom bridge RPC endpoint. Defaults tohttps://api.raito.wtf.verifierConfig(optional): partial verifier configuration. Missing fields fall back to the default verifier settings bundled with the SDK.
- Returns: the singleton
RaitoSpvSdkinstance.
createRaitoSpvSdk(config?)
Creates a new instance of RaitoSpvSdk.
config(optional):Partial<RaitoSpvSdkConfig>configuration object. Contains:raitoRpcUrl(optional): custom bridge RPC endpoint. Defaults tohttps://api.raito.wtf.verifierConfig(optional): partial verifier configuration. Missing fields fall back to the default verifier settings bundled with the SDK.
- Returns: a new
RaitoSpvSdkinstance.
resetRaitoSpvSdk()
Resets the singleton instance. Useful for testing or reinitialization with different parameters.
- Returns:
void
RaitoSpvSdk
init(): Promise<void>
Loads and initialises the WASM module. Call once before using the other methods.
fetchRecentProvenHeight(): Promise<number>
Fetches the most recent proven Bitcoin block height available from the bridge API.
verifyRecentChainState(): Promise<ChainStateProofVerificationResult>
Downloads and verifies the latest recursive proof. Returns an object with the
verified MMR root and the parsed chainState snapshot. Results are cached per
SDK instance.
verifyBlockHeader(blockHeight: number, blockHeader?: BlockHeader): Promise<BlockHeader>
Verifies that the block header at blockHeight is included in the proven MMR.
Optionally accepts a pre-fetched header to avoid an extra RPC round trip.
verifyTransaction(txid: string): Promise<Transaction>
Verifies the merkle proof for txid, ensures the enclosing block header is in
the MMR, and returns the parsed transaction data.
Types
RaitoSpvSdkConfig
interface RaitoSpvSdkConfig {
raitoRpcUrl: string;
verifierConfig: Partial<VerifierConfig>;
}Configuration object for initializing the RaitoSpvSdk. Both fields are required when using the full config object, but when passed to getRaitoSpvSdk() or createRaitoSpvSdk(), you can use Partial<RaitoSpvSdkConfig> to make all fields optional.
raitoRpcUrl: The RPC endpoint URL for the Raito bridge APIverifierConfig: Partial verifier configuration that will be merged with defaults
VerifierConfig
interface VerifierConfig {
min_work: string;
bootloader_hash: string;
task_program_hash: string;
task_output_size: number;
}Verifier configuration passed to the WASM backend for proof verification.
ChainStateProofVerificationResult
interface ChainStateProofVerificationResult {
mmrRoot: string;
chainState: ChainState;
}ChainState
interface ChainState {
block_height: number;
total_work: string;
best_block_hash: string;
current_target: string;
epoch_start_time: number;
prev_timestamps: number[];
}BlockHeader
interface BlockHeader {
version: number;
prev_blockhash: string;
merkle_root: string;
time: number;
bits: number;
nonce: number;
}Transaction
interface Transaction {
version: number;
lock_time: number;
input: Array<{
previous_output: { txid: string; vout: number };
script_sig: string;
sequence: number;
witness: string[];
}>;
output: Array<{
value: bigint;
script_pubkey: string;
}>;
}Building from Source
Prerequisites
- Rust toolchain (latest stable)
wasm-packfor building WASM- Node.js 18+ and npm
Build Steps
# Install wasm-pack if you haven't already
cargo install wasm-pack
# Build the complete SDK (includes WASM compilation and TypeScript bundling)
npm run build
Examples
The SDK includes complete examples demonstrating different usage patterns:
Node.js Example
# Run the Node.js example
node examples/node-example.jsBlock Proof Example
# Run the block proof example
node examples/block-proof-example.jsWeb Browser Example
# Start the web example development server
cd examples/web-example
npm install
npm run dev