Skip to main content

Tezos (XTZ)

Sign Tezos transaction operations. Provide a Taquito-style operation object together with extra.branch (a recent block hash); the bridge forges the operation locally and signs it with no network access, so counter, fee, gasLimit and storageLimit are used exactly as you supply them. You can instead send pre-forged operation bytes under unsignedTx. FA1.2 and FA2 token transfers are expressed as a smart-contract call to a KT1 contract.

FieldValue
coinType1729
keyPathm/44'/1729'/<accountIdx>'/0'
amount unitmutez
chainIdtezos:NetXdQprcVkpaWU/slip44:1729
chainId · Testnettezos:NetXnHfVqm9iesp/slip44:1729 (Shadownet)

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.24.1 or higher1.0.0 or higher
signTransaction2.24.1 or higher1.0.0 or higher

getAddress — account address

Retrieves the Tezos account. Returns a tz1… (ed25519) address derived from the keyPath.

FieldTypeRequiredDescription
chainIdstringRequiredFull CAIP-19 id — tezos:NetXdQprcVkpaWU/slip44:1729
keyPathstringRequiredBIP32 derivation path. Default m/44'/1729'/0'/0'

Request

await dcent.getAddress({
chainId: 'tezos:NetXdQprcVkpaWU/slip44:1729',
keyPath: "m/44'/1729'/0'/0'"
})

Response

FieldTypeDescription
body.parameter.addressstringTezos account address in tz1… (ed25519) format, derived from the keyPath
header.statusstring"success" when the address is returned
{
"header": {
"version": "1.0",
"status": "success"
},
"body": {
"command": "getAddress",
"parameter": {
"address": "tz1…"
}
}
}

signTransaction

Signs a Tezos operation. Returns the signed operation bytes / signature ready to inject.

Variant — native XTZ transfer

payload.transaction:

{
"kind": "transaction",
"source": "tz1…",
"fee": "1420",
"counter": "1",
"gasLimit": "10307",
"storageLimit": "257",
"amount": "1000000",
"destination": "tz1burnburnburnburnburnburnburjAYjjX"
}
FieldTypeRequiredSourceUnitDescription
kindstringRequiredAppAlways "transaction"
sourcetz addressRequired-RealWalletDevice Tezos account (tz1…); must be revealed / funded
destinationtz / KT addressRequired-RealAppRecipient (tz1… for native; KT1… for token calls)
amountstringRequiredAppmutez1 XTZ = 1,000,000 mutez. "0" for token calls
feestringRequired-RealAppmutezOperation fee
counterstringRequired-RealAppAccount counter (placeholder "1" OK)
gasLimit / storageLimitstringRequired-RealAppUsed exactly as supplied — the bridge does not re-estimate them
extra.branchbase58 block hashRequired-RealAppRecent block hash (B…) so the bridge can forge the operation offline. Required unless you send pre-forged unsignedTx; with neither, the request fails with -32602

Request

await dcent.sign({
method: 'signTransaction',
chainId: 'tezos:NetXdQprcVkpaWU/slip44:1729',
payload: {
keyPath: "m/44'/1729'/0'/0'",
transaction: {
kind: 'transaction',
source: 'tz1…',
fee: '1420',
counter: '1',
gasLimit: '10307',
storageLimit: '257',
amount: '1000000',
destination: 'tz1burnburnburnburnburnburnburjAYjjX',
extra: { branch: 'BLockGenesisGenesisGenesisGenesisGenesisf79b5d1CoW2' }
}
}
})

Response

FieldTypeDescription
body.parameter.signaturestringThe Tezos operation signature (edsig…, ed25519) for this operation. Attach it to the forged operation bytes before injecting through an RPC injection/operation call — this is a Tezos operation signature, not an RLP-style serialized raw transaction.
body.commandstringEchoes the operation kind"transaction"
header.statusstring"success" when signing completes on the device
{
"header": {
"version": "1.0",
"status": "success"
},
"body": {
"command": "signTransaction",
"parameter": {
"signature": "edsig…"
}
}
} // operation signature

Variant — FA1.2 token transfer TZIP-7

info

Works for any token, registered or not. This raw Michelson shape is the token operation itself, so the bridge signs it exactly as given — no registry lookup, no descriptor needed. It never queries a node for you: you build the correct parameters.value yourself. For a simpler alternative that skips hand-building the Michelson Pair/int tree, use the form-D descriptor variant below instead.

A fungible token transfer is a smart-contract call to the token's KT1… contract. The outer amount is "0" (no native XTZ moves); the token amount lives in the Michelson parameters.value.

payload.transaction:

