4.2 KiB
OpenSpec Change: enterprise-gaming-api-plugin-bank
- Change ID: enterprise-gaming-api-plugin-bank
- Package:
@suaveplan/api-plugin-bank - Category: gaming/server
- Target path:
gaming/server/api-plugin-bank - Status: PROPOSED
- Date: 2026-04-24
- Reference spec:
/mnt/s/web/suaveplan/enterprise/api-plugin-bank.md
Summary
Deliver @suaveplan/api-plugin-bank on the genesis branch from scratch at enterprise quality. The package is a game-oriented virtual-currency bank built on top of @suaveplan/economy. It adds per-account-type interest accrual (savingsInterestRate vs. currentInterestRate), configurable currency code (default "GOLD"), transfer support, and deposit/withdrawal tracking with a full transaction audit trail. Four Hono route groups expose HTTP endpoints: /accounts, /interest, /transactions, /config. A GameBankService and InterestService are registered as plugin services. Genesis adds Zod request/response schemas, structured errors, OTel route instrumentation, and 100% coverage.
Current-state audit (genesis)
Package does not exist on genesis yet — fresh build.
Available workspace deps on genesis
| Package | Role |
|---|---|
@suaveplan/error (workspace:^) |
BankError; BANK.* codes |
@suaveplan/types (workspace:^) |
Clock |
@suaveplan/economy (workspace:^) |
Wallet for balance management |
@suaveplan/events (workspace:^) |
bank:deposit, bank:withdrawal, bank:transfer, bank:interest events |
zod (catalog:forms) |
Request/response schemas |
@opentelemetry/api (catalog:observability) |
Route span instrumentation |
Public API surface
type AccountType = 'current' | 'savings'
interface BankAccount {
id: string
playerId: string
type: AccountType
balance: number
currency: string
createdAt: number
lastInterestAt: number
}
interface BankTransaction {
id: string
accountId: string
type: 'deposit' | 'withdrawal' | 'transfer' | 'interest'
amount: number
currency: string
description?: string
timestamp: number
}
function createGameBankService(options: BankServiceOptions): GameBankService
interface BankServiceOptions {
currency?: string
savingsInterestRate?: number // per day, e.g. 0.005
currentInterestRate?: number
clock?: Clock
}
interface GameBankService {
openAccount(playerId: string, type: AccountType): BankAccount
getAccount(accountId: string): BankAccount | undefined
listAccounts(playerId: string): BankAccount[]
deposit(accountId: string, amount: number, description?: string): BankTransaction
withdraw(accountId: string, amount: number, description?: string): BankTransaction
transfer(fromId: string, toId: string, amount: number): [BankTransaction, BankTransaction]
listTransactions(accountId: string, limit?: number): BankTransaction[]
}
function createInterestService(bank: GameBankService, clock?: Clock): InterestService
interface InterestService {
accrueAll(): void
tick(dt: number): void // daily accrual on interval
}
// Hono plugin
function bankPlugin(options: BankPluginOptions): HonoPlugin
Error codes
type BankErrorCode =
| 'BANK_ACCOUNT_NOT_FOUND'
| 'BANK_INSUFFICIENT_FUNDS'
| 'BANK_ACCOUNT_LIMIT'
| 'BANK_INVALID_AMOUNT'
| 'BANK_TRANSFER_FAILED'
File layout
gaming/server/api-plugin-bank/
package.json
tsconfig.json
vitest.config.ts
src/
index.ts
error-codes.ts
constants/index.ts
types/common.ts
types/common.md
services/
game-bank-service/
game-bank-service.ts
game-bank-service.md
game-bank-service.types.ts
game-bank-service.test.ts
index.ts
interest-service/
interest-service.ts
interest-service.md
interest-service.types.ts
interest-service.test.ts
index.ts
routes/
accounts.ts
accounts.md
interest.ts
transactions.ts
config.ts
plugin.ts
plugin.md
tests/
integration.test.ts
Impact
Downstream: @suaveplan/react-bank and @suaveplan/api-plugin-virtual-currency build on this. Prerequisites: @suaveplan/error, @suaveplan/types, @suaveplan/economy, @suaveplan/events.