RDE_BANKING DOCS
RED DRAGON ELITE // ox_core NATIVE

Banking that survives
a logout.

rde_banking is a full account system for ox_core — deposits, transfers, investments, loans, prestige tiers — with one thing most FiveM banking scripts get wrong: payouts that actually reach the recipient, whether they're online or not.

5
Account Tiers
3
Investment Types
4
Loan Tiers
0
External Dependencies
01 / Start Here

Overview

rde_banking is a complete account system built directly against ox_core — no ESX or QBCore compatibility bridge, no framework-agnostic abstraction layer standing between your code and the actual data. It shipped originally as an NPWD phone app; the NPWD/Module Federation frontend is gone, the money logic underneath it never changed.

Core Principle Every mutating action (deposit, withdraw, transfer, invest, loan) has exactly one implementation, called from both the proximity-based teller/ATM flow and the phone app. Money logic is never duplicated between the two entry points.

What it replaces

The old NPWD-based build required a React/Webpack toolchain just to change a button. The current version is plain HTML/CSS/JS running on rde_phone's SDK — no build step, and the phone app can be edited and reloaded like any other resource file.

02 / Start Here

Quick Start

server.cfg
-- rde_phone must start first — the phone app registers into it
ensure ox_core
ensure ox_lib
ensure oxmysql
ensure ox_inventory
ensure rde_phone
ensure rde_banking

The phone app registers itself automatically on start via the same RegisterPhoneApp export any third-party app uses — see the rde_phone App Registry docs for the mechanism itself.

03 / Start Here

Architecture

The phone app doesn't talk to rde_banking's server through rde_phone's SDK bridge — that bridge only reaches rde_phone's own server callbacks. rde_banking's phone frontend talks directly to its own resource's client NUI callback, which relays to its own server callbacks via lib.callback. rde_phone's SDK is used only for theme, icons, and shell integration (notify/close).

client.lua
RegisterNUICallback('phone:request', function(data, cb)
    local ok, result = pcall(function()
        return lib.callback.await('rde_banking:cb:phone' .. data.action, false, data.payload)
    end)
    cb(ok and result or { error = true })
end)
04 / Reference

Tiers & Fees

Tier is calculated from lifetime transaction volume, not current balance — spending and earning both count. Higher tiers get lower transfer fees and higher daily deposit/withdraw limits.

B

Bronze

Starting tier, baseline fees and limits.

S

Silver

Reduced transfer fee, higher daily caps.

G

Gold

Meaningful fee reduction, high daily caps.

P

Platinum

Near-minimum fees, near-max limits.

B

Black

Lowest fee tier, highest limits — reserved for high-volume accounts.

05 / Reference

Investments

Three risk tiers, each with a min/max investment amount, a return-rate range, and a fixed duration in hours. Investments mature automatically — no action needed to collect, the payout (or loss) posts and a phone notification fires the moment it's ready, even if the app isn't open.

RiskWhat happens
LowSmaller return range, shorter odds of loss.
MediumBalanced return/duration profile.
HighWidest return range — biggest upside, biggest downside.
Why this needed rde_phone's push-notification API An investment maturing while the player is off doing something else needs to notify them without the banking app being open. This is exactly what exports.rde_phone:PushNotification() exists for — see rde_phone's docs.
06 / Reference

Loans

Four loan amounts, each gated by a minimum credit score. Credit score starts at a baseline and improves when a loan is fully paid off. Interest accrues once, at approval — pay it down in any increment, not all at once.

07 / Reference

Exports

Two of these exist specifically so other resources can move money without requiring the target player to be online — built for the rde_bodyguards marketplace, usable by anything.

ExportSignatureNotes
AdjustBalanceByCharIdexports.rde_banking:AdjustBalanceByCharId(charId, amount, description, txType)Works offline. Writes directly to the account row — no live player object required. Refuses to create an account that doesn't exist.
GetBalanceByCharIdexports.rde_banking:GetBalanceByCharId(charId)Offline-safe read, returns 0 if no account exists.
AddMoney / RemoveMoneyexports.rde_banking:AddMoney(src, amount, description)Online-only — requires a live source.
GetPlayerBalanceexports.rde_banking:GetPlayerBalance(src)Online-only.
08 / More

Common Pitfalls

lib.callback.await() has no server-to-server variant

It's tempting to call it from inside another server callback to reuse a list-fetch (transactions/investments/loans). It silently times out — the awaiting mechanism only bridges client → server, never server → server.

Fix: extract the shared query logic into a plain Lua function (GetTransactionsForPlayer, etc.) that both callbacks call directly.

Online-only payouts silently fail for offline recipients

The original direct-trade system paid a seller via AddMoney(source, ...) — if the seller wasn't online, the money simply never arrived, with no error surfaced anywhere.

Fix: AdjustBalanceByCharId writes to the DB row directly, no live source required. Use it for any payout where the recipient might not be online.

09 / More

FAQ

Does this need ESX or QBCore?

No. It's written directly against ox_core — no compatibility bridge, no framework-agnostic abstraction layer. If your server is still on ESX, this is a reason to finish the migration, not a blocker.

Can another resource take money from a player without them being online?

Yes — that's exactly what AdjustBalanceByCharId is for. It requires the target to already have an account row (won't invent one for a charId that's never banked).

Do I need the ATM/teller world UI if I only want the phone app?

They share the same money logic but are independent entry points — you can disable one without breaking the other.

10 / More

Changelog

Latest

Offline-safe balance exports added, powering the rde_bodyguards public marketplace.

NPWD/Module Federation removed entirely. Phone app rebuilt on rde_phone's SDK.

Deposit/withdraw/transfer/investment/loan logic extracted into shared functions — no duplication between the world-UI and the phone app.