Skip to main content
When a sender cancels a vesting stream, the covenant computes the vested amount at the moment of cancellation and splits the pool fairly:
  • Vested (unclaimed) tokens go to the recipient
  • Unvested tokens return to the sender
Cancel requires FLAG_CANCELABLE (0x01) to be set. If the stream was created without this flag, it cannot be cancelled by anyone.

Split Formula

At cancellation time T:
elapsed       = T - cursor
vestedTotal   = (totalAmount × elapsed) / duration    # linear
claimable     = vestedTotal - totalReleased            # what recipient gets
unvested      = totalAmount - vestedTotal              # what sender gets
If the stream is paused at cancellation time, the cursor reflects the pre-pause value. The unvested portion is calculated as of the pause_start time.

How to Cancel in the App

1

Open the stream

Navigate to Streams and select the stream you want to cancel.
2

Click Cancel

Click Cancel Stream. The transaction preview shows the recipient and sender split amounts.
3

Sign and broadcast

Sign with the sender wallet. The single transaction:
  • Sends the vested (unclaimed) amount to the recipient’s address
  • Sends the unvested amount back to the sender’s address
  • Consumes the stream UTXO without producing a replacement (CANCELLED terminal state)

What Happens if the Recipient Already Claimed Some?

The split correctly accounts for prior claims. total_released is read from the NFT state, so only the difference between vestedTotal and totalReleased goes to the recipient.
recipient_gets = vestedTotal - totalReleased
sender_gets    = totalAmount - vestedTotal

API

POST /api/streams/:id/cancel
x-user-address: bchtest:q...
Content-Type: application/json

{
  "sender": "bchtest:q..."
}

# Response
{
  "success": true,
  "vestedAmount": 2.5,
  "unvestedAmount": 7.5,
  "wcTransaction": { "...": "..." }
}

POST /api/streams/:id/confirm-cancel
Content-Type: application/json

{
  "txHash": "hex64"
}