/SKILL.md
Guide for developing with the Arkade TypeScript SDK (@arkade-os/sdk) — Bitcoin wallets, Lightning, smart contracts, and stablecoin swaps.
npx skillsauth add arkade-os/skill arkadeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Arkade is a programmable Bitcoin execution layer. It uses VTXOs (Virtual Transaction Outputs) to enable instant offchain Bitcoin transactions with near-zero fees, while users retain full self-custody and unilateral exit rights. No changes to Bitcoin are required.
Use current Arkade terminology in all docs, comments, and user-facing text:
pnpm add @arkade-os/sdk
Requires Node.js >= 22.
import { generateMnemonic } from "@scure/bip39";
import { wordlist } from "@scure/bip39/wordlists/english";
import { MnemonicIdentity, Wallet } from "@arkade-os/sdk";
const mnemonic = generateMnemonic(wordlist);
const identity = MnemonicIdentity.fromMnemonic(mnemonic);
const wallet = await Wallet.create({
identity,
arkServerUrl: "https://arkade.computer",
});
const address = await wallet.getAddress();
console.log("Arkade address:", address);
For production, always use a secure key management solution rather than hardcoded keys.
// Offchain Arkade address (ark1.../tark1...) — for instant payments
const arkAddress = await wallet.getAddress();
// Boarding address — for receiving onchain BTC to be onboarded later
const boardingAddress = await wallet.getBoardingAddress();
const balance = await wallet.getBalance();
console.log("Available:", balance.available, "sats"); // spendable now
console.log("Total:", balance.total, "sats"); // includes recoverable
console.log("Settled:", balance.settled, "sats"); // Bitcoin-anchored
console.log("Preconfirmed:", balance.preconfirmed, "sats"); // cosigned
// Pending onchain deposits
console.log("Boarding:", balance.boarding.total, "sats");
// Send to an Arkade address — instant, near-zero fees
const txid = await wallet.sendBitcoin({
address: "ark1...",
amount: 50000, // satoshis
});
For onchain destinations (bc1.../tb1...), use the Ramps offboard flow below. For Lightning invoices, use @arkade-os/boltz-swap.
const address = await wallet.getAddress();
// Share this address with the sender
// Monitor for incoming funds
const stop = wallet.notifyIncomingFunds(async (notification) => {
if (notification.type === "vtxo") {
for (const vtxo of notification.vtxos) {
console.log(`Received ${vtxo.amount} sats`);
}
}
});
// Call stop() when done listening
const vtxos = await wallet.getVtxos();
for (const vtxo of vtxos) {
console.log(vtxo.txid, vtxo.amount, vtxo.status);
}
Convert between onchain Bitcoin UTXOs and offchain Arkade VTXOs. Best for large transfers; for everyday amounts, Lightning swaps have lower overhead.
import { Ramps } from "@arkade-os/sdk";
const ramps = new Ramps(wallet);
// Get fee info from the Arkade operator
const info = await wallet.arkProvider.getInfo();
// Onboard: convert boarding UTXOs to VTXOs
const commitmentTxid = await ramps.onboard(info.fees);
// Offboard: convert VTXOs to onchain BTC
const exitTxid = await ramps.offboard(
"bc1q...", // destination onchain address
info.fees,
// amount, // optional — defaults to all available
);
pnpm add @arkade-os/boltz-swap
Lightning integration uses Boltz submarine swaps to bridge between Arkade and the Lightning Network.
import { ArkadeSwaps, BoltzSwapProvider } from "@arkade-os/boltz-swap";
const swapProvider = new BoltzSwapProvider({
apiUrl: "https://api.ark.boltz.exchange",
network: "bitcoin",
});
const lightning = new ArkadeSwaps({
wallet,
swapProvider,
});
// Receive via Lightning (reverse swap)
const { invoice, paymentHash } = await lightning.createLightningInvoice({
amount: 25000,
});
console.log("Pay this:", invoice);
// Send via Lightning (submarine swap)
const result = await lightning.sendLightningPayment({
invoice: "lnbc...",
});
console.log("Preimage:", result.preimage);
| Network | URL |
|---------|-----|
| Bitcoin mainnet | https://api.ark.boltz.exchange |
| Mutinynet | https://api.boltz.mutinynet.arkade.sh |
| Signet | https://api.boltz.signet.arkade.sh |
| Regtest (local) | http://localhost:9069 |
This package (@arkade-os/skill) provides higher-level wrapper classes over the SDK:
pnpm add @arkade-os/skill
import { generateMnemonic } from "@scure/bip39";
import { wordlist } from "@scure/bip39/wordlists/english";
import { MnemonicIdentity, Wallet } from "@arkade-os/sdk";
import {
ArkadeBitcoinSkill,
ArkadeLightningSkill,
LendaSwapSkill,
} from "@arkade-os/skill";
const mnemonic = generateMnemonic(wordlist);
const identity = MnemonicIdentity.fromMnemonic(mnemonic);
const wallet = await Wallet.create({
identity,
arkServerUrl: "https://arkade.computer",
});
// Bitcoin: addresses, balances, send/receive, onboard/offboard
const bitcoin = new ArkadeBitcoinSkill(wallet);
const balance = await bitcoin.getBalance();
await bitcoin.send({ address: "ark1...", amount: 50000 });
// Lightning: invoices, payments via Boltz
const lightning = new ArkadeLightningSkill({ wallet });
const inv = await lightning.createInvoice({ amount: 25000 });
// Stablecoin swaps: BTC <-> USDC/USDT
const lendaswap = new LendaSwapSkill({ wallet });
const quote = await lendaswap.getQuoteBtcToStablecoin(100000, "usdc_pol");
getArkadeAddress() / getBoardingAddress() — get addressesgetBalance() — balance breakdown (offchain + onchain)send({ address, amount }) — send sats offchaingetTransactionHistory() — transaction listonboard(params) / offboard(params) — onchain rampswaitForIncomingFunds(timeout?) — wait for incoming paymentcreateInvoice({ amount, description? }) — Lightning invoice (reverse swap)payInvoice({ bolt11 }) — pay Lightning invoice (submarine swap)getFees() / getLimits() — swap fees and limitsgetPendingSwaps() / getSwapHistory() — swap trackinggetQuoteBtcToStablecoin(amount, token) / getQuoteStablecoinToBtc(amount, token)swapBtcToStablecoin(params) / swapStablecoinToBtc(params)getSwapStatus(swapId) / getPendingSwaps() / getSwapHistory()claimSwap(swapId) / refundSwap(swapId)getAvailablePairs()Non-custodial BTC/stablecoin atomic swaps via HTLCs.
Supported tokens: usdc_pol, usdc_eth, usdc_arb, usdt0_pol, usdt_eth, usdt_arb
Supported chains: polygon, ethereum, arbitrum
const lendaswap = new LendaSwapSkill({ wallet });
// Get quote
const quote = await lendaswap.getQuoteBtcToStablecoin(100000, "usdc_pol");
console.log("You'll receive:", quote.targetAmount, "USDC");
// Execute swap (BTC -> USDC)
const swap = await lendaswap.swapBtcToStablecoin({
targetAddress: "0x...", // EVM address
targetToken: "usdc_pol",
targetChain: "polygon",
sourceAmount: 100000,
});
console.log("Swap ID:", swap.swapId);
// Check status
const status = await lendaswap.getSwapStatus(swap.swapId);
// Claim completed swap
const claim = await lendaswap.claimSwap(swap.swapId);
Arkade supports any valid Tapscript as VTXO locking conditions, enabling programmable offchain Bitcoin.
pnpm add @arkade-os/sdk @scure/base
import {
RestArkProvider,
RestIndexerProvider,
VtxoScript,
MultisigTapscript,
CLTVMultisigTapscript,
CSVMultisigTapscript,
} from "@arkade-os/sdk";
import { hex } from "@scure/base";
const arkProvider = new RestArkProvider("https://mutinynet.arkade.sh");
const indexerProvider = new RestIndexerProvider("https://mutinynet.arkade.sh");
const info = await arkProvider.getInfo();
const operatorPubkey = hex.decode(info.signerPubkey).slice(1);
Available contract primitives:
Contract patterns in docs: HTLC/Hashlock, Escrow (3-path), Spilman channels, Dryja-Poon channels, Lightning channels, chain swaps, Oracle DLC.
Use @scure/base for encoding, NOT bitcoinjs-lib.
See: https://docs.arkadeos.com/contracts/overview
| Network | Operator URL | Explorer |
|---------|-----------|----------|
| Bitcoin mainnet | https://arkade.computer | https://arkade.space |
| Mutinynet (testnet) | https://mutinynet.arkade.sh | https://explorer.mutinynet.arkade.sh |
| Signet | https://signet.arkade.sh | https://explorer.signet.arkade.sh |
| Regtest (local) | http://localhost:7070 | — |
Local development:
nigiri start --ark
This starts a Bitcoin regtest node with an Arkade operator at http://localhost:7070.
ark1... (mainnet) / tark1... (testnet) — bech32m-encoded addresses containing operator + user keys.development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
development
Run, watch, debug, and extend OpenClaw QA testing with qa-lab and qa-channel. Use when Codex needs to execute the repo-backed QA suite, inspect live QA artifacts, debug failing scenarios, add new QA scenarios, or explain the OpenClaw QA workflow. Prefer the live OpenAI lane with regular openai/gpt-5.4 in fast mode; do not use gpt-5.4-pro or gpt-5.4-mini unless the user explicitly overrides that policy.
development
End-to-end Parallels smoke, upgrade, and rerun workflow for OpenClaw across macOS, Windows, and Linux guests. Use when Codex needs to run, rerun, debug, or interpret VM-based install, onboarding, gateway smoke tests, latest-release-to-main upgrade checks, fresh snapshot retests, or optional Discord roundtrip verification under Parallels.