Skip to main content

Filecoin (FIL)

Sign Filecoin Lotus Messages. The app builds a complete message (nonce, gas, value in attoFIL) and the device signs it with its secp256k1 key by keyPath.

FieldValue
FamilyFilecoin
coinType461
keyPathm/44'/461'/0'/0/<accountIdx>
amount unitattoFIL (1 FIL = 1e18)
chainIdfil:f/slip44:461

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

getAddress — account address​

Retrieves the Filecoin account address for a chainId + keyPath. Returns an f1 (secp256k1) address derived at the keyPath. Call this before building a message so from matches the device account.

FieldTypeRequiredSourceNotes
chainIdstringRequiredAppfil:f/slip44:461 (mainnet); the Calibration testnet is fil:t/slip44:461 (t1 addresses)
keyPathstringRequiredAppBIP-44 path; default m/44'/461'/0'/0/0

Request

await dcent.getAddress({
chainId: 'fil:f/slip44:461',
keyPath: "m/44'/461'/0'/0/0"
})

Response

FieldTypeNotes
body.parameter.addressstringFilecoin address — f1 (secp256k1), derived at keyPath
body.commandstring"getAddress"
header.statusstring"success" on completion
{
"header": {
"version": "1.0",
"status": "success",
"response_from": "getAddress"
},
"body": {
"command": "getAddress",
"parameter": {
"address": "f1…"
}
}
}

signTransaction — Lotus Message​

payload.transaction:

{
"to": "f1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahaui6xa",
"from": "f1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahaui6xa",
"nonce": 0,
"value": "1000000000000000000",
"gasLimit": 500000,
"gasFeeCap": "100000",
"gasPremium": "100000",
"method": 0,
"params": ""
}
FieldTypeRequiredSourceNotes
tostringRequired-RealAppRecipient: f1…, f410f…, or a 0x… EVM address (signed as its f410f form; on testnet the t1… / t410f… forms). f3 (BLS) and f0 (ID) recipients fail with -32603
fromstringRequired-RealWalletYour device account. It must be present, but it is not checked and not signed — the signed message's From is always your account's address derived from keyPath (f1… on mainnet)
noncenumberRequired-RealAppReal, current account nonce — the app must supply it; not auto-filled
valuestringRequiredAppattoFIL; "1000000000000000000" = 1 FIL
gasLimitnumberRequiredRPCFrom GasEstimateMessageGas
gasFeeCapstringRequiredRPCattoFIL per gas unit (max)
gasPremiumstringRequiredRPCattoFIL tip per gas unit
methodnumberOptionalApp0 = plain transfer (also the default when omitted or null). Only 0 (Transfer) can be signed — any other non-negative safe integer → -32601; a negative or non-integer value → -32602
paramsstringOptionalAppMust be empty (""), null or omitted — non-empty base64 actor params → -32601; a non-string or non-base64 value → -32602

Request

await dcent.sign({
method: 'signTransaction',
chainId: 'fil:f/slip44:461',
payload: {
keyPath: "m/44'/461'/0'/0/0",
transaction: {
to: 'f1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahaui6xa',
from: 'f1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahaui6xa',
nonce: 0,
value: '1000000000000000000',
gasLimit: 500000,
gasFeeCap: '100000',
gasPremium: '100000',
method: 0,
params: ''
}
}
})

Response

FieldTypeNotes
body.parameter.signaturestringThe device's secp256k1 signature over the message, as hex — not a signed message. On DCENT X it is 65 bytes (r‖s‖recovery id). To broadcast, build the Lotus Message yourself and call MpoolPush with { Message, Signature: { Type: 1, Data: <signature as base64> } }. The Message must match what was signed: From = the getAddress result for the keyPath, To in its f410f form (t410f on testnet) if you passed a 0x address, Method 0, Params "", Version 0, and the same nonce, value and gas values.
body.commandstring"signTransaction"
header.statusstring"success" on completion
{
"header": {
"version": "1.0",
"status": "success",
"response_from": "signTransaction"
},
"body": {
"command": "signTransaction",
"parameter": {
"signature": "<secp256k1 signature hex>"
}
}
}
info

The device signs the CBOR-serialized message body. The signed From is always your secp256k1 account's address derived at keyPath (f1… on mainnet) — the from you send is not used. BLS (f3) keys are not supported.

Common Mistakes​

danger

Amounts not in attoFIL — value/gasFeeCap/gasPremium are attoFIL strings; 1 FIL = 1e18. BLS (f3) from — only secp256k1 (f1) accounts are supported; the signed From is always your account's address derived at keyPath. Stale nonce / underestimated gas — refresh nonce and the gas* fields from a live node right before signing. Non-empty params with method: 0 — plain transfers must use method 0 and params "".