Stacks (STX)
Sign Stacks (STX) transactions. The device signs a structured transaction object — either a native STX tokenTransfer or a contractCall (e.g. a SIP-010 fungible-token transfer). A placeholder nonce passes the format check and is signed as sent — supply the real nonce and fee for an account that exists on-chain.
| Field | Value |
|---|---|
| Family | Stacks |
| coinType | 5757 |
| keyPath | m/44'/5757'/<accountIdx>'/0/0 |
| amount unit | microSTX |
| chainId | stacks:1/slip44:5757 |
Supported Methods
| Method | Supported |
|---|---|
| getAddress | ✓ |
| signTransaction | ✓ |
| signMessage | ✗ |
| signTypedData | ✗ |
| 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 | 2.14.1 or higher | 1.0.0 or higher |
signTransaction | 2.14.1 or higher | 1.0.0 or higher |
getAddress — account address
Retrieves the Stacks account address for the given keyPath. Returns a c32check-encoded address (SP… on mainnet, ST… on testnet). Stacks has no address variants, so no addressFormat is needed.
| Field | Type | Required | Source | Description |
|---|---|---|---|---|
chainId | string | Required | App | Full CAIP-19 id — stacks:1/slip44:5757 |
keyPath | string | Required-Real | Wallet | BIP-44 path of the device account; default m/44'/5757'/0'/0/0 |
Request
await dcent.getAddress({
chainId: 'stacks:1/slip44:5757',
keyPath: "m/44'/5757'/0'/0/0"
})
Response
| Field | Type | Description |
|---|---|---|
header.status | string | success on success; failure otherwise |
body.command | string | getAddress |
body.parameter.address | string | c32check-encoded Stacks address (SP… on mainnet, ST… on testnet) |
{
"header": {
"version": "1.0",
"status": "success",
"response_from": "getAddress"
},
"body": {
"command": "getAddress",
"parameter": {
"address": "SP…"
}
}
}
signTransaction — <transaction>
Variant — native STX (tokenTransfer)
await dcent.sign({
method: 'signTransaction',
chainId: 'stacks:1/slip44:5757',
payload: {
keyPath: "m/44'/5757'/0'/0/0",
transaction: {
txType: "tokenTransfer",
recipient: "SP000000000000000000002Q6VF78",
amount: "1000000", // microSTX — 1 STX
memo: "",
fee: "180",
nonce: "0",
anchorMode: 3,
network: "mainnet"
}
}
})
| Field | Type | Required | Source | Description |
|---|---|---|---|---|
keyPath | string | Required-Real | Wallet | BIP-44 path of the signing device account (SP…) |
txType | enum | Required | App | tokenTransfer for native STX |
recipient | string | Required-Real | App | Destination Stacks address (SP…) |
amount | string | Required | App | microSTX — 1 STX = 1,000,000 |
memo | string | Optional | App | Optional plain-text memo |
fee | string | Optional | App | Transaction fee in microSTX. If omitted, the transaction is signed with fee 0 — always send a real fee |
nonce | string | Required-Real | App | Real, current account nonce — the app must supply it; not auto-filled |
anchorMode | number | Optional | App | 3 = any (on/off-chain) |
postConditionMode | number | Optional | App | 1 = allow, 2 = deny. 1 (allow) requires at least one entry in postConditions — allow with no post-condition is rejected with -32602. Because DCENT X rejects post-conditions on a native transfer, leave both fields out for tokenTransfer |
postConditions | array | Optional | App | Serialized post-condition hex strings, one per post-condition (at most 32). DCENT X rejects a native STX transfer that carries any post-condition — omit it for a native transfer |
network | enum | Optional | App | Ignored — the network is determined by chainId |
Variant — SIP-010 token transfer (contractCall)
What the bridge accepts today. (1) contractCall currently routes only the SIP-010 transfer function. Other Clarity calls (swap, mint, staking) return -32602. (2) This shape has nowhere to put decimals, so it only works for a token DCENT already supports (see Supported Coins & Tokens); anything else fails with -32602 cannot resolve token. For every other SIP-010 token, send the form-D descriptor shape below instead.
Token model: form-D descriptor. A token on DCENT's supported list is signed with its registered symbol and decimals. For any other token, send a form-D descriptor under transaction.token — contract, to, amount, decimals and optionally symbol (without contract — or its aliases assetId / address — the descriptor is ignored) — the bridge signs with no network access and uses the decimals you supply. See Core Concepts → Token descriptors.
await dcent.sign({
method: 'signTransaction',
chainId: 'stacks:1/slip44:5757',
payload: {
keyPath: "m/44'/5757'/0'/0/0",
transaction: {
txType: "contractCall",
contractAddress: "SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR",
contractName: "arkadiko-token",
functionName: "transfer",
functionArgs: [
1000000, // amount in token base units (DIKO, 6 decimals)
"SP0000000000000000006YNMHVRQZ0", // sender — your device account
"SP0000000000000000006AZVJGZ4FR", // recipient
"" // memo
],
nonce: 0,
fee: 180
}
}
})
| Field | Type | Required | Source | Description |
|---|---|---|---|---|
txType | enum | Required | App | contractCall — SIP-010 transfer only. Any other Clarity function is rejected with -32602 |
contractAddress | string | Required-Real | App | Deployer address of the token contract (case-sensitive) |
contractName | string | Required-Real | App | Contract name, e.g. arkadiko-token (case-sensitive) |
functionName | string | Required | App | transfer for SIP-010 |
functionArgs | array | Required-Real | App | [amount, sender, recipient, memo]; plain values, or { type, value } objects whose value is a string or number. ClarityValue objects whose value is a bigint cannot be JSON-serialized, so sign() rejects them with a ProviderError (-32602) |
nonce | number | Required-Real | App | Real, current account nonce — the app must supply it; not auto-filled |
fee | number | Optional | App | Transaction fee in microSTX. If omitted, the transaction is signed with fee 0 — always send a real fee |
postConditions / postConditionMode / anchorMode | — | Optional | App | Same fields as the STX transfer above, but on DCENT X postConditionMode must be 2 (deny, the default) — 1 (allow) is rejected by the device. If you send postConditions, at least one must be a fungible guard on the sender and this token with Equal / Less / LessEqual and an amount not above the transfer amount, otherwise -32602 |
For SIP-010, amount is in the token's own base units (per its decimals), not microSTX — DIKO has 6 decimals, so 1000000 = 1 DIKO. If you omit postConditions, the wallet builds a single Equal guard for the transfer.
Variant — SIP-010 token transfer (form-D descriptor)
Use this shape for any SIP-010 token, including one DCENT does not already support. The wallet builds the SIP-010 transfer call from transaction.token.
await dcent.sign({
method: 'signTransaction',
chainId: 'stacks:1/slip44:5757',
payload: {
keyPath: "m/44'/5757'/0'/0/0",
transaction: {
token: {
contract: "SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4.sbtc-token::sbtc-token",
to: "SP000000000000000000002Q6VF78",
amount: "100000", // token base units (sBTC, 8 decimals)
decimals: 8,
symbol: "sBTC"
},
nonce: "0",
fee: "180",
anchorMode: 3
}
}
})
| Field | Type | Required | Source | Description |
|---|---|---|---|---|
token.contract | string | Required-Real | App | principal.contractName, plus ::assetName (e.g. …sbtc-token::sbtc-token). The ::assetName suffix is required for a token DCENT does not already support — without it the request fails with -32602. For a token DCENT already supports, send principal.contractName without the suffix: with it the registered entry is not matched, so decimals becomes required and your values are used |
token.to | string | Required-Real | App | Recipient Stacks address (SP…) |
token.amount | string | Required | App | Amount in the token's base units (positive integer) |
token.decimals | number | Required for unsupported tokens | App | Token decimals. A token DCENT does not already support fails with -32602 without it |
token.symbol | string | Optional | App | Token symbol |
from | string | Optional | App | Sender — your device Stacks account (SP…). sender (read before from), from_address, fromAddress, owner_address and ownerAddress are also read. If none is sent, the signing account is used |
nonce | string | Required-Real | App | Real, current account nonce — the app must supply it; not auto-filled |
fee | string | Optional | App | Transaction fee in microSTX. If omitted, the transaction is signed with fee 0 — always send a real fee |
postConditions / postConditionMode / anchorMode | — | Optional | App | Same rules as the contractCall variant above |
Response
| Field | Type | Description |
|---|---|---|
header.status | string | success on success; failure otherwise |
body.command | string | signTransaction |
body.parameter.signature | string | The broadcast-ready serialized signed Stacks transaction (hex) — a full serialized signed transaction in Stacks wire format, not a bare signature. Broadcast these bytes through a Stacks node or library. |
{
"header": {
"version": "1.0",
"status": "success",
"response_from": "signTransaction"
},
"body": {
"command": "signTransaction",
"parameter": {
"signature": "<signed serialized tx hex>"
}
}
}
On a request-level failure, header.status === 'failure' and body.error = { code, message }; argument errors caught in the connector throw or reject instead (see Error Codes).
Common Mistakes
Amounts not in microSTX — native STX amount / fee are microSTX (1 STX = 1,000,000). SIP-010 amounts use the token's base units instead. Case-sensitive contract identifiers — contractAddress and contractName must match the deployed contract exactly, or the call is rejected. Wrong sender / recipient in functionArgs — functionArgs[1] (sender) must be your own device Stacks account (SP…) — the bridge does not check it. Wrong network — the network comes from chainId (a network field is ignored): stacks:1/slip44:5757 for mainnet; testnet (stacks:2147483648/slip44:5757) is supported; on testnet send tokens as a form-D descriptor with decimals (see Core Concepts → Token descriptors).