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.
1. Choose a flow Use the recipe cards below. Create wallet is the clean first run.
2. Press run The timeline shows each request and response.
3. Copy the code The code panel shows the cashu-ts calls and the state your app owns.
Create wallet Create a wallet object and load mint metadata. Storage is your app’s job. Open Mint token Create a BOLT11 quote, use the test mint auto-fill, then mint and store real test proofs. Open Send token Select proofs, swap for sender change and receiver proofs, then encode the token. Open Receive token Mint a fresh token in the background, receive it live, then store receiver proofs. Selected Melt token / pay invoice Mint wallet proofs, create a payable test invoice, melt live, and store returned change. Open
The same calls as the live run. Add your own storage where shown.
import { Wallet } from '@cashu/cashu-ts'
const mintUrl = "https://nofee.testnut.cashu.space"
const token = "cashueyJ0b2tlbiI6W3sibWludCI6Imh0dHBzOi8vbm9mZWUudGVzdG51dC5jYXNodS5zcGFjZSIsInByb29mcyI6W3siYW1vdW50Ijo4LCJpZCI6IjAwOWExZjI5MzI1M2U0MWUiLCJzZWNyZXQiOiJkZW1vLXNlbmQtMSIsIkMiOiIwMnNlbmQxIn0seyJhbW91bnQiOjIsImlkIjoiMDA5YTFmMjkzMjUzZTQxZSIsInNlY3JldCI6ImRlbW8tc2VuZC0yIiwiQyI6IjAyc2VuZDIifSx7ImFtb3VudCI6MSwiaWQiOiIwMDlhMWYyOTMyNTNlNDFlIiwic2VjcmV0IjoiZGVtby1zZW5kLTMiLCJDIjoiMDJzZW5kMyJ9XX1dfQ"
const wallet = new Wallet(mintUrl)
await wallet.loadMint()
const proofs = await wallet.ops.receive(token).run()
await saveProofs(proofs) // your app persistence function
Step 1
Accept pasted token Local cashu-ts logic EXAMPLE
LOCAL receiveToken(token)
Computed locally by cashu-ts / your app — not an HTTP call to the mint.
When run with the default token, the API mints a fresh live token first and uses that instead of this static example.
Request
{
"token": "cashueyJ0b2tlbiI6W3sibWludCI6Imh0dHBzOi8vbm9mZWUudGVzdG51dC5jYXNodS5zcGFjZSIsInByb29mcyI6W3siYW1vdW50Ijo4LCJpZCI6IjAwOWExZjI5MzI1M2U0MWUiLCJzZWNyZXQiOiJkZW1vLXNlbmQtMSIsIkMiOiIwMnNlbmQxIn0seyJhbW91bnQiOjIsImlkIjoiMDA5YTFmMjkzMjUzZTQxZSIsInNlY3JldCI6ImRlbW8tc2VuZC0yIiwiQyI6IjAyc2VuZDIifSx7ImFtb3VudCI6MSwiaWQiOiIwMDlhMWYyOTMyNTNlNDFlIiwic2VjcmV0IjoiZGVtby1zZW5kLTMiLCJDIjoiMDJzZW5kMyJ9XX1dfQ"
} Response
{
"accepted": true,
"prefix": "cashu",
"length": 391
} Step 2
Decode token payload Local cashu-ts logic EXAMPLE
LOCAL JSON.parse(base64url(token))
Computed locally by cashu-ts / your app — not an HTTP call to the mint.
The token carries the mint URL and proofs. This step exposes both before import.
Request
{
"token": "cashueyJ0b2tlbiI6W3sibWludCI6Imh0dHBzOi8vbm9mZWUudGVzdG51dC5jYXNodS5zcGFjZSIsInByb29mcyI6W3siYW1vdW50Ijo4LCJpZCI6IjAwOWExZjI5MzI1M2U0MWUiLCJzZWNyZXQiOiJkZW1vLXNlbmQtMSIsIkMiOiIwMnNlbmQxIn0seyJhbW91bnQiOjIsImlkIjoiMDA5YTFmMjkzMjUzZTQxZSIsInNlY3JldCI6ImRlbW8tc2VuZC0yIiwiQyI6IjAyc2VuZDIifSx7ImFtb3VudCI6MSwiaWQiOiIwMDlhMWYyOTMyNTNlNDFlIiwic2VjcmV0IjoiZGVtby1zZW5kLTMiLCJDIjoiMDJzZW5kMyJ9XX1dfQ"
} Decoded mint
{
"mint": "https://nofee.testnut.cashu.space"
} Decoded proofs
[
{
"amount": 8,
"id": "009a1f293253e41e",
"secret": "demo-send-1",
"C": "02send1"
},
{
"amount": 2,
"id": "009a1f293253e41e",
"secret": "demo-send-2",
"C": "02send2"
},
{
"amount": 1,
"id": "009a1f293253e41e",
"secret": "demo-send-3",
"C": "02send3"
}
] Step 3
Validate token shape Local cashu-ts logic EXAMPLE
LOCAL validateProofs()
Computed locally by cashu-ts / your app — not an HTTP call to the mint.
Before import, check the decoded mint and proof fields against what the receiver expected.
Request
{
"expectedMint": "https://nofee.testnut.cashu.space",
"decodedMint": "https://nofee.testnut.cashu.space"
} Mint check
{
"expectedMint": "https://nofee.testnut.cashu.space",
"decodedMint": "https://nofee.testnut.cashu.space",
"mintMatchesExpected": true
} Proof summary
{
"proofCount": 3,
"totalAmount": 11
} cashu-ts · runs on execute READY
LOCAL wallet.receive()
Preview values for now. Press Run to replace them with the real response.
When run, cashu-ts spends the token proofs at the mint and returns fresh receiver-owned proofs.
Request
{
"proofs": [
{
"amount": 8,
"id": "009a1f293253e41e",
"secret": "demo-send-1",
"C": "02send1"
},
{
"amount": 2,
"id": "009a1f293253e41e",
"secret": "demo-send-2",
"C": "02send2"
},
{
"amount": 1,
"id": "009a1f293253e41e",
"secret": "demo-send-3",
"C": "02send3"
}
]
} Response
{
"balance": 11,
"proofs": [
{
"amount": 8,
"id": "009a1f293253e41e",
"secret": "demo-send-1",
"C": "02send1"
},
{
"amount": 2,
"id": "009a1f293253e41e",
"secret": "demo-send-2",
"C": "02send2"
},
{
"amount": 1,
"id": "009a1f293253e41e",
"secret": "demo-send-3",
"C": "02send3"
}
]
} Decoded mint
https://nofee.testnut.cashu.space Expected https://nofee.testnut.cashu.space. Mint check
Matches Shape validation happens before proofs are imported. Imported proofs
8 sat + 2 sat + 1 sat 3 proofs moved into the receiver wallet. Receiver balance
11 sat Wallet goes from 0 sat to 11 sat. Before summary
{
"balance": 0,
"expectedMint": "https://nofee.testnut.cashu.space"
} After summary
{
"balance": 11,
"expectedMint": "https://nofee.testnut.cashu.space",
"decodedMint": "https://nofee.testnut.cashu.space",
"importedAmount": 11,
"importedProofs": [
8,
2,
1
]
} Cashu token
cashueyJ0b2tlbiI6W3sibWludCI6Imh0dHBzOi8vbm9mZWUudGVzdG51dC5jYXNodS5zcGFjZSIsInByb29mcyI6W3siYW1vdW50Ijo4LCJpZCI6IjAwOWExZjI5MzI1M2U0MWUiLCJzZWNyZXQiOiJkZW1vLXNlbmQtMSIsIkMiOiIwMnNlbmQxIn0seyJhbW91bnQiOjIsImlkIjoiMDA5YTFmMjkzMjUzZTQxZSIsInNlY3JldCI6ImRlbW8tc2VuZC0yIiwiQyI6IjAyc2VuZDIifSx7ImFtb3VudCI6MSwiaWQiOiIwMDlhMWYyOTMyNTNlNDFlIiwic2VjcmV0IjoiZGVtby1zZW5kLTMiLCJDIjoiMDJzZW5kMyJ9XX1dfQ