Configuration — ns-banking 1.0.0
Routine changes never need core code: config.lua (rules), data/branches.lua (locations), data/markets.lua
(simulated assets and events), locales/*.lua (texts). All four stay readable under Cfx escrow.
Every value is validated on start; invalid values are reported and critical ones disable the feature they belong to.
Units: money = whole currency units · percent = percent (0.25 = 0.25 %) · time = seconds unless named days.
General
| Key | Default | Meaning |
|---|---|---|
Framework | 'auto' | 'auto' | 'qbox' | 'qbcore' | 'esx' | 'standalone' |
Locale / FallbackLocale | 'en' | 'en' | 'tr' (add locales/<code>.lua for more) |
Debug, DebugCategories | false | console debug lines (rpc, db, market, audit, bridge) |
UseOxLib, UseOxTarget | true | use them when started |
Currency | $, before, en-US, en-GB, , | display only: symbol, position ('before' | 'after'), Intl number / date locale, Lua thousands separator. Turkish example: { symbol = '₺', position = 'after', numberLocale = 'tr-TR', dateLocale = 'tr-TR', thousands = '.' } |
Features.* | all true | Atm, Branches, Transfers, Savings, TermDeposits, Crypto, Stocks, SharedAccounts, BusinessAccounts |
Database.autoMigrate | true | create / upgrade tables on start |
IBAN and privacy
| Key | Default | Meaning |
|---|---|---|
Iban.prefix | 'NS' | 2–4 letters |
Iban.length | 10 | random characters after prefix + 2 check digits (6–16) |
Iban.charset | digits | A–Z / 0–9 |
Iban.groupSize | 4 | display grouping |
Privacy.recipientName | 'masked' | what a sender sees: 'full' | 'initials' | 'masked' | 'none' |
Privacy.businessName | true | business / shared accounts show their label |
Changing the IBAN format later only affects new accounts; existing IBANs stay valid only if prefix and length are unchanged.
Limits and fees
Limits.maxAmount (10 000 000) caps every single amount. deposit, withdraw, transfer each have
{ min, max, daily }; daily = rolling 24 h from the account's own history. transfer.cooldownSeconds (5).
Fees.deposit / withdraw / atmWithdraw / transfer = { fixed, percent, min, max }
→ fee = fixed + ceil(amount × percent / 100), clamped to [min, max] (max = 0 = no cap). Withdrawal and transfer
fees are charged on top of the amount; deposit fees are taken from the deposited cash.
Fees.collector = 'jobname' credits every fee to that business account (must exist in BusinessAccounts.jobs),
nil = fees leave the economy.
Transfers.allowSelf (false) · noteMaxLength (64) · blockedIbans (list).
ATMs
| Key | Default | Meaning |
|---|---|---|
Atm.models | 4 vanilla ATM models | every prop of these models, existing or added by MLOs |
interactDistance / sessionDistance | 1.6 / 4.0 m | target distance / the session closes beyond this |
services | withdraw, transfer, history | deposit = true enables cash deposits at ATMs |
withdrawStep | 10 | ATM withdrawals must be multiples (0 = any) |
quickAmounts | 50…1000 | buttons |
limits.withdrawMax / withdrawDaily | 5 000 / 20 000 | ATM-only caps (in addition to Limits.withdraw) |
ATMs always serve the personal account only.
Card PIN (Atm.pin): enabled (true), length (4, 4–6), maxAttempts (3), lockMinutes (30), blockTrivial
(refuses 0000 / 1234 / 4321 …). The PIN is chosen on the first ATM use and reset at any branch (Settings → Card PIN).
ATM intro (Atm.visual): enabled, image (img/atm-machine.png), card (img/bank-card.png), hotspots in
percent of the image — screen, slot, keypad = { x, y, w, h, cols, rows, keys }, optional led (blinks over the image's
LED; without it the LED is drawn above the slot) — keyLabels (NUI writes the key
labels for images with blank keys), debug (draws the hotspots). See ASSETS.md for sizes, AI prompts and
calibration.
Branches (Config.Branch, data/branches.lua)
Config.Branch: sessionTolerance (3 m), icon, tellerModel, guardModel, pedSpawnDistance (60 m).
data/branches.lua entry: id, label, enabled, coords (vector3), radius, services (nil = all; or
{ crypto = false, ... } with keys withdraw, deposit, transfer, history, savings, deposits, crypto, stocks, shared, business), limits (withdrawMax, withdrawDaily, depositMax, transferMax), jobs (restrict to jobs), blip
({ sprite, color, scale } or false), teller ({ coords = vector4, model? }), guards (list). NPCs are local and
exist only near the branch. Branches can be toggled live: /bank branch <id> on|off.
Savings
| Key | Default | Meaning |
|---|---|---|
interval | 'daily' | 'hourly' | 'daily' | 'weekly' or seconds ≥ 600 |
ratePercent | 0.10 | per interval |
compound | true | credited to savings (compound) or paid to the personal account (simple) |
minBalance / maxEligibleBalance | 1 000 / 1 000 000 | eligibility window |
maxPayoutPerInterval | 1 000 | cap per period (0 = none) |
accrueWhileOffline | false | pay or skip intervals that ended while the resource was stopped |
maxCatchUpIntervals | 7 | at most this many missed intervals are settled |
withdrawCooldownSeconds | 0 | wait after a savings deposit before withdrawing |
Formula: for every ended interval, interest = min(floor(min(lowest balance during the interval, maxEligibleBalance) × rate / 100), maxPayoutPerInterval), 0 when the lowest balance is below minBalance.
Money deposited during an interval earns from the next one. Changing interval restarts all cursors at the current
period.
Fixed-term deposits
minAmount 1 000 · maxAmount 500 000 · maxActive 3 · allowEarlyWithdrawal true · earlyPenaltyPercent 2.0 ·
plans = { { id, days, ratePercent } } (ratePercent is for the whole term, fixed when the deposit is opened;
days may be fractional for testing). Payout at maturity = principal + floor(principal × rate / 100); early =
principal − ceil(principal × penalty / 100), interest forfeited.
Markets (Config.Markets, data/markets.lua)
Config.Markets: tickSeconds 300 · historyRetentionDays 14 · chartPoints 96 · maxSlippagePercent 1.5 ·
announceEvents true.
data/markets.lua → Markets.crypto / Markets.stocks: label, fee ({ fixed, percent, min, max }),
alwaysOpen, hours = { open, close, days } (server clock, days 1 = Sunday … 7 = Saturday), assets:
| Field | Meaning |
|---|---|
symbol, name, sector | 2–6 letters, display name, tech | automotive | energy | construction | retail (labels in locales) |
basePrice, minPrice, maxPrice | anchor/start, hard bounds (≤ 10 000 000) |
volatility, meanReversion, maxStepPercent | % std-dev per tick, 0–1 pull to the anchor, largest move per tick |
decimals, minOrder, maxOrder, maxHolding | quantity precision (crypto ≤ 6, stocks 0), order and position caps in asset units |
fee | optional override |
dividend | stocks: { percent, intervalDays, maxPerHolder } — paid for each ended interval on positions unchanged during it |
enabled | false hides it |
MarketEvents = { { id, market, scope = 'asset' \| 'market', chancePerTick, driftPercent, durationTicks } }; label
key event_<id> in the locales. Trigger manually: /bank market event <id> [SYM]. Pause: /bank market pause ….
Shared and business accounts
SharedAccounts: maxOwned 2 · maxMembers 6 · openingFee 500 · labelMaxLength 32.
Members are added by their personal IBAN with deposit / withdraw / transfer / manage; only the owner can grant
manage.
BusinessAccounts.jobs = { jobname = { label, grades = { view, deposit, withdraw, transfer, manage } } } — minimum
job grade per permission; the account is created on first use.
Other
| Key | Meaning |
|---|---|
Notifications | provider (auto | ox_lib | qbox | qbcore | esx | native | custom), duration, position, keepPerCharacter (60), custom = fn(message, type, duration) (client) |
Target | provider (auto | ox_target | qb-target | none), distance, promptControl (38 = E) |
Security | router flood bucket / rate limits, mutationRateLimit (700 ms between money operations), dropAfterFlags (0 = never kick) |
Admin | ace, useFrameworkAdmin, command ('bank'), granular permissions, maxAdjustment |
Audit.retentionDays | 0 = keep forever |
Exports.trustedResources | resources allowed to call money exports |
Standalone | addMoney / removeMoney / getMoney / isAdmin hooks (server) when no framework is used |
Runtime toggles that do not need a restart (persisted in ns_banking_meta): branch on/off, maintenance mode,
market / asset pause. Everything else in config.lua is read on start: restart the resource after editing.