QBESXStandalone
Agency-Banking Configuration
A complete bank for FiveM that runs on QBCore, Qbox, ESX or fully standalone.
v1.3.1Paid6 Pages

01Configuration
Quick Installation · config.lua · Agency-Banking
--[[ ============================================================================
AGENCY BANKING: CONFIGURATION
----------------------------------------------------------------------------
Adjust the values in the "SETTINGS" section to suit your server.
Framework detection lives in shared/bridge.lua. It stays readable on
escrow protected servers, so a custom framework can be wired in there.
============================================================================ ]]
Config = {}
--[[ ============================================================================
SETTINGS
============================================================================ ]]
-- ----------------------------------------------------------------------------
-- General / UI
-- ----------------------------------------------------------------------------
Config.BankName = 'Agency Bank' -- Name shown across the UI and on cards
Config.BankLogo = 'logo.png' -- Image in this resource's root folder (next to config.lua)
-- Menu design. Both work with every feature of the bank.
-- 'v1.3' -> the current design: dark panel, gold accent, sliding sidebar (default)
-- 'v1' -> the classic design of the first releases: blue liquid glass
Config.Design = 'v1.3'
Config.UseAgencyNotify = true -- true = use Agency-Notify when it runs (falls back to the framework / GTA feed)
Config.Debug = false -- true = print the framework detection in every client console too
-- ----------------------------------------------------------------------------
-- Localization
-- ----------------------------------------------------------------------------
-- Available languages live in the locales/ folder:
-- 'en', 'de', 'fr', 'esm' (Spanish), 'it', 'nl', 'pl', 'pt', 'ro', 'ru', 'sv', 'tr', 'cs'
-- A text missing in your language is shown in English instead.
Config.Locale = 'en'
-- ----------------------------------------------------------------------------
-- Framework
-- ----------------------------------------------------------------------------
-- 'auto' -> detect QBCore, Qbox or ESX by itself. Standalone is only
-- chosen when none of qb-core, qbx_core and es_extended is
-- installed at all, so a slow booting core is never mistaken
-- for a server without one.
-- 'qbcore' -> force QBCore (qb-core) or Qbox (qbx_core)
-- 'esx' -> force ESX (es_extended)
-- 'standalone' -> no framework, see Config.Standalone below
Config.Framework = 'auto'
-- Framework groups that count as admin (QBCore / Qbox permissions, ESX groups).
-- ACE works everywhere: `add_ace group.admin agency.banking allow`
Config.AdminGroups = { 'admin', 'god', 'superadmin' }
-- ----------------------------------------------------------------------------
-- Standalone (only used when no framework runs)
-- ----------------------------------------------------------------------------
--[[ WHAT WORKS WITHOUT A FRAMEWORK
* Every screen of the bank: wallet, cards, transfers, fixed deposits,
trading, activity, ATM PIN, Companion app and the display size.
* Players are told apart by their Rockstar licence (license:...), so a
player keeps the same account across sessions and reconnects.
* Bank balance and cash are kept by the bank itself (see Accounts).
* Other resources can use the bank as their money system through the
server exports GetBankBalance / AddBankMoney / RemoveBankMoney /
GetCashBalance / AddCashMoney / RemoveCashMoney.
* Admins come from ACE (agency.banking or group.admin) or from the
Admins list below.
TABLES CREATED FOR STANDALONE (automatically on start, nothing to import)
* agency_bank_accounts bank balance and cash per licence
* agency_phone_settings the stock and crypto portfolio. The same table
Agency Phone and Agency Pad use, so it is only
created when it is missing and then shared.
WHAT YOU MAY WANT TO FILL IN
* Accounts = 'hooks' plus the functions below, if your server already
has its own money system that the bank should use.
WHAT DOES NOT WORK WITHOUT A FRAMEWORK
* Character names: the bank shows the FiveM player name.
* Phone numbers only exist with Agency Phone installed (its standalone
table). Without it, the Companion transfer by phone number is off.
* Live stock and crypto prices come from Agency Phone or Agency Pad.
Without them the market trades at fixed prices.
* Cash only exists inside the bank: a cash item in an inventory is not
touched by deposits and withdrawals.
]]
Config.Standalone = {
-- Where bank balance and cash are stored:
-- 'auto' -> Agency Phone standalone wallet when its table exists
-- (so phone and bank show the same balance),
-- otherwise the bank's own table
-- 'banking' -> own table agency_bank_accounts (bank + cash per licence)
-- 'agency-phone' -> bank balance shared with Agency Phone standalone
-- (agency_phone_standalone.bank), cash in agency_bank_accounts
-- 'hooks' -> your own money system through the functions below
Accounts = 'auto',
StartBank = 5000, -- balance of a new account
StartCash = 500, -- cash of a new account
-- Licences that count as admin without ACE, e.g. 'license:1a2b3c...'
Admins = {},
-- Only used with Accounts = 'hooks'. Every function receives the player's
-- server id and must answer straight away (no Wait). The three bank hooks
-- are required, the cash hooks are optional (without them there is no cash).
-- getBank = function(src) return 0 end,
-- addBank = function(src, amount) return true end,
-- removeBank = function(src, amount) return true end, -- false when the balance is too low
-- getCash = function(src) return 0 end,
-- addCash = function(src, amount) return true end,
-- removeCash = function(src, amount) return true end,
-- getOfflineBank = function(identifier) return 0 end, -- Companion app while the player is offline
}
-- ----------------------------------------------------------------------------
-- Commands
-- ----------------------------------------------------------------------------
Config.Commands = {
openBank = 'openbank', -- opens the bank anywhere, '' turns the command off
openBankAdminOnly = true, -- false = every player may open the bank from anywhere
}
-- ----------------------------------------------------------------------------
-- Database
-- ----------------------------------------------------------------------------
-- The resource uses oxmysql (declared in fxmanifest.lua). Every table and
-- column is created on start, nothing has to be imported by hand.
Config.DatabaseType = 'oxmysql'
-- ----------------------------------------------------------------------------
-- Agency Companion App (free iOS / Android remote)
-- ----------------------------------------------------------------------------
-- Links this bank to the free Agency Companion app so players can check their
-- balance, send transfers and manage fixed deposits from their phone. Each
-- player links their OWN device via a QR code (Companion tab or /abconnect).
-- Money actions are always validated on the server against the online player:
-- transfers and deposits need the player online, reading works offline too.
Config.Companion = {
Enable = true, -- master switch for the companion integration
EnableRemote = true, -- dial out to the Agency relay (no port forwarding needed)
RelayUrl = 'https://api.agencyg.de', -- Agency relay endpoint
TokenTTL = 300, -- seconds a pairing QR / code stays valid
}
-- ----------------------------------------------------------------------------
-- Fixed Deposits (Savings)
-- ----------------------------------------------------------------------------
-- The interest rate always comes from this list on the server, never from
-- the menu, so a term that is not listed here cannot be opened.
Config.EnableFixedDeposits = true
Config.FixedDepositOptions = {
{ days = 7, interestRate = 2.0 }, -- 7 days * 2.0% return
{ days = 14, interestRate = 3.5 }, -- 14 days * 3.5% return
{ days = 30, interestRate = 6.0 }, -- 30 days * 6.0% return
}
-- ----------------------------------------------------------------------------
-- Interaction (Banks & ATMs)
-- ----------------------------------------------------------------------------
-- UseTarget = true -> interact via a target resource (qb-target / ox_target)
-- UseTarget = false -> interact via 3D markers + [E]
-- The active target system is auto-detected; if TargetResource isn't running,
-- the script picks whichever is available, or falls back to markers + [E].
Config.UseTarget = false
Config.TargetResource = 'qb-target' -- 'qb-target' or 'ox_target'
-- ----------------------------------------------------------------------------
-- Locations
-- ----------------------------------------------------------------------------
-- Bank blip / interaction points.
Config.BankLocations = {
vector3(149.91, -1040.64, 29.37), -- Legion Square
vector3(314.19, -278.62, 54.17), -- Alta
vector3(-1212.98, -330.84, 37.78), -- Rockford Hills
vector3(-2962.58, 482.63, 15.70), -- Chumash
vector3(-112.20, 6469.29, 31.62), -- Paleto Bay
vector3(1175.06, 2706.64, 38.09), -- Sandy Shores
vector3(241.727, 220.706, 106.286), -- Pacific Standard
vector3(1143.514, -471.189, 66.828), -- Mirror Park
vector3(-350.938, -49.805, 49.042), -- Burton
}
-- ATM prop models detected client-side for interaction.
Config.ATMProps = {
`prop_atm_01`,
`prop_atm_02`,
`prop_atm_03`,
`prop_fleeca_atm`,
}
--[[ ============================================================================
INTERNAL: translation helper (no configuration needed below this line)
============================================================================ ]]
-- _U('key', ...) returns the localized, string.format-ed text. A key missing in
-- the chosen language falls back to English instead of showing the key.
function _U(str, ...)
local locale = Locales[Config.Locale] or Locales['en'] or {}
local text = locale[str]
if text == nil and Locales['en'] then text = Locales['en'][str] end
if text == nil then
return ('Translation [%s][%s] does not exist'):format(tostring(Config.Locale), tostring(str))
end
if select('#', ...) == 0 then return text end
local ok, formatted = pcall(string.format, text, ...)
return ok and formatted or text
end
02SQL File
Optional: the resource creates these tables on its own when it starts. Import this file only if you set up the database by hand:
-- =============================================================================
-- Agency Banking: database schema
-- -----------------------------------------------------------------------------
-- You do NOT have to import this file. The resource creates every table and
-- every missing column by itself on start (MariaDB and MySQL 8).
-- It is here for servers that prefer to set up the database by hand.
-- =============================================================================
CREATE TABLE IF NOT EXISTS `agency_transactions` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`identifier` VARCHAR(60) NOT NULL,
`type` VARCHAR(50) NOT NULL, -- deposit, withdraw, transfer, fixed_deposit, card_added, ...
`amount` DECIMAL(15,2) NOT NULL,
`target_identifier` VARCHAR(60) DEFAULT NULL,
`reason` VARCHAR(255) DEFAULT NULL,
`date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `identifier` (`identifier`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `agency_cards` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`identifier` VARCHAR(60) NOT NULL,
`card_number` VARCHAR(16) NOT NULL,
`card_pin` VARCHAR(4) NOT NULL,
`card_type` VARCHAR(50) DEFAULT 'Visa',
`card_color` VARCHAR(50) DEFAULT 'ultra-blue',
`is_active` TINYINT(1) DEFAULT 1,
`card_name` VARCHAR(50) DEFAULT 'Main Account',
`card_holder` VARCHAR(50) DEFAULT 'Card Holder',
PRIMARY KEY (`id`),
KEY `identifier` (`identifier`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `agency_fixed_deposits` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`identifier` VARCHAR(60) NOT NULL,
`amount` DECIMAL(15,2) NOT NULL,
`interest_rate` FLOAT NOT NULL,
`duration_days` INT(11) NOT NULL,
`start_date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`end_date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`is_claimed` TINYINT(1) DEFAULT 0,
`source` VARCHAR(16) NOT NULL DEFAULT 'bank', -- 'bank' = paid out by the bank, 'phone' = a copy of an Agency Phone wallet deposit
`external_ref` VARCHAR(64) DEFAULT NULL, -- the phone's own id for a 'phone' deposit
PRIMARY KEY (`id`),
KEY `identifier` (`identifier`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `agency_atm_pins` (
`identifier` VARCHAR(60) NOT NULL,
`pin` VARCHAR(4) NOT NULL,
PRIMARY KEY (`identifier`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Standalone only (no QBCore / Qbox / ESX): balance and cash per Rockstar licence.
CREATE TABLE IF NOT EXISTS `agency_bank_accounts` (
`identifier` VARCHAR(60) NOT NULL,
`bank` DECIMAL(15,2) NOT NULL DEFAULT 0,
`cash` DECIMAL(15,2) NOT NULL DEFAULT 0,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`identifier`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Standalone and ESX only: the stock and crypto portfolio. The same table Agency
-- Phone and Agency Pad use; on QBCore / Qbox the portfolio lives in the
-- character's metadata instead.
CREATE TABLE IF NOT EXISTS `agency_phone_settings` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`identifier` VARCHAR(60) NOT NULL,
`setting_key` VARCHAR(60) NOT NULL,
`setting_value` TEXT DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `identifier_key` (`identifier`, `setting_key`),
KEY `identifier` (`identifier`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Agency Companion app (created by server/companion.lua as well).
CREATE TABLE IF NOT EXISTS `agency_banking_cmp_meta` (
`k` VARCHAR(64) NOT NULL PRIMARY KEY,
`v` TEXT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `agency_banking_cmp_devices` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`identifier` VARCHAR(60) NOT NULL,
`player_name` VARCHAR(80) DEFAULT NULL,
`token_hash` CHAR(64) NOT NULL,
`device_name` VARCHAR(64) DEFAULT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_seen` TIMESTAMP NULL DEFAULT NULL,
`revoked` TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `token_hash` (`token_hash`),
KEY `identifier` (`identifier`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;