Install and enable

Activating the Forex Investment addon — the licence flow, the seven tables it creates, the 36 permission keys, the four KYC gates, the hourly settlement cron and a smoke test that proves the whole chain works.

14 min readUpdated 26 August 2026install, permissions, kyc, cron, extension

Activation is short. The work is what comes after it: a freshly enabled install has no plans, no durations and no accounts, and a customer who reaches /forex sees an empty product. Work through this page in order and finish with the smoke test — it is the only thing that proves settlement actually runs on your box.

Before you start

  • Bicrypto core installed and running — see Installing Bicrypto
  • The purchase code for Forex Broker & Investments — product ID 36668679 — from your MashDiv dashboard
  • Shell access to the app server, for pnpm updator
  • The cron process alive — check /admin/system/cron shows jobs running
  • At least one currency your customers already hold in a FIAT or SPOT wallet

There is no Ecosystem prerequisite and no ScyllaDB prerequisite. This addon uses core's users, wallets, transactions, notifications, KYC and permissions and nothing else.

Activation

  1. The Forex Broker & Investments card — click it to open the product page. The Forex & Multi-Asset Trading card beside it is the separate terminal product
  2. Its switch stays disabled, reading Activate license first, until the licence is activated
  1. Open the Extension ManagerAdmin → System → Extension Manager (/admin/system/extension), heading Add-ons & Integrations. On the Extensions tab, or by searching for Forex, find Forex Broker & Investments and click the card — not the Forex & Multi-Asset Trading card next to it, which is the separate terminal product. Until the licence is activated the switch on the card is disabled and reads Activate license first.

  2. Activate the licence — on the product page press Activate License. Paste the purchase code from your MashDiv dashboard, optionally an email address for update notifications, and press Activate License. The screen confirms License Activated! and returns you to the product page a couple of seconds later. If the server has no outbound access, the License File tab on the same screen takes the licence certificate downloaded from your MashDiv dashboard instead, placed as license.txt in the lic folder at the project root.

    1. Paste the purchase code here
    2. Activate License — then wait for the redirect back to the product page
    3. License File — the offline route, for a server with no outbound HTTPS
    4. The product's name and Product ID — 36668679 for this one
  3. Install the release — back on the product page, now licensed, the Overview tab has a release panel. If it offers Install v…, press it; if it says Up to date on a product you have only just licensed, press Check for Updates once, then install whatever it offers. The Releases tab holds the notes for the version you are being offered — read them first.

    Install downloads the release, verifies it and extracts it over the project root. It runs no migrations, builds nothing and restarts nothing, so finish it from a shell on the server:

    pnpm updator

    That is the finalise chain — stop, dependencies, schema, seed data, frontend build, start — and it is what creates the seven tables below and the addon's routes. If the panel still says Up to date after the check there is nothing to download; go straight to the next step.

    1. Check for Updates, then Install v… when it is offered
    2. Releases — the notes for the version you are about to install
    3. The Enabled switch — step 4, not yet
  4. Switch it on — turn the Enabled switch on, in the product page heading or on the card in the Extension Manager, which is usable now that the licence is verified. This is the product's only on/off switch; there is no separate settings screen and no .env variable. It takes effect without a restart: the admin screens and /forex appear at once, and the scheduler picks up processForexInvestments on its next re-sync, within a minute.

  5. Confirm the surfaces appearForex Broker & Investments shows up under Admin → Extensions → Investment Products, the user area answers at /forex, and /admin/system/cron lists processForexInvestments under the forex category.

What activation creates

Seven tables:

Table Holds
forex_plan The investment plans — currency, limits, profit percentage, default result
forex_duration Terms: an integer plus HOUR, DAY, WEEK or MONTH
forex_plan_duration Which durations each plan offers. A plan with no rows here can never be invested in
forex_investment One row per investment, with its principal, result and end date
forex_account DEMO and LIVE accounts: broker, MetaTrader version, balance, leverage, withdrawal caps
forex_signal Signals — a title, an image and a status
forex_account_signal Which accounts see which signals

Deposits and withdrawals do not get their own table. They live in core's transaction table under the types FOREX_DEPOSIT and FOREX_WITHDRAW, and each investment also writes an audit row of type FOREX_INVESTMENT. That is why the deposit and withdrawal screens are gated on this addon's permissions but read a core model.

If you build from source, run pnpm types:generate once the tables exist.

Permissions

Thirty-six keys ship with the platform's permission seeder. Assign them to the roles that should administer the addon at /admin/crm/role.

Screen Route Access View / Create / Edit / Delete
Dashboard /admin/forex access.forex
Accounts /admin/forex/account access.forex.account *.forex.account
Plans /admin/forex/plan access.forex.plan *.forex.plan
Durations /admin/forex/duration access.forex.duration *.forex.duration
Investments /admin/forex/investment access.forex.investment *.forex.investment
Signals /admin/forex/signal access.forex.signal *.forex.signal
Deposits /admin/forex/deposit access.forex.deposit *.forex.deposit
Withdrawals /admin/forex/withdraw access.forex.withdraw *.forex.withdraw

* expands to view, create, edit and delete — so the accounts screen uses view.forex.account, create.forex.account, edit.forex.account and delete.forex.account.

The Forex Broker & Investments item in the admin extensions menu checks access.forex.account, not access.forex. An operator granted only access.forex can load the dashboard by URL but will not see the menu entry. Grant both.

Two behaviours worth knowing about the admin API:

  • Approving a withdrawal and reversing a deposit both need editedit.forex.withdraw and edit.forex.deposit respectively. A read-only finance role cannot clear either queue.
  • Recovering a cancelled investment needs edit.forex.investment. It is not a Super-Admin-only action, despite having behaved that way in older builds.

