Cashu playground

Run cashu-ts flows and see what actually changes.

Choose a flow, run it against a test mint, and compare the request, response, wallet state, and cashu-ts code. Test shortcuts are labelled where they appear.

Primary mint: https://nofee.testnut.cashu.spaceFallback: https://testnut.cashu.spaceLive calls and test-only steps are labelled in the timeline.Open starter kit

How it works

Start here.

1. Choose a flowUse the recipe cards below. Create wallet is the clean first run.
2. Press runThe timeline shows each request and response.
3. Copy the codeThe code panel shows the cashu-ts calls and the state your app owns.

Choose a flow

These cards are clickable.

Inputs

Send token

Mint: https://nofee.testnut.cashu.space

Select proofs, swap for sender change and receiver proofs, then encode the token.

Ready. Run this to mint a fresh 21 sat test wallet, swap live proofs, and encode the receiver token.

Code

cashu-ts code

send-token.ts

Kept close to the cashu-ts docs. Add your own storage functions where shown.

import { Wallet, getEncodedToken } from '@cashu/cashu-ts'

const mintUrl = "https://nofee.testnut.cashu.space"
const amount = 11

const wallet = new Wallet(mintUrl)
await wallet.loadMint()

const proofs = await loadSpendableProofs()
const { keep, send } = await wallet.ops.send(amount, proofs).run()
const token = getEncodedToken({ mint: mintUrl, proofs: send })

await replaceProofs({ remove: proofs, add: keep }) // your app persistence function
console.log(token)

Workings

Request / response timeline

4 steps

Step 1

Select spendable proofs

EXAMPLE

LOCAL wallet.selectProofs()

Shows which proofs are consumed, which remain untouched, and whether the send creates change.

Requested send amount

{
  "amount": 11
}

Available proofs in wallet

[
  {
    "amount": 8,
    "id": "009a1f293253e41e"
  },
  {
    "amount": 8,
    "id": "009a1f293253e41e"
  },
  {
    "amount": 4,
    "id": "009a1f293253e41e"
  },
  {
    "amount": 1,
    "id": "009a1f293253e41e"
  }
]

Selected proofs to consume

[
  {
    "amount": 8,
    "id": "009a1f293253e41e"
  },
  {
    "amount": 4,
    "id": "009a1f293253e41e"
  }
]

Untouched proofs that stay put

[
  {
    "amount": 8,
    "id": "009a1f293253e41e"
  },
  {
    "amount": 1,
    "id": "009a1f293253e41e"
  }
]

Expected change from swap

{
  "selectedTotal": 12,
  "sendAmount": 11,
  "changeAmount": 1
}

Step 2

Construct send + change outputs

EXAMPLE

LOCAL splitAmount()

The sender-facing outputs are made explicit here so the user can see how their edited amount changes the split.

Request

{
  "sendAmount": 11,
  "changeAmount": 1
}

Receiver output targets

[
  8,
  2,
  1
]

Sender change outputs

[
  1
]

Step 3

Swap for receiver proofs

READY

POST /v1/swap

When run, this step spends freshly minted test proofs at the mint and returns receiver proofs plus sender change.

Inputs: proofs the sender spends

[
  {
    "amount": 8,
    "id": "009a1f293253e41e"
  },
  {
    "amount": 4,
    "id": "009a1f293253e41e"
  }
]

Outputs for receiver token

[
  8,
  2,
  1
]

Outputs for sender change

[
  1
]

Receiver proofs minted by swap

[
  {
    "amount": 8,
    "id": "009a1f293253e41e"
  },
  {
    "amount": 2,
    "id": "009a1f293253e41e"
  },
  {
    "amount": 1,
    "id": "009a1f293253e41e"
  }
]

Sender wallet after swap

{
  "untouched": [
    {
      "amount": 8,
      "id": "009a1f293253e41e"
    },
    {
      "amount": 1,
      "id": "009a1f293253e41e"
    }
  ],
  "freshChange": [
    {
      "amount": 1,
      "id": "009a1f293253e41e"
    }
  ]
}

Step 4

Encode portable token

READY

LOCAL getEncodedToken()

When run, the receiver token contains live test proofs produced by the swap.

Request

{
  "proofs": [
    {
      "amount": 8,
      "id": "009a1f293253e41e"
    },
    {
      "amount": 2,
      "id": "009a1f293253e41e"
    },
    {
      "amount": 1,
      "id": "009a1f293253e41e"
    }
  ]
}

Response

{
  "token": "cashu-demo-send-11-8-2-1"
}

State

Before / after

Token output

Selected proofs

8 sat + 4 satConsumes 12 sat to cover a 11 sat send.

Untouched proofs

8 sat + 1 satThese stay in the sender wallet before swap change comes back.

Fresh change

1 satNew proofs returned to the sender from the live swap.

Receiver outputs

8 sat + 2 sat + 1 satThe proofs that end up inside the encoded token.

Before summary

{
  "balance": 21,
  "requestedAmount": 11,
  "consumed": [
    8,
    4
  ],
  "untouched": [
    8,
    1
  ]
}

After summary

{
  "balance": 10,
  "consumed": [
    8,
    4
  ],
  "untouched": [
    8,
    1
  ],
  "senderChange": [
    1
  ],
  "receiverProofs": [
    8,
    2,
    1
  ]
}

Cashu token

cashu-demo-send-11-8-2-1