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.
| Field | Value |
|---|---|
| coinType | 1729 |
| keyPath | m/44'/1729'/<accountIdx>'/0' |
| amount unit | mutez |
| chainId | tezos:NetXdQprcVkpaWU/slip44:1729 |
| chainId · Testnet | tezos:NetXnHfVqm9iesp/slip44:1729 (Shadownet) |
Supported Methods
| Method | Supported |
|---|---|
| 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.
| Method | DCENT Biometric Wallet | DCENT X |
|---|---|---|
getAddress | 2.24.1 or higher | 1.0.0 or higher |
signTransaction | 2.24.1 or higher | 1.0.0 or higher |
getAddress — account address
Retrieves the Tezos account. Returns a tz1… (ed25519) address derived from the keyPath.
| Field | Type | Required | Description |
|---|---|---|---|
chainId | string | Required | Full CAIP-19 id — tezos:NetXdQprcVkpaWU/slip44:1729 |
keyPath | string | Required | BIP32 derivation path. Default m/44'/1729'/0'/0' |
Request
await dcent.getAddress({
chainId: 'tezos:NetXdQprcVkpaWU/slip44:1729',
keyPath: "m/44'/1729'/0'/0'"
})
Response
| Field | Type | Description |
|---|---|---|
body.parameter.address | string | Tezos account address in tz1… (ed25519) format, derived from the keyPath |
header.status | string | "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"
}
| Field | Type | Required | Source | Unit | Description |
|---|---|---|---|---|---|
kind | string | Required | App | — | Always "transaction" |
source | tz address | Required-Real | Wallet | — | Device Tezos account (tz1…); must be revealed / funded |
destination | tz / KT address | Required-Real | App | — | Recipient (tz1… for native; KT1… for token calls) |
amount | string | Required | App | mutez | 1 XTZ = 1,000,000 mutez. "0" for token calls |
fee | string | Required-Real | App | mutez | Operation fee |
counter | string | Required-Real | App | — | Account counter (placeholder "1" OK) |
gasLimit / storageLimit | string | Required-Real | App | — | Used exactly as supplied — the bridge does not re-estimate them |
extra.branch | base58 block hash | Required-Real | App | — | Recent 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
| Field | Type | Description |
|---|---|---|
body.parameter.signature | string | The 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.command | string | Echoes the operation kind — "transaction" |
header.status | string | "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
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"
}
]
}
]
}
}
}
| Field | Type | Required | Source | Description |
|---|---|---|---|---|
destination | KT address | Required-Real | App | FA1.2 token contract (e.g. SMAK, 3 decimals) |
amount | string | Required | App | Outer native XTZ = "0" |
parameters.entrypoint | string | Required | App | Always "transfer" |
value → args[0].string | tz address | Required-Real | Wallet | from — your device account (tz1…) |
value → args[1].args[0].string | tz address | Required-Real | App | to — recipient (tz1…) |
value → args[1].args[1].int | int string | Required | App | Token base units (1000 = 1 SMAK at 3 decimals) |
Variant — FA2 token transfer TZIP-12
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"
}
]
}
]
}
]
]
}
]
}
}
| Field | Type | Required | Source | Description |
|---|---|---|---|---|
destination | KT address | Required-Real | App | FA2 token contract (e.g. QUIPU, 6 decimals) |
value[0].args[0].string | tz address | Required-Real | Wallet | from_ — your device account (tz1…) |
…args[1][0].args[0].string | tz address | Required-Real | App | to_ — recipient (tz1…) |
inner Pair → first int | int string | Required | App | token_id (commonly 0) |
inner Pair → second int | int string | Required | App | amount 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.
| Field | Type | Required | Description |
|---|---|---|---|
token.contract | KT address | Required-Real | FA contract address, must start with KT1 |
token.to | tz address | Required-Real | Recipient tz account — cannot be a KT1 contract (rejected to prevent misdirected funds) |
token.amount | string | Required | Base units, non-negative integer string |
token.tokenId | string | Optional | Omit for FA1.2. Set to "0" for FA2 — any other value is rejected (signer only supports token_id 0) |
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.
| Field | Type | Required | Source | Description |
|---|---|---|---|---|
unsignedTx | hex string | Required-Real | App | Pre-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
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.