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 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 | ✗ |
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 below 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, so addressFormat is not used. The value returned is the implicit account id — 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 — the 64-character lowercase hex of the ed25519 public key |
{
"header": {
"version": "1.0",
"status": "success"
},
"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). 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
| Field | Type | Required | Source | Description |
|---|---|---|---|---|
type | enum | Required | App | transfer |
sender | string | Required-Real | Wallet | Device NEAR account (e.g. name.near); must exist on-chain |
recipient | string | Required | App | Recipient account id |
amount | string | Required | App | yoctoNEAR; 1 NEAR = 1e24 |
blockHash | string | 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 and it disagrees with the derived value the request fails with -32602 |
Request
await dcent.sign({
method: 'signTransaction',
chainId: 'near:mainnet/slip44:397',
payload: {
keyPath: "m/44'/397'/0'",
transaction: {
"type": "transfer",
"family": "near",
"symbol": "NEAR",
"decimals": 24,
"sender": "sender.near",
"recipient": "receiver.near",
"amount": "1000000000000000000000000",
"blockHash": "GJp9NRJGBnXqWJAKFxkzD8p9cJTiSNi1J3UWKVBbcfRw",
"nonce": 0,
"fee": "100000000000000000000"
}
}
})
Response
{
"header": {
"status": "success"
},
"body": {
"command": "signTransaction",
"parameter": {
"signature": "ed25519:…"
}
}
}
Response fields
| Field | Type | Description |
|---|---|---|
header.status | string | success on success |
body.command | string | signTransaction |
body.parameter.signature | string | The ed25519 signature (base58, ed25519: prefix) the device produced over the borsh-encoded NEAR transaction hash. Combine it with the transaction to assemble the borsh-serialized SignedTransaction, then broadcast via broadcast_tx_commit. Returned identically for the native, NEP-141, and NEP-171 variants below. |
Variant — NEP-141 token (ft_transfer)
Token model: form-D descriptor. Always send the token under transaction.token with its symbol and trustworthy decimals (read from the chain yourself) — the bridge signs with no network access and never looks symbol / decimals up, so without the descriptor it fails closed with -32602. 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-Real | Wallet | Device NEAR account; must exist on-chain |
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 | Required | App | e.g. "30000000000000" (30 TGas) |
actions[].params.deposit | string | Required | App | "1" yoctoNEAR (NEP-141 security requirement) |
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 synthesizes the token screen (e.g. USDC 1.0 → receiver.near). The bridge does not query ft_metadata over RPC: it signs with no network access, so the decimals you supply are what the device shows. 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.
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 amount 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).