Exchange integration
This guide is written for exchange engineers who list ELA and operate hot wallets, deposit scanners, and withdrawal pipelines. Elastos is not Bitcoin-compatible on the main chain: curve choice, address encoding, and transaction signing differ from secp256k1 chains.
1. Overview
Two integration paths
| Path | Model | Signing curve | Typical stack |
|---|---|---|---|
| ELA main chain | UTXO | NIST P-256 (secp256r1) | Elastos Wallet JS SDK, Keypair SDKs, or native libraries with P-256 |
| ESC (Elastos Smart Contract chain) | Account / EVM | secp256k1 | web3.js, ethers.js, standard Ethereum tooling |
The ELA main chain uses P-256 for ECDSA on standard transfer inputs. Bitcoin or Ethereum libraries that assume secp256k1 cannot generate valid main-chain addresses or signatures. Use Elastos SDKs or implementations that explicitly support P-256 and the Elastos transaction format.
ESC uses chain ID 20 on mainnet and standard Ethereum transaction encoding. Existing EVM integration (nonce, gas, eth_sendRawTransaction, contract ABIs) applies unchanged for native ELA on ESC and ERC-style assets.
- Main Chain (UTXO)
- Smart Chain (EVM)
2. ELA main chain integration (UTXO)
2.1 Address generation
Recommended libraries
- Elastos.ELA.Wallet.JS.SDK (primary TypeScript SDK):
@elastosfoundation/wallet-js-sdk(see Elastos wallet SDK ecosystem). - Elastos.SDK.Keypair.Javascript (lightweight):
elastos-wallet-jsfor keys, addresses, and basic tx helpers.
HD derivation (main-chain ELA)
- BIP39 mnemonic → seed.
- BIP32 / BIP44 account path:
m/44'/0'/0'for Elastos UTXO (P-256 context). External / internal chains followm/44'/0'/0'/{0|1}/{index}(receiving vs change). - Child key derivation uses the P-256 curve order (not secp256k1), even though BIP32 structure mirrors Bitcoin.
Address encoding
- Public key is hashed (SHA-256 then RIPEMD-160) from the redeem script (compressed pubkey + sign type).
- The program hash is 21 bytes: a prefix byte plus 20-byte hash. Standard ELA addresses use prefix
0x21for the standard program type (distinct from the0x21push-byte inside the redeem script in documentation diagrams). - Encoding is Base58Check (double SHA-256 checksum). Standard single-sig addresses start with
E. Multi-sig addresses start with8, node deposit addresses withD, and staking addresses withSN.
Standard Bitcoin stacks derive secp256k1 keys at m/44'/0'/0' and encode P2PKH-style addresses. Those keys and addresses are not valid on Elastos main chain. Treat Elastos as a separate coin type with its own implementations.
TypeScript example (conceptual flow)
The SDK wires MainchainSubWallet for ELA. The following illustrates the shape of integration: mnemonic, master wallet, and main-chain sub-wallet. Adjust imports and constructors to match the version you pin.
// Example pattern — align with typings in @elastosfoundation/wallet-js-sdk (MasterWalletManager.create, etc.).
import { MasterWalletManager } from "@elastosfoundation/wallet-js-sdk";
async function exampleCreateElaWatchingWallet(
storage: Parameters<typeof MasterWalletManager.create>[0],
netType: string,
config: Parameters<typeof MasterWalletManager.create>[2]
) {
const manager = await MasterWalletManager.create(storage, netType, config);
const mnemonic = "your twelve or twenty four words ...";
const master = await manager.createMasterWallet(
"exchange-wallet",
mnemonic,
"",
"pay-password",
false
);
const elaSub = await master.createSubWallet("ELA"); // MainchainSubWallet: P-256 / m/44'/0'/0'
// First external receiving address (see getAddresses in ElastosBaseSubWallet typings)
const [depositAddress] = elaSub.getAddresses(0, 1, false);
return { depositAddress };
}
For read-only deposit scanning, use the SDK’s support for xpub-style accounts where exposed: extended public keys for P-256 must come from Elastos tooling, not from Bitcoin xpubs.
2.2 Deposit detection
JSON-RPC
- Default HTTP JSON-RPC port for the ELA node:
20336(seeservers/httpjsonrpc/ deployment docs). - Prefer localhost or VPN-linked nodes; see Security.
Useful RPC methods
| Method | Role |
|---|---|
getreceivedbyaddress | Total amount received by an address (for reconciliation). |
listunspent | List UTXOs for given addresses (for custody and withdrawal selection). |
getrawtransaction | Fetch a transaction by hash; use verbose mode for JSON detail. |
getblockcount / getbestblockhash / getblock | Chain tip and block contents. |
getrawmempool | Pending transactions (node exposes this as the transaction pool; maps to GetTransactionPool in the node). |
Confirmations
- Blocks are produced on a two-minute target interval (
TargetTimePerBlockin chain parameters). - BPoS provides strong block-level finality once a block is agreed; for operations policy, many services still require 6+ confirmations before crediting deposits to match risk appetite.
- Coinbase maturity: coinbase outputs are spendable only after
CoinbaseMaturity = 100blocks (~200 minutes at target time), percommon/configeconomic parameters.
The JSON-RPC method that lists pending transactions is getrawmempool. Older internal docs sometimes say “transaction pool”; that is the same data path as GetTransactionPool in the node implementation.
2.3 Withdrawal processing
UTXO workflow
- Query
listunspent(or your index) for spendable outputs to hot-wallet addresses. - Select inputs, compute outputs (recipient + change), and attach
TransferAssetpayload. - Sign each input with P-256 ECDSA over SHA-256 of the unsigned serialization (see transaction model in Elastos sources).
- Broadcast
sendrawtransactionwith the raw hex.
Transaction type
TransferAsset=0x02(payload discriminator for standard ELA transfers).
Fees
MinTransactionFee = 100sela = 0.000001 ELA (8 decimals; 1 ELA =100_000_000sela). This is the protocol-enforced minimum; in practice, wallets and SDKs typically use 10,000 sela (0.0001 ELA) as the standard fee for reliable inclusion.- The mempool prioritizes by fee per kilobyte (
FeePerKB). Larger serialized transactions need proportionally higher total fees to compete for inclusion.
Signing
- Use Elastos SDKs (
EcdsaSignerwith P-256 in Wallet JS SDK) or audited code paths that match the node’s script and signature encoding. - Never sign main-chain txs with Bitcoin secp256k1 stacks.
TypeScript example (high-level)
// Conceptual steps — use MainchainSubWallet + Transaction from the SDK.
// 1) Fetch UTXOs via your node's listunspent / indexer.
// 2) Build unsigned tx: TransferAsset (0x02), outputs, change to internal address.
// 3) subWallet.signTransaction(tx, payPassword) // P-256 ECDSA per input
// 4) rpc.sendrawtransaction(tx.serialize().toString("hex"))
import type { UTXOInput } from "@elastosfoundation/wallet-js-sdk";
async function buildWithdrawal(
utxos: UTXOInput[],
toAddress: string,
amountSela: bigint,
changeAddress: string
) {
void utxos;
void toAddress;
void amountSela;
void changeAddress;
// Implement using SDK Wallet.createTransaction / MainchainSubWallet helpers.
}
2.4 Key RPC methods for exchanges
| Method | Description |
|---|---|
getblockcount | Current block height. |
getblockhash | Block hash for a height. |
getblock | Full block by hash (includes tx ids / raw per verbosity). |
getrawtransaction | Transaction by hash (verbose JSON or hex). |
listunspent | UTXOs for one or more addresses. |
getreceivedbyaddress | Total received by address. |
sendrawtransaction | Broadcast a signed raw transaction. |
getbestblockhash | Best chain tip hash. |
getrawmempool | Pending transactions in the mempool. |
Additional wallet-style helpers (when enabled on the node): createrawtransaction, signrawtransactionwithkey, getbalancebyaddr, getutxosbyamount, estimatesmartfee.
3. ESC sidechain integration (EVM)
ESC is an Ethereum-compatible sidechain: same RPC surface as go-ethereum style clients for eth_*, net_*, web3_*, and pbft_* where exposed.
| Item | Value |
|---|---|
| Chain ID | 20 (mainnet) |
| Default JSON-RPC port | 20636 (typical node deployment) |
| Public HTTPS (convenience) | https://api.elastos.io/esc (mainnet), https://api-testnet.elastos.io/esc (testnet) |
| Explorer | https://esc.elastos.io |
Use eth_getBalance, eth_sendRawTransaction, eth_getTransactionReceipt, eth_blockNumber, and the usual subscription filters. Balance and amount fields follow EVM integer semantics (wei-style precision on the RPC). Main-chain ELA remains 8 decimals (sela); do not mix units between rails without conversion logic.
ESC consensus uses PBFT-style finality in the Elastos geth fork: produced blocks are treated as final for practical purposes (no deep PoW-style reorgs as on ETH mainnet). Still run your own nodes or trusted RPC for production.
4. ELA cross-chain deposits (main chain → ESC)
Users can hold ELA on the main chain or ELA on ESC. An exchange should treat these as separate deposit rails:
- Main chain: Base58 ELA addresses (
E...). - ESC:
0xhex addresses (same as Ethereum).
Mechanism
- Cross-chain transfers that move ELA toward sidechains use payload type
TransferCrossChainAsset=0x08, with versioned payloads (TransferCrossChainVersion/TransferCrossChainVersionV1) describing outputs, indexes, and cross-chain destinations.
Economics (from chain parameters)
MinCrossChainTxFee = 10000sela = 0.0001 ELA minimum cross-chain fee.- 1:1 exchange rate between main-chain ELA and ESC ELA at the protocol level (sidechain params use a unit exchange rate; amounts are converted in sela with fixed-point rules in the node).
A deposit to an ESC 0x address must be detected via ESC RPC and chain ID 20. A deposit to a main-chain E address must be detected via ELA UTXO RPC. Do not assume both appear in one indexer without explicit support.
5. Security considerations
- Main chain (BPoS): Blocks include BPoS confirmation data (
getconfirmbyheight/getconfirmbyhash). For policy, consider waiting until confirmations include sufficient arbiter agreement for your risk model (often described as supermajority participation among the active arbiter set). - ESC (PBFT): Treat one included transaction receipt as final for hot-wallet policy unless your security team requires extra headroom.
- Key storage: P-256 private keys for main-chain hot wallets must live in HSM / KMS or hardened signing services designed for non-secp256k1 curves where applicable.
- Network: Do not expose 20336 (ELA RPC) or 20636 (ESC RPC) on the public internet. Bind to loopback or private interfaces, use firewall allowlists, and terminate TLS on your own API layer.
Public RPC endpoints are for read traffic at best. Never run personal, unlocked accounts, or wallet RPC on interfaces reachable from untrusted networks.
6. Special addresses (main chain)
These are fixed Base58 burn / system addresses you may see in block explorers and governance flows:
| Address | Purpose |
|---|---|
ELANULLXXXXXXXXXXXXXXXXXXXXXYvs3rr | Burn / destroy (null program) |
CRASSETSXXXXXXXXXXXXXXXXXXXX2qDX5J | Elastos DAO treasury (assets) |
STAKEPooLXXXXXXXXXXXXXXXXXXXpP1PQ2 | BPoS stake pool |
Other system addresses (for example CR expenses or BPoS reward accumulation) appear in the same family of special program hashes in Elastos documentation.
7. Reference parameters (verified from Elastos.ELA economics)
| Constant | Value |
|---|---|
ELA decimals | 8 (sela units) |
MinTransactionFee | 100 sela |
MinCrossChainTxFee | 10 000 sela |
CoinbaseMaturity | 100 blocks |
TargetTimePerBlock | 2 minutes |
8. Further reading
- Rosetta: Elastos.ELA.Rosetta.API exposes a normalized API some custodians prefer over raw RPC.
- Source of truth: Elastos.ELA (
common/config, transaction payloads, RPC registration).
For implementation questions, prefer SDK issues and node RPC docs tied to the exact tag you run in production.