How to Make a Discord Economy Bot (TypeScript, 2026)
An economy bot gives your community server a points system: members collect virtual coins with /daily or /work, spend them on roles or items in a shop, and compare scores on a leaderboard. This guide covers the commands you need, the data model, the code for a /daily command with a cooldown, and the rules you should set before you start.
Ground rules first: no money value, no gambling
Decide this before you write a line of code:
- The currency has no real-money value. Don't sell coins, items or ranks for real money, and don't pay out or exchange them.
- No gambling. No slots, coin flips with a stake or loot boxes. If you add mini-games, make them free and without a stake.
- Don't sell powerful roles. Roles with moderation or admin permissions should never be in the shop.
That keeps the bot a community feature. Real-money value or stakes would raise legal questions you don't want on a hobby server.
The commands a typical economy bot has
| Command | What it does |
|---|---|
/balance | Shows the member's wallet |
/daily, /work | Fixed amount, with a cooldown |
/shop list, /shop buy | Lists and buys roles or items |
/inventory, /use | Shows items, uses one (e.g. a role for N minutes) |
/leaderboard | Top 10 of the server |
/eco (admins) | give, take, set, reset, history |
Data model
Three tables cover most of it: wallets (guild ID, user ID, balance, last daily), shop items (name, price, role ID, stock) and a booking log (who, what, when, which admin). Store Discord IDs and numbers, never message content.
Step 1: Create the bot and invite it
Create an application in the Discord Developer Portal, reset and copy the bot token, and invite the bot with the scopes bot and applications.commands. To sell roles, the bot needs Manage Roles, and its own role must sit above the roles it hands out. The full walkthrough is in Create a Discord bot.
Step 2: A /daily command with a cooldown (discord.js 14 + node:sqlite)
import { DatabaseSync } from "node:sqlite";
import { MessageFlags, SlashCommandBuilder, type ChatInputCommandInteraction } from "discord.js";
const db = new DatabaseSync("economy.db");
db.exec(`CREATE TABLE IF NOT EXISTS wallets (
guild_id TEXT, user_id TEXT, balance INTEGER DEFAULT 0, last_daily INTEGER DEFAULT 0,
PRIMARY KEY (guild_id, user_id))`);
const DAILY_AMOUNT = 100;
const COOLDOWN_MS = 24 * 60 * 60 * 1000;
export const data = new SlashCommandBuilder()
.setName("daily")
.setDescription("Collect your daily coins");
export async function execute(interaction: ChatInputCommandInteraction) {
const g = interaction.guildId!, u = interaction.user.id, now = Date.now();
const row = db.prepare("SELECT last_daily FROM wallets WHERE guild_id = ? AND user_id = ?")
.get(g, u) as { last_daily: number } | undefined;
if (row && now - row.last_daily < COOLDOWN_MS) {
const next = Math.floor((row.last_daily + COOLDOWN_MS) / 1000);
return interaction.reply({ content: `Come back <t:${next}:R>.`, flags: MessageFlags.Ephemeral });
}
db.prepare(`INSERT INTO wallets (guild_id, user_id, balance, last_daily) VALUES (?, ?, ?, ?)
ON CONFLICT (guild_id, user_id) DO UPDATE SET balance = balance + ?, last_daily = ?`)
.run(g, u, DAILY_AMOUNT, now, DAILY_AMOUNT, now);
return interaction.reply(`+${DAILY_AMOUNT} coins.`);
}<t:…:R> is Discord's timestamp format and shows "in 5 hours" in each member's own time zone. node:sqlite is built into Node.js; check the Node.js docs for the version you run.
Step 3: The shop and role purchases
When a member buys a role, do it in this order: check the balance, try to add the role, and only then take the coins. If member.roles.add() fails (the bot's role is too low, or the role was deleted), refund or don't charge. Log every booking with the acting user or admin ID so you can sort out disputes.
Step 4: Privacy on your server
You run the bot, so you're responsible for the data. Keep it small: IDs, balances, purchases, a booking log with a retention period. Let members export or delete their data and opt out. Delete data of inactive members after a set time.
Discord Economy & Shop Bot Starter
The Economy & Shop Bot Starter for Discord is a template with automated tests for a self-hosted economy and shop bot (TypeScript, discord.js 14, SQLite). Per the product page it includes /balance, /daily and /work with cooldowns, /shop list and /shop buy for roles or items (optional stock and purchase limit, automatic refund if a role grant fails), /inventory, /use, /leaderboard, /eco admin commands, an audit log, /privacy export/delete/opt-out, DE/EN, Dockerfile and docker-compose. Roles with moderation/admin permissions can't be sold. The virtual currency has no monetary value, and the code contains no chance features. Requirements: Node.js 22 (or Docker), your own Discord application and hosting. Price: €19 incl. VAT. Licence: personal, non-commercial use on private and community servers only (licence). Not affiliated with Discord Inc.
Common problems
- "Missing Permissions" when buying a role: the bot's role is below the role it should give. Move it higher.
- Commands don't show up: the bot was invited without
applications.commands, or global commands haven't propagated yet. Register on a test server first. - Balances reset after a restart: the database file lives inside a container without a volume. Mount a volume for it.
FAQ
Can members buy coins with real money?
Not with this setup, and we advise against it. The currency should have no money value: no sales for real money, no payout, no exchange.
Can I add a casino or slots game?
Don't. Games with a stake are gambling. The Economy & Shop Bot Starter contains no chance features; you may add only free mini-games without a stake.
Is the Economy & Shop Bot Starter a subscription?
No. €19 incl. VAT, paid once, delivered as a ZIP. You host it yourself.
Can I run it on a server with paid memberships?
No. The licence covers private and community servers only, not shops, businesses or servers with paid memberships/roles. Donations are fine as long as they unlock no perks.
Python or JavaScript?
Both work for economy bots. This guide and the starter use TypeScript with discord.js 14.
Related guides
_Not affiliated with or endorsed by Discord Inc. "Discord" is a trademark of Discord Inc._