Skip to main content

Ethereum / EVM (ETH)

Sign transactions, messages, and EIP-712 typed data on Ethereum and 93 EVM-compatible chains. All EVM chains share one payload shape — only chainId changes.

FieldValue
FamilyEthereum (EVM)
coinType60
keyPathm/44'/60'/<accountIdx>'/0/0
chainId · Mainneteip155:1/slip44:60

Supported Methods

MethodSupported
getAddress
signTransaction
signMessage
signTypedData EIP-712
signAuthEntry

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
getAddress1.0.0 or higher1.0.0 or higher
signTransaction1.0.0 or higher1.0.0 or higher
signMessage1.3.0 or higher1.0.0 or higher
signTypedData2.11.1 or higher1.0.0 or higher
info

Firmware versions below are for the DCENT Biometric Wallet line — DCENT X supports them from 1.0.0. Values are for Ethereum mainnet. Some EVM chains need newer firmware — 64-bit chainIds require 2.19.7, and several chains were added later (e.g. BSC 2.6.1, Polygon 2.8.0).

getAddress — account address

Retrieves the EVM address. Returns a checksummed 0x address.

FieldTypeRequiredNotes
chainIdstringRequiredFull CAIP-19 — eip155:1/slip44:60
keyPathstringRequiredBIP-44 derivation path — default m/44'/60'/0'/0/0

Request

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

Response

FieldTypeNotes
body.parameter.addressstringChecksummed EIP-55 0x address (40 hex chars). EVM does not return a separate public-key field.
header.statusstring"success" on completion
{
"header": {
"version": "1.0",
"status": "success"
},
"body": {
"command": "getAddress",
"parameter": {
"address": "0x6A5C…"
}
}
}

Supported chainIds

NetworkchainId
Ethereumeip155:1/slip44:60
Sepolia (testnet)eip155:11155111/slip44:60
Polygoneip155:137/slip44:60
BNB Smart Chaineip155:56/slip44:60
Arbitrum Oneeip155:42161/slip44:60
Optimismeip155:10/slip44:60
Baseeip155:8453/slip44:60
Avalanche C-Chaineip155:43114/slip44:60
tip

Every EVM chain uses this exact payload shape — only the chainId changes (always the full eip155:N/slip44:60). Full list on Supported EVM Chains.

info

Kaia (Klaytn) has its own page — see Kaia.

keyPaths

UsePath
Defaultm/44'/60'/0'/0/0
Account index Nm/44'/60'/N'/0/0

signTransaction

Signs an EVM transaction. Returns an RLP-encoded signed raw transaction ready for eth_sendRawTransaction.

Payload — native transfer (EIP-1559)

payload.transaction:

{
"type": 2,
"to": "0x000000000000000000000000000000000000dEaD",
"value": "0x2386f26fc10000",
"gasLimit": "0x5208",
"maxFeePerGas": "0x77359400",
"maxPriorityFeePerGas": "0x3b9aca00",
"nonce": "0x0",
"data": "0x"
}
FieldTypeRequiredSourceUnitNotes
typenumberOptionalApp2 = EIP-1559 (recommended), 0 = legacy
tohex addrRequired-RealAppRecipient
valuehexRequiredAppwei0x2386f26fc10000 = 0.01 ETH
gasLimithexRequired-RealAppapp estimate
maxFeePerGashexRequired-RealAppweiEIP-1559 fee
maxPriorityFeePerGashexRequired-RealAppweiEIP-1559 tip
noncehexRequired-RealAppAccount nonce
datahexOptionalApp0x for native; calldata for contracts

Request

await dcent.sign({
method: 'signTransaction',
chainId: 'eip155:1/slip44:60',
payload: {
keyPath: "m/44'/60'/0'/0/0",
transaction: {
type: 2,
to: '0x000000000000000000000000000000000000dEaD',
value: '0x2386f26fc10000',
gasLimit: '0x5208',
maxFeePerGas: '0x77359400',
maxPriorityFeePerGas: '0x3b9aca00',
nonce: '0x0',
data: '0x'
}
}
})

Response

FieldTypeNotes
body.parameter.signaturehexBroadcast-ready RLP-encoded signed raw transaction (not a bare r/s/v signature). Pass directly to eth_sendRawTransaction.
body.commandstring"signTransaction"
header.statusstring"success" on completion
{
"header": {
"version": "1.0",
"status": "success"
},
"body": {
"command": "signTransaction",
"parameter": {
"signature": "0x02f8…"
}
}
} // RLP signed raw tx

