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 status
The current package is published for testnet-only integration under exchange-testnet-v0.5.221. Do not present it as mainnet-ready or accept mainnet LICN deposits until the mainnet launch exchange handoff passes, the readiness gate is rerun with full scope, and a signed mainnet-inclusive package is published.

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.

Text
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_spores from 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.

  1. Generate or allocate a native account for the user.
  2. Persist the user-to-address assignment before displaying the address.
  3. Poll getTransactionsByAddress for the deposit address; WebSocket slot events may wake the poller but do not replace archive-backed reconciliation.
  4. Fetch every candidate transaction with getTransaction.
  5. Confirm that the transaction transfers native LICN to the assigned address.
  6. Require confirmation_status = "finalized" plus the configured operational buffer.
  7. Credit raw spores exactly once using the transaction hash and credited account as the idempotency key.
  8. Reconcile address balance, credited deposits, pending sweeps, and hot/cold balances.
Validated flow
The deposit, credit, sweep, withdrawal, retry, and reconciliation flow passed in the local three-validator exchange simulation and in the public faucet-backed testnet simulation after the signed 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.

  1. Validate the destination as a native Base58 address decoding to exactly 32 bytes.
  2. Convert the requested withdrawal amount to spores before transaction construction.
  3. Check hot-wallet spendable balance in spores.
  4. Build and sign a native transfer transaction with the target native chain ID.
  5. Submit through canonical sendTransaction.
  6. Persist the returned native transaction hash before any retry.
  7. Poll getTransaction until finalized plus buffer.
  8. Mark the withdrawal complete once, then reconcile the hot wallet, ledger, and fee spend.
Retry policy
After signing and submitting a withdrawal, do not blindly create a replacement withdrawal. Poll the recorded hash through 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 getTransaction reports confirmation_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, and getAccountTxCount.
  • 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
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
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
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
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
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
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.

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