Kaia (Klaytn) (KAIA)
Kaia (formerly Klaytn) is an EVM chain (eip155:8217/slip44:60). It takes EVM-style fields, but the bridge signs a Kaia native transaction type (see signTransaction); Klaytn-native features (fee-delegation, KCT) are wired — see the note below.
| Field | Value |
|---|---|
| Family | Klaytn / Kaia |
| coinType | 60 |
| keyPath | m/44'/60'/<accountIdx>'/0/0 (also m/44'/8217'/… and, on mainnet, m/44'/137'/…) |
| chainId · Mainnet | eip155:8217/slip44:60 |
| Testnet (Kairos) | eip155:1001/slip44:60 |
Supported Methods
| Method | Supported |
|---|---|
| getAddress | ✓ |
| signTransaction | ✓ |
| signMessage | ✓ |
| signTypedData EIP-712 | ✓ |
| signData | ✗ |
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 | 1.5.1 or higher | 1.0.0 or higher |
signTransaction | 1.5.1 or higher | 1.0.0 or higher |
signMessage | 1.5.1 or higher | 1.0.0 or higher |
signTypedData | 2.11.1 or higher | 1.0.0 or higher |
Kaia routes to the Klaytn family. Plain EVM transfer, message, and EIP-712 typed-data all work, and Klaytn-native features are now wired: fee-delegation (sender side, typeInt: 9) returns the sender-partial RLP (senderTxHashRLP) for an external fee payer, and KIP-7 (KCT) tokens sign via the standard 0xa9059cbb calldata or a form-D token descriptor. Only fee-payer mode (kaia_signTransactionAsFeePayer — signing as the payer) is still not implemented.
getAddress — account address
Retrieves the Kaia address. Returns a checksummed 0x address, identical to EVM.
| Field | Type | Required | Notes |
|---|---|---|---|
chainId | string | Required | Full CAIP-19 — eip155:8217/slip44:60 |
keyPath | string | Required | BIP-44 path — default m/44'/60'/0'/0/0. m/44'/8217'/0'/0/0 (Kaia Legacy) is also accepted, and on mainnet m/44'/137'/0'/0/0; each coin type derives a different address. |
Request
await dcent.getAddress({
chainId: 'eip155:8217/slip44:60',
keyPath: "m/44'/60'/0'/0/0"
})
Response
{
"header": {
"version": "1.0",
"status": "success",
"response_from": "getAddress"
},
"body": {
"command": "getAddress",
"parameter": {
"address": "0x…"
}
}
}
signTransaction
Signs a Kaia transaction. Send the EVM-style fields below; the bridge signs a Kaia native transaction type chosen from the payload — VALUE_TRANSFER (0x08) when data is empty, SMART_CONTRACT_EXECUTION (0x30) when it carries calldata — whatever EVM type you send, as long as to is set. Without to the request is not converted to a Kaia type: it reaches the device as an EVM transaction, and if the device signs it, assembling the result fails with -32603 — always set to. A Kaia type sent as typeInt (e.g. fee delegation below) is used as-is. Use chainId: 'eip155:8217/slip44:60'.
await dcent.sign({
method: 'signTransaction',
chainId: 'eip155:8217/slip44:60',
payload: {
keyPath: "m/44'/60'/0'/0/0",
transaction: {
type: 2,
to: '0x000000000000000000000000000000000000dEaD',
value: '0x…',
gasLimit: '0x…',
maxFeePerGas: '0x…',
maxPriorityFeePerGas: '0x…',
nonce: '0x0',
data: '0x'
}
}
})
| Field | Type | Required | Source | Notes |
|---|---|---|---|---|
type | number | Optional | App | An EVM type (0 / 2) does not change the signed type — see above. Send a Kaia type as typeInt |
to | hex addr | Required-Real | App | Recipient |
value | hex | Optional | App | Amount in peb (1 KAIA = 1e18). Omitted → 0 |
gasLimit | hex | Required-Real | App | — |
maxFeePerGas | hex | Required-Real | App | Used as the gas price (gasPrice is used instead if present). One of the two is required (-32602) |
maxPriorityFeePerGas | hex | Optional | App | Not used |
nonce | hex | Required-Real | App | Account nonce |
data | hex | Optional | App | 0x for native; calldata for contracts |
Response
| Field | Type | Notes |
|---|---|---|
body.parameter.signature | hex | Signed raw transaction (Kaia native transaction type) |
body.command | string | "signTransaction" |
header.status | string | "success" on completion |
Payload field names and the response envelope follow the Ethereum / EVM page, but the transaction is signed as a Kaia native type (see above). For Klaytn-native fee-delegation and KIP-7 (KCT) payloads, see the sections below.
Fee-delegation (sender)
For an externally fee-delegated transfer (a service pays the fee), the user signs as the sender. Set typeInt: 9 (FeeDelegatedValueTransfer); the response is the sender-partial RLP (senderTxHashRLP) that the fee payer counter-signs. This is a native value transfer, so to is the recipient.
payload.transaction:
{
"typeInt": 9,
"to": "0x<recipient>",
"value": "0x2386f26fc10000",
"gasLimit": "0x186a0",
"maxFeePerGas": "0x5d21dba00",
"maxPriorityFeePerGas": "0x0",
"nonce": "0x0",
"chainId": 8217,
"data": "0x"
}
| Field | Type | Required | Notes |
|---|---|---|---|
typeInt | number | Required | 9 = FeeDelegatedValueTransfer |
to | hex addr | Required-Real | Recipient (native transfer — to is the recipient) |
value | hex | Optional | Amount in peb. Omitted → 0 |
chainId | number | Optional | Defaults to the network of the request chainId (8217 on mainnet); if sent, it overrides it |
gasLimit · maxFeePerGas (or gasPrice) · nonce | hex | Required-Real | Fee + nonce (from RPC). maxPriorityFeePerGas is not used |
data | hex | Optional | 0x for native |
Response: body.parameter.signature is the sender-partial RLP (senderTxHashRLP), not a broadcast-ready tx — hand it to the fee payer to counter-sign.
Change before sending: to → the real recipient address, and value → the real amount (here 0x2386f26fc10000 = 0.01 KAIA). For a native value transfer the tx to is the recipient.
KIP-7 (KCT) token transfer
Token model: same as EVM. KIP-7 (KCT) transfers use raw ERC-20 calldata (below) or, as on Ethereum / EVM, a form-D transaction.token descriptor (the structured transaction.contract field is accepted too, but always signed as a plain contract call). With raw calldata or a descriptor, a token on DCENT's supported list is signed as a KCT transfer on the default m/44'/60' account (on the m/44'/8217' and m/44'/137' accounts every token is signed as a plain contract call) with its registered symbol and decimals; any other token — including one sent as a form-D descriptor — is signed as a plain contract call. A token descriptor sent with an explicit Kaia transaction type other than smart-contract execution (0x30 / 0x31) — for example typeInt: 9 — is rejected with -32602. See Core Concepts → Token descriptors.
KIP-7 uses the same transfer(address,uint256) selector as ERC-20 (0xa9059cbb). Here to is the token contract — leave it — and the recipient + amount live inside data.
payload.transaction:
{
"type": 2,
"to": "0x<token-contract>",
"value": "0x0",
"gasLimit": "0x186a0",
"maxFeePerGas": "0x77359400",
"maxPriorityFeePerGas": "0x3b9aca00",
"nonce": "0x0",
"data": "0xa9059cbb<recipient 32B><amount 32B>"
}
| Field | Type | Required | Notes |
|---|---|---|---|
type | number | Optional | Signed as SMART_CONTRACT_EXECUTION (0x30) whatever EVM type you send |
to | hex addr | Required-Real | The KIP-7 token contract (not the recipient) |
value | hex | Optional | Omit or 0x0 — the amount lives in data. A nonzero value turns off token identification: the transaction is signed as a plain contract call that also sends that native value |
data | hex | Required | 0xa9059cbb + recipient (32B) + amount (32B) |
Change before sending: keep to = the KIP-7 token contract. The real recipient is the 32 bytes after 0xa9059cbb in data (the preset ships all-zero) and the amount is the last 32 bytes (…03e8 = 1000 base units). Set both to real values so the device shows the correct KCT remap screen (for a registered token on the default m/44'/60' account; on m/44'/8217' / m/44'/137' it is signed as a plain contract call).
Common Mistakes
Fee-payer mode — signing as the fee payer (kaia_signTransactionAsFeePayer) is not implemented; only the sender side is supported (e.g. typeInt: 9). KIP-7 recipient in to — for a KIP-7 transfer, to is the token contract; the recipient + amount go inside data (see the KIP-7 section above).