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.

7 min readUpdated 3 August 2026install, licence, permissions, cron, escrow

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.

  1. Buy and download the ICO Launchpad from CodeCanyon. Keep the purchase code and your Envato username to hand — activation needs both.

  2. Open the Extensions screen at /admin/system/extension and find ICO in the list.

  3. Activate with your Envato username and purchase code. Activation writes a licence file to lic/<productId>.lic in the install root.

  4. Install the latest version, then wait for the extraction to finish.

  5. Toggle the extension on. This sets status = true on its row in the extension table.

  6. 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.

Display name shown in the launch form and on the offer page
The stored identifier — this is the string address and hash validation keys off

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 restart has been run since.
  • lic/<productId>.lic exists in the install root.
  • One account holds the Super Admin role.
  • At least one blockchain exists, using one of the five recognised value strings 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_ico and create_ico are on the right KYC levels — or platform KYC is deliberately off.
  • Admin → System → Cron shows processIcoOfferings and processIcoVestingReleases with 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.