Building on Spark: How the SDK Lets Wallet Developers Ship Bitcoin Payments in Days
Spark's developer SDK abstracts statechain and FROST complexity, letting wallet builders integrate self-custodial Bitcoin payments quickly.
Wallet developers building Bitcoin payment features have traditionally faced months of integration work. Lightning implementations require channel management, liquidity provisioning, and peer-to-peer networking. On-chain wallets demand UTXO tracking, fee estimation, and coin selection. The Spark SDK takes a different approach: it abstracts statechain transfers, FROST threshold signing, and key management behind a simple API, letting developers ship self-custodial Bitcoin and stablecoin payments in days rather than months.
This article walks through the SDK architecture, the integration path from installation to first payment, and how it compares to other Bitcoin payment SDKs like LDK, Breez SDK, and Greenlight.
What the Spark SDK Abstracts
The core of Spark is a statechain protocol enhanced with FROST threshold signatures. Transfers work by rotating key shares between sender and receiver while the underlying Bitcoin remains in the same on-chain address. The Spark Entity (a set of independent operators) participates in a 2-of-2 multisig with the user, where the operator side is itself a FROST threshold key split across multiple parties.
None of this complexity is visible to SDK consumers. The SparkWallet class exposes methods like transfer(), getBalance(), and createLightningInvoice(). Under the hood, each call coordinates FROST signing rounds, manages virtual transaction outputs (VTXOs), handles key derivation from the user's seed phrase, and communicates with Spark Operators over an authenticated channel.
Statechain transfer coordination
When a developer calls wallet.transfer(), the SDK performs a multi-step process invisibly: it contacts the Spark Entity to initiate a key rotation, participates in a FROST signing round to produce the new shared key, verifies that the old key share has been invalidated, and delivers the transfer notification to the receiver. The developer sees a single async function call that resolves when the transfer is complete.
FROST signing abstraction
FROST (Flexible Round-Optimized Schnorr Threshold) signatures require coordinated multi-round protocols between signers. Implementing FROST from scratch involves nonce commitment schemes, Schnorr signature aggregation, and share verification. The SDK handles all of this internally, including retry logic for operator communication and key share validation. Developers never interact with raw cryptographic primitives.
Key management
Users generate a standard BIP-39 mnemonic locally. The SDK derives all necessary key material from this mnemonic, including the user's half of each 2-of-2 signing pair. Key storage, derivation paths, and backup are handled by the SDK's initialization flow. The self-custody guarantee is preserved: the user's mnemonic never leaves the device, and operators never see the user's private key material.
Self-custody by default: Unlike custodial APIs where a backend holds keys, the Spark SDK generates and stores keys on the client side. Users can always exit to Bitcoin L1 using pre-signed exit transactions, even if Spark operators go offline. This is true self-custody, not a custodial service wrapped in an SDK.
What the SDK Exposes
The API surface is deliberately minimal. The SparkWallet class covers six categories: wallet lifecycle, balance queries, Spark transfers, Lightning operations, L1 deposits and withdrawals, and token operations.
| Category | Key Methods | What It Does |
|---|---|---|
| Wallet lifecycle | SparkWallet.initialize() | Create new wallet or restore from mnemonic |
| Balance | getBalance() | Returns BTC balance (sats) and token balances |
| Spark transfers | transfer(), getSparkAddress() | Send/receive BTC on Spark with instant settlement |
| Lightning | payLightningInvoice(), createLightningInvoice() | Send and receive Lightning payments natively |
| L1 bridge | getSingleUseDepositAddress(), withdraw() | Move Bitcoin between L1 and Spark |
| Tokens | transferTokens(), createTokensInvoice() | Send/receive USDB and other Spark-native tokens |
Event listeners (wallet.on("transfer:claimed", callback)) let apps react to incoming payments in real time. This is sufficient to build a complete payment wallet without touching any lower-level protocol details.
From Installation to First Payment
The integration path for the Spark SDK is designed for speed. A developer with Node.js experience can go from zero to a working Bitcoin payment in under an hour.
Step 1: Install the SDK
The TypeScript SDK is available on npm. For teams starting a new project, the scaffolding tool sets up a complete project structure:
npm install @buildonspark/spark-sdk
# Or scaffold a complete project:
npx @buildonspark/create-spark-app my-walletStep 2: Initialize a wallet
Wallet creation generates a new HD wallet with a BIP-39 mnemonic. The SDK handles key derivation and operator registration:
import { SparkWallet } from "@buildonspark/spark-sdk";
// Create a new wallet
const { wallet, mnemonic } = await SparkWallet.initialize({
options: { network: "MAINNET" }
});
// Or restore from existing mnemonic
const { wallet: restored } = await SparkWallet.initialize({
mnemonicOrSeed: existingMnemonic,
accountNumber: 0,
options: { network: "MAINNET" }
});Step 3: Send a payment
Sending Bitcoin on Spark is a single method call. The SDK resolves the recipient's Spark address, coordinates the statechain transfer, and returns when settlement is complete:
// Spark-to-Spark transfer (instant, near-zero fee)
await wallet.transfer({
receiverSparkAddress: recipientAddress,
amountSats: 50000
});
// Pay a Lightning invoice
await wallet.payLightningInvoice({
invoice: bolt11Invoice,
maxFeeSats: 100
});Step 4: Receive payments
Receiving is equally straightforward. The SDK supports both Spark-native invoices and Lightning invoices from the same wallet:
// Create a Spark invoice
const sparkInvoice = await wallet.createSatsInvoice({
amount: 25000,
memo: "Coffee payment"
});
// Create a Lightning invoice
const lnInvoice = await wallet.createLightningInvoice({
amountSats: 25000,
memo: "Coffee payment"
});
// Listen for incoming payments
wallet.on("transfer:claimed", (transfer) => {
console.log("Received:", transfer.amountSats, "sats");
});Zero-conf deposits: The Spark SDK credits on-chain Bitcoin deposits instantly by validating the transaction at broadcast time. The protocol handles confirmation risk, so users do not wait for block confirmations. Developers callgetSingleUseDepositAddress()to generate a deposit address andclaimDeposit()to finalize.
Stablecoin Support: Bitcoin and Dollars from One SDK
A distinctive feature of the Spark SDK is native stablecoin support. USDB, a USD-backed stablecoin issued by Brale (a FinCEN-registered MSB), is a first-class citizen in the SDK. It uses the BTKN token standard native to Spark, not a bridge from another chain.
The same SparkWallet instance handles both BTC and token operations. Developers do not need a separate stablecoin SDK, a bridge integration, or an EVM-compatible layer:
// Check token balances
const { balance, tokenBalances } = await wallet.getBalance();
// balance: BTC in sats
// tokenBalances: array of { tokenIdentifier, amount }
// Send USDB
await wallet.transferTokens({
tokenIdentifier: "usdb",
tokenAmount: 1000, // $10.00
receiverSparkAddress: recipientAddress
});
// Create a USDB invoice
const invoice = await wallet.createTokensInvoice({
tokenIdentifier: "usdb",
amount: 5000,
memo: "Invoice #1234"
});This dual-asset capability is particularly relevant for fintech applications that need dollar-denominated payments without leaving the Bitcoin ecosystem. A single SDK integration gives users access to both volatile BTC and stable USD transfers.
How Spark SDK Compares to Lightning SDKs
The most direct comparisons are with LDK (Lightning Dev Kit), Breez SDK, and Greenlight by Blockstream. Each targets a different point on the control-vs-complexity spectrum.
LDK: maximum control, maximum effort
LDK is a Rust library that gives developers full control over every aspect of a Lightning node. It is modular by design: you provide your own on-chain wallet (often BDK), your own persistence layer, your own fee estimator, and your own chain data source. A minimal LDK wallet requires implementing roughly 10 trait interfaces covering chain monitoring, key management, transaction broadcasting, event persistence, and logging.
The result is maximum flexibility for teams building differentiated Lightning products, but the integration timeline is measured in months. Post-launch maintenance includes channel rebalancing, peer management, and watchtower operation.
Breez SDK: managed Lightning with LSP abstraction
Breez SDK wraps Lightning complexity behind a higher-level API and connects to Breez's Lightning Service Provider infrastructure for automated channel management and liquidity provisioning. Integration is substantially faster than raw LDK: configuration plus connection takes roughly 10 lines of code, and sending a payment takes 3. Breez SDK is built in Rust with bindings for Swift, Kotlin, Python, Flutter, Go, C#, and React Native.
The tradeoff is dependency on Breez infrastructure for LSP services and a fee structure that includes LSP channel-open fees for inbound liquidity. Breez now also offers a Spark integration alongside its Lightning offering.
Greenlight: cloud-hosted CLN nodes
Blockstream's Greenlight runs Core Lightning nodes in the cloud on behalf of developers. The user holds keys locally while the node runs on Blockstream's infrastructure. This provides the full CLN feature set without server management, but developers still need to handle channel liquidity, routing configuration, and the operational complexity that comes with running a Lightning node.
Spark SDK: protocol complexity removed
The Spark SDK eliminates entire categories of infrastructure that Lightning-based solutions require. There are no channels to open, no liquidity to manage, no routing to configure, and no watchtowers to run. The tradeoff is the 1-of-n trust model: users trust that at least one Spark operator behaves honestly during each transfer. For many consumer wallet use cases, this is an acceptable tradeoff given the dramatic reduction in integration complexity and ongoing maintenance.
| Dimension | LDK | Breez SDK | Greenlight | Spark SDK |
|---|---|---|---|---|
| Core language | Rust | Rust | C (CLN) | TypeScript |
| Wallet init complexity | ~100+ lines, 10 trait impls | ~10 lines | ~20 lines + cloud setup | ~5 lines |
| Send payment | ~20 lines | ~3 lines | ~5 lines | ~3 lines |
| Channel management | Manual (developer handles) | Automated via LSP | Semi-automated | Not applicable |
| Liquidity planning | Required | LSP handles inbound | Required | Not applicable |
| Infrastructure required | Full node, Electrum, gossip data | Breez API key | Blockstream cloud access | None (public operators) |
| Offline receiving | No | No | No | Yes (SSP holds conditionally) |
| Native stablecoin support | No | No | No | Yes (USDB, BTKN tokens) |
| Trust model | Fully trustless | Trustless (non-custodial LSP) | Blockstream hosts node | 1-of-n operators |
| Ongoing maintenance | Channel rebalancing, peer mgmt, watchtowers | SDK updates, LSP fee monitoring | Channel mgmt, routing config | SDK updates only |
| Platform bindings | Rust, Swift, Kotlin, Node.js | Rust, Swift, Kotlin, Flutter, RN, Go, C# | CLN plugins, Breez wraps it | TypeScript, Kotlin, Swift, RN |
Platform Support and Language Bindings
The Spark SDK is available natively for the platforms where most wallet development happens:
- TypeScript (npm):
@buildonspark/spark-sdkfor Node.js, browser, and React Native environments - Kotlin:
spark-kotlin-sdkfor native Android applications - Swift:
spark-swift-sdkfor native iOS applications
For additional language support, the Breez Spark SDK extends reach to Rust, Python, Go, Flutter, and C# through FFI bindings. This means developers working in virtually any major mobile or server-side language can integrate Spark without writing TypeScript.
The scaffolding tool (npx @buildonspark/create-spark-app) generates a complete project skeleton with wallet initialization, environment configuration, and example payment flows. This is particularly useful for hackathon prototypes and proof-of-concept builds where time to first demo is critical.
Developer Experience: What Makes It Different
Several design decisions in the Spark SDK reflect lessons learned from the Lightning SDK ecosystem.
No infrastructure to provision
LDK and Greenlight require developers to run or connect to Bitcoin full nodes, Electrum servers, or cloud infrastructure. The Spark SDK connects to the existing Spark operator network directly. There is no server to deploy, no RPC endpoint to configure, and no gossip data to sync. This removes an entire deployment category from the launch checklist.
No state management burden
Lightning wallets must persist channel state reliably. Losing channel state can result in funds loss through outdated commitment transactions. The Spark SDK stores wallet state locally but the protocol is not vulnerable to stale state attacks: if local data is lost, the wallet can be fully restored from the mnemonic because the operators maintain the current state of each VTXO.
Unified payment interface
A Spark wallet can send and receive via three rails from the same instance: Spark-to-Spark transfers (instant, near-zero fee), Lightning payments (via Spark Service Providers performing atomic swaps), and L1 Bitcoin (deposits and withdrawals). Developers do not need to integrate multiple SDKs or maintain separate codepaths for different payment types.
Event-driven architecture
The SDK uses an event emitter pattern for incoming payments. Instead of polling, developers register callbacks that fire when transfers are claimed, deposits confirm, or token payments arrive. This integrates cleanly with modern frontend frameworks and mobile app architectures.
Production Integrations
The SDK's design has been validated by production deployments across wallet categories. Over 20 applications have integrated Spark, including consumer wallets like Wallet of Satoshi, Xverse, Blitz, and Breez; neobanks like Deblock; infrastructure providers like Privy and Dynamic; and trading platforms like Flashnet.
The breadth of integrations demonstrates that the SDK surface is general enough for different product architectures while remaining specific enough to be useful without extensive customization. Teams building embedded wallets, standalone payment apps, and Telegram bots have all shipped using the same API surface.
Documentation and Developer Resources
The Spark developer documentation covers the complete SDK surface with quickstart guides, API references, and integration examples for TypeScript and React Native. Key resources include:
- Quickstart guide: wallet creation to first payment in a single tutorial
- API reference: complete method signatures with parameter types and return values
- Token issuance guide: creating and managing custom tokens using the BTKN standard
- GitHub repository: buildonspark/spark (Apache 2.0 license)
For developers evaluating the SDK against alternatives, the Bitcoin wallet SDK comparison provides a detailed feature-by-feature breakdown across BDK, LDK, Breez SDK, and Spark SDK. The payment app development guide covers the full decision tree from architecture to deployment.
Tradeoffs Developers Should Understand
The Spark SDK is not a universal solution. Several tradeoffs are worth evaluating before committing to the integration.
Trust model
Spark relies on a 1-of-n trust assumption: at least one operator must behave honestly during each transfer. This is weaker than Lightning's fully trustless model but stronger than custodial solutions. For applications where absolute trustlessness is a product requirement (institutional custody, high-value settlement), a Lightning-based SDK may be more appropriate.
Operator dependency
If all Spark operators go offline, new transfers cannot be processed. Users can still exit to Bitcoin L1 via pre-signed exit transactions, so funds are never at risk, but the liveness of the payment layer depends on operator availability. Currently, Lightspark and Flashnet operate as operators with plans to expand to additional independent parties.
Privacy considerations
Spark operators can observe transfer metadata including amounts and participant addresses. This is similar to the visibility that Lightning routing nodes have, but the centralized operator model concentrates this information. Developers building privacy-focused applications should evaluate whether this visibility model meets their requirements.
L1 exit costs
Exiting from Spark to Bitcoin L1 requires an on-chain transaction with associated fees. Small balances may become uneconomical to exit during high-fee periods. This is a limitation shared by all Bitcoin Layer 2 solutions.
Getting Started
For developers ready to integrate, the fastest path is the scaffolding tool: npx @buildonspark/create-spark-app generates a working project with wallet initialization and example payment flows. The Spark developer documentation provides step-by-step quickstart guides, and the GitHub repository is open source under the Apache 2.0 license. For a concrete example of what a production Spark wallet looks like for end users, General Bread demonstrates the self-custodial Bitcoin and stablecoin payment experience that the SDK enables.
This article is for educational purposes only. It does not constitute financial or investment advice. Bitcoin and Layer 2 protocols involve technical and financial risk. Always do your own research and understand the tradeoffs before using any protocol.

