NEAR (NEAR)
Sign NEAR Protocol transactions. A plain transfer carries an amount in yoctoNEAR; NEP-141 tokens and NEP-171 NFTs are sent as FunctionCall actions with a JSON args object. The bridge signs with no network access — it looks nothing up and refreshes nothing, so you must send a complete transaction: supply blockHash, nonce and fee yourself — a missing one fails with -32602. publicKey is optional (the bridge derives it offline from the signing key), but a non-blank string publicKey that does not match that derived key is rejected the same way.
| Field | Value |
|---|---|
| Family | NEAR |
| coinType | 397 |
| keyPath | m/44'/397'/<accountIdx>' |
| amount unit | yoctoNEAR |
| chainId | near:mainnet/slip44:397 |
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.24.0 or higher | 1.0.0 or higher |
signTransaction | 2.24.0 or higher | 1.0.0 or higher |
Firmware versions above are for the DCENT Biometric Wallet line — DCENT X supports them from 1.0.0. NEAR token (not native NEAR) requires firmware 2.27.1 or higher.
getAddress — account address
Retrieves the NEAR account for a chainId + keyPath. Call it before building transactions. NEAR has no address variants — omit addressFormat. The value returned is the implicit account id — on DCENT X, the 64-character lowercase hex encoding of the ed25519 public key. Named accounts (e.g. name.near) are created on top of this key on-chain.
| Field | Type | Required | Source | Description |
|---|---|---|---|---|
chainId | string | Required | App | near:mainnet/slip44:397 (CAIP-19) |
keyPath | string | Required | App | BIP-44; default m/44'/397'/0' |
Request
await dcent.getAddress({
chainId: 'near:mainnet/slip44:397',
keyPath: "m/44'/397'/0'"
})
Response
| Field | Type | Description |
|---|---|---|
header.status | string | success on success |
body.command | string | getAddress |
body.parameter.address | string | NEAR implicit account id — on DCENT X, the 64-character lowercase hex of the ed25519 public key |
{
"header": {
"version": "1.0",
"status": "success",
"response_from": "getAddress"
},
"body": {
"command": "getAddress",
"parameter": {
"address": "9c1d…"
}
}
}
Address format: a NEAR implicit account id is the raw ed25519 public key rendered as 64 lowercase hex characters (no 0x prefix; returned this way on DCENT X). It is also the value the device signs with — the same key appears in signTransaction as publicKey in ed25519: base58 form.
signTransaction — <NEAR transaction>
Variant — native transfer
Send the near-api-js Transaction shape (signerId / receiverId / actions[]) with a single Transfer action.
| Field | Type | Required | Source | Description |
|---|---|---|---|---|
signerId | string | Optional | Wallet | Sender account. If omitted, the device's implicit account (64-hex) is used — set it to sign as a named account (e.g. name.near) |
receiverId | string | Required | App | Recipient account id. Missing → -32602 |
actions[] | array | Required | App | Exactly one action. Empty → -32602; more than one, or a type string other than Transfer / FunctionCall (case-sensitive), → -32601; a missing or non-string type, a Transfer without params, or a null action → -32602 (for multiple actions use borsh-serialized extra.serializedActions) |
actions[0].params.deposit | string | Required | App | yoctoNEAR (1 NEAR = 1e24); must be positive, otherwise -32602 |
blockHash | string | Required-Real | App | Required — the app must supply a fresh value (otherwise param_error) |
nonce | number | Required-Real | App | Required — the app must supply a fresh value (otherwise param_error) |
fee | string | Required-Real | App | Total fee in yoctoNEAR. Mapped to the device's fee display; omitting it fails with -32602 |
publicKey | string | Optional | App | Sender's access-key public key (ed25519: base58). The bridge derives it offline from the signing key, so you may omit it; if you do send it as a non-blank string and it disagrees with the derived value the request fails with -32602 |
A { type: 'transfer', sender, recipient, amount } object with only these fields is rejected with -32602.
Request
await dcent.sign({
method: 'signTransaction',
chainId: 'near:mainnet/slip44:397',
payload: {
keyPath: "m/44'/397'/0'",
transaction: {
"signerId": "sender.near",
"receiverId": "receiver.near",
"actions": [
{ "type": "Transfer", "params": { "deposit": "1000000000000000000000000" } }
],
"blockHash": "GJp9NRJGBnXqWJAKFxkzD8p9cJTiSNi1J3UWKVBbcfRw",
"nonce": 0,
"fee": "100000000000000000000"
}
}
})
Response
{
"header": {
"version": "1.0",
"status": "success",
"response_from": "signTransaction"
},
"body": {
"command": "signTransaction",
"parameter": {
"signature": "<borsh SignedTransaction hex>"
}
}
}
Response fields
| Field | Type | Description |
|---|---|---|
header.status | string | success on success |
body.command | string | signTransaction |
body.parameter.signature | string | The borsh-serialized SignedTransaction (the transaction plus the device's ed25519 signature) as hex. To broadcast, convert it to base64 and send it as signed_tx_base64 to the RPC send_tx method. Returned identically for the native, NEP-141, and NEP-171 variants below. |
Variant — NEP-141 token (ft_transfer)
Token model: form-D descriptor. A token on DCENT's supported list signs either way — as the ft_transfer call below or as a form-D descriptor. For any other token, send a form-D descriptor under transaction.token — contract, to, amount, trustworthy decimals (read from the chain yourself) and optionally symbol — the bridge signs with no network access and never looks symbol / decimals up, so an unregistered token without the descriptor fails closed with -32602 (a registered token such as usdt.tether-token.near resolves without one). See Core Concepts → Token descriptors.
Token transfers use the near-api-js Transaction shape (signerId / receiverId / actions[]). The bridge converts the FunctionCall action into a contract call. receiverId is the token contract account and args is a plain JSON object (not base64).
| Field | Type | Required | Source | Description |
|---|---|---|---|---|
signerId | string | Required | Wallet | Device NEAR account; must exist on-chain. Required for a token transfer — without it the request fails with -32603 (the implicit-account default applies only to native transfers and non-token calls) |
receiverId | string | Required-Real | App | Token contract account (e.g. usdt.tether-token.near) |
actions[].params.methodName | string | Required | App | ft_transfer |
actions[].params.args | object | Required | App | { receiver_id, amount }; amount in token base units |
actions[].params.gas | string | Optional | App | e.g. "30000000000000" (30 TGas); defaults to 30 TGas |
actions[].params.deposit | string | Required | App | "1" yoctoNEAR (NEP-141 security requirement). If omitted the bridge signs 0 |
blockHash / nonce | string / number | Required-Real | App | Required — the app must supply a fresh value (otherwise param_error) |
fee | string | Required-Real | App | Total fee in yoctoNEAR. Omitting it fails with -32602 |
Request
await dcent.sign({
method: 'signTransaction',
chainId: 'near:mainnet/slip44:397',
payload: {
keyPath: "m/44'/397'/0'",
transaction: {
"signerId": "sender.near",
"receiverId": "usdt.tether-token.near",
"actions": [
{
"type": "FunctionCall",
"params": {
"methodName": "ft_transfer",
"args": {
"receiver_id": "receiver.near",
"amount": "1000000"
},
"gas": "30000000000000",
"deposit": "1"
}
}
],
"blockHash": "GJp9NRJGBnXqWJAKFxkzD8p9cJTiSNi1J3UWKVBbcfRw",
"nonce": 0,
"fee": "100000000000000000000"
}
}
})
USDT on NEAR has 6 decimals, so amount: "1000000" = 1 USDT. The token base unit is unrelated to yoctoNEAR — only the deposit is in yoctoNEAR.
Unregistered FT tokens. Send the token as a form-D descriptor — transaction.token = { contract, to, amount, decimals, symbol } — and the bridge builds the ft_transfer from it and sends the supplied symbol / decimals to the device with the request (if symbol is omitted, the first 10 characters of the contract are used). Send signerId (your NEAR account) at the top level of transaction as well — without it the request fails with -32603. The bridge does not query ft_metadata over RPC: it signs with no network access, so the decimals you supply are what is sent to the device. There is no silent native fallback — without the descriptor the resolver loud-fails with -32602 rather than signing raw calldata. Playground preset: near-ft-transfer-unregistered — remove its placeholder publicKey before signing (a key that does not match your account is rejected with -32602).
Variant — NEP-171 NFT (nft_transfer)
Same FunctionCall path; receiverId is the NFT contract account and args carries { receiver_id, token_id }.
Request
await dcent.sign({
method: 'signTransaction',
chainId: 'near:mainnet/slip44:397',
payload: {
keyPath: "m/44'/397'/0'",
transaction: {
"signerId": "sender.near",
"receiverId": "nft.contract.near",
"actions": [
{
"type": "FunctionCall",
"params": {
"methodName": "nft_transfer",
"args": {
"receiver_id": "receiver.near",
"token_id": "1"
},
"gas": "30000000000000",
"deposit": "1"
}
}
],
"blockHash": "GJp9NRJGBnXqWJAKFxkzD8p9cJTiSNi1J3UWKVBbcfRw",
"nonce": 0,
"fee": "100000000000000000000"
}
}
})
Common Mistakes
Sender not on-chain — the bridge never reads the sender's access key (it derives the public key offline and makes no RPC call), so signing still succeeds; the transaction is rejected later, at broadcast, because the account has no matching access key. Wrong network — a mainnet account does not exist on testnet (and vice-versa); select the network that matches the account you signed up. Amounts not in yoctoNEAR — native transfer actions[0].params.deposit uses 1 NEAR = 1e24; NEP-141 args.amount uses the token's own base units. Missing FunctionCall deposit — NEP-141/171 transfers require exactly "1" yoctoNEAR, and args must be a JSON object (not base64).