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

Pick one to load its steps and code.

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

The same calls as the live run. Add your own storage 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

Step 1

Select spendable proofs

Local cashu-ts logicEXAMPLE

LOCAL wallet.selectProofsToSend()

Computed locally by cashu-ts / your app — not an HTTP call to the mint.

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

Local cashu-ts logicEXAMPLE

LOCAL splitAmount()

Computed locally by cashu-ts / your app — not an HTTP call to the mint.

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

Mint · runs on executeREADY

POST /v1/swap

Preview values for now. Press Run to replace them with the real response.

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

cashu-ts · runs on executeREADY

LOCAL getEncodedToken()

Preview values for now. Press Run to replace them with the real response.

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