Tokens and markets

Deploy a new token or import an existing contract, set its fees and limits, then pair two active tokens into a tradable market with your own precision and maker/taker fees.

7 min readUpdated 8 August 2026tokens, markets, erc20, spl, fees, limits

A market is two tokens. Both must exist, both must be active, and the assets behind them must be on a chain that is configured and has a funded master wallet. So tokens come first, in every sense.

What a token record is

ecosystem_token is the platform's definition of a tradable and withdrawable asset. It carries the contract address, the chain and network it lives on, its on-chain decimals, the display precision, its contractType, and two JSON blobs: fee and limits.

A token's currency symbol is what ties everything together. A user's ECO wallet is per currency, and the address map inside it gets one entry per chain that has an active token with that symbol. So USDT on ETH, BSC and TRON is three token rows and one wallet with three addresses.

There are two ways to create one, and they are not interchangeable.

Deploying a new token

Use this when the token does not exist yet and you want to issue it. The platform deploys a real contract on-chain, signed by the master wallet.

Deploys a token contract and registers it
  1. Confirm the prerequisites. The chain must have <SYMBOL>_NETWORK set — deployment rejects with "Network not found for chain" otherwise. The vault must be unlocked. The master wallet must exist and hold enough native coin; a contract deployment is expensive relative to a transfer.

  2. Open Admin → Ecosystem → Trading → Tokens → Create.

  3. Fill in the token itself — name, currency symbol, chain, decimals.

  4. Set the supply. Three fields, with rules the endpoint enforces: initialSupply must be greater than zero, marketCap must be at least initialSupply, and neither may be negative. initialHolder is the address that receives the initial supply and is required.

  5. Set precision, fees and limits — see below.

  6. Deploy. On EVM chains this uses the bundled ERC20 contract, which supports permit, so the token is recorded as contractType: PERMIT. On Solana it deploys an SPL mint and queues the initial minting as a background task; if that minting fails, the token row is removed again.

The contract name recorded on the token follows the chain: ERC20 on Ethereum and most EVM chains, BEP20 on BSC, HRC20 on HECO, CRC20 on Cronos, SPL on Solana.

Importing an existing token

Use this for an asset that already exists — USDT, USDC, any third-party contract, or a chain's native coin.

Registers an already-deployed token without deploying anything

You supply the contract address, chain, network, decimals and — critically — the contractType. Get that wrong and deposits go to the wrong kind of address: marking a non-permit token as PERMIT means users are given their own address for a token the platform will never be able to move out of it.

For a native coin, choose NATIVE and leave the contract blank. The endpoint substitutes the null-address sentinel 0x0000000000000000000000000000000000000000, which is what the seeded natives use and what the withdrawal path expects. A second native import on the same chain returns 409 with "already has a native token registered".

Adding a custom EVM chain backfills its native coin as a token automatically, because a native currency has no contract address and cannot go through the token import form. Do not create it by hand.

Fees, limits and precision

Both creation paths take the same three configuration blocks, and all three are editable afterwards from the token's edit screen.

Updates a token's precision, limits and fee

Fee is an object with min and percentage. The withdrawal fee charged is max(amount × percentage ÷ 100, min), always denominated in the token's own currency. min is what stops a 0.5% fee from being worthless on a small withdrawal; set it to at least cover the network cost you expect to absorb, because network gas is paid by the platform and recovered through this fee.

Limits is an object with deposit and withdraw, each having min and max. Minimums keep dust and spam out; maximums cap your exposure per transaction.

Precision is the number of decimal places users may enter. It is checked on withdrawal — an amount with more decimals than precision is rejected with a message naming the maximum — and it falls back to the token's on-chain decimals, then to 8, if unset.

Status is the master switch. An inactive token disappears from deposit and withdrawal options, cannot be used to create a market, and stops being considered when a user's addresses are generated.

Enables or disables a token

The token's icon is written to an icon cache on create and import. A failure there is logged but does not fail the operation — you get a token with a missing picture, not a missing token.

Lists the on-chain holders of a token contract

The holders view reads the contract's transfer list through the same explorer failover as transaction history, so on a chain with a keyless Blockscout or Routescan instance it works with no key at all. On a chain that has neither — BSC (56 and 97), Fantom (250 and 4002), Cronos (25), HECO (128 and 256) and Polygon Amoy (80002) — it still needs <CHAIN>_EXPLORER_API_KEY or ETHERSCAN_API_KEY, and without one it throws rather than returning an empty list. "This contract has no transfers" is a real answer and returns an empty list, not an error.

Creating a market

Creates a market from two active tokens
  1. Go to Admin → Ecosystem → Trading → Markets → Create.

  2. Choose the base and quote assets. Both dropdowns list only tokens with status: true. An inactive token is not offered, and passing one anyway returns 404 "Currency token not found or inactive".

  3. Save. The pair must be unique — a second BTC/USDT returns 409. The market is created active.

  4. Configure it from the row's edit action: precision, limits, fees and the two promotional flags.

  5. Check it appears at /ecosystem, and that it opens at /trade?symbol=BTC-USDT&type=spot-eco.

Market configuration

Everything except the pair itself lives in the market's metadata object.

Field What it controls
precision.amount Decimal places allowed on the base asset — BTC in BTC/USDT
precision.price Decimal places allowed on the price, in quote units
limits.amount Minimum and maximum order size in the base asset
limits.price Minimum and maximum limit price
limits.cost Minimum and maximum total order value (amount × price)
maker Percentage fee charged to the resting side of a trade
taker Percentage fee charged to the side that crosses the spread

limits.cost is the one that does the real work. It is what stops orders too small to be worth settling, and it is enforced against the total rather than either component, so a user cannot evade it by splitting price and size.

Two flags sit outside metadata. Trending promotes the market in the market list, and Hot flags it for the promotional category used by the frontend and the mobile app. Neither affects trading.

Updates a market's metadata and flags
Enables or disables a market

Disabling a market hides it from users and keeps its configuration. It does not cancel resting orders — do that first if you intend to retire a pair rather than pause it.

What trades, and what does not

The matching engine handles limit and market orders. Stop-limit and stop-market orders are accepted on the same endpoint but rest outside the engine until their trigger price is crossed, at which point they are activated. Anything else is rejected with 422.

Places an order on an ecosystem market

Orders are also gated by the platform's KYC feature policy for trading, and by a per-user rate limiter tuned for active traders rather than one-shot checkout flows.

Candles, the ticker and the order book are all built from real orders. A freshly created pair shows nothing until someone trades it. If you need quoted markets from day one, that is what the AI Market Maker addon is for — and note that it enqueues into the matching engine's in-process queue, so it must run in the same process as the engine.