Conflux (CFX)
Sign Conflux Core Space transactions. The fields are EVM-style, but addresses use the CIP-37 base32 format (cfx:…) — the device firmware expects base32, not hex.
| Field | Value |
|---|---|
| Family | Conflux (Core Space) |
| coinType | 503 |
| keyPath | m/44'/60'/<accountIdx>' |
| amount unit | Drip |
| chainId | conflux:cfx/slip44:503 |
Supported Methods
| Method | Supported |
|---|---|
| getAddress | ✓ |
| signTransaction | ✓ |
| signMessage | ✗ |
| signTypedData | ✗ |
Requirements
Minimum firmware for each method. The two models are on different version lines, so DCENT Biometric Wallet and DCENT X are listed separately (the numbers are not comparable across models). Below this the request returns the firmware-update error (5005) and the bridge prompts to update.
| Method | DCENT Biometric Wallet | DCENT X |
|---|---|---|
getAddress | 2.18.3 or higher | 1.0.0 or higher |
signTransaction | 2.18.3 or higher | 1.0.0 or higher |
Conflux derives keys on the EVM path m/44'/60'/0' even though its registered coinType is 503. The path and the coinType are intentionally different.
getAddress — account address
Retrieves the Conflux Core Space account address. Returns a CIP-37 base32 address (cfx:…), not a hex address.
| Field | Type | Required | Source | Notes |
|---|---|---|---|---|
chainId | string | Required | App | Full CAIP-19 — conflux:cfx/slip44:503 |
keyPath | string | Required | App | BIP-44 EVM path — m/44'/60'/0' |
Request
await dcent.getAddress({
chainId: 'conflux:cfx/slip44:503',
keyPath: "m/44'/60'/0'"
})
Response
| Field | Type | Description |
|---|---|---|
header.status | string | success on completion |
body.command | string | getAddress |
parameter.address | cfx address | Account address in CIP-37 base32 (cfx:…); mainnet prefix is cfx: |
{
"header": {
"version": "1.0",
"status": "success"
},
"body": {
"command": "getAddress",
"parameter": {
"address": "cfx:…"
}
}
}
signTransaction — Core Space transaction
payload.transaction:
{
"from": "cfx:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0sfbnjm2",
"to": "cfx:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0sfbnjm2",
"value": "0x10",
"gas": "0x5208",
"gasPrice": "0x3b9aca00",
"nonce": "0x0",
"chainId": "0x405",
"epochHeight": "0x0",
"storageLimit": "0x0",
"data": "0x"
}
| Field | Type | Required | Source | Description |
|---|---|---|---|---|
from | cfx address | Required-Real | Wallet | Device CFX account in CIP-37 base32 (cfx:…) |
to | cfx address | Required-Real | App | Recipient in CIP-37 base32 (cfx:…) |
value | hex | Required | App | Amount in Drip — 0x10 = 16 Drip (1 CFX = 1e18 Drip) |
gas | hex | Required | App | 0x5208 = 21000 (plain transfer) |
gasPrice | hex | Required | App | Price per gas in Drip — 0x3b9aca00 = 1e9 |
nonce | hex | Required-Real | App | Real, current sender transaction count — the app must supply it; not auto-filled |
chainId | hex | Required | App | 0x405 = 1029 (Conflux mainnet) |
epochHeight | hex | Required-Real | App | Real, current Conflux epoch height — the app must supply it; not auto-filled |
storageLimit | hex | Required | App | Collateral storage cap; 0x0 for plain transfer |
data | hex | Optional | App | 0x for a plain transfer; contract calldata otherwise |
Request
await dcent.sign({ method: 'signTransaction',
chainId: 'conflux:cfx/slip44:503',
payload: { keyPath: "m/44'/60'/0'",
transaction: {
"from": "cfx:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0sfbnjm2",
"to": "cfx:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0sfbnjm2",
"value": "0x10", "gas": "0x5208", "gasPrice": "0x3b9aca00",
"nonce": "0x0", "chainId": "0x405", "epochHeight": "0x0",
"storageLimit": "0x0", "data": "0x" } } })
Response
| Field | Type | Description |
|---|---|---|
header.status | string | success on completion |
body.command | string | signTransaction |
parameter.signature | hex | The broadcast-ready serialized signed Core Space transaction (not a bare signature) — submit it through a Conflux Core Space RPC |
{
"header": {
"status": "success"
},
"body": {
"command": "signTransaction",
"parameter": {
"signature": "0x…"
}
}
}
Variant — CRC-20 token transfer (raw calldata)
Signs, but the confirmation screen is misleading (verified on real hardware 2026-07-26). Conflux has no form-D transaction.token descriptor and no blob-passthrough path — the plain native-transfer data field is never interpreted or gated, so a hand-built ERC-20-style transfer(address,uint256) calldata passes through byte-for-byte, exactly like EVM/Kaia's form-E graceful fallback. The signed bytes are exactly what you sent (no misdirection) — but the device screen shows only the outer fields: to = the token contract address, amount = 0 CFX. The real recipient and token amount, both buried inside data, are never shown on-device. Render your own confirmation UI in the App before sending; do not rely on the device screen to confirm token transfer details on Conflux today. This is a display-only gap tracked by wm objective m04-01-15 — closing it needs no App-side change.
payload.transaction:
{
"from": "cfx:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0sfbnjm2",
"to": "cfx:acg158kvr8zanb1bs048ryb6rtrhr283ma70vz70tx",
"value": "0x0",
"gas": "0x186a0",
"gasPrice": "0x3b9aca00",
"nonce": "0x0",
"chainId": "0x405",
"epochHeight": "0x6a1b2c",
"storageLimit": "0x0",
"data": "0xa9059cbb00000000000000000000000011111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000000000000000"
} // to = WCFX contract (CIP-37 base32), data = transfer(address,uint256) selector + recipient + amount
| Field | Type | Required | Source | Description |
|---|---|---|---|---|
to | cfx address | Required-Real | App | The token contract, in CIP-37 base32 (cfx:…) — this is what the device shows, not the recipient |
value | hex | Required | App | Always 0x0 for a token call — the device labels this the "amount", which is misleading for a token transfer |
data | hex | Required | App | ABI-encoded transfer(address,uint256) — 0xa9059cbb + 32-byte recipient + 32-byte base-unit amount. Never decoded or shown by the device |
Common Mistakes
Hex (0x…) addresses instead of CIP-37 base32 — Conflux Core Space addresses must be cfx:…; hex to/from caused a device SYSTEM HALT in HW testing. Network prefix vs. chainId mismatch — cfx: = mainnet (chainId 0x405 / 1029); testnet uses cfxtest:. Keep the prefix and chainId in sync. Confusing coinType with keyPath — coinType is 503 but derivation uses the EVM path m/44'/60'/0'. Stale epochHeight — it bounds transaction validity; refresh it near the current epoch or the network rejects the tx.