Variants

ERC-20 transfer a9059cbb

info

Token model: form-D descriptor. Always send the token's symbol and decimals under transaction.token — the bridge signs with no network access and uses the decimals you supply directly, so the device shows the correct token name and amount. See Core Concepts → Token descriptors.

payload.transaction:

{
"type": 2,
"to": "0x<token-contract>",
"value": "0x0",
"gasLimit": "0x186a0",
"maxFeePerGas": "0x77359400",
"maxPriorityFeePerGas": "0x3b9aca00",
"nonce": "0x0",
"data": "0xa9059cbb<recipient 32B><amount 32B>"
}
FieldTypeRequiredSourceDescription
tohex addrRequired-RealAppThe token contract address — not the recipient.
valuehexRequiredApp0x0 — no native value is sent; the token amount lives in data.
datahexRequiredAppSelector 0xa9059cbb + recipient (32B, left-padded) + amount (32B, token base units).
import { Interface } from 'ethers'
const data = new Interface(['function transfer(address,uint256)'])
.encodeFunctionData('transfer', [recipient, amount]) // amount in base units

ERC-20 approve 095ea7b3

data = 0x095ea7b3 + spender (32B) + amount (32B). Prefer an exact amount over unlimited (0xff…).

ERC-721 transfer 42842e0e

to = NFT contract; data = 0x42842e0e + from (32B) + to (32B) + tokenId (32B). The bridge also recognizes 23b872dd (transferFrom) and b88d4fde.

info

Token transfer — two ways. The confirmed app path is raw data (above). The DCENT Web Bridge also supports a structured transaction.contract = {address, to, value, decimals} field; it is forwarded opaquely by the connector and resolved at the wire layer, so reachability through the connector→bridge is confirmed. Either form works.

info

Token labeling. A token you describe with a form-D descriptor shows a parsed token screen on the device (symbol / decimals remap). An ERC-20 sent without a descriptor does not error: the EVM / Kaia adapter runs with nativeFallbackOnUnresolved=true and signs the original raw calldata ({to: contract, value: 0x0, data}) exactly like the WalletConnect native path — the device shows the raw data (no bridge-synthesized symbol / decimals summary) instead of a -32602 rejection. Playground preset: evm-erc20-transfer-unregistered.

signMessage

info

XDC: supported since wallet-models v0.8.16-rc.2 (2026-07-29). An earlier sweep (2026-07-21) found signMessage returning -32601 on XDC (eip155:50/slip44:60) and XDC Apothem (eip155:51/slip44:60), because the XINFIN family had no slot for it. That release wires XINFIN to the Ethereum family implementation, so both networks now sign messages and EIP-712 typed data. Keep handling -32601 if you target an older bridge deployment.

await dcent.sign({
method: 'signMessage',
chainId: 'eip155:1/slip44:60',
payload: {
keyPath: "m/44'/60'/0'/0/0",
message: '0x48656c6c6f',
meta: {
kind: 'personal'
}
}
})
// → body.parameter.signature
FieldTypeRequiredNotes
messagehex stringRequiredEIP-191 personal message (hex recommended)
meta.kindenumOptional'personal' | 'raw' | 'eip712' (routes to signTypedData)

Response

FieldTypeNotes
body.parameter.signaturehexEIP-191 personal-sign signature — 65-byte r/s/v hex (0x…). This is a bare signature, not a serialized transaction.
header.statusstring"success" on completion

signTypedData EIP-712

await dcent.sign({
method: 'signTypedData',
chainId: 'eip155:1/slip44:60',
payload: {
keyPath: "m/44'/60'/0'/0/0",
data: JSON.stringify({
types,
primaryType,
domain,
message
}),
version: 'V4'
}
})
// → body.parameter.signature
FieldTypeRequiredNotes
datastringRequiredJSON.stringify of the typed-data object
versionenumRequired'V1' | 'V3' | 'V4'

Response

FieldTypeNotes
body.parameter.signaturehexEIP-712 typed-data signature — 65-byte r/s/v hex (0x…) over the hashed struct. A bare signature, not a serialized transaction.
header.statusstring"success" on completion

Common Mistakes

danger

Wrong chainId — replay protection differs per chain; use the exact eip155:N. Stale nonce / gas — refetch from RPC immediately before signing. ERC-20 to set to the recipient instead of the token contract. Mixed-case token addresses — prefer all-lowercase (EIP-1191 checksums are rejected on some chains like RSK).