Skip to main content

Algorand (ALGO)

Sign Algorand transactions. Provide a transaction object with the suggested-params round window; the device signs the encoded transaction by its keyPath. Both native ALGO payments (pay) and ASA token transfers (axfer) are supported.

FieldValue
coinType283
keyPathm/44'/283'/<accountIdx>'/0/0
addressFormatomit or legacy (default account) / ledger
amount unitmicroAlgo
chainIdalgorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73k/slip44:283
chainId · Testnetalgorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDe/slip44:283

Supported Methods​

MethodSupported
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.

MethodDCENT Biometric WalletDCENT X
getAddress2.29.0 or higher1.0.0 or higher
signTransaction2.29.0 or higher1.0.0 or higher
info

The Ledger account (addressFormat: 'ledger', below) needs DCENT Biometric Wallet firmware 2.36.2 or higher and DCENT X firmware 1.0.1 or higher.

addressFormat — Ledger account​

Algorand has two accounts on the same keyPath: DCENT's default account and a Ledger account derived with Ledger's BIP32-Ed25519 scheme. The two derive different keys, so they have different addresses. Because the keyPath is identical, it cannot tell them apart — addressFormat is the only thing that selects the Ledger account.

addressFormatAccount
omitted, or legacyDCENT default account
ledgerLedger account (BIP32-Ed25519)

Send the same value on getAddress and on signTransaction for that account — pay and axfer both follow it; add it to the payload next to keyPath. legacy is the value getAccountInfo reports for the default account, so passing it back is fine; standard, segwit-wrapped, segwit-native and taproot are rejected with -32602. The testnet chainId has the same two accounts. from should be the address getAddress returned for the same addressFormat; the bridge does not check it.

getAddress — account address​

Retrieves the Algorand account address. Returns a 58-character base32 address (the ed25519 public key plus a 4-byte checksum). Call before building a transaction so the from field matches the device account.

FieldTypeRequiredSourceNotes
chainIdstringRequiredAppFull CAIP-19 — algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73k/slip44:283
keyPathstringRequiredAppBIP-44 — m/44'/283'/0'/0/0
addressFormatstringOptionalAppOmit (or legacy) for the default account; ledger for the Ledger account — see addressFormat

Request

await dcent.getAddress({
chainId: 'algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73k/slip44:283',
keyPath: "m/44'/283'/0'/0/0"
})

Response

FieldTypeDescription
header.statusstringsuccess on completion
body.commandstringgetAddress
body.parameter.addressstringAlgorand account address — 58-char base32 (ed25519 public key + 4-byte checksum)
{
"header": {
"version": "1.0",
"status": "success",
"response_from": "getAddress"
},
"body": {
"command": "getAddress",
"parameter": {
"address": "737777777777777777777777777777777777777777777777777UFEJ2CI"
}
}
}
info

Algorand has a single address encoding — the returned address already encodes the public key. The response also carries a pubkey field (0x-prefixed hex, which may be empty — "0x"); use address as the account identifier. addressFormat does not change the encoding; it picks the account (see addressFormat).

signTransaction​

Variant — payment (pay)​

payload.transaction:

{
"type": "pay",
"from": "737777777777777777777777777777777777777777777777777UFEJ2CI",
"to": "737777777777777777777777777777777777777777777777777UFEJ2CI",
"amount": 1000000,
"fee": 1000,
"firstRound": 1,
"lastRound": 1000,
"genesisID": "mainnet-v1.0",
"genesisHash": "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiHc0CYz/uo="
}
FieldTypeRequiredSourceDescription
typestringOptionalAppNot validated: if omitted, or any value other than axfer / asset-transfer, the request is signed as a native ALGO payment. Send pay
fromstringRequired-RealWalletDevice Algorand account; must own the funds
tostringRequired-RealAppRecipient address
amountnumberRequiredAppmicroAlgo (1 ALGO = 1,000,000)
feenumberOptionalAppmicroAlgo — set at least the network minimum (1000); the bridge does not enforce it. A negative or non-finite value, or one that does not parse as a number (e.g. "abc", true, ""), is rejected with -32602, and a non-integer value or one above 2^53−1 fails with -32603; if omitted the transaction is signed with fee 0
firstRound / lastRoundnumberRequired-RealAppReal validity window — the app must supply current values; not auto-filled
genesisIDstringRequiredAppe.g. mainnet-v1.0
genesisHashbase64Required-RealRPCNetwork genesis hash; pins the chain

Request

await dcent.sign({
method: 'signTransaction',
chainId: 'algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73k/slip44:283',
payload: {
keyPath: "m/44'/283'/0'/0/0",
transaction: {
"type": "pay",
"from": "737777777777777777777777777777777777777777777777777UFEJ2CI",
"to": "737777777777777777777777777777777777777777777777777UFEJ2CI",
"amount": 1000000,
"fee": 1000,
"firstRound": 1,
"lastRound": 1000,
"genesisID": "mainnet-v1.0",
"genesisHash": "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiHc0CYz/uo="
}
}
})

