rotki

rotki.com
rotki

A self-hosted, opensource, privacy-first portfolio tracking and accounting tool for crypto and more. Support for all 3 major Operating systems and docker. The tool focus is on data self-sovereignty.

Crypto Payments Accepted Open Source

rotki Source Code

Author

rotki

Description

A portfolio tracking, analytics, accounting and management application that protects your privacy

#accounting#analytics#bitcoin#blockchain#cryptocurrencies#cryptocurrency-exchanges#cryptocurrency-portfolio#cryptocurrency-portfolio-tracking#ethereum#hacktoberfest#management#management-system#portfolio-tracker#tracking

Homepage

https://rotki.com

Repository

  • LicenseAGPL-3.0
  • Created05 Mar 18
  • Primary languagePython
  • Size532,706 KB
  • Stars4,039
  • Forks767
  • Watchers4,039

Language Usage

Language Usage

Project Health

  • Last commit6 days ago
  • Open issues407
  • Latest releasev1.44.1

Top Contributors

Recent Commits

  • Konstantinos Paparas(30 Sept 26)

    feat(frontend): fold and reorder action center Sections now come in the order their fixes depend on each other: keys first, then chains, history and assets. A missing key or indexer leaves the chains and history behind it incomplete, so it is worth fixing first. The order is fixed, so a section never moves while it is being read. Each section header folds its rows away. A folded header keeps the row count, coloured by its most pressing row, and says when a new row is inside. The folded sections are kept per user in local storage.

  • Konstantinos Paparas(30 Sept 26)

    feat(frontend): show progress in the action center The center remembers each row's count when it closes. On the next open a row that went down reads "down from N" beside its count, and a row that cleared is tagged "cleared since your last visit" in the checks list, which opens by itself when that happens. The comparison lasts until the center closes again, and nothing is compared before the first scan.

  • Konstantinos Paparas(30 Sept 26)

    fix(frontend): drop semver from preinstall check pnpm 12.6 runs the root preinstall before resolving dependencies, so check-versions.js failed on a clean checkout with ERR_MODULE_NOT_FOUND for semver. It now compares the engines ranges without dependencies, and the root package drops semver, which nothing else there used.

  • Konstantinos Paparas(30 Sept 26)

    ci: update pinned github actions Every bump has passed the 7-day release age Renovate enforces: attest-build-provenance 4.2.2, benchmark 1.22.2, codecov 7.1.1, typos 1.50.2, build-push 7.4.0, setup-buildx 4.4.1, codeql 4.38.1, pnpm/action-setup 6.1.0, rust-cache 2.9.2, and the rust-toolchain clippy and stable branch heads. setup-uv moves from 8.3.2 to 10.2.0. Every step sets enable-cache explicitly, so v10's auto-cache change does not apply. v9 turned prune-cache off by default; the CI flow (rotki_ci and the backend, contract and e2e tests it calls) sets it back on to keep its uv caches small.

  • Konstantinos Paparas(30 Sept 26)

    fix(ci): update js-yaml to 5.4.1 Fixes GHSA-r3ph-w7gj-g6xm in the CI/release scripts. The lockfile also records pnpm 12.6.0, which the packageManager bump requires.

  • Konstantinos Paparas(30 Sept 26)

    fix(frontend): refresh vulnerable transitive deps Clears all 80 pnpm audit advisories (1 critical, 51 high) by moving tar, @xmldom/xmldom, undici, brace-expansion, fast-uri, js-yaml, shell-quote and devalue to patched releases within their existing ranges. No manifest changes.

  • Konstantinos Paparas(30 Sept 26)

    chore(frontend): update dependencies Non-major frontend updates from the dependency dashboard (#12044), plus pnpm 12.6.0 and node 24.21.0. - @vue/test-utils 2.5.1 adds a findComponent overload for functional components, which a ReturnType<typeof defineComponent> stub matches, so the history specs type their stubs as DefineComponent. - stylelint 17.15 enables at-rule-prelude-no-invalid, which rejects Tailwind's @apply; it gets the same at-rule ignore list as at-rule-no-unknown.

  • Konstantinos Paparas(30 Sept 26)

    test(frontend): cover the balance processing store

  • Konstantinos Paparas(30 Sept 26)

    docs: document balance processing completed ws message

  • Yábir Benchakhtir(30 Sept 26)

    send ws message after balance processing (#13160) * send ws message after balance processing * Refresh balances only after processing completes

  • Konstantinos Paparas(29 Sept 26)

    refactor(frontend): plan an account delete once The confirmation wording and the delete request each ran their own case analysis over the row, so a change to one that missed the other would tell the user it deletes something other than what it sends. The row is now turned once into an AccountDeletion in accounts/core, discriminated by an as-const DeletionKind, and both the message and the request switch over that one value, which fails to compile when a kind is unhandled. What left the backend is a RemovedAccounts rather than a string list that held addresses, validator keys and xpubs alike, and the store prune is the pure withoutRemoved, which no longer deletes entries from the balances store's own per-chain object before replacing it. Each removal resolves to an Option of what it removed, so a failed or cancelled delete prunes nothing by construction.

  • Konstantinos Paparas(29 Sept 26)

    fix(frontend): prune only the deleted xpub path After an xpub delete, the local prune matched xpubs by the xpub string alone. The backend keys an xpub by (xpub, derivation path, chain), so deleting one derivation path also dropped the same xpub under another path, with its derived addresses, from the table until the next reload. The prune now matches the xpub key, derivation path included.

  • Konstantinos Paparas(29 Sept 26)

    fix(frontend): delete a group under its category Deleting a group from every chain at once sent the payload tag, always 'evm', as the chain type. The backend only looks for the address on the chains of that type, so a legacy Bitcoin address tracked on both BTC and BCH failed with "Tried to delete non tracked addresses" and stayed. The agnostic delete now uses the group's own category.

  • Konstantinos Paparas(29 Sept 26)

    fix(frontend): keep a validator whose delete fails removeValidator ignored the boolean deleteEth2Validators returns and pruned the validators from the store either way. A failed delete showed its error and still dropped the validators from the table until the next reload, although the backend kept tracking them.

  • Konstantinos Paparas(29 Sept 26)

    refactor(frontend): compose account list filters Rework sortAndFilterAccounts in accounts/core/account-list.ts without changing what it returns: - Each filter is a predicate (byAddress, byChain, byTags, byCategory), combined with plainfp's `and` over only the active ones. The picked addresses are lowercased once instead of per row. The group-member pass reuses the same predicates for chain and tags. - A row is shaped by one `T => Option<T>` step: none drops a group no member matches, otherwise the group is narrowed or gets its chain exclusion. This replaces the undefined/null/value return that the caller had to decode. - The separate no-filter branch is gone. With nothing filtered every row passed and no group was refined, so both branches already produced the same rows. - Sorting resolves each row's sort values once before sorting, so the label resolver runs once per row instead of twice per comparison. The per-row fallthrough on a missing attribute and the order of ties are unchanged. `sum` now accepts a readonly array, since it only reads it.

  • Konstantinos Paparas(28 Sept 26)

    refactor(frontend): flatten the account model Accounts carried their identity in a nested data object discriminated by type, plus a stored nativeAsset and, for BTC xpubs, a groupHeader flag and a hand-built groupId to pair the xpub row with its derived addresses. Replace that with flat AddressAccount, XpubAccount and ValidatorAccount types discriminated by kind (AccountKind), so the account itself narrows. - An xpub is its own entity; each derived address points back to it through xpubParent, so groupHeader and the stored groupId go. - nativeAsset is no longer stored: balance code takes it through a nativeAssetOf port backed by getNativeAsset. - Rows split into AddressGroupWithBalance and XpubGroupWithBalance, with amount and nativeAsset required on the xpub one; an xpub is never an account row. - matchKind dispatches on kind and needs a handler per kind, replacing the 'publicKey' in / 'xpub' in probes; hasAccountAddress and isAccountWithBalanceValidator give way to generic kind guards. The shape is frontend-only: requests, storage, premium and the CSV export do not carry it, and the group id format kept in URLs is unchanged.

  • Konstantinos Paparas(28 Sept 26)

    refactor(frontend): brand account and group ids Add AccountGroupId and AccountId brands, returned by getGroupId and getAccountId, and getXpubGroupId as the one place that builds an xpub's group id; bitcoin-accounts no longer spells the format out by hand. The account group id, the member index and the group request payload now carry the brand, so a hand-built string can no longer stand in for one. The id format is unchanged, keeping existing URLs valid.

  • Konstantinos Paparas(28 Sept 26)

    refactor(frontend): type the account group category Add AccountCategory (the chain types with an accounts page, evm-like folded into evm) and return it from getChainAccountType. A group's category is now required, so buildGroupManage loses its assert and the table and expanded row lose their empty-string fallbacks. Account rows never carried a category, so the field goes from them. A group on a chain the backend did not report has no category and is now left out. No accounts page could list it, and accounts are only fetched for reported chains, so it only happened in specs that never loaded chain info; those now provide it.

  • Konstantinos Paparas(28 Sept 26)

    refactor(frontend): drop dead account row fields Nothing has set an account's virtual flag since the loopring removal (581e0100fa), so the isVirtual plumbing through the accounts table and AccountActions only ever saw false. aggregatedAssets was never set or read. Remove both, the stale AccountActions note about xpub "virtual rows", and correct a comment that called the local excluded filter a request param.

  • Konstantinos Paparas(28 Sept 26)

    refactor(frontend): move account helpers to core Split account-helpers.ts into pure accounts/core modules: account-list (filter, group refinement, sort, page), bitcoin-accounts and account-balance. The two type guards move to account-utils. refineGroup and the sort comparator become module-level functions with explicit parameters instead of closures in sortAndFilterAccounts. convertBtcBalances merges xpub address maps in one pass instead of a spread inside reduce, and convertBtcAccounts drops a ?? fallback that could never apply (getNativeAsset already falls back to the chain).

  • Konstantinos Paparas(29 Sept 26)

    fix(frontend): prebundle every plainfp subpath optimizeDeps.include listed five of the ten plainfp entry points the app imports. A subpath reached first from a lazily loaded route, such as plainfp/non-empty-array from the balance refresher, was then discovered at runtime, and vite re-optimized and forced a full page reload mid-session. List all ten.

  • Yábir Benchakhtir(29 Sept 26)

    test: fix flaky test_query_async_tasks (#13241) The test only mocked binance's session.get, so other binance endpoints hit the live API. On CI they failed fast with HTTP 451, the task finished before the pending check and the test saw completed=[0] instead of pending=[0]. Patch ExchangesService.query_exchange_balances with a function that blocks on an Event, so the task is pending exactly as long as the test needs. A wrapper around _write_task_result signals when the result is stored, replacing the sleep polling loop.

  • Konstantinos Paparas(28 Sept 26)

    feat(frontend): list premium and Binance in center Two more one-off notifications become action center rows under Integrations & keys. - Premium inactive: the backend reports premium status on every hourly check, but only while a premium key is saved, so an inactive report means a saved key that does not work. The row names the cause: expired (renew), device limit (the backend's own explanation) or an unreachable server (rotki retries, so it is only worth a look). It offers removing the key, and leaves once a check finds the key working, a new key is saved or the key is removed. A pure reader in premium/core turns the report into a status. "Premium activated" stays a notification, shown only on a change. - Binance pairs missing: raised when a trade history query finds an account with no market pairs selected, one row per account. It leaves once pairs are saved, the account is removed or renamed, or a re-check finds pairs, and it offers "Do not show again for this account" (suppressBinancePairsMissing) for balance-only accounts. The notification texts nothing else uses are removed from every locale.

  • Konstantinos Paparas(24 Sept 26)

    feat(frontend): mark detected accounts, drop toasts Account detection no longer raises a sticky toast per chain. The accounts table rings the chains detection added and marks the row with a "New" chip whose tooltip names them. Clicking the chip dismisses the marks, and they clear on logout. The Detect button reports its outcome in its own label for a few seconds, at a fixed width. The found accounts come from comparing the tracked accounts before the run with a re-read after it, since the detection websocket message and the polled task result arrive in no guaranteed order. The comparison runs inside the task, so a retry from the task dock repeats it, and it waits for the account load, so a store still filling does not count unread accounts as found. Accounts the user adds by hand while a run is going are left out: each manual addition is noted when submitted, since the backend saves it before the app polls its result, and is forgotten by the first run that starts after it finished.

  • Konstantinos Paparas(28 Sept 26)

    fix(frontend): tone action center trigger by urgency The trigger was always an orange warning triangle once anything was pending, even when every row was a to-do drawn in blue, such as the history sync row on a fresh account. It now takes its icon, colour and badge colour from the most pressing urgency among the active rows. The history sync row no longer offers "Go to history events" before transactions were ever queried, and its link uses an arrow instead of repeating the row's history icon. The subtitle now reads "to look at" instead of "needs your attention".

  • Konstantinos Paparas(28 Sept 26)

    test(frontend): use await import in hoisted mocks Values a vi.mock factory needs are built in an async vi.hoisted with await import instead of a require behind an eslint-disable for no-require-imports. Specs are ESM, so top-level await works and the import stays typed; the login page spec's state ref now carries UnlockState instead of any. CLAUDE.md and AGENTS.md note the pattern under "Writing any spec".

  • Konstantinos Paparas(28 Sept 26)

    feat(frontend): list one-offs in the action center Accounting rule conflicts, Solana tokens that need migrating by hand and a Gnosis Pay Safe left untracked by its migration are now action center rows instead of notifications. - Accounting conflicts share one count between the accounting rules page, its resolve dialog, the websocket handler and the History row. Resolve opens the page with the dialog up. - The Solana websocket message only fills the store; the Assets row counts it and leads to the migration page. - The Gnosis Pay Safe row adds the Safe in place. The lookup and the reading of the addition result move to a pure core, and the state is now cleared on logout. The login-time check and the weekly re-notify setting are gone, since the center's first scan reads it. - Both re-readable sources are read on the first scan and on Re-scan, not whenever history settles.

  • Konstantinos Paparas(25 Sept 26)

    test(frontend): cover empty account groups A tracked address whose balances have not loaded yet, and an xpub with no derived addresses, both show as empty rows with nothing to expand.

  • Konstantinos Paparas(25 Sept 26)

    refactor(frontend): move account grouping to core The accounts table rows are now built by pure functions in accounts/core, which the core lint rule keeps free of vue and stores: - accountGroups builds the address and xpub rows from an index of accounts and balances by address, instead of scanning every chain for every address - fetchAccounts looks a group's members up in a map instead of filtering the whole account list once per group - accountAssetBalances, topTokens and xpubNativeHolding replace the inline logic in use-blockchain-account-data and AccountTopTokens.vue

  • Konstantinos Paparas(25 Sept 26)

    test(frontend): drop comments the specs restate The selector contract comment sat above the snapshot at eleven form specs, repeating what selectorContract's TSDoc already says. The six price comments become named ETH_PRICE and ETH_USD_PRICE constants, and the transformer comments move into the test titles.

rotki Security

6.7/10

Repo Security Summary

Updated 24 Aug 26

  • Code-Review2/10
  • Maintained10/10
  • CII-Best-Practices0/10
  • Dangerous-Workflow10/10
  • Token-Permissions10/10
  • Security-Policy0/10
  • License10/10
  • Binary-Artifacts10/10
  • Branch-Protection8/10
  • Signed-Releases0/10
  • Packaging10/10
  • SAST10/10
  • Pinned-Dependencies9/10
  • Fuzzing0/10

rotki Website

Website

rotki

rotki is an open source portfolio tracker, accounting and analytics tool that protects your privacy.

Redirects

Does not redirect

Security Checks

All 65 security checks passed

Server Details

  • IP Address136.244.105.88
  • Hostname136.244.105.88.vultrusercontent.com
  • LocationAmsterdam,Noord-Holland,Netherlands (Kingdom of the),EU
  • ISPVultr Holdings LLC
  • ASNAS20473

Associated Countries

  • USUS
  • NLNL

Safety Score

Website marked as safe

100%

Blacklist Check

rotki.com was found on 0 blacklists

  • AntiSocial Blacklist
  • Artists Against 419
  • Badbitcoin
  • Bambenek Consulting
  • CERT Polska
  • CoinBlockerLists
  • CRDF
  • CryptoScamDB
  • EtherAddressLookup
  • EtherScamDB
  • Fake Website Buster
  • MetaMask EthPhishing
  • NABP Not Recommended Sites
  • OpenPhish
  • PetScams
  • PhishFeed
  • PhishFort
  • Phishing.Database
  • PhishStats
  • PhishTank
  • Phishunt
  • RPiList Not Serious
  • Scam.Directory
  • SecureReload Phishing List
  • Spam404
  • StopGunScams
  • Suspicious Hosting IP
  • ThreatFox
  • ThreatLog
  • TweetFeed
  • URLhaus
  • ViriBack C2 Tracker

Website Preview

Website preview

rotki Reviews

More Secure Budgeting

About the Data: rotki

Change History

Edit rotki Data

You can edit rotki's entry in this section of awesome-privacy.yml by submitting a PR to our GitHub repo.
Note that some of the information shown above has been aggregated from external sources, a list of these can be found data documentation.

Origin Data

Modify Data

API

You can access rotki's data programmatically via our API. Simply make a GET request to:

https://api.awesome-privacy.xyz/v1/services/rotki

The REST API is free, no-auth and CORS-enabled. To learn more, view the API Docs or read the API Usage Guide.

Share rotki

Help your friends compare Secure Budgeting, and pick privacy-respecting software and services.
Share rotki and Awesome Privacy with your network!