Skip to main content

HAVAH (HVH)

Sign HAVAH transactions. HAVAH is an ICON-family chain, so transactions use the ICON-native wire shape (from/to/value/stepLimit/nid/nonce). The bridge converts this wire into a HavahTransaction before the device signs.

FieldValue
coinType858
keyPathm/44'/858'/<accountIdx>'/0/0
amount unitloop
chainIdhavah:mainnet/slip44:858

Supported Methods

MethodSupported
getAddress
signTransaction
signMessage
signTypedData
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
getAddress2.26.0 or higher1.0.0 or higher
signTransaction2.26.0 or higher1.0.0 or higher

getAddress — account address

Retrieves the HAVAH account address for a chainId + keyPath. HAVAH uses the ICON-family hx… address format (there are no address variants). Call this before building a transaction so from matches the device account.

FieldTypeRequiredSourceDescription
chainIdstringRequiredAppFull CAIP-19 id — havah:mainnet/slip44:858
keyPathstringRequiredAppBIP-44 derivation path — default m/44'/858'/0'/0/0

Request

await dcent.getAddress({
chainId: 'havah:mainnet/slip44:858',
keyPath: "m/44'/858'/0'/0/0"
})

Response

FieldTypeDescription
header.statusstringsuccess on a completed request
body.commandstringEchoes the method — getAddress
body.parameter.addressstringHAVAH account address in ICON-family hx… format
{
"header": {
"version": "1.0",
"status": "success"
},
"body": {
"command": "getAddress",
"parameter": {
"address": "hx…"
}
}
}

signTransaction — ICON-native wire

Variant — native HVH transfer

payload.transaction:

{
"from": "hx0000000000000000000000000000000000000000",
"to": "hx0000000000000000000000000000000000000000",
"value": "0xDE0B6B3A7640001",
"stepLimit": "0x186a0",
"stepPrice": "0x2e90edd000",
"timestamp": "0x0",
"nid": "0x100",
"nonce": "0x1",
"version": "0x3"
}
FieldTypeRequiredSourceDescription
fromstringRequired-RealWalletDevice HAVAH account (hx…)
tostringRequired-RealAppRecipient (hx… for native send)
valuehexRequiredAppAmount in loop, 0x-prefixed hex (1 HVH = 1e18 loop). Keep as hex — values exceed MAX_SAFE_INTEGER
stepLimithexRequiredAppStep (gas) limit, hex. When provided together with stepPrice the bridge builds a self-contained preparedFee
stepPricehexRequired-RealAppReal, current step price, hex — the app must supply it; a stale/zero value is rejected
timestamphexRequired-RealAppICON microsecond epoch. The wallet never fills this in — the value you send is the one that is signed. Omitting it fails with -32602
nidhexRequiredAppNetwork id — 0x100 for mainnet
noncehexOptionalAppTransaction nonce, hex
versionhexRequiredAppICON tx version — 0x3

js — Request:

await dcent.sign({
method: 'signTransaction',
chainId: 'havah:mainnet/slip44:858',
payload: {
keyPath: "m/44'/858'/0'/0/0",
transaction: {
from: "hx0000000000000000000000000000000000000000",
to: "hx0000000000000000000000000000000000000000",
value: "0xDE0B6B3A7640001",
stepLimit: "0x186a0",
stepPrice: "0x2e90edd000",
timestamp: "0x0",
nid: "0x100",
nonce: "0x1",
version: "0x3"
}
}
}) // → body.parameter.signature

Response

FieldTypeDescription
header.statusstringsuccess on a completed signature
body.commandstringSigning command echo — signTransaction
body.parameter.signaturestringBroadcast-ready serialized signed HAVAH (ICON) transaction, not a bare r/s/v signature. Submit it as-is to a HAVAH node
{
"header": {
"status": "success"
},
"body": {
"command": "signTransaction",
"parameter": {
"signature": "0x…"
}
}
}

Variant — HSP-20 token transfer

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.

HSP-20 (IRC-2-like) tokens use the ICON call data shape. to is the token contract (cx…), the real recipient is data.params._to, and native value stays 0x0 (no native HVH moves).

payload.transaction:

