# API: hyper-p2p-auction-gossip **Protocol:** `auction-gossip/v1` **Export:** `{ HyperP2PAuctionGossip, PROTOCOL }` ## Overview `HyperP2PAuctionGossip` maintains a peer-merged map of auctions. Each auction tracks an ordered bid list (highest first), lifecycle (`open` → `closed`), and optional metadata. Local mutations gossip over Hyperswarm via `../../_shared/p2p-bare.js` when `topic` is set. Extends `bare-events` `EventEmitter`. ## Constructor ```js const { HyperP2PAuctionGossip } = require('hyper-p2p-auction-gossip') const auction = new HyperP2PAuctionGossip(opts) ``` | Option | Type | Default | Description | |--------|------|---------|-------------| | `topic` | `string` \| `Buffer` | `null` | Hyperswarm topic; omit for local-only | | `keyPair` | `KeyPair` | `hypercore-crypto.keyPair()` | Peer identity; `peerHex` derived from public key | ### Instance fields | Field | Type | Description | |-------|------|-------------| | `peerHex` | `string` | Hex public key of this peer | | `_auctions` | `Map` | `auctionId → auction` record | ## Lifecycle ### `async ready() → HyperP2PAuctionGossip` Joins Hyperswarm when `topic` is set and swarm not already active. No-op if `topic` is null. ### `async close() → void` Destroys swarm, clears auction map. ### `getStats() → object` Returns `{ opened, bids, closed, gossipIn, gossipOut, auctions, open, protocol }`. ## Methods ### `openAuction(auctionId, meta = {}) → auction` Creates an open auction and gossips `auction-open`. - **Parameters:** `auctionId` (non-empty string), `meta` (object, stored on auction) - **Returns:** auction object - **Throws:** - `Error: auction already open` - `assertNonEmpty` on `auctionId` **Auction shape:** `{ id, meta, status: 'open', bids: [], openedAt, openedBy: peerHex }` ### `placeBid(auctionId, amount, meta = {}) → bid` Appends bid, re-sorts descending by `amount`, gossips `auction-bid`. - **Parameters:** `amount` must be positive number - **Returns:** `{ amount, bidder: peerHex, meta, at }` - **Throws:** - `Error: auction not open` - `Error: amount must be a positive number` ### `closeAuction(auctionId) → auction | null` Sets `status: 'closed'`, `winner` to highest bid (or `null`), gossips `auction-close`. - **Returns:** closed auction or `null` if unknown id ### `getAuction(auctionId) → auction | null` ### `listOpen() → auction[]` All auctions with `status === 'open'`. ### `listAuctionIds() → string[]` ### `highestBid(auctionId) → bid | null` Top bid after sort, or `null` if none. ### `withdrawBid(auctionId, bidder = null) → number` Removes all bids from `bidder` (defaults to `peerHex`). Returns count removed; gossips `auction-withdraw`. ### `cancelAuction(auctionId) → boolean` Deletes an open auction locally and gossips `auction-cancel`. ## Events | Event | When | Payload | |-------|------|---------| | `open` | Local `openAuction` | auction | | `bid` | Local `placeBid` | `{ auctionId, bid }` | | `close` | Local `closeAuction` | auction | | `remote-open` | Gossip `auction-open` | auction | | `remote-bid` | Gossip `auction-bid` | full gossip payload | | `remote-close` | Gossip `auction-close` | auction | ## P2P wire (gossip JSON) | type | fields | receiver behavior | |------|--------|-------------------| | `auction-open` | `auction` | `Map.set`; emit `remote-open` | | `auction-bid` | `auctionId`, `bid` | append + sort if auction open; emit `remote-bid` | | `auction-close` | `auctionId`, `winner`, `closedAt` | set closed; emit `remote-close` | | `auction-withdraw` | `auctionId`, `bidder` | filter bids for bidder | | `auction-cancel` | `auctionId` | delete auction | Gossip is skipped until `ready()` has initialized `_peerMsgs`. ## Errors See [`../../_shared/ERROR_CODES.md`](../../_shared/ERROR_CODES.md). Stable strings: `auction already open`, `auction not open`, `amount must be a positive number`. ## Testing ```bash npm install && npm test ``` Example: [`../examples/basic.js`](../examples/basic.js). Integration: [`../../../real_tests/integration/`](../../../real_tests/integration/) — auction-gossip two-node when present.