Skip to main content
Experimental TechnologySpilman Channels on Arkade are experimental and under active development.
The examples and scripts presented here are for research and proof-of-concept use only.
Do not deploy in production environments.

Spilman Channel Example

Reference implementation of a virtual Spilman Channel within Arkade
A Spilman Channel is a classic unidirectional payment channel design that allows one party (Alice) to incrementally pay another (Bob) offchain, using monotonically increasing state updates. On Arkade, Spilman Channels are implemented as virtual channels, using VTXOs and checkpoint transactions instead of onchain funding and settlement transactions. This design enables lightweight, private, and low-cost payment streams between users while retaining Bitcoin-level security guarantees via Arkade.

Channel Lifecycle

  1. Setup: Alice locks funds so that either Bob can take an ever-increasing amount immediately (by holding the latest state transaction), or Alice can take everything back after a timeout (refund path).
  2. Offchain Updates: Every payment is a new transaction that is signed by Alice and that pays more to Bob than the previous one. The transaction is not published to the Arkade server, but sent to Bob.
  3. Closing the Channel
    • Cooperative Close: Bob can close the channel by adding his signature to the presigned transaction he received from Alice together with the corresponding checkpoint data.
    • Refund Path: If Bob is unresponsive, Alice waits for the CLTV/CSV timelock to expire and reclaims her funds via the refund path.

Spending Paths

A virtual Spilman Channel is composed of a Taproot tree with four key spending paths:
PathScript TypeParticipantsDescription
updateScriptMultiSigAlice + Bob + ServerUsed for cooperative offchain updates
refundScriptCLTV MultiSigAlice + ServerAllows refund after an absolute locktime
unilateralUpdateScriptCSV MultiSigAlice + BobEnables unilateral channel closure after a short delay
unilateralRefundScriptCSV SingleSigAliceFallback refund path after a longer delay
The timelocks are ordered such that: unilateralUpdateDelay < unilateralRefundDelay. This ensures that updates are always possible before refunds, meaning: Bob can always close with the latest valid state before Alice’s refund becomes valid.

Example Implementations

The following code snippets are an excerpt from the ts-sdk repo (spilman.js):
This snippet sets up a virtual Spilman payment channel between Alice, Bob, and a coordinating server. It defines the Tapscript-based spending conditions, covering cooperative updates, time-locked refunds, and unilateral exits, using multisig and timelocked scripts that together form the channel’s lifecycle logic.
import {
  SingleKey,
  Wallet,
  RestArkProvider,
  RestIndexerProvider,
  buildOffchainTx,
  VtxoScript,
  MultisigTapscript,
  CLTVMultisigTapscript,
  CSVMultisigTapscript,
  networks,
} from "../dist/esm/index.js";

// Spilman Channel construction (simplified)
const SERVER_PUBLIC_KEY = hex.decode("e35799...dbdb");
const alice = SingleKey.fromRandomBytes();
const bob = SingleKey.fromRandomBytes();

const updateScript = MultisigTapscript.encode({
  pubkeys: [await alice.xOnlyPublicKey(), await bob.xOnlyPublicKey(), SERVER_PUBLIC_KEY],
}).script;

const refundScript = CLTVMultisigTapscript.encode({
  pubkeys: [await alice.xOnlyPublicKey(), SERVER_PUBLIC_KEY],
  absoluteTimelock: BigInt(chainTip + 10),
}).script;

const unilateralUpdateScript = CSVMultisigTapscript.encode({
  pubkeys: [await alice.xOnlyPublicKey(), await bob.xOnlyPublicKey()],
  timelock: { type: "blocks", value: 100n },
}).script;

const unilateralRefundScript = CSVMultisigTapscript.encode({
  pubkeys: [await alice.xOnlyPublicKey()],
  timelock: { type: "blocks", value: 102n },
}).script;

const virtualSpilmanChannel = new VtxoScript([
  updateScript,
  refundScript,
  unilateralUpdateScript,
  unilateralRefundScript,
]);

This snippet simulates off-chain channel updates between Alice and Bob. Alice first sends 1000 sats, both sign the transaction, then she updates the state by sending 500 more sats, resulting in a new co-signed off-chain transaction reflecting the updated balance.
  console.log("\nStarting channel updates...");
  // Alice sends 1000 to bob
  console.log("Alice sends 1000 sats to Bob");
  const { arkTx: tx1, checkpoints } = buildOffchainTx(
      [input],
      [
          {
              amount: BigInt(1000),
              script: virtualSpilmanChannel.pkScript,
          },
          {
              amount: BigInt(channelCapacity - 1000),
              script: virtualSpilmanChannel.pkScript,
          },
      ],
      serverUnrollScript
  );
  const signedTx1 = await alice.sign(tx1);
  const signedCheckpointsByAlice = await Promise.all(
      checkpoints.map(async (c) => {
          return alice.sign(c, [0]);
      })
  );
  console.log("Alice signed transaction 1");
  bobChannelStates.push(await bob.sign(signedTx1));
  console.log("Bob signed transaction 1");


  // Alice updates the state, sending 500 sats more to Bob
  console.log("\nAlice sends 500 more sats to Bob");
  const { arkTx: tx2 } = buildOffchainTx(
      [input],
      [
          {
              amount: BigInt(1500),
              script: virtualSpilmanChannel.pkScript,
          },
          {
              amount: BigInt(channelCapacity - 1500),
              script: virtualSpilmanChannel.pkScript,
          },
      ],
      serverUnrollScript
  );
  const signedTx2 = await alice.sign(tx2);
  console.log("Alice signed transaction 2");
  bobChannelStates.push(await bob.sign(signedTx2));
  console.log("Bob signed transaction 2");

Integration with Arkade

On Arkade, these channel contracts are expressed as VTXOs. The Arkade server participates in cooperative branches only, facilitating batching and checkpoint finalization, but it cannot unilaterally spend or steal funds. Key properties:
  • Private: Updates remain offchain.
  • Cheap: No onchain footprint until settlement.
  • Safe: Script-level guarantees enforced by timelocks.
  • Compositional: Can be nested or linked to higher-level Arkade contracts.