{
"dataType": "call",
"from": "hx0000000000000000000000000000000000000000",
"to": "cxd7fed2ae1d9b2314087520efe1870c33e5c5baa4",
"value": "0x0",
"stepLimit": "0x186a0",
"stepPrice": "0x2e90edd000",
"timestamp": "0x0",
"nid": "0x100",
"nonce": "0x1",
"version": "0x3",
"data": {
"method": "transfer",
"params": {
"_to": "hx0000000000000000000000000000000000000000",
"_value": "0xDE0B6B3A7640001"
}
}
}
FieldTypeRequiredSourceDescription
dataTypeenumRequiredAppMust be call for a contract call
tostringRequired-RealAppToken contract address (cx…), not the recipient
valuehexRequiredAppNative HVH amount — keep 0x0 for a token-only transfer
data.methodstringRequiredAppContract method — transfer
data.params._tostringRequired-RealAppReal token recipient (hx…)
data.params._valuehexRequiredAppToken amount in base units, 0x-prefixed hex (PER has 18 decimals; 0xF4240 = 1e6 for a 6-decimal token)
timestamphexRequired-RealAppICON microsecond epoch — the wire path never fills it in; omitting it fails with -32602

js — Request:

await dcent.sign({
method: 'signTransaction',
chainId: 'havah:mainnet/slip44:858',
payload: {
keyPath: "m/44'/858'/0'/0/0",
transaction: {
dataType: "call",
from: "hx0000000000000000000000000000000000000000",
to: "cxd7fed2ae1d9b2314087520efe1870c33e5c5baa4",
value: "0x0",
stepLimit: "0x186a0",
stepPrice: "0x2e90edd000",
timestamp: "0x0",
nid: "0x100",
nonce: "0x1",
version: "0x3",
data: { method: "transfer",
params: { _to: "hx0000000000000000000000000000000000000000",
_value: "0xDE0B6B3A7640001" } }
}
}
}) // → body.parameter.signature

Response

FieldTypeDescription
header.statusstringsuccess on a completed signature
body.commandstringSigning command echo — signTransaction
body.parameter.signaturestringBroadcast-ready serialized signed HAVAH (ICON) transaction carrying the HSP-20 call data, not a bare r/s/v signature. Submit it as-is to a HAVAH node
{
"header": {
"status": "success"
},
"body": {
"command": "signTransaction",
"parameter": {
"signature": "0x…"
}
}
}
info

HSP-20 tokens are signed under parent HAVAH on mainnet (slip44:858). A wrong chain is rejected (-32602); any HSP-20 contract signs — supply a form-D descriptor (see Core Concepts → Token descriptors) to prevent a silent native HVH transfer.

Variant — HSP-20 form-D descriptor

Send a compact token descriptor instead of a full ICON dataType:"call" envelope. The bridge builds the transfer(_to,_value) SCORE call from { contract, to, amount }, rewrites to to the contract address, and sets value to 0x0. Envelope fields you send (from, stepLimit, stepPrice, nid, nonce, version) are preserved. amount is a base-unit string (not rescaled by decimals).

payload.transaction:

{
"token": {
"contract": "cxd8303731bf989a1597a6d38505d7a9483c4d9a38",
"to": "hx0000000000000000000000000000000000000000",
"amount": "1000000",
"decimals": 6,
"symbol": "GODH"
},
"from": "hx0000000000000000000000000000000000000000",
"stepLimit": "0x186a0",
"stepPrice": "0x2e90edd000",
"timestamp": "0x0",
"nid": "0x100",
"nonce": "0x1",
"version": "0x3"
}
FieldTypeRequiredNotes
token.contractstringRequiredSCORE address; must match cx + 40 hex chars. Unregistered tokens allowed.
token.tostringRequiredRecipient (hx…). Becomes data.params._to.
token.amountstringRequiredBase-unit integer string; not rescaled by decimals. 0 is allowed.
token.decimalsnumberRequiredBase-unit exponent; enables descriptor resolution on the device.
token.symbolstringOptionalDisplay metadata only.
fromstringRequired-RealDevice HAVAH account that signs (hx…). Omitting it fails with -32602.
stepLimit / stepPricestringRequiredMap to the fee gate (gasLimit / fee). Zero or missing fails the gate.
nid / nonce / versionstringOptionalICON envelope fields; passed through unchanged.
timestamphexRequired-RealICON microsecond epoch — the wire path never fills it in; omitting it fails with -32602
info

Verified on device (2026-07-20): this descriptor displays as GODH 1.0amount "1000000" at decimals 6. Replace token.to / from with your own device HAVAH account (hx…).

Common Mistakes

danger

Decimal amountsvalue / _value must be 0x-prefixed hex loop, not a decimal string. Keep them as hex because values exceed MAX_SAFE_INTEGER. Token to vs recipient — for HSP-20, to is the contract (cx…) and the recipient is data.params._to (hx…). Putting the recipient in to moves native HVH instead. Non-zero value on a token transfer — leave value as 0x0 for HSP-20; a non-zero value sends native HVH alongside the token. Missing stepLimit — without it the bridge cannot build preparedFee. Missing stepPrice — the app must supply a real, current step price; it is not auto-filled.