TRUST — what enforces what in Kaskly
This is the plain-language map of what the Kaspa chain enforces versus what you are trusting the app to do. It is kept accurate with every change to how money is locked or moved, and it is written to be read by a non-developer. (Brief §7 L1, §8 R6.)
⚠️ This is TESTNET. Play money. No real value.
Everything here runs on Kaspa testnet-10. The coins ("TKAS") are free faucet tokens with no monetary value — you cannot lose or make real money using this app, and it is not a place to hold savings. The app refuses to run on any non-testnet network — it will not even start against mainnet. Your keys are generated and stored in your own browser, which is appropriate for testnet keys and nothing else.
Read the rest for exactly what is and isn't guaranteed. Where a guarantee has a limit, the limit is stated.
Two different things live here
Kaskly is a reference client for two separate on-chain primitives. They have different rules, so this document keeps them separate — a guarantee for one is not a guarantee for the other.
- An Ask is one-to-one: you lock some KAS to a single person's address with a message. They reply and the reply is the claim; if they never reply, the deadline returns your money. (Protocol version 2, "V3 covenant".)
- A Kaspak is a prize drop: you lock a pot as a set of sealed envelopes and hand out secret links. Whoever opens a link first keeps what's inside; whatever nobody opens comes back to you after the deadline.
Both are non-custodial (your keys never touch a server) and carry no app fees, ever — no cut, no fee output, at any point. Network miner fees are separate and unavoidable, as with any Kaspa transaction.
Kaspaks (the prize-drop / party model)
A party link is a bearer instrument — this is the whole design
The link a creator posts for everyone (the "party link") carries every envelope's key. That is the same exposure as posting all the individual claim links at once, which is exactly what it is. So:
- Whoever holds the link can open envelopes until they're gone. First come, first served. The share screen says so in the creator's own words: this is the link that "gives out the money."
- The creator cannot stop, pause, reorder, or take back the race once the drop is on chain. No Kaspa script can see the current time, so a link cannot be made to "expire" on its own; only a sweep after the deadline ends it.
- Post it publicly and anyone can claim — a stranger, a bot, or ten friends. Post it where you want your people, not wider. We never see your links (their secret lives in the part of the URL browsers never send to a server), so we cannot get one back for you if it leaks or is forwarded.
- The "lucky draw" is a courtesy, not a rule. The app picks an envelope for you at random, but every amount is public on the chain the moment the drop is created — the "reveal" when you tap is theatre, and the page says so. Someone using their own tools can skip the randomness and take the biggest envelope instead.
- The same-browser memory is a convenience, not enforcement. After you open an envelope, this browser remembers it and shows a note. That memory is trivially bypassable by design: open the same link in another browser, a private window, or another device and you can take another envelope. That is the bearer model working as intended, not a bug.
What the chain enforces here — no trust required
These are consensus rules on the envelope covenant; they hold no matter which client you use:
- 1.Each envelope opens exactly once. Opening one requires that envelope's own key, and the instant its money moves, it is gone from the envelope. Two people racing the same link is settled by the chain — one wins, the other's spend is rejected as a double-spend.
- 2.Only your key can sweep the leftovers, and only after the deadline. The return path requires the creator's signature and the chain rejects it before the deadline. Because only your key can sign it, nobody else — not us, not a miner, not a claimant — can sweep your leftovers. (Honest limit: unlike the Ask refund below, the envelope covenant does not script-pin where the sweep pays — it is your signature that controls that, and the app sends it to your own wallet. Only your key can move it; the destination is your key's choice, not the script's.)
- 3.A claim pays whoever signs it. Spending an envelope requires that envelope's key; the signer chooses the destination (the app sends it to your connected wallet). No one without the key can take it.
- 4.No app fees, and no path for us to touch any of it. There is no fee output and no route through our server to your funds, keys, or anyone's envelope. The server never sees a secret.
What the chain does NOT enforce — honest client, documented not prevented
- A late opening still works. The deadline only makes your sweep possible; it does not switch the links off. Until you actually sweep, a link holder can still open theirs.
- You minted every secret, so you can open your own drop. Nothing stops a creator quietly claiming their own envelopes. What the chain gives everyone instead is visibility: those claims are public and land in addresses anyone can follow. A drop is a promise made visible, not a promise made unbreakable.
- We cannot tell you the openers are different people. One person with ten wallets looks exactly like ten people. The chain guarantees one opening per envelope, nothing about who is behind it.
- The randomness of the draw (above) — a client courtesy, not a chain rule.
- Very small envelopes can be impossible for the network to move, so the app blocks a pot split into envelopes too small to spend. That is a client check, sized from the live network fee.
The one double-claim guarantee, stated exactly
There is one thing the app itself guarantees on top of the chain, and it is worth stating precisely because it is easy to over- or under-claim:
- An accidental double-claim is prevented — and verified on testnet. A single tap will not spend two envelopes, even if the connection drops mid-broadcast, a request is retried, the page is reloaded, or two tabs are open at once. Before it opens anything, the app settles any claim it may already have in flight against the chain, so a claim that quietly succeeded is recognised rather than repeated. This was broken and re-fixed several times and is now confirmed on live testnet.
- A deliberate multi-claim is NOT prevented, by design. If you deliberately open more envelopes from a second browser, device, or private window, you can — that is the bearer model and first-come-first-served working as intended, not a defect. The guarantee above is only about the accident of one action becoming two.
- A "you won" can never be faked. A win is shown only after your own Kaspa node confirms the transaction that paid you — never from anything stored in your browser. So even a corrupted or tampered local record cannot invent a prize or show an envelope you didn't actually open.
- One accepted limit, in the hostile-code case only. If a compromised version of this site were running hostile JavaScript in your browser (see "The trust you place in us" below), it could jam its own claim screen on your machine. It still cannot fake a win or take an envelope you didn't open. We accept this narrow case rather than harden against it, because a page already running hostile code in your browser has far worse options than freezing one screen — and no on-page promise can remove that.
The scoreboard — and exactly how much it can tell you
The public watch link shows a drop's live state, and everything on it comes from your own Kaspa node — no third-party service, no data of ours.
- Always exact: how many envelopes are still sealed, how much KAS is still sealed, and how much sits in each unopened envelope.
- Exact while you watch: who opened what, for how much, and when — for anything that happens while the page is open. This is why the page tells you to watch live.
- Honestly blank otherwise: Kaspa nodes forget old block detail after roughly a day, which is shorter than a typical drop. When an envelope settled outside what your node still remembers, the feed says "settled — details unverifiable" rather than guessing. It will never tell you an envelope was returned when it was actually claimed, and it will never invent an opener.
If your node is having a bad day, every screen here shows an error and asks to retry — a failed read is reported as a failed read, never as "the prize is gone."
Asks (the one-to-one reply-to-claim model)
What the chain enforces — no trust required
These hold on the Ask covenant (V3) no matter which client you use:
- 1.Only the recipient can claim, and only with a reply bound to this Ask. The claim requires the recipient's signature and a payload that carries this Ask's own id — so one reply cannot sweep several people's Asks, and a claim for a different Ask is rejected. (Earlier the chain only checked a 15-byte label; the shipped V3 covenant binds the specific Ask.)
- (Honest limit: the chain checks the reply is present and bound to this Ask; it does not read the words or judge whether the reply is "good." The message content is between you and the recipient.)
- 2.Before the deadline, the sender cannot take the money back. The chain rejects an early refund.
- 3.After the deadline, the refund needs nobody's key. The refund carries no signature — anyone can send it, and the covenant forces it to pay only your address, as the single output, for your locked amount minus at most a small, fixed network-fee allowance set when the Ask was created. The chain rejects a refund to any other address, with a smaller amount, or with extra outputs. (This is stronger than the Kaspak sweep, which is signature-gated rather than output-pinned.)
- 4.Once a refund happens, a late reply can never take the money. The chain rejects it as a double-spend.
- 5.No app fees. Every test decodes the real transactions from independent chain data: money goes recipient-or-sender, and no fee output exists anywhere.
The one honest caveat
Between the deadline passing and the refund actually landing, a late reply is still valid. The chain cannot expire a claim on its own — the refund transaction is what closes the door. Because the refund needs no key, any participant can send it in the first block after the deadline (your app, the recipient's app, or an independent watcher), and the protocol requires clients to do exactly that and requires recipient apps to refuse late replies. The honest product statement: "a reply or your money back — late replies lose to the refund."
What this means if you're the one replying. Your reply is the claim, so it has to land before the refund does. Reply on time and you're paid. But a reply that arrives late — or right at the deadline — races that refund, and if the refund wins, your reply is rejected and the money returns to the asker. You lose only the network fee on the failed claim; the escrow itself can never be taken by a third party or redirected — it can only pay the recipient (you, on time) or refund the asker. A late claim that fails is the asker declining, not a loss of your funds. So reply to Asks you have some reason to trust — this is the same "we disclose it, we don't prevent it" honesty as the bearer risks in Kaspaks above, and it exists for the same reason: no Kaspa script can see the current time, so a claim cannot be made to expire and a late one cannot be given priority.
Message privacy
Everything you write is encrypted. There is no plaintext mode. Ask messages are encrypted so only the recipient can read them; replies are encrypted so only you can read them — using the same encryption scheme as Kasia, the encrypted messenger this extends. A Kaspa address is enough; no key exchange first.
What stays public, permanently, on chain: who asked whom (addresses), how much, the deadline, and whether it ended in a reply or a refund. The words themselves do not. (One honest asterisk: Kasia publishes no official test vectors, so our "same scheme" claim rests on a line-by-line reimplementation of their code, not a cross-check against their output. Flagged for confirmation with the Kasia team.)
The trust assumption we chose on purpose: the transaction indexer
Kaspa nodes do not index transactions by id. A node can tell you what is unspent right now, but it cannot hand you an old transaction or an address history — that is what a separate indexer service is for. This app reads one (api-tn10.kaspa.org), and there is no second source to check it against. So we state the assumption rather than paper over it.
What a dishonest indexer could do: change the message text you see on a settled Ask, misreport whether a finished Ask was answered or refunded, alter a reply shown to a sender, or make a settled Ask look unresolved. That is deception, and worth taking seriously.
What it cannot do — the bound that matters:
- It cannot move your money. Ask refunds are pinned by the covenant to the sender; claims require the recipient's key; Kaspak envelopes require their own keys. No indexer, and no operator of this app, has a spend path.
- It cannot invent or hide a settlement, and it is never on the money path. Whether an escrow is still funded comes from your Kaspa node, not the indexer — and nothing about claiming (reading whether an envelope is open, building the spend, broadcasting it, confirming it) touches the indexer at all. The app reads the indexer only for detail a node cannot give: settled and historical Ask status, a "never funded" check on your own drops (asked only after your node already shows nothing live), and one cosmetic thing — the rarity colour of an envelope. Opening an individual claim link and tapping to reveal reads that drop's creation transaction from the indexer to colour the envelope (a node cannot look a transaction up by its id). That call is gated behind your tap, so just previewing a link sends nothing; it falls back to a plain colour if it fails; and it never decides, gates, or delays whether — or what — you can claim.
- It cannot forge a message on its own. Displayed Ask text is checked against the announcement in the lock transaction; a mismatch is refused rather than shown.
So: a hostile indexer can lie to your eyes about a finished item, or about an envelope's rarity colour. It cannot take, redirect, or freeze a single sompi, and it cannot decide what you are allowed to claim. (Your header's "Earned" figure — income you've been paid for replies and won from Kaspaks — is derived through this indexer route; the balance beside your address comes straight from a Kaspa node with no indexer in the path.)
What your browser talks to — and what it doesn't
Everything the app shows is chain-derived, so your browser only ever contacts:
- Your Kaspa node (via the public node network) — every read that decides money, and every broadcast. This is the money path, and it is node-only, for both Asks and Kaspaks.
- The transaction indexer above (
api-tn10.kaspa.org) — for settled and historical detail, the "never funded" check, and the cosmetic rarity colour, exactly as bounded above and never to move or gate money. - Our own cache — a disposable database of public chain data and encrypted message blobs, keyed by address. It never holds a key or a link secret, and every status is re-verified against the chain before it is shown.
- The KNS name service (
api.knsdomains.org) — and only if you type a .kas name when addressing an Ask — to look up the address it points at. You are trusting that service to return the right address, which is why the address itself is always shown before you send. - A block explorer (
tn10.kaspa.stream) — never automatically; only when you click a "view transaction" link, which opens that separate site, as clicking any external link would.
No analytics, no telemetry, no beacons. Kaskly loads no analytics or tracking scripts of any kind and sends no usage data anywhere — no third-party analytics package, no page-view beacons, nothing that reports what you do. Every request the app makes on its own is one of the functional calls named above: your Kaspa node (the money path), the transaction indexer (settled and historical detail, and the reveal-tap rarity colour bounded above), our own cache, and — only for a .kas name — KNS.
The trust you place in us (the real one)
We never see your keys or your links. Keys are generated and used in your browser only, and Kaskly never holds them. But your browser runs JavaScript we served, and a hostile or compromised version of this site could misbehave inside your own browser — read a key it shouldn't, or jam a screen. This is true of every page here, Asks and Kaspaks alike, and no promise on any page can remove it. It is the one trust you place in us by using the app at all, and we would rather name it than imply it away.
Always true, regardless of outcome
- This deployment runs on Kaspa testnet-10 — play money, no real value. A mainnet version with real KAS is planned but not yet live and will only launch after external security review and legal review of the mechanism.
- No app fees, ever, at the protocol level (D2).
- Non-custodial: your keys never touch a server (D4).
- The chain is the source of truth. Every status the app shows is re-derived from public chain data; its local database is a disposable cache that can be deleted and rebuilt from the chain alone.
How this stays honest: when the code changes how money is locked or moved, this page changes with it — we would rather correct an overclaim the same day than let a trust document promise more than the code delivers. That has happened before (an earlier version of this page described escrow defects that were later fixed and re-proven on testnet, and it was corrected), and it is the standing rule.
This page is rendered from TRUST.md, the same file that ships with the reference client, so what you read here is exactly what the code commits to. Back to Kaskly →