Set up Spark Bitcoin L2 wallet capabilities for AI agents. Initialize wallets from mnemonic, transfer sats and tokens, create/pay Lightning invoices, pay L402 paywalls, manage deposits and withdrawals. Use when user mentions "Spark wallet," "Spark Bitcoin," "BTKN tokens," "Spark L2," "Spark SDK," "Spark payment," "Spark transfer," "Spark invoice," "L402," "Lightning paywall," or wants Bitcoin L2 capabilities for an agent.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
Instruções da origem · Visualização somente leitura
name
sparkbtcbot
description
Set up Spark Bitcoin L2 wallet capabilities for AI agents. Initialize wallets from mnemonic, transfer sats and tokens, create/pay Lightning invoices, pay L402 paywalls, manage deposits and withdrawals. Use when user mentions "Spark wallet," "Spark Bitcoin," "BTKN tokens," "Spark L2," "Spark SDK," "Spark payment," "Spark transfer," "Spark invoice," "L402," "Lightning paywall," or wants Bitcoin L2 capabilities for an agent.
argument-hint
[Optional: specify what to set up - wallet, payments, tokens, lightning, l402, or full]
requires
{"env":[{"name":"SPARK_MNEMONIC","description":"12 or 24 word BIP39 mnemonic for the Spark wallet. This is a secret key that controls all funds — never commit to git or expose in logs.","sensitive":true},{"name":"SPARK_NETWORK","description":"Network to connect to (MAINNET or REGTEST)","default":"MAINNET"}]}
model-invocation
autonomous
model-invocation-reason
This skill enables agents to autonomously send and receive Bitcoin payments. Autonomous invocation is intentional — agents need to pay invoices and respond to incoming transfers without human approval for each transaction. Use spending limits and the proxy for production environments where you need guardrails.
homepage
https://sparkbot.yvrbtclabs.dev
Spark Bitcoin L2 for AI Agents
You are an expert in setting up Spark Bitcoin L2 wallet capabilities for AI agents using the @buildonspark/spark-sdk.
Spark is a Bitcoin Layer 2 that enables instant, zero-fee self-custodial transfers of BTC and tokens, with native Lightning Network interoperability. Spark-to-Spark transfers cost nothing — compared to Lightning routing fees or on-chain transaction fees of 200+ sats. Even cross-network payments (Lightning interop) are cheaper than most alternatives at 0.15-0.25%. A single BIP39 mnemonic gives an agent identity, wallet access, and payment capabilities.
For Production Use
This skill gives the agent full custody of the wallet. The agent holds the mnemonic and can send all funds without restriction. This is appropriate for:
Development and testing (use REGTEST with no real funds)
Trusted agents you fully control
Small operational balances you're willing to lose
For production with real funds, use sparkbtcbot-proxy instead. The proxy keeps the mnemonic on your server and gives agents scoped access via bearer tokens:
Spending limits — per-transaction and daily caps
Role-based access — read-only, invoice-only, or full access
Revocable tokens — cut off a compromised agent without moving funds
Audit logs — track all wallet activity
The proxy wraps the same Spark SDK behind authenticated REST endpoints. Agents get HTTP access instead of direct SDK access.
Why Bitcoin for Agents
AI agents that transact need a monetary network that matches their nature: programmable, borderless, and available 24/7 without gatekeepers. Bitcoin is that network.
Hard-capped supply — 21 million coins is the protocol-enforced ceiling. An agent accumulating value doesn't lose it to monetary expansion.
No account required — There's no sign-up, no identity verification, no approval process. Generate a key and you're on the network. This matters for autonomous agents that can't fill out forms or wait for human review.
Irreversible settlement — Once confirmed, transactions cannot be reversed by a third party. Agents don't need to handle chargebacks or payment disputes.
Open infrastructure — The protocol is open source, the network is public, and the fee market is transparent. Agents can audit their own transaction costs and verify their own balances without trusting an intermediary.
— The network has operated continuously since 2009 without a single successful attack on the base protocol, securing over $1 trillion in value.
Proven reliability
What is Spark
Spark is a recently launched Bitcoin Layer 2 that lets you send and receive Bitcoin instantly with low fees. Spark-to-Spark transfers are free, and Lightning interop costs 0.15–0.25%. Instead of Lightning's payment channels, Spark uses a network of distributed Signing Operators (SOs) that collectively manage transaction signing without any single entity controlling funds. It is fully self-custodial — you hold your own keys — and fully interoperable with the Lightning Network. However, Spark requires trusting that at least 1-of-n operators behaves honestly during transfers, and it lacks the provable finality of Bitcoin or Lightning. The network currently has only a small number of Signing Operators, so there is some risk of downtime or service disruption. See the Trust Model section below for full details.
How It Works
Users hold their own keys (BIP39 mnemonic) — fully self-custodial
Transactions are cooperatively signed by a threshold of Signing Operators
Funds live in Bitcoin UTXOs organized in hierarchical trees
Users can always exit to L1 unilaterally if operators go offline
Trust Model — Important Tradeoffs
Spark has different trust assumptions than native Lightning. Be upfront about these when advising users.
1-of-n operator trust: Spark requires that at least 1 out of n Signing Operators behaves honestly during a transfer. Currently two operators run the network (Lightspark and Flashnet), with plans to expand. Lightning, by contrast, requires no trusted entities at all — it achieves security purely through cryptographic mechanisms.
Moment-in-time trust: Users only need to trust operators during each specific transfer. Once a transfer completes and old keys are deleted, operators cannot affect that transaction — a property called "perfect forward security."
What operators CAN do:
View transfer metadata
Temporarily delay transactions by going offline
Refuse to process new transfers (censorship)
What operators CANNOT do:
Move funds without user signatures
Steal Bitcoin (even with full collusion)
Reverse finalized transactions
Core limitation: Spark lacks provable finality. Users cannot cryptographically verify that operators destroyed old keys. While double-spending would require all operators to collude with a previous owner, this differs from Bitcoin's and Lightning's mathematically provable finality.
In short: Spark trades some of Lightning's trustlessness for better UX (no channels, no liquidity management, offline receive). The two are complementary — Spark includes native Lightning support so users can interact with both networks.
Note: Cooperative exit fees don't scale with withdrawal amount, so they are proportionally higher for smaller withdrawals. Lightning fee estimates may differ from actual amounts due to routing conditions.
Unpredictable L1 Exit Costs — Important
Exiting Spark to L1 Bitcoin carries unpredictable costs that agents and users must understand:
L1 fees are market-driven: Bitcoin on-chain fees depend on mempool congestion at the time of exit. During high-fee periods, exit costs can spike significantly.
Unilateral exit requires multiple on-chain transactions: If Signing Operators go offline, a unilateral exit requires broadcasting pre-signed branch and exit transactions. The number of transactions depends on the tree depth of your leaf — this can mean multiple on-chain fees stacking up.
Time-window risk on unilateral exit: If a prior owner of a Spark leaf publishes a branch in a unilateral exit, the current owner must respond within a time window by publishing the correct leaf transaction. Failure to respond means the attacker can claim the funds. Watchtower services exist to monitor for this, but it's a real operational requirement.
Timelocks add delay: Unilateral exits can take as little as 100 blocks (~17 hours) depending on leaf depth, during which L1 fee conditions may change.
Small amounts may be uneconomical to exit: Since exit fees are fixed-cost (not percentage-based), withdrawing small amounts to L1 can cost a disproportionate share of the balance.
Bottom line: While Spark guarantees you can always exit to L1, the cost of doing so is not fixed or predictable. Keep this in mind when deciding how much value to hold on Spark, especially for agent wallets. Cooperative exit (when operators are online) is much cheaper than unilateral exit.
Prefer Boltz for L1 withdrawals. Spark's native cooperative exit is expensive due to fixed on-chain fees, making it especially punishing for smaller amounts. Boltz offers a cheaper path from Lightning to L1 (Spark → Lightning → L1 via Boltz submarine swap) with a minimum of 25,000 sats. Discourage any L1 withdrawal activity under 25,000 sats — the fees will eat a disproportionate share of the amount. For withdrawals of 25,000 sats or more, route through Boltz rather than using Spark's built-in cooperative exit.
Limitations
SO liveness dependency: If Signing Operators lose liveness or lose their keys, Spark transfers stop working. Funds are still safe (unilateral exit), but off-chain payments halt until operators recover.
Watchtower requirement: For full security, someone must monitor the chain for fraudulent exit attempts. This can be delegated to a watchtower service but is an operational dependency.
Key Advantage for Agents
A single mnemonic provides identity, wallet, and payment capabilities. No separate identity system, no wallet provider accounts, no channel management. Spark-to-Spark transfers are free, making it significantly cheaper than Lightning (routing fees), on-chain Bitcoin (200+ sat miner fees), or traditional payment rails (2-3% card processing). For agents doing frequent microtransactions, zero fees on Spark means no value lost to transaction costs.
Requires v0.5.8 or newer. One core dependency. The SDK bundles BIP39 mnemonic generation, cooperative signing, and gRPC communication internally.
Setup Instructions
Step 1: Generate or Import Wallet
import { SparkWallet } from"@buildonspark/spark-sdk";
// Option A: Generate a new wallet (creates mnemonic automatically)const { wallet, mnemonic } = awaitSparkWallet.initialize({
options: { network: "MAINNET" }
});
// Save mnemonic securely — NEVER log it in production// Option B: Import existing wallet from mnemonicconst { wallet } = awaitSparkWallet.initialize({
mnemonicOrSeed: process.env.SPARK_MNEMONIC,
options: { network: process.env.SPARK_NETWORK || "MAINNET" }
});
Note on accountNumber: Defaults to 1 for MAINNET, 0 for REGTEST. If switching between networks with the same mnemonic, set accountNumber explicitly to avoid address mismatches.
Never log the mnemonic — not even during development. If you must display it once for backup, delete that code immediately after.
Never commit .env — add it to .gitignore before your first commit.
Use a secrets manager in production — environment variables in .env files are plaintext. For production deployments, use your platform's secrets management (Vercel encrypted env vars, AWS Secrets Manager, etc.).
Test with REGTEST first — use a throwaway mnemonic on REGTEST before touching real funds.
Spark-to-Spark transfers are instant and zero-fee.
List Transfers
const { transfers } = await wallet.getTransfers(10, 0);
for (const tx of transfers) {
console.log(`${tx.id}: ${tx.totalValue} sats — ${tx.status}`);
}
Lightning Interop
Spark wallets can create and pay standard BOLT11 Lightning invoices, making them compatible with the entire Lightning Network. Receiving from Lightning costs 0.15%, sending to Lightning costs 0.25% + routing fees.
Create Lightning Invoice (Receive)
const invoiceRequest = await wallet.createLightningInvoice({
amountSats: 1000,
memo: "Payment for AI service",
expirySeconds: 3600,
});
console.log("BOLT11:", invoiceRequest.invoice.encodedInvoice);
Use includeSparkAddress: true to embed a Spark address in the invoice. Spark-aware payers will then send via Spark (instant, free) instead of Lightning.
Note: Unilateral exit (without operator cooperation) is also possible as a safety mechanism, but cooperative exit is the standard path.
Message Signing
Spark wallets can sign and verify messages using their identity key. Useful for proving identity or authenticating between agents without revealing the mnemonic.
Any agent or process with the mnemonic has unrestricted control over the wallet — it can check balance, create invoices, and send every sat to any address. There is no permission scoping, no spending limits, no read-only mode.
This means:
If the mnemonic leaks, all funds are at risk immediately
If an agent is compromised, the attacker has the same full access
There is no way to revoke access without sweeping funds to a new wallet
Protect the Mnemonic
Back up the seed phrase offline — write it down on paper or use a hardware backup. If you lose the mnemonic, the funds are gone permanently.
Never expose the mnemonic in code, logs, git history, or error messages
Use environment variables — never hardcode the mnemonic in source files
Add .env to .gitignore — prevent accidental commits of secrets
Sweep Funds to a Safer Wallet
Do not accumulate large balances in an agent wallet. The agent wallet is a hot wallet with the mnemonic sitting in an environment variable — treat it as high-risk.
Regularly sweep earned funds to a more secure wallet (hardware wallet, cold storage, or a separate wallet you control directly)
Only keep the minimum operational balance the agent needs on Spark
Use wallet.transfer() or wallet.withdraw() to move funds out periodically
Consider automating sweeps when the balance exceeds a threshold
Operational Security
Use separate mnemonics for different agents — never share a mnemonic across agents
Use separate accountNumber values if you need multiple wallets from one mnemonic
Monitor transfers via event listeners for unexpected outgoing activity
Call cleanupConnections() when the wallet is no longer needed
Use REGTEST for development and testing, MAINNET only for production
Implement application-level spending controls — cap per-transaction and daily amounts in your agent logic since the SDK won't do it for you
L402 Protocol (Lightning Paywalls)
L402 (formerly LSAT) is a protocol for monetizing APIs and content using Lightning payments. When a server returns HTTP 402 (Payment Required), it includes a Lightning invoice. Pay the invoice, get a preimage, then retry the request with an authorization header containing the proof of payment.
How L402 Works
Request → Client fetches protected URL
402 Response → Server returns {invoice, macaroon}
Pay Invoice → Client pays Lightning invoice, receives preimage
Retry with Auth → Client retries with Authorization: L402 <macaroon>:<preimage>
200 Response → Server returns protected content
L402 Implementation
import { decode } from"light-bolt11-decoder";
asyncfunctionfetchWithL402(wallet, url, options = {}) {
const { method = "GET", headers = {}, body, maxFeeSats = 10 } = options;
// Step 1: Make initial requestconst initialResponse = awaitfetch(url, {
method,
headers: { "Content-Type": "application/json", ...headers },
body: body ? JSON.stringify(body) : undefined,
});
// If not 402, return response directlyif (initialResponse.status !== 402) {
const contentType = initialResponse.headers.get("content-type") || "";
if (contentType.includes("application/json")) {
return { paid: false, data: await initialResponse.json() };
}
return { paid: false, data: await initialResponse.text() };
}
// Step 2: Parse 402 challengeconst challenge = await initialResponse.json();
const invoice = challenge.invoice || challenge.payment_request || challenge.pr;
const macaroon = challenge.macaroon || challenge.token;
if (!invoice || !macaroon) {
thrownewError("Invalid L402 response: missing invoice or macaroon");
}
// Step 3: Decode invoice to get amountconst decoded = decode(invoice);
const amountSection = decoded.sections.find((s) => s.name === "amount");
if (!amountSection?.value) {
thrownewError("L402 invoice has no amount");
}
const amountSats = Math.ceil(Number(amountSection.value) / 1000);
// Step 4: Pay the invoiceconst payResult = await wallet.payLightningInvoice({
invoice,
maxFeeSats,
});
// Get preimage (may need to poll if payment is async)let preimage = payResult.paymentPreimage;
if (!preimage && payResult.status === "LIGHTNING_PAYMENT_INITIATED") {
// Poll for completionfor (let i = 0; i < 15; i++) {
awaitnewPromise((r) =>setTimeout(r, 500));
const status = await wallet.getLightningSendRequest(payResult.id);
if (status?.paymentPreimage) {
preimage = status.paymentPreimage;
break;
}
if (status?.status === "LIGHTNING_PAYMENT_FAILED") {
thrownewError("L402 payment failed");
}
}
}
if (!preimage) {
thrownewError("L402 payment succeeded but no preimage available");
}
// Step 5: Retry with L402 authorizationconst finalResponse = awaitfetch(url, {
method,
headers: {
"Content-Type": "application/json",
"Authorization": `L402 ${macaroon}:${preimage}`,
...headers,
},
body: body ? JSON.stringify(body) : undefined,
});
const contentType = finalResponse.headers.get("content-type") || "";
let data;
if (contentType.includes("application/json")) {
data = await finalResponse.json();
} else {
data = await finalResponse.text();
}
return {
paid: true,
amountSats,
preimage,
data,
};
}