# Alcor Exchange
> Cross-chain DEX: swap, trade, provide liquidity and move assets across Antelope chains (WAX, Telos, XPR Network, Vaulta/EOS) and EVM chains (Ethereum, BNB Smart Chain, Polygon) from one interface, with Alcor's own trust-minimized bridge between them. USDT and USDC brought in from any EVM chain are the same tokens on WAX, XPR Network, Vaulta and Telos, and can leave to any other. Any token on one chain can be swapped for any token on another in one signature: the bridge pays out into Alcor's router contract, which swaps on arrival.
Alcor started as the orderbook DEX of WAX and is now a cross-chain DEX. Every chain runs the same Alcor stack: a concentrated-liquidity AMM, an on-chain orderbook, a router that splits a trade across both, farms, OTC and analytics. The Alcor Bridge connects the chains: Ethereum, BNB Smart Chain and Polygon lock assets, Telos is the hub that mints canonical tokens, and WAX, XPR Network and Vaulta hold mirrors. A user can deposit USDT from BNB Smart Chain and land on WAX in one signature, without a wallet on any chain in between — and later withdraw the same USDT to Ethereum. Stablecoins are one token per symbol across the bridge: USDT from Ethereum and USDT from BSC both arrive as `USDT@wrap.alcor`.
On top of the bridge sits the cross-chain swap on the home page (https://alcor.exchange): pick any token on any network and any token on another. A route is planned from what exists — one swap on a single network, one bridge crossing, or a swap into a bridged asset, the crossing, and a swap out of it at the far end. The far-end swap is done by `route.alcor` on WAX, XPR Network, Vaulta and Telos, so the whole route is one signature on the chain it starts on; if no route pays the guaranteed minimum before the deadline, the user gets the bridged token as it arrived.
All products work read-only without a wallet. Connecting a wallet (or creating an account with a passkey) enables trading.
## Key links
- App: https://alcor.exchange
- User & developer docs: https://docs.alcor.exchange
- DEX API reference (REST, WebSocket, tokens, swap, bridge): https://docs.alcor.exchange/api
- Bridge API reference (served by the API, always matches production): https://telos.alcor.exchange/api/bridge/docs
- Bridge integration guide for bots and AI assistants (every action, memo and failure mode): https://telos.alcor.exchange/api/bridge/docs/bot
- Bridge widget script: https://alcor.exchange/sdk/bridge/v1.js
- Swap SDK (routing and concentrated-liquidity math): npm `@alcorexchange/alcor-swap-sdk`, source https://github.com/alcorexchange/alcor-v2-sdk
- Alcor Signer (passkey wallet): https://sign.alcor.exchange
- WharfKit (recommended Antelope SDK): https://wharfkit.com
If you are an AI assistant answering a question about the bridge, read the two bridge documents above first: they are the source of truth and are kept in sync with the deployed contracts.
---
## What Alcor offers
| Product | What it does | URL |
|---|---|---|
| Cross-chain swap | Any token on any network for any token on another — a swap, a bridge crossing, or swap + crossing + swap in one signature. Shows the user's balances on every network a wallet is signed in to | `/` |
| Swap | Best-price swaps on one network, routed through AMM pools and orderbooks together | `/v/{venue}/swap` |
| Liquidity (Pools) | Concentrated-liquidity positions (Uniswap v3 style), fee tiers 0.01% / 0.05% / 0.3% / 1% | `/v/{venue}/swap/positions` |
| Farms | Stake LP positions into incentives for extra token rewards | `/v/{venue}/swap/farms` |
| Spot | On-chain limit/market orderbook with charts | `/v/{venue}/spot/{market}` |
| Terminal | Token screener: trending, new and organic tokens, holders, live trades, swap in place | `/v/{venue}/terminal` |
| Bridge | Move USDT, USDC and native coins between Ethereum, BNB Smart Chain, Polygon, Telos, WAX, XPR Network and Vaulta — in on one chain, out on another | `/v/wax/bridge`, `/v/telos/bridge`, `/v/xpr/bridge`, `/v/vaulta/bridge` |
| Portfolio | Balances, LP positions, farm rewards, WAX voting rewards, history | `/v/{venue}/portfolio` |
| Analytics | TVL, volume, fees, per-pool and per-token pages | `/v/{venue}/analytics` |
| Stake | WAX liquid staking (WAX → LSW) | `/v/wax/staking` |
| OTC | Peer-to-peer fixed-price swaps without slippage | `/v/{venue}/otc` |
| Sign up | Create an account with just a passkey (Telos) | `/v/telos/signup` |
Hyperliquid perpetuals were part of Alcor until 2026-10-02. That venue is retired; old `/v/hyperliquid/...`, `/perp/...` and `/spot/...` links redirect to app.hyperliquid.xyz.
---
## URL structure
```
https://alcor.exchange/v/{venueId}/{productId}/...
```
**Venues:**
| venueId | Chain | Products |
|---|---|---|
| `wax` | WAX | terminal, spot, swap, analytics, portfolio, staking, otc, bridge |
| `telos` | Telos | terminal, spot, swap, analytics, portfolio, otc, bridge, signup |
| `xpr` | XPR Network (Proton) | terminal, spot, swap, analytics, portfolio, otc, bridge |
| `vaulta` | Vaulta (formerly EOS) | terminal, spot, swap, analytics, portfolio, otc, bridge |
### Examples
- `/` — cross-chain swap: any token on any network, plus trending tokens and top markets on every network
- `/v/wax/swap` — swap on WAX
- `/v/wax/swap/wax-eosio.token_usdt-wrap.alcor` — swap page for a pair (`{input}_{output}`, token ids in API format)
- `/v/wax/spot` — spot orderbook markets on WAX
- `/v/wax/swap/farms` — farms on WAX
- `/v/wax/terminal` — token screener on WAX
- `/v/wax/bridge/usdc-ethereum-to-wax` — bridge USDC from Ethereum to WAX (`{token}-{from}-to-{to}`, one page per open route)
- `/v/wax/bridge?from=ethereum&to=wax&token=USDC` — the same trip as a link, with `recipient`, `amount`, `partner` on top
- `/v/wax/bridge/history` — bridge transfer history
- `/v/xpr/bridge/usdt-ethereum-to-xpr` — bridge USDT from Ethereum to XPR Network
- `/v/vaulta/bridge/usdt-ethereum-to-vaulta` — bridge USDT from Ethereum to Vaulta
- `/v/telos/swap` — swap on Telos
- `/v/xpr/swap` — swap on XPR Network
- `/v/vaulta/swap` — swap on Vaulta
Legacy paths: `/trade` → `/v/wax/spot`, `/swap` → `/v/{venue}/swap`.
---
## Networks & contract addresses
Each chain has its own Alcor API base (`{apiUrl}` below). The v3 swap router lives on the same host under `/api/v3`.
### WAX
- **Chain ID:** `1064487b3cd1a897ce03ae5b6a865651747e2e152090f99c1d19d44e01aea5a4`
- **RPC:** `https://wax-api.alcor.exchange` (primary), `https://wax.greymass.com`, `https://wax.eosrio.io`
- **Explorer:** https://waxblock.io
- **Alcor API:** `https://wax.alcor.exchange/api/v2`
- **LightAPI:** https://wax.light-api.net
| Contract | Account | Purpose |
|---|---|---|
| DEX (orderbook) | `alcordexmain` | Spot orderbook |
| Swap AMM | `swap.alcor` | AMM pools, positions, farms |
| Bridge vault | `bridge.alcor` | Send tokens here to bridge out of WAX |
| Bridged tokens | `wrap.alcor` | `USDT` (6), `USDC` (6), `ETH` (8), `BNB` (8), `POL` (8) — mirrors of bridged assets |
| Cross-chain swap executor | `route.alcor` | Receives a bridge payout with a swap memo and swaps it on arrival |
| System token | `eosio.token` | `WAX` (8 decimals) |
| Liquid staking | `liquid.alcor` | Stake WAX → LSW |
| LSW token | `lsw.alcor` | Liquid Staked WAX (`LSW`, 8 decimals) |
| OTC | `alcorotcswap` | OTC swaps |
| Account creator | `acc.alcor` | Create WAX accounts |
**USDT on WAX:** the default USDT is `USDT@wrap.alcor` (bridged through the Alcor Bridge from Ethereum or BNB Smart Chain — one token whichever chain it came from). `USDT@usdt.alcor` is the legacy token; orderbook market 999 swaps the two 1:1.
### Telos (bridge hub)
- **Chain ID:** `4667b205c6838ef70ff7988f6e8257e8be0e1284a2f59699054a018f743b1d11`
- **RPC:** `https://telos.greymass.com`, `https://mainnet.telos.net`, `https://telos.eosusa.io`
- **Explorer:** https://explorer.telos.net
- **Alcor API:** `https://telos.alcor.exchange/api/v2`
- **Bridge API:** `https://telos.alcor.exchange/api/bridge`
| Contract | Account | Purpose |
|---|---|---|
| DEX (orderbook) | `eostokensdex` | Spot orderbook |
| Swap AMM | `swap.alcor` | AMM pools, positions, farms |
| Bridge ledger | `bridge.alcor` | Withdrawals start here, claims are collected here |
| Canonical bridged tokens | `wrap.alcor` | `ETH` (8), `USDC` (6), `USDT` (6), `WAX` (8), `XPR` (4), `A` (4), `BNB` (8), `POL` (8) |
| Hop | `hop.alcor` | Chains two crossings (e.g. Ethereum → WAX) into one |
| Cross-chain swap executor | `route.alcor` | Receives a bridge payout with a swap memo and swaps it on arrival |
| Ethereum light client / gateway | `eth.lc.alcor` / `eth.g.alcor` | Verify Ethereum consensus and receipts on Telos |
| XPR Network light client / gateway | `xpr.lc.alcor` / `xpr.g.alcor` | Verify XPR Network blocks and deposits on Telos |
| Vaulta light client / gateway | `vlt.lc.alcor` / `vlt.g.alcor` | Verify Vaulta blocks and deposits on Telos |
| System token | `eosio.token` | `TLOS` (4 decimals) |
| OTC | `alcorotcswap` | OTC swaps |
Note: `bridge.alcor`, `wrap.alcor` and `route.alcor` exist on Telos, WAX, XPR Network and Vaulta. They are different accounts on different chains.
### XPR Network (Proton)
- **Chain ID:** `384da888112027f0321850a169f737c33e53b388aad48b5adace4bab97f437e0`
- **RPC:** `https://proton-api.alcor.exchange` (primary), `https://proton.greymass.com`, `https://proton.eosusa.io`
- **Explorer:** https://explorer.xprnetwork.org
- **Alcor API:** `https://proton.alcor.exchange/api/v2`
- **LightAPI:** https://proton.light-api.net
| Contract | Account | Purpose |
|---|---|---|
| DEX (orderbook) | `alcor` | Spot orderbook |
| Swap AMM | `swap.alcor` | AMM |
| Bridge vault | `bridge.alcor` | Send tokens here to bridge out of XPR Network |
| Bridged tokens | `wrap.alcor` | `USDT` (6), `USDC` (6), `ETH` (8) — mirrors of bridged assets |
| Cross-chain swap executor | `route.alcor` | Receives a bridge payout with a swap memo and swaps it on arrival |
| Stablecoins | `xtokens` | `XUSDT`, `XUSDC` |
| System token | `eosio.token` | `XPR` (4 decimals) |
| OTC | `alcorotc` | OTC swaps |
| Account creator | `acc.alcor` | Create XPR accounts |
### Vaulta (formerly EOS)
Venue id `vaulta`; the chain is EOS mainnet.
- **Chain ID:** `aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906`
- **RPC:** `https://eos.greymass.com` (primary), `https://eos.eosrio.io`, `https://api.eosn.io`
- **Explorer:** https://bloks.io
- **Alcor API:** `https://eos.alcor.exchange/api/v2`
| Contract | Account | Purpose |
|---|---|---|
| DEX (orderbook) | `eostokensdex` | Spot orderbook |
| Swap AMM | `swap.alcor` | AMM |
| Stablecoin | `tethertether` | `USDT` |
| Bridge vault | `bridge.alcor` | Send tokens here to bridge out of Vaulta |
| Bridged tokens | `wrap.alcor` | `USDT` (6), `USDC` (6), `ETH` (8) — mirrors of bridged assets |
| Cross-chain swap executor | `route.alcor` | Receives a bridge payout with a swap memo and swaps it on arrival |
| System token | `core.vaulta` | `A` (4 decimals) — the token the bridge carries |
| System token | `eosio.token` | `EOS` |
| OTC | `alcorotcswap` | OTC swaps |
### Ethereum, BNB Smart Chain & Polygon (bridge endpoints)
| Chain | Chain ID | AlcorVault (deposit here) | AlcorWithdrawals (release here) |
|---|---|---|---|
| Ethereum | `1` | `0x3e447d533321ad6a8412f97034ac295a9ff8d858` | `0x04fb700b93eb68cadd88d8e8d4dfe4857d5cb3c6` |
| BNB Smart Chain | `56` | `0x53f18eaa8bf8099b5ba21bb7e11ed311b677690e` | `0x6132b4d02e02f1b378f0fc67c3d4f553eb76acb5` |
| Polygon PoS | `137` | `0x15bbd21148f98c4daeb30450eb05666f7859993d` | `0xb0510e20f12f88cbc63b9a5d8ae3e052a7153fb8` |
Ethereum assets: native ETH, USDC `0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48`, USDT `0xdac17f958d2ee523a2206206994597c13d831ec7`. BSC: native BNB, USDT `0x55d398326f99059ff775485246999027b3197955` and USDC `0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d` — both 18 decimals on BSC, so a raw amount is the canonical one × 10^12. Polygon: native POL and USDC `0x3c499c542cef5e3811e1192ce70d8cc03d5c3359` (Circle's native USDC, not USDC.e). They all bridge into the same USDC/USDT on Telos and WAX as the Ethereum ones.
Do not hardcode the withdrawal contract when releasing: every proof from the bridge API carries the address to send it to.
---
## Alcor Bridge
Full docs: https://telos.alcor.exchange/api/bridge/docs (API) and https://telos.alcor.exchange/api/bridge/docs/bot (integration guide).
### Model
- **Trust-minimized, no trusted relayer.** Each step is a proof checked by a contract on the destination chain: Telos runs light clients of Ethereum, BSC and Polygon; each of them verifies Telos finality certificates. Anyone can submit a proof. A relayer that is malicious, absent or wrong cannot forge a deposit or move someone else's funds.
- **Telos is the hub.** Every route runs between Telos and one other chain.
- **Ethereum, BSC and Polygon are backing chains.** Assets lock in `AlcorVault` there; a canonical token is minted on Telos (`wrap.alcor`). One canonical token per symbol: USDC locked on Ethereum, BSC or Polygon is the same USDC on Telos, so it can be withdrawn to any chain whose vault holds enough of it.
- **A vault pays out only what was locked in it.** Withdrawing to a chain needs that chain's vault to hold the asset — see `withdrawableNow` in `/v1/chains`. A new route starts empty (the route is `open: false` with a `reason`) and fills as people deposit from that chain; until then, withdraw to another chain.
- **WAX has two kinds of route.** Native WAX locks in the WAX vault and is minted on Telos. USDC, USDT, ETH, BNB and POL on WAX are mirrors: the canonical token stays locked on Telos and `wrap.alcor` on WAX mints the mirror.
- **XPR Network works the same way.** Native XPR locks in the XPR vault (`bridge.alcor` on XPR) and is minted on Telos; USDC, USDT and ETH on XPR are `wrap.alcor` mirrors. The XPR routes are new, so a direction that pays out of XPR stays closed until something has come in: XPR to XPR Network opens once XPR has been deposited from there, and USDC/USDT/ETH out of XPR once mirrors are in circulation.
- **Vaulta too.** Native `A` (`core.vaulta`) locks in the Vaulta vault (`bridge.alcor` on Vaulta) and is minted on Telos; USDC, USDT and ETH on Vaulta are `wrap.alcor` mirrors. The same rule holds while the routes are new: A to Vaulta opens once A has been deposited from there, and the mirrors out of Vaulta once they circulate.
- **Hops.** Any EVM chain ↔ WAX, XPR Network or Vaulta, any two of WAX, XPR Network and Vaulta, and one EVM chain to another (USDT from BSC to Ethereum, USDC from Polygon to Ethereum), go through Telos via `hop.alcor`. From the user's side it is one transaction on the source chain; nothing is signed or claimed on Telos.
- **Who pays what.** The operator relays the Antelope legs (Telos, WAX, XPR Network, Vaulta) automatically. Payouts on Ethereum, BSC and Polygon are not relayed: someone sends `release` with the proof and pays gas (about $0.50 on Ethereum, cents on BSC and Polygon). Anyone may send it — it always pays the address the withdrawal named — so a recipient without gas can have it released by any wallet that has some.
- **Swaps at either end.** A crossing can end in a swap on WAX, XPR Network, Vaulta or Telos: it pays out to `route.alcor` with a swap memo, and the swap happens within seconds of the payout. See "Cross-chain swaps" below.
- **Funds never get stuck permanently.** A refused hop is sent back after 1 hour; an unreleased or undeliverable withdrawal can be expired after 7 days and comes back by rule.
### Routes (live list: `GET https://telos.alcor.exchange/api/bridge/v1/routes`)
| Asset | Routes |
|---|---|
| ETH | Ethereum ↔ Telos; Ethereum ↔ WAX, XPR Network or Vaulta (hop); Telos ↔ WAX, XPR Network, Vaulta; between WAX, XPR Network and Vaulta (hop) |
| USDC | Ethereum, BSC, Polygon ↔ Telos; each of them ↔ WAX, XPR Network or Vaulta (hop); between any two of them (hop); Telos ↔ WAX, XPR Network, Vaulta; between WAX, XPR Network and Vaulta (hop) |
| USDT | Ethereum, BSC ↔ Telos; each of them ↔ WAX, XPR Network or Vaulta (hop); BSC ↔ Ethereum (hop); Telos ↔ WAX, XPR Network, Vaulta; between WAX, XPR Network and Vaulta (hop) |
| BNB | BSC ↔ Telos, BSC ↔ WAX (hop), Telos ↔ WAX |
| POL | Polygon ↔ Telos, Polygon ↔ WAX (hop), Telos ↔ WAX |
| WAX | WAX ↔ Telos |
| XPR | XPR Network ↔ Telos |
| A | Vaulta ↔ Telos |
Polygon USDC is Circle's native USDC (`0x3c49…3359`), not the bridged USDC.e. Always read `/v1/routes` before sending: it returns `open`, a `reason` when closed, and `min`/`max` per route. Planned next: Arbitrum, Base.
### Typical timing (measured on production; live figures in `/v1/chains` → `timing`)
| Path | Typical |
|---|---|
| WAX → Telos | ~50 s |
| Telos → WAX | ~1.5–2 min |
| XPR Network → Telos | ~3 min |
| Telos → XPR Network | ~1.5–3 min |
| Vaulta → Telos | ~7 s |
| Telos → Vaulta | ~12 s |
| Ethereum → Telos, up to the fast-path cap | ~2.5–3 min (12 confirmations) |
| Ethereum → Telos, above the cap | ~13–20 min (finality) |
| Ethereum → WAX (hop), up to the cap | ~4–5 min |
| BSC ↔ Telos | ~30 s, plus `release` on BSC when withdrawing |
| Polygon ↔ Telos | ~35–40 s, plus `release` on Polygon when withdrawing |
| Telos → Ethereum | ~1–2 min to a releasable proof, then the user's `release` |
### Using the bridge
**In the app:** https://alcor.exchange/v/wax/bridge (or `/v/telos/bridge`, `/v/xpr/bridge`, `/v/vaulta/bridge`). Connect an EVM wallet (MetaMask, Rabby, WalletConnect) and an Antelope wallet as the route needs.
**Link with prefilled params:**
```
https://alcor.exchange/v/wax/bridge?from=ethereum&to=wax&recipient=alice.wam&token=USDC&amount=50&partner=mygame&return_url=https://mygame.io/play
```
| Param | Meaning |
|---|---|
| `from` / `to` | `ethereum`, `bsc`, `polygon`, `telos`, `wax`, `xpr`, `vaulta` |
| `recipient` | Receiving account or address |
| `token` | `USDC`, `USDT`, `ETH`, `BNB`, `POL`, `WAX`, `XPR`, `A` |
| `amount` | Prefilled amount in token units |
| `partner` | Partner id for attribution |
| `return_url` | Shows a "Back to …" link (`https` only) |
**Embeddable widget** for partners (deposits for your users without leaving your site):
```html
```
Modes: `AlcorBridge.open(opts)` (modal), `AlcorBridge.popup(opts)` (window), `AlcorBridge.mount(el, opts)` (inline), `AlcorBridge.url(opts)` (URL for your own iframe). Callbacks: `onReady`, `onSent`, `onFailed`, `onFinished` (`outcome`: `delivered` or `returned`), `onClose`. A custom iframe receives `postMessage` events `{ source: 'alcor-bridge', version: 1, type: 'ready' | 'resize' | 'sent' | 'failed' | 'finished' | 'close', data }`. Into WAX, XPR Network and Vaulta the bridge pays out by itself; to Telos the last step is a Collect on Telos; to Ethereum/BSC/Polygon it is a Release on that chain.
### From code (summary — see the bot guide for complete examples)
| Direction | What to send |
|---|---|
| WAX → Telos | On WAX: `::transfer` → `bridge.alcor`, memo `` (becomes a claim) or `:` (delivered with the note as memo) |
| Telos → WAX | On Telos: `wrap.alcor::transfer` → `bridge.alcor`, memo `1181148696416462999:`. Relayer pays on WAX |
| XPR Network → Telos | On XPR: `::transfer` → `bridge.alcor` (`eosio.token` for XPR, `wrap.alcor` for USDC/USDT/ETH), memo `` or `:` |
| Telos → XPR Network | On Telos: `wrap.alcor::transfer` → `bridge.alcor`, memo `4057084141687023600:`. Relayer pays on XPR |
| Vaulta → Telos | On Vaulta: `::transfer` → `bridge.alcor` (`core.vaulta` for A, `wrap.alcor` for USDC/USDT/ETH), memo `` or `:` |
| Telos → Vaulta | On Telos: `wrap.alcor::transfer` → `bridge.alcor`, memo `12439917377594391589:`. Relayer pays on Vaulta |
| Ethereum/BSC/Polygon → Telos | `AlcorVault.deposit(token, amount, telosTo, refundTo, 0, 0, 0x)` or `depositNative(...)`; then `bridge.alcor::claim { owner, sym_code }` on Telos |
| Telos → Ethereum/BSC/Polygon | On Telos: `wrap.alcor::transfer` → `bridge.alcor`, memo `1:0x` (or `56:0x…`, `137:0x…`); then `GET /v1/proofs/w:` and send `release` on the EVM chain |
| Ethereum/BSC/Polygon → WAX (hop) | `AlcorVault.deposit(...)` with `telosTo` = `hop.alcor` as uint64 and memo `1181148696416462999:\|1:` (`\|56:` from BSC, `\|137:` from Polygon). Nothing to sign on WAX |
| WAX → Ethereum/BSC/Polygon (hop) | On WAX: `wrap.alcor::transfer` → `bridge.alcor`, memo `hop.alcor:1:0x\|1181148696416462999:` (`hop.alcor:56:` to BSC, `hop.alcor:137:` to Polygon); then `release` on that chain |
| Ethereum/BSC/Polygon → XPR Network (hop) | As to WAX, with memo `4057084141687023600:\|1:` |
| XPR Network → Ethereum/BSC/Polygon (hop) | On XPR: `wrap.alcor::transfer` → `bridge.alcor`, memo `hop.alcor:1:0x\|4057084141687023600:`; then `release` on that chain |
| Ethereum/BSC/Polygon → Vaulta (hop) | As to WAX, with memo `12439917377594391589:\|1:` |
| Vaulta → Ethereum/BSC/Polygon (hop) | On Vaulta: `wrap.alcor::transfer` → `bridge.alcor`, memo `hop.alcor:1:0x\|12439917377594391589:`; then `release` on that chain |
| Between WAX, XPR Network and Vaulta (hop) | On the source chain: `wrap.alcor::transfer` → `bridge.alcor`, memo `hop.alcor::\|:` — e.g. `hop.alcor:4057084141687023600:\|1181148696416462999:` for WAX → XPR |
| EVM → another EVM chain (hop) | `AlcorVault.deposit(...)` on the source chain with `telosTo` = `hop.alcor` and memo `:0x\|:` — e.g. `1:0x…\|56:0x…` for BSC → Ethereum; then `release` on the destination |
A withdrawal memo out of Telos is `:[:[:]]`; to WAX, XPR Network and Vaulta the fee is `0` (the operator relays), and the memo is what the payout carries.
Domains as the bridge spells them: Ethereum `1`, BSC `56`, Polygon `137`, WAX `1181148696416462999`, XPR Network `4057084141687023600`, Vaulta `12439917377594391589` (keep them strings — too large for a JS number). Amounts on Telos, WAX, XPR Network and Vaulta use the token's Antelope precision (USDC/USDT 6, ETH/BNB/POL/WAX 8, XPR and A 4). USDT on Ethereum: `approve(0)` before approving a new amount. Check that a WAX, XPR or Vaulta account exists before bridging to it.
### Cross-chain swaps (one signature)
Any token in, any token out: swap into a bridged asset on the source chain if needed, cross, and swap out of it on the destination. The destination swap is done by `route.alcor`. Everything below comes from `GET /v1/chains`: `swaps` on each source and `settlement.swaps` / `settlement.hopMemo` for Telos. `swaps: null` means the executor is not deployed there and that leg does not exist.
**Swap memo** — what `route.alcor` executes:
```
|@|
alice|403.5737 TLM@alien.worlds|1760300000
```
- `least out` is an asset as `swap.alcor` writes it (exact token precision) — the minimum the recipient must get; take it from the route API's `minReceived` for the destination swap.
- `deadline` is unix seconds, at most `swaps.memo.maxWait` (604800 s, 7 days) ahead. Leave room for the crossing: an hour or more.
- The recipient gets the token asked for, at least `least out`, or — if no route pays that before the deadline — the bridged token as it arrived. Nothing is sent back across the bridge. A memo the contract cannot read, a past deadline or an unknown token also pay out the token as it arrived; only a recipient that does not exist is refused (the crossing comes back like a refused withdrawal). Check the account exists first.
- The whole bridge memo must fit in `maxBytes` (256).
**Where the swap memo goes:**
| Route | What to send |
|---|---|
| Ethereum/BSC/Polygon → WAX, XPR Network or Vaulta | `AlcorVault.deposit(...)` with `telosTo` = `hop.alcor` and memo `:route.alcor\|:\|` |
| Ethereum/BSC/Polygon → Telos | `AlcorVault.deposit(...)` with `telosTo` = `route.alcor` and the swap memo as the deposit memo |
| Between WAX, XPR Network and Vaulta | On the source chain: transfer the bridged token to `bridge.alcor`, memo `hop.alcor::route.alcor\|:\|` |
| WAX, XPR Network or Vaulta → Telos | Transfer to `bridge.alcor`, memo `route.alcor:` |
| Telos → WAX, XPR Network or Vaulta | `wrap.alcor::transfer` → `bridge.alcor`, memo `:route.alcor:0:` |
From an Antelope chain, a swap into the bridged asset and the transfer into `bridge.alcor` go in **one transaction** (route API `transfers`, then the bridge transfer for the swap's `minReceived`): both land or neither does.
**Following it:** the transfer row (`/v1/transfers/{key}`) whose payout made the order, and a hop's journey (`/v1/hops/{key}`), carry `swap`: `status` (`swapping`, `swapped`, `unread`, `late`, `expired`, `cancelled`), `paid`, `summary` (ready to show, e.g. `delivered as 4033.1234 TLM`) and `id`.
**Taking it as it arrived:** while the order waits (`swapping` or `late`), the recipient can send `route.alcor::cancel { id }` on the destination chain and receive the bridged token instead.
**Swap at the start on an EVM chain** (e.g. ETH → USDC on Ethereum before depositing) goes through `AlcorRouter.swapAndDeposit` and `GET /v1/swap/quote`. The router is not deployed yet — the endpoint says so — so for now deposit a bridged asset (USDC, USDT, ETH, BNB, POL) as it is.
A destination swap needs liquidity for the bridged token on that chain. WAX has `wrap.alcor` pools (USDC, USDT, ETH, BNB, POL); on other chains, quote the destination swap with the route API before sending.
### Making a token cross-chain (for projects)
A token on WAX, XPR Network, Vaulta or Telos can be bought from any other network, and sold to any other network, once its own chain has liquidity between it and a bridged asset: the route swaps into that asset where the trip starts and out of it where it ends.
**USDC is the standard pair.** Create a pool ` / USDC@wrap.alcor` on Alcor on the token's own chain (`/v//swap/positions`) and keep real depth in it. USDC arrives on every network the same — Ethereum, BSC and Polygon lock into one `USDC@wrap.alcor` — so one USDC pool connects the token to every chain the bridge reaches, and every route meets in the same place. Pairs against other bridged assets (USDT, ETH, the chain's own coin) also route, but each extra pool on the way costs fees and depth.
Thin pools lose value: XPR for A through two pools on Telos holding $81 and $24 delivered about half of what was paid. The home page shows what is received in dollars next to what is paid, and asks to confirm a swap that loses more than 20%.
### Bridge API (read-only, no auth, CORS `*`)
Base: `https://telos.alcor.exchange/api/bridge`
| Endpoint | Use |
|---|---|
| `GET /v1/routes` | Every asset × chain pair: `open`, `reason`, `min`, `max`, `via` (hop) |
| `GET /v1/chains` | Chains, contracts, limits, fast-path caps, live `timing`, `swaps` (cross-chain swap executor and memo format per chain) |
| `GET /v1/transfers/{key}` | One crossing: `status`, `flags`, `progress.etaSeconds`, `hasProof`, `src_tx`/`dst_tx`, `swap` when it paid into `route.alcor` |
| `GET /v1/transfers?account=&address=&status=&limit=` | List of crossings, newest first |
| `GET /v1/hops?party={account or 0x}` / `GET /v1/hops/{deposit key}` | Hop journeys and their legs, with `swap` at the top when the hop ends in a swap |
| `GET /v1/swap/quote` | The swap half of `AlcorRouter.swapAndDeposit` for a swap at the EVM start (not deployed yet) |
| `GET /v1/pending?address=0x…&ready=true` | What is waiting for the user to sign |
| `GET /v1/proofs/{key}` | Ready-to-send proof arguments (`404` = not ready yet) |
| `GET /v1/accounts/{telos account}` | `claimable` balances on Telos |
Keys: `d::` for a deposit, `w:` for a withdrawal from Telos, `v:` for the rollback of a withdrawal. Statuses: deposit `seen → provable → credited` (or `parked → forwarded / bounced`); withdrawal `burned → provable → released` (or `expired → refunded`).
---
## Accounts & signing
- **Alcor Signer** (https://sign.alcor.exchange) — Alcor's passkey wallet for Antelope chains. The passkey key sits on the account's permissions; no seed phrase. Three signing levels: Passkey (device prompt per transaction), Fast sign (confirm in a window), Auto sign (no click).
- **Sign up with a passkey** on Telos (`/v/telos/signup`): creates a `.ac` account, opened and paid for by the first deposit.
- **Other wallets:** Anchor, WAX Cloud Wallet and WebAuth (XPR Network) on Antelope; MetaMask, Rabby and WalletConnect on EVM (for the bridge).
- **Free CPU on WAX:** Alcor co-signs Alcor transactions on WAX (see CPU Payer below).
---
## WharfKit SDK setup (Antelope chains)
```bash
npm install @wharfkit/session @wharfkit/contract @wharfkit/antelope @wharfkit/wallet-plugin-privatekey
```
```typescript
import { Session } from '@wharfkit/session'
import { ContractKit } from '@wharfkit/contract'
import { APIClient } from '@wharfkit/antelope'
import { WalletPluginPrivateKey } from '@wharfkit/wallet-plugin-privatekey'
// 1. API client for your chain
const client = new APIClient({ url: 'https://wax-api.alcor.exchange' })
// 2. Session (for signing transactions)
const session = new Session({
actor: 'myaccount',
permission: 'active',
chain: {
id: '1064487b3cd1a897ce03ae5b6a865651747e2e152090f99c1d19d44e01aea5a4', // WAX
url: 'https://wax-api.alcor.exchange',
},
walletPlugin: new WalletPluginPrivateKey('5K...'), // or any other wallet plugin
})
// 3. ContractKit (for reading tables, building actions)
const contractKit = new ContractKit({ client })
```
| Chain | Chain ID |
|---|---|
| WAX | `1064487b3cd1a897ce03ae5b6a865651747e2e152090f99c1d19d44e01aea5a4` |
| Telos | `4667b205c6838ef70ff7988f6e8257e8be0e1284a2f59699054a018f743b1d11` |
| XPR Network | `384da888112027f0321850a169f737c33e53b388aad48b5adace4bab97f437e0` |
| Vaulta (EOS) | `aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906` |
---
## Swap
Swaps are routed across AMM pools **and** orderbooks together, and an exact-input trade can be split between them. The route API returns the exact transfers to send.
> **Routing at scale — run your own indexer, don't hammer our API.** The route endpoint is for interactive, on-demand quotes. For bots, aggregators, backtesting or batch quoting, pull pool state from the on-chain `swap.alcor::pairs` table (or `GET /swap/pools`), follow updates, and compute routes locally with the official SDK (`@alcorexchange/alcor-swap-sdk`, https://github.com/alcorexchange/alcor-v2-sdk). It exposes `Pool`, `Route`, `Trade`, `Position`, `computeAllRoutes` / `getBestSwapRoute` (incl. a WASM route finder) and tick helpers (`TickMath`, `SqrtPriceMath`, `tickToPrice`, `priceToClosestTick`, `nearestUsableTick`). Reserve the route API for one-off quotes.
### Token ID formats
- **API format** (URLs and API calls): `symbol-contract`, lowercase — `wax-eosio.token`, `tlm-alien.worlds`, `usdt-wrap.alcor`, `xusdt-xtokens`
- **Key format:** `contract:SYMBOL` — `eosio.token:WAX`, `wrap.alcor:USDT`
### Pool fee tiers
| Fee | Use case |
|---|---|
| 0.01% | Pegged pairs (one stablecoin against another, a token against its wrapped copy) |
| 0.05% | Stable / correlated pairs |
| 0.3% | Standard pairs |
| 1% | Exotic / volatile pairs |
### Get a route (v3)
```
GET https://{chain}.alcor.exchange/api/v3/swapRouter/getRoute
```
Hosts: `wax.alcor.exchange`, `telos.alcor.exchange`, `proton.alcor.exchange`, `eos.alcor.exchange`.
| Param | Description |
|---|---|
| `tradeType` | `exactIn` or `exactOut` |
| `input` | Input token, API format (`wax-eosio.token`) |
| `output` | Output token, API format (`usdt-wrap.alcor`) |
| `amount` | Amount as a decimal string |
| `slippage` | Tolerance in percent, e.g. `0.5` |
| `maxHops` | (optional) Max hops per route |
| `orderbook` | (optional) `false` to route through the AMM only. Exact-output stays on the AMM regardless |
Example:
```
GET https://wax.alcor.exchange/api/v3/swapRouter/getRoute?tradeType=exactIn&input=wax-eosio.token&output=usdt-wrap.alcor&amount=100&slippage=0.5
```
```json
{
"tradeType": "exactIn",
"input": { "id": "wax-eosio.token", "symbol": "WAX", "contract": "eosio.token", "decimals": 8, "amount": "100.00000000" },
"output": { "id": "usdt-wrap.alcor", "symbol": "USDT", "contract": "wrap.alcor", "decimals": 6, "amount": "0.621850" },
"minReceived": "0.618756",
"maxSent": "100.00000000",
"priceImpact": "0.3",
"routes": [
{ "percent": 100, "input": "100.00000000", "output": "0.621850",
"hops": [{ "venue": "amm", "pool": 12405, "input": "wax-eosio.token", "output": "usdt-wrap.alcor", "fee": "0.3" }] }
],
"transfers": [
{ "tokenContract": "eosio.token", "to": "swap.alcor", "quantity": "100.00000000 WAX",
"memo": "swapexactin#12405##0.618756 USDT@wrap.alcor#0" }
]
}
```
`transfers` is what to send, in order, in **one transaction**. Memos contain the `` placeholder: replace it with the receiving account. Send each transfer to the `to` it names (it is not always `swap.alcor` when the route uses an orderbook).
### Execute a swap (cleos)
```bash
cleos -u https://wax-api.alcor.exchange push action eosio.token transfer \
'["myaccount","swap.alcor","100.00000000 WAX","swapexactin#12405#myaccount#0.618756 USDT@wrap.alcor#0"]' \
-p myaccount@active
```
### Execute a swap (WharfKit)
```typescript
const params = new URLSearchParams({
tradeType: 'exactIn',
input: 'wax-eosio.token',
output: 'usdt-wrap.alcor',
amount: '100',
slippage: '0.5',
})
const route = await fetch(`https://wax.alcor.exchange/api/v3/swapRouter/getRoute?${params}`)
.then(r => r.json())
const account = String(session.actor)
const result = await session.transact({
actions: route.transfers.map((t) => ({
account: t.tokenContract,
name: 'transfer',
authorization: [session.permissionLevel],
data: {
from: account,
to: t.to,
quantity: t.quantity,
memo: t.memo.replaceAll('', account),
},
})),
})
```
The v2 router (`GET {apiUrl}/swapRouter/getRoute?trade_type=EXACT_INPUT&input=…&output=…&amount=…&slippage=…&v2=true&receiver=…`) still answers but routes through the AMM only. Prefer v3.
### Token list & candles
```
GET {apiUrl}/tokens
GET {apiUrl}/swap/candles?tokenA={id}&tokenB={id}&resolution={1m|5m|15m|1h|4h|1d}&from={ms}&to={ms}&limit={n}
```
---
## Liquidity (AMM)
Concentrated liquidity, like Uniswap v3: a position has a tick range (`tickLower`, `tickUpper`) and earns fees while the price is inside it. Contract: `swap.alcor` on every chain.
### Add liquidity (WharfKit)
Three actions in one transaction: deposit token A, deposit token B, `addliquid`.
```typescript
const poolId = 5 // pool id from GET /swap/pools
const owner = String(session.actor)
await session.transact({
actions: [
{
account: 'eosio.token', // tokenA contract
name: 'transfer',
authorization: [session.permissionLevel],
data: { from: owner, to: 'swap.alcor', quantity: '100.00000000 WAX', memo: 'deposit' },
},
{
account: 'wrap.alcor', // tokenB contract
name: 'transfer',
authorization: [session.permissionLevel],
data: { from: owner, to: 'swap.alcor', quantity: '50.000000 USDT', memo: 'deposit' },
},
{
account: 'swap.alcor',
name: 'addliquid',
authorization: [session.permissionLevel],
data: {
poolId,
owner,
tokenADesired: '100.00000000 WAX',
tokenBDesired: '50.000000 USDT',
tickLower: -100,
tickUpper: 100,
tokenAMin: '99.00000000 WAX', // slippage-adjusted minimum
tokenBMin: '49.500000 USDT',
deadline: 0,
},
},
],
})
```
> Find the current tick with `GET {apiUrl}/swap/pools/{id}`. A tighter range is more capital-efficient but goes out of range sooner.
### Remove liquidity / collect fees (WharfKit)
`subliquid` removes liquidity; `collect` withdraws the tokens and accrued fees. `subliquid` with `liquidity: 0` followed by `collect` collects fees only.
```typescript
const owner = String(session.actor)
await session.transact({
actions: [
{
account: 'swap.alcor',
name: 'subliquid',
authorization: [session.permissionLevel],
data: {
poolId: 5,
owner,
liquidity: '1000000000', // position liquidity to remove; 0 = fees only
tickLower: -100,
tickUpper: 100,
tokenAMin: '0.00000000 WAX',
tokenBMin: '0.000000 USDT',
deadline: 0,
},
},
{
account: 'swap.alcor',
name: 'collect',
authorization: [session.permissionLevel],
data: {
poolId: 5,
owner,
recipient: owner,
tickLower: -100,
tickUpper: 100,
tokenAMax: '0.00000000 WAX', // zero assets = collect everything owed
tokenBMax: '0.000000 USDT',
},
},
],
})
```
### Farms
Pools can have incentives (farms) that pay extra tokens to staked positions. Farms live in the `incentives` table of `swap.alcor`. New positions in the app are staked into the pool's farms automatically (a setting the user can turn off).
| Action on `swap.alcor` | Data | Purpose |
|---|---|---|
| `stake` | `{ incentiveId, posId }` | Stake a position into a farm |
| `unstake` | `{ incentiveId, posId }` | Unstake it |
| `getreward` | `{ incentiveId, posId }` | Claim farm rewards |
Any number of `(incentiveId, posId)` pairs can go in one transaction.
### Position data
```typescript
// Alcor API
const positions = await fetch('https://wax.alcor.exchange/api/v2/account/myaccount/positions')
.then(r => r.json())
// On-chain pool state (ContractKit)
const swap = await contractKit.load('swap.alcor')
const pool = await swap.table('pairs', 'swap.alcor').get(5)
console.log('Current tick:', pool.currSlot, 'Liquidity:', pool.liquidity)
```
---
## Spot orderbook
Orders are placed with a `transfer` on the **token contract** to the DEX contract; there is no separate "place order" action. The memo is the amount you want to receive.
DEX contract per chain: `alcordexmain` (WAX), `alcor` (XPR Network), `eostokensdex` (Telos, Vaulta). On Vaulta `alcordexmain` is a plain account, not the DEX — never send orders there.
### Memo format
```
{amount} {SYMBOL}@{contract}
```
- **Limit order:** desired output amount (`price × size` in quote for a sell, `size` in base for a buy)
- **Market order:** amount `0` — fills at the best available price
### cleos examples (WAX)
```bash
# Limit BUY 100 TLM at 0.0008 WAX: send 0.08 WAX, want 100 TLM
cleos -u https://wax-api.alcor.exchange push action eosio.token transfer \
'["myaccount","alcordexmain","0.08000000 WAX","100.0000 TLM@alien.worlds"]' -p myaccount@active
# Limit SELL 100 TLM at 0.0008 WAX: send 100 TLM, want 0.08 WAX
cleos -u https://wax-api.alcor.exchange push action alien.worlds transfer \
'["myaccount","alcordexmain","100.0000 TLM","0.08000000 WAX@eosio.token"]' -p myaccount@active
# Market BUY (memo amount 0)
cleos -u https://wax-api.alcor.exchange push action eosio.token transfer \
'["myaccount","alcordexmain","0.08000000 WAX","0.0000 TLM@alien.worlds"]' -p myaccount@active
# Cancel
cleos -u https://wax-api.alcor.exchange push action alcordexmain cancelbuy \
'{"executor":"myaccount","market_id":99,"order_id":12345}' -p myaccount@active
cleos -u https://wax-api.alcor.exchange push action alcordexmain cancelsell \
'{"executor":"myaccount","market_id":99,"order_id":12345}' -p myaccount@active
```
Amounts are Antelope assets with the token's exact precision: `"N.DDDD SYMBOL"` (WAX 8, TLM 4, USDT 6).
### WharfKit
```typescript
const dex = 'alcordexmain' // 'alcor' on XPR, 'eostokensdex' on Telos and Vaulta
// Limit BUY: send quote, memo = desired base
await session.transact({
action: {
account: 'eosio.token',
name: 'transfer',
authorization: [session.permissionLevel],
data: { from: session.actor, to: dex, quantity: '0.08000000 WAX', memo: '100.0000 TLM@alien.worlds' },
},
})
// Cancel several orders in one transaction
const orders = [
{ side: 'buy', market_id: 99, order_id: 111 },
{ side: 'sell', market_id: 99, order_id: 333 },
]
await session.transact({
actions: orders.map(o => ({
account: dex,
name: o.side === 'buy' ? 'cancelbuy' : 'cancelsell',
authorization: [session.permissionLevel],
data: { executor: String(session.actor), market_id: o.market_id, order_id: o.order_id },
})),
})
```
### Orderbook on chain
- `{dex}::markets` (scope `{dex}`) — all markets: `id`, `base_token`, `quote_token`, `min_buy`, `min_sell`, `fee`
- `{dex}::buyorder` / `{dex}::sellorder` (scope = market id) — open orders: `id`, `account`, `bid`, `ask`, `unit_price`, `timestamp`; secondary index `byaccount`
---
## Alcor REST API
Reference: https://docs.alcor.exchange/api
`{apiUrl}` per chain: `https://wax.alcor.exchange/api/v2`, `https://telos.alcor.exchange/api/v2`, `https://proton.alcor.exchange/api/v2`, `https://eos.alcor.exchange/api/v2`.
### Tokens
| Endpoint | Description |
|---|---|
| `GET {apiUrl}/tokens` | All tokens with decimals, USD prices, metadata |
| `GET {apiUrl}/tokens/{token_id}` | One token (`wax-eosio.token`) |
| `GET {apiUrl}/tokens/{token_id}/logo` | Token logo |
### Swap (AMM)
| Endpoint | Description |
|---|---|
| `GET {apiUrl}/swap/pools` | All pools with TVL, volume, fees |
| `GET {apiUrl}/swap/pools/{pool_id}` | One pool |
| `GET {apiUrl}/swap/pools/{pool_id}/swaps` | Swap history. Params: `from`, `to`, `recipient`, `sender`, `limit`, `skip` |
| `GET {apiUrl}/swap/pools/{pool_id}/positions` | LP positions in a pool |
| `GET {apiUrl}/swap/candles` | Candles for a pair. Params: `tokenA`, `tokenB`, `resolution`, `from`, `to`, `limit` |
| `GET https://{chain}.alcor.exchange/api/v3/swapRouter/getRoute` | Best route over AMM + orderbooks (see Swap) |
### Spot orderbook
| Endpoint | Description |
|---|---|
| `GET {apiUrl}/markets` | All markets |
| `GET {apiUrl}/markets/{id}` | One market (tokens, price, 24h volume) |
| `GET {apiUrl}/markets/{id}/deals` | Recent trades. Params: `limit` |
| `GET {apiUrl}/markets/{id}/charts` | Candles. Params: `resolution` (1/5/15/30/60/240/1440), `from`, `to`, `limit` |
| `GET {apiUrl}/markets/{id}/orderbook` | Bids and asks. Params: `depth` |
| `GET {apiUrl}/markets/{id}/orders` | Open orders. Params: `account` |
### Tickers (CoinGecko-compatible)
| Endpoint | Description |
|---|---|
| `GET {apiUrl}/pairs` | All pairs. Params: `base`, `target` |
| `GET {apiUrl}/tickers` | All tickers with 24h stats |
| `GET {apiUrl}/tickers/{ticker_id}` | One ticker |
| `GET {apiUrl}/tickers/{ticker_id}/orderbook` | `[price, quantity][]`. Params: `depth` |
| `GET {apiUrl}/tickers/{ticker_id}/latest_trades` | Recent trades. Params: `limit` |
| `GET {apiUrl}/tickers/{ticker_id}/historical_trades` | Params: `type`, `limit`, `step`, `from`, `to` |
| `GET {apiUrl}/tickers/{ticker_id}/charts` | Candles. Params: `resolution`, `from`, `to`, `limit` |
### Account
| Endpoint | Description |
|---|---|
| `GET {apiUrl}/account/{account}/deals` | Spot trade history. Params: `from`, `to`, `limit`, `skip`, `market` |
| `GET {apiUrl}/account/{account}/positions` | LP positions with fees, value, P&L |
| `GET {apiUrl}/account/{account}/positions-history` | Position history. Params: `limit`, `skip` |
| `GET {apiUrl}/account/{account}/swap-history` | Swap history. Params: `limit`, `skip` |
### Analytics
| Endpoint | Description |
|---|---|
| `GET {apiUrl}/analytics/global` | TVL, volume, fees, users. Params: `resolution` (1D/1W/1M) |
### CPU Payer (WAX only)
Free CPU for Alcor transactions on WAX. Limits: 500/hour per IP, 300/hour per account.
| Endpoint | Description |
|---|---|
| `POST https://wax.alcor.exchange/api/v2/cpu/status` | Availability |
| `POST https://wax.alcor.exchange/api/v2/cpu/cosign` | Co-sign a transaction. Body: `{ "serializedTransaction": "hex..." }` |
Covered contracts: `alcordexmain`, `swap.alcor`, `otc.alcor`, `alcorotcswap`, `liquid.alcor`.
### WebSocket (Socket.IO)
Connect to `https://alcor.exchange` with Socket.IO.
```javascript
socket.emit('subscribe', { room: 'deals', params: { chain: 'wax', market: 99 } })
socket.on('new_deals', (deals) => { /* { time, ask, bid, type, unit_price, trx_id } */ })
socket.emit('subscribe', { room: 'orderbook', params: { chain: 'wax', market: 99, side: 'buy' } })
socket.on('orderbook_buy', (rows) => { /* [[price, quantity, accumulated], ...] */ })
socket.emit('subscribe', { room: 'account', params: { chain: 'wax', name: 'myaccount' } })
```
---
## Liquid staking (WAX)
Stake WAX into `liquid.alcor` and receive LSW (`lsw.alcor`, 8 decimals), a liquid token that earns WAX staking rewards and stays tradeable. The portfolio also shows and claims WAX voting rewards. UI: https://alcor.exchange/v/wax/staking
## OTC
Peer-to-peer fixed-price swaps for large trades without slippage.
| Chain | Contract |
|---|---|
| WAX | `alcorotcswap` |
| Telos | `alcorotcswap` |
| XPR Network | `alcorotc` |
| Vaulta (EOS) | `alcorotcswap` |