Perps where the chain can't read your box.
Hushring is a perp desk on Solana where nobody outside the trade can see your position. Each trade is a deal between you and one maker. The numbers go into a box, the chain keeps a SHA-256 seal of that box, and only the two of you hold the salt that opens it.
This page covers how a trade works, what stays hidden, how the seal is made, and the small module that does all of it. Everything here runs today on the simulation desk with live prices and test dollars.
Quick start
From nothing to a sealed position.
- Open the desk. Go to /app. Your browser makes a desk account on the spot with 5,000 test dollars. No wallet popup, no email.
- Pick a market and a side. SOL, BTC or ETH, long or short. Type a size and drag leverage between 1× and 20×. The ticket shows your margin and roughly where liquidation sits.
- Ask the makers. Three makers answer with a price and a cap. Offers are good for 15 seconds. Take the best one or click another.
- Watch it from outside. Open the On-chain view tab. That's your box the way a stranger sees it: two wallets, a time, a seal and seven bars.
Try it
This box runs hush.js from this site against the live index price.
// press Run
A trade, start to end
Three steps, one box, two people who can read it.
1. Makers quote
You pick a market, a side, a size and leverage. The desk sends that request to three makers. Each one answers with a price for your exact size and the multiple of your margin it will lock. The offers are addressed to you; nobody else sees the size you asked for.
2. The box closes
You take an offer. Your margin and the maker's margin go into one box. Neither side can take money out alone. The desk writes the position down, hashes it with a fresh salt and publishes only the hash. That hash is the seal.
3. The box opens once
You can close any time. The box pays out at the index price at that moment: what you won comes out of the maker's margin, what you lost goes to the maker. The maker can only close it by liquidating you, and has to show the price crossed your line without saying where the line was.
import * as hush from "SITE/lib/hush.js";
const { price } = await hush.fetchIndex("SOL");
const offers = hush.quotes({ side: "long", size: 10, leverage: 5, index: price });
const box = hush.open(hush.best(offers), { market: "SOL" });
const { seal, salt } = await hush.seal(box);
console.log(seal); // what the chain keeps
console.log(hush.publicView(box)); // what a stranger reads
console.log(hush.settle(box, price * 1.02)); // the split if SOL moves 2%<script type="module">
import * as hush from "SITE/lib/hush.js";
const { price } = await hush.fetchIndex("ETH");
const box = hush.open(hush.best(hush.quotes({ side: "short", size: 2, leverage: 3, index: price })));
document.body.textContent = (await hush.seal(box)).seal;
</script>Makers and quotes
There's no order book and no shared pool.
Every position is a deal between you and one maker. Three makers answer every request on the desk. Each quotes the index price plus its own spread and puts up a multiple of your margin. A bigger multiple means a bigger possible win for you, and makers charge for it with a wider spread.
| Maker | Spread | Cap | Most you can win |
|---|
The spread on each offer wobbles a little around the maker's base so the three don't always line up the same way. For a long the best offer is the lowest price; for a short it's the highest.
Margin, profit, liquidation
The same few lines of maths for every market.
| Value | How it's worked out |
|---|---|
| Notional | Size × entry price. |
| Your margin | Notional ÷ leverage. It's also the most you can lose. |
| Maker margin | Your margin × the maker's cap. The most you can win. |
| Profit | Size × (price − entry) for a long, the reverse for a short, clamped between −your margin and +maker margin. |
| Liquidation | The price where your margin minus your loss equals 20% of your margin. |
| Fees and funding | None. Makers earn the spread between their quote and the index. |
How far liquidation sits
For an entry of $100, this is where each leverage gets liquidated. The table is computed by liquidationPrice() from hush.js as the page loads.
| Leverage | Distance | Long liquidated at | Short liquidated at |
|---|
The seal
SHA-256 over the position and a salt.
When a box closes the desk writes the position as a fixed list of fields, adds a random 16-byte salt and hashes the whole string with SHA-256. The chain keeps the hash. You and the maker keep the salt. Without the salt, guessing the position from the hash means guessing every field and 128 random bits at once.
import { seal, verify } from "SITE/lib/hush.js";
const sealed = await seal(box); // { seal: "9f3c…", salt: "a71e…" }
await verify(box, sealed); // true
await verify({ ...box, size: 11 }, sealed); // false: one field changed// canonical(box) + "|" + salt, then SHA-256, hex
[["id","…"],["market","SOL"],["side","long"],["size",10],["leverage",5],
["entry",71.35],["margin",142.7],["makerMargin",142.7],["maker","Orrin"],
["trader","V4xR…V2br"],["opened",1794765606000]]|a71e…canonical(). Two boxes with the same numbers but different salts get different seals, so identical trades don't look identical on-chain.The desk
What every part of /app does.
| Part | What it does |
|---|---|
| Market bar | Index price and 24h change, high and low from Coinbase, refreshed every 4 seconds. The age of the price counts up beside it. |
| Chart | Kraken candles from 1m to 1D, Coinbase if Kraken doesn't answer. The brass line is the index price you trade at; dashed red lines are your own liquidation levels. |
| Makers | The three makers' current short and long prices for this market, with the best one marked. |
| Ticket | Side, size, leverage, and a live summary of notional, margin and liquidation. Ask the makers returns three offers with a 15-second timer. |
| Positions | Open boxes with live profit at the index price, the maker, the first characters of the seal and a Close button. |
| On-chain view | Your boxes the way a stranger sees them. Bars instead of numbers. |
| Cover the dollar amounts | Blurs every money figure so you can share your screen. |
The desk watches the index while the tab is open. If the price crosses a box's liquidation line, the box is closed at that line and the rest of your margin comes back.
hush.js
One ES module, no dependencies, served from this site.
import * as hush from "SITE/lib/hush.js";
console.log(hush.VERSION, hush.CONST.MAX_LEVERAGE);# the module itself
curl SITE/lib/hush.js
# the index price it reads
curl https://api.exchange.coinbase.com/products/SOL-USD/stats| Function | Returns |
|---|---|
quotes({side,size,leverage,index}) | Three offers with price, cap, both margins, liquidation and expiry. |
best(offers) | The best offer for your side. |
open(offer, opts) | A position. Throws if the offer expired or the balance is short. |
settle(pos, price) | Profit, what each side gets, and whether it was capped or liquidated. |
liquidationPrice({side,entry,leverage}) | The liquidation line. |
capPrice(pos) | The price past which the position pays nothing more. |
seal(pos, salt?) · verify(pos, sealed) | The SHA-256 seal and its check. |
publicView(pos, phase) | What the chain shows for an open or closed box. |
fetchIndex · fetchStats · fetchCandles | Live prices from Coinbase and Kraken. |
Markets and prices
Three markets, two public price sources.
| Market | Index | Candles |
|---|---|---|
| SOL-USD | Coinbase SOL-USD | Kraken SOLUSD |
| BTC-USD | Coinbase BTC-USD | Kraken XBTUSD |
| ETH-USD | Coinbase ETH-USD | Kraken ETHUSD |
Every open and close uses one price: the index at that moment. The desk refuses a price older than 60 seconds.
Constants
Read live from hush.CONST.
| Name | Value |
|---|
Errors
Every HushError has a code from this list.
| Code | Message |
|---|
Threat model
What the box protects against, and what it doesn't.
Covered
- Liquidation hunting. Nobody outside the trade knows where your line is, so nobody can aim the market at it.
- Copy and fade traders. Your size and side don't show up next to your wallet.
- Tampering after the fact. Change one field of a box and its seal stops matching.
Not covered
- Your maker. The maker on the other side sees everything in your box and could use it when trading elsewhere.
- Timing. Both wallets and the time of every step are public. Someone patient can learn things from timing alone.
- Your browser. The desk account and the salts live in this browser's storage. Anything that can read the page can read them.
- Bad prices. A box settles at one index price. If that price is wrong or late, it settles anyway.
Limits
What the desk doesn't do yet.
- Market orders only. With no order book there's nowhere to rest a limit order.
- No take profit or stop loss. Liquidation is the only automatic close.
- Liquidation is watched by your open tab. Close the tab and the box waits until you're back.
- One box per trade. There's no adding to a position; open a second box instead.
$HUSH
The token of the box room.
$HUSH is the token for Hushring. The contract address appears below as soon as it's live.
FAQ
Why quotes and not one market price?
Because each box has exactly one maker on the other side. A quote is that maker saying what it wants for your size. Three quotes let you pick.
Can the maker run off with my margin?
No. Both margins sit in the box from the moment it opens, and the box only pays out at the index price.
What does the chain see if I win big?
That a box closed, which market, and the index price at close. Not how much you made.
Where are my test dollars kept?
In your browser's local storage. Clear it, or press Reset account, and you start over with 5,000.
Can I check a seal myself?
Yes. Take the position and its salt, call verify() from hush.js, or hash canonical(pos) + "|" + salt with any SHA-256 tool.