Sealed bid auctions

Everything the create page does, as three calls, with the rules that decide what a bid means.

Try one

Run these in order against the live network. The auction closes about a minute after you open it, so you can watch a real one through from an empty board to a result.

1. Open the auction

The rules travel with it: the currency and its decimals, an optional reserve and an optional maximum. Rules that cannot be satisfied, like a maximum below the reserve, are refused here rather than at the close on an auction already running.

const auction = await peal.createAuction({
  title:        'Signed tour poster',
  description:  'One of a kind, ships worldwide.',
  imageUrl:     'https://images.example.com/poster.jpg',

  closesIn:     3600,        // or closesAt: '2026-09-12T18:00:00Z'

  currency:     'USD',       // decimals come with the code
  reserveMinor: 10_00,       // nothing below this can win
  maximumMinor: 500_00,      // nothing above this can win

  tag:          'my-shop',
});

// auction.bid_url is a hosted page bidders can open right away.

2. Place a sealed bid

The amount goes into a fixed width record and is encrypted here with batched threshold encryption, so what reaches the network is 320 bytes of ciphertext whether the bid is five dollars or five hundred thousand. Run it more than once to add bidders: none of them can see the others.

await peal.bid(auction.id, {
  amountMinor: 125_00,       // 125.00 in a 2 decimal currency
  name:        'ana',        // shown on the board, never trusted
});

3. Read the board

Null until it closes, so "not open yet" can never be read as "no bids". Afterwards: every readable bid ranked, the queue the rules allow to win, and anything discarded with the reason why.

const { winner, queue, bids, discarded } = await peal.results(auction.id);

// bids     every readable bid, ranked, whether or not it can win
// queue    only the ones inside the reserve and the maximum
// winner   queue[0], or null if nothing qualified

The rules, and why each one is there

The rounds API gives you submissions sealed with batched threshold encryption (BTE) that open together when a threshold of the committee produces its shares. An auction is that plus the rules that decide what a bid means, and those rules are the reason this lives in the API rather than being left to every caller to get subtly wrong.

  • Amounts are integers of minor units. 12.50 in a two decimal currency is 1250. Money in a float is a rounding error waiting for a big enough auction.
  • Every bid is the same size on the wire. The record is padded to 320 bytes before encryption, so a bid of five and a bid of five hundred thousand are indistinguishable until the auction opens. Without this the ciphertext length ranks the bids for anyone watching.
  • A reserve and a maximum, both optional. Nothing is escrowed, so a bid is cheap talk. The maximum is what stops a joke bid of ninety nine million taking your auction.
  • The result is a queue, not just a winner. For the same reason: if the top bidder does not pay, the seller works down the list rather than losing the sale.
  • Ties break on batch position, which comes from the ciphertext hashes rather than arrival order. So a tie cannot be won by bidding earlier, and the coordinator cannot reorder a batch to choose a winner.
  • A bid naming a different auction is discarded, with the reason. A ciphertext is not bound to a round, so the same sealed bytes can be replayed into another auction; the id inside the record is what makes that detectable.

A page bidders can open

Every auction with a title comes back with a bid_url: a hosted page where somebody reads the terms and places a bid. You do not have to build a bidding interface to test this, or ever, if the hosted one suits you.

The whole auction rides in the URL fragment, the part after the #. Browsers never send a fragment to a server, so opening that link tells nobody which auction it is, including us.

Next, the full integration: creating an auction covers the money rules, contact details, the closing time and a checklist before you ship.