Skip to main content

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.

FieldValue
FamilyConflux (Core Space)
coinType503
keyPathm/44'/60'/<accountIdx>'
amount unitDrip
chainIdconflux:cfx/slip44:503

Supported Methods

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

MethodDCENT Biometric WalletDCENT X
getAddress2.18.3 or higher1.0.0 or higher
signTransaction2.18.3 or higher1.0.0 or higher
info

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.

FieldTypeRequiredSourceNotes
chainIdstringRequiredAppFull CAIP-19 — conflux:cfx/slip44:503
keyPathstringRequiredAppBIP-44 EVM path — m/44'/60'/0'

Request

await dcent.getAddress({
chainId: 'conflux:cfx/slip44:503',
keyPath: "m/44'/60'/0'"
})

Response

FieldTypeDescription
header.statusstringsuccess on completion
body.commandstringgetAddress
parameter.addresscfx addressAccount 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"
}
FieldTypeRequiredSourceDescription
fromcfx addressRequired-RealWalletDevice CFX account in CIP-37 base32 (cfx:…)
tocfx addressRequired-RealAppRecipient in CIP-37 base32 (cfx:…)
valuehexRequiredAppAmount in Drip — 0x10 = 16 Drip (1 CFX = 1e18 Drip)
gashexRequiredApp0x5208 = 21000 (plain transfer)
gasPricehexRequiredAppPrice per gas in Drip — 0x3b9aca00 = 1e9
noncehexRequired-RealAppReal, current sender transaction count — the app must supply it; not auto-filled
chainIdhexRequiredApp0x405 = 1029 (Conflux mainnet)
epochHeighthexRequired-RealAppReal, current Conflux epoch height — the app must supply it; not auto-filled
storageLimithexRequiredAppCollateral storage cap; 0x0 for plain transfer
datahexOptionalApp0x 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

FieldTypeDescription
header.statusstringsuccess on completion
body.commandstringsignTransaction
parameter.signaturehexThe 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)

warning

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
FieldTypeRequiredSourceDescription
tocfx addressRequired-RealAppThe token contract, in CIP-37 base32 (cfx:…) — this is what the device shows, not the recipient
valuehexRequiredAppAlways 0x0 for a token call — the device labels this the "amount", which is misleading for a token transfer
datahexRequiredAppABI-encoded transfer(address,uint256)0xa9059cbb + 32-byte recipient + 32-byte base-unit amount. Never decoded or shown by the device

Common Mistakes

danger

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 mismatchcfx: = mainnet (chainId 0x405 / 1029); testnet uses cfxtest:. Keep the prefix and chainId in sync. Confusing coinType with keyPathcoinType 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.