Skip to main content

Bank System

The banking system provides persistent item storage separate from the player’s inventory. Following OSRS/RS3 design, each town has its own bank and players can organize items into tabs.
Banking code lives in packages/shared/src/systems/shared/economy/BankingSystem.ts.

Core Features

  • Per-town banks - Each starter town has its own bank
  • Independent storage - Banks don’t share items across towns
  • 480 slot capacity - Per bank (configurable via BANKING_CONSTANTS.MAX_BANK_SLOTS)
  • Tab organization - Organize items into custom tabs (9 tabs: 1 main + 8 custom)
  • Placeholders - RS3-style placeholder mode for remembered slots
  • Two-phase slot updates - Prevents database constraint violations during bulk operations
  • Distance check - Must be within 3 meters of bank booth
  • Combat interruption - Bank automatically closes when player is attacked (OSRS-accurate)
Combat Closes Bank: Being attacked automatically closes the bank interface (OSRS-accurate). Even splash attacks (0 damage) will interrupt banking. This is server-authoritative - the server sends a bankClose packet with reason: "combat".

Bank Constants


Bank Data Structure


Bank Operations

Opening a Bank

Depositing Items

Withdrawing Items

Deposit All


Placeholder System

Banks support RS3-style placeholders that remember item positions:

Release All Placeholders

The “Release All Placeholders” operation uses a two-phase slot update to prevent unique constraint violations:
Why Two-Phase? PostgreSQL doesn’t guarantee UPDATE execution order. Direct renumbering could cause collisions:
  • Row A updates from slot 10→6
  • Row B updates from slot 6→3
  • If Row A executes first, both rows temporarily occupy slot 6 → unique constraint violation
The two-phase approach eliminates this by ensuring source and target slot ranges never overlap:
  • Phase 1: All slots move to 1000+ range
  • Phase 2: All slots renumber to 0-N range
  • No collision possible since 1000+ and 0-N don’t overlap
The same two-phase pattern is used in compactBankSlots() for consistent slot renumbering.

Bank Events


Placeholder System

Placeholders remember item positions when items are withdrawn, maintaining bank organization.

Placeholder Operations

Two-Phase Slot Update

When releasing all placeholders, the system uses a two-phase approach to prevent database unique constraint violations:
Why Two-Phase? PostgreSQL doesn’t guarantee UPDATE execution order. Direct renumbering could cause temporary slot collisions (e.g., row A updates slot 10→6 before row B updates slot 6→3). The two-phase approach eliminates this by ensuring source and target ranges never overlap.

Database Persistence

Banks are persisted via BankRepository:

Client UI

The BankPanel.tsx component displays:
  • Grid view of all bank items
  • Tab navigation (9 tabs)
  • Search/filter functionality
  • Deposit all button
  • Withdraw-X functionality
  • Placeholder toggle


Placeholder System

Two-Phase Slot Updates

The bank system uses a two-phase update to prevent unique constraint violations when releasing all placeholders:
This prevents the error:

Placeholder Toggle

Players can toggle placeholder mode: