From 184b98722b2c9f0522bf06ddd48ee83a798a665f Mon Sep 17 00:00:00 2001 From: Konstantinos Paparas Date: Thu, 9 Apr 2026 13:34:46 +0200 Subject: [PATCH 1/7] feat: restructure usage-guides into grouped sections Reorganize the flat usage-guides directory into 8 grouped subdirectories mirroring the app navigation: portfolio, history, tax-accounting, data-management, integrations, settings, utilities, and advanced. - Move/rename 22 files into subdirectories - Split accounts-and-balances.md, api-keys.md, customization.md into 9 focused pages - Merge tiny utility pages (search, notes, background-tasks) into one - Add local Vite redirects plugin to generate redirect HTML at build time for all old URLs (with anchor-aware routing for split pages) - Update sidebar with grouped collapsible sections - Rename "Introduction" to "Getting Started" - Group Staking and Statistics under "Tracking" - Improve landing page with NavCards component and move disclaimer below - Add description frontmatter to all 49 content pages for llms.txt - Update ~76 internal cross-references across the docs tree - Fix dead links in premium/devices.md - Exclude redirect paths from vitepress-plugin-llms output --- .vitepress/config.mts | 192 ++++++-- .vitepress/plugins/redirects.ts | 123 +++++ .vitepress/theme/index.ts | 2 + components/NavCards.vue | 99 ++++ contribution-guides/code-profiling.md | 4 + .../contribute-as-developer.md | 4 + contribution-guides/docker-publishing.md | 4 + contribution-guides/feature-requests.md | 4 + contribution-guides/index.md | 6 +- contribution-guides/manual-testing.md | 4 + contribution-guides/python-testing.md | 6 +- contribution-guides/rotki-database.md | 8 +- contribution-guides/vue-typescript.md | 4 + contribution-guides/working-on-issues.md | 4 + contribution-guides/working-with-frontend.md | 4 + faq.md | 20 +- index.md | 25 +- premium/api-keys.md | 4 + premium/devices.md | 8 +- premium/index.md | 4 + premium/payment-methods.md | 4 + premium/payment.md | 4 + premium/plans-and-pricing.md | 4 + premium/referrals.md | 4 + premium/subscription.md | 4 + .../build-from-source.md | 6 +- requirement-and-installation/index.md | 4 + .../packaged-binaries.md | 6 +- .../backend-config.md} | 4 + usage-guides/{ => advanced}/data-directory.md | 6 +- .../database-access.md} | 6 +- .../mobile.md} | 4 + .../{ => advanced}/troubleshooting.md | 4 + usage-guides/customization.md | 445 ------------------ .../{ => data-management}/address-book.md | 6 +- usage-guides/{ => data-management}/assets.md | 6 +- .../prices.md} | 4 + .../tags.md} | 4 + usage-guides/global-search.md | 12 - .../events.md} | 6 +- .../{import-csv.md => history/import-data.md} | 4 + usage-guides/{ => history}/onchain.md | 4 + usage-guides/{ => history}/pnl.md | 20 +- usage-guides/index.md | 16 +- usage-guides/{ => integrations}/calendar.md | 4 + usage-guides/integrations/exchange-keys.md | 109 +++++ .../external-services.md} | 136 +----- usage-guides/long-running-tasks.md | 9 - .../accounts.md} | 183 +------ usage-guides/portfolio/balances.md | 182 +++++++ usage-guides/settings/account.md | 62 +++ usage-guides/settings/accounting.md | 135 ++++++ usage-guides/settings/blockchain.md | 102 ++++ usage-guides/settings/general.md | 113 +++++ usage-guides/settings/interface.md | 55 +++ usage-guides/staking.md | 4 + usage-guides/{statistic.md => statistics.md} | 6 +- .../{ => tax-accounting}/accounting-rules.md | 12 +- .../{ => tax-accounting}/event-types.md | 6 +- .../guide.md} | 54 ++- usage-guides/user-notes.md | 13 - .../{help-support.md => utilities/help.md} | 4 + usage-guides/utilities/index.md | 42 ++ 63 files changed, 1460 insertions(+), 887 deletions(-) create mode 100644 .vitepress/plugins/redirects.ts create mode 100644 components/NavCards.vue rename usage-guides/{backend-arguments.md => advanced/backend-config.md} (85%) rename usage-guides/{ => advanced}/data-directory.md (82%) rename usage-guides/{accessing-db-manually.md => advanced/database-access.md} (90%) rename usage-guides/{using-rotki-from-mobile.md => advanced/mobile.md} (94%) rename usage-guides/{ => advanced}/troubleshooting.md (94%) delete mode 100644 usage-guides/customization.md rename usage-guides/{ => data-management}/address-book.md (86%) rename usage-guides/{ => data-management}/assets.md (98%) rename usage-guides/{custom-price.md => data-management/prices.md} (89%) rename usage-guides/{tag-management.md => data-management/tags.md} (74%) delete mode 100644 usage-guides/global-search.md rename usage-guides/{historical-events.md => history/events.md} (98%) rename usage-guides/{import-csv.md => history/import-data.md} (98%) rename usage-guides/{ => history}/onchain.md (95%) rename usage-guides/{ => history}/pnl.md (90%) rename usage-guides/{ => integrations}/calendar.md (94%) create mode 100644 usage-guides/integrations/exchange-keys.md rename usage-guides/{api-keys.md => integrations/external-services.md} (50%) delete mode 100644 usage-guides/long-running-tasks.md rename usage-guides/{accounts-and-balances.md => portfolio/accounts.md} (59%) create mode 100644 usage-guides/portfolio/balances.md create mode 100644 usage-guides/settings/account.md create mode 100644 usage-guides/settings/accounting.md create mode 100644 usage-guides/settings/blockchain.md create mode 100644 usage-guides/settings/general.md create mode 100644 usage-guides/settings/interface.md rename usage-guides/{statistic.md => statistics.md} (96%) rename usage-guides/{ => tax-accounting}/accounting-rules.md (92%) rename usage-guides/{ => tax-accounting}/event-types.md (99%) rename usage-guides/{tax-accounting.md => tax-accounting/guide.md} (62%) delete mode 100644 usage-guides/user-notes.md rename usage-guides/{help-support.md => utilities/help.md} (92%) create mode 100644 usage-guides/utilities/index.md diff --git a/.vitepress/config.mts b/.vitepress/config.mts index 174999f..7cd5a6a 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -5,6 +5,76 @@ import { defineConfig } from 'vitepress'; import llmstxt from 'vitepress-plugin-llms'; import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'; import { markdownFitMedia } from './plugins/markdown-fit-media'; +import { getRedirectPaths, redirectsPlugin } from './plugins/redirects'; + +const redirects: Record = { + // Simple redirects (1:1 moves) + 'usage-guides/historical-events': '/usage-guides/history/events', + 'usage-guides/onchain': '/usage-guides/history/onchain', + 'usage-guides/pnl': '/usage-guides/history/pnl', + 'usage-guides/import-csv': '/usage-guides/history/import-data', + 'usage-guides/tax-accounting': '/usage-guides/tax-accounting/guide', + 'usage-guides/event-types': '/usage-guides/tax-accounting/event-types', + 'usage-guides/accounting-rules': '/usage-guides/tax-accounting/accounting-rules', + 'usage-guides/statistic': '/usage-guides/statistics', + 'usage-guides/assets': '/usage-guides/data-management/assets', + 'usage-guides/custom-price': '/usage-guides/data-management/prices', + 'usage-guides/address-book': '/usage-guides/data-management/address-book', + 'usage-guides/tag-management': '/usage-guides/data-management/tags', + 'usage-guides/calendar': '/usage-guides/integrations/calendar', + 'usage-guides/global-search': '/usage-guides/utilities/#global-search', + 'usage-guides/user-notes': '/usage-guides/utilities/#taking-notes-in-app', + 'usage-guides/long-running-tasks': '/usage-guides/utilities/#background-tasks', + 'usage-guides/help-support': '/usage-guides/utilities/help', + 'usage-guides/troubleshooting': '/usage-guides/advanced/troubleshooting', + 'usage-guides/backend-arguments': '/usage-guides/advanced/backend-config', + 'usage-guides/data-directory': '/usage-guides/advanced/data-directory', + 'usage-guides/accessing-db-manually': '/usage-guides/advanced/database-access', + 'usage-guides/using-rotki-from-mobile': '/usage-guides/advanced/mobile', + // Anchor-aware redirects (split files) + 'usage-guides/accounts-and-balances': { + default: '/usage-guides/portfolio/accounts', + anchors: { + '#exchange-balances': '/usage-guides/portfolio/balances', + '#manual-balances': '/usage-guides/portfolio/balances', + '#nfts': '/usage-guides/portfolio/balances', + '#filtering-by-tags': '/usage-guides/portfolio/balances', + '#hide-small-balances': '/usage-guides/portfolio/balances', + '#airdrops': '/usage-guides/portfolio/balances', + '#balances-snapshots': '/usage-guides/portfolio/balances', + }, + }, + 'usage-guides/api-keys': { + default: '/usage-guides/integrations/exchange-keys', + anchors: { + '#external-services': '/usage-guides/integrations/external-services', + '#etherscan': '/usage-guides/integrations/external-services', + '#loopring-balances': '/usage-guides/integrations/external-services', + '#monerium': '/usage-guides/integrations/external-services', + '#gnosis-pay': '/usage-guides/integrations/external-services', + '#the-graph': '/usage-guides/integrations/external-services', + '#defillama': '/usage-guides/integrations/external-services', + '#coingecko': '/usage-guides/integrations/external-services', + }, + }, + 'usage-guides/customization': { + default: '/usage-guides/settings/general', + anchors: { + '#accounting-settings': '/usage-guides/settings/accounting', + '#trade-settings': '/usage-guides/settings/accounting', + '#csv-export-settings': '/usage-guides/settings/accounting', + '#evm': '/usage-guides/settings/blockchain', + '#price-oracle-settings': '/usage-guides/settings/blockchain', + '#rpc-node-setting': '/usage-guides/settings/blockchain', + '#module-settings': '/usage-guides/settings/blockchain', + '#interface-only-settings': '/usage-guides/settings/interface', + '#disabling-the-tray-icon': '/usage-guides/settings/interface', + '#account-settings': '/usage-guides/settings/account', + '#database-settings': '/usage-guides/settings/account', + '#backend-settings': '/usage-guides/settings/account', + }, + }, +}; const __dirname = path.dirname(fileURLToPath(new URL(import.meta.url))); @@ -58,38 +128,91 @@ export default defineConfig({ { text: 'Usage Guides', items: [ - { text: 'Introduction', link: '/usage-guides/' }, - { text: 'Tax Accounting Guide', link: '/usage-guides/tax-accounting' }, - { text: 'Tracking Accounts & Balances', link: '/usage-guides/accounts-and-balances' }, - { text: 'Historical Events', link: '/usage-guides/historical-events' }, - { text: 'Event Types & Subtypes', link: '/usage-guides/event-types' }, - { text: 'On-Chain Transactions', link: '/usage-guides/onchain' }, - { text: 'Staking', link: '/usage-guides/staking' }, - { text: 'Statistics', link: '/usage-guides/statistic' }, - { text: 'Profit/Loss Report', link: '/usage-guides/pnl' }, - { text: 'Accounting Rule Options', link: '/usage-guides/accounting-rules' }, - { text: 'Tag Management', link: '/usage-guides/tag-management' }, - { text: 'Assets Management', link: '/usage-guides/assets' }, - { text: 'Add Missing Prices', link: '/usage-guides/custom-price' }, - { text: 'Address Book', link: '/usage-guides/address-book' }, - { text: 'API Keys', link: '/usage-guides/api-keys' }, - { text: 'Import CSV', link: '/usage-guides/import-csv' }, - { text: 'Calendar', link: '/usage-guides/calendar' }, - { text: 'Taking Notes In-App', link: '/usage-guides/user-notes' }, - { text: 'Global Search', link: '/usage-guides/global-search' }, - { text: 'Settings', link: '/usage-guides/customization' }, - { text: 'Help & Support', link: '/usage-guides/help-support' }, - ], - }, - { - text: 'Advanced', - items: [ - { text: 'Troubleshooting', link: '/usage-guides/troubleshooting' }, - { text: 'Set the backend\'s arguments', link: '/usage-guides/backend-arguments' }, - { text: 'rotki data directory', link: '/usage-guides/data-directory' }, - { text: 'Accessing the database manually', link: '/usage-guides/accessing-db-manually' }, - { text: 'Long running tasks', link: '/usage-guides/long-running-tasks' }, - { text: 'Using rotki from mobile', link: '/usage-guides/using-rotki-from-mobile' }, + { text: 'Getting Started', link: '/usage-guides/' }, + { + text: 'Portfolio', + collapsed: false, + items: [ + { text: 'Accounts', link: '/usage-guides/portfolio/accounts' }, + { text: 'Balances', link: '/usage-guides/portfolio/balances' }, + ], + }, + { + text: 'History & Events', + collapsed: false, + items: [ + { text: 'Historical Events', link: '/usage-guides/history/events' }, + { text: 'On-Chain Transactions', link: '/usage-guides/history/onchain' }, + { text: 'Import Data', link: '/usage-guides/history/import-data' }, + ], + }, + { + text: 'Tax & Accounting', + collapsed: false, + items: [ + { text: 'Tax Accounting Guide', link: '/usage-guides/tax-accounting/guide' }, + { text: 'Profit/Loss Report', link: '/usage-guides/history/pnl' }, + { text: 'Event Types & Subtypes', link: '/usage-guides/tax-accounting/event-types' }, + { text: 'Accounting Rules', link: '/usage-guides/tax-accounting/accounting-rules' }, + ], + }, + { + text: 'Tracking', + collapsed: false, + items: [ + { text: 'Staking', link: '/usage-guides/staking' }, + { text: 'Statistics', link: '/usage-guides/statistics' }, + ], + }, + { + text: 'Integrations', + collapsed: true, + items: [ + { text: 'Exchange API Keys', link: '/usage-guides/integrations/exchange-keys' }, + { text: 'External Services', link: '/usage-guides/integrations/external-services' }, + { text: 'Calendar', link: '/usage-guides/integrations/calendar' }, + ], + }, + { + text: 'Utilities', + collapsed: true, + items: [ + { text: 'Overview', link: '/usage-guides/utilities/' }, + { text: 'Help & Support', link: '/usage-guides/utilities/help' }, + ], + }, + { + text: 'Data Management', + collapsed: true, + items: [ + { text: 'Assets', link: '/usage-guides/data-management/assets' }, + { text: 'Missing Prices', link: '/usage-guides/data-management/prices' }, + { text: 'Address Book', link: '/usage-guides/data-management/address-book' }, + { text: 'Tags', link: '/usage-guides/data-management/tags' }, + ], + }, + { + text: 'Settings', + collapsed: true, + items: [ + { text: 'General', link: '/usage-guides/settings/general' }, + { text: 'Interface', link: '/usage-guides/settings/interface' }, + { text: 'Accounting', link: '/usage-guides/settings/accounting' }, + { text: 'Blockchain & EVM', link: '/usage-guides/settings/blockchain' }, + { text: 'Account & Database', link: '/usage-guides/settings/account' }, + ], + }, + { + text: 'Advanced', + collapsed: true, + items: [ + { text: 'Troubleshooting', link: '/usage-guides/advanced/troubleshooting' }, + { text: 'Backend Configuration', link: '/usage-guides/advanced/backend-config' }, + { text: 'Data Directory', link: '/usage-guides/advanced/data-directory' }, + { text: 'Database Access', link: '/usage-guides/advanced/database-access' }, + { text: 'Mobile / Docker', link: '/usage-guides/advanced/mobile' }, + ], + }, ], }, { @@ -157,7 +280,10 @@ export default defineConfig({ }, }, vite: { - plugins: [llmstxt()], + plugins: [ + llmstxt({ ignoreFiles: getRedirectPaths(redirects) }), + redirectsPlugin({ redirects, base }), + ], resolve: { alias: { '@': path.resolve(__dirname, '../'), diff --git a/.vitepress/plugins/redirects.ts b/.vitepress/plugins/redirects.ts new file mode 100644 index 0000000..627b72d --- /dev/null +++ b/.vitepress/plugins/redirects.ts @@ -0,0 +1,123 @@ +import type { Plugin } from 'vite'; + +interface RedirectTarget { + /** Default destination when no anchor matches */ + default: string; + /** Map anchor hashes to specific destinations (for split-page redirects) */ + anchors?: Record; +} + +export type RedirectValue = string | RedirectTarget; + +export interface RedirectsConfig { + /** + * Map of old paths to new paths. + * Keys are relative to site root without leading slash (e.g. 'usage-guides/old-page'). + * Values are either a string (simple redirect) or a RedirectTarget (anchor-aware). + * + * @example + * { + * 'usage-guides/old-page': '/usage-guides/new-page', + * 'usage-guides/split-page': { + * default: '/usage-guides/section-a', + * anchors: { + * '#some-section': '/usage-guides/section-b', + * }, + * }, + * } + */ + redirects: Record; + /** Base path for the site (default: '/') */ + base?: string; +} + +function generateRedirectHtml(target: RedirectValue, base: string): string { + const resolveUrl = (path: string) => base === '/' ? path : `${base}${path}`; + + if (typeof target === 'string') { + const url = resolveUrl(target); + return ` + + + + + + Redirecting... + + +

This page has moved. Redirecting to ${url}...

+ + +`; + } + + const defaultUrl = resolveUrl(target.default); + const anchors = target.anchors ?? {}; + + const anchorEntries = Object.entries(anchors).map( + ([hash, dest]) => ` ${JSON.stringify(hash)}: '${resolveUrl(dest)}'`, + ); + + return ` + + + + + + Redirecting... + + +

This page has moved. Redirecting to ${defaultUrl}...

