Install and enable
Licensing and enabling the ICO Launchpad, the three reference tables that ship empty, the escrow account it needs, the permissions to grant and the cron jobs that settle every sale.
Installing the addon is the easy half. The half that catches people out is that a freshly enabled ICO Launchpad cannot host a single sale: three reference tables ship empty, and the launch form is unusable until you fill all three. Work through this page in order.
Licence and enable
The addon is licensed separately from core, through the same Extensions screen as every other Bicrypto addon.
-
Buy and download the ICO Launchpad from CodeCanyon. Keep the purchase code and your Envato username to hand — activation needs both.
-
Open the Extensions screen at
/admin/system/extensionand find ICO in the list. -
Activate with your Envato username and purchase code. Activation writes a licence file to
lic/<productId>.licin the install root. -
Install the latest version, then wait for the extraction to finish.
-
Toggle the extension on. This sets
status = trueon its row in theextensiontable. -
Restart the platform so the new routes and models load.
pnpm restart
Two separate mechanisms decide whether the addon works, and they fail in different ways:
| Mechanism | What it controls | Symptom when missing |
|---|---|---|
lic/<productId>.lic on disk |
Every request to /api/ico and /api/admin/ico |
API calls refused; screens load but stay empty |
extension.status = true |
Whether ico appears in the cached extension list the frontend reads |
The ICO links vanish from the site footer and nav; the routes still resolve if typed |
The licence check is cached for five minutes, so a freshly activated licence can take that long to take effect on a running backend. A restart clears it immediately.
Copying an install to a new server, or changing the machine it identifies
itself by, invalidates the file. Re-activate from the Extensions screen on the
new box rather than copying lic/ across.
Database tables
The addon adds thirteen tables. They are created by Sequelize's auto-sync on first boot after the extension is enabled — there is no separate migration step and no SQL to run.
| Table | Holds |
|---|---|
ico_token_offering |
One row per sale: name, symbol, status, target, dates, participant count |
ico_token_detail |
Supply, blockchain, description, links, use of funds, vesting terms |
ico_token_offering_phase |
Priced phases: allocation, remaining, duration, sequence |
ico_transaction |
One row per contribution |
ico_token_vesting |
One row per contribution that vests — the whole promise |
ico_token_vesting_release |
One row per tranche of that promise |
ico_launch_plan |
The packages creators pay for |
ico_blockchain |
Chains creators may launch on |
ico_token_type |
Token standards creators may pick |
ico_team_member |
Team profiles on an offering |
ico_roadmap_item |
Roadmap milestones on an offering |
ico_token_offering_update |
Project update posts |
ico_admin_activity |
The addon's own audit trail |
ico_token_offering carries foreign keys to ico_launch_plan and
ico_token_type with ON DELETE CASCADE. Deleting a launch plan or a token
type that offerings point at deletes those offerings. Disable a plan
(status = false) instead of removing it.
Seed the three reference tables
ico_launch_plan, ico_blockchain and ico_token_type are created with no
rows. The launch form's first step is a plan picker with nothing in it, and the
token-configuration step needs a blockchain and a token type before it will
advance. A creator hitting this sees an empty dropdown and no explanation.
All three live under Admin → ICO → Settings, on their own tabs.
Blockchains
Each row is a name and a value. The name is what a creator sees; the value
is what gets stored on the offering and used for validation.
Wallet addresses and transaction hashes are validated against a fixed table of
chain names, compared lowercase: ethereum, bsc, polygon, bitcoin,
solana. Any other value falls back to a loose check — an address is accepted
if it is 20 to 128 characters with no spaces, and a transaction hash is accepted
unconditionally.
So a blockchain named "Ethereum" with the value eth gets no address
validation, and a buyer can typo their address into an unrecoverable transfer.
Use the exact five values above wherever they apply.
Token types
Name, value and a description. Nothing is enforced against the value — it is
descriptive metadata shown on the offer page (ERC-20, BEP-20, SPL and so on).
Create at least one, or no offering can be submitted.
Launch plans
The package a creator buys to list. Price, currency, wallet type and a JSON feature block.
| Field | Effect |
|---|---|
price |
Charged from the creator's wallet at submission. 0 is allowed and skips the charge entirely |
currency + walletType |
Which wallet the fee comes from — and the currency every contribution to that offering is paid in |
features.maxTeamMembers |
Hard limit, enforced at launch and when adding members later |
features.maxRoadmapItems |
Hard limit, enforced at launch and when adding items later |
features.maxOfferingPhases |
Hard limit, enforced at launch |
status |
false hides the plan from the picker without deleting it |
maxUpdatePosts, supportLevel, marketingSupport, auditIncluded,
customTokenomics, priorityListing and kycRequired are collected by the
plan form and displayed on the plan card, but nothing in the backend reads
them. Only the three max* limits above are enforced. Do not sell a plan on
the promise that kycRequired gates anything — KYC is decided elsewhere, in the
level builder.
The plan's currency is the most consequential field on the page. It is copied
onto the offering as purchaseWalletCurrency / purchaseWalletType, so a plan
priced in USDT on the SPOT wallet means every investor in every offering
bought with that plan contributes in spot USDT. If your users hold fiat, they
cannot participate. Create one plan per currency you want sales denominated in.
The escrow account
Every contribution is held on the Super Admin account's wallet until the sale settles.
The purchase route resolves the Super Admin account to credit escrow. If none exists it throws:
ICO escrow is not configured: no Super Admin wallet available to hold contributed funds.
The buyer's wallet is never touched — the whole purchase rolls back — but the error reads like a server fault, not a configuration problem. Confirm one account holds the Super Admin role before you approve the first offering.
The escrow wallet itself is created on demand in the offering's currency and wallet type, so you do not need to pre-create wallets. What you do need is for the account to exist and to be the one the platform's fee collection already uses.
Permissions
Fifteen ICO keys are seeded with core. None of them are granted to any role —
Admin and Support ship empty. Grant them on Admin → Roles.
| Key | Grants |
|---|---|
access.ico |
Opens the ICO admin dashboard |
access.ico.offer |
Opens the offer list and the per-status views |
view.ico.offer |
Loads offer rows, funding charts and per-offer vesting |
create.ico.offer |
Opens and uses the admin "create offering" form |
edit.ico.offer |
Approve, reject, flag, pause, resume, edit, add and delete phases |
delete.ico.offer |
Deletes an offering |
access.ico.transaction |
Opens the transaction desk and a transaction's detail page |
view.ico.transaction |
Loads transaction rows |
edit.ico.transaction |
Verify, reject, and add or remove notes |
access.ico.settings |
Opens the settings page |
view.ico.settings |
Reads the investment-limits endpoint |
edit.ico.settings |
Saves settings, blockchains, token types and launch plans |
access.ico.stat |
Loads the admin dashboard's statistics |
manage.system |
The Super Admin emergency cancel-and-refund |
Grant access.ico.offer without view.ico.offer and the operator gets the
offer page, the filters and a permanently empty table — no error, no banner.
Tick both keys for every screen. create.ico.transaction and
delete.ico.transaction are also seeded but no route asks for them; granting
them does nothing.
Two of the settings endpoints additionally check the caller's role name
rather than a permission, and accept only Admin or Super Admin. An operator
on a custom role holding view.ico.settings will still be refused there.
KYC gating
Token-sale participation and token-sale creation are KYC features, decided once in the KYC level builder — not on the ICO settings page.
- Token Sale Participation (
purchase_ico) — lets a verified user contribute to an offering. - Token Sale Creation (
create_ico) — lets a verified user submit an offering.
Open Admin → CRM → KYC, edit the levels that should carry them, and tick both features on the levels you want to hold them.
Neither is enforced unless the platform KYC switch and per-feature enforcement are both on. With both off, anybody signed in can buy and launch.
Earlier builds had one on the ICO settings page. It wrote a key nothing read, while the offer page was already hiding itself from the same user through the shared gate — so the UI refused what the server allowed. It has been removed; the settings page now links to the level builder instead.
Cron
Two scheduled jobs do all the settlement work. Both run hourly and both live
in the cron process — the PM2 app started with CRON_MODE=only on port 4001.
| Job | What it does |
|---|---|
processIcoOfferings |
Activates offerings whose start date has passed, then closes ended offerings as SUCCESS or FAILED and refunds every contribution on a failure |
processIcoVestingReleases |
Announces vesting tranches that have come due, closes finished schedules, cancels schedules behind refunded contributions |
processIcoOfferings is the only thing that decides whether an offering
succeeded or failed, and the only automatic path that pays contributors back
when it failed. If the cron app is not running, ended offerings sit at ACTIVE
forever, refuse new contributions because the end date has passed, and hold
every contributor's money in escrow indefinitely.
Check it on Admin → System → Cron. Both jobs report per-run status there, and a failed run is reported as failed rather than swallowed.
Settlement runs one database transaction per offering, deliberately, because refunding a large failed sale takes row locks on every contribution and on the escrow wallet — the single hottest row on the platform. A 3,000-contributor refund in one transaction would block staking, investment and P2P settlement for its duration.
Verify the install
Work down this list on a fresh install. Every item is something that fails later, and quietly, if you skip it.
- The extension is toggled on and
pnpm restarthas been run since. lic/<productId>.licexists in the install root.- One account holds the Super Admin role.
- At least one blockchain exists, using one of the five recognised
valuestrings if it is one of those chains. - At least one token type exists.
- At least one launch plan exists,
status = true, in the currency and wallet type you want sales denominated in. - The ICO permissions are granted to whichever role your reviewers sit on.
purchase_icoandcreate_icoare on the right KYC levels — or platform KYC is deliberately off.- Admin → System → Cron shows
processIcoOfferingsandprocessIcoVestingReleaseswith a recent successful run. - Contribution limits on Admin → ICO → Settings match the size of sale you expect. The defaults are a 10 minimum, a 100,000 single-contribution maximum and 50,000 per user per offering.
Then submit a test offering with a zero-price launch plan, approve it, contribute a small amount from a second account, and walk it through delivery and verification. That exercises every leg of the ledger before real money does.