Response

FieldTypeDescription
header.statusstringsuccess on completion
body.commandstringsignTransaction
body.parameter.signaturestringThe msgpack-encoded signed Algorand transaction { sig, txn } as hex without 0x (not a bare signature) — hex-decode it to bytes before POSTing to algod /v2/transactions. Same shape for both pay and axfer.
{
"header": {
"version": "1.0",
"status": "success",
"response_from": "signTransaction"
},
"body": {
"command": "signTransaction",
"parameter": {
"signature": "<signed tx>"
}
}
}

Variant — ASA token transfer (axfer)​

info

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.

payload.transaction:

{
"type": "axfer",
"assetIndex": 31566704,
"from": "737777777777777777777777777777777777777777777777777UFEJ2CI",
"to": "737777777777777777777777777777777777777777777777777UFEJ2CI",
"amount": 1000,
"fee": 1000,
"firstRound": 1,
"lastRound": 1000,
"genesisID": "mainnet-v1.0",
"genesisHash": "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiHc0CYz/uo="
}
FieldTypeRequiredSourceDescription
typeenumRequired-RealAppaxfer for ASA token transfer — not checked: if omitted, assetIndex is ignored and a native ALGO payment is signed
assetIndexnumberRequired-RealAppOn-chain ASA id (e.g. 31566704 = USDC, decimals 6). If it is missing or not a positive integer, the request is not rejected — it is signed as a native ALGO payment of amount microAlgo
fromstringRequired-RealWalletDevice account; must hold the ASA
tostringRequired-RealAppRecipient; must have opted in to the ASA
amountnumberRequiredAppBase units of the ASA (e.g. 1000 = 0.001 USDC)
feenumberOptionalAppmicroAlgo (ASA fees are always paid in ALGO). If omitted, the transaction is signed with fee 0 — send a real fee
firstRound / lastRound / genesisHash / genesisIDnumber / base64 / stringRequired-RealAppSame as the pay variant — a missing one → -32602
info

The USDC ASA (assetIndex 31566704) is registered only on Algorand mainnet (for both the default and the Ledger account). A bare axfer for it on another chain, such as the testnet chainId, raises a lookup miss (-32602).

Variant — ASA descriptor​

Always pass a form-D token descriptor instead of a bare axfer. The bridge builds the axfer envelope from token.contract (the ASA id), token.to and token.amount, so any assetIndex can be signed — including an unregistered one, as long as token.decimals is supplied.

payload.transaction:

{
"token": {
"contract": "312769",
"to": "737777777777777777777777777777777777777777777777777UFEJ2CI",
"amount": "1000",
"decimals": 6,
"symbol": "USDt"
},
"from": "737777777777777777777777777777777777777777777777777UFEJ2CI",
"fee": 1000,
"firstRound": 1,
"lastRound": 1000,
"genesisID": "mainnet-v1.0",
"genesisHash": "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiHc0CYz/uo="
}
FieldTypeRequiredSourceDescription
token.contractstringRequired-RealAppASA id as a positive-integer string — must match /^[1-9][0-9]*$/ (non-numeric → -32602; a JSON number such as 312769 is not recognised as a descriptor and fails with -32603). Listing on the supported-token page not required.
token.tostringRequired-RealAppRecipient; must have opted in to the ASA
token.amountstringRequiredAppBase units of the ASA (decimals applied for display)
token.decimals / token.symbolnumber / stringOptional (token.decimals Required for an unregistered ASA)AppDisplay metadata synthesized when the ASA is unregistered. An unregistered ASA without token.decimals is rejected with -32602
fromstringRequired-RealWalletDevice account (top-level; sender / from_address / fromAddress / owner_address / ownerAddress are also accepted). If it is missing the request fails with -32603
feenumberOptionalAppmicroAlgo. If omitted, the transaction is signed with fee 0 — send a real fee; a negative or non-finite value, or one that does not parse as a number (e.g. "abc", true, "") → -32602; a non-integer value or one above 2^53−1 → -32603
firstRound / lastRound / genesisHash / genesisIDnumber / base64 / stringRequired-RealAppReal, current suggested-params values — the app must supply them; not auto-filled. A missing one → -32602
info

Response shape is the same broadcast-ready msgpack-encoded signTransaction as the pay / axfer variants — the descriptor only changes how the axfer is built, not the output.

Common Mistakes​

danger

Amounts not in microAlgo — 1 ALGO = 1,000,000; the fee minimum is 1000 microAlgo. ASA recipient not opted in — an axfer to an account that has not opted in to the asset is rejected at broadcast. Wrong chain for an ASA — a bare axfer for an ASA registered on Algorand mainnet fails the asset lookup with -32602 on another network; use the form-D descriptor with token.decimals there. Stale round window — firstRound/lastRound come from suggested params; an expired validity window is rejected.