Nothing under /api/forex — the customer-facing half — carries a permission. Every route there is scoped to the caller's own records. Who may use the product is decided by KYC features instead.

KYC gates

Four verification features are enforced by this addon, configured per level under Admin → CRM → Compliance & Verification → Verification Levels (/admin/crm/kyc).

Feature Refuses
deposit_forex Funding a forex account
withdraw_forex Withdrawing from a forex account
invest_forex Opening an investment
create_forex_account Provisioning a new LIVE account

All four are checked server-side. A customer whose verification level does not carry the feature is refused even if they call the API directly. This applies only on installs with verification enforcement switched on — with it off the platform is never stricter than the screens allow.

create_forex_account is deliberately not fatal to the rest of the page. A customer who is not cleared to open a new live account still gets their demo account and every account they already hold, so tightening your levels never locks an existing customer out of their own balance.

view_forex and trade_forex exist in the platform's feature list but are not checked by any route in this addon — trade_forex belongs to the Forex & Multi-Asset Trading terminal.

The settlement cron

One job does all the settling. Find it at /admin/system/cron under the forex category.

Job Every Does
processForexInvestments 1 hour Finds every ACTIVE investment whose end date has passed, settles it, and pays the result into the customer's LIVE forex account

Nothing else in the product settles an investment. If the cron process is not running, investments pass their end date and stay ACTIVE indefinitely — the principal has already left the customer's forex account and nothing returns it. Customers notice this within hours of your first short-duration plan maturing.

Check lastRun and lastRunError on that job before investigating anything else about a missing payout.

The hourly period is also the resolution of the product. An investment on a one-hour duration settles on the next tick after its end date, not at the second it matures. Plan your shortest duration accordingly.

Smoke test

Do this on a staging install, or with a test user, before you announce anything. It exercises every part of the chain in about five minutes.

  1. Create a duration/admin/forex/duration, add 1 HOUR.

  2. Create a plan/admin/forex/plan. Give it a name, pick a wallet type and currency your test user actually holds, set min profit 1, max profit 20, profit percentage 10, default result WIN, minimum amount 10, maximum amount 1000. Attach the 1 HOUR duration. Set its status to active — plans are created disabled.

  3. Sign in as the test user and open /forex/dashboard — a DEMO and a LIVE account are provisioned on first visit.

  4. Deposit — from the LIVE account card, deposit an amount you hold in the matching wallet. This settles instantly; the forex account balance should change on the spot.

  5. Invest/forex/plan, open your plan, choose the 1-hour duration, accept the terms and invest. The forex account balance drops by the principal.

  6. Force settlement — rather than waiting, open /admin/system/cron, find processForexInvestments and run it manually once the end date has passed.

  7. Check the payout — the investment reads COMPLETED / WIN at /admin/forex/investment, and the customer's forex account is back up by principal plus 10%.

  8. Withdraw — submit a withdrawal as the customer, then approve it at /admin/forex/withdraw. The wallet is credited only at that point.

If step 7 does not happen, the cause is almost always one of: the cron is not running, the plan's duration was never linked, or the plan's currency does not match what the account was funded with. All three are covered in Troubleshooting.

Upgrading an existing install

Press Install v… on the product page's Overview tab in the Extension Manager, run pnpm updator, then read this. Several behaviours around money changed and none of them are optional.

Forex accounts are single-currency now

An account is locked to one currency and one wallet type the first time it is funded, and every later movement must agree. An existing account whose balance was built from more than one currency will refuse movements in anything but the first currency it is used with after upgrading. That is intentional — a mixed balance has no correct interpretation — but settle such accounts before you upgrade if you have any.

Investment payouts land in the forex account

A matured investment used to pay straight into the spot wallet, which bypassed the approval every forex withdrawal requires. Payouts now return to the forex account the principal came from, and the customer withdraws them through the normal queue. Expect your withdrawal queue to get busier.

The admin deposit screen is a reversal screen

Forex deposits settle instantly, so there has never been anything to approve. The screen now reverses a completed deposit: the forex account gives back what it was credited, and the wallet is made whole for the amount and the fee. The amount is not editable.

A plan's duration must be one the plan offers

Every duration on the platform used to be accepted against every plan. Because a plan's profit is a flat percentage that does not scale with time, that let a customer take a 30-day plan's full return in one hour. Check that each plan has the durations you intend attached — a plan with none can no longer be invested in at all.

Settlement pays the advertised percentage

Every screen showed the plan's profit percentage; settlement used the separate default profit field, which defaults to 0. A plan advertised at 15% whose default profit was left alone paid exactly nothing on every win. Settlement now uses the percentage the customer was quoted. If you compensated for the old behaviour by inflating default profit, undo it.

Withdrawal limits actually reset

The daily and monthly caps shared one anchor and the daily rollover overwrote it, so the monthly counter only reset after thirty consecutive days with no withdrawals. Active customers hit the monthly cap and were then locked out permanently. The two windows are tracked separately now — customers who were stuck will be able to withdraw again on upgrade.

Deleting a plan or duration is refused while it is in use

forex_investment cascades from both tables at the database level, so deleting a duration used to physically remove every investment on it — principal, history and all. Deletion is now refused while active investments reference the row. Cancel or settle them first; cancelling refunds.

If you deploy with DB_SYNC=none, run the backend once with sync enabled so the new columns land — the account currency binding and the second withdrawal anchor are both new columns on forex_account.