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.

8 min readUpdated 3 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
    • Your CodeCanyon username and the licence code for item 36668679
    • 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. Open Admin → System → Extensions — the screen is at /admin/system/extension.

  2. Activate — click the Forex entry, enter your CodeCanyon username and licence code, and confirm. The platform verifies the purchase before enabling anything.

  3. Install the latest version — choose it from the version list and wait for the install to finish.

  4. Enable it — toggle the extension on. This is the product's only on/off switch; there is no separate settings screen and no .env variable.

  5. Run the updator — from the project root:

    pnpm updator
  6. Confirm the surfaces appearForex Broker & Investments shows up under Admin → Extensions → Investment Products, and the user area answers at /forex.

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

Run pnpm updator, then read this. Several behaviours around money changed and none of them are optional.

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.

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.

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.

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.

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.

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.

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.