Horizen (ZEN)
Reference metadata for Horizen. The chain is discontinued and every call that carries its chainId is rejected — the facts below describe the contract as it stood before the shutdown.
| Field | Value |
|---|---|
| coinType | 121 |
| keyPath | m/44'/121'/<accountIdx>'/0/0 |
| amount unit | zatoshi (1 ZEN = 1e8) |
| chainId | bip122:0007104ccda289427919efc39dc9e4d4/slip44:121 |
Supported Methods
| Method | Supported |
|---|---|
| getAddress | ✗ |
| signTransaction | ✗ |
| signMessage | ✗ |
| signTypedData | ✗ |
| signAuthEntry | ✗ |
Notes
Discontinued. The native ZEN chain shut down on 2025-07-23, when ZEN migrated to an ERC-20 token on Base; both the legacy mainchain and the EON EVM chain were retired. signTransaction for this chainId is no longer supported. ZEN on Base is an ordinary ERC-20 and uses the Ethereum-family path (eip155:8453/slip44:60). The description below is kept for historical reference only. Formerly a fully signable UTXO chain forked from Zcash. Transparent addresses with a 2-byte version prefix (zn... / zs...) and CHECKBLOCKATHEIGHT replay protection that binds each output to a recent block height. Legacy addresses only, no SegWit. Shares the Bitcoin-family signTransaction path; provide the previous transactions for the inputs you spend.
option (BIP-115 replay protection)
Horizen output scripts are BIP-115 (CHECKBLOCKATHEIGHT): the device appends <block hash><height> to every output script. The signer has no network access, so the app must supply this value via transaction.option — unlike a fixed chain ID, no static wallet default can exist here because it depends on the current chain tip.
| Field | Type | Required | Source | Notes |
|---|---|---|---|---|
option.blockHash | hex (64 chars) | Required | App | Exactly as shown by a block explorer (display byte order) — the wallet reverses the bytes internally before signing. |
option.height | number | Required | App | Height of the same block as blockHash. DCENT's own app uses tip − 200 to avoid reorgs — Apps should keep a similar margin. |
The wallet only guarantees correct encoding of whatever blockHash/height you pass — it cannot verify that block actually exists on-chain. A wrong-but-well-formed pair signs successfully and is only rejected at broadcast, which makes the root cause hard to trace. Omitting option entirely is caught earlier: the device rejects with bip115 opt size too small: 0.
Already have the encoded bytes? A hex string is also accepted: <block hash, 32 bytes, byte-reversed><height, little-endian> — even length, no 0x prefix, no length prefix (the device adds that itself). Any other shape — object or string — is rejected with -32602.
Everything below is the contract as it stood before the chain shut down. Horizen's chainId is on the bridge's discontinued list, so every call that carries it — getAddress included — is rejected with unsupported_method before the method is even dispatched. The payload shapes are kept for historical reference only.
Horizen used the Bitcoin-family signing path: the signTransaction payload shape (inputs, outputs, previous transactions) matched the Bitcoin reference, and only the address version, coinType and amount decimals differed.
signTransaction
await dcent.sign({
method: 'signTransaction',
chainId: 'bip122:0007104ccda289427919efc39dc9e4d4/slip44:121',
payload: {
keyPath: "m/44'/121'/0'/0/0",
transaction: {
inputs: [
{ rawTransaction: '<prev tx hex>', index: 0, txType: 'p2pkh', keyPath: "m/44'/121'/0'/0/0" }
],
outputs: [
{ txType: 'p2pkh', amount: '990000', addresses: ['<zn... recipient>'] }
],
option: { blockHash: '<64 hex, display byte order>', height: 1899800 }
}
}
}) // → body.parameter.signature
signTransaction — full field reference
| Field | Type | Required | Source | Unit | Notes |
|---|---|---|---|---|---|
inputs[].rawTransaction | hex | Required-Real | Wallet | — | Full prev-tx hex of the UTXO; must be device-owned |
inputs[].index | number | Required | App | — | UTXO output index |
inputs[].txType | enum | Required | App | — | Always p2pkh — Horizen has no SegWit variant |
inputs[].keyPath | string | Required-Real | Wallet | — | Path that signs this input |
inputs[].sequence | number | Optional | App | — | Same defaulting behavior as Bitcoin (0xfffffffd for RBF-enabled coins when omitted) |
outputs[].amount | string | Required | App | zatoshi | Output value |
outputs[].addresses | string[] | Required-Real | App | — | Recipient. Only addresses[0] is used, exactly one non-change output allowed — use a second output with txType: 'change' for change. |
option | object | hex | Required | App | — | BIP-115 replay-protection tail — sub-field breakdown above. |