Exchange Integration
Native LICN exchange integration is published for testnet-only integration testing under exchange-testnet-v0.5.221. This page is the exchange-facing portal version of the package: metadata, address handling, deposits, withdrawals, finality, archive expectations, operations contacts, and validation gates are documented here directly. GitHub remains the immutable source and audit trail.
Testnet Package
The current exchange package is for native LICN testing on lichen-testnet-1. It is
intended for exchange engineering, wallet/custody integration, deposit/withdrawal rehearsal,
archive/history verification, and reconciliation testing before mainnet launch.
| Item | Value |
|---|---|
| Package tag | exchange-testnet-v0.5.221 |
| Package release | GitHub release |
| Current rollback anchor | v0.5.223 |
| Scope | Testnet-only until the mainnet launch exchange handoff and full-scope readiness gate pass. |
| Final readiness gate | python3 scripts/qa/exchange_public_readiness.py --scope testnet --status-approved --release-tag-selected |
Exchange Chain Metadata
| Field | Current value |
|---|---|
| Chain name | Lichen |
| Native asset / ticker | LICN |
| Base unit | spore |
| Decimals | 9; 1 LICN = 1,000,000,000 spores |
| Fee unit | Native LICN spores; runtime fee values must be read through getFeeConfig. |
| Native testnet chain ID | lichen-testnet-1 |
| Native mainnet chain ID | lichen-mainnet-1; launch placeholder, excluded from this package. |
| EVM compatibility chain ID | Query /evm eth_chainId at runtime. Public testnet currently
returns 0xca3f1595a6c25e9f. Do not use 8001 for native LICN
deposit or withdrawal signing. |
| Testnet RPC / WebSocket | https://testnet-api.lichen.network /
wss://testnet-api.lichen.network/ws |
| Mainnet RPC / WebSocket | https://rpc.lichen.network /
wss://rpc.lichen.network/ws; launch placeholders until mainnet handoff. |
| Explorer | https://explorer.lichen.network |
| Logo URL | https://lichen.network/Lichen_Logo_256.png |
Addressing And Accounting
Native Address Rule
Native LICN deposit addresses are Base58 strings encoding exactly 32 bytes. A regex is only a
prefilter; production validation must Base58-decode and reject any decoded length other than
32 bytes. EVM-format 0x... addresses are mappings, not native deposit addresses.
prefilter: ^[1-9A-HJ-NP-Za-km-z]{32,44}$
valid_native_address(address):
if not matches(address, "^[1-9A-HJ-NP-Za-km-z]{32,44}$"):
return false
decoded = base58_decode(address)
return len(decoded) == 32
Exchange Accounting Rule
Store balances, credits, debits, and fees as raw integer spores. Formatted LICN strings in RPC responses are display-only and must not drive the exchange ledger.
- Credit amount: exact
amount_sporesfrom transaction or history data. - Debit amount: exact withdrawal spores plus exact fee spores.
- Idempotency key: native transaction hash plus credited account or withdrawal id.
- JavaScript SDK is not approved for exchange accounting until lossless u64 parsing is used.
Deposit Cookbook
The recommended model is one native Lichen address per exchange user or account allocation. Native LICN base transfers do not require a memo or tag. If pooled deposit addresses are used, user attribution is an exchange-owned off-chain ledger responsibility.
- Generate or allocate a native account for the user.
- Persist the user-to-address assignment before displaying the address.
- Poll
getTransactionsByAddressfor the deposit address; WebSocket slot events may wake the poller but do not replace archive-backed reconciliation. - Fetch every candidate transaction with
getTransaction. - Confirm that the transaction transfers native LICN to the assigned address.
- Require
confirmation_status = "finalized"plus the configured operational buffer. - Credit raw spores exactly once using the transaction hash and credited account as the idempotency key.
- Reconcile address balance, credited deposits, pending sweeps, and hot/cold balances.
v0.5.221 recovery rollout. Public exchange readiness was revalidated after the
signed v0.5.224 archive-parity rollout.
Withdrawal Cookbook
Use a cold wallet for the majority reserve, a limited hot wallet for normal withdrawals, and deposit wallets that sweep according to the exchange custody policy.
- Validate the destination as a native Base58 address decoding to exactly 32 bytes.
- Convert the requested withdrawal amount to spores before transaction construction.
- Check hot-wallet spendable balance in spores.
- Build and sign a native transfer transaction with the target native chain ID.
- Submit through canonical
sendTransaction. - Persist the returned native transaction hash before any retry.
- Poll
getTransactionuntil finalized plus buffer. - Mark the withdrawal complete once, then reconcile the hot wallet, ledger, and fee spend.
getTransaction and account history first. Escalate to manual
review if the hash remains unavailable beyond the exchange timeout policy.
Finality And Archive
Confirmation Policy
Lichen finality is deterministic under the active BFT commitment model. Exchanges must still apply an operational buffer to cover endpoint lag, archive lag, monitoring delay, and internal retry races.
- Standard policy: credit after
getTransactionreportsconfirmation_status = "finalized"and current finalized slot is at least transaction slot plus 8. - High-value policy: require finalized slot at least transaction slot plus 32 or manual review.
Archive Requirement
Exchange integrations must use archive-backed RPC. A pruned or state-only endpoint is not acceptable because exchanges need old transaction and account-history data for replay, reconciliation after outages, withdrawal proof, support, and audits.
- Required methods:
getBlock,getLatestBlock,getTransaction,getTransactionsByAddress, andgetAccountTxCount. - Hot/cold archive behavior is regression-tested after migration and reopen at storage and RPC boundaries.
- A new validator must be able to sync and serve complete history when configured as an archive-backed exchange endpoint.
Canonical JSON-RPC Cookbook
All examples use the canonical JSON-RPC route at / and public testnet endpoint.
Get Finalized Slot
curl -s https://testnet-api.lichen.network \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"getSlot","params":[{"commitment":"finalized"}]}'
Get Runtime Fee Config
curl -s https://testnet-api.lichen.network \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"getFeeConfig","params":[]}'
Get Balance
Use spores and spendable for accounting.
curl -s https://testnet-api.lichen.network \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"getBalance","params":["<native_base58_address>"]}'
Get Transaction
curl -s https://testnet-api.lichen.network \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"getTransaction","params":["<tx_hash_hex>"]}'
Get Address History
Pagination uses next_before_slot with before_slot.
curl -s https://testnet-api.lichen.network \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"getTransactionsByAddress","params":["<native_base58_address>",{"limit":100}]}'
Broadcast Native Transaction
curl -s https://testnet-api.lichen.network \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"sendTransaction","params":["<base64_signed_native_transaction>"]}'
Operations
| Surface | Exchange-facing value |
|---|---|
| Status page | https://exchanges.lichen.network. Dedicated exchange status/operations
page with only exchange-safe health, incidents, maintenance, and contact information.
Internal monitoring is admin-only and must not be published in exchange materials. |
| Security incidents | security@lichen.network |
| Exchange operations | exchange-ops@lichen.network |
| Business/listing | business@lichen.network |
| Critical acknowledgement target | Within 1 hour for deposit, withdrawal, RPC/WebSocket, archive, finality, signing, key, custody, or fund-safety impact. |
| Active incident updates | Status-page update at acknowledgement and at least every 2 hours until mitigation or resolution. |
| Planned maintenance | Target 72 hours notice; 24 hours minimum where operationally possible. Emergency security releases may use shorter notice with immediate status publication. |
| Release verification | Use GitHub release assets, SHA256SUMS, SHA256SUMS.sig, and
signer 8HitBNnh8qbhfne5NCv2yHrQFoD6xbmHcWaUSgCGtsk. |
Validation Gates
- Keep address validation vectors passing before publishing or changing a regex.
- Keep deterministic finality plus the selected exchange buffer validated on a local three-validator testnet.
- Keep archive-backed getTransaction, getBlock, and address history covered across hot/cold data and restart.
- Keep the deposit, credit, sweep, withdrawal, retry, and reconciliation simulation passing locally.
- Clean up every local stack run and prove validator, custody, faucet, and source-chain mock processes are stopped.
- Keep the public testnet exchange simulation evidence attached to the signed recovery release.
- Keep the published exchange package tag, public developer page, and testnet-scope readiness gate aligned before outreach.
- Do not publish a mainnet package until the mainnet launch exchange handoff and full-scope readiness gate pass.
Mainnet Handoff
Mainnet is not live and is excluded from this exchange package. Before any mainnet exchange package
exists, the mainnet launch runbook must close the exchange handoff gate, public mainnet RPC and
WebSocket endpoints must pass readiness, archive/history must be verified on mainnet, a dust
deposit/withdrawal flow must pass, and the public readiness gate must be rerun with
--scope full.
python3 scripts/qa/exchange_public_readiness.py --scope full --status-approved --release-tag-selected
Source And Artifacts
The portal carries the reviewer-facing content directly. The release-tagged GitHub links below are retained as source, checksum, and audit references.
Exchange Integration Guide
Full source guide for deposit, withdrawal, polling, retry, finality, archive, and reconciliation.
Exchange Chain Metadata
Exchange metadata sheet with source mapping and deferred mainnet rows.
Address Validation Vectors
Native Base58 validation vectors and invalid cases.
Exchange Operations Pack
Status page, contacts, upgrade policy, rollback policy, release signatures, and archive policy.
Readiness Tracker
Gate status, source map, evidence, and execution record.