+ + +`; +} + +/** + * Returns the list of source paths that are redirects, + * for use with vitepress-plugin-llms ignoreFiles. + */ +export function getRedirectPaths(redirects: Record): string[] { + return Object.keys(redirects).map(path => `${path}.md`); +} + +/** + * Vite plugin that generates redirect HTML files at build time. + * Replaces manual redirect stub .md files. + */ +export function redirectsPlugin(config: RedirectsConfig): Plugin { + const { redirects, base = '/' } = config; + + return { + name: 'vitepress-redirects', + enforce: 'post', + generateBundle() { + for (const [oldPath, target] of Object.entries(redirects)) { + const html = generateRedirectHtml(target, base); + const fileName = oldPath.endsWith('.html') + ? oldPath + : `${oldPath}.html`; + + this.emitFile({ + type: 'asset', + fileName, + source: html, + }); + } + }, + }; +} diff --git a/.vitepress/theme/index.ts b/.vitepress/theme/index.ts index bcfb04a..5f0138b 100644 --- a/.vitepress/theme/index.ts +++ b/.vitepress/theme/index.ts @@ -3,6 +3,7 @@ import { enhanceAppWithTabs } from 'vitepress-plugin-tabs/client'; import DefaultTheme from 'vitepress/theme'; import { h } from 'vue'; import CsvTable from '@/components/CsvTable.vue'; +import NavCards from '@/components/NavCards.vue'; import './style.css'; export default { @@ -13,5 +14,6 @@ export default { enhanceApp({ app }) { enhanceAppWithTabs(app); app.component('CsvTable', CsvTable); + app.component('NavCards', NavCards); }, } satisfies Theme; diff --git a/components/NavCards.vue b/components/NavCards.vue new file mode 100644 index 0000000..8b6f9d8 --- /dev/null +++ b/components/NavCards.vue @@ -0,0 +1,99 @@ + + + + + diff --git a/contribution-guides/code-profiling.md b/contribution-guides/code-profiling.md index 6aa095e..1a65f36 100644 --- a/contribution-guides/code-profiling.md +++ b/contribution-guides/code-profiling.md @@ -1,3 +1,7 @@ +--- +description: Profiling rotki Python code using flamegraphs and viztracer to identify performance bottlenecks. +--- + # Code Profiling ## Python diff --git a/contribution-guides/contribute-as-developer.md b/contribution-guides/contribute-as-developer.md index 70e2d4d..3a8aec8 100644 --- a/contribution-guides/contribute-as-developer.md +++ b/contribution-guides/contribute-as-developer.md @@ -1,3 +1,7 @@ +--- +description: Developer contribution guide covering commit rules, linting, PR process, CLA, and development environment setup. +--- + # Contributing as a Developer Being an open-source project, we welcome contributions in the form of source code. To do that, you will have to work on an issue and open a Pull Request for it. diff --git a/contribution-guides/docker-publishing.md b/contribution-guides/docker-publishing.md index 85e19f6..eec878b 100644 --- a/contribution-guides/docker-publishing.md +++ b/contribution-guides/docker-publishing.md @@ -1,3 +1,7 @@ +--- +description: Manual steps for building and publishing multi-architecture rotki Docker images to Docker Hub. +--- + # Docker Publishing (Manual) If you need to publish on [hub.docker.com](https://hub.docker.com), follow these steps: diff --git a/contribution-guides/feature-requests.md b/contribution-guides/feature-requests.md index 14586c4..767fd04 100644 --- a/contribution-guides/feature-requests.md +++ b/contribution-guides/feature-requests.md @@ -1,3 +1,7 @@ +--- +description: How to submit feature requests for rotki using the GitHub issue template. +--- + # Feature Requests Use the [feature request](https://github.com/rotki/rotki/issues/new?template=feature_request.md) template. diff --git a/contribution-guides/index.md b/contribution-guides/index.md index 371ef16..8fdcaf6 100644 --- a/contribution-guides/index.md +++ b/contribution-guides/index.md @@ -1,3 +1,7 @@ +--- +description: How to contribute to rotki including bug reporting, debug mode, feature requests, and development setup. +--- + # rotki Contribution Guide rotki is an open-source project, so help is really appreciated. @@ -16,7 +20,7 @@ Before reporting an issue, make sure to check the issue tracker for similar ones For running rotki in debug mode, you can do it either via a config file or the app UI. The choice will depend on how you run rotki. -- **Config file**: See the section [Set the backend's arguments](/usage-guides/backend-arguments.html#set-the-backend-s-arguments). This is possible in the **electron app** and the **docker version**. For docker, you can even use environment variables as explained [here](/requirement-and-installation/packaged-binaries.html#configuring-the-backend-in-docker). +- **Config file**: See the section [Set the backend's arguments](/usage-guides/advanced/backend-config#set-the-backend-s-arguments). This is possible in the **electron app** and the **docker version**. For docker, you can even use environment variables as explained [here](/requirement-and-installation/packaged-binaries.html#configuring-the-backend-in-docker). - **App UI**: Before logging in, click the cog wheel at the bottom right corner and select "Debug" (image below). Press the save button and proceed to log in as usual. This is only possible in the **electron app**. ![Run rotki in debug mode via app UI](/images/rotki_debug_mode_set.png) diff --git a/contribution-guides/manual-testing.md b/contribution-guides/manual-testing.md index 88f43ce..0b03d84 100644 --- a/contribution-guides/manual-testing.md +++ b/contribution-guides/manual-testing.md @@ -1,3 +1,7 @@ +--- +description: Manual testing checklist for rotki release binaries covering startup, trades, imports, and exchanges. +--- + # Manual Testing To ensure the final executable works as a complete package (including the UI), a bit of manual testing with the final binaries is required. This should eventually be reduced as the E2E test suite becomes more complete. Everything below that can be E2E tested should be. diff --git a/contribution-guides/python-testing.md b/contribution-guides/python-testing.md index 01f95b9..a0c1c5f 100644 --- a/contribution-guides/python-testing.md +++ b/contribution-guides/python-testing.md @@ -1,3 +1,7 @@ +--- +description: Running the Python test suite, linting with ruff/mypy/pylint, and mocking network calls in tests. +--- + # Python Code Testing To run the Python test suite, ensure you have installed all dependencies including the dev group, and then execute: @@ -38,7 +42,7 @@ Mocking should be done in one of the following ways: ## Using VCR -From version 1.27.0, we have introduced VCR to mock network queries in most tests to improve the speed of the test suite. VCR works by generating a `yaml` file that records information about all the requests made. Then, for every request that occurs in the test, VCR tries to match it to one of the recorded ones. We already have some pre-recorded cassettes (the name used by VCR for those yaml files), which are available on [GitHub](https://github.com/rotki/test-caching). During a fresh run, this repository will be cloned, and the cassettes will be replayed. This occurs in the path set by the `vcr_cassette_dir` fixture, which also sets the directory where the cassettes are located. By default, this is the `test-caching` directory under [rotki's data directory](/usage-guides/data-directory.html#rotki-data-directory). +From version 1.27.0, we have introduced VCR to mock network queries in most tests to improve the speed of the test suite. VCR works by generating a `yaml` file that records information about all the requests made. Then, for every request that occurs in the test, VCR tries to match it to one of the recorded ones. We already have some pre-recorded cassettes (the name used by VCR for those yaml files), which are available on [GitHub](https://github.com/rotki/test-caching). During a fresh run, this repository will be cloned, and the cassettes will be replayed. This occurs in the path set by the `vcr_cassette_dir` fixture, which also sets the directory where the cassettes are located. By default, this is the `test-caching` directory under [rotki's data directory](/usage-guides/advanced/data-directory#rotki-data-directory). Locally, cassettes are only read and never written to prevent unexpected behavior during testing. To record a new test, we provide a make rule called `create-cassette`. diff --git a/contribution-guides/rotki-database.md b/contribution-guides/rotki-database.md index 4422690..6c5aa22 100644 --- a/contribution-guides/rotki-database.md +++ b/contribution-guides/rotki-database.md @@ -1,15 +1,19 @@ +--- +description: Architecture of rotki's SQLite databases, schema upgrades, data migrations, and cache management. +--- + # rotki Database rotki uses two different SQLite databases: one with information about assets, prices, and other non-sensitive information (`global.db`), and one with user information (`rotkehlchen.db`). The latter is encrypted using an extension called [SQLCipher](https://github.com/sqlcipher/sqlcipher) that provides transparent 256-bit AES full database encryption. ## Database Location -Databases are stored in directories under the [rotki data directory](/usage-guides/data-directory.html#rotki-data-directory). +Databases are stored in directories under the [rotki data directory](/usage-guides/advanced/data-directory#rotki-data-directory). - The global database is stored at `global/global.db`. - The accounts you create in rotki have their own database stored at `users//rotkehlchen.db`. -If you need to manually access the database, you can find the guide [here](/usage-guides/accessing-db-manually.html#accessing-the-database-manually). +If you need to manually access the database, you can find the guide [here](/usage-guides/advanced/database-access#accessing-the-database-manually). ## DB Upgrades diff --git a/contribution-guides/vue-typescript.md b/contribution-guides/vue-typescript.md index 3655aaf..48e09b6 100644 --- a/contribution-guides/vue-typescript.md +++ b/contribution-guides/vue-typescript.md @@ -1,3 +1,7 @@ +--- +description: Running Vue/TypeScript unit tests with vitest and end-to-end tests with Playwright for the rotki frontend. +--- + # Vue/TypeScript ## Testing diff --git a/contribution-guides/working-on-issues.md b/contribution-guides/working-on-issues.md index 1ad8e4f..7c8c6c1 100644 --- a/contribution-guides/working-on-issues.md +++ b/contribution-guides/working-on-issues.md @@ -1,3 +1,7 @@ +--- +description: Workflow for picking up issues, opening PRs, and coordinating between backend and frontend teams. +--- + # Working on issues The current workflow for working on issues is the following. diff --git a/contribution-guides/working-with-frontend.md b/contribution-guides/working-with-frontend.md index 4a470ff..bab9b34 100644 --- a/contribution-guides/working-with-frontend.md +++ b/contribution-guides/working-with-frontend.md @@ -1,3 +1,7 @@ +--- +description: Frontend development setup including editor integration, environment variables, and development proxy config. +--- + # Working with the Frontend ## Editor Integration diff --git a/faq.md b/faq.md index e4db3bb..429570e 100644 --- a/faq.md +++ b/faq.md @@ -1,3 +1,7 @@ +--- +description: Frequently asked questions about rotki, premium subscriptions, supported exchanges, and common issues. +--- + # Frequently Asked Questions ## Questions on the application @@ -86,11 +90,11 @@ rotki is an abbreviation for Rotkehlchen. That is the German word for the bird k ### My asset is not showing in rotki -If your asset is not showing in rotki, even though you are sure that you have a balance, you need to first ensure that the asset is present on the list of assets (read [inspecting list of assets](/usage-guides/assets.html#inspecting-list-of-assets)). +If your asset is not showing in rotki, even though you are sure that you have a balance, you need to first ensure that the asset is present on the list of assets (read [inspecting list of assets](/usage-guides/data-management/assets#inspecting-list-of-assets)). -If you still cannot find your asset, it might be ignored. By default, rotki only displays un-ignored assets in the table. To also show the ignored assets, choose the `Filter by ignored status β†’ Show all`, and then unignore the asset manually. Additionally, you can whitelist the asset to prevent it from being automatically ignored by rotki's spam detection (read: [whitelisting of ignored assets](/usage-guides/assets.html#whitelisting-of-ignored-assets)). +If you still cannot find your asset, it might be ignored. By default, rotki only displays un-ignored assets in the table. To also show the ignored assets, choose the `Filter by ignored status β†’ Show all`, and then unignore the asset manually. Additionally, you can whitelist the asset to prevent it from being automatically ignored by rotki's spam detection (read: [whitelisting of ignored assets](/usage-guides/data-management/assets#whitelisting-of-ignored-assets)). -After whitelisting the token, you may need to re-detect it to see it in your balances (read: [token detection methods](/usage-guides/assets.html#whitelisting-and-re-detecting-missing-tokens)). +After whitelisting the token, you may need to re-detect it to see it in your balances (read: [token detection methods](/usage-guides/data-management/assets#whitelisting-and-re-detecting-missing-tokens)). If the asset is still not showing, you may need to add it manually. @@ -104,7 +108,7 @@ For more information on un-ignoring and optionally whitelisting assets, see [My ### Events are missing -If you notice that some events are missing for a chain or from exchanges, you can re-pull events for a specific time range. See [Re-pulling events missed in the past](/usage-guides/historical-events.md#re-pulling-events-missed-in-the-past) for detailed instructions. +If you notice that some events are missing for a chain or from exchanges, you can re-pull events for a specific time range. See [Re-pulling events missed in the past](/usage-guides/history/events#re-pulling-events-missed-in-the-past) for detailed instructions. ### My balances are not showing after importing my history/creating history events @@ -124,7 +128,7 @@ If you just registered your ENS name and you don't see the name and/or avatar be ### Issues related to PnL report generation -You can go to [PnL report creation problems](/usage-guides/pnl#pnl-report-creation-problems) +You can go to [PnL report creation problems](/usage-guides/history/pnl#pnl-report-creation-problems) ### I receive a notification error: `can't deserialize XXX, unknown asset YY found` @@ -134,8 +138,8 @@ Important to remember that the global DB is not moved by the premium sync mechan If you are affected by this, there are a number of things you can do. -- For assets that are EVM tokens with identifiers like `eip155:10/erc20:0x99C59ACeBFEF3BBFB7129DC90D1a11DB0E91187f` if you press [redecode all history events](/usage-guides/historical-events.html#redecoding-blockchain-transactions) then the redecoding process should repopulate them in the global db. -- If you have an asset with a unique identifier that looks like `a19964d9-20da-a6dc-1b50-9f293eb85c0d` then that means it's a custom asset or a manually input asset and we have no idea what it is. To figure out you would need to [access the database manually](/usage-guides/accessing-db-manually) and query the event or trade that had it. For example for trades: +- For assets that are EVM tokens with identifiers like `eip155:10/erc20:0x99C59ACeBFEF3BBFB7129DC90D1a11DB0E91187f` if you press [redecode all history events](/usage-guides/history/events#redecoding-blockchain-transactions) then the redecoding process should repopulate them in the global db. +- If you have an asset with a unique identifier that looks like `a19964d9-20da-a6dc-1b50-9f293eb85c0d` then that means it's a custom asset or a manually input asset and we have no idea what it is. To figure out you would need to [access the database manually](/usage-guides/advanced/database-access) and query the event or trade that had it. For example for trades: ```sql SELECT * from trades WHERE base_asset='a19964d9-20da-a6dc-1b50-9f293eb85c0d' OR quote_asset='a19964d9-20da-a6dc-1b50-9f293eb85c0d'; @@ -147,7 +151,7 @@ Or for history events: SELECT * from history_events WHERE asset='a19964d9-20da-a6dc-1b50-9f293eb85c0d'; ``` -Then, from the response, understand which asset it is, recreate it, and merge it with the old identifier following the merging process outlined [here](/usage-guides/assets#merging-two-assets) +Then, from the response, understand which asset it is, recreate it, and merge it with the old identifier following the merging process outlined [here](/usage-guides/data-management/assets#merging-two-assets) ### Out of gas error during eth_call diff --git a/index.md b/index.md index 20891c3..c69540b 100644 --- a/index.md +++ b/index.md @@ -1,19 +1,24 @@ +--- +description: Documentation for rotki, an open-source crypto portfolio tracker and tax reporting tool. +--- + # What is rotki? -rotki is an asset management and accounting application specializing in Crypto assets and aims to also help with tax reporting. It has integration for multiple exchanges with more coming soon. For more info check out our [FAQ](/faq). +rotki is an open-source asset management and accounting application specializing in crypto assets and aims to also help with tax reporting. It tracks your portfolio across blockchains and exchanges. For more info check out our [FAQ](/faq). + +## Where to start? -# Disclaimer + + +## Disclaimer ROTKI'S SERVICE IS INTENDED ONLY TO IMPORT, DISPLAY, STORE, AND GENERATE REPORTS AND STATISTICS FROM CRYPTOCURRENCY TRANSACTION DATA AND OTHER ASSETS. YOU, AS THE USER OF THE SERVICE, ARE RESPONSIBLE FOR THE TRANSACTION DATA IMPORTED, STORED, AND ANALYZED BY THE SERVICE. IF INACCURATE OR INCOMPLETE TRANSACTION DATA IS PROVIDED TO THE SERVICE, THE REPORTS GENERATED BY THE SERVICE WILL ALSO BE INACCURATE OR INCOMPLETE. ROTKI DOES NOT PROVIDE TAX OR LEGAL ADVICE THROUGH THE SERVICE AND THE SERVICE IS NOT INTENDED TO BE A SUBSTITUTE FOR PROFESSIONAL TAX OR LEGAL ADVICE OR FOR YOUR OWN DILIGENCE IN ENSURING THE ACCURACY OF ANY AND ALL INFORMATION YOU SUBMIT TO TAX AUTHORITIES. IT IS YOUR RESPONSIBILITY TO PRESENT YOUR TRANSACTION DATA AND ANY REPORTS GENERATED BY THE SERVICE TO YOUR TAX OR LEGAL ADVISORS FOR REVIEW. ALWAYS SEEK THE ADVICE OF YOUR ACCOUNTANTS, ATTORNEYS, OR OTHER QUALIFIED TAX ADVISORS WITH ANY QUESTIONS YOU MAY HAVE REGARDING YOUR TAX LIABILITY. NEVER DISREGARD PROFESSIONAL TAX OR LEGAL ADVICE OR DELAY IN SEEKING IT BECAUSE OF SOMETHING YOU HAVE READ OR BEEN PROVIDED FROM THE SERVICE. THE SERVICE IS NOT INTENDED FOR CONTINUOUS MONITORING OF TRANSACTION DATA OR FOR AUTOMATIC TRANSMISSION OF YOUR TRANSACTION DATA OR ANY REPORTS OR SAMPLE FORMS GENERATED BY THE SERVICE TO ANY TAX AUTHORITY. YOU CANNOT SUBMIT PAYMENT TO ANY TAX AUTHORITY THROUGH THE SERVICE, AND WE ARE NOT RESPONSIBLE FOR ANY PAYMENT OR NON-PAYMENT OF TAXES BY YOU. - -# Where to start? - -If this is the first time looking at rotki you will probably want to visit the [Installation Guide](/requirement-and-installation/). Once you have successfully managed to install rotki you can proceed to the [Usage Guide](/usage-guides/). - -**Looking to do your crypto taxes?** Check the [Tax Accounting Guide](/usage-guides/tax-accounting) for a step-by-step walkthrough from setup to generating your PnL report. - -If you wish to contribute to rotki please check the [Contribution Guide](/contribution-guides/). diff --git a/premium/api-keys.md b/premium/api-keys.md index fdfab47..61fe282 100644 --- a/premium/api-keys.md +++ b/premium/api-keys.md @@ -1,3 +1,7 @@ +--- +description: Creating, managing, and securing rotki premium API key and secret credentials for app activation. +--- + # API Credentials rotki premium uses API credentials to connect your subscription to the rotki application. This guide explains how to create, manage, and secure your API credentials. diff --git a/premium/devices.md b/premium/devices.md index 2a7fe1b..34e1fe7 100644 --- a/premium/devices.md +++ b/premium/devices.md @@ -1,3 +1,7 @@ +--- +description: Managing devices connected to your rotki premium subscription and understanding per-tier device limits. +--- + # Device Management Manage devices using your rotki premium subscription and understand device limits for your plan tier. @@ -33,8 +37,6 @@ From **API Keys** β†’ **rotki Premium**: ![Premium devices management in the app](/images/premium_devices_app.png) -For detailed app instructions, see [Managing Premium Devices](/usage-guides/api-keys#managing-premium-devices). - ## Editing Device Names Device names help you identify which device is which (e.g., "Work Laptop", "Home Desktop", "MacBook Pro"). @@ -120,8 +122,6 @@ If you genuinely need more devices: 2. Upgrade directly from your [subscription page](https://rotki.com/home/subscription) 3. See [Upgrading Your Subscription](/premium/plans-and-pricing#upgrading-your-subscription) for details -For detailed troubleshooting, see the [Usage Guide](/usage-guides/api-keys#device-limit-exceeded). - ## Understanding Device Registration ### When is a Device Registered? diff --git a/premium/index.md b/premium/index.md index 8ee9a7e..223e00b 100644 --- a/premium/index.md +++ b/premium/index.md @@ -1,3 +1,7 @@ +--- +description: Overview of rotki premium subscription tiers, features, and how to get started with premium. +--- + # Premium Overview rotki premium is a paid subscription with several tiers unlocking additional features depending on your needs while supporting the ongoing development of rotki as an open-source project. diff --git a/premium/payment-methods.md b/premium/payment-methods.md index bc669db..8566e3d 100644 --- a/premium/payment-methods.md +++ b/premium/payment-methods.md @@ -1,3 +1,7 @@ +--- +description: Managing saved credit/debit cards and setting default payment methods for rotki premium renewals. +--- + # Payment Methods Manage your saved credit/debit cards and payment preferences for rotki premium subscriptions. diff --git a/premium/payment.md b/premium/payment.md index 3a54749..3f2600e 100644 --- a/premium/payment.md +++ b/premium/payment.md @@ -1,3 +1,7 @@ +--- +description: Step-by-step guide to purchasing a rotki premium subscription including plan selection and payment. +--- + # Payment Process This guide walks you through the process of purchasing a rotki premium subscription. diff --git a/premium/plans-and-pricing.md b/premium/plans-and-pricing.md index 6066742..935f970 100644 --- a/premium/plans-and-pricing.md +++ b/premium/plans-and-pricing.md @@ -1,3 +1,7 @@ +--- +description: Comparing rotki premium subscription tiers, billing cycles, and choosing the right plan. +--- + # Plans & Pricing rotki premium offers multiple subscription tiers with varying limits and capacities to suit different user needs. diff --git a/premium/referrals.md b/premium/referrals.md index 0349656..7a07ab0 100644 --- a/premium/referrals.md +++ b/premium/referrals.md @@ -1,3 +1,7 @@ +--- +description: Creating and using rotki premium referral codes for discounts on first subscriptions. +--- + # Referral Program Share rotki premium with others and both you and your referrals benefit. diff --git a/premium/subscription.md b/premium/subscription.md index 304d44f..028e60e 100644 --- a/premium/subscription.md +++ b/premium/subscription.md @@ -1,3 +1,7 @@ +--- +description: Managing your rotki premium subscription, viewing payment history, canceling, and renewing plans. +--- + # Subscription Management Manage your rotki premium subscription, view payment history, and access your API keys from your account page. diff --git a/requirement-and-installation/build-from-source.md b/requirement-and-installation/build-from-source.md index 6b0cc50..041c621 100644 --- a/requirement-and-installation/build-from-source.md +++ b/requirement-and-installation/build-from-source.md @@ -1,7 +1,11 @@ +--- +description: Building rotki from source with prerequisites, backend setup, frontend setup, and Colibri service compilation. +--- + # Build from Source > [!WARNING] -> Please note that you should not switch between running unreleased code from git branches and official releases of rotki on the same [data set](/usage-guides/data-directory.md), as unreleased code does not provide guarantees around forward-compatibility of data schemas etc. +> Please note that you should not switch between running unreleased code from git branches and official releases of rotki on the same [data set](/usage-guides/advanced/data-directory), as unreleased code does not provide guarantees around forward-compatibility of data schemas etc. ## Prerequisites diff --git a/requirement-and-installation/index.md b/requirement-and-installation/index.md index f47337d..caaf996 100644 --- a/requirement-and-installation/index.md +++ b/requirement-and-installation/index.md @@ -1,3 +1,7 @@ +--- +description: Overview of rotki installation options with links to packaged binaries and building from source. +--- + # Installation The easiest way to start rotki is to download the packaged binary for your operating system. Linux, macOS, and Windows are supported. To see how to do this, go to the [next section](/requirement-and-installation/packaged-binaries). diff --git a/requirement-and-installation/packaged-binaries.md b/requirement-and-installation/packaged-binaries.md index a7227d1..db71442 100644 --- a/requirement-and-installation/packaged-binaries.md +++ b/requirement-and-installation/packaged-binaries.md @@ -1,3 +1,7 @@ +--- +description: Installing rotki from packaged binaries on Linux, macOS, and Windows, including Docker and DAppNode. +--- + # Packaged Binaries ## Verifying Integrity @@ -476,7 +480,7 @@ networks: If you would like to move your accounts from the rotki application to Docker, you can do so by copying the data directory of the application to the Docker data volume. -You can find where the rotki application data is stored in the [rotki data directory](/usage-guides/data-directory.html#rotki-data-directory). +You can find where the rotki application data is stored in the [rotki data directory](/usage-guides/advanced/data-directory#rotki-data-directory). To move your existing accounts from the application, copy the contents of the application data directory to the data volume mount point. diff --git a/usage-guides/backend-arguments.md b/usage-guides/advanced/backend-config.md similarity index 85% rename from usage-guides/backend-arguments.md rename to usage-guides/advanced/backend-config.md index d412c50..9325012 100644 --- a/usage-guides/backend-arguments.md +++ b/usage-guides/advanced/backend-config.md @@ -1,3 +1,7 @@ +--- +description: Customizing rotki backend arguments via rotki_config.json for log levels, data directories, and more. +--- + # Set the backend's arguments rotki runs a Python daemon on the backend. Most times you won't need to customize its arguments, but if you need to do so, especially for debugging purposes, this is how you can. diff --git a/usage-guides/data-directory.md b/usage-guides/advanced/data-directory.md similarity index 82% rename from usage-guides/data-directory.md rename to usage-guides/advanced/data-directory.md index b55f92e..cbe992c 100644 --- a/usage-guides/data-directory.md +++ b/usage-guides/advanced/data-directory.md @@ -1,3 +1,7 @@ +--- +description: Default rotki data directory locations on Linux, macOS, and Windows, plus backup recommendations. +--- + # rotki data directory rotki saves user data by default in a different directory per OS. For each OS, data is stored in the respective standards-compliant equivalent directory. @@ -14,4 +18,4 @@ A very good idea for the rotki data directory would be to make frequent backups If you are running rotki from unreleased code from git branches, please note that [the data directory is in a slightly different -location](../contribution-guides/contribute-as-developer.html#working-with-the-develop-branch). +location](/contribution-guides/contribute-as-developer#working-with-the-develop-branch). diff --git a/usage-guides/accessing-db-manually.md b/usage-guides/advanced/database-access.md similarity index 90% rename from usage-guides/accessing-db-manually.md rename to usage-guides/advanced/database-access.md index 43fe856..81102bb 100644 --- a/usage-guides/accessing-db-manually.md +++ b/usage-guides/advanced/database-access.md @@ -1,3 +1,7 @@ +--- +description: How to open and query the encrypted rotki SQLite database using DB Browser for SQLite or sqlcipher CLI. +--- + # Accessing the database manually To detect potential problems with data or modify the state of the database, you might need to access it manually. Here’s a guide on how to do this using `DB Browser for SQLite` or `sqlcipher` CLI tool. @@ -7,7 +11,7 @@ To detect potential problems with data or modify the state of the database, you 1. **Download and Install**: Get [DB Browser for SQLite](https://sqlitebrowser.org/dl/). It's available for Windows, macOS, and Linux. 2. **Starting the Program**: Launch the program with the SQLCipher functionality. 3. **Opening the rotki Database**: - - Navigate to the rotki database in the [rotki data directory](/usage-guides/data-directory.html#rotki-data-directory). + - Navigate to the rotki database in the [rotki data directory](/usage-guides/advanced/data-directory#rotki-data-directory). - Enter the password you use to unlock your rotki account to decrypt the database. 4. **Browsing and Modifying Data**: - Use the `Browse Data` tab to view the information. diff --git a/usage-guides/using-rotki-from-mobile.md b/usage-guides/advanced/mobile.md similarity index 94% rename from usage-guides/using-rotki-from-mobile.md rename to usage-guides/advanced/mobile.md index 0926303..285c698 100644 --- a/usage-guides/using-rotki-from-mobile.md +++ b/usage-guides/advanced/mobile.md @@ -1,3 +1,7 @@ +--- +description: Accessing rotki from a mobile device using DAppNode VPN or Docker with an authenticated proxy. +--- + # Using rotki from mobile If you are using DAppNode or the Docker image instead of the Electron application, it is possible to access rotki from a mobile device. diff --git a/usage-guides/troubleshooting.md b/usage-guides/advanced/troubleshooting.md similarity index 94% rename from usage-guides/troubleshooting.md rename to usage-guides/advanced/troubleshooting.md index 337c50e..fff6fa7 100644 --- a/usage-guides/troubleshooting.md +++ b/usage-guides/advanced/troubleshooting.md @@ -1,3 +1,7 @@ +--- +description: Fixing common rotki issues such as login errors, frontend settings corruption, and data problems. +--- + # Troubleshooting ## Invalid input error during login diff --git a/usage-guides/customization.md b/usage-guides/customization.md deleted file mode 100644 index f31d9dd..0000000 --- a/usage-guides/customization.md +++ /dev/null @@ -1,445 +0,0 @@ -# Settings - -This section provides information on how to customize the application through the settings. Click on the user icon on the top right and choose "Settings" to access basic customization options. - -## Profit Currency - -rotki calculates everything, including your total profit/loss during the PnL report, in a given fiat currency, called the `profit_currency`. By default, this is USD. You can change this by clicking on the currency icon in the top right menu and selecting your preferred currency. - -![Changing the profit currency](/images/sc_profit_currency.png) - -## Application Settings - -Access the settings menu via `User icon β†’ Settings`. - -## Account Settings - -### Changing Password - -Choose the "User & Security" section to change the user password. - -![Changing the user's password](/images/sc_user_password_change.png) - -## General Settings - -![Customizing the general app settings](/images/sc_general_settings.png) - -#### Anonymous Usage Analytics - -Specify whether the application can submit anonymous usage analytics. This helps measure active users while ensuring data is anonymized and contains no sensitive information. - -#### Auto detect tokens - -Specify whether to automatically detect tokens and refresh balances by periodically checking historical events. - -#### CSV Export - -Specify your preferred date format and delimiter for CSV exports. - -#### Automatic database sync - -Whether to force push when a size discrepancy occurs during automatic db sync. - -#### Version update check - -Set how often (in hours) the version will be checked for updates. - -#### Balance Snapshots Saving Frequency - -Set how often (in hours) the balance data snapshots are saved. This data helps calculate statistics historical and graph data for the user. - -#### BTC Derivation Gap Limit - -Set the derivation gap limit for deriving addresses from a bitcoin xpub. More information [here](https://insights.blockonomics.co/bitcoin-what-is-this-gap-limit/). - -#### Date Format - -Set the date display and date input format in the rotki user interface, such as `%m/%d/%Y %H:%M:%S` for month/day/year hour:minutes:seconds. Check [here](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes) for valid formats. - -### Amount Settings - -![Customizing the app's amount settings](/images/sc_amount_settings.png) - -#### Main Currency - -Same as [changing the profit currency](#profit-currency). - -#### Floating Precision - -Set the number of decimal points shown in the UI for floating point numbers. - -#### Thousands Separator - -Set the symbol separating every 3 digits for large numbers, e.g., `1,000,000`. - -#### Decimal Separator - -Set the symbol separating the floating part of a number, e.g., `5.42`. - -### Subscript Format - -Whether to apply subscript formatting for consecutive zeros after the decimal point in small numbers, e.g., `0.000000087` => `0.0₇87`. - -#### Amount Rounding - -Choose the rounding mechanism: `Round up`, `Round down`, or `Half even`. Customize how amounts and values are rounded. - -#### Abbreviation for large numbers - -If enabled, large numbers will be abbreviated, e.g., `1,234,567` as `1.23 M`. Set the minimum value to be abbreviated. - -#### Currency Location - -Set whether the currency symbol appears before or after the number, e.g., `$1,000` or `1,000$`. - -### NFT Settings - -![Customizing the app's NFT settings](/images/sc_nf_settings.png) - -#### Include NFTs in Graphs and Total Amounts - -Decide whether to include NFTs in total net worth calculations and displayed graphs. - -#### NFT Images Rendering Setting - -For privacy, allow images from all or specific domains. More details [here](https://medium.com/@alxlpsc/critical-privacy-vulnerability-getting-exposed-by-metamask-693c63c2ce94). - -### External Service Settings - -Define rules for retry and timeout for external service calls made by rotki. - -### Backend Settings - -![Customizing the backend settings](/images/usage_guides_settings_general_backend_settings.webp) - -#### Log Level - -Specify the minimum severity level for recorded log messages. You can change this at runtime without restarting rotki. This is useful for temporarily enabling debug logs when troubleshooting issues, without needing to modify the [`rotki_config.json`](/usage-guides/backend-arguments.html) file or restart the application. Additional log-related settings such as max log size, max number of log files, and logging from other modules can be configured from the [login screen backend settings](#advanced-backend-settings). - -## Database Settings - -### Database Info & User Database Backups - -View information about your user and global database, such as directory, size, and version. - -![Creating database backups](/images/sc_db_backup.png) - -Create new database backups, delete backups, and download backups locally. - -### 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. - -![Purging user data](/images/sc_purge_data.png) - -### Exporting and Importing User Assets - -Use the export/import function to migrate user assets between computers. This function creates a zip archive of user assets for transfer. - -![Importing user assets](/images/sc_custom_import_export.png) - -> [!WARNING] -> This archive cannot be used as a backup/restore across different versions of rotki since there is no guarantee of compatibility across versions. - -### Reset Assets Database - -There are two options to reset the assets database: - -1. **Soft Reset**: This option will not reset assets added by the user. -2. **Hard Reset**: This option will reset assets added by the user. - -## Accounting Settings - -> [!TIP] -> For a detailed explanation of what each accounting option does (with worked examples), see [Accounting Rule Options Explained](/usage-guides/accounting-rules). - -![Customizing the accounting rules](/images/sc_accounting_custom_rule.png) - -In the accounting menu, you can customize application settings related to accounting calculations. These settings will affect the PnL report calculations. - -> [!IMPORTANT] -> Before changing any settings: -> -> 1. Review each option carefully -> 2. Check with your tax advisor about what's required in your country -> 3. Make adjustments based on their guidance - -**Current Default Settings:** - -- Based on German tax rules -- Uses first-in/first-out (FIFO) method for calculating profits/losses -- Treats crypto sales as tax-free after holding for 1 year - -You can change these settings to match your country's tax requirements. - -### Add/Edit Accounting Rules - -![Add new accounting rules](/images/sc_accounting_add_rule.png) - -You can add or edit accounting rules based on `Event type`, `Event subtype`, and `Counterparty`. - -### Special Accounting Rules For Specific Events - -![Special Accounting Rules](/images/sc_accounting_rules_special.png) - -You can set custom accounting rules for individual events or groups of events directly from the History Events page. This allows you to override the default accounting behavior for specific events. - -There are two ways to apply special rules: - -- Use the [Edit accounting rule](/usage-guides/historical-events.html#edit-accounting-rule) menu for individual events -- Use [Select multiple events](/usage-guides/historical-events.html#select-multiple-events) to apply rules to multiple events at once - -### Trade Settings - -![Customizing the accounting trade settings](/images/sc_accounting_trade_settings.png) - -#### Crypto to Crypto Trades - -A setting to determine whether crypto to crypto trades or any events that spend crypto are taxable and should be taken into account. By default it’s `True`. - -:::tabs -== Crypto to Crypto Trades - -> **Illustration:** -> You trade your `1 ETH`, to get `11 USDT`. Current price of ETH is `10 EUR`, but you bought it when it was `5 EUR`. - -1. If `True`, virtual trades are generated, and profits/losses are calculated based on the difference in asset prices. By making this trade, we will create two virtual trade, which are: - - **Virtual Trade 1**: Sell `1 ETH` for `10 EUR`. PnL of this virtual trade is calculated as `the value when you sell this ETH (10 EUR)` minus `the value when you bought this ETH (5 EUR)` = `5 EUR`. - - **Virtual Trade 2**: Buy `11 USDT` with `10 EUR`. PnL of this virtual trade is `0 EUR` because it's a buy. However, later on, when you trade this `USDT` with another crypto, point (1) will also be applied. - > **Total PnL** = `5 EUR`. - -2. If `False`, no virtual trades are generated, and no additional profits/losses are calculated. - > **Total PnL** = `0 EUR`. - -== Crypto Spending - -> **Illustration:** -> You have `1` ETH that you bought with price `50 EUR`. Then you spend this `1` ETH for gas fees, and the price at the moment is `100 EUR`. - -1. If `True`, when you use crypto for fees, donations, or purchases, the profit and loss (PnL) calculation shows two things: the loss from spending the crypto and any profit or loss from the difference between the asset's current price and its buying price. - - **Loss from spending** = `-100 EUR`. - - **Profit from price difference** = `100 EUR (spend price) - 50 EUR (buy price) = 50 EUR`. - > **Total PnL** = `-100 EUR + 50 EUR` = `-50 EUR`. - -2. If `False`, only the spending loss is considered. - > **Total PnL** = `-100 EUR`. - -::: - -#### EVM Gas Costs - -Specify if EVM transaction gas costs should be counted as a loss. - -#### Tax Free Period - -Specify if there is a tax-free holding period for crypto assets. - -#### Calculate Past Cost Basis - -Enable or disable calculating cost basis from all past events, even before the report period. - -#### Omit ETH Staking Events - -Specify if ETH staking events are taxable only after the merge and withdrawals are enabled or at the point of receiving. - -#### Cost Basis Method - -Select the cost basis calculation method: `FIFO`, `LIFO`, `HIFO`, or `ACB`. - -#### Include Fees in Cost Basis - -A setting to determine if trade fees should be included in the cost basis of the asset being bought/sold. By default, this setting is `True`. - -> **Illustration:** -> You bought `1` ETH for `10 EUR` and paid `1 EUR` fee. - -:::tabs -== True - -The fee event only reduces the amount of the fee asset paid. The actual fee is then used to determine the cost basis of the asset being bought or sold. - -> The cost basis of that ETH is `10 + 1` = `11 EUR`. This is where the fee is taken into account. - -== False - -The above does not happen. - -> The cost basis of that ETH is `10 EUR`. But at the time of the trade you also have a spend event of `1 EUR` as fee. - -::: - -### CSV Export Settings - -![Customizing the CSV export settings](/images/sc_accounting_csv_export_settings.png) - -#### Export Formulas - -Specify if formulas should be exported as formulas in the CSV or as actual values. - -#### Have Summary - -Specify whether the all_events CSV export should include a summary of all events and the total profit/loss at the end. This summary would also include the rotki version and the settings used during the PnL report, making it easier to reproduce a report run. - -## EVM - -![EVM settings](/images/sc_evm_settings.png) - -#### Treat Staked ETH as ETH - -If enabled, ETH2 (staked ETH) will appear as ETH in the UI, and all tables and charts will combine the values of ETH and ETH2. - -#### EVM Chains for Automatic Detection - -Configure which EVM chains should not automatically detect tokens. By default, EVM chains detect activities of all registered EVM accounts in other EVM chains. - -### Indexers - -rotki uses several indexers to identify which transactions belong to your tracked addresses. The order used for each chain can be adjusted in the default settings and will apply unless a specific chain configuration overrides it. For example you may want to avoid using etherscan on Optimism and Base if you do not have a paid API key for those networks. - -This lets you control which sources are queried and change the configuration if one of them is unreliable for a particular chain. - -In addition to querying historical events, indexers are used when detecting onchain activity, for example when you add a new address to all supported EVM chains or when the periodic task performs this check in the background. - -At the time of writing the only chain that cannot be queried for free is Binance SC because neither blockscout nor routescan are available and etherscan requires an API key under the Lite plan. - -Regarding the need for API keys: - -- Etherscan requires an API key in the free tier to perform API calls. -- Blockscout does not require an API key and has a default limit of 10 requests per second. -- Routescan offers a free tier comparable to etherscan and does not require an API key. - -## Price Oracle Settings - -![Change the order of price sources](/images/sc_price_oracle_order.png) - -Here, you can customize the order in which price oracles are queried, both for current and historical prices. This determines which price source to check first, second, and so on. - -DeFi oracles like Uniswap V2 and Uniswap V3 use only on-chain information to get current prices. This makes querying a bit slower, but it relies solely on the Ethereum chain. Prices for some assets may differ from Coingecko or CryptoCompare, depending on the conditions of the pools at the time of the query. - -### Oracle cache - -![Creating a historical price cache](/images/sc_historical_price_cache.png) - -Querying historical prices from oracles such as CryptoCompare and CoinGecko is slow and can be slower due to rate limiting. rotki creates historical price caches during idle times. - -Request the creation of such a cache by going to the Oracle cache section, selecting the oracle, the from asset of the pair, the to asset of the pair, and then pressing "Cache pair prices". - -Manage existing historical price cache entries, inspect start and end dates, and delete caches if needed. - -## RPC Node Setting - -This setting lets you change the nodes used to connect to blockchains. We give you a list of public nodes, but sometimes they are busy or down. You will see a green or red icon showing if a node is working. - -It is good to add more nodes and set their priority. We always try your own nodes first, then use some random public nodes if needed. If you don't have your own node, we use public nodes. - -The node's weight (percentage) shows how likely it is to be used. You can turn nodes on or off with the toggle button. - -![Customizing the app's connection to EVM nodes](/images/rotki_nodes_management.png) - -In this menu you can also edit, delete or add more nodes. - -![Add an EVM node](/images/rotki_nodes_management_addition.png) - -### Local Nodes - -#### Connecting to a Kusama Client - -rotki attempts to connect to a local Kusama node running on the default port `9933`. If no client is running, blockchain queries will use an external service. - -#### Connecting to a Polkadot Client - -Set the RPC endpoint for a Polkadot node here. - -#### Connecting to an ETH Consensus Layer Beacon Node - -Set the RPC endpoint for the Ethereum consensus layer beacon node. If unreachable, beaconcha.in will be used. For DAppNode Ethereum validator users, find the RPC node setting in the DAppNode Package for the Execution Client. - -#### Connecting to a Bitcoin Mempool instance - -A local Bitcoin node can be used to query balances and transactions via [Mempool](https://mempool.space)'s API. [Mempool](https://github.com/mempool/mempool) is an open source project that can be self-hosted on Bitcoin nodes. It is readily available to install on many full-node distros such as Umbrel or Raspiblitz. Mempool uses port 4080 by default. Please include this when setting the endpoint (e.g. `http://localhost:4080`). Other custom ports should also work. -Please note that transaction querying is currently not supported and historical transaction fetching will fail. Only address balance querying is supported when using a custom mempool instance. - -## Module Settings - -Choose the "Module" section of the settings to customize the enabled modules and the queried addresses for each module. - -Enabling only the modules you use and specifying addresses improves querying speed. - -![Managing module settings](/images/module_settings.png) - -### Activating/Deactivating Modules - -View all modules in the table. Some are activated by default. Enable/disable a module by toggling the switch. Re-login for changes to take effect. - -### Selecting Addresses - -![Select address for modules](/images/module_settings_select_address.png) - -To limit querying to selected addresses, click the "edit/pencil" button on the module to select addresses. If no addresses are selected, rotki checks all eligible addresses, increasing query duration. - -## Interface-only Settings - -![Customizing the app's interface only settings](/images/sc_interface_only_settings.png) - -#### Language - -Set the language used in the app. This feature is experimental and may not work as expected for some languages. Help us speed up the translation process by contributing [here](/contribution-guides/contribute-as-developer.html#add-a-new-language-or-translation). - -#### Animation Effect - -Reduce animation effects to improve performance. This affects animation quality but optimizes resource usage. - -#### Data Scrambling - -Enable data scrambling to randomize amounts, dates, and other data for privacy in screenshots. This setting does not persist across sessions. - -#### Automatic Balance Refresh - -Enable or disable automatic balance refresh and set the refresh interval. Disabled by default due to potential slow queries and rate limits. - -#### Periodic Status Query - -Set the frequency of backend data updates. Default is 5 seconds. - -#### Blockchain Explorer Customization - -Customize which explorer is used for transaction and address links. - -### Graph Settings - -#### Dashboard Graph Default Timeframe - -Set the default timeframe for the dashboard graph, which will be pre-selected upon login. - -#### Graph Basis - -Configure whether the graph y-axis starts at 0 or the minimum amount for the period. - -### Alias Name for Addresses - -Enable or disable alias names for blockchain addresses. Aliases are obtained from `ENS`, `addressbook`, or `blockchain account label`. Change the order of resolution as needed. - -### Theme Customization [Premium] - -Premium users can customize colors for light or dark mode. - -## Backend Settings - -Desktop app users can change the default data directory and log directory via the login screen. Click the cog wheel at the bottom right to view the backend settings dialog. - -![Change the backend settings](/images/rotki_backend_settings.png) - -Select a new data directory, log directory, etc., and press "Save". Previously created accounts won't be accessible in the new location; move them manually. - -### Advanced Backend Settings - -Modify the following settings in the advanced section: - -- **Max log size**: Maximum size (MB) of all logs for a single run. -- **Max number of log files**: Maximum number of backup (rotated) logs for a single run. -- **Instructions per SQLite context switch**: Specify instructions count for context switch between cooperative threads. Set to `0` to disable async DB access. -- **Log from other modules**: Include log entries from dependent libraries, not just rotki. Disabled by default. - -## Disabling the Tray Icon - -Disable the application tray icon by clicking the `View` menu entry in the application menu bar. Select `Display Tray Icon` to enable/disable the tray icon. diff --git a/usage-guides/address-book.md b/usage-guides/data-management/address-book.md similarity index 86% rename from usage-guides/address-book.md rename to usage-guides/data-management/address-book.md index 5567023..29419e7 100644 --- a/usage-guides/address-book.md +++ b/usage-guides/data-management/address-book.md @@ -1,3 +1,7 @@ +--- +description: Managing global and private address book entries to replace blockchain addresses with human-readable names. +--- + # Address Book You can manage the address book in `Manage Address Book` menu in the sidebar. @@ -30,5 +34,5 @@ You can add multiple address book entries at once with CSV import. You can find 1. The `address` field is **required**. 2. The `name` field is **required**. -3. The `blockchain` field is **optional**. You can find supported chain IDs in the [supported blockchains](/usage-guides/accounts-and-balances#blockchain-accounts) section. Leave it blank to add the entry to all chains. +3. The `blockchain` field is **optional**. You can find supported chain IDs in the [supported blockchains](/usage-guides/portfolio/accounts#blockchain-accounts) section. Leave it blank to add the entry to all chains. 4. The `location` field is **optional**. You can set it to either `global` or `private`. By default, it will be saved as `private`. diff --git a/usage-guides/assets.md b/usage-guides/data-management/assets.md similarity index 98% rename from usage-guides/assets.md rename to usage-guides/data-management/assets.md index fc67370..81d14d5 100644 --- a/usage-guides/assets.md +++ b/usage-guides/data-management/assets.md @@ -1,3 +1,7 @@ +--- +description: Managing supported assets, adding custom tokens, merging duplicates, and whitelisting spam tokens. +--- + # Assets Management ## Inspecting list of assets @@ -9,7 +13,7 @@ You can inspect the list of all supported assets, edit them, delete them or add ### Token Detection Methods -You can check token detection guide [here](/usage-guides/accounts-and-balances#token-detection) +You can check token detection guide [here](/usage-guides/portfolio/accounts#token-detection) ## Adding/editing an asset diff --git a/usage-guides/custom-price.md b/usage-guides/data-management/prices.md similarity index 89% rename from usage-guides/custom-price.md rename to usage-guides/data-management/prices.md index 9230eb8..f6e58ce 100644 --- a/usage-guides/custom-price.md +++ b/usage-guides/data-management/prices.md @@ -1,3 +1,7 @@ +--- +description: Adding custom latest and historical prices for assets that rotki cannot retrieve automatically. +--- + # Adding missing prices Sometimes rotki might be unable to retrieve prices for some assets. In order to always have the ability to show a price we provide two types of manual price additions in the menu `Manage Prices`: diff --git a/usage-guides/tag-management.md b/usage-guides/data-management/tags.md similarity index 74% rename from usage-guides/tag-management.md rename to usage-guides/data-management/tags.md index ccef64a..f2d736a 100644 --- a/usage-guides/tag-management.md +++ b/usage-guides/data-management/tags.md @@ -1,3 +1,7 @@ +--- +description: Creating and editing tags with custom labels, descriptions, and colors for organizing accounts and balances. +--- + # Tag Management You can find the menu on the left sidebar. diff --git a/usage-guides/global-search.md b/usage-guides/global-search.md deleted file mode 100644 index 525db95..0000000 --- a/usage-guides/global-search.md +++ /dev/null @@ -1,12 +0,0 @@ -# Global search - -You can use global search provided to speed up your actions by clicking the icon on the top bar, or using the shortcut `Control-/` (`Command-/` if you are using Mac). - -Some actions provided by this global search: - -- Navigate to any page in rotki -- Some basic actions such as adding a new trade. -- Go to a certain owned asset overview page. -- Go to a certain location overview page. - -![Global Search](/images/global_searchbox.gif) diff --git a/usage-guides/historical-events.md b/usage-guides/history/events.md similarity index 98% rename from usage-guides/historical-events.md rename to usage-guides/history/events.md index dda7b30..4dea3fe 100644 --- a/usage-guides/historical-events.md +++ b/usage-guides/history/events.md @@ -1,7 +1,11 @@ +--- +description: Browsing, filtering, decoding, and editing historical events from exchanges and blockchains. +--- + # History events > [!TIP] -> **Trying to understand event types?** See the [Event Types & Subtypes Reference](/usage-guides/event-types) for a complete guide to what each event category means, with examples and default tax treatments. +> **Trying to understand event types?** See the [Event Types & Subtypes Reference](/usage-guides/tax-accounting/event-types) for a complete guide to what each event category means, with examples and default tax treatments. rotki is capable of pulling and decoding a bunch of different events, ranging from EVM chain transactions to exchanges events and more. When you visit the `History Events` section the process to obtain all the information will start. You will be able to check the status in an informative breakdown per blockchain address. Free users are limited to a number of latest events. diff --git a/usage-guides/import-csv.md b/usage-guides/history/import-data.md similarity index 98% rename from usage-guides/import-csv.md rename to usage-guides/history/import-data.md index ba8d86a..092d88e 100644 --- a/usage-guides/import-csv.md +++ b/usage-guides/history/import-data.md @@ -1,3 +1,7 @@ +--- +description: Importing trade and transaction data from CSV files exported by exchanges into rotki. +--- + # Import CSV Go to `Import Data` menu in the sidebar. diff --git a/usage-guides/onchain.md b/usage-guides/history/onchain.md similarity index 95% rename from usage-guides/onchain.md rename to usage-guides/history/onchain.md index 3a07903..dde7bb7 100644 --- a/usage-guides/onchain.md +++ b/usage-guides/history/onchain.md @@ -1,3 +1,7 @@ +--- +description: Sending on-chain transactions from rotki via WalletConnect or browser wallet on supported EVM chains. +--- + > [!NOTE] > This is an experimental feature, and you may find some imperfections. However, we are going to continuously improve it. diff --git a/usage-guides/pnl.md b/usage-guides/history/pnl.md similarity index 90% rename from usage-guides/pnl.md rename to usage-guides/history/pnl.md index 8bbb3c5..ddbc168 100644 --- a/usage-guides/pnl.md +++ b/usage-guides/history/pnl.md @@ -1,7 +1,11 @@ +--- +description: Generating profit/loss reports with FIFO, LIFO, HIFO, or ACB methods and exporting results. +--- + # Creating a profit/loss report > [!TIP] -> **New to rotki?** If you're looking for a step-by-step guide to doing your crypto taxes, start with the [Tax Accounting Guide](/usage-guides/tax-accounting) which walks you through the entire workflow. This page covers the PnL report feature in detail. +> **New to rotki?** If you're looking for a step-by-step guide to doing your crypto taxes, start with the [Tax Accounting Guide](/usage-guides/tax-accounting/guide) which walks you through the entire workflow. This page covers the PnL report feature in detail. rotki helps you track your cryptocurrency profits and losses (PnL) by analyzing your trading history and other transactions. Here's what you need to know about how these reports work: @@ -48,7 +52,7 @@ This ensures your reports are accurate even when looking at specific time period - Report generation might take a few minutes, especially for longer periods - You can review your current accounting settings in the "Accounting settings" section -- Having problems? Check our [troubleshooting guide](/usage-guides/pnl.html#pnl-report-creation-problems) +- Having problems? Check our [troubleshooting guide](/usage-guides/history/pnl#pnl-report-creation-problems) ### Managing Your Reports @@ -91,7 +95,7 @@ Following are definitions for the all_event document's columns - `notes` Information about the event. > [!NOTE] -> To learn more about `profit_currency` or to adjust it, see the section [change profit currency](/usage-guides/customization.html#profit-currency) +> To learn more about `profit_currency` or to adjust it, see the section [change profit currency](/usage-guides/settings/general#profit-currency) Results from past profit and loss reports are saved so the user can later review them without the need to run a new execution. @@ -127,17 +131,17 @@ It's possible that rotki is not able to find an acquisition event for a sale. In This can happen for many reasons. The asset may have been acquired in a non-supported exchange/protocol, some event not detected etc. -The way to fix it is to add either a [manual trade](/usage-guides/historical-events.html#adding-manual-trades) to tell rotki how you acquired that asset or an acquisition history event. +The way to fix it is to add either a [manual trade](/usage-guides/history/events#adding-manual-trades) to tell rotki how you acquired that asset or an acquisition history event. ### Event counted as taxable / count as spend where they shouldn't -If you have an event that is counted as taxable / counts as spend when it shouldn't, you may need to edit the event type / subtype of the event. Read: [Common customization](/usage-guides/historical-events.html#common-customization) +If you have an event that is counted as taxable / counts as spend when it shouldn't, you may need to edit the event type / subtype of the event. Read: [Common customization](/usage-guides/history/events#common-customization) ### PnL report generation gets stuck There are some known reasons why PnL report generation gets stuck: -1. If you have a Binance API key registered, please check these notes about [Binance API key rate limiting](/usage-guides/api-keys.md#market-pairs-required) +1. If you have a Binance API key registered, please check these notes about [Binance API key rate limiting](/usage-guides/integrations/exchange-keys#market-pairs-required) If your PnL report is stuck for a different reason, contact us in [Discord](https://discord.rotki.com) @@ -150,12 +154,12 @@ Simply change the language on Google doc to United States. This can be done in F ![Missing prices asset](/images/sc_pnl_missing_prices.png) -It's possible that rotki is not able to find the price of assets. You have to input the price manually, otherwise the event will be skipped from pnl reports. For example if you are creating a GBP profit/loss report and the asset is GNO then make sure to create the GNO -> GBP historical price cache. You can add the prices on the spot, or open [manage historical price cache](/usage-guides/customization.html#manage-historical-price-oracle-cache). +It's possible that rotki is not able to find the price of assets. You have to input the price manually, otherwise the event will be skipped from pnl reports. For example if you are creating a GBP profit/loss report and the asset is GNO then make sure to create the GNO -> GBP historical price cache. You can add the prices on the spot, or open [manage historical price cache](/usage-guides/settings/general#manage-historical-price-oracle-cache). ### The result of the generated PnL report is not what you expected. The results of the generated PnL report can vary depending on the -[accounting settings](/usage-guides/customization.html#accounting-settings). Check if any settings align with unusual treatments for your events, so you can adjust the settings to resolve the issue yourself. +[accounting settings](/usage-guides/settings/accounting#accounting-settings). Check if any settings align with unusual treatments for your events, so you can adjust the settings to resolve the issue yourself. If you have any question or are confused about the settings, feel free to send us a message on [Discord](https://discord.rotki.com). diff --git a/usage-guides/index.md b/usage-guides/index.md index f02cede..92a8135 100644 --- a/usage-guides/index.md +++ b/usage-guides/index.md @@ -1,9 +1,13 @@ -# Introduction +--- +description: Getting started with rotki including account creation, sign-in, premium setup, and data directory sync. +--- + +# Getting Started This guide explains how to use the rotki application. > [!TIP] -> **Using rotki for tax reporting?** Jump to the [Tax Accounting Guide](/usage-guides/tax-accounting) for a focused walkthrough of connecting your data, reviewing transactions, and generating your PnL report. +> **Using rotki for tax reporting?** Jump to the [Tax Accounting Guide](/usage-guides/tax-accounting/guide) for a focused walkthrough of connecting your data, reviewing transactions, and generating your PnL report. ## First Time Sign-Up @@ -57,7 +61,7 @@ Refer to the [Sync data with rotki server](#sync-data-with-rotki-server) section > - **User Database vs. Global Database**: Syncing only involves the user database, not the global database. > - **Global Database**: Contains all assets data, global address book for names, and historical prices. Premium syncing does not store your global database, so it is **essential** to manually move this database as well. You can see the guide of how to accomplish it [here](/usage-guides/#manually-move-global-database). -Alternatively, you can use the [Exporting and importing user asset](/usage-guides/customization.html#exporting-and-importing-user-assets) function instead of moving the entire global database. +Alternatively, you can use the [Exporting and importing user asset](/usage-guides/settings/account#exporting-and-importing-user-assets) function instead of moving the entire global database. ## Use an Account from a Different Installation @@ -65,7 +69,7 @@ Alternatively, you can use the [Exporting and importing user asset](/usage-guide To move your data to another system or restore it: -1. Identify the [rotki data directory](/usage-guides/data-directory) on both the source and destination systems. +1. Identify the [rotki data directory](/usage-guides/advanced/data-directory) on both the source and destination systems. 2. Move the entire data directory from the source system to the destination system. 3. Ensure both systems use the same version of rotki. @@ -78,7 +82,7 @@ To sign in with your local rotki account, enter your profile name and password a ## Set Up rotki Premium -If you decide to purchase [rotki Premium](https://rotki.com/products/) later, you can set it up [here](/usage-guides/api-keys#rotki-premium) +If you decide to purchase [rotki Premium](https://rotki.com/products/) later, you can set it up [here](/usage-guides/integrations/exchange-keys#rotki-premium) ## Sync Data with rotki Server @@ -103,7 +107,7 @@ If you use multiple accounts/devices, the one with the most recent login will up You can also manually move the global database containing assets from one system to another: -1. Locate the [rotki data directory](/usage-guides/data-directory) on the source system. +1. Locate the [rotki data directory](/usage-guides/advanced/data-directory) on the source system. 2. The global database is located at `/global/global.db` under the data directory above. Move it to the equivalent location on the new system. ![Manual DB sync](/images/rotki_premium_manual_db_sync.png) diff --git a/usage-guides/calendar.md b/usage-guides/integrations/calendar.md similarity index 94% rename from usage-guides/calendar.md rename to usage-guides/integrations/calendar.md index 3567bff..46f8742 100644 --- a/usage-guides/calendar.md +++ b/usage-guides/integrations/calendar.md @@ -1,3 +1,7 @@ +--- +description: Using the calendar to track events, set reminders, and receive automatic alerts like ENS expiration. +--- + # Calendar rotki provides a calendar view where you can add and track events for your activities. You can also set reminders to perform some actions related to these events. diff --git a/usage-guides/integrations/exchange-keys.md b/usage-guides/integrations/exchange-keys.md new file mode 100644 index 0000000..678c760 --- /dev/null +++ b/usage-guides/integrations/exchange-keys.md @@ -0,0 +1,109 @@ +--- +description: Connecting centralized exchanges to rotki via API keys, with per-exchange setup instructions. +--- + +# Exchange API Keys + +In this section, we will explain how to connect exchanges to rotki via API Keys. +Go to the `API Keys` menu in the sidebar. + +## rotki Premium + +![Set up rotki premium API key/secret pair in an existing account](/images/rotki_premium_set.png) + +A rotki premium subscription is activated in the app by adding your **API Key** and **API Secret**. +If you don't have a premium subscription yet, you can subscribe at [rotki.com/products](https://rotki.com/products/). + +For detailed information about premium plans, pricing, payment options, and how to use your premium API key see the [Premium documentation](/premium/). + +## Exchanges API Keys + +![List of connected exchanges](/images/rotki_add_exchange_2.png) + +You can integrate many different exchanges with rotki via API Keys. +Currently supported exchanges are: + +- Kraken (Spot and Future) +- Poloniex +- Binance +- Bitmex +- Coinbase +- Coinbase Pro +- Gemini +- Bitstamp +- Binance US +- Bitfinex +- Bitcoin.de +- Iconomi +- KuCoin +- Independent Reserve +- Bitpanda +- OKX +- Woo +- Bybit +- HTX + +![Add API keys for a new exchange](/images/rotki_add_exchange_1.png) + +### Steps to Add Exchange API Key: + +1. Create API key on your exchange (see [API key permissions](#api-key-permissions)) +2. Navigate to `API Keys > Exchanges` in the left sidebar +3. Click button `Add an exchange` to open addition menu +4. Enter your: + - API Key + - API Secret (for the majority of exchanges) + - Password (for some exchanges) +5. Click `Save` + +### After Adding: + +- Successful addition: Exchange will appear in your list +- If failed: + - Verify key and secret are correct + - Some exchanges may have issues due to timestamp difference between the computer and the server (e.g. binance, read [this](https://github.com/tiagosiebler/awesome-crypto-examples/wiki/Timestamp-for-this-request-is-outside-of-the-recvWindow)) + +### Sync Settings: + +- Option to enable/disable exchange synchronization +- Consider disabling to avoid IP bans from frequent syncs + +> **Note**: At the moment, [margin trades](https://github.com/rotki/rotki/issues/1980) and [future trades](https://github.com/rotki/rotki/issues/1606) are not yet supported in rotki. + +### API key permissions + +rotki only needs read-only permissions for your accounts. As a general rule, exchanges (e.g., Binance, Coinbase Pro) group all the read-only permissions as "read" or "view". + +![Simple API key permissions](/images/add_exchange_api_keys_binance.png) + +In the case of an exchange providing a more granular permissions scheme (e.g., Coinbase, Kraken) or having additional options (e.g., query limits, passphrase), refer to the exchange documentation or get in touch via their customer support channel. + +![Granular API key permissions](/images/add_exchange_api_keys_coinbase.png) + +You may also try creating an API key with the minimum read-related permissions, then adding it in rotki and finally checking that the connection was successful and data was loaded as expected. Otherwise, try again adding more read-related permissions. + +#### Kraken + +When inputting the API key for Kraken, you need to specify the type of your Kraken account, which depends on your Kraken account verification level. Refer to [this](https://support.kraken.com/hc/en-us/articles/360001395743-Verification-levels-explained) for more information. + +![Kraken account type](/images/exchanges_add_kraken.png) + +To track your Kraken Futures balances, you can optionally provide your Futures API key and Futures API secret in the same Kraken exchange form. Both fields must be provided together. When set, rotki will query your Kraken Futures cash, margin, and flex balances and merge them into your overall Kraken balance total. + +#### Binance / Binance US + +To improve the speed of querying trade information using the Binance API, you can specify which market pairs to query instead of querying all possible pairs. This reduces the number of requests made to Binance servers, avoiding potential rate limits and failures. To select specific markets, edit your Binance exchange instance configuration. + +![Edit Binance in the exchanges section](/images/exchanges_edit_binance.png) + +##### Market Pairs (required) + +Choose the markets in the `Filter market pair(s)` search. + +::: warning +**Due to Binance API limitations**, querying trade information does not work without specifying market pairs. Binance's endpoint requires every possible market pair to be queried individually, and their rate limits make it impossible to query all markets for your entire history. This API issue has existed for years and has not been fixed by Binance. You must select which specific markets you want to query for the integration to work properly. +::: + +![Binance markets selection](/images/binance_markets_selection.png) + +Once finished, click on save. diff --git a/usage-guides/api-keys.md b/usage-guides/integrations/external-services.md similarity index 50% rename from usage-guides/api-keys.md rename to usage-guides/integrations/external-services.md index 6421472..a15695a 100644 --- a/usage-guides/api-keys.md +++ b/usage-guides/integrations/external-services.md @@ -1,112 +1,10 @@ -# API Keys +--- +description: Configuring external service API keys such as Etherscan, CryptoCompare, and other data providers. +--- -In this section, we will explain various API Keys you can add to rotki. -Go to the `API Keys` menu in the sidebar. +# External Services -## rotki Premium - -![Set up rotki premium API key/secret pair in an existing account](/images/rotki_premium_set.png) - -A rotki premium subscription is activated in the app by adding your **API Key** and **API Secret**. -If you don't have a premium subscription yet, you can subscribe at [rotki.com/products](https://rotki.com/products/). - -For detailed information about premium plans, pricing, payment options, and how to use your premium API key see the [Premium documentation](/premium/). - -## Exchanges API Keys - -![List of connected exchanges](/images/rotki_add_exchange_2.png) - -You can integrate many different exchanges with rotki via API Keys. -Currently supported exchanges are: - -- Kraken (Spot and Future) -- Poloniex -- Binance -- Bitmex -- Coinbase -- Coinbase Pro -- Gemini -- Bitstamp -- Binance US -- Bitfinex -- Bitcoin.de -- Iconomi -- KuCoin -- Independent Reserve -- Bitpanda -- OKX -- Woo -- Bybit -- HTX - -![Add API keys for a new exchange](/images/rotki_add_exchange_1.png) - -### Steps to Add Exchange API Key: - -1. Create API key on your exchange (see [API key permissions](#api-key-permissions)) -2. Navigate to `API Keys > Exchanges` in the left sidebar -3. Click button `Add an exchange` to open addition menu -4. Enter your: - - API Key - - API Secret (for the majority of exchanges) - - Password (for some exchanges) -5. Click `Save` - -### After Adding: - -- Successful addition: Exchange will appear in your list -- If failed: - - Verify key and secret are correct - - Some exchanges may have issues due to timestamp difference between the computer and the server (e.g. binance, read [this](https://github.com/tiagosiebler/awesome-crypto-examples/wiki/Timestamp-for-this-request-is-outside-of-the-recvWindow)) - -### Sync Settings: - -- Option to enable/disable exchange synchronization -- Consider disabling to avoid IP bans from frequent syncs - -> **Note**: At the moment, [margin trades](https://github.com/rotki/rotki/issues/1980) and [future trades](https://github.com/rotki/rotki/issues/1606) are not yet supported in rotki. - -### API key permissions - -rotki only needs read-only permissions for your accounts. As a general rule, exchanges (e.g., Binance, Coinbase Pro) group all the read-only permissions as "read" or "view". - -![Simple API key permissions](/images/add_exchange_api_keys_binance.png) - -In the case of an exchange providing a more granular permissions scheme (e.g., Coinbase, Kraken) or having additional options (e.g., query limits, passphrase), refer to the exchange documentation or get in touch via their customer support channel. - -![Granular API key permissions](/images/add_exchange_api_keys_coinbase.png) - -You may also try creating an API key with the minimum read-related permissions, then adding it in rotki and finally checking that the connection was successful and data was loaded as expected. Otherwise, try again adding more read-related permissions. - -#### Kraken - -When inputting the API key for Kraken, you need to specify the type of your Kraken account, which depends on your Kraken account verification level. Refer to [this](https://support.kraken.com/hc/en-us/articles/360001395743-Verification-levels-explained) for more information. - -![Kraken account type](/images/exchanges_add_kraken.png) - -To track your Kraken Futures balances, you can optionally provide your Futures API key and Futures API secret in the same Kraken exchange form. Both fields must be provided together. When set, rotki will query your Kraken Futures cash, margin, and flex balances and merge them into your overall Kraken balance total. - -#### Binance / Binance US - -To improve the speed of querying trade information using the Binance API, you can specify which market pairs to query instead of querying all possible pairs. This reduces the number of requests made to Binance servers, avoiding potential rate limits and failures. To select specific markets, edit your Binance exchange instance configuration. - -![Edit Binance in the exchanges section](/images/exchanges_edit_binance.png) - -##### Market Pairs (required) - -Choose the markets in the `Filter market pair(s)` search. - -::: warning -**Due to Binance API limitations**, querying trade information does not work without specifying market pairs. Binance's endpoint requires every possible market pair to be queried individually, and their rate limits make it impossible to query all markets for your entire history. This API issue has existed for years and has not been fixed by Binance. You must select which specific markets you want to query for the integration to work properly. -::: - -![Binance markets selection](/images/binance_markets_selection.png) - -Once finished, click on save. - -## External services - -### Why External API Keys Are Needed +## Why External API Keys Are Needed Required for accessing: @@ -114,7 +12,7 @@ Required for accessing: - EVM transactions - Other external data services -### How to External Add API Keys: +## How to Add External API Keys: 1. Create free account on service website 2. Generate API key @@ -124,7 +22,7 @@ Required for accessing: ![External services](/images/external_services.png) -### Etherscan +## Etherscan We **strongly recommend** getting an Etherscan API Key - it's completely free and will make the queries much faster! Without it, the queries will be really slow. You just need to: @@ -135,7 +33,7 @@ Without it, the queries will be really slow. You just need to: You only need one Etherscan API key for all EVM chains since the key is now unified. -### Loopring balances +## Loopring balances To have your Loopring balances detected, you will need an API Key from Loopring. To get one, visit [Loopring Security](https://loopring.io/#/layer2/security) and unlock your account. In the list of options, click on **Export Account**. @@ -147,7 +45,7 @@ After following these steps, your balances in the dashboard will be updated incl ![Loopring balances in the UI](/images/loopring_balances.png) -### Monerium +## Monerium You can integrate Monerium with rotki to import your transaction data. This feature is only available for premium users. @@ -158,7 +56,7 @@ As long as you provide Monerium credentials, all Monerium transactions on Mainne ![Monerium decorated transactions](/images/monerium_transactions.png) -#### Adding Monerium OAuth Token +### Adding Monerium OAuth Token ![Monerium get access token](/images/monerium_get_access_token.png) ![Monerium OAuth](/images/monerium_oauth.png) @@ -178,17 +76,17 @@ To connect your Monerium account: - **Docker mode**: You will need to manually copy the access token and refresh token from the OAuth page and input them into rotki. 4. **Redecode Transactions:** - - After successfully adding your Monerium credentials, you need to redecode the Monerium transactions in the history events section to see the updated bank data. See [Redecoding blockchain transactions](/usage-guides/historical-events#redecoding-blockchain-transactions) for more information on how to redecode transactions. + - After successfully adding your Monerium credentials, you need to redecode the Monerium transactions in the history events section to see the updated bank data. See [Redecoding blockchain transactions](/usage-guides/history/events#redecoding-blockchain-transactions) for more information on how to redecode transactions. > **Note**: The Monerium credentials only provide read-only access to your Monerium data. When you authenticate, Monerium's OAuth consent screen may show that rotki is requesting broad permissions. This is because Monerium's API doesn't currently support granular permission scopes, so all OAuth tokens appear to request full access. However, rotki only performs read-only operations and cannot modify your account, initiate transfers, or make changes to your Monerium data. The OAuth authentication flow described above is mandated by Monerium's API requirements, not a design choice by rotki. rotki simply integrates with their authentication system as required. -### Gnosis Pay +## Gnosis Pay ![Gnosis Pay SIWE](/images/gnosis_pay_siwe.png) You can integrate Gnosis Pay with rotki to import your transaction data. This feature is only available for premium users. -#### Adding Gnosis Pay Access Token +### Adding Gnosis Pay Access Token To connect your Gnosis Pay account: @@ -201,11 +99,11 @@ To connect your Gnosis Pay account: - Sign the message to authenticate and get the access token. 3. **Redecode Transactions:** - - After successfully connecting your Gnosis Pay account, you need to redecode the Gnosis Pay transactions in the history events section to enrich the transaction details. See [Redecoding blockchain transactions](/usage-guides/historical-events#redecoding-blockchain-transactions) for more information on how to redecode transactions. + - After successfully connecting your Gnosis Pay account, you need to redecode the Gnosis Pay transactions in the history events section to enrich the transaction details. See [Redecoding blockchain transactions](/usage-guides/history/events#redecoding-blockchain-transactions) for more information on how to redecode transactions. > **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. -### The Graph +## The Graph rotki uses The Graph to obtain Balancer balances and particular ENS data. You can create one [here](https://thegraph.com/studio/apikeys). @@ -215,10 +113,10 @@ After creating the API key, you can add it to rotki. Additionally, ensure that t ![The Graph subgraphs](/images/the_graph_subgraphs.png) -### DefiLlama +## DefiLlama rotki integrates with DefiLlama for price data. An API key is not required, but a paid API key will provide higher rate limits. You can find more information about their API [here](https://defillama.com/pro-api). -### CoinGecko +## CoinGecko rotki uses CoinGecko for cryptocurrency data. An API key is not required, but a paid API key will provide higher rate limits. You can find more information about their API [here](https://www.coingecko.com/en/api). diff --git a/usage-guides/long-running-tasks.md b/usage-guides/long-running-tasks.md deleted file mode 100644 index 808a753..0000000 --- a/usage-guides/long-running-tasks.md +++ /dev/null @@ -1,9 +0,0 @@ -# Long running tasks - -A list of processing tasks is available on the notifications tray. - -![running background tasks](/images/pending_tasks.png) - -It is possible to cancel a long running task, but use this feature sparingly. - -![cancel background task](/images/pending_tasks_cancel.png) diff --git a/usage-guides/accounts-and-balances.md b/usage-guides/portfolio/accounts.md similarity index 59% rename from usage-guides/accounts-and-balances.md rename to usage-guides/portfolio/accounts.md index 809168d..628f161 100644 --- a/usage-guides/accounts-and-balances.md +++ b/usage-guides/portfolio/accounts.md @@ -1,4 +1,8 @@ -# Tracking Accounts & Balances +--- +description: Adding and managing blockchain accounts (EVM, Bitcoin, Substrate, Solana) and exchange connections. +--- + +# Tracking Accounts To manage Blockchain Accounts, you need to visit the `Accounts` section from the left sidebar. @@ -152,180 +156,3 @@ You can also see the breakdown of the assets, which locations they belong to, wh From the balances section you can quickly get an overview of the accounts having balances in Loopring and what assets these accounts hold. ![Loopring balances detailed per address](/images/loopring_balances_detailed.png) - -## Exchange Balances - -You can check all of the asset balances that you have in each connected exchange in the `Exchange Balances` sub-page. Clicking the `Add exchange` button takes you to the API Keys page where you can manage your exchange connections (see [Exchanges API Keys](/usage-guides/api-keys#exchanges-api-keys)). - -![Exchange Balance](/images/sc_exchange_balances.png) - -## Manual Balances - -You can add any type of asset to rotki, that may not officially supported yet. This includes things like: - -- Real estate -- Stocks -- Assets from unsupported blockchains or exchanges - -To add or edit a manual balance: - -1. Go to the Manual Balances page -2. Click `Add Manual Balance` (top right) -3. Add a unique label -4. Select your asset from the dropdown -5. Add any tags you want -6. Enter the amount and location - -You can also filter the manual balances by `location`, `name` or `asset`. - -![The manually tracked balances](/images/sc_manual_balances.png) - -By pressing the edit button for the account you can also add tags to the blockchain account. If you want to create a new tag or edit an existing one you can open the [tag manager](/usage-guides/tag-management) and choose the name, description and colors of the tag. - -## NFTs - -rotki provides an NFT gallery where you can view the NFTs owned by your accounts. - -![NFT Gallery](/images/sc_nfts.png) - -You have an overview of the total value of your NFTs in the application dashboard, on the NFTs table. - -![NFT Value Dashboard](/images/sc_nf_balances_dashboard.png) - -An estimation of the value of the NFTs you own is counted into your total net worth. The estimation strategy is currently the maximum of either the floor price of the collection or the last sale of the NFT. If a manual price has been given this is always preferred. - -![NFT Value Dashboard](/images/sc_nft_balances.png) - -If a price cannot be found for an NFT asset or if you want to change the calculated price estimate you can easily set the price for an NFT asset manually. You can do this by either clicking on the `>` button in the NFTs table in the dashboard or by going to `Blockchains & Accounts β†’ NFT Balances`. And then click on the pen icon for the NFT you are interested in. - -For privacy concerns, it is possible to allow all or only a certain list of domains for images rendered, this can be done here by clicking on the icon highlighted below. - -More details here [Critical Privacy Vulnerability: Getting Exposed by MetaMask](https://medium.com/@alxlpsc/critical-privacy-vulnerability-getting-exposed-by-metamask-693c63c2ce94) - -The configuration menu: - -![NFT Image Render Settings](/images/sc_nf_image_render_settings.png) - -Highlight details: - -1. Link to blog post about image rendering and privacy. -2. Option to allow all NFT images to be rendered. -3. Option to allow only whitelisted domains. -4. If only whitelist, input list of allowed domains. -5. Save button. - -![NFT Image Render Settings](/images/sc_nf_image_render_settings_whitelist.png) - -This will enable image rendering of only whitelisted NFT domains. - -## Filtering by tags - -You can filter the tables by a combination of tags. - -![Filter the accounts by tag](/images/filter_by_tag.png) - -Simply add the tags you wish to filter by in the filter textbox above the tables. - -## Hide small balances - -You can filter out small balances and set the threshold yourself. - -By default, this setting will apply to all balance types (blockchain balances, exchange balances, and manual balances). -You can uncheck the checkbox to apply the setting only to the current balances view. - -> [!NOTE] -> You need to press "Apply Changes" for the setting to take effect. - -![Hide small balances](/images/hide_small_balances.png) - -## Airdrops - -rotki can detect some airdrops for you - -![rotki airdrops detection](/images/rotki_airdrops.png) - -The list of currently supported airdrops is: - -- Uniswap -- 1INCH -- Tornado -- Cornichon -- Grain -- Furocombo -- Lido -- Curve -- Convex -- Shapeshift -- ENS -- ParaSwap -- Saddle finance -- Cow -- Diva -- Shutter -- Starknet -- Optimism 4 -- Degen 2 -- Omni -- Eigen token - -For some airdrops, you may see the status `Unknown`. This means rotki can't determine the status of the airdrop, whether it has been claimed or not. You need to check it yourself. - -## Balances Snapshots - -The application automatically saves balance snapshots to your local database: - -- Occurs at login -- Default interval: every 24 hours (configurable) - -To manually create a snapshot: - -1. Click the `arrow down` near the graph -2. Select `Force Save` - -![Force snapshots saves](/images/rotki_snapshot_forcing.png) - -### Error Handling - -- Snapshots won't save if there are external source query errors -- To save despite errors, select `Ignore Errors` - -### Modify a snapshot point - -1. Click on a snapshot point in the dashboard's net value graph -2. From the menu you can: - - Edit snapshot data - - Remove the snapshot - - Download the snapshot - -![Delete snapshot](/images/delete_snapshot_menu.png) - -### Edit Snapshots Value - -- Click a snapshot point -- Select edit -- Modify values for assets and locations as needed - -![Edit snapshot](/images/edit_snapshot_menu.png) - -### Delete Snapshots - -Click a snapshot point and select delete to remove saved information. - -### Download/Export Snapshots - -When exporting, four files are generated: - -1. Two files for future data import -2. Two human-readable files for accounting: - - `balances_snapshot`: Asset balances at snapshot time - - `location_data_snapshot`: Value per location for each asset - -### Import Snapshot Back - -To import previously exported snapshot data: - -1. Use files with `_import` suffix -2. Click the `Arrow down` button near the chart -3. Select `Import` - -![Import snapshots information](/images/import_snapshot.png) diff --git a/usage-guides/portfolio/balances.md b/usage-guides/portfolio/balances.md new file mode 100644 index 0000000..ab54a8c --- /dev/null +++ b/usage-guides/portfolio/balances.md @@ -0,0 +1,182 @@ +--- +description: Viewing exchange balances, adding manual balances, tracking NFTs, airdrops, and managing snapshots. +--- + +# Balances + +## Exchange Balances + +You can check all of the asset balances that you have in each connected exchange in the `Exchange Balances` sub-page. Clicking the `Add exchange` button takes you to the API Keys page where you can manage your exchange connections (see [Exchanges API Keys](/usage-guides/integrations/exchange-keys#exchanges-api-keys)). + +![Exchange Balance](/images/sc_exchange_balances.png) + +## Manual Balances + +You can add any type of asset to rotki, that may not officially supported yet. This includes things like: + +- Real estate +- Stocks +- Assets from unsupported blockchains or exchanges + +To add or edit a manual balance: + +1. Go to the Manual Balances page +2. Click `Add Manual Balance` (top right) +3. Add a unique label +4. Select your asset from the dropdown +5. Add any tags you want +6. Enter the amount and location + +You can also filter the manual balances by `location`, `name` or `asset`. + +![The manually tracked balances](/images/sc_manual_balances.png) + +By pressing the edit button for the account you can also add tags to the blockchain account. If you want to create a new tag or edit an existing one you can open the [tag manager](/usage-guides/data-management/tags) and choose the name, description and colors of the tag. + +## NFTs + +rotki provides an NFT gallery where you can view the NFTs owned by your accounts. + +![NFT Gallery](/images/sc_nfts.png) + +You have an overview of the total value of your NFTs in the application dashboard, on the NFTs table. + +![NFT Value Dashboard](/images/sc_nf_balances_dashboard.png) + +An estimation of the value of the NFTs you own is counted into your total net worth. The estimation strategy is currently the maximum of either the floor price of the collection or the last sale of the NFT. If a manual price has been given this is always preferred. + +![NFT Value Dashboard](/images/sc_nft_balances.png) + +If a price cannot be found for an NFT asset or if you want to change the calculated price estimate you can easily set the price for an NFT asset manually. You can do this by either clicking on the `>` button in the NFTs table in the dashboard or by going to `Blockchains & Accounts β†’ NFT Balances`. And then click on the pen icon for the NFT you are interested in. + +For privacy concerns, it is possible to allow all or only a certain list of domains for images rendered, this can be done here by clicking on the icon highlighted below. + +More details here [Critical Privacy Vulnerability: Getting Exposed by MetaMask](https://medium.com/@alxlpsc/critical-privacy-vulnerability-getting-exposed-by-metamask-693c63c2ce94) + +The configuration menu: + +![NFT Image Render Settings](/images/sc_nf_image_render_settings.png) + +Highlight details: + +1. Link to blog post about image rendering and privacy. +2. Option to allow all NFT images to be rendered. +3. Option to allow only whitelisted domains. +4. If only whitelist, input list of allowed domains. +5. Save button. + +![NFT Image Render Settings](/images/sc_nf_image_render_settings_whitelist.png) + +This will enable image rendering of only whitelisted NFT domains. + +## Filtering by tags + +You can filter the tables by a combination of tags. + +![Filter the accounts by tag](/images/filter_by_tag.png) + +Simply add the tags you wish to filter by in the filter textbox above the tables. + +## Hide small balances + +You can filter out small balances and set the threshold yourself. + +By default, this setting will apply to all balance types (blockchain balances, exchange balances, and manual balances). +You can uncheck the checkbox to apply the setting only to the current balances view. + +> [!NOTE] +> You need to press "Apply Changes" for the setting to take effect. + +![Hide small balances](/images/hide_small_balances.png) + +## Airdrops + +rotki can detect some airdrops for you + +![rotki airdrops detection](/images/rotki_airdrops.png) + +The list of currently supported airdrops is: + +- Uniswap +- 1INCH +- Tornado +- Cornichon +- Grain +- Furocombo +- Lido +- Curve +- Convex +- Shapeshift +- ENS +- ParaSwap +- Saddle finance +- Cow +- Diva +- Shutter +- Starknet +- Optimism 4 +- Degen 2 +- Omni +- Eigen token + +For some airdrops, you may see the status `Unknown`. This means rotki can't determine the status of the airdrop, whether it has been claimed or not. You need to check it yourself. + +## Balances Snapshots + +The application automatically saves balance snapshots to your local database: + +- Occurs at login +- Default interval: every 24 hours (configurable) + +To manually create a snapshot: + +1. Click the `arrow down` near the graph +2. Select `Force Save` + +![Force snapshots saves](/images/rotki_snapshot_forcing.png) + +### Error Handling + +- Snapshots won't save if there are external source query errors +- To save despite errors, select `Ignore Errors` + +### Modify a snapshot point + +1. Click on a snapshot point in the dashboard's net value graph +2. From the menu you can: + - Edit snapshot data + - Remove the snapshot + - Download the snapshot + +![Delete snapshot](/images/delete_snapshot_menu.png) + +### Edit Snapshots Value + +- Click a snapshot point +- Select edit +- Modify values for assets and locations as needed + +![Edit snapshot](/images/edit_snapshot_menu.png) + +### Delete Snapshots + +Click a snapshot point and select delete to remove saved information. + +### Download/Export Snapshots + +When exporting, four files are generated: + +1. Two files for future data import +2. Two human-readable files for accounting: + - `balances_snapshot`: Asset balances at snapshot time + - `location_data_snapshot`: Value per location for each asset + +### Import Snapshot Back + +To import previously exported snapshot data: + +1. Use files with `_import` suffix +2. Click the `Arrow down` button near the chart +3. Select `Import` + +![Import snapshots information](/images/import_snapshot.png) diff --git a/usage-guides/settings/account.md b/usage-guides/settings/account.md new file mode 100644 index 0000000..8a87fc5 --- /dev/null +++ b/usage-guides/settings/account.md @@ -0,0 +1,62 @@ +--- +description: Managing account passwords, database backups, data purging, and user settings import/export. +--- + +# Account & Database Settings + +## Account Settings + +### Changing Password + +Choose the "User & Security" section to change the user password. + +![Changing the user's password](/images/sc_user_password_change.png) + +## Database Settings + +### Database Info & User Database Backups + +View information about your user and global database, such as directory, size, and version. + +![Creating database backups](/images/sc_db_backup.png) + +Create new database backups, delete backups, and download backups locally. + +### 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. + +![Purging user data](/images/sc_purge_data.png) + +### Exporting and Importing User Assets + +Use the export/import function to migrate user assets between computers. This function creates a zip archive of user assets for transfer. + +![Importing user assets](/images/sc_custom_import_export.png) + +> [!WARNING] +> This archive cannot be used as a backup/restore across different versions of rotki since there is no guarantee of compatibility across versions. + +### Reset Assets Database + +There are two options to reset the assets database: + +1. **Soft Reset**: This option will not reset assets added by the user. +2. **Hard Reset**: This option will reset assets added by the user. + +## Backend Settings + +Desktop app users can change the default data directory and log directory via the login screen. Click the cog wheel at the bottom right to view the backend settings dialog. + +![Change the backend settings](/images/rotki_backend_settings.png) + +Select a new data directory, log directory, etc., and press "Save". Previously created accounts won't be accessible in the new location; move them manually. + +### Advanced Backend Settings + +Modify the following settings in the advanced section: + +- **Max log size**: Maximum size (MB) of all logs for a single run. +- **Max number of log files**: Maximum number of backup (rotated) logs for a single run. +- **Instructions per SQLite context switch**: Specify instructions count for context switch between cooperative threads. Set to `0` to disable async DB access. +- **Log from other modules**: Include log entries from dependent libraries, not just rotki. Disabled by default. diff --git a/usage-guides/settings/accounting.md b/usage-guides/settings/accounting.md new file mode 100644 index 0000000..35781cb --- /dev/null +++ b/usage-guides/settings/accounting.md @@ -0,0 +1,135 @@ +--- +description: Configuring accounting rules, cost basis methods, trade settings, and custom event rules for PnL reports. +--- + +# Accounting Settings + +> [!TIP] +> For a detailed explanation of what each accounting option does (with worked examples), see [Accounting Rule Options Explained](/usage-guides/tax-accounting/accounting-rules). + +![Customizing the accounting rules](/images/sc_accounting_custom_rule.png) + +In the accounting menu, you can customize application settings related to accounting calculations. These settings will affect the PnL report calculations. + +> [!IMPORTANT] +> Before changing any settings: +> +> 1. Review each option carefully +> 2. Check with your tax advisor about what's required in your country +> 3. Make adjustments based on their guidance + +**Current Default Settings:** + +- Based on German tax rules +- Uses first-in/first-out (FIFO) method for calculating profits/losses +- Treats crypto sales as tax-free after holding for 1 year + +You can change these settings to match your country's tax requirements. + +### Add/Edit Accounting Rules + +![Add new accounting rules](/images/sc_accounting_add_rule.png) + +You can add or edit accounting rules based on `Event type`, `Event subtype`, and `Counterparty`. + +### Special Accounting Rules For Specific Events + +![Special Accounting Rules](/images/sc_accounting_rules_special.png) + +You can set custom accounting rules for individual events or groups of events directly from the History Events page. This allows you to override the default accounting behavior for specific events. + +There are two ways to apply special rules: + +- Use the [Edit accounting rule](/usage-guides/history/events#edit-accounting-rule) menu for individual events +- Use [Select multiple events](/usage-guides/history/events#select-multiple-events) to apply rules to multiple events at once + +### Trade Settings + +![Customizing the accounting trade settings](/images/sc_accounting_trade_settings.png) + +#### Crypto to Crypto Trades + +A setting to determine whether crypto to crypto trades or any events that spend crypto are taxable and should be taken into account. By default it's `True`. + +:::tabs +== Crypto to Crypto Trades + +> **Illustration:** +> You trade your `1 ETH`, to get `11 USDT`. Current price of ETH is `10 EUR`, but you bought it when it was `5 EUR`. + +1. If `True`, virtual trades are generated, and profits/losses are calculated based on the difference in asset prices. By making this trade, we will create two virtual trade, which are: + - **Virtual Trade 1**: Sell `1 ETH` for `10 EUR`. PnL of this virtual trade is calculated as `the value when you sell this ETH (10 EUR)` minus `the value when you bought this ETH (5 EUR)` = `5 EUR`. + - **Virtual Trade 2**: Buy `11 USDT` with `10 EUR`. PnL of this virtual trade is `0 EUR` because it's a buy. However, later on, when you trade this `USDT` with another crypto, point (1) will also be applied. + > **Total PnL** = `5 EUR`. + +2. If `False`, no virtual trades are generated, and no additional profits/losses are calculated. + > **Total PnL** = `0 EUR`. + +== Crypto Spending + +> **Illustration:** +> You have `1` ETH that you bought with price `50 EUR`. Then you spend this `1` ETH for gas fees, and the price at the moment is `100 EUR`. + +1. If `True`, when you use crypto for fees, donations, or purchases, the profit and loss (PnL) calculation shows two things: the loss from spending the crypto and any profit or loss from the difference between the asset's current price and its buying price. + - **Loss from spending** = `-100 EUR`. + - **Profit from price difference** = `100 EUR (spend price) - 50 EUR (buy price) = 50 EUR`. + > **Total PnL** = `-100 EUR + 50 EUR` = `-50 EUR`. + +2. If `False`, only the spending loss is considered. + > **Total PnL** = `-100 EUR`. + +::: + +#### EVM Gas Costs + +Specify if EVM transaction gas costs should be counted as a loss. + +#### Tax Free Period + +Specify if there is a tax-free holding period for crypto assets. + +#### Calculate Past Cost Basis + +Enable or disable calculating cost basis from all past events, even before the report period. + +#### Omit ETH Staking Events + +Specify if ETH staking events are taxable only after the merge and withdrawals are enabled or at the point of receiving. + +#### Cost Basis Method + +Select the cost basis calculation method: `FIFO`, `LIFO`, `HIFO`, or `ACB`. + +#### Include Fees in Cost Basis + +A setting to determine if trade fees should be included in the cost basis of the asset being bought/sold. By default, this setting is `True`. + +> **Illustration:** +> You bought `1` ETH for `10 EUR` and paid `1 EUR` fee. + +:::tabs +== True + +The fee event only reduces the amount of the fee asset paid. The actual fee is then used to determine the cost basis of the asset being bought or sold. + +> The cost basis of that ETH is `10 + 1` = `11 EUR`. This is where the fee is taken into account. + +== False + +The above does not happen. + +> The cost basis of that ETH is `10 EUR`. But at the time of the trade you also have a spend event of `1 EUR` as fee. + +::: + +### CSV Export Settings + +![Customizing the CSV export settings](/images/sc_accounting_csv_export_settings.png) + +#### Export Formulas + +Specify if formulas should be exported as formulas in the CSV or as actual values. + +#### Have Summary + +Specify whether the all_events CSV export should include a summary of all events and the total profit/loss at the end. This summary would also include the rotki version and the settings used during the PnL report, making it easier to reproduce a report run. diff --git a/usage-guides/settings/blockchain.md b/usage-guides/settings/blockchain.md new file mode 100644 index 0000000..d88d331 --- /dev/null +++ b/usage-guides/settings/blockchain.md @@ -0,0 +1,102 @@ +--- +description: Configuring EVM chain settings, RPC nodes, transaction indexers, price oracles, and DeFi modules. +--- + +# Blockchain & EVM Settings + +## EVM + +![EVM settings](/images/sc_evm_settings.png) + +#### Treat Staked ETH as ETH + +If enabled, ETH2 (staked ETH) will appear as ETH in the UI, and all tables and charts will combine the values of ETH and ETH2. + +#### EVM Chains for Automatic Detection + +Configure which EVM chains should not automatically detect tokens. By default, EVM chains detect activities of all registered EVM accounts in other EVM chains. + +### Indexers + +rotki uses several indexers to identify which transactions belong to your tracked addresses. The order used for each chain can be adjusted in the default settings and will apply unless a specific chain configuration overrides it. For example you may want to avoid using etherscan on Optimism and Base if you do not have a paid API key for those networks. + +This lets you control which sources are queried and change the configuration if one of them is unreliable for a particular chain. + +In addition to querying historical events, indexers are used when detecting onchain activity, for example when you add a new address to all supported EVM chains or when the periodic task performs this check in the background. + +At the time of writing the only chain that cannot be queried for free is Binance SC because neither blockscout nor routescan are available and etherscan requires an API key under the Lite plan. + +Regarding the need for API keys: + +- Etherscan requires an API key in the free tier to perform API calls. +- Blockscout does not require an API key and has a default limit of 10 requests per second. +- Routescan offers a free tier comparable to etherscan and does not require an API key. + +## Price Oracle Settings + +![Change the order of price sources](/images/sc_price_oracle_order.png) + +Here, you can customize the order in which price oracles are queried, both for current and historical prices. This determines which price source to check first, second, and so on. + +DeFi oracles like Uniswap V2 and Uniswap V3 use only on-chain information to get current prices. This makes querying a bit slower, but it relies solely on the Ethereum chain. Prices for some assets may differ from Coingecko or CryptoCompare, depending on the conditions of the pools at the time of the query. + +### Oracle cache + +![Creating a historical price cache](/images/sc_historical_price_cache.png) + +Querying historical prices from oracles such as CryptoCompare and CoinGecko is slow and can be slower due to rate limiting. rotki creates historical price caches during idle times. + +Request the creation of such a cache by going to the Oracle cache section, selecting the oracle, the from asset of the pair, the to asset of the pair, and then pressing "Cache pair prices". + +Manage existing historical price cache entries, inspect start and end dates, and delete caches if needed. + +## RPC Node Setting + +This setting lets you change the nodes used to connect to blockchains. We give you a list of public nodes, but sometimes they are busy or down. You will see a green or red icon showing if a node is working. + +It is good to add more nodes and set their priority. We always try your own nodes first, then use some random public nodes if needed. If you don't have your own node, we use public nodes. + +The node's weight (percentage) shows how likely it is to be used. You can turn nodes on or off with the toggle button. + +![Customizing the app's connection to EVM nodes](/images/rotki_nodes_management.png) + +In this menu you can also edit, delete or add more nodes. + +![Add an EVM node](/images/rotki_nodes_management_addition.png) + +### Local Nodes + +#### Connecting to a Kusama Client + +rotki attempts to connect to a local Kusama node running on the default port `9933`. If no client is running, blockchain queries will use an external service. + +#### Connecting to a Polkadot Client + +Set the RPC endpoint for a Polkadot node here. + +#### Connecting to an ETH Consensus Layer Beacon Node + +Set the RPC endpoint for the Ethereum consensus layer beacon node. If unreachable, beaconcha.in will be used. For DAppNode Ethereum validator users, find the RPC node setting in the DAppNode Package for the Execution Client. + +#### Connecting to a Bitcoin Mempool instance + +A local Bitcoin node can be used to query balances and transactions via [Mempool](https://mempool.space)'s API. [Mempool](https://github.com/mempool/mempool) is an open source project that can be self-hosted on Bitcoin nodes. It is readily available to install on many full-node distros such as Umbrel or Raspiblitz. Mempool uses port 4080 by default. Please include this when setting the endpoint (e.g. `http://localhost:4080`). Other custom ports should also work. +Please note that transaction querying is currently not supported and historical transaction fetching will fail. Only address balance querying is supported when using a custom mempool instance. + +## Module Settings + +Choose the "Module" section of the settings to customize the enabled modules and the queried addresses for each module. + +Enabling only the modules you use and specifying addresses improves querying speed. + +![Managing module settings](/images/module_settings.png) + +### Activating/Deactivating Modules + +View all modules in the table. Some are activated by default. Enable/disable a module by toggling the switch. Re-login for changes to take effect. + +### Selecting Addresses + +![Select address for modules](/images/module_settings_select_address.png) + +To limit querying to selected addresses, click the "edit/pencil" button on the module to select addresses. If no addresses are selected, rotki checks all eligible addresses, increasing query duration. diff --git a/usage-guides/settings/general.md b/usage-guides/settings/general.md new file mode 100644 index 0000000..30098b9 --- /dev/null +++ b/usage-guides/settings/general.md @@ -0,0 +1,113 @@ +--- +description: Configuring general app settings including profit currency, analytics, CSV export, and NFT display options. +--- + +# General Settings + +This section provides information on how to customize the application through the settings. Click on the user icon on the top right and choose "Settings" to access basic customization options. + +## Profit Currency + +rotki calculates everything, including your total profit/loss during the PnL report, in a given fiat currency, called the `profit_currency`. By default, this is USD. You can change this by clicking on the currency icon in the top right menu and selecting your preferred currency. + +![Changing the profit currency](/images/sc_profit_currency.png) + +## Application Settings + +Access the settings menu via `User icon β†’ Settings`. + +## General Settings + +![Customizing the general app settings](/images/sc_general_settings.png) + +#### Anonymous Usage Analytics + +Specify whether the application can submit anonymous usage analytics. This helps measure active users while ensuring data is anonymized and contains no sensitive information. + +#### Auto detect tokens + +Specify whether to automatically detect tokens and refresh balances by periodically checking historical events. + +#### CSV Export + +Specify your preferred date format and delimiter for CSV exports. + +#### Automatic database sync + +Whether to force push when a size discrepancy occurs during automatic db sync. + +#### Version update check + +Set how often (in hours) the version will be checked for updates. + +#### Balance Snapshots Saving Frequency + +Set how often (in hours) the balance data snapshots are saved. This data helps calculate statistics historical and graph data for the user. + +#### BTC Derivation Gap Limit + +Set the derivation gap limit for deriving addresses from a bitcoin xpub. More information [here](https://insights.blockonomics.co/bitcoin-what-is-this-gap-limit/). + +#### Date Format + +Set the date display and date input format in the rotki user interface, such as `%m/%d/%Y %H:%M:%S` for month/day/year hour:minutes:seconds. Check [here](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes) for valid formats. + +### Amount Settings + +![Customizing the app's amount settings](/images/sc_amount_settings.png) + +#### Main Currency + +Same as [changing the profit currency](#profit-currency). + +#### Floating Precision + +Set the number of decimal points shown in the UI for floating point numbers. + +#### Thousands Separator + +Set the symbol separating every 3 digits for large numbers, e.g., `1,000,000`. + +#### Decimal Separator + +Set the symbol separating the floating part of a number, e.g., `5.42`. + +### Subscript Format + +Whether to apply subscript formatting for consecutive zeros after the decimal point in small numbers, e.g., `0.000000087` => `0.0₇87`. + +#### Amount Rounding + +Choose the rounding mechanism: `Round up`, `Round down`, or `Half even`. Customize how amounts and values are rounded. + +#### Abbreviation for large numbers + +If enabled, large numbers will be abbreviated, e.g., `1,234,567` as `1.23 M`. Set the minimum value to be abbreviated. + +#### Currency Location + +Set whether the currency symbol appears before or after the number, e.g., `$1,000` or `1,000$`. + +### NFT Settings + +![Customizing the app's NFT settings](/images/sc_nf_settings.png) + +#### Include NFTs in Graphs and Total Amounts + +Decide whether to include NFTs in total net worth calculations and displayed graphs. + +#### NFT Images Rendering Setting + +For privacy, allow images from all or specific domains. More details [here](https://medium.com/@alxlpsc/critical-privacy-vulnerability-getting-exposed-by-metamask-693c63c2ce94). + +### External Service Settings + +Define rules for retry and timeout for external service calls made by rotki. + +### Backend Settings + +![Customizing the backend settings](/images/usage_guides_settings_general_backend_settings.webp) + +#### Log Level + +Specify the minimum severity level for recorded log messages. You can change this at runtime without restarting rotki. This is useful for temporarily enabling debug logs when troubleshooting issues, without needing to modify the [`rotki_config.json`](/usage-guides/advanced/backend-config.html) file or restart the application. Additional log-related settings such as max log size, max number of log files, and logging from other modules can be configured from the [login screen backend settings](/usage-guides/settings/account#advanced-backend-settings). diff --git a/usage-guides/settings/interface.md b/usage-guides/settings/interface.md new file mode 100644 index 0000000..ce6ae1c --- /dev/null +++ b/usage-guides/settings/interface.md @@ -0,0 +1,55 @@ +--- +description: Customizing the rotki interface including language, theme, animations, balance refresh, and explorer links. +--- + +# Interface Settings + +## Interface-only Settings + +![Customizing the app's interface only settings](/images/sc_interface_only_settings.png) + +#### Language + +Set the language used in the app. This feature is experimental and may not work as expected for some languages. Help us speed up the translation process by contributing [here](/contribution-guides/contribute-as-developer.html#add-a-new-language-or-translation). + +#### Animation Effect + +Reduce animation effects to improve performance. This affects animation quality but optimizes resource usage. + +#### Data Scrambling + +Enable data scrambling to randomize amounts, dates, and other data for privacy in screenshots. This setting does not persist across sessions. + +#### Automatic Balance Refresh + +Enable or disable automatic balance refresh and set the refresh interval. Disabled by default due to potential slow queries and rate limits. + +#### Periodic Status Query + +Set the frequency of backend data updates. Default is 5 seconds. + +#### Blockchain Explorer Customization + +Customize which explorer is used for transaction and address links. + +### Graph Settings + +#### Dashboard Graph Default Timeframe + +Set the default timeframe for the dashboard graph, which will be pre-selected upon login. + +#### Graph Basis + +Configure whether the graph y-axis starts at 0 or the minimum amount for the period. + +### Alias Name for Addresses + +Enable or disable alias names for blockchain addresses. Aliases are obtained from `ENS`, `addressbook`, or `blockchain account label`. Change the order of resolution as needed. + +### Theme Customization [Premium] + +Premium users can customize colors for light or dark mode. + +## Disabling the Tray Icon + +Disable the application tray icon by clicking the `View` menu entry in the application menu bar. Select `Display Tray Icon` to enable/disable the tray icon. diff --git a/usage-guides/staking.md b/usage-guides/staking.md index b2578d1..a1e1663 100644 --- a/usage-guides/staking.md +++ b/usage-guides/staking.md @@ -1,3 +1,7 @@ +--- +description: How to track ETH2 validator staking, Liquity staking, and Kraken staking in rotki. +--- + # Staking rotki currently supports staking tracking for: diff --git a/usage-guides/statistic.md b/usage-guides/statistics.md similarity index 96% rename from usage-guides/statistic.md rename to usage-guides/statistics.md index 44937b7..517330c 100644 --- a/usage-guides/statistic.md +++ b/usage-guides/statistics.md @@ -1,3 +1,7 @@ +--- +description: Viewing net value graphs, asset amount/value charts, and balance snapshots with rotki premium. +--- + # Statistics If you have a premium subscription you can get statistics on all your assets and trades. @@ -70,7 +74,7 @@ Moreover, you can see a pie chart of the distribution of your net value across a ![Distribution of networth by asset](/images/sc_stats_distribution_asset.png) > [!NOTE] -> The pie charts showing value distribution by location and asset use data from your latest snapshot, not your current balance. To see the most recent data, you'll need to [create a new snapshot](/usage-guides/accounts-and-balances#balances-snapshots). +> The pie charts showing value distribution by location and asset use data from your latest snapshot, not your current balance. To see the most recent data, you'll need to [create a new snapshot](/usage-guides/portfolio/balances#balances-snapshots). ## Event Analysis diff --git a/usage-guides/accounting-rules.md b/usage-guides/tax-accounting/accounting-rules.md similarity index 92% rename from usage-guides/accounting-rules.md rename to usage-guides/tax-accounting/accounting-rules.md index ed15903..638082c 100644 --- a/usage-guides/accounting-rules.md +++ b/usage-guides/tax-accounting/accounting-rules.md @@ -1,6 +1,10 @@ +--- +description: Detailed explanation of every accounting setting in rotki including cost basis methods and tax-free periods. +--- + # Accounting Rule Options Explained -This page explains every accounting setting in rotki in detail. These settings control how your transactions are processed when generating a [Profit/Loss Report](/usage-guides/pnl). You can configure them under **Settings β†’ Accounting Settings** ([screenshot guide](/usage-guides/customization#accounting-settings)). +This page explains every accounting setting in rotki in detail. These settings control how your transactions are processed when generating a [Profit/Loss Report](/usage-guides/history/pnl). You can configure them under **Settings β†’ Accounting Settings** ([screenshot guide](/usage-guides/settings/accounting#accounting-settings)). > [!IMPORTANT] > rotki's default settings are based on German tax rules. Check with your tax advisor about what's required in your country and adjust accordingly. @@ -103,7 +107,7 @@ Whether trading fees are added to the cost basis of the asset you're buying. ## Understanding accounting rule properties -When you create or edit an [accounting rule](/usage-guides/customization#add-edit-accounting-rules), or when you look at the default rules in rotki's codebase, each rule has several properties that control how events are processed: +When you create or edit an [accounting rule](/usage-guides/settings/accounting#add-edit-accounting-rules), or when you look at the default rules in rotki's codebase, each rule has several properties that control how events are processed: ### Taxable @@ -168,12 +172,12 @@ You can create custom rules that override the defaults for specific combinations - Event subtype - Counterparty (protocol identifier) -See [Add/Edit accounting rules](/usage-guides/customization#add-edit-accounting-rules) for how to create them in the UI. +See [Add/Edit accounting rules](/usage-guides/settings/accounting#add-edit-accounting-rules) for how to create them in the UI. ### 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). -- **Rules are global**: A rule applies to all events matching the type/subtype/counterparty combination. For per-event overrides, use [special accounting rules for specific events](/usage-guides/customization#special-accounting-rules-for-specific-events). +- **Rules are global**: A rule applies to all events matching the type/subtype/counterparty combination. For per-event overrides, use [special accounting rules for specific events](/usage-guides/settings/accounting#special-accounting-rules-for-specific-events). ## CSV export settings diff --git a/usage-guides/event-types.md b/usage-guides/tax-accounting/event-types.md similarity index 99% rename from usage-guides/event-types.md rename to usage-guides/tax-accounting/event-types.md index 9f11dc9..9921b4f 100644 --- a/usage-guides/event-types.md +++ b/usage-guides/tax-accounting/event-types.md @@ -1,3 +1,7 @@ +--- +description: Complete reference of all event types and subtypes in rotki with examples and default tax treatments. +--- + # Event Types and Subtypes Reference This page provides a complete reference for all event types and subtypes in rotki. Understanding these categories is essential for reviewing your transaction history and ensuring your PnL reports are accurate. @@ -351,6 +355,6 @@ The entry type determines which fields are available when editing an event. For ## Editing events -If an event is miscategorized, you can edit it directly from the History Events page. See the [common customization guide](/usage-guides/historical-events#common-customization) for step-by-step instructions and examples. +If an event is miscategorized, you can edit it directly from the History Events page. See the [common customization guide](/usage-guides/history/events#common-customization) for step-by-step instructions and examples. Changes you make to event types/subtypes directly affect how they are processed in the PnL report. diff --git a/usage-guides/tax-accounting.md b/usage-guides/tax-accounting/guide.md similarity index 62% rename from usage-guides/tax-accounting.md rename to usage-guides/tax-accounting/guide.md index 93f8b2b..9454e14 100644 --- a/usage-guides/tax-accounting.md +++ b/usage-guides/tax-accounting/guide.md @@ -1,3 +1,7 @@ +--- +description: Step-by-step walkthrough for calculating crypto taxes with rotki, from data setup to PnL report generation. +--- + # Using rotki for Tax Accounting This guide walks you through using rotki to calculate your cryptocurrency taxes. If you just installed rotki and want to generate a tax report, this is the page for you. @@ -9,8 +13,8 @@ This guide walks you through using rotki to calculate your cryptocurrency taxes. The two most important sections of rotki for tax accounting are: -1. **[History Events](/usage-guides/historical-events)** β€” where you review, correct, and customize all of your transactions -2. **[Profit/Loss Report](/usage-guides/pnl)** β€” where you generate the actual PnL (profit and loss) report for a given time period +1. **[History Events](/usage-guides/history/events)** β€” where you review, correct, and customize all of your transactions +2. **[Profit/Loss Report](/usage-guides/history/pnl)** β€” where you generate the actual PnL (profit and loss) report for a given time period Everything else in rotki (adding accounts, importing data, configuring settings) feeds into these two sections. @@ -20,15 +24,15 @@ Everything else in rotki (adding accounts, importing data, configuring settings) Before you can generate a tax report, rotki needs to know about your transactions. -- **Exchanges**: Add API keys for your centralized exchanges under [API Keys](/usage-guides/api-keys). rotki will automatically pull your trade history, deposits, and withdrawals. -- **Blockchain accounts**: Add your EVM, Bitcoin, or Solana addresses under [Accounts & Balances](/usage-guides/accounts-and-balances). rotki will pull and decode on-chain transactions automatically. -- **CSV imports**: For exchanges that don't support API integration (or that no longer exist, like FTX), you can [import CSV files](/usage-guides/import-csv) with your trade history. +- **Exchanges**: Add API keys for your centralized exchanges under [API Keys](/usage-guides/integrations/exchange-keys). rotki will automatically pull your trade history, deposits, and withdrawals. +- **Blockchain accounts**: Add your EVM, Bitcoin, or Solana addresses under [Accounts & Balances](/usage-guides/portfolio/accounts). rotki will pull and decode on-chain transactions automatically. +- **CSV imports**: For exchanges that don't support API integration (or that no longer exist, like FTX), you can [import CSV files](/usage-guides/history/import-data) with your trade history. ### 2. Configure your accounting settings -Go to **Settings β†’ Accounting Settings** ([detailed reference](/usage-guides/customization#accounting-settings)) and configure: +Go to **Settings β†’ Accounting Settings** ([detailed reference](/usage-guides/settings/accounting#accounting-settings)) and configure: -- **Cost basis method**: FIFO, LIFO, HIFO, or ACB β€” check which method your tax jurisdiction requires. See [accounting rule options explained](/usage-guides/accounting-rules) for details. +- **Cost basis method**: FIFO, LIFO, HIFO, or ACB β€” check which method your tax jurisdiction requires. See [accounting rule options explained](/usage-guides/tax-accounting/accounting-rules) for details. - **Crypto to crypto trades**: Whether swapping one crypto for another is a taxable event (it is in most jurisdictions). - **Tax-free period**: If your country allows tax-free treatment after a holding period (e.g., Germany's 1-year rule), set it here. - **Profit currency**: The fiat currency your taxes are denominated in (e.g., EUR, USD, GBP). Change this via the currency icon in the top-right menu. @@ -37,14 +41,14 @@ Go to **Settings β†’ Accounting Settings** ([detailed reference](/usage-guides/c Go to **History Events** in the left sidebar. This is where all your transactions live. rotki automatically decodes most on-chain transactions, but you should review them for accuracy: -- **Check for missing events**: If you moved assets through unsupported protocols or peer-to-peer, you may need to [add events manually](/usage-guides/historical-events#add--edit-events). -- **Fix incorrectly categorized events**: rotki may not always correctly identify what a transaction represents. See the [event types and subtypes reference](/usage-guides/event-types) to understand each category, and the [common customization guide](/usage-guides/historical-events#common-customization) for how to re-categorize events. -- **Check for missing accounting rules**: Events with a warning icon won't be processed correctly. Either edit the event or add a [missing accounting rule](/usage-guides/historical-events#missing-accounting-rule). -- **Match asset movements**: If you have exchange deposits/withdrawals that aren't linked to on-chain transactions, use the [asset movement matching](/usage-guides/historical-events#unmatched-asset-movements) feature. +- **Check for missing events**: If you moved assets through unsupported protocols or peer-to-peer, you may need to [add events manually](/usage-guides/history/events#add--edit-events). +- **Fix incorrectly categorized events**: rotki may not always correctly identify what a transaction represents. See the [event types and subtypes reference](/usage-guides/tax-accounting/event-types) to understand each category, and the [common customization guide](/usage-guides/history/events#common-customization) for how to re-categorize events. +- **Check for missing accounting rules**: Events with a warning icon won't be processed correctly. Either edit the event or add a [missing accounting rule](/usage-guides/history/events#missing-accounting-rule). +- **Match asset movements**: If you have exchange deposits/withdrawals that aren't linked to on-chain transactions, use the [asset movement matching](/usage-guides/history/events#unmatched-asset-movements) feature. ### 4. Add missing prices -Some assets or time periods may not have price data available from rotki's oracles. Go to **Add Missing Prices** ([guide](/usage-guides/custom-price)) to manually specify prices for assets that rotki can't find automatically. +Some assets or time periods may not have price data available from rotki's oracles. Go to **Add Missing Prices** ([guide](/usage-guides/data-management/prices)) to manually specify prices for assets that rotki can't find automatically. ### 5. Generate your PnL report @@ -62,17 +66,17 @@ The report shows: - Click **Export CSV** to download the report for use in Google Sheets or LibreOffice - Share the export with your tax advisor for review -- See the [PnL report guide](/usage-guides/pnl#results-of-the-pnl-report) for column definitions +- See the [PnL report guide](/usage-guides/history/pnl#results-of-the-pnl-report) for column definitions ## Common issues and how to fix them -| Problem | Likely cause | Solution | -| --------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- | -| "No documented acquisition found" | rotki doesn't know when/where you originally bought an asset | [Add a manual trade](/usage-guides/historical-events#add--edit-events) or acquisition event | -| Event counted as taxable when it shouldn't be | Wrong event type/subtype | [Edit the event](/usage-guides/historical-events#common-customization) to the correct type | -| Missing price for an asset | Oracle doesn't have data for that asset/timestamp | [Add missing price manually](/usage-guides/custom-price) | -| PnL numbers seem wrong | Accounting settings may not match your jurisdiction | Review [accounting settings](/usage-guides/customization#accounting-settings) and [accounting rule options](/usage-guides/accounting-rules) | -| Report generation gets stuck | Often caused by exchange API rate limits | Check [troubleshooting](/usage-guides/pnl#pnl-report-generation-gets-stuck) | +| Problem | Likely cause | Solution | +| --------------------------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| "No documented acquisition found" | rotki doesn't know when/where you originally bought an asset | [Add a manual trade](/usage-guides/history/events#add--edit-events) or acquisition event | +| Event counted as taxable when it shouldn't be | Wrong event type/subtype | [Edit the event](/usage-guides/history/events#common-customization) to the correct type | +| Missing price for an asset | Oracle doesn't have data for that asset/timestamp | [Add missing price manually](/usage-guides/data-management/prices) | +| PnL numbers seem wrong | Accounting settings may not match your jurisdiction | Review [accounting settings](/usage-guides/settings/accounting#accounting-settings) and [accounting rule options](/usage-guides/tax-accounting/accounting-rules) | +| Report generation gets stuck | Often caused by exchange API rate limits | Check [troubleshooting](/usage-guides/history/pnl#pnl-report-generation-gets-stuck) | ## What rotki currently does NOT support @@ -83,8 +87,8 @@ Understanding what's not available saves you time: ## Further reading -- [Event types and subtypes reference](/usage-guides/event-types) β€” what each event category means -- [Accounting rule options explained](/usage-guides/accounting-rules) β€” detailed explanation of every accounting setting -- [Profit/Loss Report guide](/usage-guides/pnl) β€” full report documentation -- [History Events guide](/usage-guides/historical-events) β€” managing and customizing your transaction history -- [Import CSV](/usage-guides/import-csv) β€” importing data from unsupported exchanges +- [Event types and subtypes reference](/usage-guides/tax-accounting/event-types) β€” what each event category means +- [Accounting rule options explained](/usage-guides/tax-accounting/accounting-rules) β€” detailed explanation of every accounting setting +- [Profit/Loss Report guide](/usage-guides/history/pnl) β€” full report documentation +- [History Events guide](/usage-guides/history/events) β€” managing and customizing your transaction history +- [Import CSV](/usage-guides/history/import-data) β€” importing data from unsupported exchanges diff --git a/usage-guides/user-notes.md b/usage-guides/user-notes.md deleted file mode 100644 index 90bda92..0000000 --- a/usage-guides/user-notes.md +++ /dev/null @@ -1,13 +0,0 @@ -# Taking Notes In-App - -You can now take notes in various sections of the application. Note taking is categorized into two types: - -1. **General Notes**: These are notes available & visible across the application. - - ![General notes](/images/rotki_general_notes.png) - -2. **Location-specific Notes**: These are notes restricted to the location in which they were created in the application. - - ![Location specific notes](/images/rotki_location_specific_notes.png) - -You can also pin notes; the pinned notes will appear at the top. diff --git a/usage-guides/help-support.md b/usage-guides/utilities/help.md similarity index 92% rename from usage-guides/help-support.md rename to usage-guides/utilities/help.md index b13454f..0162b90 100644 --- a/usage-guides/help-support.md +++ b/usage-guides/utilities/help.md @@ -1,3 +1,7 @@ +--- +description: Accessing help resources, reporting bugs, and submitting feature requests through the in-app support menu. +--- + # Help & Support To access the Help & Support menu, click the **?** icon in the toolbar. diff --git a/usage-guides/utilities/index.md b/usage-guides/utilities/index.md new file mode 100644 index 0000000..5db7e01 --- /dev/null +++ b/usage-guides/utilities/index.md @@ -0,0 +1,42 @@ +--- +description: Quick-access utilities in rotki including global search, in-app notes, and background task management. +--- + +# Utilities + +## Global Search + +You can use global search provided to speed up your actions by clicking the icon on the top bar, or using the shortcut `Control-/` (`Command-/` if you are using Mac). + +Some actions provided by this global search: + +- Navigate to any page in rotki +- Some basic actions such as adding a new trade. +- Go to a certain owned asset overview page. +- Go to a certain location overview page. + +![Global Search](/images/global_searchbox.gif) + +## Taking Notes In-App + +You can now take notes in various sections of the application. Note taking is categorized into two types: + +1. **General Notes**: These are notes available & visible across the application. + + ![General notes](/images/rotki_general_notes.png) + +2. **Location-specific Notes**: These are notes restricted to the location in which they were created in the application. + + ![Location specific notes](/images/rotki_location_specific_notes.png) + +You can also pin notes; the pinned notes will appear at the top. + +## Background Tasks + +A list of processing tasks is available on the notifications tray. + +![running background tasks](/images/pending_tasks.png) + +It is possible to cancel a long running task, but use this feature sparingly. + +![cancel background task](/images/pending_tasks_cancel.png) From 1abd576ba911bcb18f268de3a03dd62519092d82 Mon Sep 17 00:00:00 2001 From: Konstantinos Paparas Date: Thu, 9 Apr 2026 15:12:05 +0200 Subject: [PATCH 2/7] chore: polish theme CSS and improve landing page Refresh the default VitePress theme with modern styling: refined dark mode colors, Inter/JetBrains Mono fonts, polished code blocks, rounded corners on containers and tables, subtle hover effects on images, and cleaner link styling. Add NavCards component for the landing page navigation grid. Remove backdrop blur on nav to avoid rendering issues. --- .vitepress/theme/style.css | 298 ++++++++++++++++++++++++++++--------- 1 file changed, 225 insertions(+), 73 deletions(-) diff --git a/.vitepress/theme/style.css b/.vitepress/theme/style.css index 8ca4c45..4f84b23 100644 --- a/.vitepress/theme/style.css +++ b/.vitepress/theme/style.css @@ -1,54 +1,38 @@ /** - * Customize default theme styling by overriding CSS variables: + * rotki docs β€” custom theme + * + * Extends the default VitePress theme with a modern, clean aesthetic + * inspired by Carbon and VoidZero design patterns. + * + * Overrides CSS variables defined in: * https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css */ -/** - * Colors - * - * Each colors have exact same color scale system with 3 levels of solid - * colors with different brightness, and 1 soft color. - * - * - `XXX-1`: The most solid color used mainly for colored text. It must - * satisfy the contrast ratio against when used on top of `XXX-soft`. - * - * - `XXX-2`: The color used mainly for hover state of the button. - * - * - `XXX-3`: The color for solid background, such as bg color of the button. - * It must satisfy the contrast ratio with pure white (#ffffff) text on - * top of it. - * - * - `XXX-soft`: The color used for subtle background such as custom container - * or badges. It must satisfy the contrast ratio when putting `XXX-1` colors - * on top of it. - * - * The soft color must be semi transparent alpha channel. This is crucial - * because it allows adding multiple "soft" colors on top of each other - * to create a accent, such as when having inline code block inside - * custom containers. - * - * - `default`: The color used purely for subtle indication without any - * special meanings attched to it such as bg color for menu hover state. - * - * - `brand`: Used for primary brand colors, such as link text, button with - * brand theme, etc. - * - * - `tip`: Used to indicate useful information. The default theme uses the - * brand color for this by default. - * - * - `warning`: Used to indicate warning to the users. Used in custom - * container, badges, etc. +/* -------------------------------------------------------------------------- + * Typography + * -------------------------------------------------------------------------- */ + +:root { + --vp-font-family-base: + 'Inter', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', + Helvetica, Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', + 'Noto Color Emoji'; + --vp-font-family-mono: + 'JetBrains Mono', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Monaco, Consolas, 'Liberation Mono', + 'Courier New', monospace; +} + +/* -------------------------------------------------------------------------- + * Colors β€” Brand * - * - `danger`: Used to show error, or dangerous message to the users. Used - * in custom container, badges, etc. + * rotki indigo palette with refined tones for better contrast * -------------------------------------------------------------------------- */ :root { --vp-c-indigo-1: #4e5ba6; - --vp-c-default-1: var(--vp-c-gray-1); - --vp-c-default-2: var(--vp-c-gray-2); - --vp-c-default-3: var(--vp-c-gray-3); - --vp-c-default-soft: var(--vp-c-gray-soft); + --vp-c-indigo-2: #3e4c96; + --vp-c-indigo-3: #384590; + --vp-c-indigo-soft: rgba(78, 91, 166, 0.12); --vp-c-brand-1: var(--vp-c-indigo-1); --vp-c-brand-2: var(--vp-c-indigo-2); @@ -59,6 +43,24 @@ --vp-c-tip-2: var(--vp-c-brand-2); --vp-c-tip-3: var(--vp-c-brand-3); --vp-c-tip-soft: var(--vp-c-brand-soft); +} + +.dark { + --vp-c-indigo-1: #7c8adb; + --vp-c-indigo-2: #6b79d0; + --vp-c-indigo-3: #5b68c2; + --vp-c-indigo-soft: rgba(124, 138, 219, 0.14); +} + +/* -------------------------------------------------------------------------- + * Colors β€” Semantic + * -------------------------------------------------------------------------- */ + +:root { + --vp-c-default-1: var(--vp-c-gray-1); + --vp-c-default-2: var(--vp-c-gray-2); + --vp-c-default-3: var(--vp-c-gray-3); + --vp-c-default-soft: var(--vp-c-gray-soft); --vp-c-warning-1: var(--vp-c-yellow-1); --vp-c-warning-2: var(--vp-c-yellow-2); @@ -69,15 +71,29 @@ --vp-c-danger-2: var(--vp-c-red-2); --vp-c-danger-3: var(--vp-c-red-3); --vp-c-danger-soft: var(--vp-c-red-soft); +} + +/* -------------------------------------------------------------------------- + * Colors β€” Background + * + * Slightly cooler backgrounds for a modern feel + * -------------------------------------------------------------------------- */ - --vp-code-bg: #65758512; +:root { + --vp-c-bg: #ffffff; + --vp-c-bg-alt: #f8f9fb; + --vp-c-bg-elv: #ffffff; + --vp-c-bg-soft: #f3f4f6; } .dark { - --vp-c-indigo-1: #5b68b2; + --vp-c-bg: #161618; + --vp-c-bg-alt: #131315; + --vp-c-bg-elv: #1e1e20; + --vp-c-bg-soft: #222224; } -/** +/* -------------------------------------------------------------------------- * Component: Button * -------------------------------------------------------------------------- */ @@ -93,15 +109,23 @@ --vp-button-brand-active-bg: var(--vp-c-brand-1); } -/** +.VPButton.medium { + border-radius: 8px !important; + font-weight: 500; +} + +/* -------------------------------------------------------------------------- * Component: Home * -------------------------------------------------------------------------- */ :root { --vp-home-hero-name-color: transparent; - --vp-home-hero-name-background: -webkit-linear-gradient(120deg, var(--vp-c-brand-1) 30%, var(--vp-c-brand-1) 30%); - - --vp-home-hero-image-background-image: linear-gradient(-45deg, var(--vp-c-brand-1) 50%, var(--vp-c-brand-1) 50%); + --vp-home-hero-name-background: linear-gradient(135deg, var(--vp-c-brand-3) 0%, var(--vp-c-brand-1) 100%); + --vp-home-hero-image-background-image: linear-gradient( + -45deg, + var(--vp-c-brand-soft) 50%, + var(--vp-c-indigo-soft) 50% + ); --vp-home-hero-image-filter: blur(44px); } @@ -113,12 +137,12 @@ @media (min-width: 960px) { :root { - --vp-home-hero-image-filter: blur(68px); + --vp-home-hero-image-filter: blur(72px); } } -/** - * Component: Custom Block +/* -------------------------------------------------------------------------- + * Component: Custom Blocks * -------------------------------------------------------------------------- */ :root { @@ -128,40 +152,168 @@ --vp-custom-block-tip-code-bg: var(--vp-c-brand-soft); } -/** - * Component: Algolia +.custom-block { + border-radius: 8px; +} + +/* -------------------------------------------------------------------------- + * Component: Nav + * + * Make the navbar bottom divider span the full width so the header reads + * as one continuous bar, rather than being split visually at the sidebar edge. * -------------------------------------------------------------------------- */ -.DocSearch { - --docsearch-primary-color: var(--vp-c-brand-1) !important; +@media (min-width: 960px) { + .VPNavBar.has-sidebar .divider { + padding-left: 0 !important; + } + + .VPNavBarTitle.has-sidebar .title { + border-bottom-color: transparent !important; + } } -/** - * Images - */ -.content img { +/* -------------------------------------------------------------------------- + * Component: Sidebar + * + * Match the sidebar background to the main content background, and contain + * the sidebar scroll below the navbar so the scrollbar doesn't extend up + * through the title area. + * -------------------------------------------------------------------------- */ + +:root { + --vp-sidebar-bg-color: var(--vp-c-bg); +} + +@media (min-width: 960px) { + .VPSidebar { + top: var(--vp-nav-height) !important; + padding-top: 0 !important; + } + + .VPSidebar .curtain { + display: none; + } +} + +.VPSidebar .group .VPSidebarItem .text { + transition: color 0.15s ease; +} + +/* -------------------------------------------------------------------------- + * Component: Code Blocks + * -------------------------------------------------------------------------- */ + +:root { + --vp-code-bg: rgba(101, 117, 133, 0.08); + --vp-code-block-bg: var(--vp-c-bg-alt); + --vp-code-tab-divider: var(--vp-c-divider); + --vp-code-copy-code-border-color: transparent; + --vp-code-copy-code-bg: var(--vp-c-bg-soft); + --vp-code-copy-code-hover-border-color: var(--vp-c-divider); + --vp-code-copy-code-hover-bg: var(--vp-c-bg-soft); + --vp-code-copy-code-active-text: var(--vp-c-text-2); +} + +.dark { + --vp-code-bg: rgba(101, 117, 133, 0.12); + --vp-code-block-bg: #1a1a1c; +} + +.vp-doc div[class*='language-'] { border-radius: 8px; - border: 1px solid #ddd; } -.dark .content img { - border-color: #333; +.vp-doc [class*='language-'] code { + font-size: 13px; + line-height: 1.7; } -/* - * Code style for logs - */ .vp-doc .language-log code { white-space: normal; } -/* - * Button on the homepage - */ -.VPButton.medium { - border-radius: 0.5rem !important; +/* Inline code */ +.vp-doc :not(pre) > code { + border-radius: 4px; + padding: 2px 6px; + font-size: 0.9em; +} + +/* -------------------------------------------------------------------------- + * Component: Content β€” Images + * -------------------------------------------------------------------------- */ + +.content img { + border-radius: 8px; + border: 1px solid var(--vp-c-divider); + transition: box-shadow 0.2s ease; +} + +.content img:hover { + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08); } -.main .name .clip { - font-size: 1.25em; +.dark .content img { + border-color: var(--vp-c-divider); +} + +.dark .content img:hover { + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3); +} + +/* -------------------------------------------------------------------------- + * Component: Content β€” Tables + * -------------------------------------------------------------------------- */ + +.vp-doc table { + border-radius: 8px; + overflow: hidden; +} + +.vp-doc tr { + transition: background-color 0.15s ease; +} + +/* -------------------------------------------------------------------------- + * Component: Content β€” Links + * -------------------------------------------------------------------------- */ + +.vp-doc a { + text-decoration: none; + transition: color 0.15s ease; +} + +.vp-doc a:hover { + text-decoration: underline; + text-underline-offset: 3px; +} + +.vp-doc .nav-cards a, +.vp-doc .nav-cards a:hover { + text-decoration: none; +} + +/* -------------------------------------------------------------------------- + * Component: Search + * -------------------------------------------------------------------------- */ + +.DocSearch { + --docsearch-primary-color: var(--vp-c-brand-1) !important; +} + +/* -------------------------------------------------------------------------- + * Layout β€” Content width + * -------------------------------------------------------------------------- */ + +.VPDoc.has-aside .content-container { + max-width: 780px; +} + +/* -------------------------------------------------------------------------- + * Transitions β€” Smooth page transitions + * -------------------------------------------------------------------------- */ + +.VPContent { + transition: opacity 0.15s ease; } From fcc0ce57c7d15888d358d8bddb93aa458862a57c Mon Sep 17 00:00:00 2001 From: Konstantinos Paparas Date: Thu, 9 Apr 2026 20:51:10 +0200 Subject: [PATCH 3/7] docs: add dashboard page and fix documentation gaps Add comprehensive dashboard documentation with screenshots covering total balance, net value graph, balance summary, assets table, liquidity pools, liabilities, and NFT balances. Fix documentation gaps found by cross-checking with frontend source: - Add Lido CSM staking section - Add Crypto.com, Coinbase Prime exchanges; remove dead Coinbase Pro - Add 6 missing external services (Blockscout, Helius, etc.) - Add Solana Event and Solana Swap Event types - Add missing settings across all settings pages - Add missing mappings section to asset management - Update airdrops to reference rotki/data repo dynamically - Add OKX region selector documentation --- .vitepress/config.mts | 1 + public/images/rotki_dashboard.webp | Bin 0 -> 67962 bytes public/images/rotki_dashboard_assets.webp | Bin 0 -> 71438 bytes usage-guides/data-management/assets.md | 14 +- usage-guides/history/events.md | 29 +++- usage-guides/integrations/exchange-keys.md | 23 ++- .../integrations/external-services.md | 24 +++ usage-guides/portfolio/balances.md | 33 +--- usage-guides/portfolio/dashboard.md | 146 ++++++++++++++++++ usage-guides/settings/account.md | 4 + usage-guides/settings/accounting.md | 4 + usage-guides/settings/blockchain.md | 14 +- usage-guides/settings/general.md | 38 ++++- usage-guides/settings/interface.md | 16 ++ usage-guides/staking.md | 21 ++- 15 files changed, 332 insertions(+), 35 deletions(-) create mode 100644 public/images/rotki_dashboard.webp create mode 100644 public/images/rotki_dashboard_assets.webp create mode 100644 usage-guides/portfolio/dashboard.md diff --git a/.vitepress/config.mts b/.vitepress/config.mts index 7cd5a6a..7571a06 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -133,6 +133,7 @@ export default defineConfig({ text: 'Portfolio', collapsed: false, items: [ + { text: 'Dashboard', link: '/usage-guides/portfolio/dashboard' }, { text: 'Accounts', link: '/usage-guides/portfolio/accounts' }, { text: 'Balances', link: '/usage-guides/portfolio/balances' }, ], diff --git a/public/images/rotki_dashboard.webp b/public/images/rotki_dashboard.webp new file mode 100644 index 0000000000000000000000000000000000000000..0eb960858dd915599f39ea74e46d6e72cded35ea GIT binary patch literal 67962 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 literal 0 HcmV?d00001 diff --git a/public/images/rotki_dashboard_assets.webp b/public/images/rotki_dashboard_assets.webp new file mode 100644 index 0000000000000000000000000000000000000000..9c0737eb1d80d385f0dc35a9d6dc8b5fd097ba37 GIT binary patch literal 71438 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�QK%@iY-|-Xn62k zCA@t=Vy^eJ_Nlq2+Rdy;7C{WMs#r>{CNFGG?Y5pfRg5YkQMbBIdx-KNexDFoN#|?<;YFH3p4c+B zKDJa10Wv^-uMiSXE%U+pl5FWu4t~R!vBcqsUdeIH;ZrxZv$jxtrzzP@K6#3B^c_o+ zN>=|f0%Qgo3;CaK<4$t^k21{OY%-+yJWy$;(yjt55&c=3bybL)X@UInFwEimhYt^k zkh(#I?VBZk6Ez38*npYDk`na4r%AqUTb9bICQjsd-SzE9yav7~aLcH$D0{hK zFx98!Gl%5bpAJ^m+}IBXyb*+$Z9t0bONPY6ASf3n5FXkD?ynL6g#9M2pk zV5`xG`D}NlSUXBeSTg02!gPzfroZOGODzLQB1W+dK&VvFzC_faElIP(29R{$~Sp zR8NysCf?iZ2Lc=JrCC0-_Jy=4Rr5g81v_j?6;>~Z6C)Z)}J&0 z6oC`|u;RUUJa&N2N2*hLa~Qj_O%V&^RR5o^<$~&hOxmA+sFG*&; z206v|rjCy&2`+?5=;hhB@YBedc~SdUr-h%C=uCQ*SjFPHJe6bzuXYDQ5yG;z%XZ}y z5`@$+BaWbn=yBOs?5SOT-c4c*=BM_0hY;vJE02s@)tY<8?PB$gM%L+@&nG_kgymU> z*a151Ep8ag+!XS0V%kciGn^)iKX7HUKSbHApiXC){Gb*sq~sCBk!fde(v%HcI*mZ^ z0-Q5=O1b5*n^9U-E#a;K0U;FmSC)1KCP#g%ujr$E2vd32uQzq{65VP0Y!sfsrk zpFeHwW{v{1sqT8U5svs4MPM8ngNYim1+skQsLQv=mrjP!2dV2o(Wn_=;ns~<0<(a0 z$}7bgg-k^bzsh4UFDs(p3a;WY@}s?>1(@FQkUY%@)aJls;p?sOAYFJ{L!M`5Xuc;H zmE=x-EWykJ+r|`e!12!X+~g~D7{7unBlpA)LZiZ#8xV2toqQBe(E)W-qatvTCLblY`$6-Fll!wg&G-BD4t`K>-;uC3CZL z+l`x^+cbr=WGviU z6dgV%8(RUg&=Wt1Kj)dKVDN@HOqnXNNwDikUDV7m-zm_r6q9Pl{Oz;PH5t^MB+>Bv zd=%rT>1DPH^kIILkQdgNNeA!jS1HMt7Qfe8-%Y1hRVz8t?|8e|P1GRioWihT$q<)&2L0!OCj}BMrY^SE0@`4=h>>7g@+=&NM_5 zqVwh)B%!B0h1y$?t%z(%z9HFCiiMciKAnEB?S+7ARl{^qR*Ag0