{
"kind": "transaction",
"destination": "KT1TwzD6zV3WeJ39ukuqxcfK2fJCnhvrdN1X",
"amount": "0",
"parameters": {
"entrypoint": "transfer",
"value": {
"prim": "Pair",
"args": [
{
"string": "tz1…"
},
{
"prim": "Pair",
"args": [
{
"string": "tz1…"
},
{
"int": "1000"
}
]
}
]
}
}
}
FieldTypeRequiredSourceDescription
destinationKT addressRequired-RealAppFA1.2 token contract (e.g. SMAK, 3 decimals)
amountstringRequiredAppOuter native XTZ = "0"
parameters.entrypointstringRequiredAppAlways "transfer"
valueargs[0].stringtz addressRequired-RealWalletfrom — your device account (tz1…)
valueargs[1].args[0].stringtz addressRequired-RealAppto — recipient (tz1…)
valueargs[1].args[1].intint stringRequiredAppToken base units (1000 = 1 SMAK at 3 decimals)

Variant — FA2 token transfer TZIP-12

info

Works for any token, registered or not. This raw Michelson shape is the token operation itself, so the bridge signs it exactly as given — no registry lookup, no descriptor needed. It never queries a node for you: you build the correct parameters.value yourself. For a simpler alternative that skips hand-building the Michelson Pair/int tree, use the form-D descriptor variant below instead.

FA2 (multi-asset) uses a list-shaped transfer batch with an explicit token_id. Outer amount is again "0".

payload.transaction:

{
"kind": "transaction",
"destination": "KT193D4vozYnhGJQVtw7CoxxqphqUEEwK6Vb",
"amount": "0",
"parameters": {
"entrypoint": "transfer",
"value": [
{
"prim": "Pair",
"args": [
{
"string": "tz1…"
},
[
{
"prim": "Pair",
"args": [
{
"string": "tz1…"
},
{
"prim": "Pair",
"args": [
{
"int": "0"
},
{
"int": "1000000"
}
]
}
]
}
]
]
}
]
}
}
FieldTypeRequiredSourceDescription
destinationKT addressRequired-RealAppFA2 token contract (e.g. QUIPU, 6 decimals)
value[0].args[0].stringtz addressRequired-RealWalletfrom_ — your device account (tz1…)
…args[1][0].args[0].stringtz addressRequired-RealAppto_ — recipient (tz1…)
inner Pair → first intint stringRequiredApptoken_id (commonly 0)
inner Pair → second intint stringRequiredAppamount in base units (1000000 = 1 QUIPU at 6 decimals)

Variant — FA1.2 / FA2 form-D descriptor (compact shape)

Instead of hand-building the Michelson Pair/int tree above, send a compact token descriptor and the bridge assembles the same operation for you. Omit tokenId for FA1.2; set tokenId: "0" for FA2 (only token_id 0 is supported this way — non-zero is rejected).

payload.transaction:

{
"token": {
"contract": "KT1TwzD6zV3WeJ39ukuqxcfK2fJCnhvrdN1X",
"to": "tz1burnburnburnburnburnburnburjAYjjX",
"amount": "1000"
},
"from": "tz1…"
} // tokenId omitted = FA1.2. Add "tokenId": "0" for FA2.
FieldTypeRequiredDescription
token.contractKT addressRequired-RealFA contract address, must start with KT1
token.totz addressRequired-RealRecipient tz account — cannot be a KT1 contract (rejected to prevent misdirected funds)
token.amountstringRequiredBase units, non-negative integer string
token.tokenIdstringOptionalOmit for FA1.2. Set to "0" for FA2 — any other value is rejected (signer only supports token_id 0)
info

Both token variants go to a KT1… contract with entrypoint: "transfer" and outer amount: "0". The bridge identifies the token transfer and synthesizes the token account — set the inner from / from_ to your own device account.

Variant — unsignedTx (pre-forged operation, blind-sign)

Send a pre-forged Tezos operation (hex bytes: branch + contents, already built and encoded outside the device) under unsignedTx — the same field name Hedera uses (no new field). The device blind-signs the bytes as-is. This is the only fully self-contained signTransaction form for Tezos; missing or malformed bytes return -32602.

FieldTypeRequiredSourceDescription
unsignedTxhex stringRequired-RealAppPre-forged operation bytes (hex): branch(32B) + contents, built outside the device

Request

await dcent.sign({
method: 'signTransaction',
chainId: 'tezos:NetXdQprcVkpaWU/slip44:1729',
payload: {
keyPath: "m/44'/1729'/0'/0'",
transaction: {
"unsignedTx": "288f8bb117200c366cade5c8f22e0854cc99429853dcc9b35287cc9cdcc8e3c66c00338cdba49ec68d3e14903e4fd37db865a990ed22900301e80700c0843d000041812f66a66258718eb77f7bdc4f89e2f151af8a00"
}
}
})

Common Mistakes

danger

Non-zero outer amount on a token transfer — for FA1.2 / FA2 the outer amount must be "0", otherwise you also move native XTZ silently. tz address as token destination — token transfers go to the KT1… contract, not the recipient tz1…. Whole-token amounts — the Michelson int is base units (SMAK 3 decimals, QUIPU 6 decimals), not display units. Unrevealed source — a brand-new source account must be revealed / funded before its operation can be injected.