Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,8 @@ jobs:
- name: Check images 🖼
run: pnpm run check:images

- name: Check anchors 🔗
run: pnpm run check:anchors

- name: Build
run: pnpm run build
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"preview": "vitepress preview",
"lint": "eslint .",
"check:images": "node scripts/check-images.mjs",
"check:anchors": "node scripts/check-anchors.mjs",
"lint-staged": "lint-staged",
"prepare": "husky"
},
Expand Down
4 changes: 2 additions & 2 deletions premium/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ See [Payment Process](/premium/payment) for step-by-step instructions.
After successful payment, generate your **API Key** and **API Secret**
by clicking the **Create** button on your [subscription page](https://rotki.com/home/subscription).

For detailed instructions, see [Creating API Keys](/premium/api-keys#creating-api-keys).
For detailed instructions, see [Creating API Credentials](/premium/api-keys#creating-api-credentials).

### 4. Add Keys to the App

Navigate to **API Keys** → **rotki Premium** in the rotki application and enter the
**API Key** and **API Secret** generated in the last step to activate the premium features
included in your subscription.

For detailed instructions, see [Using API Keys in the App](/premium/api-keys#using-api-keys-in-the-app).
For detailed instructions, see [Using API Credentials in the App](/premium/api-keys#using-api-credentials-in-the-app).

## Managing Your Premium Subscription

Expand Down
99 changes: 99 additions & 0 deletions scripts/check-anchors.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/**
* Internal anchor gate.
*
* VitePress validates that a linked *page* exists, but not that the `#anchor` on the end of it
* does. So renaming a heading silently breaks every link pointing at it, and nothing reports it.
* That has already happened twice in this repo: "API Keys" became "API Credentials" while two
* links in premium/index.md kept pointing at the old slug, and the app's own importAddressBook
* deep link pointed at a heading that had never rendered that way.
*
* Run with `pnpm run check:anchors`.
*/
import { readdir, readFile } from 'node:fs/promises';
import { join, relative, resolve } from 'node:path';
import process from 'node:process';

const ROOT = resolve(import.meta.dirname, '..');
const SKIP_DIRS = new Set(['node_modules', '.git', '.vitepress', 'dist', 'cache', 'scripts', 'public']);

/** A markdown link to an internal page with an anchor: `](/some/page#the-anchor)`. */
const ANCHORED_LINK = /]\(\/([\w/-]+)#([\w-]+)\)/g;

/** ATX headings. Setext headings are not used in this corpus. */
const HEADING = /^#{1,6} +(.+?)\s*$/gm;

/**
* VitePress slugs a heading by lowercasing it and collapsing every run of non-alphanumeric
* characters into a single hyphen. So "Add / edit events" is `add-edit-events` and
* "Set the backend's arguments" is `set-the-backend-s-arguments`.
*/
function slug(heading) {
return heading
.replace(/`/g, '')
.toLowerCase()
.replace(/[^\da-z]+/g, '-')
.replace(/^-|-$/g, '');
}

async function walk(dir) {
const found = [];
for (const entry of await readdir(dir, { withFileTypes: true })) {
if (entry.isDirectory()) {
if (SKIP_DIRS.has(entry.name))
continue;
found.push(...await walk(join(dir, entry.name)));
}
else if (entry.name.endsWith('.md')) {
found.push(join(dir, entry.name));
}
}
return found;
}

/** A link target resolves to `<path>.md` or `<path>/index.md`. */
function pageFor(path, pages) {
return pages.get(path) ?? pages.get(`${path.replace(/\/$/, '')}/index`);
}

async function main() {
const files = await walk(ROOT);
const pages = new Map(files.map(file => [
relative(ROOT, file).split('\\').join('/').replace(/\.md$/, ''),
file,
]));

const anchorsByPage = new Map();
for (const [path, file] of pages) {
const content = await readFile(file, 'utf8');
anchorsByPage.set(path, new Set([...content.matchAll(HEADING)].map(match => slug(match[1]))));
}

const errors = [];
for (const file of files) {
const content = await readFile(file, 'utf8');
const source = relative(ROOT, file);

for (const [, path, anchor] of content.matchAll(ANCHORED_LINK)) {
const page = pageFor(path, pages);
if (!page) {
errors.push(`${source}\n links to /${path}#${anchor}, but no such page exists`);
continue;
}

const resolved = relative(ROOT, page).split('\\').join('/').replace(/\.md$/, '');
if (!anchorsByPage.get(resolved)?.has(anchor))
errors.push(`${source}\n links to /${path}#${anchor}, but that page has no such heading`);
}
}

if (errors.length > 0) {
console.error(`\n${errors.length} broken anchor${errors.length === 1 ? '' : 's'} found:\n`);
for (const error of errors)
console.error(` ✖ ${error}\n`);
process.exit(1);
}

console.log(`✔ every internal #anchor across ${files.length} pages resolves to a heading`);
}

await main();
14 changes: 14 additions & 0 deletions usage-guides/advanced/data-directory.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@ rotki saves user data by default in a different directory per OS. For each OS, d

Before v1.6.0, rotki was saving data in `$USER/.rotkehlchen`. From v1.6.0, that directory got migrated to the OS equivalent standard directory, and it should be safe for users to delete the old directory as long as the new directory contains the migrated DB.

## Opening it from the app

In the desktop app you do not have to go looking for either directory. The **Help** menu in the
application menu bar has two entries that open them in your file manager:

- **Logs Directory** — where rotki writes its log files.
- **Data Directory** — the directory the running backend actually resolved, which is not necessarily
the default above if you configured a different one.

> [!NOTE]
> **Data Directory** stays disabled until the backend is running, because until then rotki does not
> yet know which directory is in use. Both entries are in the desktop application's own menu bar, not
> the in-app `?` menu, so they are not available when running rotki in a browser through Docker.

A very good idea for the rotki data directory would be to make frequent backups of it as it contains all of the data of all of your rotki accounts and cache data for historical price queries.

> [!WARNING]
Expand Down
12 changes: 12 additions & 0 deletions usage-guides/data-management/address-book.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ rotki provides an address book for blockchains. This replaces addresses with nam
> 5. Hardcoded Mappings
> 6. ENS names.

## Filtering the address book

The address book uses the same filter bar as the rest of rotki, with a pill for `Address`, `Name` and
`Chain`. Chains are shown with their logo and name and picked from a list. There is also a
`Strict chain` pill: with it added, only entries recorded for that exact chain are shown, rather than
also including entries that apply to every chain.

Both the chain selector and the strict-chain checkbox used to sit beside the bar; they are pills
inside it now, so there is a single place to filter from. See
[Filtering history events](/usage-guides/history/filtering) for the shared syntax and keyboard
handling.

## Importing address book names (CSV)

You can add multiple address book entries at once with CSV import. You can find the menu in the three dots `⋮` menu here.
Expand Down
9 changes: 9 additions & 0 deletions usage-guides/data-management/assets.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ There are also some other fields that are completely optional and expand if you
> [!NOTE]
> Underlying tokens only apply to asset type of `EVM Token`.

### Hyperliquid Core tokens

Native tokens on Hyperliquid Core are first class assets, with the asset type `Hyperliquid Token`.
You can add or edit their metadata here the same way as any other token, search for them by name,
symbol or token ID, and use them in asset mappings.

Their identifier is a **token ID** rather than a contract address, so the address field takes that ID
and, like other token types, cannot be changed after the asset is created.

## Adding/editing a custom asset

There is a lot of assets that rotki can't automatically track and they don't fit into traditional crypto assets. For example an ETF, real estate, ancient coins, valuable art etc. To represent those you can create custom assets, and then add a manual balance of those assets.
Expand Down
7 changes: 7 additions & 0 deletions usage-guides/data-management/prices.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ The `Oracle Prices` page has two tabs:

![Oracle prices listing](/images/usage-guides/data-management/prices/oracle_list.webp)

The **Prices** tab uses the same filter bar as the rest of rotki, with a pill for the `From asset`,
the `To asset`, the `Source` oracle and the `Period`. Assets are shown with their icon and symbol,
and each oracle by the name the table itself uses rather than its raw identifier. The two separate
start and end date filters are now one period pill with a date picker for each end. See
[Filtering history events](/usage-guides/history/filtering) for the shared syntax and keyboard
handling.

Each row in the **Prices** tab can be edited or deleted. Use this when you know the cached price is wrong (for example, an oracle returned a stale or incorrect value) and want to override it without adding a separate manual entry. Deleting an entry removes the cached value entirely; the next lookup will hit the oracle again.

Click the edit icon on a row to open the edit dialog:
Expand Down
7 changes: 6 additions & 1 deletion usage-guides/integrations/calendar.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ Here the non-obvious fields are:

rotki can also create automatic events based on your on-chain activity. The events that rotki currently can check include:

- ENS Expiration & Renewal
- **Name service expiry and renewal** — for ENS, Basenames and Gwei Name Service (`.gwei`) names you hold.
- **Airdrop claim deadlines** — so a claimable airdrop does not expire unnoticed.
- **Yearn vesting escrows** — one entry at the cliff date and one when the escrow is fully vested.
- **CRV vote escrow** — when your locked CRV lock period ends.
- **VELO and AERO vote escrow** — when a veNFT lock period ends.
- **L2 bridging** — when funds bridged to or from an L2 become available.

You can customize how rotki handles automatic events by clicking the `setting` icon at the top.

Expand Down
12 changes: 12 additions & 0 deletions usage-guides/integrations/external-services.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,18 @@ To connect your Gnosis Pay account:

> **Note**: The access token only provides read-only access to your Gnosis Pay data. The "Sign in with Ethereum" authentication process described above is mandated by Gnosis Pay's API requirements, not a design choice by rotki. rotki simply integrates with their authentication system as required.

### Safe migration

Gnosis Pay replaced user Safes during its security migration, so an account can have both a previous
and a current Safe. rotki notices when you track only one of the two and tells you which address is
missing:

- If you track only the **previous** Safe, add the new active one to keep tracking future activity.
- If you track only the **new** Safe, add the previous one to keep its historical activity.

Add the named address as a normal blockchain account on Gnosis. Tracking both means your history
covers the whole account rather than stopping or starting at the migration.

## The Graph

rotki uses The Graph to obtain Balancer balances and particular ENS data. You can create one [here](https://thegraph.com/studio/apikeys).
Expand Down
4 changes: 4 additions & 0 deletions usage-guides/portfolio/accounts.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,7 @@ You can see the list of aggregated assets from Blockchain Accounts from menu `Ba
You can also see the breakdown of the assets, which locations they belong to, whether they are in the wallet, or being put into some protocol.

![Aggregated list of assets from blockchain accounts](/images/usage-guides/portfolio/accounts/blockchain_balances.webp)

The search box above the table finds an asset by name, symbol or **contract address**, and shows an
exact symbol or name match first. Pasting a contract address is the quickest way to identify a token
whose name you do not know, or to tell apart several tokens sharing a symbol.
2 changes: 1 addition & 1 deletion usage-guides/portfolio/dashboard.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ The assets table shows all your holdings aggregated across all sources. Each row
### Table Features

- **Sorting** — Click any column header to sort. Default sort is by value (descending).
- **Search** — Use the search box to filter by asset name or symbol.
- **Search** — Use the search box to filter by asset name, symbol, or **contract address**. Pasting a contract address is the quickest way to pin down a token whose name you do not know, or one that shares a symbol with several others. An asset whose symbol or name is exactly what you typed is shown first, so searching for `eth` finds ETH rather than burying it under every token containing those letters. Matches appear as you type.
- **Pagination** — Configure how many rows to display per page using the "Rows per page" dropdown.
- **Column Visibility** — Click the column configuration button to toggle optional columns ("% of Net Value" and "% of Group").
- **Row Expansion** — Click the expand arrow on a row to see a detailed breakdown of where that asset is held (per chain, per exchange, per protocol).
Expand Down
10 changes: 10 additions & 0 deletions usage-guides/settings/account.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ View information about your user and global database, such as directory, size, a

Create new database backups, delete backups, and download backups locally.

### Cloud sync integrity checks

For premium users syncing the database to rotki's cloud, rotki verifies the database before it moves
in either direction. It runs an integrity check before uploading a backup, and again on a downloaded
copy before that copy replaces your local database.

If a check fails, the sync is abandoned and rotki reports the problem rather than continuing. That
stops a corrupt local database from overwriting a good remote copy, and a corrupt download from
overwriting a good local one.

### Purging Data

rotki keeps a lot of data cached locally. Clean this data periodically from the "Manage Data" section in the settings. Remove specific exchanges by first removing any active API keys.
Expand Down
23 changes: 23 additions & 0 deletions usage-guides/settings/blockchain.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,29 @@ Which means, in practice:
- **Scroll** needs a **Blockscout key**, since Etherscan no longer serves Scroll and Routescan does not cover it.
- **Binance SC** needs a **paid Etherscan plan**, since it is the only indexer that serves the chain.

### Suppressing indexer notifications

When a chain has no usable indexer, rotki raises a **"No indexers available"** notification for it.
If it names a chain you have no intention of configuring, the notification offers to suppress it:
confirm, and rotki stops raising it for that chain.

Suppressed chains are listed under **Suppressed "No indexers available" notifications** on this page.
Remove a chain from that list to start showing its notification again.

Suppression is per chain, so silencing one never silences another. Even without suppressing anything,
a notification you keep ignoring backs off on its own — see
[how often a notification repeats](/usage-guides/utilities/#how-often-a-notification-repeats).

### Recommended settings after upgrading

Some releases change which indexer a chain should use by default. When that happens and you had
already chosen your own order for the affected chain, rotki shows a recommended-settings dialog after
the upgrade rather than silently overriding your choice.

Upgrading to 1.44 shows this for **Gnosis** if you have Gnosis events and had picked your own order.
It explains that Etherscan no longer serves Gnosis for free, shows which of the two keys you already
have, and preselects the order matching them. You can accept the recommendation or keep what you had.

## Price Oracle Settings

![Change the order of price sources](/images/usage-guides/settings/blockchain/price_oracle_order.webp)
Expand Down
10 changes: 10 additions & 0 deletions usage-guides/settings/general.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ Specify whether the application can submit anonymous usage analytics. This helps

Specify whether to automatically detect tokens and refresh balances by periodically checking historical events.

#### Auto detect tokens on login

Also run token detection after the first balance scan following login, so newly acquired tokens show up without waiting for the next periodic run. This is opt-in and **disabled by default**.

#### Auto detect tokens cooldown

The minimum time between two on-login detection runs, from 1 to 168 hours (7 days). Logging in again inside the cooldown skips the scan, so several logins in a day do not each trigger one. Triggering detection yourself from the accounts page ignores the cooldown.

This setting only appears when **Auto detect tokens on login** is enabled.

#### Display Date in Localtime

Specify whether dates in CSV exports should be displayed in local time rather than UTC. Enabled by default.
Expand Down
18 changes: 18 additions & 0 deletions usage-guides/tax-accounting/accounting-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,24 @@ You can create custom rules that override the defaults for specific combinations

See [Add/Edit accounting rules](/usage-guides/settings/accounting#add-edit-accounting-rules) for how to create them in the UI. You can also [import/export accounting rules](/usage-guides/settings/accounting#import-export-accounting-rules) as JSON to back them up or share them.

### Seeing which events a rule governs

A rule and the events it applies to are one click apart in either direction:

- From a rule, use **View events matching this rule**. It opens the history events page with the
filter already set to that rule's event type, subtype and counterparty, so you see exactly what it
affects before changing it.
- From an event, the [edit accounting rule](/usage-guides/history/events#edit-accounting-rule) action
takes you to the rule that governs it.

### Filtering the rules

The rules table uses the same filter bar as the rest of rotki, with a pill for `Event type`,
`Event subtype` and `Counterparty`. Types and subtypes are picked from a list and read as words
rather than as their raw values, and counterparties are shown with their protocol icon and name. See
[Filtering history events](/usage-guides/history/filtering) for the shared syntax and keyboard
handling.

### Limitations

- **Counterparty must be a known protocol**: You can only create rules for counterparties that rotki recognizes (e.g., "uniswap-v3", "aave", "makerdao_dsr"). Custom smart contract addresses cannot currently be used as counterparties for accounting rules. Support for custom counterparties is tracked in [rotki/rotki#9803](https://github.com/rotki/rotki/issues/9803).
Expand Down
8 changes: 8 additions & 0 deletions usage-guides/utilities/help.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ The Help & Support menu provides quick access to:
- **Discord** - Join the community and get support
- **Github** - Review the code and open issues
- **Twitter / X** - Follow for updates
- **About** - Version information, including the data directory currently in use
- **Browser Log** - Download the browser log file

> [!NOTE]
> The desktop app also has its own **Help** menu in the application menu bar, which is a different
> menu with different entries. That is where you will find **Logs Directory** and **Data Directory**,
> which open those folders in your file manager — see
> [opening the data directory](/usage-guides/advanced/data-directory#opening-it-from-the-app).

## Report Issue

Expand Down
Loading