Uc@4AKC@qeUq;b%Pv)PiFQ50KFYUud6^_;ha)_Z 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 jv@sDY%T(8e4N Report Issue), on our github repository, or in our discord server. The customizations that you make also affect how events are processed in accounting. diff --git a/usage-guides/integrations/exchange-keys.md b/usage-guides/integrations/exchange-keys.md index 678c760..59ac2a5 100644 --- a/usage-guides/integrations/exchange-keys.md +++ b/usage-guides/integrations/exchange-keys.md @@ -28,7 +28,7 @@ Currently supported exchanges are: - Binance - Bitmex - Coinbase -- Coinbase Pro +- Coinbase Prime - Gemini - Bitstamp - Binance US @@ -42,6 +42,7 @@ Currently supported exchanges are: - Woo - Bybit - HTX +- Crypto.com (experimental) ![Add API keys for a new exchange](/images/rotki_add_exchange_1.png) @@ -72,7 +73,7 @@ Currently supported exchanges are: ### API key permissions -rotki only needs read-only permissions for your accounts. As a general rule, exchanges (e.g., Binance, Coinbase Pro) group all the read-only permissions as "read" or "view". +rotki only needs read-only permissions for your accounts. As a general rule, exchanges (e.g., Binance) group all the read-only permissions as "read" or "view". ![Simple API key permissions](/images/add_exchange_api_keys_binance.png) @@ -107,3 +108,21 @@ Choose the markets in the `Filter market pair(s)` search. ![Binance markets selection](/images/binance_markets_selection.png) Once finished, click on save. + +#### Coinbase Prime + +Coinbase Prime requires an API Key, API Secret, and a Passphrase. Make sure you provide all three when adding the exchange. + +#### OKX + +OKX requires an API Key, API Secret, and a Passphrase. When adding OKX, you also need to select your **region**: + +- **Global** β€” the default OKX platform. +- **EEA** β€” for European Economic Area users. +- **US** β€” for United States users. + +Make sure to select the region that matches the OKX platform you registered on, as the API endpoints differ between regions. + +#### Crypto.com + +Crypto.com is currently listed as an **experimental** exchange. It requires an API Key and API Secret. Since it is experimental, some functionality may be incomplete or subject to change. diff --git a/usage-guides/integrations/external-services.md b/usage-guides/integrations/external-services.md index a15695a..b807e9c 100644 --- a/usage-guides/integrations/external-services.md +++ b/usage-guides/integrations/external-services.md @@ -33,6 +33,30 @@ Without it, the queries will be really slow. You just need to: You only need one Etherscan API key for all EVM chains since the key is now unified. +## Blockscout + +Blockscout is an open-source blockchain explorer that rotki can use as an alternative data source for on-chain transactions and token transfers. You can add per-chain API keys, allowing rotki to query Blockscout instances for specific EVM chains. This can be useful as a fallback or supplement to Etherscan. + +## Helius + +Helius is a Solana indexer and RPC provider. Adding a Helius API key allows rotki to query Solana transaction data more reliably and with higher rate limits. You can get an API key from [helius.dev](https://www.helius.dev/). + +## CryptoCompare + +CryptoCompare provides historical cryptocurrency price data. While rotki can use CryptoCompare without an API key, adding one increases the rate limits for price queries. You can get a free API key from [cryptocompare.com](https://www.cryptocompare.com/cryptopian/api-keys). + +## Beaconchain + +Beaconchain provides Ethereum consensus layer (beacon chain) data. Adding an API key allows rotki to query validator information with higher rate limits. You can get an API key from [beaconcha.in](https://beaconcha.in/user/settings#api). + +## OpenSea + +OpenSea is an NFT marketplace and data provider. Adding an OpenSea API key allows rotki to fetch NFT data such as collection information and valuations. You can request an API key from [opensea.io](https://docs.opensea.io/reference/api-keys). + +## Alchemy + +Alchemy is a multi-chain data provider and price oracle. rotki can use Alchemy for blockchain data queries and as an additional price source. Adding an API key improves rate limits and reliability. You can get a free API key from [alchemy.com](https://www.alchemy.com/). + ## Loopring balances To have your Loopring balances detected, you will need an API Key from Loopring. To get one, visit [Loopring Security](https://loopring.io/#/layer2/security) and unlock your account. In the list of options, click on **Export Account**. diff --git a/usage-guides/portfolio/balances.md b/usage-guides/portfolio/balances.md index ab54a8c..93342f3 100644 --- a/usage-guides/portfolio/balances.md +++ b/usage-guides/portfolio/balances.md @@ -95,31 +95,14 @@ rotki can detect some airdrops for you ![rotki airdrops detection](/images/rotki_airdrops.png) -The list of currently supported airdrops is: - -- Uniswap -- 1INCH -- Tornado -- Cornichon -- Grain -- Furocombo -- Lido -- Curve -- Convex -- Shapeshift -- ENS -- ParaSwap -- Saddle finance -- Cow -- Diva -- Shutter -- Starknet -- Optimism 4 -- Degen 2 -- Omni -- Eigen token - -For some airdrops, you may see the status `Unknown`. This means rotki can't determine the status of the airdrop, whether it has been claimed or not. You need to check it yourself. +The list of supported airdrops is pulled from the [rotki/data](https://github.com/rotki/data/tree/main/airdrops) repository and is updated automatically. New airdrops may be added over time without requiring an app update. + +Each airdrop shows one of the following statuses: + +- **Claimed** β€” The airdrop has been claimed. +- **Unclaimed** β€” The airdrop is available but has not been claimed yet. +- **Missed** β€” The claim window has expired. +- **Unknown** β€” rotki can't determine the status. You need to check it yourself. ## Balances Snapshots diff --git a/usage-guides/portfolio/dashboard.md b/usage-guides/portfolio/dashboard.md new file mode 100644 index 0000000..a3b85c1 --- /dev/null +++ b/usage-guides/portfolio/dashboard.md @@ -0,0 +1,146 @@ +--- +description: Overview of the rotki dashboard showing total balance, net value graph, balance breakdowns, and asset holdings. +--- + +# Dashboard + +The dashboard is the first page you see after logging into rotki. It provides a high-level overview of your entire portfolio across all tracked accounts, exchanges, and manual balances. + +![rotki Dashboard](/images/rotki_dashboard.webp) + +## Progress Indicator + +At the top of the dashboard, a progress indicator shows the status of ongoing operations such as balance queries, history event fetching, and historical balance processing. This bar appears automatically when rotki is working and can be dismissed. + +## Total Balance + +Your **Total Balance** is displayed in your configured [profit currency](/usage-guides/settings/general#profit-currency). This is the combined value of all your assets across every tracked source β€” blockchain accounts, exchange balances, and manual entries. + +Below the total, a change indicator shows: + +- A **green arrow up** with the percentage and absolute gain if your portfolio increased +- A **red arrow down** with the percentage and absolute loss if it decreased +- A **gray horizontal arrow** if there is no change + +The change is calculated relative to the earliest snapshot in the selected timeframe. + +## Net Value Graph + +The graph visualizes your portfolio's total value over time, based on saved [balance snapshots](/usage-guides/portfolio/balances#balances-snapshots). + +### Interacting with the Graph + +- **Hover** over the graph to see the exact balance and date at any point +- **Click** on a snapshot point to open the snapshot management dialog (edit, delete, or download) +- **Double-click** to reset the zoom level +- **Scroll wheel** to zoom in or out on the data +- **Drag** to pan across the timeline + +### Timeframe Selection + +Use the buttons above the graph to switch between timeframes: + +- **1W** β€” Last week +- **2W** β€” Last 2 weeks +- **1M** β€” Last month [Premium] +- **3M** β€” Last 3 months [Premium] +- **1Y** β€” Last year [Premium] +- **All** β€” Full history since your first snapshot [Premium] + +> [!NOTE] +> Free users can access the 1W and 2W timeframes. The longer timeframes (1M, 3M, 1Y, All) require a [premium subscription](/premium/). +> Timeframe buttons are also disabled if there are not enough snapshots to cover that period. + +### Snapshot Controls + +The snapshot dropdown button (next to the graph) provides: + +- **Force Save** β€” Manually trigger a balance snapshot. Shows when the last snapshot was taken. +- **Ignore Errors** β€” A checkbox to save snapshots even if some external service queries failed. This setting persists across sessions. +- **Import Snapshot** β€” Upload previously exported snapshot CSV files (balance snapshot file + location data snapshot file). After import, rotki will log you out to apply the changes. + +For more details on managing snapshots, see [Balance Snapshots](/usage-guides/portfolio/balances#balances-snapshots). + +## Balance Summary + +Below the graph, three columns break down your balances by source: + +### Exchange Balances + +Shows the total value held in each connected exchange. Click on an exchange name to navigate to its detailed balance view. If no exchanges are connected, an add button is shown to link one. To add an exchange connection, see [Exchange API Keys](/usage-guides/integrations/exchange-keys). + +### Blockchain Balances + +Lists each blockchain network where you have tracked accounts, with the total value per chain. Click on a chain name to view the accounts on that specific network. + +The refresh button on this card has a dropdown with two options: + +- **Only Refresh Balances** β€” Re-queries balances for all tracked addresses (default) +- **Redetect Tokens** β€” Also scans for newly acquired tokens before refreshing balances + +To add blockchain accounts, see [Accounts](/usage-guides/portfolio/accounts). + +### Manual Balances + +Displays manually tracked balances grouped by location (e.g., External, Blockchain, specific exchanges). These are useful for tracking assets that rotki can't query automatically, such as real estate, stocks, or assets on unsupported chains. See [Manual Balances](/usage-guides/portfolio/balances#manual-balances) for how to add them. + +## Assets Table + +![Dashboard Assets Table](/images/rotki_dashboard_assets.webp) + +The assets table shows all your holdings aggregated across all sources. Each row displays: + +| Column | Description | +| ------------------ | -------------------------------------------------------------------- | +| **Asset** | The asset name, symbol, and the chain it's on (for tokens) | +| **Location** | Icons showing where the asset is held (blockchain, exchange, manual) | +| **Price** | Current price in your profit currency | +| **Amount** | Total quantity you hold | +| **Value** | Total value in your profit currency | +| **% of Net Value** | What percentage of your total portfolio this asset represents | + +### 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. +- **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). +- **Total Row** β€” A summary row at the bottom shows the aggregate value of all displayed assets. + +> [!TIP] +> If an asset shows a warning icon, it means the asset is not recognized by rotki's asset database. You can click the warning to navigate to the manual balance page for that asset. + +## Liquidity Pools + +If you have assets in DeFi liquidity pools, a **Liquidity Pools** table appears below the assets table. It shows: + +- Pool name with icons for the constituent assets +- Total value of your position +- Percentage of net value + +Click the expand arrow to see the detailed asset composition of each pool. + +> [!NOTE] +> Some liquidity pool details are only available with a [premium subscription](/premium/). These are indicated by a lock icon. + +## Liabilities + +If you have any tracked liabilities (debts), a **Liabilities** table appears with the same structure as the assets table, showing your outstanding obligations. + +## NFT Balances + +If the NFT module is enabled, the **NFT Balances** table shows NFTs owned by your tracked accounts: + +- NFT name and collection +- Price in the NFT's native asset +- Estimated value in your profit currency +- Percentage of your net value + +Click the link icon to navigate to the full [NFT balances](/usage-guides/portfolio/balances#nfts) page for more details on managing NFT prices and display settings. + +## Refreshing Data + +Click **Refresh Prices** below the balance summary to update all asset prices from the configured [price oracles](/usage-guides/settings/blockchain#price-oracle-settings). + +To refresh balances from specific sources, use the refresh button on the individual balance summary columns (Exchange, Blockchain, or Manual). diff --git a/usage-guides/settings/account.md b/usage-guides/settings/account.md index 8a87fc5..139d2b7 100644 --- a/usage-guides/settings/account.md +++ b/usage-guides/settings/account.md @@ -12,6 +12,10 @@ Choose the "User & Security" section to change the user password. ![Changing the user's password](/images/sc_user_password_change.png) +### Password Confirmation + +When using auto-login, you can enable periodic password confirmation to ensure you still remember your password. Toggle the setting on or off and set the confirmation interval in days (between 1 and 14). Disabling this setting will show a warning, since forgetting your password while using auto-login means losing access to your account. + ## Database Settings ### Database Info & User Database Backups diff --git a/usage-guides/settings/accounting.md b/usage-guides/settings/accounting.md index 35781cb..0153854 100644 --- a/usage-guides/settings/accounting.md +++ b/usage-guides/settings/accounting.md @@ -96,6 +96,10 @@ Enable or disable calculating cost basis from all past events, even before the r Specify if ETH staking events are taxable only after the merge and withdrawals are enabled or at the point of receiving. +#### Use Asset Collections in Cost Basis + +When enabled, assets that belong to the same collection share cost basis. For example, if WETH and ETH are in the same asset collection, buying WETH and later selling ETH will use the WETH purchase as the cost basis. By default, this setting is `True`. + #### Cost Basis Method Select the cost basis calculation method: `FIFO`, `LIFO`, `HIFO`, or `ACB`. diff --git a/usage-guides/settings/blockchain.md b/usage-guides/settings/blockchain.md index d88d331..497b5b6 100644 --- a/usage-guides/settings/blockchain.md +++ b/usage-guides/settings/blockchain.md @@ -38,7 +38,7 @@ Regarding the need for API keys: Here, you can customize the order in which price oracles are queried, both for current and historical prices. This determines which price source to check first, second, and so on. -DeFi oracles like Uniswap V2 and Uniswap V3 use only on-chain information to get current prices. This makes querying a bit slower, but it relies solely on the Ethereum chain. Prices for some assets may differ from Coingecko or CryptoCompare, depending on the conditions of the pools at the time of the query. +Available price oracles include CoinGecko, CryptoCompare, Uniswap V2, Uniswap V3, DefiLlama, Alchemy, and custom (manual) prices. DeFi oracles like Uniswap V2 and Uniswap V3 use only on-chain information to get current prices. This makes querying a bit slower, but it relies solely on the Ethereum chain. Prices for some assets may differ from Coingecko or CryptoCompare, depending on the conditions of the pools at the time of the query. ### Oracle cache @@ -50,6 +50,18 @@ Request the creation of such a cache by going to the Oracle cache section, selec Manage existing historical price cache entries, inspect start and end dates, and delete caches if needed. +### Oracle Penalty Settings + +Configure penalty behavior for misbehaving price oracles at runtime. + +#### Oracle Penalty Duration + +The duration in seconds for which an oracle is penalized after exceeding the failure threshold. Default is 1800 seconds (30 minutes). + +#### Oracle Penalty Threshold Count + +The number of consecutive failures after which an oracle is penalized and temporarily skipped. Default is 5. + ## RPC Node Setting This setting lets you change the nodes used to connect to blockchains. We give you a list of public nodes, but sometimes they are busy or down. You will see a green or red icon showing if a node is working. diff --git a/usage-guides/settings/general.md b/usage-guides/settings/general.md index 30098b9..c1c38ea 100644 --- a/usage-guides/settings/general.md +++ b/usage-guides/settings/general.md @@ -28,6 +28,10 @@ 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. +#### Display Date in Localtime + +Specify whether dates in CSV exports should be displayed in local time rather than UTC. Enabled by default. + #### CSV Export Specify your preferred date format and delimiter for CSV exports. @@ -100,9 +104,41 @@ Decide whether to include NFTs in total net worth calculations and displayed gra For privacy, allow images from all or specific domains. More details [here](https://medium.com/@alxlpsc/critical-privacy-vulnerability-getting-exposed-by-metamask-693c63c2ce94). +### History Event Settings + +Configure settings related to history event processing and management. + +#### Auto Create Profit Events + +Automatically create virtual profit/loss events when processing history. This setting controls whether rotki generates profit and loss events during history processing. + +#### Internal Transaction Conflict Repull + +Configure how rotki handles internal transaction conflicts. You can set the number of transactions to repull per batch and the frequency (in minutes) at which the system automatically attempts to repull conflicting internal transactions. + +#### Skipped External Events + +View and manage events that were skipped during external event processing. This section shows a summary of skipped events grouped by location. You can export the skipped events to CSV or attempt to reprocess them. + ### External Service Settings -Define rules for retry and timeout for external service calls made by rotki. +Configure retry and timeout behavior for external service calls made by rotki. + +#### Query Retry Limit + +The number of times to retry a query to external services before giving up. Default is 5. + +#### Connect Timeout + +The number of seconds to wait before giving up on establishing a connection to an external service. Default is 30 seconds. + +#### Read Timeout + +The number of seconds to wait for the first byte after a connection to an external service has been established. Default is 30 seconds. + +#### Suppress Missing API Key Notifications + +Select services for which you do not want to receive notifications about missing API keys. Supported services include Etherscan, Beaconchain, The Graph, and Helius. ### Backend Settings diff --git a/usage-guides/settings/interface.md b/usage-guides/settings/interface.md index ce6ae1c..e787531 100644 --- a/usage-guides/settings/interface.md +++ b/usage-guides/settings/interface.md @@ -16,10 +16,18 @@ Set the language used in the app. This feature is experimental and may not work Reduce animation effects to improve performance. This affects animation quality but optimizes resource usage. +#### Persist Table Sorting + +Save your table sorting preferences so they persist when you navigate away and return to the page. + #### Data Scrambling Enable data scrambling to randomize amounts, dates, and other data for privacy in screenshots. This setting does not persist across sessions. +#### Persist Privacy and Scramble Mode Settings + +When enabled, privacy mode and scramble settings are preserved across sessions. When disabled, these settings reset to defaults upon login. + #### Automatic Balance Refresh Enable or disable automatic balance refresh and set the refresh interval. Disabled by default due to potential slow queries and rate limits. @@ -32,6 +40,10 @@ Set the frequency of backend data updates. Default is 5 seconds. Customize which explorer is used for transaction and address links. +#### Progress Query Indicator on Dashboard + +Configure the history query progress indicator shown on the dashboard. You can set the minimum out-of-sync period (in hours) before the indicator appears, the dismissal threshold (in hours) controlling how long the indicator stays hidden after being dismissed, and reset the dismissal status to show all indicators again. + ### Graph Settings #### Dashboard Graph Default Timeframe @@ -46,6 +58,10 @@ Configure whether the graph y-axis starts at 0 or the minimum amount for the per Enable or disable alias names for blockchain addresses. Aliases are obtained from `ENS`, `addressbook`, or `blockchain account label`. Change the order of resolution as needed. +### Newly Detected Tokens + +Configure how newly detected tokens are stored and pruned. You can set the maximum number of tokens to keep (oldest tokens exceeding this limit are pruned) and the retention period in days (tokens older than this are automatically removed). + ### Theme Customization [Premium] Premium users can customize colors for light or dark mode. diff --git a/usage-guides/staking.md b/usage-guides/staking.md index a1e1663..0f2e6e4 100644 --- a/usage-guides/staking.md +++ b/usage-guides/staking.md @@ -1,5 +1,5 @@ --- -description: How to track ETH2 validator staking, Liquity staking, and Kraken staking in rotki. +description: How to track ETH2 validator staking, Liquity staking, Kraken staking, and Lido CSM node operation in rotki. --- # Staking @@ -9,6 +9,7 @@ rotki currently supports staking tracking for: 1. Ethereum (ETH2) 2. Liquity 3. Kraken +4. Lido CSM ## ETH2 Staking @@ -90,3 +91,21 @@ For `LQTY` staking we display the claimed rewards. If you stake on Kraken you can see your gains, and events in the various staked assets. ![See your Kraken staking gains](/images/sc_staking_kraken.png) + +## Lido CSM + +If you are a node operator in the [Lido Community Staking Module (CSM)](https://operatorportal.lido.fi/modules/community-staking-module), you can track your operators in rotki. Navigate to `Staking > Lido CSM` to view and manage your tracked node operators. + +To add a node operator, click the add button and provide: + +- **Ethereum address** β€” the reward address associated with the node operator. +- **Node Operator ID** β€” the numeric ID assigned to your operator in the CSM. + +Once added, the table displays the following metrics for each tracked operator: + +- **Operator Type** β€” the operator category (e.g. Community, Permissioned). +- **Bond Current / Required / Claimable** β€” current bond posted, required bond, and the amount available to claim, all denominated in stETH. +- **Total Deposited Keys** β€” the number of validator keys deposited. +- **Pending Rewards** β€” unclaimed stETH rewards. + +Click the refresh button to fetch updated metrics from the protocol. You can remove a tracked operator at any time using the delete action in the table. From 9150abeaf354329b3b85cac9f4d60fd7ae7173f0 Mon Sep 17 00:00:00 2001 From: Konstantinos Paparas Date: Thu, 9 Apr 2026 21:06:21 +0200 Subject: [PATCH 4/7] docs: add quick start guide with reused screenshots Add a step-by-step Quick Start Guide walking new users through install, account creation, adding blockchain/exchange accounts, optimizing with RPC nodes and indexer API keys, viewing the dashboard, reviewing history, and generating a PnL report. Reuses 6 existing screenshots. --- .vitepress/config.mts | 3 +- index.md | 2 +- usage-guides/index.md | 10 +-- usage-guides/quick-start.md | 123 ++++++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+), 7 deletions(-) create mode 100644 usage-guides/quick-start.md diff --git a/.vitepress/config.mts b/.vitepress/config.mts index 7571a06..8259e73 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -128,7 +128,8 @@ export default defineConfig({ { text: 'Usage Guides', items: [ - { text: 'Getting Started', link: '/usage-guides/' }, + { text: 'Quick Start Guide', link: '/usage-guides/quick-start' }, + { text: 'Accounts & Sync', link: '/usage-guides/' }, { text: 'Portfolio', collapsed: false, diff --git a/index.md b/index.md index c69540b..5a9d20f 100644 --- a/index.md +++ b/index.md @@ -10,7 +10,7 @@ rotki is an open-source asset management and accounting application specializing diff --git a/usage-guides/index.md b/usage-guides/index.md index 92a8135..7c038e0 100644 --- a/usage-guides/index.md +++ b/usage-guides/index.md @@ -1,13 +1,13 @@ --- -description: Getting started with rotki including account creation, sign-in, premium setup, and data directory sync. +description: Reference for rotki account setup, sign-in, premium sync, data restoration, and upgrading between versions. --- -# Getting Started +# Accounts & Sync -This guide explains how to use the rotki application. +This page covers account creation, sign-in, premium sync, restoring backups, moving installations, and upgrading rotki. > [!TIP] -> **Using rotki for tax reporting?** Jump to the [Tax Accounting Guide](/usage-guides/tax-accounting/guide) for a focused walkthrough of connecting your data, reviewing transactions, and generating your PnL report. +> **New to rotki?** Start with the [Quick Start Guide](/usage-guides/quick-start) for a step-by-step walkthrough from installation to your first PnL report. ## First Time Sign-Up @@ -82,7 +82,7 @@ To sign in with your local rotki account, enter your profile name and password a ## Set Up rotki Premium -If you decide to purchase [rotki Premium](https://rotki.com/products/) later, you can set it up [here](/usage-guides/integrations/exchange-keys#rotki-premium) +If you purchased a [rotki Premium](https://rotki.com/products/) subscription after creating your local account, you can activate it at any time by adding your API key and secret under **API Keys β†’ rotki Premium** in the app. See [rotki Premium](/usage-guides/integrations/exchange-keys#rotki-premium) for the full setup instructions. ## Sync Data with rotki Server diff --git a/usage-guides/quick-start.md b/usage-guides/quick-start.md new file mode 100644 index 0000000..9baf0f4 --- /dev/null +++ b/usage-guides/quick-start.md @@ -0,0 +1,123 @@ +--- +description: Step-by-step walkthrough to get started with rotki, from installation to generating your first PnL report. +--- + +# Quick Start Guide + +This guide walks you through the essential steps to get rotki up and running. By the end, you'll have your accounts connected, balances visible, and know how to generate a tax report. + +> [!TIP] +> **Focused on tax reporting?** This quick start covers the essentials. For a dedicated walkthrough tailored to tax reporting β€” including connecting data sources, reviewing transactions, and handling edge cases β€” see the [Tax Accounting Guide](/usage-guides/tax-accounting/guide). + +## 1. Install rotki + +Download and install rotki for your operating system from the [official website](https://rotki.com/download) or follow the detailed [Installation Guide](/requirement-and-installation/). + +## 2. Create Your Account + +When you first launch rotki, you'll be prompted to create a local account. This account exists only on your device β€” rotki doesn't store your data on any server. + +![rotki login screen](/images/rotki_login_screen.png) + +1. Click **Create Account** +2. Choose a profile name +3. Set a strong password β€” this encrypts your local database + +![Creating a new account](/images/rotki_create_account.png) + +> [!WARNING] +> Do not forget your password. It encrypts all your local data and cannot be recovered. + +If you have a premium subscription, you can link it during account creation to enable cloud backup and sync. See [Accounts & Sync](/usage-guides/) for full details. + +## 3. Optimize Your Setup + +Before adding accounts, set up a few things to make account detection and balance queries much faster: + +- **Etherscan API Key** β€” Free and significantly speeds up EVM queries (and is required for some chains like Binance Smart Chain). Go to **API Keys β†’ External Services** and add your key. See [External Services](/usage-guides/integrations/external-services#etherscan). +- **Custom RPC Nodes** β€” Add your own RPC endpoints (e.g., from Alchemy or Infura) for faster blockchain queries. Configure in **Settings β†’ Blockchain & EVM β†’ RPC Nodes**. See [RPC Node Settings](/usage-guides/settings/blockchain#rpc-node-setting). +- **Indexer Configuration** β€” Adjust the order of indexers (Etherscan, Blockscout, Routescan) per chain for optimal performance. See [Indexers](/usage-guides/settings/blockchain#indexers). + +> [!TIP] +> At minimum, we strongly recommend adding a free Etherscan API key **before** adding your blockchain accounts. Without it, EVM queries and token detection will be significantly slower. + +## 4. Add Your Accounts + +### Blockchain Accounts + +Navigate to **Accounts** in the sidebar and add your blockchain addresses: + +1. Select the chain category (EVM, Bitcoin, Substrate, or Solana) +2. Click **Add Account** +3. Enter your address and click **Save** + +For EVM addresses, you can select **All Supported Chains** to automatically detect activity across all EVM networks. + +![Add a blockchain account](/images/add_blockchain_account.png) + +See [Accounts](/usage-guides/portfolio/accounts) for details on xpub support, multi-address imports, and more. + +### Exchange Connections + +To track exchange balances and trade history: + +1. Go to **API Keys β†’ Exchanges** in the sidebar +2. Click **Add an exchange** +3. Enter your read-only API key and secret + +![Add API keys for an exchange](/images/rotki_add_exchange_1.png) + +See [Exchange API Keys](/usage-guides/integrations/exchange-keys) for the full list of supported exchanges and per-exchange setup instructions. + +## 5. View Your Portfolio + +Once your accounts are connected, head to the [Dashboard](/usage-guides/portfolio/dashboard) to see your portfolio overview: + +![rotki Dashboard](/images/rotki_dashboard.webp) + +The dashboard shows: + +- **Total Balance** β€” Your combined net worth across all sources +- **Net Value Graph** β€” Historical portfolio value over time +- **Balance Breakdown** β€” Split by exchange, blockchain, and manual balances +- **Assets Table** β€” All holdings sorted by value + +rotki will automatically query balances and detect tokens for your tracked accounts. This initial sync may take a few minutes depending on how many accounts and chains you have. + +## 6. Review Your History + +Navigate to **History β†’ Events** to see all your transactions, trades, and DeFi interactions. rotki automatically decodes on-chain transactions and categorizes them by event type. + +![History Events page](/images/events_filter.png) + +You can: + +- Filter events by type, time period, or asset +- Edit events that were decoded incorrectly +- Add manual events for off-chain activity + +See [Historical Events](/usage-guides/history/events) for the full guide. + +## 7. Generate a Tax Report + +When you're ready to calculate your taxes: + +1. Go to **Profit and Loss Report** in the sidebar +2. Select the reporting period (start and end dates) +3. Review your [Accounting Settings](/usage-guides/settings/accounting) β€” these control how trades are calculated (FIFO, LIFO, HIFO, or ACB) and whether to apply a tax-free holding period +4. Click **Generate** + +![PnL Report](/images/sc_pnl_report.png) + +The report calculates profit and loss for every taxable event in the period, broken down by event type (trades, fees, staking rewards, airdrops, etc.). You can export the results as CSV for your tax advisor, and re-run the report with different settings if needed. + +> [!IMPORTANT] +> Tax rules vary by jurisdiction. Before filing, consult a tax professional and adjust your accounting settings to match your local requirements. + +See [Profit/Loss Report](/usage-guides/history/pnl) for detailed instructions and the [Tax Accounting Guide](/usage-guides/tax-accounting/guide) for a comprehensive walkthrough. + +## Next Steps + +- **[Settings](/usage-guides/settings/general)** β€” Customize your profit currency, display preferences, and more +- **[Data Management](/usage-guides/data-management/assets)** β€” Manage assets, add missing prices, and organize with tags +- **[Premium Features](/premium/)** β€” Unlock extended timeframes, advanced analytics, cloud sync, and more From 75b339d530d12a9802f5dd13dc680d15125a5994 Mon Sep 17 00:00:00 2001 From: Konstantinos Paparas Date: Fri, 10 Apr 2026 10:34:59 +0200 Subject: [PATCH 5/7] docs: normalize stale .html# links to clean anchor format Drop .html extensions from internal anchor links across faq, premium, contribution-guides, requirement-and-installation, and usage-guides settings/advanced pages for consistency with the restructured docs. --- contribution-guides/index.md | 4 ++-- faq.md | 2 +- premium/index.md | 4 ++-- requirement-and-installation/build-from-source.md | 2 +- usage-guides/advanced/mobile.md | 2 +- usage-guides/settings/interface.md | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/contribution-guides/index.md b/contribution-guides/index.md index 8fdcaf6..fbd55ea 100644 --- a/contribution-guides/index.md +++ b/contribution-guides/index.md @@ -20,8 +20,8 @@ Before reporting an issue, make sure to check the issue tracker for similar ones For running rotki in debug mode, you can do it either via a config file or the app UI. The choice will depend on how you run rotki. -- **Config file**: See the section [Set the backend's arguments](/usage-guides/advanced/backend-config#set-the-backend-s-arguments). This is possible in the **electron app** and the **docker version**. For docker, you can even use environment variables as explained [here](/requirement-and-installation/packaged-binaries.html#configuring-the-backend-in-docker). -- **App UI**: Before logging in, click the cog wheel at the bottom right corner and select "Debug" (image below). Press the save button and proceed to log in as usual. This is only possible in the **electron app**. +- **Config file**: See the section [Set the backend's arguments](/usage-guides/advanced/backend-config#set-the-backend-s-arguments). This is possible in the **electron app** and the **docker version**. For docker, you can even use environment variables as explained [here](/requirement-and-installation/packaged-binaries#configuring-the-backend-in-docker). +- **App UI**: Before logging in, click the cogwheel in the bottom right corner and select "Debug" (image below). Press the save button and proceed to log in as usual. This is only possible in the **electron app**. ![Run rotki in debug mode via app UI](/images/rotki_debug_mode_set.png) diff --git a/faq.md b/faq.md index 429570e..34e9133 100644 --- a/faq.md +++ b/faq.md @@ -104,7 +104,7 @@ If a transaction is not showing in rotki, it may be due to an ignored asset bein To view transactions with ignored assets, enable `Show entries with ignored assets`, and if your transaction is now visible, check which assets used in the transaction are ignored and then un-ignore them manually. -For more information on un-ignoring and optionally whitelisting assets, see [My asset is not showing in rotki](/faq.html#my-asset-is-not-showing-in-rotki) above. +For more information on un-ignoring and optionally whitelisting assets, see [My asset is not showing in rotki](/faq#my-asset-is-not-showing-in-rotki) above. ### Events are missing diff --git a/premium/index.md b/premium/index.md index 223e00b..3226b77 100644 --- a/premium/index.md +++ b/premium/index.md @@ -48,7 +48,7 @@ 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.html#creating-api-keys). +For detailed instructions, see [Creating API Keys](/premium/api-keys#creating-api-keys). ### 4. Add Keys to the App @@ -56,7 +56,7 @@ Navigate to **API Keys** β†’ **rotki Premium** in the rotki application and ente **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.html#using-api-keys-in-the-app). +For detailed instructions, see [Using API Keys in the App](/premium/api-keys#using-api-keys-in-the-app). ## Managing Your Premium Subscription diff --git a/requirement-and-installation/build-from-source.md b/requirement-and-installation/build-from-source.md index 041c621..5fceb2e 100644 --- a/requirement-and-installation/build-from-source.md +++ b/requirement-and-installation/build-from-source.md @@ -279,4 +279,4 @@ After that go to the `View` menu and press `Force Reload`. This should resolve your issue. If the issue persists, -try following the frontend [troubleshooting steps](/contribution-guides/vue-typescript.html#troubleshooting). +try following the frontend [troubleshooting steps](/contribution-guides/vue-typescript#troubleshooting). diff --git a/usage-guides/advanced/mobile.md b/usage-guides/advanced/mobile.md index 285c698..0daa0cf 100644 --- a/usage-guides/advanced/mobile.md +++ b/usage-guides/advanced/mobile.md @@ -18,7 +18,7 @@ This way you can get the full rotki functionality on mobile. ## Docker -Accessing rotki on mobile when you run Docker on your own can be a bit complicated and depends on the kind of setup you have. You have to make sure that [rotki is never directly accessible from a public network](/requirement-and-installation/packaged-binaries.html#docker). +Accessing rotki on mobile when you run Docker on your own can be a bit complicated and depends on the kind of setup you have. You have to make sure that [rotki is never directly accessible from a public network](/requirement-and-installation/packaged-binaries#docker). One way to have rotki accessible on mobile over a public network is by making sure that an [authenticated proxy](#docker-rotki-public) intercepts all traffic directed to rotki. This way you can ensure that no one else can access your rotki instance. diff --git a/usage-guides/settings/interface.md b/usage-guides/settings/interface.md index e787531..d023721 100644 --- a/usage-guides/settings/interface.md +++ b/usage-guides/settings/interface.md @@ -10,7 +10,7 @@ description: Customizing the rotki interface including language, theme, animatio #### Language -Set the language used in the app. This feature is experimental and may not work as expected for some languages. Help us speed up the translation process by contributing [here](/contribution-guides/contribute-as-developer.html#add-a-new-language-or-translation). +Set the language used in the app. This feature is experimental and may not work as expected for some languages. Help us speed up the translation process by contributing [here](/contribution-guides/contribute-as-developer#add-a-new-language-or-translation). #### Animation Effect From 1cabb2a30326237ad1cecd948b5895105c8b3376 Mon Sep 17 00:00:00 2001 From: Konstantinos Paparas Date: Fri, 10 Apr 2026 11:27:01 +0200 Subject: [PATCH 6/7] feat: add copy/download as markdown buttons to pages Wire up the vitepress-plugin-llms CopyOrDownloadAsMarkdownButtons component so each page shows a dropdown with Copy page, View as Markdown, Open in ChatGPT/Claude, and a Download button. --- .vitepress/config.mts | 3 ++- .vitepress/theme/index.ts | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.vitepress/config.mts b/.vitepress/config.mts index 8259e73..63e354c 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -2,7 +2,7 @@ import path from 'node:path'; import process from 'node:process'; import { fileURLToPath, URL } from 'node:url'; import { defineConfig } from 'vitepress'; -import llmstxt from 'vitepress-plugin-llms'; +import llmstxt, { copyOrDownloadAsMarkdownButtons } from 'vitepress-plugin-llms'; import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'; import { markdownFitMedia } from './plugins/markdown-fit-media'; import { getRedirectPaths, redirectsPlugin } from './plugins/redirects'; @@ -272,6 +272,7 @@ export default defineConfig({ markdown: { config(md) { md.use(tabsMarkdownPlugin); + md.use(copyOrDownloadAsMarkdownButtons); md.use(markdownFitMedia, { imgDir: './public', lazyLoad: true, diff --git a/.vitepress/theme/index.ts b/.vitepress/theme/index.ts index 5f0138b..842d399 100644 --- a/.vitepress/theme/index.ts +++ b/.vitepress/theme/index.ts @@ -1,4 +1,5 @@ import type { Theme } from 'vitepress'; +import CopyOrDownloadAsMarkdownButtons from 'vitepress-plugin-llms/vitepress-components/CopyOrDownloadAsMarkdownButtons.vue'; import { enhanceAppWithTabs } from 'vitepress-plugin-tabs/client'; import DefaultTheme from 'vitepress/theme'; import { h } from 'vue'; @@ -15,5 +16,6 @@ export default { enhanceAppWithTabs(app); app.component('CsvTable', CsvTable); app.component('NavCards', NavCards); + app.component('CopyOrDownloadAsMarkdownButtons', CopyOrDownloadAsMarkdownButtons); }, } satisfies Theme; From b8327318a7bbbdfcfb2cdce5a226fdafc57b01c6 Mon Sep 17 00:00:00 2001 From: Konstantinos Paparas Date: Fri, 10 Apr 2026 12:25:22 +0200 Subject: [PATCH 7/7] docs: move rotki premium activation out of exchange-keys The rotki Premium activation section was off-topic in Exchange API Keys (which is about connecting centralized exchanges). Remove it and route the old /usage-guides/api-keys#rotki-premium anchor to /premium/api-keys via the redirect plugin. --- .vitepress/config.mts | 1 + usage-guides/index.md | 2 +- usage-guides/integrations/exchange-keys.md | 12 +----------- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/.vitepress/config.mts b/.vitepress/config.mts index 63e354c..67c50f2 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -47,6 +47,7 @@ const redirects: Record = { 'usage-guides/api-keys': { default: '/usage-guides/integrations/exchange-keys', anchors: { + '#rotki-premium': '/premium/api-keys', '#external-services': '/usage-guides/integrations/external-services', '#etherscan': '/usage-guides/integrations/external-services', '#loopring-balances': '/usage-guides/integrations/external-services', diff --git a/usage-guides/index.md b/usage-guides/index.md index 7c038e0..0fbff65 100644 --- a/usage-guides/index.md +++ b/usage-guides/index.md @@ -82,7 +82,7 @@ To sign in with your local rotki account, enter your profile name and password a ## Set Up rotki Premium -If you purchased a [rotki Premium](https://rotki.com/products/) subscription after creating your local account, you can activate it at any time by adding your API key and secret under **API Keys β†’ rotki Premium** in the app. See [rotki Premium](/usage-guides/integrations/exchange-keys#rotki-premium) for the full setup instructions. +If you purchased a [rotki Premium](https://rotki.com/products/) subscription after creating your local account, you can activate it at any time by adding your API key and secret under **API Keys β†’ rotki Premium** in the app. See [rotki Premium API Credentials](/premium/api-keys) for the full setup instructions. ## Sync Data with rotki Server diff --git a/usage-guides/integrations/exchange-keys.md b/usage-guides/integrations/exchange-keys.md index 59ac2a5..0af2219 100644 --- a/usage-guides/integrations/exchange-keys.md +++ b/usage-guides/integrations/exchange-keys.md @@ -4,17 +4,7 @@ description: Connecting centralized exchanges to rotki via API keys, with per-ex # Exchange API Keys -In this section, we will explain how to connect exchanges to rotki via API Keys. -Go to the `API Keys` menu in the sidebar. - -## rotki Premium - -![Set up rotki premium API key/secret pair in an existing account](/images/rotki_premium_set.png) - -A rotki premium subscription is activated in the app by adding your **API Key** and **API Secret**. -If you don't have a premium subscription yet, you can subscribe at [rotki.com/products](https://rotki.com/products/). - -For detailed information about premium plans, pricing, payment options, and how to use your premium API key see the [Premium documentation](/premium/). +This page covers connecting centralized exchanges to rotki via read-only API keys. Go to the `API Keys` menu in the sidebar, then **Exchanges**. ## Exchanges API Keys