Files
2026-05-27 23:29:53 +01:00

4.5 KiB

OpenSpec Change: enterprise-gaming-economy

  • Change ID: enterprise-gaming-economy
  • Package: @suaveplan/economy
  • Category: gaming/narrative
  • Target path: gaming/narrative/economy
  • Status: PROPOSED
  • Date: 2026-04-24
  • Reference spec: /mnt/s/web/suaveplan/enterprise/economy.md

Summary

Deliver @suaveplan/economy on the genesis branch from scratch at enterprise quality. The package provides an in-game economy with player wallets, peer-to-peer trading, a marketplace (fixed-price listings), and an auction system with bidding and expiry. Wallet tracks multi-currency balances with transactional add/subtract; Marketplace holds Listing objects with configurable stock and price; AuctionHouse manages Auction objects with bidding history, reserve price, and expiry timers. Genesis adds Zod schemas, structured errors, OTel transaction counters, injectable clock, and 100% coverage with concurrency invariant tests.


Current-state audit (genesis)

Package does not exist on genesis yet — fresh build.


Available workspace deps on genesis

Package Role
@suaveplan/error (workspace:^) EconomyError; ECONOMY.* codes
@suaveplan/types (workspace:^) Clock, IdGenerator
@suaveplan/events (workspace:^) economy:purchase, economy:bid, economy:auction_end events
zod (catalog:forms) Listing, Auction, WalletConfig schemas
@opentelemetry/api (catalog:observability) Transaction counter, active listings gauge

Public API surface

function createWallet(playerId: string, options?: WalletOptions): Wallet

interface WalletOptions {
  currencies?: string[]      // registered currency codes, default ['GOLD']
  initialBalances?: Record<string, number>
}

interface Wallet {
  getBalance(currency?: string): number
  add(amount: number, currency?: string, reason?: string): void
  subtract(amount: number, currency?: string, reason?: string): void
  canAfford(amount: number, currency?: string): boolean
  getHistory(): Transaction[]
}

interface Transaction {
  id: string
  type: 'credit' | 'debit'
  amount: number
  currency: string
  reason?: string
  timestamp: number
}

// Marketplace
function createMarketplace(options?: MarketplaceOptions): Marketplace

interface Marketplace {
  createListing(seller: string, itemId: string, price: number, stock: number, currency?: string): Listing
  getListing(listingId: string): Listing | undefined
  listAll(filter?: ListingFilter): Listing[]
  purchase(listingId: string, buyerWallet: Wallet, quantity?: number): PurchaseResult
  removeListing(listingId: string): void
}

interface Listing {
  id: string
  seller: string
  itemId: string
  price: number
  currency: string
  stock: number
  createdAt: number
}

interface PurchaseResult {
  itemId: string
  quantity: number
  totalCost: number
}

// Auction house
function createAuctionHouse(options?: AuctionHouseOptions): AuctionHouse

interface AuctionHouse {
  createAuction(options: AuctionOptions): Auction
  bid(auctionId: string, bidderId: string, bidderWallet: Wallet, amount: number): BidResult
  tick(dt: number): ExpiredAuction[]
  getAuction(id: string): Auction | undefined
  listActive(): Auction[]
}

interface Auction {
  id: string
  seller: string
  itemId: string
  startingPrice: number
  reservePrice?: number
  currentBid: number
  currentBidder: string | null
  endsAt: number
}

Error codes

type EconomyErrorCode =
  | 'ECONOMY_INSUFFICIENT_FUNDS'
  | 'ECONOMY_LISTING_NOT_FOUND'
  | 'ECONOMY_OUT_OF_STOCK'
  | 'ECONOMY_BID_TOO_LOW'
  | 'ECONOMY_AUCTION_ENDED'
  | 'ECONOMY_SELF_BID'

File layout

gaming/narrative/economy/
  package.json
  tsconfig.json
  vitest.config.ts
  src/
    index.ts
    error-codes.ts
    constants/index.ts
    types/common.ts
    types/common.md
    core/
      wallet/
        wallet.ts
        wallet.md
        wallet.types.ts
        wallet.test.ts
        index.ts
      marketplace/
        marketplace.ts
        marketplace.md
        marketplace.types.ts
        marketplace.test.ts
        index.ts
      auction-house/
        auction-house.ts
        auction-house.md
        auction-house.types.ts
        auction-house.test.ts
        index.ts
  tests/
    integration.test.ts

Impact

Downstream: @suaveplan/react-bank displays wallet state; @suaveplan/api-plugin-virtual-currency provides HTTP surface. Prerequisites: @suaveplan/error, @suaveplan/types, @suaveplan/events.