Wallet SDK Ecosystem
The Elastos wallet stack is implemented across six repositories in four languages (TypeScript/JavaScript, C++, C, and Java). These libraries are not drop-in replacements for general-purpose Bitcoin wallets: the Elastos main chain uses NIST P-256 (secp256r1) for signing, not Bitcoin’s secp256k1. Integration code that assumes Bitcoin or Ethereum key semantics on the main chain will fail in subtle, expensive ways.
If you port patterns from bitcoinjs-lib, MetaMask-style secp256k1 flows, or raw Ethereum ECDSA on the main chain, signatures and addresses will not validate. Use the official SDKs, or replicate their exact curve, path, and encoding rules.
Overview
| Dimension | Detail |
|---|---|
| Repositories | 6 |
| Languages | TypeScript/JS, C++, C, Java |
| Main chain curve | NIST P-256 (secp256r1) |
| Sidechain (ESC/EID) | secp256k1 (standard Ethereum ECDSA) |
| HD standards | BIP32 / BIP39 / BIP44 (with Elastos-specific path and curve usage) |
The JS/TS SDK (Elastos.ELA.Wallet.JS.SDK) is the primary choice for web and Node.js: full HD wallet, transaction building, and P-256 signing. The C++ SPV library is the heavy reference used by mobile (e.g. Essentials) with JNI/Cordova bridges. Lower-level Keypair libraries (C and JavaScript) target embedded or minimal runtimes. Elastos.ELA.Utilities.Java suits server-side signing and exchange backends. Elastos.Connectivity.Client.JS.SDK does not implement wallet crypto; it standardizes dApp ↔ wallet connectivity (connectors, session flow).
SDK matrix
| SDK | Language | Key classes / surface | Primary use |
|---|---|---|---|
Elastos.ELA.Wallet.JS.SDK | TypeScript | MasterWallet, SubWallet (e.g. main chain, ID chain) | Web/Node wallets, transaction construction and signing |
Elastos.ELA.SPV.Cpp | C++ | IMasterWallet, ISubWallet | Native mobile, multi-chain HD, SPV light client |
Elastos.SDK.Keypair.C | C | Key generation, sign/verify, ECIES | Low-level crypto, firmware, constrained environments |
Elastos.SDK.Keypair.Javascript | JavaScript | Key generation, address derivation | Browser-only key ops without full wallet stack |
Elastos.ELA.Utilities.Java | Java | Transaction building, Jetty-hosted RPC | Java services, custodial/exchange integration |
Elastos.Connectivity.Client.JS.SDK | TypeScript | IConnector, connectivity layer | dApp bridge to installed wallets (no chain signing in-library) |
- Full product wallet (web/desktop scripting): JS SDK.
- iOS/Android native with sync: C++ SPV.
- Minimal footprint or FFI from another language: Keypair C or Keypair JS.
- JVM microservice: Utilities Java.
- dApp only: Connectivity Client JS SDK plus a wallet that implements the connector.
Cryptographic foundations
Curves and chains
- HD derivation: BIP32 / BIP39 / BIP44; master seed from mnemonic, hierarchical children.
- Main Chain (P-256)
- Smart Chain (secp256k1)
- Elastos main chain (ELA): ECDSA on NIST P-256 (secp256r1).
Derivation paths (conceptual)
| Purpose | Typical path pattern | Notes |
|---|---|---|
| Main chain | m/44'/0'/0'/... | BIP44 coin type 0; P-256 math for main-chain keys |
| DID / identity-oriented | m/44'/0'/0'/0/<index> | Used in identity flows per wallet design |
Address format specification
Elastos standard addresses are Base58Check-encoded payloads built from the public key and version metadata.
Version bytes (prefix semantics)
| Version byte | Role | Typical leading character |
|---|---|---|
0x21 | Standard single-sig address | Starts with E |
0x12 | Multi-signature address | Starts with 8 |
0x4B | Cross-chain deposit address | Starts with X |
0x1F | Deposit address (BPoS node registration) | Starts with D |
0x3F | BPoS (DPoSV2) staking address | Starts with SN |
0x67 | DID (identity) address | Starts with i |
Encoding pipeline (high level)
- Public key → redeem script (script construction as defined by the chain).
- SHA-256 of script, then RIPEMD-160 → 20-byte hash.
- Prepend version byte.
- Checksum: double SHA-256, take first 4 bytes, append.
- Base58 encode the result.
The pipeline resembles Bitcoin’s P2PKH shape, but version bytes, script templates, and signing curve are Elastos-specific. Do not feed outputs into Bitcoin tooling and expect validity on Elastos.
Transaction model
- Model: UTXO-based (like Bitcoin): inputs consume prior outputs; outputs create new UTXOs.
- Types: 40+ distinct transaction / payload types identified by a type byte in the transaction header (exact enumeration lives in protocol and SDK sources).
- Representative payload kinds:
- TransferAsset (
0x02): ordinary value transfer. - RegisterProducer (
0x09): BPoS validator registration. - TransferCrossChainAsset (
0x08): cross-chain movement. - CRCProposal (
0x25): CR council proposal payloads.
- TransferAsset (
- Structure: Inputs reference previous txid + output index; outputs carry amount, lock, and payload. Change returns unspent value to a sender-controlled output.
When building txs, explicitly allocate fee and a change output back to your wallet’s address; otherwise the difference is lost to fees or invalidates the tx.
JS SDK (primary) deep dive
The published npm package is @elastosfoundation/wallet-js-sdk. The API centers on MasterWalletManager, MasterWallet, and chain-specific SubWallet / MainchainSubWallet instances that share HD state and enforce curve/path rules inside walletcore (e.g. HDKey, DeterministicKey, Secp256, EcdsaSigner).
Typical flow
- Create or restore a master from BIP39 mnemonic + password (encryption for local storage).
createSubWallet('ELA')(or the symbol your build uses for main chain) for main-chain UTXO operations.- Build an unsigned raw transaction from inputs, outputs, fee, optional memo.
- Sign with the sub-wallet key using the user password (P-256 ECDSA).
- Broadcast the signed raw transaction via your node’s JSON-RPC (for example
sendrawtransaction) using hex fromconvertToRawTransaction; there is nopublishTransactionon the sub-wallet typings.
Example (illustrative TypeScript)
The following matches typings/ in @elastosfoundation/wallet-js-sdk: you must supply WalletStorage, network id, and ConfigInfo as required by MasterWalletManager.create. Names of ConfigInfo / storage helpers are taken from the SDK exports.
import {
MasterWalletManager,
type MainchainSubWallet,
type UTXOInput,
} from '@elastosfoundation/wallet-js-sdk';
// storage: WalletStorage; netType: string; config: ConfigInfo — from the SDK
async function sendElaExample(
storage: Parameters<typeof MasterWalletManager.create>[0],
netType: string,
config: Parameters<typeof MasterWalletManager.create>[2]
) {
const mnemonic = 'your twelve or twenty four word mnemonic here ...';
const payPassword = 'strong-user-password';
const manager = await MasterWalletManager.create(storage, netType, config);
const master = await manager.createMasterWallet(
'wallet-id',
mnemonic,
'',
payPassword,
false
);
const subWallet = (await master.createSubWallet('ELA')) as MainchainSubWallet;
const inputs = [] as UTXOInput[]; // populate from listunspent / your indexer
const outputs = [
{ Address: 'E...recipient...', Amount: '100000000' },
{ Address: 'E...change...', Amount: '...' },
];
const fee = '10000';
const memo = '';
const encoded = subWallet.createTransaction(inputs, outputs, fee, memo);
const signed = await subWallet.signTransaction(encoded, payPassword);
const rawHex = subWallet.convertToRawTransaction(signed);
// Broadcast rawHex with your ELA node JSON-RPC sendrawtransaction
return rawHex;
}
Never log mnemonics or passwords. In production, derive signing keys in secure enclaves where available, and encrypt keystores at rest using the SDK’s AES paths as intended.
API recap (conceptual)
| Method | Role |
|---|---|
MasterWalletManager.create(storage, netType, config) | Create a manager bound to persistence and network |
manager.createMasterWallet(id, mnemonic, passphrase, payPassword, singleAddress) | Restore or create a MasterWallet |
master.createSubWallet('ELA') | Main chain sub-wallet (MainchainSubWallet, UTXO, P-256) |
subWallet.createTransaction(inputs, outputs, fee, memo) | Assemble unsigned EncodedTx |
subWallet.signTransaction(encoded, payPassword) | Sign with P-256 derived key |
subWallet.convertToRawTransaction(signed) | Raw hex for sendrawtransaction |
C++ SPV library (Elastos.ELA.SPV.Cpp)
- Full HD wallet with SPV (Simplified Payment Verification) light-client behavior.
- Multi-chain: ELA, ID, BTC, ETH, Ripple (scope as implemented in the repo you vendor).
- Mobile integration: Used by Elastos Essentials via JNI / Cordova bridges, not a hypothetical binding.
- Networking / sync: Bloom filters for relevant transaction discovery; local persistence typ. SQLite for wallet state.
- Interfaces:
IMasterWallet,ISubWalletmirror the logical split seen in JS (MasterWallet/ sub-wallets).
Choose this path when you need on-device sync, minimal trust in third-party full nodes for balance proofs, or tight integration with native iOS/Android codebases already shipping Essentials-style plugins.
Elastos.SDK.Keypair.C and Elastos.SDK.Keypair.Javascript
- C library: Minimal surface: key generation, ECDSA sign/verify, ECIES for encrypted payloads, and helpers aligned with raw transaction and address experiments. Ideal for embedded targets or custom language bindings.
- JavaScript library: Browser-friendly key generation and address derivation without pulling the entire wallet/SPV stack, useful for air-gapped or client-only flows when combined with your own transport and UTXO selection.
Elastos.ELA.Utilities.Java
- Focus on server-side and automation: transaction construction, utilities, and a Jetty-based RPC server pattern for signing or orchestration behind your API gateway.
- Typical in exchange or custodial backends where JVM ops teams standardize on Java.
Elastos.Connectivity.Client.JS.SDK
- Exposes
IConnectorand connectivity primitives so dApps can discover and talk to external wallets (Essentials, etc.). - Does not replace wallet cryptography: it is the session and message layer between web apps and wallet apps.
// IConnector is defined in @elastosfoundation/elastos-connectivity-sdk-js (see package typings).
// It does not expose a generic sign(bytes): use getWeb3Provider() for EVM, or DID/credential APIs for identity.
import { Interfaces } from '@elastosfoundation/elastos-connectivity-sdk-js';
function getEvmProvider(connector: Interfaces.Connectors.IConnector) {
return connector.getWeb3Provider();
}
Treat Connectivity as transport + UX for “which wallet signs,” and keep ELA.Wallet.JS.SDK (or SPV/Keypair) for actual chain signing when you author a wallet yourself.
- ESC / EID (EVM-compatible sidechains): secp256k1, same as Ethereum.
Derivation paths (conceptual)
| Purpose | Typical path pattern | Notes |
|---|---|---|
| ESC / EID | m/44'/60'/0'/0/<index> | Standard Ethereum-style path; secp256k1 |
Use ethers.js, web3.js, or any standard Ethereum wallet stack for ESC and EID: the same secp256k1 signing and standard Ethereum HD path m/44'/60'/0'/0/<index> apply. EVM addresses are hex (0x + 20 bytes, EIP-55 checksum optional), identical in shape to Ethereum mainnet addresses.
A single BIP39 mnemonic can feed both P-256 and secp256k1 derivations on different paths. Never “reuse” a Bitcoin mainnet path and expect ELA main-chain compatibility; the curve and address rules differ.
Security considerations
| Topic | Guidance |
|---|---|
| Key storage | Use password-based encryption (AES) for keystores; never persist raw private keys as plaintext. |
| Mnemonics | Store offline; restrict clipboard access on mobile/web; consider hardware-backed storage. |
| Integration errors | The #1 source of mistakes is confusing P-256 (main chain) with secp256k1 (ESC/EID); validate against test vectors and official SDKs. |
| Operational | Rotate API keys for broadcast endpoints; rate-limit and authenticate Jetty/RPC surfaces in Java utilities. |
Never store, log, or transmit unencrypted private keys. If you must export, use encrypted containers and short-lived, audited flows.
Summary
The Elastos wallet ecosystem gives you six complementary codebases: a primary TypeScript SDK for application developers, a C++ SPV reference for mobile and sync-heavy wallets, lean Keypair libraries in C and JS, Java utilities for server workflows, and a Connectivity SDK for dApp ↔ wallet UX. Success depends on respecting P-256 on the main chain, correct version bytes and Base58Check, UTXO transaction typing, and strict separation between main-chain and EVM-sidechain cryptography.
Further reading: Protocol details evolve; always cross-check transaction type bytes, address version bytes, and npm package names against the latest tagged releases in each GitHub repository before production deployment.