From 2deca5892853bae390a4d131e670c13d7f77a0a8 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Tue, 8 Apr 2025 08:56:19 +0200 Subject: [PATCH 01/62] Bugfix/fix action label in asset profile dialog (#4517) * Fix label * Update changelog --- CHANGELOG.md | 1 + .../asset-profile-dialog/asset-profile-dialog.html | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c73e55719..b45e199da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Improved the language localization for Enlish (`en`) - Upgraded `eslint` dependencies ## 2.150.0 - 2025-04-05 diff --git a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html index 9c13a503c..042c63594 100644 --- a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html +++ b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html @@ -24,7 +24,7 @@ onGatherSymbol({ dataSource: data.dataSource, symbol: data.symbol }) " > - Gather Historical Market Dataa + Gather Historical Market Data @if (price) { diff --git a/apps/client/src/app/pages/pricing/pricing-page.html b/apps/client/src/app/pages/pricing/pricing-page.html index b165d5c23..d26a2e11e 100644 --- a/apps/client/src/app/pages/pricing/pricing-page.html +++ b/apps/client/src/app/pages/pricing/pricing-page.html @@ -306,14 +306,10 @@ mat-flat-button (click)="onCheckout()" > - @if (user.subscription.offer === 'default') { - Upgrade Plan - } @else if ( - user.subscription.offer === 'renewal' || - user.subscription.offer === 'renewal-early-bird-2023' || - user.subscription.offer === 'renewal-early-bird-2024' - ) { + @if (user.subscription.offer.isRenewal) { Renew Plan + } @else { + Upgrade Plan }

diff --git a/libs/common/src/lib/interfaces/subscription-offer.interface.ts b/libs/common/src/lib/interfaces/subscription-offer.interface.ts index 9ffe96a58..a9ebb54f4 100644 --- a/libs/common/src/lib/interfaces/subscription-offer.interface.ts +++ b/libs/common/src/lib/interfaces/subscription-offer.interface.ts @@ -4,6 +4,7 @@ export interface SubscriptionOffer { coupon?: number; couponId?: string; durationExtension?: StringValue; + isRenewal?: boolean; label?: string; price: number; priceId: string; From 073e60055d12f50bd007aea0f53132d6b97061d4 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Thu, 17 Apr 2025 20:35:12 +0200 Subject: [PATCH 23/62] Release 2.152.1 (#4553) --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e53cefacb..0850d7831 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 2.152.0 - 2025-04-16 +## 2.152.1 - 2025-04-17 ### Changed diff --git a/package-lock.json b/package-lock.json index 8af486482..827033432 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ghostfolio", - "version": "2.152.0", + "version": "2.152.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "2.152.0", + "version": "2.152.1", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index 36a69a9bd..81c48066d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "2.152.0", + "version": "2.152.1", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio", From 53122b09ab194e1e062b37526a2339fbe2a8d115 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 17 Apr 2025 20:39:30 +0200 Subject: [PATCH 24/62] Feature/update locales (#4554) Co-authored-by: github-actions[bot] --- apps/client/src/locales/messages.ca.xlf | 58 ++++++++++++------------- apps/client/src/locales/messages.de.xlf | 58 ++++++++++++------------- apps/client/src/locales/messages.es.xlf | 58 ++++++++++++------------- apps/client/src/locales/messages.fr.xlf | 58 ++++++++++++------------- apps/client/src/locales/messages.it.xlf | 58 ++++++++++++------------- apps/client/src/locales/messages.nl.xlf | 58 ++++++++++++------------- apps/client/src/locales/messages.pl.xlf | 58 ++++++++++++------------- apps/client/src/locales/messages.pt.xlf | 58 ++++++++++++------------- apps/client/src/locales/messages.tr.xlf | 58 ++++++++++++------------- apps/client/src/locales/messages.uk.xlf | 58 ++++++++++++------------- apps/client/src/locales/messages.xlf | 58 ++++++++++++------------- apps/client/src/locales/messages.zh.xlf | 58 ++++++++++++------------- 12 files changed, 348 insertions(+), 348 deletions(-) diff --git a/apps/client/src/locales/messages.ca.xlf b/apps/client/src/locales/messages.ca.xlf index b028e9c10..5c833ef23 100644 --- a/apps/client/src/locales/messages.ca.xlf +++ b/apps/client/src/locales/messages.ca.xlf @@ -74,7 +74,7 @@ apps/client/src/app/components/header/header.component.html - 398 + 394 apps/client/src/app/components/home-market/home-market.html @@ -98,7 +98,7 @@ apps/client/src/app/components/header/header.component.html - 291 + 287 apps/client/src/app/pages/resources/overview/resources-overview.component.html @@ -118,7 +118,7 @@ apps/client/src/app/components/header/header.component.html - 364 + 360 @@ -238,7 +238,7 @@ apps/client/src/app/components/header/header.component.html - 351 + 347 apps/client/src/app/pages/features/features-page.html @@ -282,11 +282,11 @@ apps/client/src/app/components/header/header.component.html - 303 + 299 apps/client/src/app/components/header/header.component.html - 379 + 375 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -2131,7 +2131,7 @@ apps/client/src/app/components/header/header.component.html - 263 + 259 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -2347,7 +2347,7 @@ apps/client/src/app/components/header/header.component.html - 245 + 241 @@ -2359,7 +2359,7 @@ apps/client/src/app/components/header/header.component.html - 255 + 251 @@ -2371,7 +2371,7 @@ apps/client/src/app/components/header/header.component.html - 279 + 275 @@ -2379,7 +2379,7 @@ Millora la teva Subscripció apps/client/src/app/components/header/header.component.html - 185 + 187 apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html @@ -2387,11 +2387,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + 20 apps/client/src/app/pages/pricing/pricing-page.html - 310 + 312 @@ -2399,15 +2399,15 @@ Renova la teva Subscripció apps/client/src/app/components/header/header.component.html - 191 + 185 apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + 18 apps/client/src/app/pages/pricing/pricing-page.html - 316 + 310 @@ -2415,7 +2415,7 @@ Tu apps/client/src/app/components/header/header.component.html - 211 + 207 @@ -2427,7 +2427,7 @@ apps/client/src/app/components/header/header.component.html - 229 + 225 @@ -2435,7 +2435,7 @@ El meu Ghostfolio apps/client/src/app/components/header/header.component.html - 270 + 266 @@ -2443,7 +2443,7 @@ Sobre Ghostfolio apps/client/src/app/components/header/header.component.html - 316 + 312 apps/client/src/app/pages/about/overview/about-overview-page.html @@ -2455,7 +2455,7 @@ Iniciar Sessió apps/client/src/app/components/header/header.component.html - 412 + 408 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -2467,7 +2467,7 @@ Primers Passos apps/client/src/app/components/header/header.component.html - 422 + 418 @@ -3319,7 +3319,7 @@ per year apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + 32 apps/client/src/app/pages/pricing/pricing-page.html @@ -3331,7 +3331,7 @@ Try Premium apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + 49 @@ -3339,7 +3339,7 @@ Redeem Coupon apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + 63 @@ -4187,7 +4187,7 @@ apps/client/src/app/pages/pricing/pricing-page.html - 346 + 342 @@ -5415,7 +5415,7 @@ One-time payment, no auto-renewal. apps/client/src/app/pages/pricing/pricing-page.html - 320 + 316 @@ -5423,7 +5423,7 @@ It’s free. apps/client/src/app/pages/pricing/pricing-page.html - 349 + 345 @@ -7103,7 +7103,7 @@ No auto-renewal. apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + 70 diff --git a/apps/client/src/locales/messages.de.xlf b/apps/client/src/locales/messages.de.xlf index 9b61c4fff..945e369de 100644 --- a/apps/client/src/locales/messages.de.xlf +++ b/apps/client/src/locales/messages.de.xlf @@ -770,7 +770,7 @@ apps/client/src/app/components/header/header.component.html - 229 + 225 @@ -814,7 +814,7 @@ apps/client/src/app/components/header/header.component.html - 245 + 241 @@ -826,7 +826,7 @@ apps/client/src/app/components/header/header.component.html - 255 + 251 @@ -846,7 +846,7 @@ apps/client/src/app/components/header/header.component.html - 263 + 259 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -866,7 +866,7 @@ apps/client/src/app/components/header/header.component.html - 279 + 275 @@ -882,7 +882,7 @@ apps/client/src/app/components/header/header.component.html - 291 + 287 apps/client/src/app/pages/resources/overview/resources-overview.component.html @@ -902,11 +902,11 @@ apps/client/src/app/components/header/header.component.html - 303 + 299 apps/client/src/app/components/header/header.component.html - 379 + 375 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -926,7 +926,7 @@ apps/client/src/app/components/header/header.component.html - 364 + 360 @@ -934,7 +934,7 @@ Ich apps/client/src/app/components/header/header.component.html - 211 + 207 @@ -942,7 +942,7 @@ Mein Ghostfolio apps/client/src/app/components/header/header.component.html - 270 + 266 @@ -950,7 +950,7 @@ Über Ghostfolio apps/client/src/app/components/header/header.component.html - 316 + 312 apps/client/src/app/pages/about/overview/about-overview-page.html @@ -966,7 +966,7 @@ apps/client/src/app/components/header/header.component.html - 351 + 347 apps/client/src/app/pages/features/features-page.html @@ -982,7 +982,7 @@ apps/client/src/app/components/header/header.component.html - 398 + 394 apps/client/src/app/components/home-market/home-market.html @@ -1134,7 +1134,7 @@ Einloggen apps/client/src/app/components/header/header.component.html - 412 + 408 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1698,7 +1698,7 @@ pro Jahr apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + 32 apps/client/src/app/pages/pricing/pricing-page.html @@ -1710,7 +1710,7 @@ Premium ausprobieren apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + 49 @@ -1718,7 +1718,7 @@ Gutschein einlösen apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + 63 @@ -2598,7 +2598,7 @@ Registrieren apps/client/src/app/components/header/header.component.html - 422 + 418 @@ -3578,7 +3578,7 @@ Abonnement abschliessen apps/client/src/app/components/header/header.component.html - 185 + 187 apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html @@ -3586,11 +3586,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + 20 apps/client/src/app/pages/pricing/pricing-page.html - 310 + 312 @@ -3702,7 +3702,7 @@ Einmalige Zahlung, keine automatische Erneuerung. apps/client/src/app/pages/pricing/pricing-page.html - 320 + 316 @@ -3718,7 +3718,7 @@ Es ist kostenlos. apps/client/src/app/pages/pricing/pricing-page.html - 349 + 345 @@ -3878,15 +3878,15 @@ Abonnement erneuern apps/client/src/app/components/header/header.component.html - 191 + 185 apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + 18 apps/client/src/app/pages/pricing/pricing-page.html - 316 + 310 @@ -4918,7 +4918,7 @@ apps/client/src/app/pages/pricing/pricing-page.html - 346 + 342 @@ -7127,7 +7127,7 @@ Keine automatische Erneuerung. apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + 70 diff --git a/apps/client/src/locales/messages.es.xlf b/apps/client/src/locales/messages.es.xlf index a67e053f5..107336ecc 100644 --- a/apps/client/src/locales/messages.es.xlf +++ b/apps/client/src/locales/messages.es.xlf @@ -755,7 +755,7 @@ apps/client/src/app/components/header/header.component.html - 229 + 225 @@ -799,7 +799,7 @@ apps/client/src/app/components/header/header.component.html - 245 + 241 @@ -811,7 +811,7 @@ apps/client/src/app/components/header/header.component.html - 255 + 251 @@ -831,7 +831,7 @@ apps/client/src/app/components/header/header.component.html - 263 + 259 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -851,7 +851,7 @@ apps/client/src/app/components/header/header.component.html - 279 + 275 @@ -867,7 +867,7 @@ apps/client/src/app/components/header/header.component.html - 291 + 287 apps/client/src/app/pages/resources/overview/resources-overview.component.html @@ -887,11 +887,11 @@ apps/client/src/app/components/header/header.component.html - 303 + 299 apps/client/src/app/components/header/header.component.html - 379 + 375 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -911,7 +911,7 @@ apps/client/src/app/components/header/header.component.html - 364 + 360 @@ -919,7 +919,7 @@ apps/client/src/app/components/header/header.component.html - 211 + 207 @@ -927,7 +927,7 @@ Mi Ghostfolio apps/client/src/app/components/header/header.component.html - 270 + 266 @@ -935,7 +935,7 @@ Sobre Ghostfolio apps/client/src/app/components/header/header.component.html - 316 + 312 apps/client/src/app/pages/about/overview/about-overview-page.html @@ -951,7 +951,7 @@ apps/client/src/app/components/header/header.component.html - 351 + 347 apps/client/src/app/pages/features/features-page.html @@ -967,7 +967,7 @@ apps/client/src/app/components/header/header.component.html - 398 + 394 apps/client/src/app/components/home-market/home-market.html @@ -1119,7 +1119,7 @@ Iniciar sesión apps/client/src/app/components/header/header.component.html - 412 + 408 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1683,7 +1683,7 @@ por año apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + 32 apps/client/src/app/pages/pricing/pricing-page.html @@ -1695,7 +1695,7 @@ Prueba Premium apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + 49 @@ -1703,7 +1703,7 @@ Canjea el cupón apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + 63 @@ -2583,7 +2583,7 @@ Comenzar apps/client/src/app/components/header/header.component.html - 422 + 418 @@ -3563,7 +3563,7 @@ Mejorar plan apps/client/src/app/components/header/header.component.html - 185 + 187 apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html @@ -3571,11 +3571,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + 20 apps/client/src/app/pages/pricing/pricing-page.html - 310 + 312 @@ -3687,7 +3687,7 @@ Pago único, sin renovación automática. apps/client/src/app/pages/pricing/pricing-page.html - 320 + 316 @@ -3703,7 +3703,7 @@ Es gratis. apps/client/src/app/pages/pricing/pricing-page.html - 349 + 345 @@ -3855,15 +3855,15 @@ Renovar Plan apps/client/src/app/components/header/header.component.html - 191 + 185 apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + 18 apps/client/src/app/pages/pricing/pricing-page.html - 316 + 310 @@ -4895,7 +4895,7 @@ apps/client/src/app/pages/pricing/pricing-page.html - 346 + 342 @@ -7104,7 +7104,7 @@ No auto-renewal. apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + 70 diff --git a/apps/client/src/locales/messages.fr.xlf b/apps/client/src/locales/messages.fr.xlf index 8dcadc4d5..da9e9e620 100644 --- a/apps/client/src/locales/messages.fr.xlf +++ b/apps/client/src/locales/messages.fr.xlf @@ -1014,7 +1014,7 @@ apps/client/src/app/components/header/header.component.html - 229 + 225 @@ -1042,7 +1042,7 @@ apps/client/src/app/components/header/header.component.html - 263 + 259 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1130,7 +1130,7 @@ apps/client/src/app/components/header/header.component.html - 245 + 241 @@ -1142,7 +1142,7 @@ apps/client/src/app/components/header/header.component.html - 255 + 251 @@ -1154,7 +1154,7 @@ apps/client/src/app/components/header/header.component.html - 279 + 275 @@ -1170,7 +1170,7 @@ apps/client/src/app/components/header/header.component.html - 291 + 287 apps/client/src/app/pages/resources/overview/resources-overview.component.html @@ -1190,11 +1190,11 @@ apps/client/src/app/components/header/header.component.html - 303 + 299 apps/client/src/app/components/header/header.component.html - 379 + 375 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -1214,7 +1214,7 @@ apps/client/src/app/components/header/header.component.html - 364 + 360 @@ -1222,7 +1222,7 @@ Moi apps/client/src/app/components/header/header.component.html - 211 + 207 @@ -1230,7 +1230,7 @@ Mon Ghostfolio apps/client/src/app/components/header/header.component.html - 270 + 266 @@ -1238,7 +1238,7 @@ À propos de Ghostfolio apps/client/src/app/components/header/header.component.html - 316 + 312 apps/client/src/app/pages/about/overview/about-overview-page.html @@ -1254,7 +1254,7 @@ apps/client/src/app/components/header/header.component.html - 351 + 347 apps/client/src/app/pages/features/features-page.html @@ -1270,7 +1270,7 @@ apps/client/src/app/components/header/header.component.html - 398 + 394 apps/client/src/app/components/home-market/home-market.html @@ -1286,7 +1286,7 @@ Se connecter apps/client/src/app/components/header/header.component.html - 412 + 408 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1298,7 +1298,7 @@ Démarrer apps/client/src/app/components/header/header.component.html - 422 + 418 @@ -1938,7 +1938,7 @@ par an apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + 32 apps/client/src/app/pages/pricing/pricing-page.html @@ -1950,7 +1950,7 @@ Essayer Premium apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + 49 @@ -1958,7 +1958,7 @@ Utiliser un Code Promotionnel apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + 63 @@ -3562,7 +3562,7 @@ Mettre à niveau l’Abonnement apps/client/src/app/components/header/header.component.html - 185 + 187 apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html @@ -3570,11 +3570,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + 20 apps/client/src/app/pages/pricing/pricing-page.html - 310 + 312 @@ -3686,7 +3686,7 @@ Paiement unique, sans auto-renouvellement. apps/client/src/app/pages/pricing/pricing-page.html - 320 + 316 @@ -3702,7 +3702,7 @@ C’est gratuit. apps/client/src/app/pages/pricing/pricing-page.html - 349 + 345 @@ -3854,15 +3854,15 @@ Renouveler l’Abonnement apps/client/src/app/components/header/header.component.html - 191 + 185 apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + 18 apps/client/src/app/pages/pricing/pricing-page.html - 316 + 310 @@ -4894,7 +4894,7 @@ apps/client/src/app/pages/pricing/pricing-page.html - 346 + 342 @@ -7103,7 +7103,7 @@ Pas de renouvellement automatique. apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + 70 diff --git a/apps/client/src/locales/messages.it.xlf b/apps/client/src/locales/messages.it.xlf index 5e5454964..cf6eba907 100644 --- a/apps/client/src/locales/messages.it.xlf +++ b/apps/client/src/locales/messages.it.xlf @@ -755,7 +755,7 @@ apps/client/src/app/components/header/header.component.html - 229 + 225 @@ -799,7 +799,7 @@ apps/client/src/app/components/header/header.component.html - 245 + 241 @@ -811,7 +811,7 @@ apps/client/src/app/components/header/header.component.html - 255 + 251 @@ -831,7 +831,7 @@ apps/client/src/app/components/header/header.component.html - 263 + 259 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -851,7 +851,7 @@ apps/client/src/app/components/header/header.component.html - 279 + 275 @@ -867,7 +867,7 @@ apps/client/src/app/components/header/header.component.html - 291 + 287 apps/client/src/app/pages/resources/overview/resources-overview.component.html @@ -887,11 +887,11 @@ apps/client/src/app/components/header/header.component.html - 303 + 299 apps/client/src/app/components/header/header.component.html - 379 + 375 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -911,7 +911,7 @@ apps/client/src/app/components/header/header.component.html - 364 + 360 @@ -919,7 +919,7 @@ Io apps/client/src/app/components/header/header.component.html - 211 + 207 @@ -927,7 +927,7 @@ Il mio Ghostfolio apps/client/src/app/components/header/header.component.html - 270 + 266 @@ -935,7 +935,7 @@ Informazioni su Ghostfolio apps/client/src/app/components/header/header.component.html - 316 + 312 apps/client/src/app/pages/about/overview/about-overview-page.html @@ -951,7 +951,7 @@ apps/client/src/app/components/header/header.component.html - 351 + 347 apps/client/src/app/pages/features/features-page.html @@ -967,7 +967,7 @@ apps/client/src/app/components/header/header.component.html - 398 + 394 apps/client/src/app/components/home-market/home-market.html @@ -1119,7 +1119,7 @@ Accedi apps/client/src/app/components/header/header.component.html - 412 + 408 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1683,7 +1683,7 @@ per anno apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + 32 apps/client/src/app/pages/pricing/pricing-page.html @@ -1695,7 +1695,7 @@ Prova Premium apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + 49 @@ -1703,7 +1703,7 @@ Riscatta il buono apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + 63 @@ -2583,7 +2583,7 @@ Inizia apps/client/src/app/components/header/header.component.html - 422 + 418 @@ -3563,7 +3563,7 @@ Aggiorna il piano apps/client/src/app/components/header/header.component.html - 185 + 187 apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html @@ -3571,11 +3571,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + 20 apps/client/src/app/pages/pricing/pricing-page.html - 310 + 312 @@ -3687,7 +3687,7 @@ Pagamento una tantum, senza rinnovo automatico. apps/client/src/app/pages/pricing/pricing-page.html - 320 + 316 @@ -3703,7 +3703,7 @@ È gratuito. apps/client/src/app/pages/pricing/pricing-page.html - 349 + 345 @@ -3855,15 +3855,15 @@ Rinnova il piano apps/client/src/app/components/header/header.component.html - 191 + 185 apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + 18 apps/client/src/app/pages/pricing/pricing-page.html - 316 + 310 @@ -4895,7 +4895,7 @@ apps/client/src/app/pages/pricing/pricing-page.html - 346 + 342 @@ -7104,7 +7104,7 @@ No rinnovo automatico. apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + 70 diff --git a/apps/client/src/locales/messages.nl.xlf b/apps/client/src/locales/messages.nl.xlf index 08ec8b508..29008f66c 100644 --- a/apps/client/src/locales/messages.nl.xlf +++ b/apps/client/src/locales/messages.nl.xlf @@ -754,7 +754,7 @@ apps/client/src/app/components/header/header.component.html - 229 + 225 @@ -798,7 +798,7 @@ apps/client/src/app/components/header/header.component.html - 245 + 241 @@ -810,7 +810,7 @@ apps/client/src/app/components/header/header.component.html - 255 + 251 @@ -830,7 +830,7 @@ apps/client/src/app/components/header/header.component.html - 263 + 259 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -850,7 +850,7 @@ apps/client/src/app/components/header/header.component.html - 279 + 275 @@ -866,7 +866,7 @@ apps/client/src/app/components/header/header.component.html - 291 + 287 apps/client/src/app/pages/resources/overview/resources-overview.component.html @@ -886,11 +886,11 @@ apps/client/src/app/components/header/header.component.html - 303 + 299 apps/client/src/app/components/header/header.component.html - 379 + 375 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -910,7 +910,7 @@ apps/client/src/app/components/header/header.component.html - 364 + 360 @@ -918,7 +918,7 @@ Ik apps/client/src/app/components/header/header.component.html - 211 + 207 @@ -926,7 +926,7 @@ Mijn Ghostfolio apps/client/src/app/components/header/header.component.html - 270 + 266 @@ -934,7 +934,7 @@ Over Ghostfolio apps/client/src/app/components/header/header.component.html - 316 + 312 apps/client/src/app/pages/about/overview/about-overview-page.html @@ -950,7 +950,7 @@ apps/client/src/app/components/header/header.component.html - 351 + 347 apps/client/src/app/pages/features/features-page.html @@ -966,7 +966,7 @@ apps/client/src/app/components/header/header.component.html - 398 + 394 apps/client/src/app/components/home-market/home-market.html @@ -1118,7 +1118,7 @@ Aanmelden apps/client/src/app/components/header/header.component.html - 412 + 408 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1682,7 +1682,7 @@ per jaar apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + 32 apps/client/src/app/pages/pricing/pricing-page.html @@ -1694,7 +1694,7 @@ Probeer Premium apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + 49 @@ -1702,7 +1702,7 @@ Coupon inwisselen apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + 63 @@ -2582,7 +2582,7 @@ Aan de slag apps/client/src/app/components/header/header.component.html - 422 + 418 @@ -3562,7 +3562,7 @@ Abonnement uitbreiden apps/client/src/app/components/header/header.component.html - 185 + 187 apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html @@ -3570,11 +3570,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + 20 apps/client/src/app/pages/pricing/pricing-page.html - 310 + 312 @@ -3686,7 +3686,7 @@ Eenmalige betaling, geen automatische verlenging. apps/client/src/app/pages/pricing/pricing-page.html - 320 + 316 @@ -3702,7 +3702,7 @@ Het is gratis. apps/client/src/app/pages/pricing/pricing-page.html - 349 + 345 @@ -3854,15 +3854,15 @@ Abonnement Vernieuwen apps/client/src/app/components/header/header.component.html - 191 + 185 apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + 18 apps/client/src/app/pages/pricing/pricing-page.html - 316 + 310 @@ -4894,7 +4894,7 @@ apps/client/src/app/pages/pricing/pricing-page.html - 346 + 342 @@ -7103,7 +7103,7 @@ No auto-renewal. apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + 70 diff --git a/apps/client/src/locales/messages.pl.xlf b/apps/client/src/locales/messages.pl.xlf index 1af9108c3..a888e4074 100644 --- a/apps/client/src/locales/messages.pl.xlf +++ b/apps/client/src/locales/messages.pl.xlf @@ -507,7 +507,7 @@ apps/client/src/app/components/header/header.component.html - 398 + 394 apps/client/src/app/components/home-market/home-market.html @@ -531,7 +531,7 @@ apps/client/src/app/components/header/header.component.html - 291 + 287 apps/client/src/app/pages/resources/overview/resources-overview.component.html @@ -551,7 +551,7 @@ apps/client/src/app/components/header/header.component.html - 364 + 360 @@ -671,7 +671,7 @@ apps/client/src/app/components/header/header.component.html - 351 + 347 apps/client/src/app/pages/features/features-page.html @@ -715,11 +715,11 @@ apps/client/src/app/components/header/header.component.html - 303 + 299 apps/client/src/app/components/header/header.component.html - 379 + 375 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -1963,7 +1963,7 @@ apps/client/src/app/components/header/header.component.html - 263 + 259 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -2179,7 +2179,7 @@ apps/client/src/app/components/header/header.component.html - 245 + 241 @@ -2191,7 +2191,7 @@ apps/client/src/app/components/header/header.component.html - 255 + 251 @@ -2203,7 +2203,7 @@ apps/client/src/app/components/header/header.component.html - 279 + 275 @@ -2211,7 +2211,7 @@ Ja apps/client/src/app/components/header/header.component.html - 211 + 207 @@ -2223,7 +2223,7 @@ apps/client/src/app/components/header/header.component.html - 229 + 225 @@ -2231,7 +2231,7 @@ Moje Ghostfolio apps/client/src/app/components/header/header.component.html - 270 + 266 @@ -2239,7 +2239,7 @@ O Ghostfolio apps/client/src/app/components/header/header.component.html - 316 + 312 apps/client/src/app/pages/about/overview/about-overview-page.html @@ -2251,7 +2251,7 @@ Zaloguj się apps/client/src/app/components/header/header.component.html - 412 + 408 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -2263,7 +2263,7 @@ Rozpocznij apps/client/src/app/components/header/header.component.html - 422 + 418 @@ -2911,7 +2911,7 @@ Ulepsz Plan apps/client/src/app/components/header/header.component.html - 185 + 187 apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html @@ -2919,11 +2919,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + 20 apps/client/src/app/pages/pricing/pricing-page.html - 310 + 312 @@ -3047,7 +3047,7 @@ rocznie apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + 32 apps/client/src/app/pages/pricing/pricing-page.html @@ -3059,7 +3059,7 @@ Wypróbuj Premium apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + 49 @@ -3067,7 +3067,7 @@ Wykorzystaj kupon apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + 63 @@ -3807,7 +3807,7 @@ apps/client/src/app/pages/pricing/pricing-page.html - 346 + 342 @@ -4967,15 +4967,15 @@ Odnów Plan apps/client/src/app/components/header/header.component.html - 191 + 185 apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + 18 apps/client/src/app/pages/pricing/pricing-page.html - 316 + 310 @@ -4983,7 +4983,7 @@ Płatność jednorazowa, bez automatycznego odnawiania. apps/client/src/app/pages/pricing/pricing-page.html - 320 + 316 @@ -4999,7 +4999,7 @@ Jest bezpłatny. apps/client/src/app/pages/pricing/pricing-page.html - 349 + 345 @@ -7103,7 +7103,7 @@ Bez automatycznego odnawiania. apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + 70 diff --git a/apps/client/src/locales/messages.pt.xlf b/apps/client/src/locales/messages.pt.xlf index e33e05fde..bebd4a752 100644 --- a/apps/client/src/locales/messages.pt.xlf +++ b/apps/client/src/locales/messages.pt.xlf @@ -886,7 +886,7 @@ apps/client/src/app/components/header/header.component.html - 229 + 225 @@ -914,7 +914,7 @@ apps/client/src/app/components/header/header.component.html - 263 + 259 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1002,7 +1002,7 @@ apps/client/src/app/components/header/header.component.html - 245 + 241 @@ -1014,7 +1014,7 @@ apps/client/src/app/components/header/header.component.html - 255 + 251 @@ -1026,7 +1026,7 @@ apps/client/src/app/components/header/header.component.html - 279 + 275 @@ -1042,7 +1042,7 @@ apps/client/src/app/components/header/header.component.html - 291 + 287 apps/client/src/app/pages/resources/overview/resources-overview.component.html @@ -1062,11 +1062,11 @@ apps/client/src/app/components/header/header.component.html - 303 + 299 apps/client/src/app/components/header/header.component.html - 379 + 375 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -1086,7 +1086,7 @@ apps/client/src/app/components/header/header.component.html - 364 + 360 @@ -1094,7 +1094,7 @@ Eu apps/client/src/app/components/header/header.component.html - 211 + 207 @@ -1102,7 +1102,7 @@ O meu Ghostfolio apps/client/src/app/components/header/header.component.html - 270 + 266 @@ -1110,7 +1110,7 @@ Sobre o Ghostfolio apps/client/src/app/components/header/header.component.html - 316 + 312 apps/client/src/app/pages/about/overview/about-overview-page.html @@ -1126,7 +1126,7 @@ apps/client/src/app/components/header/header.component.html - 351 + 347 apps/client/src/app/pages/features/features-page.html @@ -1142,7 +1142,7 @@ apps/client/src/app/components/header/header.component.html - 398 + 394 apps/client/src/app/components/home-market/home-market.html @@ -1158,7 +1158,7 @@ Iniciar sessão apps/client/src/app/components/header/header.component.html - 412 + 408 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1170,7 +1170,7 @@ Começar apps/client/src/app/components/header/header.component.html - 422 + 418 @@ -1922,7 +1922,7 @@ por ano apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + 32 apps/client/src/app/pages/pricing/pricing-page.html @@ -1934,7 +1934,7 @@ Experimentar Premium apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + 49 @@ -1942,7 +1942,7 @@ Resgatar Cupão apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + 63 @@ -3562,7 +3562,7 @@ Atualizar Plano apps/client/src/app/components/header/header.component.html - 185 + 187 apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html @@ -3570,11 +3570,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + 20 apps/client/src/app/pages/pricing/pricing-page.html - 310 + 312 @@ -3686,7 +3686,7 @@ Pagamento único, sem renovação automática. apps/client/src/app/pages/pricing/pricing-page.html - 320 + 316 @@ -3702,7 +3702,7 @@ É gratuito. apps/client/src/app/pages/pricing/pricing-page.html - 349 + 345 @@ -3854,15 +3854,15 @@ Renovar Plano apps/client/src/app/components/header/header.component.html - 191 + 185 apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + 18 apps/client/src/app/pages/pricing/pricing-page.html - 316 + 310 @@ -4894,7 +4894,7 @@ apps/client/src/app/pages/pricing/pricing-page.html - 346 + 342 @@ -7103,7 +7103,7 @@ No auto-renewal. apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + 70 diff --git a/apps/client/src/locales/messages.tr.xlf b/apps/client/src/locales/messages.tr.xlf index bb60cb18b..424924dd6 100644 --- a/apps/client/src/locales/messages.tr.xlf +++ b/apps/client/src/locales/messages.tr.xlf @@ -479,7 +479,7 @@ apps/client/src/app/components/header/header.component.html - 398 + 394 apps/client/src/app/components/home-market/home-market.html @@ -503,7 +503,7 @@ apps/client/src/app/components/header/header.component.html - 291 + 287 apps/client/src/app/pages/resources/overview/resources-overview.component.html @@ -523,7 +523,7 @@ apps/client/src/app/components/header/header.component.html - 364 + 360 @@ -643,7 +643,7 @@ apps/client/src/app/components/header/header.component.html - 351 + 347 apps/client/src/app/pages/features/features-page.html @@ -687,11 +687,11 @@ apps/client/src/app/components/header/header.component.html - 303 + 299 apps/client/src/app/components/header/header.component.html - 379 + 375 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -1867,7 +1867,7 @@ apps/client/src/app/components/header/header.component.html - 263 + 259 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -1927,7 +1927,7 @@ apps/client/src/app/components/header/header.component.html - 229 + 225 @@ -2039,7 +2039,7 @@ apps/client/src/app/components/header/header.component.html - 245 + 241 @@ -2051,7 +2051,7 @@ apps/client/src/app/components/header/header.component.html - 255 + 251 @@ -2063,7 +2063,7 @@ apps/client/src/app/components/header/header.component.html - 279 + 275 @@ -2071,7 +2071,7 @@ Ben apps/client/src/app/components/header/header.component.html - 211 + 207 @@ -2079,7 +2079,7 @@ Ghostfolio’m apps/client/src/app/components/header/header.component.html - 270 + 266 @@ -2087,7 +2087,7 @@ Ghostfolio Hakkında apps/client/src/app/components/header/header.component.html - 316 + 312 apps/client/src/app/pages/about/overview/about-overview-page.html @@ -2099,7 +2099,7 @@ Giriş apps/client/src/app/components/header/header.component.html - 412 + 408 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -2111,7 +2111,7 @@ Haydi Başlayalım apps/client/src/app/components/header/header.component.html - 422 + 418 @@ -2751,7 +2751,7 @@ Üyeliğinizi Yükseltin apps/client/src/app/components/header/header.component.html - 185 + 187 apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html @@ -2759,11 +2759,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + 20 apps/client/src/app/pages/pricing/pricing-page.html - 310 + 312 @@ -3339,7 +3339,7 @@ apps/client/src/app/pages/pricing/pricing-page.html - 346 + 342 @@ -4431,15 +4431,15 @@ Aboneliği Yenile apps/client/src/app/components/header/header.component.html - 191 + 185 apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + 18 apps/client/src/app/pages/pricing/pricing-page.html - 316 + 310 @@ -4447,7 +4447,7 @@ Tek seferlik ödeme, otomatik yenileme yok. apps/client/src/app/pages/pricing/pricing-page.html - 320 + 316 @@ -4463,7 +4463,7 @@ Ücretsiz. apps/client/src/app/pages/pricing/pricing-page.html - 349 + 345 @@ -4963,7 +4963,7 @@ yıllık apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + 32 apps/client/src/app/pages/pricing/pricing-page.html @@ -4975,7 +4975,7 @@ Premium’u Deneyin apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + 49 @@ -4983,7 +4983,7 @@ Kupon Kullan apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + 63 @@ -7103,7 +7103,7 @@ No auto-renewal. apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + 70 diff --git a/apps/client/src/locales/messages.uk.xlf b/apps/client/src/locales/messages.uk.xlf index 24392994e..2141c7727 100644 --- a/apps/client/src/locales/messages.uk.xlf +++ b/apps/client/src/locales/messages.uk.xlf @@ -74,7 +74,7 @@ apps/client/src/app/components/header/header.component.html - 398 + 394 apps/client/src/app/components/home-market/home-market.html @@ -98,7 +98,7 @@ apps/client/src/app/components/header/header.component.html - 291 + 287 apps/client/src/app/pages/resources/overview/resources-overview.component.html @@ -118,7 +118,7 @@ apps/client/src/app/components/header/header.component.html - 364 + 360 @@ -238,7 +238,7 @@ apps/client/src/app/components/header/header.component.html - 351 + 347 apps/client/src/app/pages/features/features-page.html @@ -282,11 +282,11 @@ apps/client/src/app/components/header/header.component.html - 303 + 299 apps/client/src/app/components/header/header.component.html - 379 + 375 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -2119,7 +2119,7 @@ apps/client/src/app/components/header/header.component.html - 263 + 259 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -2319,7 +2319,7 @@ apps/client/src/app/components/header/header.component.html - 229 + 225 @@ -2479,7 +2479,7 @@ apps/client/src/app/components/header/header.component.html - 245 + 241 @@ -2491,7 +2491,7 @@ apps/client/src/app/components/header/header.component.html - 255 + 251 @@ -2503,7 +2503,7 @@ apps/client/src/app/components/header/header.component.html - 279 + 275 @@ -2511,7 +2511,7 @@ Оновити план apps/client/src/app/components/header/header.component.html - 185 + 187 apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html @@ -2519,11 +2519,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + 20 apps/client/src/app/pages/pricing/pricing-page.html - 310 + 312 @@ -2531,15 +2531,15 @@ Поновити план apps/client/src/app/components/header/header.component.html - 191 + 185 apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + 18 apps/client/src/app/pages/pricing/pricing-page.html - 316 + 310 @@ -2547,7 +2547,7 @@ Я apps/client/src/app/components/header/header.component.html - 211 + 207 @@ -2555,7 +2555,7 @@ Мій Ghostfolio apps/client/src/app/components/header/header.component.html - 270 + 266 @@ -2563,7 +2563,7 @@ Про Ghostfolio apps/client/src/app/components/header/header.component.html - 316 + 312 apps/client/src/app/pages/about/overview/about-overview-page.html @@ -2575,7 +2575,7 @@ Увійти apps/client/src/app/components/header/header.component.html - 412 + 408 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -2587,7 +2587,7 @@ Почати apps/client/src/app/components/header/header.component.html - 422 + 418 @@ -3559,7 +3559,7 @@ на рік apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + 32 apps/client/src/app/pages/pricing/pricing-page.html @@ -3571,7 +3571,7 @@ Спробуйте Premium apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + 49 @@ -3579,7 +3579,7 @@ Обміняти купон apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + 63 @@ -3587,7 +3587,7 @@ Без автоматичного поновлення. apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + 70 @@ -4427,7 +4427,7 @@ apps/client/src/app/pages/pricing/pricing-page.html - 346 + 342 @@ -5739,7 +5739,7 @@ Разова оплата, без автоматичного поновлення. apps/client/src/app/pages/pricing/pricing-page.html - 320 + 316 @@ -5747,7 +5747,7 @@ Це безкоштовно. apps/client/src/app/pages/pricing/pricing-page.html - 349 + 345 diff --git a/apps/client/src/locales/messages.xlf b/apps/client/src/locales/messages.xlf index 3b0e161f3..11f35ec57 100644 --- a/apps/client/src/locales/messages.xlf +++ b/apps/client/src/locales/messages.xlf @@ -495,7 +495,7 @@ apps/client/src/app/components/header/header.component.html - 398 + 394 apps/client/src/app/components/home-market/home-market.html @@ -518,7 +518,7 @@ apps/client/src/app/components/header/header.component.html - 291 + 287 apps/client/src/app/pages/resources/overview/resources-overview.component.html @@ -537,7 +537,7 @@ apps/client/src/app/components/header/header.component.html - 364 + 360 @@ -654,7 +654,7 @@ apps/client/src/app/components/header/header.component.html - 351 + 347 apps/client/src/app/pages/features/features-page.html @@ -695,11 +695,11 @@ apps/client/src/app/components/header/header.component.html - 303 + 299 apps/client/src/app/components/header/header.component.html - 379 + 375 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -1885,7 +1885,7 @@ apps/client/src/app/components/header/header.component.html - 263 + 259 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -2078,7 +2078,7 @@ apps/client/src/app/components/header/header.component.html - 245 + 241 @@ -2089,7 +2089,7 @@ apps/client/src/app/components/header/header.component.html - 255 + 251 @@ -2100,14 +2100,14 @@ apps/client/src/app/components/header/header.component.html - 279 + 275 Me apps/client/src/app/components/header/header.component.html - 211 + 207 @@ -2118,21 +2118,21 @@ apps/client/src/app/components/header/header.component.html - 229 + 225 My Ghostfolio apps/client/src/app/components/header/header.component.html - 270 + 266 About Ghostfolio apps/client/src/app/components/header/header.component.html - 316 + 312 apps/client/src/app/pages/about/overview/about-overview-page.html @@ -2143,7 +2143,7 @@ Sign in apps/client/src/app/components/header/header.component.html - 412 + 408 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -2154,7 +2154,7 @@ Get started apps/client/src/app/components/header/header.component.html - 422 + 418 @@ -2740,7 +2740,7 @@ Upgrade Plan apps/client/src/app/components/header/header.component.html - 185 + 187 apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html @@ -2748,11 +2748,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + 20 apps/client/src/app/pages/pricing/pricing-page.html - 310 + 312 @@ -2863,7 +2863,7 @@ per year apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + 32 apps/client/src/app/pages/pricing/pricing-page.html @@ -2874,14 +2874,14 @@ Try Premium apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + 49 Redeem Coupon apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + 63 @@ -3546,7 +3546,7 @@ apps/client/src/app/pages/pricing/pricing-page.html - 346 + 342 @@ -4580,22 +4580,22 @@ Renew Plan apps/client/src/app/components/header/header.component.html - 191 + 185 apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + 18 apps/client/src/app/pages/pricing/pricing-page.html - 316 + 310 One-time payment, no auto-renewal. apps/client/src/app/pages/pricing/pricing-page.html - 320 + 316 @@ -4609,7 +4609,7 @@ It’s free. apps/client/src/app/pages/pricing/pricing-page.html - 349 + 345 @@ -6464,7 +6464,7 @@ No auto-renewal. apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + 70 diff --git a/apps/client/src/locales/messages.zh.xlf b/apps/client/src/locales/messages.zh.xlf index ea776d409..38a4e5e64 100644 --- a/apps/client/src/locales/messages.zh.xlf +++ b/apps/client/src/locales/messages.zh.xlf @@ -508,7 +508,7 @@ apps/client/src/app/components/header/header.component.html - 398 + 394 apps/client/src/app/components/home-market/home-market.html @@ -532,7 +532,7 @@ apps/client/src/app/components/header/header.component.html - 291 + 287 apps/client/src/app/pages/resources/overview/resources-overview.component.html @@ -552,7 +552,7 @@ apps/client/src/app/components/header/header.component.html - 364 + 360 @@ -672,7 +672,7 @@ apps/client/src/app/components/header/header.component.html - 351 + 347 apps/client/src/app/pages/features/features-page.html @@ -716,11 +716,11 @@ apps/client/src/app/components/header/header.component.html - 303 + 299 apps/client/src/app/components/header/header.component.html - 379 + 375 apps/client/src/app/pages/resources/personal-finance-tools/product-page.html @@ -1972,7 +1972,7 @@ apps/client/src/app/components/header/header.component.html - 263 + 259 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -2188,7 +2188,7 @@ apps/client/src/app/components/header/header.component.html - 245 + 241 @@ -2200,7 +2200,7 @@ apps/client/src/app/components/header/header.component.html - 255 + 251 @@ -2212,7 +2212,7 @@ apps/client/src/app/components/header/header.component.html - 279 + 275 @@ -2220,7 +2220,7 @@ apps/client/src/app/components/header/header.component.html - 211 + 207 @@ -2232,7 +2232,7 @@ apps/client/src/app/components/header/header.component.html - 229 + 225 @@ -2240,7 +2240,7 @@ 我的 Ghostfolio apps/client/src/app/components/header/header.component.html - 270 + 266 @@ -2248,7 +2248,7 @@ 关于 Ghostfolio apps/client/src/app/components/header/header.component.html - 316 + 312 apps/client/src/app/pages/about/overview/about-overview-page.html @@ -2260,7 +2260,7 @@ 登入 apps/client/src/app/components/header/header.component.html - 412 + 408 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -2272,7 +2272,7 @@ 开始使用 apps/client/src/app/components/header/header.component.html - 422 + 418 @@ -2920,7 +2920,7 @@ 升级计划 apps/client/src/app/components/header/header.component.html - 185 + 187 apps/client/src/app/components/subscription-interstitial-dialog/subscription-interstitial-dialog.html @@ -2928,11 +2928,11 @@ apps/client/src/app/components/user-account-membership/user-account-membership.html - 18 + 20 apps/client/src/app/pages/pricing/pricing-page.html - 310 + 312 @@ -3056,7 +3056,7 @@ 每年 apps/client/src/app/components/user-account-membership/user-account-membership.html - 36 + 32 apps/client/src/app/pages/pricing/pricing-page.html @@ -3068,7 +3068,7 @@ 尝试高级版 apps/client/src/app/components/user-account-membership/user-account-membership.html - 53 + 49 @@ -3076,7 +3076,7 @@ 兑换优惠券 apps/client/src/app/components/user-account-membership/user-account-membership.html - 67 + 63 @@ -3816,7 +3816,7 @@ apps/client/src/app/pages/pricing/pricing-page.html - 346 + 342 @@ -4976,15 +4976,15 @@ 更新计划 apps/client/src/app/components/header/header.component.html - 191 + 185 apps/client/src/app/components/user-account-membership/user-account-membership.html - 24 + 18 apps/client/src/app/pages/pricing/pricing-page.html - 316 + 310 @@ -4992,7 +4992,7 @@ 一次性付款,无自动续订。 apps/client/src/app/pages/pricing/pricing-page.html - 320 + 316 @@ -5008,7 +5008,7 @@ 免费。 apps/client/src/app/pages/pricing/pricing-page.html - 349 + 345 @@ -7104,7 +7104,7 @@ No auto-renewal. apps/client/src/app/components/user-account-membership/user-account-membership.html - 74 + 70 From 3361666f63f348a23ad24cdb06d3de6d958997da Mon Sep 17 00:00:00 2001 From: csehatt741 <77381875+csehatt741@users.noreply.github.com> Date: Fri, 18 Apr 2025 11:11:49 +0200 Subject: [PATCH 25/62] Feature/activity in custom currency (#4486) * Activity in custom currency * Update changelog --------- Co-authored-by: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> --- CHANGELOG.md | 6 ++ apps/api/src/app/export/export.service.ts | 3 +- apps/api/src/app/import/import.controller.ts | 5 +- apps/api/src/app/import/import.service.ts | 88 ++++--------------- .../order/interfaces/activities.interface.ts | 4 +- apps/api/src/app/order/order.service.ts | 13 ++- .../portfolio-calculator-test-utils.ts | 3 +- .../calculator/portfolio-calculator.ts | 8 +- ...aln-buy-and-sell-in-two-activities.spec.ts | 12 +-- ...folio-calculator-baln-buy-and-sell.spec.ts | 8 +- .../portfolio-calculator-baln-buy.spec.ts | 4 +- ...ator-btcusd-buy-and-sell-partially.spec.ts | 8 +- .../roai/portfolio-calculator-fee.spec.ts | 4 +- .../portfolio-calculator-googl-buy.spec.ts | 4 +- .../roai/portfolio-calculator-item.spec.ts | 4 +- .../portfolio-calculator-liability.spec.ts | 4 +- ...-calculator-msft-buy-with-dividend.spec.ts | 8 +- ...ulator-novn-buy-and-sell-partially.spec.ts | 4 +- ...folio-calculator-novn-buy-and-sell.spec.ts | 4 +- .../src/app/portfolio/portfolio.service.ts | 8 +- ...ate-or-update-activity-dialog.component.ts | 86 +++--------------- .../create-or-update-activity-dialog.html | 74 +--------------- .../app/services/import-activities.service.ts | 3 +- .../activities-table.component.html | 2 +- .../migration.sql | 2 + test/import/ok-btceur.json | 29 ++++++ test/import/ok-btcusd.json | 29 ++++++ 27 files changed, 164 insertions(+), 263 deletions(-) create mode 100644 prisma/migrations/20250401084916_set_value_of_currency_to_null_in_order/migration.sql create mode 100644 test/import/ok-btceur.json create mode 100644 test/import/ok-btcusd.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 0850d7831..043f56390 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Changed + +- Added support for activities in a custom currency + ## 2.152.1 - 2025-04-17 ### Changed diff --git a/apps/api/src/app/export/export.service.ts b/apps/api/src/app/export/export.service.ts index f0449dc14..5efa429c7 100644 --- a/apps/api/src/app/export/export.service.ts +++ b/apps/api/src/app/export/export.service.ts @@ -120,6 +120,7 @@ export class ExportService { ({ accountId, comment, + currency, date, fee, id, @@ -137,7 +138,7 @@ export class ExportService { quantity, type, unitPrice, - currency: SymbolProfile.currency, + currency: currency ?? SymbolProfile.currency, dataSource: SymbolProfile.dataSource, date: date.toISOString(), symbol: ['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes(type) diff --git a/apps/api/src/app/import/import.controller.ts b/apps/api/src/app/import/import.controller.ts index b276a3c3d..15631a3e8 100644 --- a/apps/api/src/app/import/import.controller.ts +++ b/apps/api/src/app/import/import.controller.ts @@ -98,12 +98,9 @@ export class ImportController { @Param('dataSource') dataSource: DataSource, @Param('symbol') symbol: string ): Promise { - const userCurrency = this.request.user.Settings.settings.baseCurrency; - const activities = await this.importService.getDividends({ dataSource, - symbol, - userCurrency + symbol }); return { activities }; diff --git a/apps/api/src/app/import/import.service.ts b/apps/api/src/app/import/import.service.ts index c72420417..babe7c3e3 100644 --- a/apps/api/src/app/import/import.service.ts +++ b/apps/api/src/app/import/import.service.ts @@ -10,12 +10,10 @@ import { PlatformService } from '@ghostfolio/api/app/platform/platform.service'; import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; -import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { DataGatheringService } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.service'; import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service'; import { DATA_GATHERING_QUEUE_PRIORITY_HIGH } from '@ghostfolio/common/config'; import { - DATE_FORMAT, getAssetProfileIdentifier, parseDate } from '@ghostfolio/common/helper'; @@ -29,8 +27,8 @@ import { import { Injectable } from '@nestjs/common'; import { DataSource, Prisma, SymbolProfile } from '@prisma/client'; import { Big } from 'big.js'; -import { endOfToday, format, isAfter, isSameSecond, parseISO } from 'date-fns'; -import { isNumber, uniqBy } from 'lodash'; +import { endOfToday, isAfter, isSameSecond, parseISO } from 'date-fns'; +import { uniqBy } from 'lodash'; import { v4 as uuidv4 } from 'uuid'; @Injectable() @@ -40,7 +38,6 @@ export class ImportService { private readonly configurationService: ConfigurationService, private readonly dataGatheringService: DataGatheringService, private readonly dataProviderService: DataProviderService, - private readonly exchangeRateDataService: ExchangeRateDataService, private readonly orderService: OrderService, private readonly platformService: PlatformService, private readonly portfolioService: PortfolioService, @@ -49,9 +46,8 @@ export class ImportService { public async getDividends({ dataSource, - symbol, - userCurrency - }: AssetProfileIdentifier & { userCurrency: string }): Promise { + symbol + }: AssetProfileIdentifier): Promise { try { const { firstBuyDate, historicalData, orders } = await this.portfolioService.getPosition(dataSource, undefined, symbol); @@ -121,22 +117,16 @@ export class ImportService { currency: undefined, createdAt: undefined, fee: 0, - feeInBaseCurrency: 0, + feeInAssetProfileCurrency: 0, id: assetProfile.id, isDraft: false, SymbolProfile: assetProfile, symbolProfileId: assetProfile.id, type: 'DIVIDEND', unitPrice: marketPrice, + unitPriceInAssetProfileCurrency: marketPrice, updatedAt: undefined, - userId: Account?.userId, - valueInBaseCurrency: - await this.exchangeRateDataService.toCurrencyAtDate( - value, - assetProfile.currency, - userCurrency, - date - ) + userId: Account?.userId }; }) ); @@ -266,17 +256,17 @@ export class ImportService { const activities: Activity[] = []; - for (const [index, activity] of activitiesExtendedWithErrors.entries()) { + for (const activity of activitiesExtendedWithErrors) { const accountId = activity.accountId; const comment = activity.comment; const currency = activity.currency; const date = activity.date; const error = activity.error; - let fee = activity.fee; + const fee = activity.fee; const quantity = activity.quantity; const SymbolProfile = activity.SymbolProfile; const type = activity.type; - let unitPrice = activity.unitPrice; + const unitPrice = activity.unitPrice; const assetProfile = assetProfiles[ getAssetProfileIdentifier({ @@ -284,7 +274,6 @@ export class ImportService { symbol: SymbolProfile.symbol }) ] ?? { - currency: SymbolProfile.currency, dataSource: SymbolProfile.dataSource, symbol: SymbolProfile.symbol }; @@ -320,35 +309,6 @@ export class ImportService { Account?: { id: string; name: string }; }); - if (SymbolProfile.currency !== assetProfile.currency) { - // Convert the unit price and fee to the asset currency if the imported - // activity is in a different currency - unitPrice = await this.exchangeRateDataService.toCurrencyAtDate( - unitPrice, - SymbolProfile.currency, - assetProfile.currency, - date - ); - - if (!isNumber(unitPrice)) { - throw new Error( - `activities.${index} historical exchange rate at ${format( - date, - DATE_FORMAT - )} is not available from "${SymbolProfile.currency}" to "${ - assetProfile.currency - }"` - ); - } - - fee = await this.exchangeRateDataService.toCurrencyAtDate( - fee, - SymbolProfile.currency, - assetProfile.currency, - date - ); - } - if (isDryRun) { order = { comment, @@ -400,6 +360,7 @@ export class ImportService { order = await this.orderService.createOrder({ comment, + currency, date, fee, quantity, @@ -439,21 +400,8 @@ export class ImportService { ...order, error, value, - feeInBaseCurrency: await this.exchangeRateDataService.toCurrencyAtDate( - fee, - assetProfile.currency, - userCurrency, - date - ), // @ts-ignore - SymbolProfile: assetProfile, - valueInBaseCurrency: - await this.exchangeRateDataService.toCurrencyAtDate( - value, - assetProfile.currency, - userCurrency, - date - ) + SymbolProfile: assetProfile }); } @@ -520,7 +468,8 @@ export class ImportService { return ( activity.accountId === accountId && activity.comment === comment && - activity.SymbolProfile.currency === currency && + (activity.currency === currency || + activity.SymbolProfile.currency === currency) && activity.SymbolProfile.dataSource === dataSource && isSameSecond(activity.date, date) && activity.fee === fee && @@ -538,6 +487,7 @@ export class ImportService { return { accountId, comment, + currency, date, error, fee, @@ -545,7 +495,6 @@ export class ImportService { type, unitPrice, SymbolProfile: { - currency, dataSource, symbol, activitiesCount: undefined, @@ -553,6 +502,7 @@ export class ImportService { assetSubClass: undefined, countries: undefined, createdAt: undefined, + currency: undefined, holdings: undefined, id: undefined, isActive: true, @@ -633,12 +583,6 @@ export class ImportService { `activities.${index}.symbol ("${symbol}") is not valid for the specified data source ("${dataSource}")` ); } - - if (assetProfile.currency !== currency) { - throw new Error( - `activities.${index}.currency ("${currency}") does not match with currency of ${assetProfile.symbol} ("${assetProfile.currency}")` - ); - } } assetProfiles[getAssetProfileIdentifier({ dataSource, symbol })] = diff --git a/apps/api/src/app/order/interfaces/activities.interface.ts b/apps/api/src/app/order/interfaces/activities.interface.ts index b16d10b7d..0c25c8ef8 100644 --- a/apps/api/src/app/order/interfaces/activities.interface.ts +++ b/apps/api/src/app/order/interfaces/activities.interface.ts @@ -11,12 +11,12 @@ export interface Activities { export interface Activity extends Order { Account?: AccountWithPlatform; error?: ActivityError; - feeInBaseCurrency: number; + feeInAssetProfileCurrency: number; SymbolProfile?: EnhancedSymbolProfile; tags?: Tag[]; + unitPriceInAssetProfileCurrency: number; updateAccountBalance?: boolean; value: number; - valueInBaseCurrency: number; } export interface ActivityError { diff --git a/apps/api/src/app/order/order.service.ts b/apps/api/src/app/order/order.service.ts index aa5ac4630..c2b822ac9 100644 --- a/apps/api/src/app/order/order.service.ts +++ b/apps/api/src/app/order/order.service.ts @@ -534,18 +534,25 @@ export class OrderService { return { ...order, value, - feeInBaseCurrency: + feeInAssetProfileCurrency: await this.exchangeRateDataService.toCurrencyAtDate( order.fee, + order.currency ?? order.SymbolProfile.currency, order.SymbolProfile.currency, - userCurrency, order.date ), SymbolProfile: assetProfile, + unitPriceInAssetProfileCurrency: + await this.exchangeRateDataService.toCurrencyAtDate( + order.unitPrice, + order.currency ?? order.SymbolProfile.currency, + order.SymbolProfile.currency, + order.date + ), valueInBaseCurrency: await this.exchangeRateDataService.toCurrencyAtDate( value, - order.SymbolProfile.currency, + order.currency ?? order.SymbolProfile.currency, userCurrency, order.date ) diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator-test-utils.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator-test-utils.ts index c5a902c29..2c9f7b6f3 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator-test-utils.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator-test-utils.ts @@ -6,10 +6,11 @@ export const activityDummyData = { comment: undefined, createdAt: new Date(), currency: undefined, - feeInBaseCurrency: undefined, + fee: undefined, id: undefined, isDraft: false, symbolProfileId: undefined, + unitPrice: undefined, updatedAt: new Date(), userId: undefined, value: undefined, diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts index 52d57230b..9698cb315 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts @@ -112,12 +112,12 @@ export abstract class PortfolioCalculator { .map( ({ date, - fee, + feeInAssetProfileCurrency, quantity, SymbolProfile, tags = [], type, - unitPrice + unitPriceInAssetProfileCurrency }) => { if (isBefore(date, dateOfFirstActivity)) { dateOfFirstActivity = date; @@ -134,9 +134,9 @@ export abstract class PortfolioCalculator { tags, type, date: format(date, DATE_FORMAT), - fee: new Big(fee), + fee: new Big(feeInAssetProfileCurrency), quantity: new Big(quantity), - unitPrice: new Big(unitPrice) + unitPrice: new Big(unitPriceInAssetProfileCurrency) }; } ) diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts index e157e2d26..eed5a1e80 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts @@ -91,7 +91,7 @@ describe('PortfolioCalculator', () => { { ...activityDummyData, date: new Date('2021-11-22'), - fee: 1.55, + feeInAssetProfileCurrency: 1.55, quantity: 2, SymbolProfile: { ...symbolProfileDummyData, @@ -101,12 +101,12 @@ describe('PortfolioCalculator', () => { symbol: 'BALN.SW' }, type: 'BUY', - unitPrice: 142.9 + unitPriceInAssetProfileCurrency: 142.9 }, { ...activityDummyData, date: new Date('2021-11-30'), - fee: 1.65, + feeInAssetProfileCurrency: 1.65, quantity: 1, SymbolProfile: { ...symbolProfileDummyData, @@ -116,12 +116,12 @@ describe('PortfolioCalculator', () => { symbol: 'BALN.SW' }, type: 'SELL', - unitPrice: 136.6 + unitPriceInAssetProfileCurrency: 136.6 }, { ...activityDummyData, date: new Date('2021-11-30'), - fee: 0, + feeInAssetProfileCurrency: 0, quantity: 1, SymbolProfile: { ...symbolProfileDummyData, @@ -131,7 +131,7 @@ describe('PortfolioCalculator', () => { symbol: 'BALN.SW' }, type: 'SELL', - unitPrice: 136.6 + unitPriceInAssetProfileCurrency: 136.6 } ]; diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell.spec.ts index a1650ea82..15f3983fe 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell.spec.ts @@ -91,7 +91,7 @@ describe('PortfolioCalculator', () => { { ...activityDummyData, date: new Date('2021-11-22'), - fee: 1.55, + feeInAssetProfileCurrency: 1.55, quantity: 2, SymbolProfile: { ...symbolProfileDummyData, @@ -101,12 +101,12 @@ describe('PortfolioCalculator', () => { symbol: 'BALN.SW' }, type: 'BUY', - unitPrice: 142.9 + unitPriceInAssetProfileCurrency: 142.9 }, { ...activityDummyData, date: new Date('2021-11-30'), - fee: 1.65, + feeInAssetProfileCurrency: 1.65, quantity: 2, SymbolProfile: { ...symbolProfileDummyData, @@ -116,7 +116,7 @@ describe('PortfolioCalculator', () => { symbol: 'BALN.SW' }, type: 'SELL', - unitPrice: 136.6 + unitPriceInAssetProfileCurrency: 136.6 } ]; diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy.spec.ts index 63a4d77b4..7a34bd114 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy.spec.ts @@ -91,7 +91,7 @@ describe('PortfolioCalculator', () => { { ...activityDummyData, date: new Date('2021-11-30'), - fee: 1.55, + feeInAssetProfileCurrency: 1.55, quantity: 2, SymbolProfile: { ...symbolProfileDummyData, @@ -101,7 +101,7 @@ describe('PortfolioCalculator', () => { symbol: 'BALN.SW' }, type: 'BUY', - unitPrice: 136.6 + unitPriceInAssetProfileCurrency: 136.6 } ]; diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts index 2853e3d87..3158076cb 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts @@ -105,7 +105,7 @@ describe('PortfolioCalculator', () => { { ...activityDummyData, date: new Date('2015-01-01'), - fee: 0, + feeInAssetProfileCurrency: 0, quantity: 2, SymbolProfile: { ...symbolProfileDummyData, @@ -115,12 +115,12 @@ describe('PortfolioCalculator', () => { symbol: 'BTCUSD' }, type: 'BUY', - unitPrice: 320.43 + unitPriceInAssetProfileCurrency: 320.43 }, { ...activityDummyData, date: new Date('2017-12-31'), - fee: 0, + feeInAssetProfileCurrency: 0, quantity: 1, SymbolProfile: { ...symbolProfileDummyData, @@ -130,7 +130,7 @@ describe('PortfolioCalculator', () => { symbol: 'BTCUSD' }, type: 'SELL', - unitPrice: 14156.4 + unitPriceInAssetProfileCurrency: 14156.4 } ]; diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts index b96e4f540..22a34af24 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts @@ -91,7 +91,7 @@ describe('PortfolioCalculator', () => { { ...activityDummyData, date: new Date('2021-09-01'), - fee: 49, + feeInAssetProfileCurrency: 49, quantity: 0, SymbolProfile: { ...symbolProfileDummyData, @@ -101,7 +101,7 @@ describe('PortfolioCalculator', () => { symbol: '2c463fb3-af07-486e-adb0-8301b3d72141' }, type: 'FEE', - unitPrice: 0 + unitPriceInAssetProfileCurrency: 0 } ]; diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-googl-buy.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-googl-buy.spec.ts index b3793a5b4..41299eb40 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-googl-buy.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-googl-buy.spec.ts @@ -104,7 +104,7 @@ describe('PortfolioCalculator', () => { { ...activityDummyData, date: new Date('2023-01-03'), - fee: 1, + feeInAssetProfileCurrency: 1, quantity: 1, SymbolProfile: { ...symbolProfileDummyData, @@ -114,7 +114,7 @@ describe('PortfolioCalculator', () => { symbol: 'GOOGL' }, type: 'BUY', - unitPrice: 89.12 + unitPriceInAssetProfileCurrency: 89.12 } ]; diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-item.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-item.spec.ts index d226fe6f8..721c9ae96 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-item.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-item.spec.ts @@ -91,7 +91,7 @@ describe('PortfolioCalculator', () => { { ...activityDummyData, date: new Date('2022-01-01'), - fee: 0, + feeInAssetProfileCurrency: 0, quantity: 1, SymbolProfile: { ...symbolProfileDummyData, @@ -101,7 +101,7 @@ describe('PortfolioCalculator', () => { symbol: 'dac95060-d4f2-4653-a253-2c45e6fb5cde' }, type: 'ITEM', - unitPrice: 500000 + unitPriceInAssetProfileCurrency: 500000 } ]; diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-liability.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-liability.spec.ts index 569212b9a..a82e605d4 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-liability.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-liability.spec.ts @@ -91,7 +91,7 @@ describe('PortfolioCalculator', () => { { ...activityDummyData, date: new Date('2023-01-01'), // Date in future - fee: 0, + feeInAssetProfileCurrency: 0, quantity: 1, SymbolProfile: { ...symbolProfileDummyData, @@ -101,7 +101,7 @@ describe('PortfolioCalculator', () => { symbol: '55196015-1365-4560-aa60-8751ae6d18f8' }, type: 'LIABILITY', - unitPrice: 3000 + unitPriceInAssetProfileCurrency: 3000 } ]; diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts index 4c54ba7aa..d8e774639 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts @@ -104,7 +104,7 @@ describe('PortfolioCalculator', () => { { ...activityDummyData, date: new Date('2021-09-16'), - fee: 19, + feeInAssetProfileCurrency: 19, quantity: 1, SymbolProfile: { ...symbolProfileDummyData, @@ -114,12 +114,12 @@ describe('PortfolioCalculator', () => { symbol: 'MSFT' }, type: 'BUY', - unitPrice: 298.58 + unitPriceInAssetProfileCurrency: 298.58 }, { ...activityDummyData, date: new Date('2021-11-16'), - fee: 0, + feeInAssetProfileCurrency: 0, quantity: 1, SymbolProfile: { ...symbolProfileDummyData, @@ -129,7 +129,7 @@ describe('PortfolioCalculator', () => { symbol: 'MSFT' }, type: 'DIVIDEND', - unitPrice: 0.62 + unitPriceInAssetProfileCurrency: 0.62 } ]; diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell-partially.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell-partially.spec.ts index 84bcc5bc1..ffbfe7345 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell-partially.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell-partially.spec.ts @@ -105,13 +105,15 @@ describe('PortfolioCalculator', () => { ...activityDummyData, ...activity, date: parseDate(activity.date), + feeInAssetProfileCurrency: activity.fee, SymbolProfile: { ...symbolProfileDummyData, currency: activity.currency, dataSource: activity.dataSource, name: 'Novartis AG', symbol: activity.symbol - } + }, + unitPriceInAssetProfileCurrency: activity.unitPrice })); const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts index 937fd8b48..0256a6a1e 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts @@ -105,13 +105,15 @@ describe('PortfolioCalculator', () => { ...activityDummyData, ...activity, date: parseDate(activity.date), + feeInAssetProfileCurrency: activity.fee, SymbolProfile: { ...symbolProfileDummyData, currency: activity.currency, dataSource: activity.dataSource, name: 'Novartis AG', symbol: activity.symbol - } + }, + unitPriceInAssetProfileCurrency: activity.unitPrice })); const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 7287c103b..d3bbc1e06 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -246,10 +246,14 @@ export class PortfolioService { activities: Activity[]; groupBy?: GroupBy; }): Promise { - let dividends = activities.map(({ date, valueInBaseCurrency }) => { + let dividends = activities.map(({ currency, date, value }) => { return { date: format(date, DATE_FORMAT), - investment: valueInBaseCurrency + investment: this.exchangeRateDataService.toCurrency( + value, + currency, + this.getUserCurrency() + ) }; }); diff --git a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts index 555fbc7aa..f6ce2a81d 100644 --- a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.component.ts @@ -15,7 +15,7 @@ import { DateAdapter, MAT_DATE_LOCALE } from '@angular/material/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { AssetClass, AssetSubClass, Tag, Type } from '@prisma/client'; import { isAfter, isToday } from 'date-fns'; -import { EMPTY, Subject, lastValueFrom } from 'rxjs'; +import { EMPTY, Subject } from 'rxjs'; import { catchError, delay, takeUntil } from 'rxjs/operators'; import { DataService } from '../../../../services/data.service'; @@ -102,7 +102,8 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { Validators.required ], currencyOfUnitPrice: [ - this.data.activity?.SymbolProfile?.currency, + this.data.activity?.currency ?? + this.data.activity?.SymbolProfile?.currency, Validators.required ], dataSource: [ @@ -111,7 +112,6 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { ], date: [this.data.activity?.date, Validators.required], fee: [this.data.activity?.fee, Validators.required], - feeInCustomCurrency: [this.data.activity?.fee, Validators.required], name: [this.data.activity?.SymbolProfile?.name, Validators.required], quantity: [this.data.activity?.quantity, Validators.required], searchSymbol: [ @@ -133,10 +133,6 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { ], type: [undefined, Validators.required], // Set after value changes subscription unitPrice: [this.data.activity?.unitPrice, Validators.required], - unitPriceInCustomCurrency: [ - this.data.activity?.unitPrice, - Validators.required - ], updateAccountBalance: [false] }); @@ -148,57 +144,6 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { takeUntil(this.unsubscribeSubject) ) .subscribe(async () => { - let exchangeRateOfUnitPrice = 1; - - this.activityForm.get('feeInCustomCurrency').setErrors(null); - this.activityForm.get('unitPriceInCustomCurrency').setErrors(null); - - const currency = this.activityForm.get('currency').value; - const currencyOfUnitPrice = this.activityForm.get( - 'currencyOfUnitPrice' - ).value; - const date = this.activityForm.get('date').value; - - if ( - currency && - currencyOfUnitPrice && - currency !== currencyOfUnitPrice && - date - ) { - try { - const { marketPrice } = await lastValueFrom( - this.dataService - .fetchExchangeRateForDate({ - date, - symbol: `${currencyOfUnitPrice}-${currency}` - }) - .pipe(takeUntil(this.unsubscribeSubject)) - ); - - exchangeRateOfUnitPrice = marketPrice; - } catch { - this.activityForm.get('unitPriceInCustomCurrency').setErrors({ - invalid: true - }); - } - } - - const feeInCustomCurrency = - this.activityForm.get('feeInCustomCurrency').value * - exchangeRateOfUnitPrice; - - const unitPriceInCustomCurrency = - this.activityForm.get('unitPriceInCustomCurrency').value * - exchangeRateOfUnitPrice; - - this.activityForm.get('fee').setValue(feeInCustomCurrency, { - emitEvent: false - }); - - this.activityForm.get('unitPrice').setValue(unitPriceInCustomCurrency, { - emitEvent: false - }); - if ( this.activityForm.get('type').value === 'BUY' || this.activityForm.get('type').value === 'FEE' || @@ -265,10 +210,6 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { this.activityForm.get('type').value ) ) { - this.activityForm - .get('dataSource') - .setValue(this.activityForm.get('searchSymbol').value.dataSource); - this.updateSymbol(); } @@ -297,7 +238,7 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { .get('dataSource') .removeValidators(Validators.required); this.activityForm.get('dataSource').updateValueAndValidity(); - this.activityForm.get('feeInCustomCurrency').reset(); + this.activityForm.get('fee').reset(); this.activityForm.get('name').setValidators(Validators.required); this.activityForm.get('name').updateValueAndValidity(); this.activityForm.get('quantity').setValue(1); @@ -331,12 +272,11 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { this.activityForm.get('dataSource').updateValueAndValidity(); if ( - (type === 'FEE' && - this.activityForm.get('feeInCustomCurrency').value === 0) || + (type === 'FEE' && this.activityForm.get('fee').value === 0) || type === 'INTEREST' || type === 'LIABILITY' ) { - this.activityForm.get('feeInCustomCurrency').reset(); + this.activityForm.get('fee').reset(); } this.activityForm.get('name').setValidators(Validators.required); @@ -354,7 +294,7 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { this.activityForm.get('searchSymbol').updateValueAndValidity(); if (type === 'FEE') { - this.activityForm.get('unitPriceInCustomCurrency').setValue(0); + this.activityForm.get('unitPrice').setValue(0); } if ( @@ -410,7 +350,7 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { public applyCurrentMarketPrice() { this.activityForm.patchValue({ currencyOfUnitPrice: this.activityForm.get('currency').value, - unitPriceInCustomCurrency: this.currentMarketPrice + unitPrice: this.currentMarketPrice }); } @@ -496,7 +436,7 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { this.dataService .fetchSymbolItem({ - dataSource: this.activityForm.get('dataSource').value, + dataSource: this.activityForm.get('searchSymbol').value.dataSource, symbol: this.activityForm.get('searchSymbol').value.symbol }) .pipe( @@ -512,9 +452,11 @@ export class CreateOrUpdateActivityDialog implements OnDestroy { takeUntil(this.unsubscribeSubject) ) .subscribe(({ currency, dataSource, marketPrice }) => { - this.activityForm.get('currency').setValue(currency); - this.activityForm.get('currencyOfUnitPrice').setValue(currency); - this.activityForm.get('dataSource').setValue(dataSource); + if (this.mode === 'create') { + this.activityForm.get('currency').setValue(currency); + this.activityForm.get('currencyOfUnitPrice').setValue(currency); + this.activityForm.get('dataSource').setValue(dataSource); + } this.currentMarketPrice = marketPrice; diff --git a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html index 85fcf5a94..b0521530f 100644 --- a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html +++ b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html @@ -214,11 +214,7 @@ } } - +

- @if ( - activityForm.get('unitPriceInCustomCurrency').hasError('invalid') - ) { - Oops! Could not get the historical exchange rate - from - {{ - activityForm.get('date')?.value | date: defaultDateFormat - }} - } @if ( currentMarketPrice && @@ -263,36 +246,6 @@ } -
- - - @switch (activityForm.get('type')?.value) { - @case ('DIVIDEND') { - Dividend - } - @case ('FEE') { - Value - } - @case ('INTEREST') { - Value - } - @case ('ITEM') { - Value - } - @case ('LIABILITY') { - Value - } - @default { - Unit Price - } - } - - - {{ - activityForm.get('currency').value - }} - -
Fee - +
{{ activityForm.get('currencyOfUnitPrice').value }}
- @if (activityForm.get('feeInCustomCurrency').hasError('invalid')) { - Oops! Could not get the historical exchange rate - from - {{ - activityForm.get('date')?.value | date: defaultDateFormat - }} - } - -
-
- - Fee - - {{ - activityForm.get('currency').value - }}
@@ -392,7 +325,8 @@ [isCurrency]="true" [locale]="data.user?.settings?.locale" [unit]=" - activityForm.get('currency')?.value ?? data.user?.settings?.baseCurrency + activityForm.get('currencyOfUnitPrice')?.value ?? + data.user?.settings?.baseCurrency " [value]="total" /> diff --git a/apps/client/src/app/services/import-activities.service.ts b/apps/client/src/app/services/import-activities.service.ts index c1b2209b3..2164bd248 100644 --- a/apps/client/src/app/services/import-activities.service.ts +++ b/apps/client/src/app/services/import-activities.service.ts @@ -126,6 +126,7 @@ export class ImportActivitiesService { private convertToCreateOrderDto({ accountId, comment, + currency, date, fee, quantity, @@ -142,7 +143,7 @@ export class ImportActivitiesService { type, unitPrice, updateAccountBalance, - currency: SymbolProfile.currency, + currency: currency ?? SymbolProfile.currency, dataSource: SymbolProfile.dataSource, date: date.toString(), symbol: SymbolProfile.symbol diff --git a/libs/ui/src/lib/activities-table/activities-table.component.html b/libs/ui/src/lib/activities-table/activities-table.component.html index e5b33efd2..79a7d3417 100644 --- a/libs/ui/src/lib/activities-table/activities-table.component.html +++ b/libs/ui/src/lib/activities-table/activities-table.component.html @@ -280,7 +280,7 @@ class="d-none d-lg-table-cell px-1" mat-cell > - {{ element.SymbolProfile?.currency }} + {{ element.currency ?? element.SymbolProfile?.currency }} diff --git a/prisma/migrations/20250401084916_set_value_of_currency_to_null_in_order/migration.sql b/prisma/migrations/20250401084916_set_value_of_currency_to_null_in_order/migration.sql new file mode 100644 index 000000000..03a4e7178 --- /dev/null +++ b/prisma/migrations/20250401084916_set_value_of_currency_to_null_in_order/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +UPDATE "Order" SET "currency" = NULL; diff --git a/test/import/ok-btceur.json b/test/import/ok-btceur.json new file mode 100644 index 000000000..b370682f9 --- /dev/null +++ b/test/import/ok-btceur.json @@ -0,0 +1,29 @@ +{ + "meta": { + "date": "2021-12-12T00:00:00.000Z", + "version": "dev" + }, + "accounts": [], + "platforms": [], + "tags": [], + "activities": [ + { + "accountId": null, + "comment": null, + "fee": 3.94, + "quantity": 1, + "type": "BUY", + "unitPrice": 39378.5, + "currency": "EUR", + "dataSource": "YAHOO", + "date": "2021-12-12T00:00:00.000Z", + "symbol": "BTCUSD", + "tags": [] + } + ], + "user": { + "settings": { + "currency": "USD" + } + } +} diff --git a/test/import/ok-btcusd.json b/test/import/ok-btcusd.json new file mode 100644 index 000000000..fc2e1f66e --- /dev/null +++ b/test/import/ok-btcusd.json @@ -0,0 +1,29 @@ +{ + "meta": { + "date": "2021-12-12T00:00:00.000Z", + "version": "dev" + }, + "accounts": [], + "platforms": [], + "tags": [], + "activities": [ + { + "accountId": null, + "comment": null, + "fee": 4.46, + "quantity": 1, + "type": "BUY", + "unitPrice": 44558.42, + "currency": "USD", + "dataSource": "YAHOO", + "date": "2021-12-12T00:00:00.000Z", + "symbol": "BTCUSD", + "tags": [] + } + ], + "user": { + "settings": { + "currency": "USD" + } + } +} From edf03d1cd620684be22f36411a7005ac3f51bf03 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 18 Apr 2025 11:13:12 +0200 Subject: [PATCH 26/62] Feature/upgrade chart.js to version 4.4.9 (#4547) * Upgrade chart.js to version 4.4.9 * Update changelog --- CHANGELOG.md | 1 + package-lock.json | 8 ++++---- package.json | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 043f56390..8f1569993 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Added support for activities in a custom currency +- Upgraded `chart.js` from version `4.4.7` to `4.4.9` ## 2.152.1 - 2025-04-17 diff --git a/package-lock.json b/package-lock.json index 827033432..43a2e649b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51,7 +51,7 @@ "bull": "4.16.5", "cache-manager": "5.7.6", "cache-manager-redis-yet": "5.1.4", - "chart.js": "4.4.7", + "chart.js": "4.4.9", "chartjs-adapter-date-fns": "3.0.0", "chartjs-chart-treemap": "3.1.0", "chartjs-plugin-annotation": "3.1.0", @@ -14800,9 +14800,9 @@ "license": "MIT" }, "node_modules/chart.js": { - "version": "4.4.7", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.7.tgz", - "integrity": "sha512-pwkcKfdzTMAU/+jNosKhNL2bHtJc/sSmYgVbuGTEDhzkrhmyihmP7vUc/5ZK9WopidMDHNe3Wm7jOd/WhuHWuw==", + "version": "4.4.9", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.9.tgz", + "integrity": "sha512-EyZ9wWKgpAU0fLJ43YAEIF8sr5F2W3LqbS40ZJyHIner2lY14ufqv2VMp69MAiZ2rpwxEUxEhIH/0U3xyRynxg==", "license": "MIT", "dependencies": { "@kurkle/color": "^0.3.0" diff --git a/package.json b/package.json index 81c48066d..5fc4aa103 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "bull": "4.16.5", "cache-manager": "5.7.6", "cache-manager-redis-yet": "5.1.4", - "chart.js": "4.4.7", + "chart.js": "4.4.9", "chartjs-adapter-date-fns": "3.0.0", "chartjs-chart-treemap": "3.1.0", "chartjs-plugin-annotation": "3.1.0", From 13643f578a7bbd6ba23614ad6901d92a356190fe Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 18 Apr 2025 11:14:26 +0200 Subject: [PATCH 27/62] Feature/upgrade uuid to version 11.1.0 (#4552) * Upgrade uuid to version 11.1.0 * Update changelog --- CHANGELOG.md | 1 + package-lock.json | 8 ++++---- package.json | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f1569993..ddcf441c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added support for activities in a custom currency - Upgraded `chart.js` from version `4.4.7` to `4.4.9` +- Upgraded `uuid` from version `11.0.5` to `11.1.0` ## 2.152.1 - 2025-04-17 diff --git a/package-lock.json b/package-lock.json index 43a2e649b..8868e11c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -89,7 +89,7 @@ "stripe": "17.3.0", "svgmap": "2.12.2", "twitter-api-v2": "1.14.2", - "uuid": "11.0.5", + "uuid": "11.1.0", "yahoo-finance2": "2.11.3", "zone.js": "0.15.0" }, @@ -33015,9 +33015,9 @@ } }, "node_modules/uuid": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.5.tgz", - "integrity": "sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" diff --git a/package.json b/package.json index 5fc4aa103..74ae55585 100644 --- a/package.json +++ b/package.json @@ -135,7 +135,7 @@ "stripe": "17.3.0", "svgmap": "2.12.2", "twitter-api-v2": "1.14.2", - "uuid": "11.0.5", + "uuid": "11.1.0", "yahoo-finance2": "2.11.3", "zone.js": "0.15.0" }, From db388068124a34c56a25e152978e5edcf92b5ea1 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 18 Apr 2025 11:15:51 +0200 Subject: [PATCH 28/62] Feature/refresh cryptocurrencies list 20250417 (#4548) * Update cryptocurrencies.json * Update changelog --- CHANGELOG.md | 1 + .../cryptocurrencies/cryptocurrencies.json | 370 ++++++++++++++++-- 2 files changed, 333 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ddcf441c0..dd111fd7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Added support for activities in a custom currency +- Refreshed the cryptocurrencies list - Upgraded `chart.js` from version `4.4.7` to `4.4.9` - Upgraded `uuid` from version `11.0.5` to `11.1.0` diff --git a/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json b/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json index 6ac25e5d9..475cc6217 100644 --- a/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json +++ b/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json @@ -20,6 +20,7 @@ "2025": "2025 TOKEN", "2049": "TOKEN 2049", "2192": "LERNITAS", + "4444": "4444 Meme", "$MAID": "MaidCoin", "$TREAM": "World Stream Finance", "00": "ZER0ZER0", @@ -63,6 +64,7 @@ "1MIL": "1MillionNFTs", "1MT": "1Move", "1NFT": "1NFT", + "1OZT": "Tala", "1PECO": "1peco", "1SG": "1SG", "1SOL": "1Sol", @@ -116,6 +118,7 @@ "4MW": "For Meta World", "4P": "4P FOUR", "4RZ": "4REALZA COIN", + "4THPILLAR": "4th Pillar Four Token", "4TOKEN": "Ignore Fud", "4WIN": "4TRUMP", "4WMM": "4-Way Mirror Money", @@ -189,6 +192,7 @@ "ABOND": "ApeBond", "ABONDV1": "ApeSwap", "ABR": "Allbridge", + "ABSIMPSON": "abstract simpson", "ABT": "ArcBlock", "ABTC": "aBTC", "ABUL": "Abulaba", @@ -228,6 +232,7 @@ "ACPT": "Crypto Accept", "ACQ": "Acquire.Fi", "ACRE": "Arable Protocol", + "ACRED": "Apollo Diversified Credit Securitize Fund", "ACRIA": "Acria.AI", "ACS": "Access Protocol", "ACSI": "ACryptoSI", @@ -289,6 +294,7 @@ "AEG": "Aether Games", "AEGGS": "aEGGS", "AEGIS": "Aegis", + "AEGS": "Aegisum", "AELIN": "Aelin", "AEN": "Aenco", "AENS": "AEN Smart", @@ -306,6 +312,7 @@ "AETH": "Aave ETH", "AETHC": "Ankr Reward-Bearing Staked ETH", "AETHERV2": "AetherV2", + "AETHRA": "Aethra AI", "AEUR": "Anchored Coins AEUR", "AEVO": "Aevo", "AEVUM": "Aevum", @@ -325,6 +332,7 @@ "AFRO": "Afrostar", "AFROX": "AfroDex", "AFSUI": "Aftermath Staked SUI", + "AFT": "AIFlow Token", "AFTT": "Africa Trading Chain", "AFX": "Afrix", "AFYON": "Afyonspor Fan Token", @@ -353,6 +361,7 @@ "AGLD": "Adventure Gold", "AGM": "Argoneum", "AGN": "Agnus Ai", + "AGNT": "iAgent Protocol", "AGO": "AgoDefi", "AGON": "Arabian Dragon", "AGOV": "Answer Governance", @@ -385,6 +394,7 @@ "AIBK": "AIB Utility Token", "AIBU": "AIBUZZ TOKEN", "AIC": "AI Companions", + "AICE": "Aicean", "AICELL": "AICell", "AICH": "AIChain", "AICO": "AICON", @@ -435,6 +445,7 @@ "AIOS": "INT OS", "AIOT": "AIOT Token", "AIOZ": "AIOZ Network", + "AIP": "AI Protocol", "AIPAD": "AIPAD", "AIPE": "AI Prediction Ecosystem", "AIPEPE": "AI PEPE KING", @@ -446,6 +457,7 @@ "AIRBTC": "AIRBTC", "AIRDROP": "AIRDROP2049", "AIRE": "Tokenaire", + "AIRENE": "AIRENE by Virtuals", "AIREVOLUTION": "AI Revolution Coin", "AIRI": "aiRight", "AIRIAN": "AIRian", @@ -461,6 +473,7 @@ "AITECH": "Artificial Intelligence Utility Token", "AITEK": "AI Technology", "AITHEON": "Aitheon", + "AITHER": "Aither Protocol", "AITIGER": "BNB Tiger AI", "AITK": "AITK", "AITN": "Artificial Intelligence Technology Network", @@ -509,8 +522,10 @@ "ALC": "Arab League Coin", "ALCAZAR": "Alcazar", "ALCE": "Alcedo", - "ALCH": "Alchemy", + "ALCH": "Alchemist AI", "ALCHE": "Alchemist", + "ALCHEMYV1": "Alchemy v1", + "ALCHEMYV2": "Alchemy", "ALCX": "Alchemix", "ALD": "AladdinDAO", "ALDIN": "Alaaddin.ai", @@ -519,6 +534,7 @@ "ALEPH": "Aleph.im", "ALEX": "ALEX Lab", "ALEXANDRITE": "Alexandrite", + "ALEXIUS": "Alexius Maximus", "ALF": "AlphaCoin", "ALG": "Algory", "ALGB": "Algebra", @@ -536,6 +552,7 @@ "ALICEW": "Alice Weidel", "ALIEN": "AlienCoin", "ALIENPEP": "Alien Pepe", + "ALIENS": "Aliens", "ALIF": " ALIF COIN", "ALINK": "Aave LINK v1", "ALIS": "ALISmedia", @@ -630,6 +647,7 @@ "AMP": "Amp", "AMPL": "Ampleforth", "AMPLIFI": "AmpliFi", + "AMR": "Amero", "AMS": "Amsterdam Coin", "AMT": "Acumen", "AMU": "Amulet", @@ -686,6 +704,7 @@ "ANLOG": "Analog", "ANML": "Animal Concerts", "ANN": "Annex Finance", + "ANNE": "ANNE", "ANON": "ANON", "ANONCOIN": "Anoncoin", "ANRX": "AnRKey X", @@ -707,6 +726,7 @@ "ANY": "Anyswap", "ANYONE": "ANyONe Protocol", "ANZENUSD": "Anzen Finance", + "AO": "AO", "AOC": "Alickshundra Occasional-Cortex", "AOG": "AgeOfGods", "AOK": "AOK", @@ -758,6 +778,7 @@ "APS": "APRES", "APT": "Aptos", "APTCOIN": "Aptcoin", + "APTM": "Apertum", "APTOGE": "Aptoge", "APTR": "Aperture Finance", "APU": "Apu Apustaja", @@ -771,6 +792,7 @@ "APY": "APY.Finance", "APYS": "APYSwap", "APZ": "Alprockz", + "AQA": " AQA Token", "AQT": "Alpha Quark Token", "AQTIS": "AQTIS", "AQU": "aQuest", @@ -783,6 +805,7 @@ "AQUARI": "Aquari", "AR": "Arweave", "ARA": "Ara Token", + "ARACOIN": "Ara", "ARATA": "Arata", "ARAW": "Araw", "ARB": "Arbitrum", @@ -858,6 +881,7 @@ "ARPA": "ARPA Chain", "ARPAC": "ArpaCoin", "ARQ": "ArQmA", + "ARQX": "ARQx AI", "ARR": "ARROUND", "ARRO": "Arro Social", "ARRR": "Pirate Chain", @@ -896,6 +920,7 @@ "ASAFE2": "Allsafe", "ASAN": "ASAN VERSE", "ASAP": "Asap Sniper Bot", + "ASBNB": "Astherus Staked BNB", "ASC": "Ascend", "ASD": "AscendEX Token", "ASDEX": "AstraDEX", @@ -909,6 +934,7 @@ "ASIA": "Asia Coin", "ASIMI": "ASIMI", "ASIX": "ASIX+", + "ASIXDEV": "ASIX", "ASK": "Permission Coin", "ASKAI": "ASKAI", "ASKO": "Asko", @@ -947,6 +973,7 @@ "ASTROS": "AstroSwap", "ASTX": "Asterix Labs", "ASUNA": "Asuna Hentai", + "ASUSDF": "Astherus Staked USDF", "ASUSHI": "Sushi (Arbitrum Bridge)", "ASVA": "Asva", "ASW": "AdaSwap", @@ -985,7 +1012,8 @@ "ATMCOIN": "ATM", "ATMI": "Atonomi", "ATMOS": "Novusphere", - "ATN": "ATN", + "ATN": "ATHENE NETWORK", + "ATNIO": "ATN", "ATNT": "Artizen", "ATO": "Atocha Protocol", "ATOLO": "RIZON", @@ -1047,6 +1075,7 @@ "AUX": "Auxilium", "AV": "Avatar Coin", "AVA": "Travala", + "AVAAI": "Ava AI", "AVACN": "AVACOIN", "AVAI": "Orca AVAI", "AVAIL": "Avail", @@ -1067,6 +1096,7 @@ "AVE": "Avesta", "AVEN": "Aventis AI", "AVENT": "Aventa", + "AVERY": "Avery Games", "AVG": "Avocado DAO", "AVH": "Animation Vision Cash", "AVI": "Aviator", @@ -1078,6 +1108,7 @@ "AVN": "AVNRich", "AVO": "Avoteo", "AVR": "Avrora Metaverse", + "AVRK": "Avarik Saga", "AVS": "Aves", "AVT": "Aventus", "AVTM": "Aventis Metaverse", @@ -1141,6 +1172,7 @@ "B": "BankCoin", "B01": "b0rder1ess", "B1P": "B ONE PAYMENT", + "B2": "B² Network", "B20": "B20", "B21": "B21", "B26": "B26 Finance", @@ -1149,6 +1181,7 @@ "B2X": "SegWit2x", "B3": "B3", "B3COIN": "B3 Coin", + "B3TR": "VeBetterDAO", "B3X": "Bnext Token", "B91": "B91", "BA": "BAHA", @@ -1208,6 +1241,8 @@ "BABYKABOSU": "Baby Kabosu", "BABYKEKIUS": "Baby Kekius Maximus", "BABYKITTY": "BabyKitty", + "BABYKOMA": "Baby Koma", + "BABYLON": "Babylon", "BABYLONG": "Baby Long", "BABYM": "BabyMAGA", "BABYMAGA": "Baby Maga", @@ -1216,6 +1251,7 @@ "BABYMIGGLES": "Baby Miggles", "BABYMO": "Baby Moon Floki", "BABYMU": "Baby Musk", + "BABYMUB": "Baby Mubarak", "BABYMUSK": "Baby Musk", "BABYMYRO": "Babymyro", "BABYNEIRO": "Baby Neiro", @@ -1223,6 +1259,7 @@ "BABYOKX": "BABYOKX", "BABYP": "BabyPepe", "BABYPEIPEI": "Baby PeiPei", + "BABYPENGU": "BABY PENGU", "BABYPEPE": "Babypepe (BSC)", "BABYPNUT": "Baby Pnut", "BABYPOPCAT": "Baby PopCat", @@ -1275,6 +1312,7 @@ "BAKED": "Baked", "BAKEDB": "Baked Beans Token", "BAKEDTOKEN": "Baked", + "BAKENEKO": "BAKENEKO", "BAKSO": "Disney Sumatran Tiger", "BAKT": "Backed Protocol", "BAL": "Balancer", @@ -1298,6 +1336,7 @@ "BANANACHARITY": "BANANA", "BANANAF": "Banana For Scale", "BANANAS": "Monkey Peepo", + "BANANAS31": "Banana For Scale", "BANANO": "Banano", "BANC": "Babes and Nerds", "BANCA": "BANCA", @@ -1322,6 +1361,7 @@ "BAOS": "BaoBaoSol", "BAR": "FC Barcelona Fan Token", "BARA": "Capybara", + "BARAKATUH": "Barakatuh", "BARC": "The Blu Arctic Water Company", "BAREBEARS": "BAREBEARS", "BARIO": "Bario", @@ -1338,6 +1378,7 @@ "BASECOIN": "BASECOIN", "BASED": "Based Money", "BASEDAI": "BasedAI", + "BASEDALF": "Based Alf", "BASEDCHILL": "Based Chill Guy", "BASEDCOPE": "COPE", "BASEDFINANCE": "Based", @@ -1398,6 +1439,7 @@ "BBONK": "BitBonk", "BBOS": "Blackbox Foundation", "BBP": "BiblePay", + "BBQ": "BBQ COIN", "BBR": "Boolberry", "BBRETT": "Baby Brett", "BBROCCOLI": "Baby Broccoli", @@ -1477,6 +1519,8 @@ "BDR": "BlueDragon", "BDRM": "Bodrumspor Fan Token", "BDROP": "BlockDrop", + "BDSM": "BTC DOGE SOL MOON", + "BDTC": "BDTCOIN", "BDX": "Beldex", "BDY": "Buddy DAO", "BEA": "Beagle Inu", @@ -1660,6 +1704,7 @@ "BIGFACTS": "BIGFACTS", "BIGFOOT": "BigFoot Town", "BIGHAN": "BighanCoin", + "BIGJIM": "BIG JIM", "BIGLEZ": "THE BIG LEZ SHOW", "BIGMIKE": "Big Mike", "BIGSB": "BigShortBets", @@ -1668,6 +1713,7 @@ "BIH": "BitHostCoin", "BIHU": "Key", "BIIS": "biis (Ordinals)", + "BIKE": "White Bike", "BIKI": "BIKI", "BILL": "TillBilly", "BILLI": "Billi", @@ -1675,6 +1721,8 @@ "BILLY": "Billy ", "BILLYBSC": "BILLY", "BIM": "BitminerCoin", + "BINA": "Binance Mascort Dog", + "BINAN": "Binance Mascot", "BINANCED": "BinanceDog On Sol", "BINANCEDOG": "Binancedog", "BIND": "Compendia", @@ -1759,6 +1807,7 @@ "BITTO": "BITTO", "BITTON": "Bitton", "BITUNE": "Bitune", + "BITUPTOKEN": "BitUP Token", "BITUSD": "bitUSD", "BITV": "Bitvolt", "BITVOLT": "BitVolt", @@ -1823,6 +1872,7 @@ "BLHC": "BlackholeCoin", "BLI": "BALI TOKEN", "BLID": "Bolide", + "BLIFFY": "BLIFFY", "BLIN": "Blin Metaverse", "BLIND": "Blindsight", "BLING": "PLEB DREKE", @@ -1871,6 +1921,7 @@ "BLU": "BlueCoin", "BLUB": "BLUB", "BLUE": "Bluefin", + "BLUEBASE": "Blue", "BLUEBUTT": "BLUE BUTT CHEESE", "BLUEG": "Blue Guy", "BLUEM": "BlueMove", @@ -1901,6 +1952,7 @@ "BMARS": "Binamars", "BMBO": "Bamboo Coin", "BMC": "Blackmoon Crypto", + "BMCHAIN": "BMChain", "BMDA": "Bermuda", "BME": "BitcoMine", "BMEX": "BitMEX", @@ -1915,7 +1967,7 @@ "BMONEY": "B-money", "BMP": "Brother Music Platform", "BMS": "BMS COIN", - "BMT": "BMChain", + "BMT": "Bubblemaps", "BMTC": "Metabit", "BMW": "BMW", "BMWUKONG": "Black Myth WuKong", @@ -1926,8 +1978,10 @@ "BNANA": "Chimpion", "BNB": "Binance Coin", "BNBAI": "BNB Agents", + "BNBAICLUB": "BNB AI Agent", "BNBBONK": "BNB BONK", "BNBBUNNY": "BNB BUNNY", + "BNBCARD": "BNB Card", "BNBCAT": "BNBcat", "BNBCH": "BNB Cash", "BNBD": "BNBDOG", @@ -1935,6 +1989,7 @@ "BNBDOGE": "BNBdoge", "BNBDRGN": "BNBDragon", "BNBE": "BNBEE", + "BNBETF": "BNB ETF", "BNBFLOKI": "BNB FLOKI", "BNBFROG": "BNBFROG", "BNBH": "BnbHeroes Token", @@ -1954,6 +2009,7 @@ "BNF": "BonFi", "BNIX": "BNIX Token", "BNK": "Bankera", + "BNKR": "BankrCoin", "BNN": "Banyan Network", "BNOM": "BitNomad", "BNP": "BenePit", @@ -1996,6 +2052,7 @@ "BOBOT": "Bobo The Bear", "BOBS": "Bob's Repair", "BOBT": "BOB Token", + "BOBTHE": "Bob The Builder", "BOBUKI": "Bobuki Neko", "BOBY": "BOBY", "BOC": "BOCOIN", @@ -2019,6 +2076,8 @@ "BOGE": "Boge", "BOGEY": "Bogey", "BOGGY": "Boggy Coin", + "BOHR": "BOHR", + "BOHRV1": "BOHR v1", "BOJAK": "Based Wojak", "BOJI": "BOJI Token", "BOJIV1": "BOJI Token v1", @@ -2035,6 +2094,7 @@ "BOMA": "Book of Maga", "BOMB": "BOMB", "BOMBC": "BombCoin", + "BOMBLOONG": "Bombloong", "BOMBM": "Bomb Money", "BOMBO": "BOMBO", "BOMBS": "Bomb Shelter Inu", @@ -2085,6 +2145,7 @@ "BOOF": "Boofus by Virtuals", "BOOFI": "Boo Finance", "BOOG": "BOOG base", + "BOOGIE": "Boogie", "BOOK": "Solbook", "BOOKIE": "BookieBot", "BOOKO": "Book of Pets", @@ -2139,7 +2200,7 @@ "BOWE": "Book of Whales", "BOWSC": "BowsCoin", "BOWSER": "Bowser", - "BOX": "ContentBox", + "BOX": "DeBoxToken", "BOXETH": "Cat-in-a-Box Ether", "BOXT": "BOX Token", "BOXX": "Blockparty", @@ -2185,13 +2246,14 @@ "BQQQ": "Bitsdaq Token", "BQT": "Blockchain Quotations Index Token", "BQTX": "BQT", - "BR": "BOHR", + "BR": "Bedrock", "BR34P": "BR34P", "BRACE": "Bitci Racing Token", "BRAI": "Brain Frog", "BRAIN": "BrainCoin", "BRAINERS": "Brainers", "BRAINLET": "Brainlet", + "BRAINROT": "AI Brainrot", "BRAINZ": "Brainz Finance", "BRAM": "Defibox bRAM", "BRANA": "Branaverse", @@ -2453,6 +2515,7 @@ "BTZN": "Bitzon", "BU": "BUMO", "BUB": "BUBCAT", + "BUBB": "Bubb", "BUBBA": "Bubba", "BUBBLE": "Bubble", "BUBBLES": "BUBBLES", @@ -2476,10 +2539,13 @@ "BUGATTI": "BUGATTI", "BUGG": "Bugg Inu", "BUGS": "Bugs Bunny", - "BUIDL": "Starter.xyz", + "BUI": "Build forward", + "BUIDL": "BlackRock USD Institutional Digital Liquidity Fund", + "BUIDLI": "BlackRock USD Institutional Digital Liquidity Fund - I Class", "BUIL": "BUILD", "BUILD": "BuildAI", "BUILDIN": "Buildin Token", + "BUILDON": "Build On BNB", "BUILDTEAM": "BuildTeam", "BUILT": "Built Different", "BUK": "CryptoBuk", @@ -2498,6 +2564,7 @@ "BULLMOON": "Bull Moon", "BULLPEPE": "Bullpepe", "BULLS": "Bull Coin", + "BULLSEYE": "bulls-eye", "BULLSH": "Bullshit Inu", "BULLY": "Dolos The Bully", "BULLYINGCAT": "Bullying Cat", @@ -2530,7 +2597,7 @@ "BUSD": "Binance USD", "BUSDC": "BUSD", "BUSY": "Busy DAO", - "BUT": "BitUP Token", + "BUT": "Bucket Token", "BUTT": "Buttercat", "BUTTCOIN": "The Next Bitcoin", "BUTTHOLE": "Butthole Coin", @@ -2574,6 +2641,7 @@ "BXX": "Baanx", "BXY": "Beaxy", "BYAT": "Byat", + "BYB": "BiorBank", "BYC": "ByteCent", "BYG": "Black Eye Galaxy", "BYT": "ByteAI", @@ -2621,9 +2689,10 @@ "CAG": "Change", "CAGA": "Crypto Asset Governance Alliance", "CAH": "Moon Tropica", - "CAI": "Cai Token", + "CAI": "Chasm", "CAID": "ClearAid", "CAIR": "Crypto-AI-Robo.com", + "CAITOKEN": "Cai Token", "CAIV": "CARVIS", "CAIX": "CAIx", "CAIZ": "Caizcoin", @@ -2636,6 +2705,7 @@ "CALC": "CaliphCoin", "CALI": "CaliCoin", "CALL": "Global Crypto Alliance", + "CALLS": "OnlyCalls by Virtuals", "CALO": "Calo", "CAM": "Consumption Avatar Matrix", "CAMC": "Camcoin", @@ -2832,6 +2902,7 @@ "CCXC": "CoolinDarkCoin", "CCXX": "CounosX", "CDAI": "Compound Dai", + "CDBIO": "CDbio", "CDCETH": "Crypto.com Staked ETH", "CDEX": "Cryptodex", "CDL": "CoinDeal Token", @@ -2915,6 +2986,7 @@ "CHACHA": "Chacha", "CHAD": "Chad Coin", "CHADCAT": "CHAD CAT", + "CHADETTE": "Chadette", "CHADS": "CHADS VC", "CHAI": "Chroma AI", "CHAIN": "Chain Games", @@ -3231,6 +3303,7 @@ "COCONUT": "Coconut", "COCOR": "Cocoro", "COCORO": "Cocoro", + "COCOROERC": "COCORO", "COD": "Chief of Deswamp", "CODA": "CODA", "CODAI": "CODAI", @@ -3280,6 +3353,7 @@ "COLLG": "Collateral Pay Governance", "COLON": "Colon", "COLR": "colR Coin", + "COLS": "Cointel", "COLT": "Collateral Network", "COLX": "ColossusCoinXT", "COM": "Coliseum", @@ -3310,6 +3384,7 @@ "CONK": "ShibaPoconk", "CONS": "ConSpiracy Coin", "CONSENTIUM": "Consentium", + "CONTENTBOX": "ContentBox", "CONTROL": "Control Token", "CONV": "Convergence", "CONVO": "Prefrontal Cortex Convo Agent by Virtuals", @@ -3330,6 +3405,7 @@ "COPYCAT": "Copycat Finance", "COQ": "Coq Inu", "COR": "Coreto", + "CORA": "Cora by Virtuals", "CORAL": "CoralPay", "CORE": "Core", "COREC": "CoreConnect", @@ -3341,11 +3417,13 @@ "CORGIAI": "CorgiAI", "CORGIB": "The Corgi of PolkaBridge", "CORION": "Corion", - "CORN": "CORN", + "CORN": "Corn", "CORNELLA": "CORNELLA", + "CORNFIELDFARM": "CORN", "CORSI": "Cane Corso", "CORTEX": "Cortex Protocol", "CORX": "CorionX", + "CORXB": "CorionX BSC", "COS": "Contentos", "COSHI": "CoShi Inu", "COSM": "CosmoChain", @@ -3430,6 +3508,7 @@ "CRAVE": "CraveCoin", "CRAYRABBIT": "CrazyRabbit", "CRAZ": "CRAZY FLOKI", + "CRAZE": "Craze", "CRAZYB": "Crazy Bunny", "CRAZYBONK": "CRAZY BONK", "CRAZYBUNNY": "Crazy Bunny", @@ -3538,6 +3617,7 @@ "CRYO": "CryoDAO", "CRYP": "CrypticCoin", "CRYPT": "CryptCoin", + "CRYPTAL": "CrypTalk", "CRYPTER": "Crypteriumcoin", "CRYPTOA": "CryptoAI", "CRYPTOAGENT": "CRYPTO AGENT TRUMP", @@ -3590,6 +3670,7 @@ "CSTC": "CryptosTribe", "CSTL": "Castle", "CSTR": "CoreStarter", + "CSUSDL": "Coinshift USDL Morpho Vault", "CSUSHI": "cSUSHI", "CSW": "Crosswalk", "CSWAP": "ChainSwap", @@ -3605,6 +3686,7 @@ "CTEX": "Crypto tex", "CTF": "CyberTime Finance", "CTG": "City Tycoon Games", + "CTH": "Changcoin", "CTI": "ClinTex CTi", "CTIC": "Coinmatic", "CTK": "Shentu", @@ -3659,6 +3741,7 @@ "CURRY": "CurrySwap", "CUSD": "Carbon", "CUSDC": "Compound USD Coin", + "CUSDO": "Compounding Open Dollar", "CUSDT": "cUSDT", "CUSDTBULL": "3X Long Compound USDT Token", "CUST": "Custody Token", @@ -3763,6 +3846,7 @@ "CZSHARES": "CZshares", "CZUSD": "CZUSD", "CZZ": "ClassZZ", + "D": "Dar Open Network", "D11": "DeFi11", "D2O": "DAM Finance", "D2T": "Dash 2 Trade", @@ -3803,6 +3887,7 @@ "DAIN": "Dain Token", "DAIQ": "Daiquilibrium", "DAISY": "Daisy Launch Pad", + "DAIWO": "D.A.I.Wo", "DAK": "dak", "DAKU": "Der Daku", "DAL": "DAOLaunch", @@ -3863,6 +3948,7 @@ "DATAB": "Databot", "DATAO": "Data Ownership Protocol", "DATAWALLET": "DataWallet", + "DATBOI": "Dat Boi", "DATOM": "Drop Staked ATOM", "DATP": "Decentralized Asset Trading Platform", "DATX": "DATx", @@ -3870,6 +3956,7 @@ "DAV": "DAV", "DAVE": "DAVE", "DAVID": "David", + "DAVINC": "DaVinci Protocol", "DAVINCI": "Davincigraph", "DAVIS": "Davis Cup Fan Token", "DAVP": "Davion", @@ -3978,8 +4065,12 @@ "DEEP": "DeepBook Protocol", "DEEPCLOUD": "DeepCloud AI", "DEEPG": "Deep Gold", + "DEEPS": "DeepSeek AI", + "DEEPSE": "DeepSeek AI Assistant", "DEEPSEARCH": "Grok 3 DeepSearch", + "DEEPSEE": "DeepSeek AI", "DEEPSEEK": "Global DePIN Chain", + "DEEPSEEKAI": "DeepSeek AI Agent", "DEEPSEEKR1": "DeepSeek R1", "DEER": "ToxicDeer Finance", "DEERSEIZED": "Deer Seized by US Government", @@ -4060,6 +4151,7 @@ "DETH": "DarkEther", "DETO": "Delta Exchange", "DEUR": "DigiEuro", + "DEURO": "DecentralizedEURO", "DEUS": "DEUS Finance", "DEUSD": "Elixir deUSD", "DEV": "Deviant Coin", @@ -4151,6 +4243,7 @@ "DIABLO": "Diablo IV", "DIAM": "Diamond", "DIAMND": "Projekt Diamond", + "DIAMO": "Diamond Launch", "DIAMOND": "Diamond Coin", "DIAMONDINU": "Diamond", "DIBBLE": "Dibbles", @@ -4160,6 +4253,7 @@ "DICEM": "DICE Money", "DICETRX": "TRONbetDice", "DICK": "adDICKted", + "DICKBUTT": "Dickbutt", "DICKCOIN": "DickCoin", "DID": "Didcoin", "DIDDY": "DIDDY", @@ -4174,13 +4268,15 @@ "DIGAU": "Dignity Gold", "DIGEX": "Digex", "DIGG": "DIGG", - "DIGI": "Digiverse", + "DIGGAI": "DIGGER AI", + "DIGI": "Digicoin", "DIGIC": "DigiCube", "DIGIF": "DigiFel", "DIGIMON": "Digimon", "DIGIT": "Digital Asset Rights Token", "DIGITAL": "Digital Reserve Currency", "DIGITS": "Digits DAO", + "DIGIV": "Digiverse", "DIGNITY": "Dignity", "DIGS": "Diggits", "DIK": "DikDok", @@ -4239,7 +4335,7 @@ "DLA": "Dolla", "DLANCE": "DeeLance", "DLB": "DiemLibre", - "DLC": "Diamond Launch", + "DLC": "DeepLink", "DLCBTC": "DLC.Link", "DLISK": "Dlisk", "DLLR": "Sovryn Dollar", @@ -4278,6 +4374,7 @@ "DMZ": "DeMon Token", "DN8": "Pldgr", "DNA": "Metaverse", + "DNAPEPE": "DNA PEPE", "DND": "Diamond DND", "DNET": "DeNet", "DNF": "DNFT Protocol", @@ -4353,9 +4450,11 @@ "DOGEGROKAI": "Doge Of Grok AI", "DOGEI": "Dogei", "DOGEIN": "Doge In Glasses", + "DOGEIUS": "DOGEIUS", "DOGEKING": "DogeKing", "DOGELEGION": "DOGE LEGION", "DOGEM": "Doge Matrix", + "DOGEMARS": "DOGE TO MARS", "DOGEMETA": "Dogemetaverse", "DOGEMOB": "DOGEMOB", "DOGEMOON": "DOGE TO MOON", @@ -4414,6 +4513,7 @@ "DOLLAR": "Dollar", "DOLLARCOIN": "DollarCoin", "DOLLUR": "Dollur Go Brrr", + "DOLLY": "DOLLY", "DOLPHY": "Dolphy", "DOLZ": "DOLZ", "DOM": "Ancient Kingdom", @@ -4437,6 +4537,7 @@ "DONU": "Donu", "DONUT": "Donut", "DONUTS": "The Simpsons", + "DOODI": "Doodipals", "DOODOO": "Doodoo", "DOOGLE": "Doogle", "DOOH": "Bidooh", @@ -4446,6 +4547,7 @@ "DOPE": "Dopamine App", "DOPEC": "DOPE Coin", "DOPECOIN": "DopeCoin", + "DOPEX": "DOPE", "DOPU": "DOPU The Dog with A Purpose", "DOR": "Dorado", "DORA": "Dora Factory", @@ -4468,6 +4570,7 @@ "DOVIS": "Dovish Finance", "DOVU": "DOVU", "DOWS": "Shadows", + "DOYOUR": "Do Your Own Research", "DP": "DigitalPrice", "DPAD": "Dpad Finance", "DPAY": "Devour", @@ -4477,6 +4580,7 @@ "DPI": "DeFiPulse Index", "DPIE": "DeFiPie", "DPIN": "DPIN", + "DPINO": "DarkPino", "DPLAT": "zbyte", "DPLN": "DePlan", "DPLTR": "Palantir Tokenized Stock Defichain", @@ -4501,6 +4605,7 @@ "DRAGONKING": "DragonKing", "DRAGONMA": "Dragon Mainland Shards", "DRAGONX": "DragonX", + "DRAGONZ": "Dragonz Land", "DRAGU": "DRAGU", "DRAGY": "Dragy", "DRAKO": "Drako", @@ -4519,7 +4624,8 @@ "DRGN": "Dragonchain", "DRIFT": "Drift protocol", "DRINK": "DrinkChain", - "DRIP": "Drip Network", + "DRIP": "Metadrip", + "DRIPNET": "Drip Network", "DRIV": "DRIVEZ", "DRIVECRYPTO": "Drive Crypto", "DRKC": "DarkCash", @@ -4534,6 +4640,7 @@ "DROVERS": "Drover Inu", "DRP": "DCORP", "DRPU": "DRP Utility", + "DRPXBT": "Hunter by Virtuals", "DRS": "Digital Rupees", "DRT": "DomRaider", "DRUGS": "Big Pharmai", @@ -4552,6 +4659,7 @@ "DSG": "Dinosaureggs", "DSH": "Dashcoin", "DSHARE": "Dibs Share", + "DSHELL": "diamondshell", "DSHIB": "DOLLAR SHIBA INU", "DSK": "Darüşşafaka Spor Kulübü Token", "DSLA": "DSLA Protocol", @@ -4596,6 +4704,7 @@ "DUBI": "Decentralized Universal Basic Income", "DUBX": "DUBXCOIN", "DUC": "DucatusCoin", + "DUCAT": "Ducat", "DUCATO": "Ducato Protocol Token", "DUCK": "Unit Protocol New", "DUCKAI": "Duck AI", @@ -4604,6 +4713,7 @@ "DUCKER": "Ducker", "DUCKIES": "Yellow Duckies", "DUCKO": "Duck Off Coin", + "DUCKV1": "COL", "DUCKY": "Ducky Duck", "DUCX": "DucatusX", "DUDE": "DuDe", @@ -4622,6 +4732,7 @@ "DUN": "Dune", "DUNG": "Scarab Tools", "DUO": "ParallelCoin", + "DUOLINGOAI": "DUOLINGO AI", "DUOT": "DUO Network", "DUREV": "Povel Durev", "DUROV": "FREE DUROV", @@ -4629,6 +4740,7 @@ "DUSD": "Decentralized USD", "DUSK": "Dusk Network", "DUST": "DUST Protocol", + "DUSTY": "Dusty", "DUX": "DuxCoin", "DUZCE": "Duzce Token", "DV": "Dreamverse", @@ -4694,6 +4806,7 @@ "DYST": "Dystopia", "DYT": "DoYourTip", "DYZILLA": "DYZilla", + "DZA": "DZA", "DZAR": "Digital Rand", "DZCC": "DZCC", "DZDD": "DZD", @@ -4943,6 +5056,7 @@ "ELU": "Elumia", "ELUSKMON": "Elusk Mon", "ELV": "Elvantis", + "ELVIS": "ELVIS", "ELVN": "11Minutes", "ELX": "Elixir Network", "ELY": "Elysian", @@ -5026,6 +5140,7 @@ "ENV": "ENVOY", "ENVIENTA": "Envienta", "ENVION": "Envion", + "ENVOY": "Envoy A.I", "ENX": "ENEX", "EOC": "EveryonesCoin", "EON": "Exscudo", @@ -5043,7 +5158,8 @@ "EPENDLE": "Equilibria Pendle", "EPEP": "Epep", "EPETS": "Etherpets", - "EPIC": "Epic Cash", + "EPIC": "Epic Chain", + "EPICCASH": "Epic Cash", "EPIK": "EPIK Token", "EPIKO": "Epiko", "EPIX": "Byepix", @@ -5108,6 +5224,7 @@ "ESGC": "ESG Chain", "ESH": "Switch", "ESHIB": "Euro Shiba Inu", + "ESIM": "EvoSimGame", "ESM": "EL SALVADOR MEME", "ESN": "Ethersocial", "ESNC": "Galaxy Arena Metaverse", @@ -5298,6 +5415,7 @@ "EXOS": "Exobots", "EXP": "Expanse", "EXPAND": "Gems", + "EXPERIENCE": "Experience Points", "EXPERT": "EXPERT_MONEY", "EXPO": "Exponential Capital", "EXRD": "Radix", @@ -5348,6 +5466,7 @@ "FAH": "Falcons", "FAI": "Freysa AI", "FAIR": "FairCoin", + "FAIR3": "Fair and Free", "FAIRC": "Faireum Token", "FAIRG": "FairGame", "FAIRUM": "Fairum", @@ -5384,6 +5503,7 @@ "FARTBOY": "Fartboy", "FARTCOIN": "Fartcoin", "FARTDEV": "Fart Dev", + "FARTIMUS": "Fartimus Prime", "FARTING": "Farting Unicorn", "FAS": "fast construction coin", "FAST": "Fastswap", @@ -5483,6 +5603,7 @@ "FGT": "Flozo Game Token", "FGZ": "Free Game Zone", "FHB": "FHB", + "FHE": "MindNetwork FHE Token", "FHM": "FantOHM", "FI": "Fideum", "FIA": "FIA Protocol", @@ -5541,7 +5662,9 @@ "FIRU": "Firulais Finance", "FIS": "Stafi", "FISH": "Polycat Finance", + "FISH2": "FISH2", "FISHK": "Fishkoin", + "FISHW": "Fishwar", "FIST": "Fistbump", "FISTBUMP": "FistBump", "FIT": "Financial Investment Token", @@ -5606,6 +5729,7 @@ "FLOCK": "FLock.io", "FLOCKA": "Waka Flocka", "FLOCKE": "Flockerz", + "FLOCO": "flocoin", "FLOKA": "FLOKA", "FLOKEI": "FLOKEI", "FLOKI": "Floki Inu", @@ -5732,7 +5856,9 @@ "FOREX": "handle.fi", "FOREXCOIN": "FOREXCOIN", "FORK": "Gastro Advisor Token", - "FORM": "Formation FI", + "FORM": "Four", + "FORMATION": "Formation FI", + "FORMNET": "Form", "FORS": "Forus", "FORT": "Forta", "FORTH": "Ampleforth Governance Token", @@ -5746,7 +5872,7 @@ "FOTTIE": "Fottie", "FOUND": "ccFound", "FOUNTAIN": "Fountain", - "FOUR": "4THPILLAR TECHNOLOGIES", + "FOUR": "4", "FOX": "ShapeShift FOX Token", "FOXAI": "FOXAI", "FOXD": "Foxdcoin", @@ -5800,6 +5926,7 @@ "FRENS": "Farmer Friends", "FRESCO": "Fresco", "FRF": "France REV Finance", + "FRGB": "Pepe's Frogbar", "FRGST": "Froggies Token", "FRGX": "FRGX", "FRIC": "Fric", @@ -5840,6 +5967,7 @@ "FRV": "Fitrova", "FRWC": "Frankywillcoin", "FRXETH": "Frax Ether", + "FRXUSD": "Frax USD", "FRZ": "Frozy Inu", "FRZSS": "Frz Solar System", "FRZSSCOIN": "FRZ Solar System Coin", @@ -6000,6 +6128,7 @@ "GAMBL": "Metagamble", "GAME": "GameBuild", "GAMEBUD": "GAMEBUD", + "GAMEBYV": "GAME by Virtuals", "GAMEC": "Game", "GAMECO": "Game.com", "GAMECRED": "GameCredits", @@ -6039,7 +6168,8 @@ "GAS": "Gas", "GASDAO": "Gas DAO", "GASG": "Gasgains", - "GASP": "gAsp", + "GASP": "GASP", + "GASPCOIN": "gAsp", "GASTRO": "GastroCoin", "GAT": "GATCOIN", "GATE": "GATENet", @@ -6094,6 +6224,7 @@ "GDCC": "GLOBAL DIGITAL CLUSTER COIN", "GDDY": "Giddy", "GDE": "Golden Eagle", + "GDIGIT": "GoldDigitStandart", "GDL": "GodlyCoin", "GDO": "GroupDao", "GDOG": "GDOG", @@ -6205,6 +6336,14 @@ "GHD": "Giftedhands", "GHDV1": "Giftedhands v1", "GHE": "GHETTO PEPE", + "GHHS": "GHHS Healthcare", + "GHI": "Ghibli HeYi", + "GHIB": "GhibliCZ", + "GHIBL": "Ghibli Zao", + "GHIBLI": "Ghiblification", + "GHIBLIAI": "Ghibli AI Agent", + "GHIBLIDOGE": "Ghibli Doge", + "GHIBLIELON": "Ghibli Elon", "GHNY": "Grizzly Honey", "GHO": "GHO", "GHOAD": "GhoadCoin", @@ -6241,6 +6380,7 @@ "GIMMERV1": "Gimmer v1", "GIN": "GINcoin", "GINGER": "GINGER", + "GINI": "Kalp", "GINNAN": "Ginnan The Cat", "GINOA": "Ginoa", "GINU": "Green Shiba Inu", @@ -6271,7 +6411,7 @@ "GLD": "Goldario", "GLDGOV": "Gold DAO", "GLDR": "Golder Coin", - "GLDS": "Gdigit", + "GLDS": "Glades", "GLDX": "Goldex", "GLDY": "Buzzshow", "GLE": "Green Life Energy", @@ -6298,6 +6438,7 @@ "GLR": "Glory Finance", "GLS": "Glacier", "GLT": "GlobalToken", + "GLUE": "Glue", "GLX": "GalaxyCoin", "GLYPH": "GlyphCoin", "GM": "GM", @@ -6334,6 +6475,7 @@ "GMT": "STEPN", "GMTO": "Game Meteor Coin", "GMTT": "GMT Token", + "GMUBARAK": "Ghibli Mubarak", "GMUSD": "GND Protocol", "GMX": "GMX", "GN": "GN", @@ -6479,6 +6621,7 @@ "GPX": "GPEX", "GQ": "Galactic Quadrant", "GR": "GROM", + "GRAB": "GRABWAY", "GRACY": "Gracy", "GRAI": "Gravita Protocol", "GRAIL": "Camelot Token", @@ -6639,7 +6782,8 @@ "GUMMIES": "GUMMIES", "GUMMY": "GUMMY", "GUMSHOOS": "GUMSHOOS TRUMP", - "GUN": "GunCoin", + "GUN": "GUNZ", + "GUNCOIN": "GunCoin", "GUNS": "GeoFunders", "GUP": "Guppy", "GURL": "Gently Used Girl", @@ -6981,6 +7125,7 @@ "HNST": "Honest", "HNT": "Helium", "HNTR": "Hunter", + "HNTV1": "Helium v1", "HNX": "HeartX Utility Token", "HNY": "Honey", "HNZO": "Hanzo Inu", @@ -6991,7 +7136,9 @@ "HOBO": "HOBO THE BEAR", "HOCAI": "Heroes of Crypto AI", "HOD": "HoDooi.com", - "HODL": "HOdlcoin", + "HODLC": "HOdlcoin", + "HODLV1": "HODL v1", + "HODLV2": "HODL", "HOG": "Hog", "HOGE": "Hoge Finance", "HOGONSOLANA": "HOG", @@ -7011,6 +7158,7 @@ "HOMER": "Homer Simpson", "HOMERB": "Homer BSC", "HOMERO": "Homer Of Meme", + "HOMERS": "Homer", "HOMI": "HOMIHELP", "HOMIECOIN": "Homie Wars", "HOMMIES": "HOMMIES", @@ -7029,6 +7177,7 @@ "HOOPS": "Hoops", "HOOT": "HOOT", "HOP": "Hop Protocol", + "HOPECOIN": "Hopecoin", "HOPPY": "Hoppy", "HOPPYTOKEN": "Hoppy", "HOPR": "HOPR", @@ -7174,6 +7323,7 @@ "HYPERD": "HyperDAO", "HYPERIONX": "HyperionX", "HYPERS": "HyperSpace", + "HYPERSKIDS": "HYPERSKIDS", "HYPES": "Supreme Finance", "HYPEV1": "Hype v1", "HYPR": "Hypr Network", @@ -7192,15 +7342,18 @@ "IAG": "IAGON", "IAI": "inheritance Art", "IAM": "IAME Identity", + "IAOMIN": "Yao Ming", "IB": "Iron Bank", "IBANK": "iBankCoin", "IBAT": "Battle Infinity", + "IBERA": "Infrared Bera", "IBETH": "Interest Bearing ETH", "IBEUR": "Iron Bank EURO", "IBFK": "İstanbul Başakşehir Fan Token", "IBFN": "IBF Net", "IBFR": "iBuffer Token", "IBG": "iBG Token", + "IBGT": "Infrared BGT", "IBIT": "InfinityBit Token", "IBNB": "iBNB", "IBP": "Innovation Blockchain Payment", @@ -7305,6 +7458,7 @@ "ILC": "ILCOIN", "ILCT": "ILCoin Token", "ILK": "Inlock", + "ILLUMINAT": "Illuminat", "ILT": "iOlite", "ILV": "Illuvium", "IMARO": "IMARO", @@ -7313,7 +7467,9 @@ "IMC": "i Money Crypto", "IME": "Imperium Empires", "IMG": "ImageCoin", + "IMGN": "IMGN Labs", "IMGNAI": "Image Generation AI", + "IMGX10": "IMGx10", "IMGZ": "Imigize", "IMI": "Influencer", "IML": "IMMLA", @@ -7442,6 +7598,7 @@ "IOI": "IOI Token", "ION": "Ionomy", "IONC": "IONChain", + "IONP": "Ion Power Token", "IONX": "Charged Particles", "IONZ": "IONZ", "IOP": "Internet of People", @@ -7587,6 +7744,7 @@ "JAPAN": "Japan Open Chain", "JAR": "Jarvis+", "JARED": "Jared From Subway", + "JARVIS": "Jarvis AI", "JARY": "JeromeAndGary", "JASMY": "JasmyCoin", "JASON": "Jason Derulo", @@ -7773,6 +7931,7 @@ "JWL": "Jewels", "JYAI": "Jerry The Turtle By Matt Furie", "JYC": "Joe-Yo Coin", + "K": "Kinto", "K21": "K21", "K2G": "Kasko2go", "KAAI": "KanzzAI", @@ -7910,9 +8069,11 @@ "KEPT": "KeptChain", "KERMIT": "KermitTheCoin", "KERN": "Kernel", - "KET": "KET", + "KERNEL": "KernelDAO", + "KET": "Ket", "KETAMINE": "Ketamine", "KETAN": "Ketan", + "KETCOIN": "KET", "KEVIN": "Kevin (kevinonbase.xyz)", "KEVINTOKENME": "KEVIN (kevintoken.me)", "KEVINTOKENNET": "Kevin", @@ -7951,6 +8112,7 @@ "KILLA": "The Bitcoin Killa", "KILLER": "Fat Cat Killer", "KILLSOLANA": "KillSolana", + "KILO": "KiloEx", "KILT": "KILT Protocol", "KIM": "King Money", "KIMBO": "Kimbo", @@ -8023,6 +8185,7 @@ "KLIMA": "KlimaDAO", "KLK": "Klickzie", "KLKS": "Kalkulus", + "KLKSYNC": "KLK Sync Protocol", "KLO": "Kalao", "KLON": "Klondike Finance", "KLP": "Kulupu", @@ -8059,6 +8222,7 @@ "KNT": "Knekted", "KNTO": "Kento", "KNU": "Keanu", + "KNUT": "Knut From Zoo", "KNW": "Knowledge", "KOAI": "KOI", "KOBE": "Shabu Shabu", @@ -8156,6 +8320,7 @@ "KSWAP": "KyotoSwap", "KSYS": "K-Systems", "KT": "Kuai Token", + "KTA": "Keeta", "KTC": "KTX.Finance", "KTK": "KryptCoin", "KTN": "Kattana", @@ -8173,6 +8338,7 @@ "KUE": "Kuende", "KUJI": "Kujira", "KUKU": "KuKu", + "KULA": "Kula", "KUMA": "Kuma Inu", "KUMU": "Kumu Finance", "KUNAI": "KunaiKash", @@ -8230,6 +8396,7 @@ "LABUBU": "Labubu", "LABX": "Stakinglab", "LABZ": "Insane Labz", + "LABZBASE": "Insane Labz (Base)", "LACCOIN": "LocalAgro", "LACE": "Lovelace World", "LAD": "LADA", @@ -8344,6 +8511,7 @@ "LEE": "Love Earn Enjoy", "LEET": "LeetSwap", "LEG": "Legia Warsaw Fan Token", + "LEGAL": "LegalX", "LEGEND": "Legend", "LEGION": "LEGION", "LEGIT": "LEGIT", @@ -8482,7 +8650,8 @@ "LINU": "Luna Inu", "LINX": "Linx", "LIO": "Lio", - "LION": "Lion Token", + "LION": "Loaded Lions", + "LIONT": "Lion Token", "LIPC": "LIpcoin", "LIPS": "LipChain", "LIQ": "LIQ Protocol", @@ -8493,6 +8662,7 @@ "LIR": "Let it Ride", "LIS": "Realis Network", "LISA": "Lisa Simpson", + "LISAS": "Lisa Simpson", "LIST": "KList Protocol", "LISTA": "Lista DAO", "LISUSD": "lisUSD", @@ -8581,10 +8751,12 @@ "LOFIBUZZ": "LOFI", "LOG": "Wood Coin", "LOGO": "LOGOS", + "LOGOS": "LOGOSAI", "LOGX": "LogX Network", "LOIS": "Lois Token", "LOKA": "League of Kingdoms", "LOKR": "Polkalokr", + "LOKY": "Loky by Virtuals", "LOL": "EMOGI Network", "LOLA": "Lola", "LOLATHECAT": "Lola", @@ -8593,6 +8765,7 @@ "LOLO": "Lolo", "LON": "Tokenlon", "LONG": "Longdrink Finance", + "LONGEVITY": "longevity", "LONGFU": "LONGFU", "LONGM": "Long Mao", "LONGSHINE": "LongShine", @@ -8635,6 +8808,7 @@ "LOYAL": "Loyalty Labs", "LP": "Liquid Protocol", "LPC": "Little Phil", + "LPENGU": "Lil Pudgys", "LPI": "LPI DAO", "LPK": "Kripton", "LPL": "LinkPool", @@ -8719,6 +8893,7 @@ "LUCE": "Luce", "LUCHOW": "LunaChow", "LUCI": "LUCI", + "LUCIC": "Lucidum Coin", "LUCK": "Lucky Cat", "LUCKY": "Lucky Lion", "LUCKYB": "LuckyBlocks", @@ -8735,7 +8910,7 @@ "LUIGI": "Luigi Inu", "LUIS": "Tongue Cat", "LULU": "LULU", - "LUM": "Illuminates", + "LUM": "Luminous", "LUMA": "LUMA Token", "LUMI": "LUMI Credits", "LUMIA": "Lumia", @@ -8768,8 +8943,10 @@ "LVG": "Leverage Coin", "LVIP": "Limitless VIP", "LVL": "Level", + "LVLUSD": "Level USD", "LVM": "LakeViewMeta", "LVN": "LivenPay", + "LVVA": "Levva Protocol Token", "LVX": "Level01", "LWC": "Linework Coin", "LWF": "Local World Forwarders", @@ -8873,6 +9050,7 @@ "MALGO": "milkALGO", "MALL": "Metamall", "MALLY": "Malamute Finance", + "MALOU": "MALOU Token", "MAMAI": "MammothAI", "MAMBA": "Mamba", "MAN": "Matrix AI Network", @@ -8891,6 +9069,7 @@ "MANORUKA": "ManoRuka", "MANT": "Mantle USD", "MANTA": "Manta Network", + "MANTI": "Mantis", "MANTLE": "Mantle", "MANUSAI": "Manus AI Agent", "MANYU": "Little Manyu", @@ -8974,6 +9153,7 @@ "MAXCOIN": "MaxCoin", "MAXETH": "Max on ETH", "MAXI": "Maximus", + "MAXIMUSA": "Kekius Maximusa", "MAXL": "Maxi protocol", "MAXR": "Max Revive", "MAXX": "MAXX Finance", @@ -9032,7 +9212,7 @@ "MCAU": "Meld Gold", "MCB": "MCDEX", "MCC": "Magic Cube Coin", - "MCD": "CDbio", + "MCD": "McDonald's Job Application", "MCDAI": "Dai (Multichain)", "MCDULL": "McDull", "MCELO": "Moola Celo", @@ -9140,6 +9320,7 @@ "MEMD": "MemeDAO", "MEMDEX": "Memdex100", "MEME": "Memecoin", + "MEMEA": "MEME AI", "MEMEAI": "Meme Ai", "MEMECUP": "Meme Cup", "MEMEETF": "Meme ETF", @@ -9155,6 +9336,7 @@ "MEMESQUAD": "Meme Squad", "MEMET": "MEMETOON", "MEMETIC": "Memetic", + "MEMEX": "Meme Index", "MEMHASH": "Memhash", "MEMORYCOIN": "MemoryCoin", "MEN": "METAHUB FINANCE", @@ -9480,6 +9662,7 @@ "MNDE": "Marinade", "MNE": "Minereum", "MNEE": "MNEE USD Stablecoin ", + "MNEMO": "Mnemonics", "MNET": "MINE Network", "MNFT": "Mongol NFT", "MNFTS": "Marvelous NFTs", @@ -9491,6 +9674,7 @@ "MNRB": "MoneyRebel", "MNRCH": "Monarch", "MNS": "Monnos", + "MNSRY": "MANSORY", "MNST": "MoonStarter", "MNTA": "MantaDAO", "MNTC": "Manet Coin", @@ -9533,6 +9717,7 @@ "MODC": "Modclub", "MODE": "Mode", "MODEL": "Model Labs", + "MODERN": "bitcoin-modern", "MODEX": "Modex", "MODU": "Modular Wallet", "MODUM": "Modum", @@ -9659,7 +9844,9 @@ "MORPHO": "Morpho", "MORRA": "Morra", "MORSE": "Morse", + "MORTY": "Morty", "MOS": "MOS Coin", + "MOSS": "MOSS AI", "MOST": "MOST Global", "MOT": "Olympus Labs", "MOTA": "MotaCoin", @@ -9762,7 +9949,7 @@ "MSU": "MetaSoccer", "MSUSHI": "Sushi (Multichain)", "MSWAP": "MoneySwap", - "MT": "MyToken", + "MT": "Mint Token", "MTA": "Meta", "MTB": "MetaBridge", "MTBC": "Metabolic", @@ -9810,6 +9997,11 @@ "MTZ": "Monetizr", "MU": "Miracle Universe", "MUA": "MUA DAO", + "MUB": "Mubarak on Base", + "MUBA": "mubarak", + "MUBAR": "mubarak", + "MUBARAK": "mubarak", + "MUBARAKAH": "Mubarakah", "MUBI": "Multibit", "MUC": "Multi Universe Central", "MUDOL2": "Hero Blaze: Three Kingdoms", @@ -9912,6 +10104,7 @@ "MYT": "Mytrade", "MYTH": "Mythos", "MYTHTOKEN": "Myth Token", + "MYTOKEN": "MyToken", "MYTV": "MyTVchain", "MZC": "MazaCoin", "MZERO": "MetaZero", @@ -10154,6 +10347,7 @@ "NFN": "Nafen", "NFNT": "NFINITY AI", "NFP": "NFPrompt", + "NFPV1": "Token NFPrompt Token v1", "NFT": "APENFT", "NFT11": "NFT11", "NFTART": "NFT Art Finance", @@ -10208,6 +10402,7 @@ "NIIFI": "NiiFi", "NIK": "NIKPLACE", "NIKO": "NikolAI", + "NIL": "Nillion", "NILE": "Nile", "NIM": "Nimiq", "NIMBUS": "Nimbus AI", @@ -10280,6 +10475,7 @@ "NODIDDY": "NODIDDY", "NODIS": "Nodis", "NODL": "Nodle Network", + "NOEL": "AskNoel", "NOGS": "Noggles", "NOHAT": "DogWifNoHat", "NOIA": "Syntropy", @@ -10290,6 +10486,7 @@ "NOKUV1": "NOKU Master token v1", "NOLA": "Nola", "NOM": "Finom NOM Token", + "NOMAI": "nomAI by Virtuals", "NOMNOM": "nomnom", "NOMOX": "NOMOEX Token", "NONE": "None Trading", @@ -10412,6 +10609,7 @@ "NUUM": "MNet", "NUX": "Peanut", "NVA": "Neeva Defi", + "NVB": "NovaBank", "NVC": "NovaCoin", "NVDX": "Nodvix", "NVG": "NightVerse Game", @@ -10455,6 +10653,7 @@ "NYEX": "Nyerium", "NYM": "Nym Token", "NYN": "NYNJA", + "NYS": "node.sys", "NYX": "NYXCOIN", "NYXC": "Nyxia AI", "NYZO": "Nyzo", @@ -10531,6 +10730,7 @@ "ODMC": "ODMCoin", "ODN": "Obsidian", "ODNT": "Old Dogs New Tricks", + "ODOS": "Odos", "ODS": "Odesis", "ODX": "ODX Token", "ODYS": "OdysseyWallet", @@ -10544,6 +10744,7 @@ "OFFIC": "OFFICIAL SIMPSON", "OFFICI": "OFFICIAL BARRON", "OFFICIA": "Official Elon Coin", + "OFFICIALUSA": "Official USA Token", "OFN": "Openfabric AI", "OFT": "ONFA", "OG": "OG Fan Token", @@ -10609,6 +10810,7 @@ "OLY": "Olyseum", "OLYMP": "OlympCoin", "OLYMPE": "OLYMPÉ", + "OLYN": "Olyn by Virtuals", "OM": "MANTRA", "OMA": "OmegaCoin", "OMAX": "Omax", @@ -10697,6 +10899,7 @@ "OPENW": "OpenWorld", "OPENX": "OpenSwap Optimism Token", "OPEPE": "Optimism PEPE", + "OPERATOR": "OpenAI Agent", "OPES": "Opes", "OPET": "ÕpetFoundation", "OPEX": "Optherium Token", @@ -10886,6 +11089,8 @@ "PAK": "Pakcoin", "PAL": "PolicyPal Network", "PALAI": "PaladinAI", + "PALCOIN": "Palcoin Ventures", + "PALCOINV1": "PALCOIN Venture Capital v1", "PALE": "Palette", "PALET": "Palette", "PALG": "PalGold", @@ -10942,6 +11147,7 @@ "PARQ": "PARQ", "PARRY": "Parry Parrot", "PART": "Particl", + "PARTI": "PARTI Token", "PARTY": "Party", "PAS": "Passive Coin", "PASC": "Pascal Coin", @@ -10953,6 +11159,7 @@ "PATEK": "Silly Patek", "PATEX": "Patex", "PATH": "PathDAO", + "PATLU": "Patlu", "PATRIOT": "Patriot", "PATTON": "Patton", "PAUL": "Elephant Penguin", @@ -11036,6 +11243,7 @@ "PEA": "Pea Farm", "PEACH": "Based Peaches", "PEACHY": "Peachy", + "PEAGUY": "The Pea Guy by Virtuals", "PEAK": "PEAKDEFI", "PEAN": "Peanut the Squirrel (peanut-token.xyz)", "PEANIE": "Peanie", @@ -11074,6 +11282,7 @@ "PEKO": "Pepe Neko", "PEL": "Propel Token", "PELF": "PELFORT", + "PELL": "PELL Network Token", "PEM": "Pembrock", "PEME": "PEME", "PENC": "PenCoin", @@ -11119,6 +11328,7 @@ "PEPED": "PepeDAO Coin", "PEPEDAO": "PEPE DAO", "PEPEDERP": "PepeDerp", + "PEPEDNA": "PEPE DNA", "PEPEE": "Pepe the pepe", "PEPEF": "PEPEFLOKI", "PEPEFC": "Pepe FC", @@ -11167,6 +11377,7 @@ "PER": "Perproject", "PERA": "Pera Finance", "PERC": "Perion", + "PERCY": "Percy Verence", "PERI": "PERI Finance", "PERL": "PERL.eco", "PERMIAN": "Permian", @@ -11270,6 +11481,7 @@ "PIGEONC": "Pigeoncoin", "PIGGY": "Piggy", "PIGGYCOIN": "Piggy Coin", + "PIGLET": "PIGLET", "PIGONK": "PIGONK", "PIGS": "Elon Vitalik Pigs", "PIIN": "piin (Ordinals)", @@ -11430,6 +11642,7 @@ "PNC": "PlatiniumCoin", "PND": "PandaCoin", "PNDC": "Pond Coin", + "PNDN": "Pandana", "PNDR": "Pandora Finance", "PNFT": "Pawn My NFT", "PNG": "Pangolin", @@ -11485,6 +11698,7 @@ "POLK": "Polkamarkets", "POLKER": "Polker", "POLL": "Pollchain", + "POLLEN": "Beraborrow", "POLLUK": "Jasse Polluk", "POLLUX": "Pollux Coin", "POLLY": "Polynetica", @@ -11650,6 +11864,7 @@ "PROJECT89": "Project89", "PROLIFIC": "Prolific Game Studio", "PROM": "Prometeus", + "PROMPT": "Wayfinder", "PROOF": "PROVER", "PROP": "Propeller", "PROPC": "Propchain", @@ -11751,6 +11966,7 @@ "PUMBAA": "Pumbaa", "PUMLX": "PUMLx", "PUMP": "PUMP", + "PUMPB": "Pump", "PUMPBTC": "pumpBTC", "PUMPFUNBAN": "Pump Fun Ban", "PUMPIT": "BOGDANOFF", @@ -11758,6 +11974,7 @@ "PUMPY": "WOW MOON LAMBO PUMPPPPPPY", "PUN": "Punkko", "PUNCH": "PUNCHWORD", + "PUNDIAI": "Pundi AI", "PUNDIX": "Pundi X", "PUNDU": "Pundu", "PUNGU": "PUNGU", @@ -11920,6 +12137,7 @@ "QUA": "Quantum Tech", "QUAC": "QUACK", "QUACK": "Rich Quack", + "QUAI": "Quai Network", "QUAM": "Quam Network", "QUAN": "Quant AI", "QUANT": "Quant Finance", @@ -11946,8 +12164,10 @@ "QUIZ": "Quizando", "QUNT": "Quants", "QUO": "Quoll Finance", + "QUQ": "quq", "QUROZ": "Qfora", "QUSD": "QUSD", + "QUSDT": "Tether (Qom Bridge)", "QVT": "Qvolta", "QWAN": "The QWAN", "QWARK": "Qwark", @@ -12113,7 +12333,7 @@ "RECOM": "Recom", "RECORD": "Music Protocol", "RECT": "ReflectionAI", - "RED": "RED TOKEN", + "RED": "RedStone", "REDC": "RedCab", "REDCO": "Redcoin", "REDDIT": "Reddit", @@ -12129,6 +12349,8 @@ "REDP": "Red Ponzi Gud", "REDPEPE": "Red Pepe", "REDTH": "Red The Mal", + "REDTOKEN": "RED TOKEN", + "REDX": "REDX", "REDZILLA": "REDZILLA COIN", "REE": "ReeCoin", "REEE": "REEE", @@ -12166,6 +12388,7 @@ "REMILIA": " Remilia", "REMIT": "BlockRemit", "REMMETA": "Real Estate Metaverse", + "REMUS": "REMUS", "REN": "REN", "RENA": "Warena", "RENBTC": "renBTC", @@ -12192,6 +12415,7 @@ "RET": "Renewable Energy", "RETA": "Realital Metaverse", "RETAIL": "Retail.Global", + "RETAR": "Retard Finder Coin", "RETARDIA": "RETARDIA", "RETARDIO": "RETARDIO", "RETH": "Rocket Pool ETH", @@ -12200,6 +12424,7 @@ "RETIRE": "Retire Token", "REU": "REUCOIN", "REUNI": "Reunit Wallet", + "REUSDC": "Relend USDC", "REV": "Revain", "REV3L": "REV3AL", "REVA": "Revault Network", @@ -12332,6 +12557,7 @@ "RMS": "Resumeo Shares", "RMT": "SureRemit", "RMV": "Reality Metaverse", + "RNAPEPE": "RNA PEPE", "RNB": "Rentible", "RNBW": "Rainbow Token", "RNC": "ReturnCoin", @@ -12353,6 +12579,7 @@ "ROBIN": "Robin of Da Hood", "ROBINH": "ROBIN HOOD", "ROBO": "RoboHero", + "ROBOCOIN": "First Bitcoin ATM", "ROBOTA": "TAXI", "ROBOTAXI": "ROBOTAXI", "ROC": "Rasputin Online Coin", @@ -12412,6 +12639,7 @@ "ROUSH": "Roush Fenway Racing Fan Token", "ROUTE": "Router Protocol", "ROUTEV1": "Router Protocol v1", + "ROUTINE": "Morning Routine", "ROVI": "ROVI", "ROW": "Rage On Wheels", "ROWAN": "Sifchain", @@ -12522,6 +12750,7 @@ "RVT": "Rivetz", "RVX": "Rivex", "RWA": "Xend Finance", + "RWAECO": "RWA Ecosystem", "RWAS": "RWA Finance", "RWB": "RawBlock", "RWD": "Reward Vision", @@ -12529,6 +12758,7 @@ "RWN": "Rowan Token", "RWS": "Robonomics Web Services", "RWT": "RWT TOKEN", + "RX": "RealtyX", "RXCG": "RXCGames", "RXD": "Radiant", "RXO": "RocketXRP Official", @@ -12553,6 +12783,7 @@ "S4F": "S4FE", "S8C": "S88 Coin", "SA": "Superalgos", + "SAAD": "Saad Boi", "SAAS": "SaaSGo", "SABAI": "Sabai Protocol", "SABLE": "Sable Finance", @@ -12610,6 +12841,7 @@ "SAMA": "Moonsama", "SAMMY": "Samoyed", "SAMO": "Samoyedcoin", + "SAMS": "Samsara.Build", "SAN": "Santiment", "SANA": "Storage Area Network Anywhere", "SANCHO": "Sancho", @@ -12853,6 +13085,7 @@ "SEX": "SEX Odyssey", "SEXY": "EthXY", "SEXYP": "SEXY PEPE", + "SFAGRO": "SFAGRO", "SFARM": "SolFarm", "SFC": "Solarflarecoin", "SFCP": "SF Capital", @@ -12867,11 +13100,13 @@ "SFLOKI": "SuiFloki-Inu", "SFLR": "Sceptre Staked FLR", "SFM": "SafeMoon V2", + "SFMV2": "SafeMoon v2", "SFP": "SafePal", "SFR": "SaffronCoin", "SFRAX": "Staked FRAX", "SFRC": "Safari Crush", "SFRXETH": "Frax Staked Ether", + "SFRXUSD": "Staked Frax USD", "SFT": "SportsFix", "SFTMX": "Stader sFTMX", "SFTY": "Stella Fantasy", @@ -12910,6 +13145,7 @@ "SHARE": "Seigniorage Shares", "SHARECHAIN": "ShareChain", "SHARES": "shares.finance", + "SHAREV1": "Seigniorage Shares v1", "SHARK": "Sharky", "SHARKC": "Shark Cat", "SHARKI": "Sharki", @@ -13015,12 +13251,14 @@ "SHOGGOTHAI": "Shoggoth", "SHOKI": "Shoki", "SHON": "ShonToken", + "SHONG": "Shong Inu", "SHOOT": "Mars Battle", "SHOOTER": "Top Down Survival Shooter", "SHOP": "Shoppi Coin", "SHOPN": "ShopNEXT", "SHOPX": "Splyt", "SHORK": "shork", + "SHORT": "Bermuda Shorts", "SHORTY": "ShortyCoin", "SHOW": "ShowCoin", "SHPING": "Shping Coin", @@ -13028,12 +13266,15 @@ "SHRA": "Shrapnel", "SHRAP": "Shrapnel", "SHRED": "ShredN", - "SHREK": "ShrekCoin", + "SHREK": "Shrek", + "SHRI": "Shrimp Paste", "SHRIMP": "SHRIMP", "SHROO": "Shroomates", "SHROOM": "Shroom.Finance", "SHROOMFOX": "Magic Shroom", "SHRUB": "Shrub", + "SHRUBIUS": "Shrubius Maximus", + "SHRX": "Sherex", "SHS": "SHEESH", "SHU": "Shutter", "SHUB": "SimpleHub", @@ -13086,6 +13327,7 @@ "SIMPSO": "Simpson Neiro", "SIMPSON": "Homer", "SIMPSON6900": "Simpson6900 ", + "SIMPSONAI": "Simpson AI Agent", "SIMPSONF": "Simpson FUKU", "SIMPSONP": "Simpson Predictions", "SIMPSONSINU": "The Simpsons Inu", @@ -13170,6 +13412,7 @@ "SLAM": "Slam Token", "SLAP": "CatSlap", "SLAVI": "Slavi Coin", + "SLAYER": "ThreatSlayerAI by Virtuals", "SLB": "Solberg", "SLC": "Silencio", "SLCL": "Solcial", @@ -13208,6 +13451,7 @@ "SLT": "Salute", "SLUGDENG": "SLUG DENG", "SLUMBO": "SLUMBO", + "SLVLUSD": "Staked Level USD", "SLVX": "eToro Silver", "SLX": "Slate", "SMA": "Soma Network", @@ -13312,6 +13556,7 @@ "SNOLEX": "Snolex", "SNOOP": "SnoopDAO", "SNOOPY": "Snoopy", + "SNOR": "SNOR", "SNORK": "Snork", "SNORT": "SNORT", "SNOV": "Snovio", @@ -13393,6 +13638,7 @@ "SOLER": "Solerium", "SOLETF": "SOL ETF", "SOLEX": "Solex Launchpad", + "SOLEY": "Soley", "SOLFI": "SoliDefi", "SOLFUN": "SolFun", "SOLGOAT": "SOLGOAT", @@ -13428,6 +13674,7 @@ "SOLVBTCENA": "SolvBTC Ethena", "SOLVBTCJUP": "SolvBTC Jupiter", "SOLVE": "SOLVE", + "SOLVEX": "SOLVEX", "SOLWIF": "Solwif", "SOLX": "SolarX", "SOLXD": "Solxdex", @@ -13512,6 +13759,8 @@ "SPECT": "Spectral", "SPECTRE": "SPECTRE AI", "SPEE": "SpeedCash", + "SPEED": "IShowSpeed", + "SPEEDCOIN": "Speed Coin", "SPEEDY": "Speedy", "SPELL": "Spell Token", "SPELLFIRE": "Spellfire", @@ -13558,6 +13807,7 @@ "SPO": "Spores Network", "SPOK": "Spock", "SPOL": "Starterpool", + "SPONG": "Spongebob", "SPONGE": "Sponge", "SPONGEBOB": "Spongebob Squarepants", "SPOODY": "Spoody Man", @@ -13634,8 +13884,9 @@ "SSC": "SelfSell", "SSD": "Sonic Screw Driver Coin", "SSDX": "SpunkySDX", - "SSE": "Soroosh Smart Ecosystem", + "SSE": "Solana Social Explorer", "SSEV1": "Soroosh Smart Ecosystem v1", + "SSEV2": "Soroosh Smart Ecosystem", "SSG": "Surviving Soldiers", "SSGT": "Safeswap", "SSH": "StreamSpace", @@ -13692,6 +13943,7 @@ "STARSHIPONSOL": "Starship", "START": "StartCoin", "STARTA": "Starta", + "STARTER": "Starter.xyz", "STARWARS": "Star Wars", "STARX": "STARX TOKEN", "STASH": "BitStash", @@ -13740,6 +13992,7 @@ "STFX": "STFX", "STG": "Stargate Finance", "STHR": "Stakerush", + "STHYPE": "Staked HYPE", "STI": "Seek Tiger", "STIC": "StickMan", "STIK": "Staika", @@ -13815,6 +14068,7 @@ "STRUMP": "Super Trump", "STRX": "StrikeX", "STS": "SBank", + "STSHIP": "StarShip", "STSOL": "Lido Staked SOL", "STSOMM": "Stride Staked SOMM", "STSR": "SatelStar", @@ -14033,7 +14287,9 @@ "SYNTHSWAP": "Synthswap", "SYNX": "Syndicate", "SYPOOL": "Sypool", + "SYRAX": "Syrax AI", "SYRUP": "Syrup", + "SYRUPUSDC": "SyrupUSDC", "SYS": "Syscoin", "SZCB": "Zugacoin", "T": "Threshold Network Token", @@ -14111,6 +14367,7 @@ "TAXAD": "TAXAD", "TAXI": "Robotaxi", "TAXLESSTRUMP": "MAGA TAXLESS", + "TAXP": "Taxpad", "TBAC": "BlockAura", "TBANK": "TaoBank", "TBAR": "Titanium BAR", @@ -14189,6 +14446,7 @@ "TELOS": "Teloscoin", "TEM": "Temtum", "TEMCO": "TEMCO", + "TEMM": "TEM MARKET", "TEMP": "Tempus", "TEMPLE": "TempleDAO", "TEN": "Tokenomy", @@ -14279,6 +14537,7 @@ "THESTANDARD": "Standard Token", "THETA": "Theta Network", "THETAN": "Thetan Coin", + "THETRANSFERTOKEN": "The Transfer Token", "THETRIBE": "The Tribe", "THEX": "Thore Exchange", "THG": "Thetan Arena", @@ -14353,6 +14612,7 @@ "TITANO": "Titano", "TITANX": "TitanX", "TITC": "TitCoin", + "TITCOIN": "titcoin", "TITI": "TiTi Protocol", "TITS": "We Love Tits", "TITTY": "TamaKitty", @@ -14407,6 +14667,7 @@ "TNT": "Tierion", "TOA": "TOA Coin", "TOAD": "TOAD", + "TOADCOIN": "TOAD", "TOB": "Tom On Base", "TOBI": "MOTO DOG", "TOBY": "toby", @@ -14457,6 +14718,7 @@ "TOOLS": "TOOLS", "TOON": "Pontoon", "TOONF": "Toon Finance", + "TOOTHLESS": "Toothless", "TOPC": "Topchain", "TOPCA": "TOP CAT", "TOPCAT": "Topcat", @@ -14485,6 +14747,7 @@ "TOSHKIN": "Toshkin Coin", "TOT": "TotCoin", "TOTEM": "DragonMaster", + "TOTHEMOON": "To The Moon", "TOTM": "Totem", "TOTO": "TOTO", "TOUCHFAN": "TouchFan", @@ -14546,6 +14809,7 @@ "TRDL": "Strudel Finance", "TRDS": "Traders Token", "TRDT": "Trident", + "TRDX": "Trendix", "TREAT": "Treat", "TREB": "Treble", "TRECENTO": "Trecento Blockchain Capital", @@ -14569,6 +14833,7 @@ "TRINI": "Trinity Network Credit", "TRIO": "Tripio", "TRIPAD": "TripAdvisor, Inc.", + "TRIPPKI": "Trippki", "TRITON": "Triton", "TRIVIA": "Trivians", "TRIX": "TriumphX", @@ -14635,7 +14900,9 @@ "TRUMPEPE": "Trump Pepe", "TRUMPER": "Trump Era", "TRUMPF": "Trump Fight", + "TRUMPG": "TRUMP GROK", "TRUMPHAT": "Trump Hat", + "TRUMPI": "TRUMP IP", "TRUMPINU": "Trump Inu", "TRUMPJ": "TRUMPJR", "TRUMPJR": "OFFICIAL TRUMP JR", @@ -14687,6 +14954,7 @@ "TSL": "Energo", "TSLT": "Tamkin", "TSN": "Tsunami Exchange Token", + "TSO": "Thesirion", "TSR": "Tesra", "TST": "Test", "TSTAI": "Test AI", @@ -14700,9 +14968,9 @@ "TTC": "TTC PROTOCOL", "TTF": "TurboTrix Finance", "TTK": "The Three Kingdoms", - "TTM": "To The Moon", + "TTM": "Tradetomato", "TTN": "Titan Coin", - "TTT": "The Transfer Token", + "TTT": "TRUMPETTOKEN", "TTTU": "T-Project", "TTU": "TaTaTu", "TTV": "TV-TWO", @@ -14717,6 +14985,7 @@ "TUNA": "TUNACOIN", "TUNE": "Bitune", "TUP": "Tenup", + "TUPE": "Turtle Pepe", "TUR": "Turron", "TURB": "TurboX", "TURBO": "Turbo", @@ -14727,7 +14996,8 @@ "TUS": "Treasure Under Sea", "TUSD": "True USD", "TUSDV1": "True USD v1", - "TUT": "Tutellus", + "TUT": "Tutorial", + "TUTELLUS": "Tutellus", "TUTTER": "Tutter", "TUX": "Tux The Penguin", "TUZKI": "Tuzki", @@ -14901,6 +15171,7 @@ "UNFK": "UNFK", "UNI": "Uniswap Protocol Token", "UNIBOT": "Unibot", + "UNIBTC": "uniBTC", "UNIC": "Unicly", "UNICE": "UNICE", "UNICORN": "UNICORN Token", @@ -14961,6 +15232,7 @@ "UPR": "Upfire", "UPRO": "ULTRAPRO", "UPS": "UPFI Network", + "UPT": "Universal Protocol Token", "UPTOS": "UPTOS", "UPUNK": "Unicly CryptoPunks Collection", "UPUSD": "Universal US Dollar", @@ -14985,7 +15257,8 @@ "USD0": "Usual", "USD1": "USD1", "USD3": "Web 3 Dollar", - "USDA": "USDA", + "USDA": "USDa", + "USDACC": "USDA", "USDAP": "Bond Appetite USD", "USDB": "USD Bancor", "USDBC": "Bridged USDC", @@ -15006,7 +15279,10 @@ "USDEBT": "USDEBT", "USDEX": "eToro US Dollar", "USDFL": "USDFreeLiquidity", - "USDG": "USDG", + "USDG": "Global Dollar", + "USDGLOBI": "Globiance USD Stablecoin", + "USDGV1": "USDG v1", + "USDGV2": "USDG", "USDH": "HonestCoin", "USDI": "Interest Protocol USDi", "USDJ": "USDJ", @@ -15099,8 +15375,10 @@ "VAAVE": "Venus AAVE", "VAB": "Vabble", "VADA": "Venus Cardano", - "VADER": "Vader Protocol", + "VADER": "VaderAI", + "VADERPROTOCOL": "Vader Protocol", "VAI": "Vai", + "VAIN": "Vainguard by Virtuals", "VAIOT": "VAIOT", "VAIOTV1": "VAIOT v1", "VAL": "Validity", @@ -15367,6 +15645,7 @@ "VPR": "VaporWallet", "VPRC": "VapersCoin", "VPS": "VPS AI", + "VPT": "Veritas Protocol", "VR": "Victoria", "VRA": "Verasity", "VRC": "Virtual Coin", @@ -15412,6 +15691,7 @@ "VTRAD": "VTRADING", "VTRO": "Vitruveo DEX", "VTRUMP": "Vote Trump", + "VTRV": "VitraVerse", "VTRX": "Venus TRX", "VTS": "Veritise", "VTU": "Virtu", @@ -15475,7 +15755,7 @@ "WAIF": "Waifu Token", "WAIFU": "Waifu", "WAIT": "Hourglass", - "WAL": "The Wasted Lands", + "WAL": "WAL Token", "WALE": "Waletoken", "WALK": "Walk Token", "WALL": "Du Rove's Wall", @@ -15506,6 +15786,7 @@ "WASD": "WASD Studios", "WASH": "WashingtonCoin", "WASSIE": "WASSIE", + "WASTED": "WastedLands", "WASTR": "Wrapped Astar", "WAT": "Wat", "WATC": "WATCoin", @@ -15513,6 +15794,7 @@ "WATER": "doginwotah", "WAVAX": "Wrapped AVAX", "WAVES": "Waves", + "WAVESCOMM": "Waves Community Token", "WAVL": "Wrapped Aston Villa", "WAWA": "Wawa Cat", "WAXE": "WAXE", @@ -15561,8 +15843,9 @@ "WCRO": "Wrapped CRO", "WCS": "Weecoins", "WCSOV": "Wrapped CrownSterling", - "WCT": "Waves Community Token", + "WCT": "WalletConnect", "WCT1WCT1": "Wrapped Car Token 1", + "WCTH": "Wrapped CTH Token", "WCUSD": "Wrapped Celo Dollar", "WDAI": "Dai (Wormhole)", "WDC": "WorldCoin", @@ -15582,6 +15865,7 @@ "WEBAI": "Web Ai", "WEBC": "Webchain", "WEBD": "WebDollar", + "WEBSIM": "The Css God by Virtuals", "WEBSS": "Websser", "WEC": "Whole Earth Coin", "WECO": "WECOIN", @@ -15595,6 +15879,7 @@ "WEGI": "Wegie", "WEGLD": "Wrapped EGLD", "WEHMND": "Wrapped eHMND", + "WEHODL": "HODL", "WEIRDO": "Weirdo", "WEL": "Welsh Corgi", "WELA": "Wrapped Elastos", @@ -15636,6 +15921,7 @@ "WFLAMA": "WIFLAMA", "WFLOW": "Wrapped Flow", "WFO": "WoofOracle", + "WFRAGSOL": "Wrapped fragSOL", "WFT": "Windfall Token", "WFTM": "Wrapped Fantom", "WFTN": "Wrapped FTN", @@ -15780,6 +16066,7 @@ "WNEON": "Wrapped Neon EVM", "WNET": "Wavesnode.net", "WNK": "The Winkyverse", + "WNKV1": "The Winkyverse v1", "WNOW": "WalletNow", "WNRG": "Wrapped-Energi", "WNRZ": "WinPlay", @@ -15830,6 +16117,7 @@ "WOR": "Hollywood Capital Group WARRIOR", "WORK": "Work X", "WORKE": "Worken", + "WORKIE": "Workie", "WORL": "World Record Banana", "WORLD": "World Token", "WORM": "HealthyWorm", @@ -15892,6 +16180,7 @@ "WTC": "Waltonchain", "WTE": "Wonder Energy Technology", "WTF": "Waterfall Governance", + "WTFO": "WTF Opossum", "WTFT": "WTF Token", "WTFUEL": "Wrapped TFUEL", "WTG": "Watergate", @@ -15944,6 +16233,7 @@ "X": "X Empire", "X2": "X2Coin", "X2Y2": "X2Y2", + "X33": "Shadow Liquid Staking Token", "X42": "X42 Protocol", "X7": "X7", "X7C": "X7 Coin", @@ -16162,7 +16452,7 @@ "XOX": "XOX Labs", "XOXNO": "XOXNO", "XOXO": "XO Protocol", - "XP": "Experience Points", + "XP": "Xphere", "XPA": "XPA", "XPAT": "Bitnation Pangea", "XPAY": "Wallet Pay", @@ -16252,6 +16542,7 @@ "XTAL": "XTAL", "XTC": "TileCoin", "XTECH": "X-TECH", + "XTER": "Xterio", "XTK": "xToken", "XTM": "TORUM", "XTN": "Neutrino Index Token", @@ -16503,11 +16794,13 @@ "ZEBU": "ZEBU", "ZEC": "ZCash", "ZECD": "ZCashDarkCoin", - "ZED": "ZedCoins", + "ZED": "ZED Token", + "ZEDCOIN": "ZedCoin", "ZEDD": "ZedDex", "ZEDTOKEN": "Zed Token", - "ZEDX": "ZEDXION", + "ZEDX": "ZEDX Сoin", "ZEDXION": "Zedxion", + "ZEDXIONV1": "Zedxion v1", "ZEE": "ZeroSwap", "ZEFI": "ZCore Finance", "ZEFU": "Zenfuse", @@ -16587,6 +16880,7 @@ "ZKEVM": "zkEVMChain (BSC)", "ZKEX": "zkExchange", "ZKF": "ZKFair", + "ZKGPT": "ZKGPT", "ZKGROK": "ZKGROK", "ZKGUN": "zkGUN", "ZKHIVE": "zkHive", From 7cebfbc9c29268ffd68749b231216ccf9703f3cc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 18 Apr 2025 11:18:50 +0200 Subject: [PATCH 29/62] Feature/update locales (#4556) Co-authored-by: github-actions[bot] --- apps/client/src/locales/messages.ca.xlf | 56 +++---------------------- apps/client/src/locales/messages.de.xlf | 56 +++---------------------- apps/client/src/locales/messages.es.xlf | 56 +++---------------------- apps/client/src/locales/messages.fr.xlf | 56 +++---------------------- apps/client/src/locales/messages.it.xlf | 56 +++---------------------- apps/client/src/locales/messages.nl.xlf | 56 +++---------------------- apps/client/src/locales/messages.pl.xlf | 56 +++---------------------- apps/client/src/locales/messages.pt.xlf | 56 +++---------------------- apps/client/src/locales/messages.tr.xlf | 56 +++---------------------- apps/client/src/locales/messages.uk.xlf | 56 +++---------------------- apps/client/src/locales/messages.xlf | 54 +++--------------------- apps/client/src/locales/messages.zh.xlf | 56 +++---------------------- 12 files changed, 72 insertions(+), 598 deletions(-) diff --git a/apps/client/src/locales/messages.ca.xlf b/apps/client/src/locales/messages.ca.xlf index 5c833ef23..6363de877 100644 --- a/apps/client/src/locales/messages.ca.xlf +++ b/apps/client/src/locales/messages.ca.xlf @@ -1149,22 +1149,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 210 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 - libs/ui/src/lib/account-balances/account-balances.component.html 34 @@ -1499,7 +1483,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 400 + 334 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -1543,7 +1527,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 407 + 341 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1611,7 +1595,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + 287 libs/ui/src/lib/assistant/assistant.html @@ -1639,7 +1623,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 + 303 @@ -1911,7 +1895,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + 272 @@ -2561,10 +2545,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 201 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 - Dividend Yield @@ -4673,47 +4653,23 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 213 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 - libs/ui/src/lib/activities-table/activities-table.component.html 210 - - Oops! Could not get the historical exchange rate from - Oops! Could not get the historical exchange rate from - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 - - Fee Fee apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 + 259 libs/ui/src/lib/activities-table/activities-table.component.html 234 - - Oops! Could not get the historical exchange rate from - Oops! Could not get the historical exchange rate from - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 - - Import Activities Import Activities diff --git a/apps/client/src/locales/messages.de.xlf b/apps/client/src/locales/messages.de.xlf index 945e369de..3ca9ddc95 100644 --- a/apps/client/src/locales/messages.de.xlf +++ b/apps/client/src/locales/messages.de.xlf @@ -212,22 +212,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 210 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 - libs/ui/src/lib/account-balances/account-balances.component.html 34 @@ -526,7 +510,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 400 + 334 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -570,7 +554,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 407 + 341 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1276,10 +1260,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 201 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 - Please set the amount of your emergency fund. @@ -2272,10 +2252,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 213 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 - libs/ui/src/lib/activities-table/activities-table.component.html 210 @@ -2286,11 +2262,7 @@ Gebühr apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 + 259 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2310,7 +2282,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + 272 @@ -2334,7 +2306,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + 287 libs/ui/src/lib/assistant/assistant.html @@ -2690,7 +2662,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 + 303 @@ -3829,14 +3801,6 @@ 2 - - Oops! Could not get the historical exchange rate from - Ups! Der historische Wechselkurs konnte nicht abgerufen werden vom - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 - - Retirement Date Pensionierungsdatum @@ -5826,14 +5790,6 @@ 41 - - Oops! Could not get the historical exchange rate from - Ups! Der historische Wechselkurs konnte nicht abgerufen werden vom - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 - - Fee Gebühr diff --git a/apps/client/src/locales/messages.es.xlf b/apps/client/src/locales/messages.es.xlf index 107336ecc..3f978ecc3 100644 --- a/apps/client/src/locales/messages.es.xlf +++ b/apps/client/src/locales/messages.es.xlf @@ -213,22 +213,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 210 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 - libs/ui/src/lib/account-balances/account-balances.component.html 34 @@ -527,7 +511,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 400 + 334 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -571,7 +555,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 407 + 341 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1261,10 +1245,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 201 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 - Please set the amount of your emergency fund. @@ -2257,10 +2237,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 213 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 - libs/ui/src/lib/activities-table/activities-table.component.html 210 @@ -2271,11 +2247,7 @@ Comisión apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 + 259 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2295,7 +2267,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + 272 @@ -2319,7 +2291,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + 287 libs/ui/src/lib/assistant/assistant.html @@ -2663,7 +2635,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 + 303 @@ -3814,14 +3786,6 @@ 2 - - Oops! Could not get the historical exchange rate from - Oops! Could not get the historical exchange rate from - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 - - Retirement Date Retirement Date @@ -5803,14 +5767,6 @@ 41 - - Oops! Could not get the historical exchange rate from - Oops! Could not get the historical exchange rate from - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 - - Fee Fee diff --git a/apps/client/src/locales/messages.fr.xlf b/apps/client/src/locales/messages.fr.xlf index da9e9e620..9e999ae3a 100644 --- a/apps/client/src/locales/messages.fr.xlf +++ b/apps/client/src/locales/messages.fr.xlf @@ -268,22 +268,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 210 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 - libs/ui/src/lib/account-balances/account-balances.component.html 34 @@ -582,7 +566,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 400 + 334 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -626,7 +610,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 407 + 341 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -662,7 +646,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + 287 libs/ui/src/lib/assistant/assistant.html @@ -690,7 +674,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 + 303 @@ -854,7 +838,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + 272 @@ -1608,10 +1592,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 201 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 - Please set the amount of your emergency fund. @@ -2476,10 +2456,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 213 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 - libs/ui/src/lib/activities-table/activities-table.component.html 210 @@ -2490,11 +2466,7 @@ Frais apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 + 259 libs/ui/src/lib/activities-table/activities-table.component.html @@ -3813,14 +3785,6 @@ 2 - - Oops! Could not get the historical exchange rate from - Oups ! Nous n’avons pas pu obtenir le taux de change historique à partir de - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 - - Retirement Date Date de Retraite @@ -5802,14 +5766,6 @@ 41 - - Oops! Could not get the historical exchange rate from - Oops! Echec de la récupération des données historiques depuis - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 - - Fee Frais diff --git a/apps/client/src/locales/messages.it.xlf b/apps/client/src/locales/messages.it.xlf index cf6eba907..00f70df4c 100644 --- a/apps/client/src/locales/messages.it.xlf +++ b/apps/client/src/locales/messages.it.xlf @@ -213,22 +213,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 210 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 - libs/ui/src/lib/account-balances/account-balances.component.html 34 @@ -527,7 +511,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 400 + 334 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -571,7 +555,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 407 + 341 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1261,10 +1245,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 201 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 - Please set the amount of your emergency fund. @@ -2257,10 +2237,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 213 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 - libs/ui/src/lib/activities-table/activities-table.component.html 210 @@ -2271,11 +2247,7 @@ Commissione apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 + 259 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2295,7 +2267,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + 272 @@ -2319,7 +2291,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + 287 libs/ui/src/lib/assistant/assistant.html @@ -2663,7 +2635,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 + 303 @@ -3814,14 +3786,6 @@ 2 - - Oops! Could not get the historical exchange rate from - Ops! Impossibile ottenere il tasso di cambio storico da - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 - - Retirement Date Data di pensionamento @@ -5803,14 +5767,6 @@ 41 - - Oops! Could not get the historical exchange rate from - Ops! Impossibile ottenere il tasso di cambio storico da - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 - - Fee Commissione diff --git a/apps/client/src/locales/messages.nl.xlf b/apps/client/src/locales/messages.nl.xlf index 29008f66c..a62aed365 100644 --- a/apps/client/src/locales/messages.nl.xlf +++ b/apps/client/src/locales/messages.nl.xlf @@ -212,22 +212,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 210 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 - libs/ui/src/lib/account-balances/account-balances.component.html 34 @@ -526,7 +510,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 400 + 334 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -570,7 +554,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 407 + 341 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1260,10 +1244,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 201 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 - Please set the amount of your emergency fund. @@ -2256,10 +2236,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 213 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 - libs/ui/src/lib/activities-table/activities-table.component.html 210 @@ -2270,11 +2246,7 @@ Transactiekosten apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 + 259 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2294,7 +2266,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + 272 @@ -2318,7 +2290,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + 287 libs/ui/src/lib/assistant/assistant.html @@ -2662,7 +2634,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 + 303 @@ -3813,14 +3785,6 @@ 2 - - Oops! Could not get the historical exchange rate from - Oeps! Kon de historische wisselkoers niet krijgen van - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 - - Retirement Date Pensioen Datum @@ -5802,14 +5766,6 @@ 41 - - Oops! Could not get the historical exchange rate from - Oops! Could not get the historical exchange rate from - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 - - Fee Fee diff --git a/apps/client/src/locales/messages.pl.xlf b/apps/client/src/locales/messages.pl.xlf index a888e4074..d255afe93 100644 --- a/apps/client/src/locales/messages.pl.xlf +++ b/apps/client/src/locales/messages.pl.xlf @@ -1077,22 +1077,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 210 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 - libs/ui/src/lib/account-balances/account-balances.component.html 34 @@ -1391,7 +1375,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 400 + 334 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -1435,7 +1419,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 407 + 341 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1503,7 +1487,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + 287 libs/ui/src/lib/assistant/assistant.html @@ -1531,7 +1515,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 + 303 @@ -1735,7 +1719,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + 272 @@ -2709,10 +2693,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 201 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 - Please set the amount of your emergency fund. @@ -4285,47 +4265,23 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 213 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 - libs/ui/src/lib/activities-table/activities-table.component.html 210 - - Oops! Could not get the historical exchange rate from - Ups! Nie udało się uzyskać historycznego kursu wymiany z - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 - - Fee Opłata apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 + 259 libs/ui/src/lib/activities-table/activities-table.component.html 234 - - Oops! Could not get the historical exchange rate from - Ups! Nie udało się uzyskać historycznego kursu wymiany z - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 - - Import Activities Importuj Aktywności diff --git a/apps/client/src/locales/messages.pt.xlf b/apps/client/src/locales/messages.pt.xlf index bebd4a752..80ded6ee4 100644 --- a/apps/client/src/locales/messages.pt.xlf +++ b/apps/client/src/locales/messages.pt.xlf @@ -268,22 +268,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 210 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 - libs/ui/src/lib/account-balances/account-balances.component.html 34 @@ -582,7 +566,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 400 + 334 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -626,7 +610,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 407 + 341 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -662,7 +646,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + 287 libs/ui/src/lib/assistant/assistant.html @@ -690,7 +674,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 + 303 @@ -1488,10 +1472,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 201 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 - Please set the amount of your emergency fund. @@ -2388,10 +2368,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 213 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 - libs/ui/src/lib/activities-table/activities-table.component.html 210 @@ -2402,11 +2378,7 @@ Comissão apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 + 259 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2426,7 +2398,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + 272 @@ -3813,14 +3785,6 @@ 2 - - Oops! Could not get the historical exchange rate from - Oops! Não foi possível obter a taxa de câmbio histórica de - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 - - Retirement Date Data da Reforma @@ -5802,14 +5766,6 @@ 41 - - Oops! Could not get the historical exchange rate from - Oops! Could not get the historical exchange rate from - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 - - Fee Fee diff --git a/apps/client/src/locales/messages.tr.xlf b/apps/client/src/locales/messages.tr.xlf index 424924dd6..c73a87433 100644 --- a/apps/client/src/locales/messages.tr.xlf +++ b/apps/client/src/locales/messages.tr.xlf @@ -1037,22 +1037,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 210 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 - libs/ui/src/lib/account-balances/account-balances.component.html 34 @@ -1351,7 +1335,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 400 + 334 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -1395,7 +1379,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 407 + 341 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1455,7 +1439,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + 287 libs/ui/src/lib/assistant/assistant.html @@ -1483,7 +1467,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 + 303 @@ -1655,7 +1639,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + 272 @@ -2533,10 +2517,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 201 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 - Please set the amount of your emergency fund. @@ -3765,33 +3745,17 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 213 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 - libs/ui/src/lib/activities-table/activities-table.component.html 210 - - Oops! Could not get the historical exchange rate from - Hay Allah! Geçmiş döviz kuru alınamadı: - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 - - Fee Komisyon apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 + 259 libs/ui/src/lib/activities-table/activities-table.component.html @@ -5810,14 +5774,6 @@ 49 - - Oops! Could not get the historical exchange rate from - Hay Allah! Tarihsel kur verisi elde edilemedi - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 - - Choose or drop a file here Dosya seçin ya da sürükleyin diff --git a/apps/client/src/locales/messages.uk.xlf b/apps/client/src/locales/messages.uk.xlf index 2141c7727..34abd7311 100644 --- a/apps/client/src/locales/messages.uk.xlf +++ b/apps/client/src/locales/messages.uk.xlf @@ -1165,22 +1165,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 210 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 - libs/ui/src/lib/account-balances/account-balances.component.html 34 @@ -1503,7 +1487,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + 287 libs/ui/src/lib/assistant/assistant.html @@ -1531,7 +1515,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 + 303 @@ -1803,7 +1787,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + 272 @@ -1843,7 +1827,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 400 + 334 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -1887,7 +1871,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 407 + 341 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -2689,10 +2673,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 201 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 - Dividend Yield @@ -4933,47 +4913,23 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 213 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 - libs/ui/src/lib/activities-table/activities-table.component.html 210 - - Oops! Could not get the historical exchange rate from - Упс! Не вдалося отримати історичний обмінний курс від - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 - - Fee Комісія apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 + 259 libs/ui/src/lib/activities-table/activities-table.component.html 234 - - Oops! Could not get the historical exchange rate from - Упс! Не вдалося отримати історичний обмінний курс від - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 - - Import Activities Імпортувати активності diff --git a/apps/client/src/locales/messages.xlf b/apps/client/src/locales/messages.xlf index 11f35ec57..0f868281d 100644 --- a/apps/client/src/locales/messages.xlf +++ b/apps/client/src/locales/messages.xlf @@ -1046,22 +1046,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 210 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 - libs/ui/src/lib/account-balances/account-balances.component.html 34 @@ -1341,7 +1325,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 400 + 334 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -1384,7 +1368,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 407 + 341 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1446,7 +1430,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + 287 libs/ui/src/lib/assistant/assistant.html @@ -1473,7 +1457,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 + 303 @@ -1681,7 +1665,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + 272 @@ -2556,10 +2540,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 201 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 - Please set the amount of your emergency fund. @@ -3969,44 +3949,22 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 213 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 - libs/ui/src/lib/activities-table/activities-table.component.html 210 - - Oops! Could not get the historical exchange rate from - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 - - Fee apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 + 259 libs/ui/src/lib/activities-table/activities-table.component.html 234 - - Oops! Could not get the historical exchange rate from - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 - - Import Activities diff --git a/apps/client/src/locales/messages.zh.xlf b/apps/client/src/locales/messages.zh.xlf index 38a4e5e64..1b8d853d2 100644 --- a/apps/client/src/locales/messages.zh.xlf +++ b/apps/client/src/locales/messages.zh.xlf @@ -1086,22 +1086,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 210 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 274 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 277 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 280 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 283 - libs/ui/src/lib/account-balances/account-balances.component.html 34 @@ -1400,7 +1384,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 400 + 334 apps/client/src/app/pages/register/show-access-token-dialog/show-access-token-dialog.html @@ -1444,7 +1428,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 407 + 341 libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html @@ -1512,7 +1496,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 354 + 287 libs/ui/src/lib/assistant/assistant.html @@ -1540,7 +1524,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 370 + 303 @@ -1744,7 +1728,7 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 339 + 272 @@ -2718,10 +2702,6 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 201 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 271 - Please set the amount of your emergency fund. @@ -4294,47 +4274,23 @@ apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 213 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 286 - libs/ui/src/lib/activities-table/activities-table.component.html 210 - - Oops! Could not get the historical exchange rate from - 哎呀!无法从以下来源获取历史汇率 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 318 - - Fee 费用 apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 306 - - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 330 + 259 libs/ui/src/lib/activities-table/activities-table.component.html 234 - - Oops! Could not get the historical exchange rate from - 哎呀!无法获取历史汇率 - - apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html - 240 - - Import Activities 导入活动 From f29f201a4f4164aefb748731488e61bf469f8ced Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 18 Apr 2025 14:04:39 +0200 Subject: [PATCH 30/62] Bugfix/add missing isActive flag in asset profile of custom currency (#4557) * Add missing isActive flag * Update changelog --- CHANGELOG.md | 4 ++++ apps/api/src/app/admin/admin.service.ts | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd111fd7c..2b3171dcd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Upgraded `chart.js` from version `4.4.7` to `4.4.9` - Upgraded `uuid` from version `11.0.5` to `11.1.0` +### Fixed + +- Fixed the functionality to open an asset profile of a custom currency in the admin control panel + ## 2.152.1 - 2025-04-17 ### Changed diff --git a/apps/api/src/app/admin/admin.service.ts b/apps/api/src/app/admin/admin.service.ts index f77d50aac..ccbec46f9 100644 --- a/apps/api/src/app/admin/admin.service.ts +++ b/apps/api/src/app/admin/admin.service.ts @@ -451,7 +451,8 @@ export class AdminService { currency, dataSource, dateOfFirstActivity, - symbol + symbol, + isActive: true } }; } From b6f87e46a73ecb2781a20648cda823c13c7c0b4d Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 18 Apr 2025 14:41:55 +0200 Subject: [PATCH 31/62] Bugfix/fix asset class parsing in Financial Modeling Prep service for exchange rates (#4559) * Fix the asset class parsing * Update changelog --- CHANGELOG.md | 1 + .../alpha-vantage/alpha-vantage.service.ts | 5 ++- .../financial-modeling-prep.service.ts | 41 +++++++++++++------ 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b3171dcd..0597a2e4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fixed the functionality to open an asset profile of a custom currency in the admin control panel +- Fixed the asset class parsing in the _Financial Modeling Prep_ service for exchange rates ## 2.152.1 - 2025-04-17 diff --git a/apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts b/apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts index 606e6b7fd..f9593f0d0 100644 --- a/apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts +++ b/apps/api/src/services/data-provider/alpha-vantage/alpha-vantage.service.ts @@ -11,6 +11,7 @@ import { IDataProviderHistoricalResponse, IDataProviderResponse } from '@ghostfolio/api/services/interfaces/interfaces'; +import { DEFAULT_CURRENCY } from '@ghostfolio/common/config'; import { DATE_FORMAT } from '@ghostfolio/common/helper'; import { DataProviderInfo, @@ -72,7 +73,9 @@ export class AlphaVantageService implements DataProviderInterface { const historicalData: { [symbol: string]: IAlphaVantageHistoricalResponse[]; } = await this.alphaVantage.crypto.daily( - symbol.substring(0, symbol.length - 3).toLowerCase(), + symbol + .substring(0, symbol.length - DEFAULT_CURRENCY.length) + .toLowerCase(), 'usd' ); diff --git a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts index d6eaec076..32aff4387 100644 --- a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts +++ b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts @@ -12,8 +12,11 @@ import { IDataProviderHistoricalResponse, IDataProviderResponse } from '@ghostfolio/api/services/interfaces/interfaces'; -import { REPLACE_NAME_PARTS } from '@ghostfolio/common/config'; -import { DATE_FORMAT, parseDate } from '@ghostfolio/common/helper'; +import { + DEFAULT_CURRENCY, + REPLACE_NAME_PARTS +} from '@ghostfolio/common/config'; +import { DATE_FORMAT, isCurrency, parseDate } from '@ghostfolio/common/helper'; import { DataProviderInfo, LookupItem, @@ -67,7 +70,15 @@ export class FinancialModelingPrepService implements DataProviderInterface { }; try { - if (this.cryptocurrencyService.isCryptocurrency(symbol)) { + if ( + isCurrency(symbol.substring(0, symbol.length - DEFAULT_CURRENCY.length)) + ) { + response.assetClass = AssetClass.LIQUIDITY; + response.assetSubClass = AssetSubClass.CASH; + response.currency = symbol.substring( + symbol.length - DEFAULT_CURRENCY.length + ); + } else if (this.cryptocurrencyService.isCryptocurrency(symbol)) { const [quote] = await fetch( `${this.URL}/quote/${symbol}?apikey=${this.apiKey}`, { @@ -77,7 +88,9 @@ export class FinancialModelingPrepService implements DataProviderInterface { response.assetClass = AssetClass.LIQUIDITY; response.assetSubClass = AssetSubClass.CRYPTOCURRENCY; - response.currency = symbol.substring(symbol.length - 3); + response.currency = symbol.substring( + symbol.length - DEFAULT_CURRENCY.length + ); response.name = quote.name; } else { const [assetProfile] = await fetch( @@ -472,15 +485,17 @@ export class FinancialModelingPrepService implements DataProviderInterface { let assetClass: AssetClass; let assetSubClass: AssetSubClass; - if (profile.isEtf) { - assetClass = AssetClass.EQUITY; - assetSubClass = AssetSubClass.ETF; - } else if (profile.isFund) { - assetClass = AssetClass.EQUITY; - assetSubClass = AssetSubClass.MUTUALFUND; - } else { - assetClass = AssetClass.EQUITY; - assetSubClass = AssetSubClass.STOCK; + if (profile) { + if (profile.isEtf) { + assetClass = AssetClass.EQUITY; + assetSubClass = AssetSubClass.ETF; + } else if (profile.isFund) { + assetClass = AssetClass.EQUITY; + assetSubClass = AssetSubClass.MUTUALFUND; + } else { + assetClass = AssetClass.EQUITY; + assetSubClass = AssetSubClass.STOCK; + } } return { assetClass, assetSubClass }; From f3022ca1f456a0cec4a34d47738a38130a514da1 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 18 Apr 2025 14:44:45 +0200 Subject: [PATCH 32/62] Release 2.153.0 (#4561) --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0597a2e4d..7bd31d5e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## 2.153.0 - 2025-04-18 ### Changed diff --git a/package-lock.json b/package-lock.json index 8868e11c8..426dfcfa3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ghostfolio", - "version": "2.152.1", + "version": "2.153.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "2.152.1", + "version": "2.153.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index 74ae55585..328aa59eb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "2.152.1", + "version": "2.153.0", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio", From 1b45ce8619d672203057be5811872c006d5ad344 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 18 Apr 2025 19:25:59 +0200 Subject: [PATCH 33/62] Feature/add watchlist to user database schema (#4560) * Add watchlist to user database schema * Update changelog --- CHANGELOG.md | 6 ++++++ .../migration.sql | 16 ++++++++++++++++ prisma/migrations/migration_lock.toml | 2 +- prisma/schema.prisma | 2 ++ 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 prisma/migrations/20250418123137_added_watchlist_to_user/migration.sql diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bd31d5e7..0874d91d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Added + +- Added `watchlist` to the `User` database schema as a preparation for watching assets + ## 2.153.0 - 2025-04-18 ### Changed diff --git a/prisma/migrations/20250418123137_added_watchlist_to_user/migration.sql b/prisma/migrations/20250418123137_added_watchlist_to_user/migration.sql new file mode 100644 index 000000000..25fd35041 --- /dev/null +++ b/prisma/migrations/20250418123137_added_watchlist_to_user/migration.sql @@ -0,0 +1,16 @@ +-- CreateTable +CREATE TABLE "_UserWatchlist" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL, + + CONSTRAINT "_UserWatchlist_AB_pkey" PRIMARY KEY ("A","B") +); + +-- CreateIndex +CREATE INDEX "_UserWatchlist_B_index" ON "_UserWatchlist"("B"); + +-- AddForeignKey +ALTER TABLE "_UserWatchlist" ADD CONSTRAINT "_UserWatchlist_A_fkey" FOREIGN KEY ("A") REFERENCES "SymbolProfile"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_UserWatchlist" ADD CONSTRAINT "_UserWatchlist_B_fkey" FOREIGN KEY ("B") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml index 648c57fd5..044d57cdb 100644 --- a/prisma/migrations/migration_lock.toml +++ b/prisma/migrations/migration_lock.toml @@ -1,3 +1,3 @@ # Please do not edit this file manually # It should be added in your version-control system (e.g., Git) -provider = "postgresql" \ No newline at end of file +provider = "postgresql" diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 29c98788f..637819fd8 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -191,6 +191,7 @@ model SymbolProfile { symbolMapping Json? url String? userId String? + watchedBy User[] @relation("UserWatchlist") Order Order[] SymbolProfileOverrides SymbolProfileOverrides? User User? @relation(fields: [userId], onDelete: Cascade, references: [id]) @@ -251,6 +252,7 @@ model User { role Role @default(USER) thirdPartyId String? updatedAt DateTime @updatedAt + watchlist SymbolProfile[] @relation("UserWatchlist") Access Access[] @relation("accessGet") AccessGive Access[] @relation("accessGive") Account Account[] From 81639662126877de4e80332068fa12648ee6908c Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 19 Apr 2025 10:18:37 +0200 Subject: [PATCH 34/62] Bugfix/fix word wrap in menu of historical market data table of admin control panel (#4562) * Fix word wrap * Update changelog --- CHANGELOG.md | 4 ++++ .../app/components/admin-market-data/admin-market-data.html | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0874d91d9..2f0057a0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `watchlist` to the `User` database schema as a preparation for watching assets +### Fixed + +- Fixed the word wrap in the menu of the historical market data table in the admin control panel + ## 2.153.0 - 2025-04-18 ### Changed diff --git a/apps/client/src/app/components/admin-market-data/admin-market-data.html b/apps/client/src/app/components/admin-market-data/admin-market-data.html index 8c092f960..6ba8f1810 100644 --- a/apps/client/src/app/components/admin-market-data/admin-market-data.html +++ b/apps/client/src/app/components/admin-market-data/admin-market-data.html @@ -215,7 +215,11 @@ > - + - + @if (deviceType !== 'mobile' && !searchFormControl.value) { +
/
+ } + @if (searchFormControl.value) { + + } @else { + + }
- -
No entries...
+ @if (isLoading) { + + } @else { +
No entries...
+ }
@@ -72,16 +72,18 @@ (clicked)="onCloseAssistant()" /> - -
No entries...
+ @if (isLoading) { + + } @else { +
No entries...
+ }
From 10580e22d1d380343ec98769fd169ff75de5d0ef Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 23 Apr 2025 20:23:20 +0200 Subject: [PATCH 52/62] Feature/migrate value component to control flow (#4592) * Migrate to control flow * Update changelog --- CHANGELOG.md | 1 + libs/ui/src/lib/value/value.component.html | 94 +++++++++++----------- 2 files changed, 50 insertions(+), 45 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0f000afa..ac62bb06c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Renamed `User` to `user` in the `Subscription` database schema - Migrated the `@ghostfolio/ui/assistant` component to control flow +- Migrated the `@ghostfolio/ui/value` component to control flow ### Fixed diff --git a/libs/ui/src/lib/value/value.component.html b/libs/ui/src/lib/value/value.component.html index 0ead7497e..e252ef8a2 100644 --- a/libs/ui/src/lib/value/value.component.html +++ b/libs/ui/src/lib/value/value.component.html @@ -13,42 +13,45 @@
+
-
-
- @if (value === null) { - *****% - } @else { - {{ formattedValue }}% - } -
-
- @if (value === null) { - ***** - } @else { - {{ formattedValue }} - } -
- - {{ unit }} - -
- {{ unit }} -
+ @if (isPercent) { +
+ @if (value === null) { + *****% + } @else { + {{ formattedValue }}% + } +
+ } @else { +
+ @if (value === null) { + ***** + } @else { + {{ formattedValue }} + } +
+ } + @if (unit) { + + {{ unit }} + +
+ {{ unit }} +
+ } - + @if (isString) {
+ @if (value === undefined) { + + }
From 50e7e3d3c786e9bcf45490f13664cedd3484a63b Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 23 Apr 2025 20:24:08 +0200 Subject: [PATCH 53/62] Feature/simplify data source checks in DTOs (#4581) * Simplify DataSource checks in DTOs * Add test case * Update changelog --- CHANGELOG.md | 2 ++ .../src/app/admin/update-asset-profile.dto.ts | 2 +- apps/api/src/app/order/create-order.dto.ts | 2 +- test/import/invalid-data-source.json | 18 ++++++++++++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 test/import/invalid-data-source.json diff --git a/CHANGELOG.md b/CHANGELOG.md index ac62bb06c..ffa35cf41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Simplified the data source check in the DTO of the activity creation +- Simplified the data source check in the DTO of the asset profile update - Renamed `User` to `user` in the `Subscription` database schema - Migrated the `@ghostfolio/ui/assistant` component to control flow - Migrated the `@ghostfolio/ui/value` component to control flow diff --git a/apps/api/src/app/admin/update-asset-profile.dto.ts b/apps/api/src/app/admin/update-asset-profile.dto.ts index 45923410a..5056dccdb 100644 --- a/apps/api/src/app/admin/update-asset-profile.dto.ts +++ b/apps/api/src/app/admin/update-asset-profile.dto.ts @@ -32,7 +32,7 @@ export class UpdateAssetProfileDto { @IsOptional() currency?: string; - @IsEnum(DataSource, { each: true }) + @IsEnum(DataSource) @IsOptional() dataSource?: DataSource; diff --git a/apps/api/src/app/order/create-order.dto.ts b/apps/api/src/app/order/create-order.dto.ts index f40e65ba1..c2b10fd81 100644 --- a/apps/api/src/app/order/create-order.dto.ts +++ b/apps/api/src/app/order/create-order.dto.ts @@ -49,7 +49,7 @@ export class CreateOrderDto { @IsOptional() customCurrency?: string; - @IsEnum(DataSource, { each: true }) + @IsEnum(DataSource) @IsOptional() dataSource?: DataSource; diff --git a/test/import/invalid-data-source.json b/test/import/invalid-data-source.json new file mode 100644 index 000000000..472e295ee --- /dev/null +++ b/test/import/invalid-data-source.json @@ -0,0 +1,18 @@ +{ + "meta": { + "date": "2021-01-01T00:00:00.000Z", + "version": "dev" + }, + "activities": [ + { + "currency": "USD", + "dataSource": "", + "date": "2021-01-01T00:00:00.000Z", + "fee": 0, + "quantity": 20, + "symbol": "AAPL", + "type": "BUY", + "unitPrice": 100.0 + } + ] +} From ac37974fd69c37b4954b20cadb63801b9713caf1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 23 Apr 2025 20:26:35 +0200 Subject: [PATCH 54/62] Feature/update locales (#4593) Co-authored-by: github-actions[bot] --- apps/client/src/locales/messages.ca.xlf | 20 ++++++++++---------- apps/client/src/locales/messages.de.xlf | 20 ++++++++++---------- apps/client/src/locales/messages.es.xlf | 20 ++++++++++---------- apps/client/src/locales/messages.fr.xlf | 20 ++++++++++---------- apps/client/src/locales/messages.it.xlf | 20 ++++++++++---------- apps/client/src/locales/messages.nl.xlf | 20 ++++++++++---------- apps/client/src/locales/messages.pl.xlf | 20 ++++++++++---------- apps/client/src/locales/messages.pt.xlf | 20 ++++++++++---------- apps/client/src/locales/messages.tr.xlf | 20 ++++++++++---------- apps/client/src/locales/messages.uk.xlf | 20 ++++++++++---------- apps/client/src/locales/messages.xlf | 20 ++++++++++---------- apps/client/src/locales/messages.zh.xlf | 20 ++++++++++---------- 12 files changed, 120 insertions(+), 120 deletions(-) diff --git a/apps/client/src/locales/messages.ca.xlf b/apps/client/src/locales/messages.ca.xlf index 41a5e9078..456e15790 100644 --- a/apps/client/src/locales/messages.ca.xlf +++ b/apps/client/src/locales/messages.ca.xlf @@ -1003,7 +1003,7 @@ libs/ui/src/lib/assistant/assistant.html - 46 + 44 @@ -1603,7 +1603,7 @@ libs/ui/src/lib/assistant/assistant.html - 166 + 168 @@ -4639,7 +4639,7 @@ libs/ui/src/lib/assistant/assistant.html - 107 + 109 @@ -4739,7 +4739,7 @@ libs/ui/src/lib/assistant/assistant.html - 127 + 129 @@ -6035,11 +6035,11 @@ No entries... libs/ui/src/lib/assistant/assistant.html - 63 + 62 libs/ui/src/lib/assistant/assistant.html - 84 + 85 @@ -6055,7 +6055,7 @@ Date Range libs/ui/src/lib/assistant/assistant.html - 93 + 95 @@ -6063,7 +6063,7 @@ Reset Filters libs/ui/src/lib/assistant/assistant.html - 185 + 187 @@ -6071,7 +6071,7 @@ Apply Filters libs/ui/src/lib/assistant/assistant.html - 195 + 197 @@ -7473,7 +7473,7 @@ Tag libs/ui/src/lib/assistant/assistant.html - 155 + 157 diff --git a/apps/client/src/locales/messages.de.xlf b/apps/client/src/locales/messages.de.xlf index 1cc922c39..10f26cddb 100644 --- a/apps/client/src/locales/messages.de.xlf +++ b/apps/client/src/locales/messages.de.xlf @@ -1666,7 +1666,7 @@ libs/ui/src/lib/assistant/assistant.html - 107 + 109 @@ -2186,7 +2186,7 @@ libs/ui/src/lib/assistant/assistant.html - 46 + 44 @@ -2314,7 +2314,7 @@ libs/ui/src/lib/assistant/assistant.html - 166 + 168 @@ -3358,7 +3358,7 @@ libs/ui/src/lib/assistant/assistant.html - 127 + 129 @@ -5963,11 +5963,11 @@ Keine Einträge vorhanden... libs/ui/src/lib/assistant/assistant.html - 63 + 62 libs/ui/src/lib/assistant/assistant.html - 84 + 85 @@ -6183,7 +6183,7 @@ Zeitraum libs/ui/src/lib/assistant/assistant.html - 93 + 95 @@ -6383,7 +6383,7 @@ Filter zurücksetzen libs/ui/src/lib/assistant/assistant.html - 185 + 187 @@ -6407,7 +6407,7 @@ Filter anwenden libs/ui/src/lib/assistant/assistant.html - 195 + 197 @@ -7497,7 +7497,7 @@ Tag libs/ui/src/lib/assistant/assistant.html - 155 + 157 diff --git a/apps/client/src/locales/messages.es.xlf b/apps/client/src/locales/messages.es.xlf index 555c95ac1..8ba704729 100644 --- a/apps/client/src/locales/messages.es.xlf +++ b/apps/client/src/locales/messages.es.xlf @@ -1651,7 +1651,7 @@ libs/ui/src/lib/assistant/assistant.html - 107 + 109 @@ -2171,7 +2171,7 @@ libs/ui/src/lib/assistant/assistant.html - 46 + 44 @@ -2299,7 +2299,7 @@ libs/ui/src/lib/assistant/assistant.html - 166 + 168 @@ -3343,7 +3343,7 @@ libs/ui/src/lib/assistant/assistant.html - 127 + 129 @@ -5940,11 +5940,11 @@ No entries... libs/ui/src/lib/assistant/assistant.html - 63 + 62 libs/ui/src/lib/assistant/assistant.html - 84 + 85 @@ -6160,7 +6160,7 @@ Date Range libs/ui/src/lib/assistant/assistant.html - 93 + 95 @@ -6360,7 +6360,7 @@ Reiniciar filtros libs/ui/src/lib/assistant/assistant.html - 185 + 187 @@ -6384,7 +6384,7 @@ Aplicar filtros libs/ui/src/lib/assistant/assistant.html - 195 + 197 @@ -7474,7 +7474,7 @@ Tag libs/ui/src/lib/assistant/assistant.html - 155 + 157 diff --git a/apps/client/src/locales/messages.fr.xlf b/apps/client/src/locales/messages.fr.xlf index fa1007391..78893b590 100644 --- a/apps/client/src/locales/messages.fr.xlf +++ b/apps/client/src/locales/messages.fr.xlf @@ -654,7 +654,7 @@ libs/ui/src/lib/assistant/assistant.html - 166 + 168 @@ -1906,7 +1906,7 @@ libs/ui/src/lib/assistant/assistant.html - 107 + 109 @@ -2798,7 +2798,7 @@ libs/ui/src/lib/assistant/assistant.html - 46 + 44 @@ -3342,7 +3342,7 @@ libs/ui/src/lib/assistant/assistant.html - 127 + 129 @@ -5939,11 +5939,11 @@ Pas d’entrées ... libs/ui/src/lib/assistant/assistant.html - 63 + 62 libs/ui/src/lib/assistant/assistant.html - 84 + 85 @@ -6159,7 +6159,7 @@ Intervalle de Date libs/ui/src/lib/assistant/assistant.html - 93 + 95 @@ -6359,7 +6359,7 @@ Réinitialiser les Filtres libs/ui/src/lib/assistant/assistant.html - 185 + 187 @@ -6383,7 +6383,7 @@ Appliquer les Filtres libs/ui/src/lib/assistant/assistant.html - 195 + 197 @@ -7473,7 +7473,7 @@ Étiquette libs/ui/src/lib/assistant/assistant.html - 155 + 157 diff --git a/apps/client/src/locales/messages.it.xlf b/apps/client/src/locales/messages.it.xlf index 081535681..c8c1a086d 100644 --- a/apps/client/src/locales/messages.it.xlf +++ b/apps/client/src/locales/messages.it.xlf @@ -1651,7 +1651,7 @@ libs/ui/src/lib/assistant/assistant.html - 107 + 109 @@ -2171,7 +2171,7 @@ libs/ui/src/lib/assistant/assistant.html - 46 + 44 @@ -2299,7 +2299,7 @@ libs/ui/src/lib/assistant/assistant.html - 166 + 168 @@ -3343,7 +3343,7 @@ libs/ui/src/lib/assistant/assistant.html - 127 + 129 @@ -5940,11 +5940,11 @@ Nessun risultato... libs/ui/src/lib/assistant/assistant.html - 63 + 62 libs/ui/src/lib/assistant/assistant.html - 84 + 85 @@ -6160,7 +6160,7 @@ Intervallo di date libs/ui/src/lib/assistant/assistant.html - 93 + 95 @@ -6360,7 +6360,7 @@ Reset Filtri libs/ui/src/lib/assistant/assistant.html - 185 + 187 @@ -6384,7 +6384,7 @@ Applica i Filtri libs/ui/src/lib/assistant/assistant.html - 195 + 197 @@ -7474,7 +7474,7 @@ Tag libs/ui/src/lib/assistant/assistant.html - 155 + 157 diff --git a/apps/client/src/locales/messages.nl.xlf b/apps/client/src/locales/messages.nl.xlf index 6852f7260..7c5066ad6 100644 --- a/apps/client/src/locales/messages.nl.xlf +++ b/apps/client/src/locales/messages.nl.xlf @@ -1650,7 +1650,7 @@ libs/ui/src/lib/assistant/assistant.html - 107 + 109 @@ -2170,7 +2170,7 @@ libs/ui/src/lib/assistant/assistant.html - 46 + 44 @@ -2298,7 +2298,7 @@ libs/ui/src/lib/assistant/assistant.html - 166 + 168 @@ -3342,7 +3342,7 @@ libs/ui/src/lib/assistant/assistant.html - 127 + 129 @@ -5939,11 +5939,11 @@ No entries... libs/ui/src/lib/assistant/assistant.html - 63 + 62 libs/ui/src/lib/assistant/assistant.html - 84 + 85 @@ -6159,7 +6159,7 @@ Date Range libs/ui/src/lib/assistant/assistant.html - 93 + 95 @@ -6359,7 +6359,7 @@ Reset Filters libs/ui/src/lib/assistant/assistant.html - 185 + 187 @@ -6383,7 +6383,7 @@ Apply Filters libs/ui/src/lib/assistant/assistant.html - 195 + 197 @@ -7473,7 +7473,7 @@ Tag libs/ui/src/lib/assistant/assistant.html - 155 + 157 diff --git a/apps/client/src/locales/messages.pl.xlf b/apps/client/src/locales/messages.pl.xlf index e7c42b11b..4970c3d53 100644 --- a/apps/client/src/locales/messages.pl.xlf +++ b/apps/client/src/locales/messages.pl.xlf @@ -1495,7 +1495,7 @@ libs/ui/src/lib/assistant/assistant.html - 166 + 168 @@ -4251,7 +4251,7 @@ libs/ui/src/lib/assistant/assistant.html - 107 + 109 @@ -4351,7 +4351,7 @@ libs/ui/src/lib/assistant/assistant.html - 127 + 129 @@ -4751,7 +4751,7 @@ libs/ui/src/lib/assistant/assistant.html - 46 + 44 @@ -5499,11 +5499,11 @@ Brak wpisów... libs/ui/src/lib/assistant/assistant.html - 63 + 62 libs/ui/src/lib/assistant/assistant.html - 84 + 85 @@ -6159,7 +6159,7 @@ Zakres Dat libs/ui/src/lib/assistant/assistant.html - 93 + 95 @@ -6359,7 +6359,7 @@ Resetuj Filtry libs/ui/src/lib/assistant/assistant.html - 185 + 187 @@ -6383,7 +6383,7 @@ Zastosuj Filtry libs/ui/src/lib/assistant/assistant.html - 195 + 197 @@ -7473,7 +7473,7 @@ Tag libs/ui/src/lib/assistant/assistant.html - 155 + 157 diff --git a/apps/client/src/locales/messages.pt.xlf b/apps/client/src/locales/messages.pt.xlf index 414bacda8..84a3a0061 100644 --- a/apps/client/src/locales/messages.pt.xlf +++ b/apps/client/src/locales/messages.pt.xlf @@ -654,7 +654,7 @@ libs/ui/src/lib/assistant/assistant.html - 166 + 168 @@ -1890,7 +1890,7 @@ libs/ui/src/lib/assistant/assistant.html - 107 + 109 @@ -2694,7 +2694,7 @@ libs/ui/src/lib/assistant/assistant.html - 46 + 44 @@ -3342,7 +3342,7 @@ libs/ui/src/lib/assistant/assistant.html - 127 + 129 @@ -5939,11 +5939,11 @@ No entries... libs/ui/src/lib/assistant/assistant.html - 63 + 62 libs/ui/src/lib/assistant/assistant.html - 84 + 85 @@ -6159,7 +6159,7 @@ Date Range libs/ui/src/lib/assistant/assistant.html - 93 + 95 @@ -6359,7 +6359,7 @@ Reset Filters libs/ui/src/lib/assistant/assistant.html - 185 + 187 @@ -6383,7 +6383,7 @@ Apply Filters libs/ui/src/lib/assistant/assistant.html - 195 + 197 @@ -7473,7 +7473,7 @@ Tag libs/ui/src/lib/assistant/assistant.html - 155 + 157 diff --git a/apps/client/src/locales/messages.tr.xlf b/apps/client/src/locales/messages.tr.xlf index 78a66fc99..97457c7a0 100644 --- a/apps/client/src/locales/messages.tr.xlf +++ b/apps/client/src/locales/messages.tr.xlf @@ -1447,7 +1447,7 @@ libs/ui/src/lib/assistant/assistant.html - 166 + 168 @@ -3731,7 +3731,7 @@ libs/ui/src/lib/assistant/assistant.html - 107 + 109 @@ -3831,7 +3831,7 @@ libs/ui/src/lib/assistant/assistant.html - 127 + 129 @@ -4223,7 +4223,7 @@ libs/ui/src/lib/assistant/assistant.html - 46 + 44 @@ -5939,11 +5939,11 @@ Girdi yok... libs/ui/src/lib/assistant/assistant.html - 63 + 62 libs/ui/src/lib/assistant/assistant.html - 84 + 85 @@ -6159,7 +6159,7 @@ Date Range libs/ui/src/lib/assistant/assistant.html - 93 + 95 @@ -6359,7 +6359,7 @@ Reset Filters libs/ui/src/lib/assistant/assistant.html - 185 + 187 @@ -6383,7 +6383,7 @@ Apply Filters libs/ui/src/lib/assistant/assistant.html - 195 + 197 @@ -7473,7 +7473,7 @@ Tag libs/ui/src/lib/assistant/assistant.html - 155 + 157 diff --git a/apps/client/src/locales/messages.uk.xlf b/apps/client/src/locales/messages.uk.xlf index 47fb7663a..dae661112 100644 --- a/apps/client/src/locales/messages.uk.xlf +++ b/apps/client/src/locales/messages.uk.xlf @@ -1019,7 +1019,7 @@ libs/ui/src/lib/assistant/assistant.html - 46 + 44 @@ -1495,7 +1495,7 @@ libs/ui/src/lib/assistant/assistant.html - 166 + 168 @@ -4879,7 +4879,7 @@ libs/ui/src/lib/assistant/assistant.html - 107 + 109 @@ -4999,7 +4999,7 @@ libs/ui/src/lib/assistant/assistant.html - 127 + 129 @@ -6681,11 +6681,11 @@ Немає записів... libs/ui/src/lib/assistant/assistant.html - 63 + 62 libs/ui/src/lib/assistant/assistant.html - 84 + 85 @@ -6701,7 +6701,7 @@ Діапазон дат libs/ui/src/lib/assistant/assistant.html - 93 + 95 @@ -6709,7 +6709,7 @@ Тег libs/ui/src/lib/assistant/assistant.html - 155 + 157 @@ -6717,7 +6717,7 @@ Скинути фільтри libs/ui/src/lib/assistant/assistant.html - 185 + 187 @@ -6725,7 +6725,7 @@ Застосувати фільтри libs/ui/src/lib/assistant/assistant.html - 195 + 197 diff --git a/apps/client/src/locales/messages.xlf b/apps/client/src/locales/messages.xlf index ad4e1a3ad..d8a7b552c 100644 --- a/apps/client/src/locales/messages.xlf +++ b/apps/client/src/locales/messages.xlf @@ -1438,7 +1438,7 @@ libs/ui/src/lib/assistant/assistant.html - 166 + 168 @@ -3937,7 +3937,7 @@ libs/ui/src/lib/assistant/assistant.html - 107 + 109 @@ -4026,7 +4026,7 @@ libs/ui/src/lib/assistant/assistant.html - 127 + 129 @@ -4383,7 +4383,7 @@ libs/ui/src/lib/assistant/assistant.html - 46 + 44 @@ -5084,11 +5084,11 @@ No entries... libs/ui/src/lib/assistant/assistant.html - 63 + 62 libs/ui/src/lib/assistant/assistant.html - 84 + 85 @@ -5616,7 +5616,7 @@ Date Range libs/ui/src/lib/assistant/assistant.html - 93 + 95 @@ -5801,7 +5801,7 @@ Reset Filters libs/ui/src/lib/assistant/assistant.html - 185 + 187 @@ -5829,7 +5829,7 @@ Apply Filters libs/ui/src/lib/assistant/assistant.html - 195 + 197 @@ -6766,7 +6766,7 @@ Tag libs/ui/src/lib/assistant/assistant.html - 155 + 157 diff --git a/apps/client/src/locales/messages.zh.xlf b/apps/client/src/locales/messages.zh.xlf index 12ed4498b..6305867a3 100644 --- a/apps/client/src/locales/messages.zh.xlf +++ b/apps/client/src/locales/messages.zh.xlf @@ -1504,7 +1504,7 @@ libs/ui/src/lib/assistant/assistant.html - 166 + 168 @@ -4260,7 +4260,7 @@ libs/ui/src/lib/assistant/assistant.html - 107 + 109 @@ -4360,7 +4360,7 @@ libs/ui/src/lib/assistant/assistant.html - 127 + 129 @@ -4760,7 +4760,7 @@ libs/ui/src/lib/assistant/assistant.html - 46 + 44 @@ -5540,11 +5540,11 @@ 没有条目... libs/ui/src/lib/assistant/assistant.html - 63 + 62 libs/ui/src/lib/assistant/assistant.html - 84 + 85 @@ -6144,7 +6144,7 @@ 日期范围 libs/ui/src/lib/assistant/assistant.html - 93 + 95 @@ -6352,7 +6352,7 @@ 重置过滤器 libs/ui/src/lib/assistant/assistant.html - 185 + 187 @@ -6384,7 +6384,7 @@ 应用过滤器 libs/ui/src/lib/assistant/assistant.html - 195 + 197 @@ -7474,7 +7474,7 @@ Tag libs/ui/src/lib/assistant/assistant.html - 155 + 157 From 8dcf04019d7b87daf4d4d1cbef0289daec96ac16 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 23 Apr 2025 20:27:06 +0200 Subject: [PATCH 55/62] Feature/update locales (#4594) Co-authored-by: github-actions[bot] From 4c63e08e3c84e51876d49ae576bc0773f3618aa1 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 23 Apr 2025 20:29:27 +0200 Subject: [PATCH 56/62] Release 2.155.0 (#4595) --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ffa35cf41..fcc336b31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## 2.155.0 - 2025-04-23 ### Added diff --git a/package-lock.json b/package-lock.json index 51ddd7bc2..a45d5d875 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ghostfolio", - "version": "2.154.0", + "version": "2.155.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "2.154.0", + "version": "2.155.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index 4d8616297..64fc87aa0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "2.154.0", + "version": "2.155.0", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio", From 447fe1806fa4fb33fb2d97371b43dd6698909f59 Mon Sep 17 00:00:00 2001 From: Vinodh Zamboulingame <48854069+vzamboulingame@users.noreply.github.com> Date: Thu, 24 Apr 2025 20:40:12 +0200 Subject: [PATCH 57/62] Bugfix/fix activities import of files with extension in uppercase (#4596) * Fix activities import of files with extension in uppercase * Update changelog --- CHANGELOG.md | 6 ++++++ .../import-activities-dialog.component.ts | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fcc336b31..db8312af0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Fixed + +- Improved the file selector of the activities import functionality to accept case-insensitive file extensions (`.CSV` and `.JSON`) + ## 2.155.0 - 2025-04-23 ### Added diff --git a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts index 82e78a180..20f135801 100644 --- a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts @@ -247,9 +247,10 @@ export class ImportActivitiesDialog implements OnDestroy { reader.onload = async (readerEvent) => { const fileContent = readerEvent.target.result as string; + const fileExtension = file.name.split('.').pop()?.toLowerCase(); try { - if (file.name.endsWith('.json')) { + if (fileExtension === 'json') { const content = JSON.parse(fileContent); this.accounts = content.accounts; @@ -294,7 +295,7 @@ export class ImportActivitiesDialog implements OnDestroy { } return; - } else if (file.name.endsWith('.csv')) { + } else if (fileExtension === 'csv') { const content = fileContent.split('\n').slice(1); try { From 3b59d7989a23c9dd6c59c12b604cb8ad0d6c801b Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Fri, 25 Apr 2025 08:24:16 +0200 Subject: [PATCH 58/62] Feature/improve currency code validation (#4598) * Improve currency code validation * Update changelog --- CHANGELOG.md | 5 +++++ apps/api/src/validators/is-currency-code.ts | 21 +++++++++++++-------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db8312af0..328d7749e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Changed + +- Improved the error message of the currency code validation +- Tightened the currency code validation by requiring uppercase letters + ### Fixed - Improved the file selector of the activities import functionality to accept case-insensitive file extensions (`.CSV` and `.JSON`) diff --git a/apps/api/src/validators/is-currency-code.ts b/apps/api/src/validators/is-currency-code.ts index 34a82c481..d04da7808 100644 --- a/apps/api/src/validators/is-currency-code.ts +++ b/apps/api/src/validators/is-currency-code.ts @@ -25,19 +25,24 @@ export class IsExtendedCurrencyConstraint implements ValidatorConstraintInterface { public defaultMessage() { - return '$value must be a valid ISO4217 currency code'; + return '$property must be a valid ISO4217 currency code'; } public validate(currency: any) { // Return true if currency is a standard ISO 4217 code or a derived currency return ( - isISO4217CurrencyCode(currency) || - [ - ...DERIVED_CURRENCIES.map((derivedCurrency) => { - return derivedCurrency.currency; - }), - 'USX' - ].includes(currency) + this.isUpperCase(currency) && + (isISO4217CurrencyCode(currency) || + [ + ...DERIVED_CURRENCIES.map((derivedCurrency) => { + return derivedCurrency.currency; + }), + 'USX' + ].includes(currency)) ); } + + private isUpperCase(aString: string) { + return aString === aString?.toUpperCase(); + } } From 68dcd4006b191276d3e290acc05bb46f5ee68f1e Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 25 Apr 2025 18:04:16 +0200 Subject: [PATCH 59/62] Merge Conflict Fixes + remove cpr and add calculate networth to base portfolio calculator --- .../portfolio-calculator.ts | 595 ------------------ .../portfolio-calculator.factory.ts | 34 +- .../calculator/portfolio-calculator.ts | 271 +++++++- .../src/app/portfolio/portfolio.controller.ts | 6 +- .../src/app/portfolio/portfolio.service.ts | 25 +- .../data-gathering.processor.ts | 3 +- package-lock.json | 79 +-- 7 files changed, 310 insertions(+), 703 deletions(-) delete mode 100644 apps/api/src/app/portfolio/calculator/constantPortfolioReturn/portfolio-calculator.ts diff --git a/apps/api/src/app/portfolio/calculator/constantPortfolioReturn/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/constantPortfolioReturn/portfolio-calculator.ts deleted file mode 100644 index c5d73e6d6..000000000 --- a/apps/api/src/app/portfolio/calculator/constantPortfolioReturn/portfolio-calculator.ts +++ /dev/null @@ -1,595 +0,0 @@ -import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; -import { OrderService } from '@ghostfolio/api/app/order/order.service'; -import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; -import { getFactor } from '@ghostfolio/api/helper/portfolio.helper'; -import { LogPerformance } from '@ghostfolio/api/interceptors/performance-logging/performance-logging.interceptor'; -import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; -import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; -import { IDataGatheringItem } from '@ghostfolio/api/services/interfaces/interfaces'; -import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; -import { DATE_FORMAT, parseDate, resetHours } from '@ghostfolio/common/helper'; -import { Filter, HistoricalDataItem } from '@ghostfolio/common/interfaces'; - -import { Inject, Logger } from '@nestjs/common'; -import { Big } from 'big.js'; -import { - addDays, - eachDayOfInterval, - endOfDay, - format, - isAfter, - isBefore, - subDays -} from 'date-fns'; - -import { CurrentRateService } from '../../current-rate.service'; -import { DateQuery } from '../../interfaces/date-query.interface'; -import { PortfolioOrder } from '../../interfaces/portfolio-order.interface'; -import { RoaiPortfolioCalculator } from '../roai/portfolio-calculator'; - -export class CPRPortfolioCalculator extends RoaiPortfolioCalculator { - private holdings: { [date: string]: { [symbol: string]: Big } } = {}; - private holdingCurrencies: { [symbol: string]: string } = {}; - - constructor( - { - accountBalanceItems, - activities, - configurationService, - currency, - currentRateService, - exchangeRateDataService, - portfolioSnapshotService, - redisCacheService, - userId, - filters - }: { - accountBalanceItems: HistoricalDataItem[]; - activities: Activity[]; - configurationService: ConfigurationService; - currency: string; - currentRateService: CurrentRateService; - exchangeRateDataService: ExchangeRateDataService; - portfolioSnapshotService: PortfolioSnapshotService; - redisCacheService: RedisCacheService; - filters: Filter[]; - userId: string; - }, - @Inject() - private orderService: OrderService - ) { - super({ - accountBalanceItems, - activities, - configurationService, - currency, - filters, - currentRateService, - exchangeRateDataService, - portfolioSnapshotService, - redisCacheService, - userId - }); - } - - @LogPerformance - public async getPerformanceWithTimeWeightedReturn({ - start, - end - }: { - start: Date; - end: Date; - }): Promise<{ chart: HistoricalDataItem[] }> { - const item = await super.getPerformance({ - end, - start - }); - - const itemResult = item.chart; - const dates = itemResult.map((item) => parseDate(item.date)); - const timeWeighted = await this.getTimeWeightedChartData({ - dates - }); - - item.chart = itemResult.map((itemInt) => { - const timeWeightedItem = timeWeighted.find( - (timeWeightedItem) => timeWeightedItem.date === itemInt.date - ); - if (timeWeightedItem) { - itemInt.timeWeightedPerformance = - timeWeightedItem.netPerformanceInPercentage; - itemInt.timeWeightedPerformanceWithCurrencyEffect = - timeWeightedItem.netPerformanceInPercentageWithCurrencyEffect; - } - - return itemInt; - }); - return item; - } - - @LogPerformance - public async getUnfilteredNetWorth(currency: string): Promise { - const activities = await this.orderService.getOrders({ - userId: this.userId, - userCurrency: currency, - types: ['BUY', 'SELL', 'STAKE'], - withExcludedAccounts: true - }); - const orders = this.activitiesToPortfolioOrder(activities.activities); - const start = orders.reduce( - (date, order) => - parseDate(date.date).getTime() < parseDate(order.date).getTime() - ? date - : order, - { date: orders[0].date } - ).date; - - const end = new Date(Date.now()); - - const holdings = await this.getHoldings(orders, parseDate(start), end); - const marketMap = await this.currentRateService.getValues({ - dataGatheringItems: this.mapToDataGatheringItems(orders), - dateQuery: { in: [end] } - }); - const endString = format(end, DATE_FORMAT); - const exchangeRates = await Promise.all( - Object.keys(holdings[endString]).map(async (holding) => { - const symbolCurrency = this.getCurrencyFromActivities(orders, holding); - const exchangeRate = - await this.exchangeRateDataService.toCurrencyAtDate( - 1, - symbolCurrency, - this.currency, - end - ); - return { symbolCurrency, exchangeRate }; - }) - ); - const currencyRates = exchangeRates.reduce<{ [currency: string]: number }>( - (all, currency): { [currency: string]: number } => { - all[currency.symbolCurrency] ??= currency.exchangeRate; - return all; - }, - {} - ); - - const totalInvestment = await Object.keys(holdings[endString]).reduce( - (sum, holding) => { - if (!holdings[endString][holding].toNumber()) { - return sum; - } - const symbol = marketMap.values.find((m) => m.symbol === holding); - - if (symbol?.marketPrice === undefined) { - Logger.warn( - `Missing historical market data for ${holding} (${end})`, - 'PortfolioCalculator' - ); - return sum; - } else { - const symbolCurrency = this.getCurrency(holding); - const price = new Big(currencyRates[symbolCurrency]).mul( - symbol.marketPrice - ); - return sum.plus(new Big(price).mul(holdings[endString][holding])); - } - }, - new Big(0) - ); - return totalInvestment; - } - - @LogPerformance - protected async getTimeWeightedChartData({ - dates - }: { - dates?: Date[]; - }): Promise { - dates = dates.sort((a, b) => a.getTime() - b.getTime()); - const start = dates[0]; - const end = dates[dates.length - 1]; - const marketMapTask = this.computeMarketMap({ - gte: start, - lt: addDays(end, 1) - }); - const timelineHoldings = await this.getHoldings( - this.activities, - start, - end - ); - - const data: HistoricalDataItem[] = []; - const startString = format(start, DATE_FORMAT); - - data.push({ - date: startString, - netPerformanceInPercentage: 0, - netPerformanceInPercentageWithCurrencyEffect: 0, - investmentValueWithCurrencyEffect: 0, - netPerformance: 0, - netPerformanceWithCurrencyEffect: 0, - netWorth: 0, - totalAccountBalance: 0, - totalInvestment: 0, - totalInvestmentValueWithCurrencyEffect: 0, - value: 0, - valueWithCurrencyEffect: 0 - }); - - this.marketMap = await marketMapTask; - - let totalInvestment = Object.keys(timelineHoldings[startString]).reduce( - (sum, holding) => { - return sum.plus( - timelineHoldings[startString][holding].mul( - this.marketMap[startString][holding] ?? new Big(0) - ) - ); - }, - new Big(0) - ); - - let previousNetPerformanceInPercentage = new Big(0); - let previousNetPerformanceInPercentageWithCurrencyEffect = new Big(0); - - for (let i = 1; i < dates.length; i++) { - const date = format(dates[i], DATE_FORMAT); - const previousDate = format(dates[i - 1], DATE_FORMAT); - const holdings = timelineHoldings[previousDate]; - let newTotalInvestment = new Big(0); - let netPerformanceInPercentage = new Big(0); - let netPerformanceInPercentageWithCurrencyEffect = new Big(0); - - for (const holding of Object.keys(holdings)) { - ({ - netPerformanceInPercentage, - netPerformanceInPercentageWithCurrencyEffect, - newTotalInvestment - } = await this.handleSingleHolding( - previousDate, - holding, - date, - totalInvestment, - timelineHoldings, - netPerformanceInPercentage, - netPerformanceInPercentageWithCurrencyEffect, - newTotalInvestment - )); - } - totalInvestment = newTotalInvestment; - - previousNetPerformanceInPercentage = previousNetPerformanceInPercentage - .plus(1) - .mul(netPerformanceInPercentage.plus(1)) - .minus(1); - previousNetPerformanceInPercentageWithCurrencyEffect = - previousNetPerformanceInPercentageWithCurrencyEffect - .plus(1) - .mul(netPerformanceInPercentageWithCurrencyEffect.plus(1)) - .minus(1); - - data.push({ - date, - netPerformanceInPercentage: previousNetPerformanceInPercentage - .mul(100) - .toNumber(), - netPerformanceInPercentageWithCurrencyEffect: - previousNetPerformanceInPercentageWithCurrencyEffect - .mul(100) - .toNumber() - }); - } - - return data; - } - - @LogPerformance - protected async handleSingleHolding( - previousDate: string, - holding: string, - date: string, - totalInvestment: Big, - timelineHoldings: { [date: string]: { [symbol: string]: Big } }, - netPerformanceInPercentage: Big, - netPerformanceInPercentageWithCurrencyEffect: Big, - newTotalInvestment: Big - ) { - const previousPrice = - Object.keys(this.marketMap).indexOf(previousDate) > 0 - ? this.marketMap[previousDate][holding] - : undefined; - const priceDictionary = this.marketMap[date]; - let currentPrice = - priceDictionary !== undefined ? priceDictionary[holding] : previousPrice; - currentPrice ??= previousPrice; - const previousHolding = timelineHoldings[previousDate][holding]; - - const priceInBaseCurrency = currentPrice - ? new Big( - await this.exchangeRateDataService.toCurrencyAtDate( - currentPrice?.toNumber() ?? 0, - this.getCurrency(holding), - this.currency, - parseDate(date) - ) - ) - : new Big(0); - - if (previousHolding.eq(0)) { - return { - netPerformanceInPercentage: netPerformanceInPercentage, - netPerformanceInPercentageWithCurrencyEffect: - netPerformanceInPercentageWithCurrencyEffect, - newTotalInvestment: newTotalInvestment.plus( - timelineHoldings[date][holding].mul(priceInBaseCurrency) - ) - }; - } - if (previousPrice === undefined || currentPrice === undefined) { - Logger.warn( - `Missing historical market data for ${holding} (${previousPrice === undefined ? previousDate : date}})`, - 'PortfolioCalculator' - ); - return { - netPerformanceInPercentage: netPerformanceInPercentage, - netPerformanceInPercentageWithCurrencyEffect: - netPerformanceInPercentageWithCurrencyEffect, - newTotalInvestment: newTotalInvestment.plus( - timelineHoldings[date][holding].mul(priceInBaseCurrency) - ) - }; - } - const previousPriceInBaseCurrency = previousPrice - ? new Big( - await this.exchangeRateDataService.toCurrencyAtDate( - previousPrice?.toNumber() ?? 0, - this.getCurrency(holding), - this.currency, - parseDate(previousDate) - ) - ) - : new Big(0); - const portfolioWeight = totalInvestment.toNumber() - ? previousHolding.mul(previousPriceInBaseCurrency).div(totalInvestment) - : new Big(0); - - netPerformanceInPercentage = netPerformanceInPercentage.plus( - currentPrice.div(previousPrice).minus(1).mul(portfolioWeight) - ); - - netPerformanceInPercentageWithCurrencyEffect = - netPerformanceInPercentageWithCurrencyEffect.plus( - priceInBaseCurrency - .div(previousPriceInBaseCurrency) - .minus(1) - .mul(portfolioWeight) - ); - - newTotalInvestment = newTotalInvestment.plus( - timelineHoldings[date][holding].mul(priceInBaseCurrency) - ); - return { - netPerformanceInPercentage, - netPerformanceInPercentageWithCurrencyEffect, - newTotalInvestment - }; - } - - @LogPerformance - protected getCurrency(symbol: string) { - return this.getCurrencyFromActivities(this.activities, symbol); - } - - @LogPerformance - protected getCurrencyFromActivities( - activities: PortfolioOrder[], - symbol: string - ) { - if (!this.holdingCurrencies[symbol]) { - this.holdingCurrencies[symbol] = activities.find( - (a) => a.SymbolProfile.symbol === symbol - ).SymbolProfile.currency; - } - - return this.holdingCurrencies[symbol]; - } - - @LogPerformance - protected async getHoldings( - activities: PortfolioOrder[], - start: Date, - end: Date - ) { - if ( - this.holdings && - Object.keys(this.holdings).some((h) => - isAfter(parseDate(h), subDays(end, 1)) - ) && - Object.keys(this.holdings).some((h) => - isBefore(parseDate(h), addDays(start, 1)) - ) - ) { - return this.holdings; - } - - this.computeHoldings(activities, start, end); - return this.holdings; - } - - @LogPerformance - protected async computeHoldings( - activities: PortfolioOrder[], - start: Date, - end: Date - ) { - const investmentByDate = this.getInvestmentByDate(activities); - this.calculateHoldings(investmentByDate, start, end); - } - - private calculateHoldings( - investmentByDate: { [date: string]: PortfolioOrder[] }, - start: Date, - end: Date - ) { - const transactionDates = Object.keys(investmentByDate).sort(); - const dates = eachDayOfInterval({ start, end }, { step: 1 }) - .map((date) => { - return resetHours(date); - }) - .sort((a, b) => a.getTime() - b.getTime()); - const currentHoldings: { [date: string]: { [symbol: string]: Big } } = {}; - - this.calculateInitialHoldings(investmentByDate, start, currentHoldings); - - for (let i = 1; i < dates.length; i++) { - const dateString = format(dates[i], DATE_FORMAT); - const previousDateString = format(dates[i - 1], DATE_FORMAT); - if (transactionDates.some((d) => d === dateString)) { - const holdings = { ...currentHoldings[previousDateString] }; - investmentByDate[dateString].forEach((trade) => { - holdings[trade.SymbolProfile.symbol] ??= new Big(0); - holdings[trade.SymbolProfile.symbol] = holdings[ - trade.SymbolProfile.symbol - ].plus(trade.quantity.mul(getFactor(trade.type))); - }); - currentHoldings[dateString] = holdings; - } else { - currentHoldings[dateString] = currentHoldings[previousDateString]; - } - } - - this.holdings = currentHoldings; - } - - @LogPerformance - protected calculateInitialHoldings( - investmentByDate: { [date: string]: PortfolioOrder[] }, - start: Date, - currentHoldings: { [date: string]: { [symbol: string]: Big } } - ) { - const preRangeTrades = Object.keys(investmentByDate) - .filter((date) => resetHours(new Date(date)) <= start) - .map((date) => investmentByDate[date]) - .reduce((a, b) => a.concat(b), []) - .reduce((groupBySymbol, trade) => { - if (!groupBySymbol[trade.SymbolProfile.symbol]) { - groupBySymbol[trade.SymbolProfile.symbol] = []; - } - - groupBySymbol[trade.SymbolProfile.symbol].push(trade); - - return groupBySymbol; - }, {}); - - currentHoldings[format(start, DATE_FORMAT)] = {}; - - for (const symbol of Object.keys(preRangeTrades)) { - const trades: PortfolioOrder[] = preRangeTrades[symbol]; - const startQuantity = trades.reduce((sum, trade) => { - return sum.plus(trade.quantity.mul(getFactor(trade.type))); - }, new Big(0)); - currentHoldings[format(start, DATE_FORMAT)][symbol] = startQuantity; - } - } - - @LogPerformance - protected getInvestmentByDate(activities: PortfolioOrder[]): { - [date: string]: PortfolioOrder[]; - } { - return activities.reduce((groupedByDate, order) => { - if (!groupedByDate[order.date]) { - groupedByDate[order.date] = []; - } - - groupedByDate[order.date].push(order); - - return groupedByDate; - }, {}); - } - - @LogPerformance - protected mapToDataGatheringItems( - orders: PortfolioOrder[] - ): IDataGatheringItem[] { - return orders - .map((activity) => { - return { - symbol: activity.SymbolProfile.symbol, - dataSource: activity.SymbolProfile.dataSource - }; - }) - .filter( - (gathering, i, arr) => - arr.findIndex((t) => t.symbol === gathering.symbol) === i - ); - } - - @LogPerformance - protected async computeMarketMap(dateQuery: DateQuery): Promise<{ - [date: string]: { [symbol: string]: Big }; - }> { - const dataGatheringItems: IDataGatheringItem[] = - this.mapToDataGatheringItems(this.activities); - const { values: marketSymbols } = await this.currentRateService.getValues({ - dataGatheringItems, - dateQuery - }); - - const marketSymbolMap: { - [date: string]: { [symbol: string]: Big }; - } = {}; - - for (const marketSymbol of marketSymbols) { - const date = format(marketSymbol.date, DATE_FORMAT); - - if (!marketSymbolMap[date]) { - marketSymbolMap[date] = {}; - } - - if (marketSymbol.marketPrice) { - marketSymbolMap[date][marketSymbol.symbol] = new Big( - marketSymbol.marketPrice - ); - } - } - - return marketSymbolMap; - } - - @LogPerformance - protected activitiesToPortfolioOrder( - activities: Activity[] - ): PortfolioOrder[] { - return activities - .map( - ({ - date, - fee, - quantity, - SymbolProfile, - tags = [], - type, - unitPrice - }) => { - if (isAfter(date, new Date(Date.now()))) { - // Adapt date to today if activity is in future (e.g. liability) - // to include it in the interval - date = endOfDay(new Date(Date.now())); - } - - return { - SymbolProfile, - tags, - type, - date: format(date, DATE_FORMAT), - fee: new Big(fee), - quantity: new Big(quantity), - unitPrice: new Big(unitPrice) - }; - } - ) - .sort((a, b) => { - return a.date?.localeCompare(b.date); - }); - } -} diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.factory.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.factory.ts index 27f4ead2f..fe4b04cff 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.factory.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.factory.ts @@ -10,19 +10,13 @@ import { PerformanceCalculationType } from '@ghostfolio/common/types/performance import { Injectable } from '@nestjs/common'; +import { OrderService } from '../../order/order.service'; import { MwrPortfolioCalculator } from './mwr/portfolio-calculator'; import { PortfolioCalculator } from './portfolio-calculator'; import { RoaiPortfolioCalculator } from './roai/portfolio-calculator'; import { RoiPortfolioCalculator } from './roi/portfolio-calculator'; import { TwrPortfolioCalculator } from './twr/portfolio-calculator'; -export enum PerformanceCalculationType { - MWR = 'MWR', // Money-Weighted Rate of Return - ROAI = 'ROAI', // Return on Average Investment - TWR = 'TWR', // Time-Weighted Rate of Return - CPR = 'CPR' // Constant Portfolio Rate of Return -} - @Injectable() export class PortfolioCalculatorFactory { public constructor( @@ -30,7 +24,8 @@ export class PortfolioCalculatorFactory { private readonly currentRateService: CurrentRateService, private readonly exchangeRateDataService: ExchangeRateDataService, private readonly portfolioSnapshotService: PortfolioSnapshotService, - private readonly redisCacheService: RedisCacheService + private readonly redisCacheService: RedisCacheService, + private readonly orderService: OrderService ) {} @LogPerformance @@ -61,7 +56,8 @@ export class PortfolioCalculatorFactory { currentRateService: this.currentRateService, exchangeRateDataService: this.exchangeRateDataService, portfolioSnapshotService: this.portfolioSnapshotService, - redisCacheService: this.redisCacheService + redisCacheService: this.redisCacheService, + orderService: this.orderService }); case PerformanceCalculationType.ROAI: @@ -75,7 +71,8 @@ export class PortfolioCalculatorFactory { currentRateService: this.currentRateService, exchangeRateDataService: this.exchangeRateDataService, portfolioSnapshotService: this.portfolioSnapshotService, - redisCacheService: this.redisCacheService + redisCacheService: this.redisCacheService, + orderService: this.orderService }); case PerformanceCalculationType.ROI: @@ -89,7 +86,8 @@ export class PortfolioCalculatorFactory { currentRateService: this.currentRateService, exchangeRateDataService: this.exchangeRateDataService, portfolioSnapshotService: this.portfolioSnapshotService, - redisCacheService: this.redisCacheService + redisCacheService: this.redisCacheService, + orderService: this.orderService }); case PerformanceCalculationType.TWR: @@ -103,19 +101,7 @@ export class PortfolioCalculatorFactory { exchangeRateDataService: this.exchangeRateDataService, portfolioSnapshotService: this.portfolioSnapshotService, redisCacheService: this.redisCacheService, - filters - }); - case PerformanceCalculationType.CPR: - return new RoaiPortfolioCalculator({ - accountBalanceItems, - activities, - currency, - currentRateService: this.currentRateService, - userId, - configurationService: this.configurationService, - exchangeRateDataService: this.exchangeRateDataService, - portfolioSnapshotService: this.portfolioSnapshotService, - redisCacheService: this.redisCacheService, + orderService: this.orderService, filters }); diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts index 9bfd320f9..629c4b33e 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts @@ -41,6 +41,7 @@ import { Logger } from '@nestjs/common'; import { Big } from 'big.js'; import { plainToClass } from 'class-transformer'; import { + addDays, differenceInDays, eachDayOfInterval, endOfDay, @@ -52,6 +53,8 @@ import { } from 'date-fns'; import { isNumber, sortBy, sum, uniqBy } from 'lodash'; +import { OrderService } from '../../order/order.service'; + export abstract class PortfolioCalculator { protected static readonly ENABLE_LOGGING = false; @@ -64,6 +67,7 @@ export abstract class PortfolioCalculator { private dataProviderInfos: DataProviderInfo[]; private endDate: Date; protected exchangeRateDataService: ExchangeRateDataService; + protected orderService: OrderService; private filters: Filter[]; private portfolioSnapshotService: PortfolioSnapshotService; private redisCacheService: RedisCacheService; @@ -73,6 +77,8 @@ export abstract class PortfolioCalculator { private transactionPoints: TransactionPoint[]; protected userId: string; protected marketMap: { [date: string]: { [symbol: string]: Big } } = {}; + private holdings: { [date: string]: { [symbol: string]: Big } } = {}; + private holdingCurrencies: { [symbol: string]: string } = {}; public constructor({ accountBalanceItems, @@ -84,7 +90,8 @@ export abstract class PortfolioCalculator { filters, portfolioSnapshotService, redisCacheService, - userId + userId, + orderService }: { accountBalanceItems: HistoricalDataItem[]; activities: Activity[]; @@ -96,6 +103,7 @@ export abstract class PortfolioCalculator { portfolioSnapshotService: PortfolioSnapshotService; redisCacheService: RedisCacheService; userId: string; + orderService: OrderService; }) { this.accountBalanceItems = accountBalanceItems; this.configurationService = configurationService; @@ -103,6 +111,7 @@ export abstract class PortfolioCalculator { this.currentRateService = currentRateService; this.exchangeRateDataService = exchangeRateDataService; this.filters = filters; + this.orderService = orderService; let dateOfFirstActivity = new Date(); @@ -613,9 +622,77 @@ export abstract class PortfolioCalculator { }; } - protected abstract getPerformanceCalculationType(): PerformanceCalculationType; + @LogPerformance + public async getUnfilteredNetWorth(currency: string): Promise { + const activities = await this.orderService.getOrders({ + userId: this.userId, + userCurrency: currency, + types: ['BUY', 'SELL', 'STAKE'], + withExcludedAccounts: true + }); + const orders = this.activitiesToPortfolioOrder(activities.activities); + const start = orders.reduce( + (date, order) => + parseDate(date.date).getTime() < parseDate(order.date).getTime() + ? date + : order, + { date: orders[0].date } + ).date; + + const end = new Date(Date.now()); + + const holdings = await this.getHoldings(orders, parseDate(start), end); + const marketMap = await this.currentRateService.getValues({ + dataGatheringItems: this.mapToDataGatheringItems(orders), + dateQuery: { in: [end] } + }); + const endString = format(end, DATE_FORMAT); + const exchangeRates = await Promise.all( + Object.keys(holdings[endString]).map(async (holding) => { + const symbolCurrency = this.getCurrencyFromActivities(orders, holding); + const exchangeRate = + await this.exchangeRateDataService.toCurrencyAtDate( + 1, + symbolCurrency, + this.currency, + end + ); + return { symbolCurrency, exchangeRate }; + }) + ); + const currencyRates = exchangeRates.reduce<{ [currency: string]: number }>( + (all, currency): { [currency: string]: number } => { + all[currency.symbolCurrency] ??= currency.exchangeRate; + return all; + }, + {} + ); - protected abstract getPerformanceCalculationType(): PerformanceCalculationType; + const totalInvestment = await Object.keys(holdings[endString]).reduce( + (sum, holding) => { + if (!holdings[endString][holding].toNumber()) { + return sum; + } + const symbol = marketMap.values.find((m) => m.symbol === holding); + + if (symbol?.marketPrice === undefined) { + Logger.warn( + `Missing historical market data for ${holding} (${end})`, + 'PortfolioCalculator' + ); + return sum; + } else { + const symbolCurrency = this.getCurrency(holding); + const price = new Big(currencyRates[symbolCurrency]).mul( + symbol.marketPrice + ); + return sum.plus(new Big(price).mul(holdings[endString][holding])); + } + }, + new Big(0) + ); + return totalInvestment; + } @LogPerformance public getDataProviderInfos() { @@ -807,6 +884,25 @@ export abstract class PortfolioCalculator { return this.snapshot; } + @LogPerformance + protected getCurrency(symbol: string) { + return this.getCurrencyFromActivities(this.activities, symbol); + } + + @LogPerformance + protected getCurrencyFromActivities( + activities: PortfolioOrder[], + symbol: string + ) { + if (!this.holdingCurrencies[symbol]) { + this.holdingCurrencies[symbol] = activities.find( + (a) => a.SymbolProfile.symbol === symbol + ).SymbolProfile.currency; + } + + return this.holdingCurrencies[symbol]; + } + @LogPerformance protected computeTransactionPoints() { this.transactionPoints = []; @@ -1030,6 +1126,173 @@ export abstract class PortfolioCalculator { } } + @LogPerformance + protected activitiesToPortfolioOrder( + activities: Activity[] + ): PortfolioOrder[] { + return activities + .map( + ({ + date, + fee, + quantity, + SymbolProfile, + tags = [], + type, + unitPrice + }) => { + if (isAfter(date, new Date(Date.now()))) { + // Adapt date to today if activity is in future (e.g. liability) + // to include it in the interval + date = endOfDay(new Date(Date.now())); + } + + return { + SymbolProfile, + tags, + type, + date: format(date, DATE_FORMAT), + fee: new Big(fee), + quantity: new Big(quantity), + unitPrice: new Big(unitPrice) + }; + } + ) + .sort((a, b) => { + return a.date?.localeCompare(b.date); + }); + } + + @LogPerformance + protected async getHoldings( + activities: PortfolioOrder[], + start: Date, + end: Date + ) { + if ( + this.holdings && + Object.keys(this.holdings).some((h) => + isAfter(parseDate(h), subDays(end, 1)) + ) && + Object.keys(this.holdings).some((h) => + isBefore(parseDate(h), addDays(start, 1)) + ) + ) { + return this.holdings; + } + + this.computeHoldings(activities, start, end); + return this.holdings; + } + + @LogPerformance + protected async computeHoldings( + activities: PortfolioOrder[], + start: Date, + end: Date + ) { + const investmentByDate = this.getInvestmentByDate(activities); + this.calculateHoldings(investmentByDate, start, end); + } + + @LogPerformance + protected calculateInitialHoldings( + investmentByDate: { [date: string]: PortfolioOrder[] }, + start: Date, + currentHoldings: { [date: string]: { [symbol: string]: Big } } + ) { + const preRangeTrades = Object.keys(investmentByDate) + .filter((date) => resetHours(new Date(date)) <= start) + .map((date) => investmentByDate[date]) + .reduce((a, b) => a.concat(b), []) + .reduce((groupBySymbol, trade) => { + if (!groupBySymbol[trade.SymbolProfile.symbol]) { + groupBySymbol[trade.SymbolProfile.symbol] = []; + } + + groupBySymbol[trade.SymbolProfile.symbol].push(trade); + + return groupBySymbol; + }, {}); + + currentHoldings[format(start, DATE_FORMAT)] = {}; + + for (const symbol of Object.keys(preRangeTrades)) { + const trades: PortfolioOrder[] = preRangeTrades[symbol]; + const startQuantity = trades.reduce((sum, trade) => { + return sum.plus(trade.quantity.mul(getFactor(trade.type))); + }, new Big(0)); + currentHoldings[format(start, DATE_FORMAT)][symbol] = startQuantity; + } + } + + @LogPerformance + protected getInvestmentByDate(activities: PortfolioOrder[]): { + [date: string]: PortfolioOrder[]; + } { + return activities.reduce((groupedByDate, order) => { + if (!groupedByDate[order.date]) { + groupedByDate[order.date] = []; + } + + groupedByDate[order.date].push(order); + + return groupedByDate; + }, {}); + } + + @LogPerformance + protected mapToDataGatheringItems( + orders: PortfolioOrder[] + ): IDataGatheringItem[] { + return orders + .map((activity) => { + return { + symbol: activity.SymbolProfile.symbol, + dataSource: activity.SymbolProfile.dataSource + }; + }) + .filter( + (gathering, i, arr) => + arr.findIndex((t) => t.symbol === gathering.symbol) === i + ); + } + + private calculateHoldings( + investmentByDate: { [date: string]: PortfolioOrder[] }, + start: Date, + end: Date + ) { + const transactionDates = Object.keys(investmentByDate).sort(); + const dates = eachDayOfInterval({ start, end }, { step: 1 }) + .map((date) => { + return resetHours(date); + }) + .sort((a, b) => a.getTime() - b.getTime()); + const currentHoldings: { [date: string]: { [symbol: string]: Big } } = {}; + + this.calculateInitialHoldings(investmentByDate, start, currentHoldings); + + for (let i = 1; i < dates.length; i++) { + const dateString = format(dates[i], DATE_FORMAT); + const previousDateString = format(dates[i - 1], DATE_FORMAT); + if (transactionDates.some((d) => d === dateString)) { + const holdings = { ...currentHoldings[previousDateString] }; + investmentByDate[dateString].forEach((trade) => { + holdings[trade.SymbolProfile.symbol] ??= new Big(0); + holdings[trade.SymbolProfile.symbol] = holdings[ + trade.SymbolProfile.symbol + ].plus(trade.quantity.mul(getFactor(trade.type))); + }); + currentHoldings[dateString] = holdings; + } else { + currentHoldings[dateString] = currentHoldings[previousDateString]; + } + } + + this.holdings = currentHoldings; + } + private getChartDateMap({ endDate, startDate, @@ -1117,4 +1380,6 @@ export abstract class PortfolioCalculator { protected abstract calculateOverallPerformance( positions: TimelinePosition[] ): PortfolioSnapshot; + + protected abstract getPerformanceCalculationType(): PerformanceCalculationType; } diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index c00db4b40..92371fb26 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -506,8 +506,7 @@ export class PortfolioController { @Query('range') dateRange: DateRange = 'max', @Query('symbol') filterBySymbol?: string, @Query('tags') filterByTags?: string, - @Query('withExcludedAccounts') withExcludedAccounts = false, - @Query('timeWeightedPerformance') calculateTimeWeightedPerformance = false + @Query('withExcludedAccounts') withExcludedAccounts = false ): Promise { const filters = this.apiService.buildFiltersFromQueryParams({ filterByAccounts, @@ -522,8 +521,7 @@ export class PortfolioController { filters, impersonationId, withExcludedAccounts, - userId: this.request.user.id, - calculateTimeWeightedPerformance + userId: this.request.user.id }); if ( diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index fa4c40994..2fab5e5ec 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -86,7 +86,6 @@ import { } from 'date-fns'; import { isEmpty, uniqBy } from 'lodash'; -import { CPRPortfolioCalculator } from './calculator/constantPortfolioReturn/portfolio-calculator'; import { PortfolioCalculator } from './calculator/portfolio-calculator'; import { PortfolioCalculatorFactory } from './calculator/portfolio-calculator.factory'; import { PortfolioHoldingDetail } from './interfaces/portfolio-holding-detail.interface'; @@ -1102,15 +1101,13 @@ export class PortfolioService { dateRange = 'max', filters, impersonationId, - userId, - calculateTimeWeightedPerformance = false + userId }: { dateRange?: DateRange; filters?: Filter[]; impersonationId: string; userId: string; withExcludedAccounts?: boolean; - calculateTimeWeightedPerformance?: boolean; }): Promise { userId = await this.getUserId(impersonationId, userId); const user = await this.userService.user({ id: userId }); @@ -1158,11 +1155,7 @@ export class PortfolioService { const { endDate, startDate } = getIntervalFromDateRange(dateRange); const range = { end: endDate, start: startDate }; - const { chart } = await (calculateTimeWeightedPerformance - ? ( - portfolioCalculator as CPRPortfolioCalculator - ).getPerformanceWithTimeWeightedReturn(range) - : portfolioCalculator.getPerformance(range)); + const { chart } = await portfolioCalculator.getPerformance(range); const { netPerformance, @@ -1932,17 +1925,9 @@ export class PortfolioService { .plus(totalOfExcludedActivities) .toNumber(); - const netWorth = - portfolioCalculator instanceof CPRPortfolioCalculator - ? await (portfolioCalculator as CPRPortfolioCalculator) - .getUnfilteredNetWorth(this.getUserCurrency()) - .then((value) => value.toNumber()) - : new Big(balanceInBaseCurrency) - .plus(currentValueInBaseCurrency) - .plus(valuables) - .plus(excludedAccountsAndActivities) - .minus(liabilities) - .toNumber(); + const netWorth = await portfolioCalculator + .getUnfilteredNetWorth(this.getUserCurrency()) + .then((value) => value.toNumber()); const daysInMarket = differenceInDays(new Date(), firstOrderDate); diff --git a/apps/api/src/services/queues/data-gathering/data-gathering.processor.ts b/apps/api/src/services/queues/data-gathering/data-gathering.processor.ts index 0e1936399..d65d50fb7 100644 --- a/apps/api/src/services/queues/data-gathering/data-gathering.processor.ts +++ b/apps/api/src/services/queues/data-gathering/data-gathering.processor.ts @@ -210,9 +210,8 @@ export class DataGatheringProcessor { name: GATHER_MISSING_HISTORICAL_MARKET_DATA_PROCESS_JOB_NAME }) public async gatherMissingHistoricalMarketData(job: Job) { + const { dataSource, date, symbol } = job.data; try { - const { dataSource, date, symbol } = job.data; - Logger.log( `Historical market data gathering for missing values has been started for ${symbol} (${dataSource}) at ${format( date, diff --git a/package-lock.json b/package-lock.json index 1dfa43d7d..d1adff321 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13231,6 +13231,18 @@ "dev": true, "license": "MIT" }, + "node_modules/array-union": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", + "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/array.prototype.findlastindex": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", @@ -17238,6 +17250,18 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", @@ -19803,61 +19827,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/globby": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", - "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", - "dev": true, - "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.3", - "ignore": "^7.0.3", - "path-type": "^6.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby/node_modules/ignore": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.3.tgz", - "integrity": "sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/globby/node_modules/path-type": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", - "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby/node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/good-listener": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", From 6a3d60af0c73ffdfd2ff74b89d394e84ed45ea3e Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 25 Apr 2025 18:15:57 +0200 Subject: [PATCH 60/62] FIx tests --- ...-calculator-baln-buy-and-sell-in-two-activities.spec.ts | 3 ++- .../roai/portfolio-calculator-baln-buy-and-sell.spec.ts | 3 ++- .../calculator/roai/portfolio-calculator-baln-buy.spec.ts | 3 ++- ...tfolio-calculator-btcusd-buy-and-sell-partially.spec.ts | 3 ++- .../calculator/roai/portfolio-calculator-fee.spec.ts | 3 ++- .../calculator/roai/portfolio-calculator-googl-buy.spec.ts | 3 ++- .../calculator/roai/portfolio-calculator-item.spec.ts | 3 ++- .../calculator/roai/portfolio-calculator-liability.spec.ts | 7 ++++++- .../portfolio-calculator-msft-buy-with-dividend.spec.ts | 3 ++- .../calculator/roai/portfolio-calculator-no-orders.spec.ts | 3 ++- ...ortfolio-calculator-novn-buy-and-sell-partially.spec.ts | 3 ++- .../roai/portfolio-calculator-novn-buy-and-sell.spec.ts | 3 ++- 12 files changed, 28 insertions(+), 12 deletions(-) diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts index 88133604a..4c46ae6d1 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts @@ -77,7 +77,8 @@ describe('PortfolioCalculator', () => { currentRateService, exchangeRateDataService, portfolioSnapshotService, - redisCacheService + redisCacheService, + null ); }); diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell.spec.ts index 62edc515e..a65ee9c90 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy-and-sell.spec.ts @@ -77,7 +77,8 @@ describe('PortfolioCalculator', () => { currentRateService, exchangeRateDataService, portfolioSnapshotService, - redisCacheService + redisCacheService, + null ); }); diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy.spec.ts index b21192db1..b123647c1 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-baln-buy.spec.ts @@ -77,7 +77,8 @@ describe('PortfolioCalculator', () => { currentRateService, exchangeRateDataService, portfolioSnapshotService, - redisCacheService + redisCacheService, + null ); }); diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts index acd07344e..2ad0f84bc 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts @@ -90,7 +90,8 @@ describe('PortfolioCalculator', () => { currentRateService, exchangeRateDataService, portfolioSnapshotService, - redisCacheService + redisCacheService, + null ); }); diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts index a8aea0841..fb8f81c41 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-fee.spec.ts @@ -77,7 +77,8 @@ describe('PortfolioCalculator', () => { currentRateService, exchangeRateDataService, portfolioSnapshotService, - redisCacheService + redisCacheService, + null ); }); diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-googl-buy.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-googl-buy.spec.ts index cf0b0f305..8ed8b4830 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-googl-buy.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-googl-buy.spec.ts @@ -90,7 +90,8 @@ describe('PortfolioCalculator', () => { currentRateService, exchangeRateDataService, portfolioSnapshotService, - redisCacheService + redisCacheService, + null ); }); diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-item.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-item.spec.ts index 21d208d9f..47ffa7d32 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-item.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-item.spec.ts @@ -77,7 +77,8 @@ describe('PortfolioCalculator', () => { currentRateService, exchangeRateDataService, portfolioSnapshotService, - redisCacheService + redisCacheService, + null ); }); diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-liability.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-liability.spec.ts index 2cb3899e9..50b701415 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-liability.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-liability.spec.ts @@ -1,4 +1,5 @@ import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; +import { OrderService } from '@ghostfolio/api/app/order/order.service'; import { activityDummyData, symbolProfileDummyData, @@ -55,6 +56,7 @@ describe('PortfolioCalculator', () => { let portfolioCalculatorFactory: PortfolioCalculatorFactory; let portfolioSnapshotService: PortfolioSnapshotService; let redisCacheService: RedisCacheService; + let orderServiceMock: OrderService; beforeEach(() => { configurationService = new ConfigurationService(); @@ -72,12 +74,15 @@ describe('PortfolioCalculator', () => { redisCacheService = new RedisCacheService(null, null); + orderServiceMock = new OrderService(null, null, null, null, null, null); + portfolioCalculatorFactory = new PortfolioCalculatorFactory( configurationService, currentRateService, exchangeRateDataService, portfolioSnapshotService, - redisCacheService + redisCacheService, + orderServiceMock ); }); diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts index 8fc179879..2dcb12753 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts @@ -90,7 +90,8 @@ describe('PortfolioCalculator', () => { currentRateService, exchangeRateDataService, portfolioSnapshotService, - redisCacheService + redisCacheService, + null ); }); diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-no-orders.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-no-orders.spec.ts index 9d5b74bb2..ad33e6b82 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-no-orders.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-no-orders.spec.ts @@ -72,7 +72,8 @@ describe('PortfolioCalculator', () => { currentRateService, exchangeRateDataService, portfolioSnapshotService, - redisCacheService + redisCacheService, + null ); }); diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell-partially.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell-partially.spec.ts index ec97a7410..9399f93dd 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell-partially.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell-partially.spec.ts @@ -91,7 +91,8 @@ describe('PortfolioCalculator', () => { currentRateService, exchangeRateDataService, portfolioSnapshotService, - redisCacheService + redisCacheService, + null ); }); diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts index c405d0509..e1f98d293 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts @@ -91,7 +91,8 @@ describe('PortfolioCalculator', () => { currentRateService, exchangeRateDataService, portfolioSnapshotService, - redisCacheService + redisCacheService, + null ); }); From e802b36bfe57b001edcd15ef3a8511d052cfcc87 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 25 Apr 2025 18:22:11 +0200 Subject: [PATCH 61/62] Fix format --- .../asset-profile-dialog/asset-profile-dialog.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts index 29175c6c3..a653e85ee 100644 --- a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts +++ b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts @@ -35,8 +35,8 @@ import { ValidationErrors, Validators } from '@angular/forms'; -import { MatCheckboxChange } from '@angular/material/checkbox'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; +import { MatCheckboxChange } from '@angular/material/checkbox'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MatSnackBar } from '@angular/material/snack-bar'; import { From c017168c000a09a196a22c6d52d17d4f297965c4 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 25 Apr 2025 18:24:20 +0200 Subject: [PATCH 62/62] Add Husky Pre commit handling --- .husky/pre-commit | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .husky/pre-commit diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 000000000..8592824fa --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,2 @@ +# Check formatting on modified and uncommitted files, stop the commit if issues are found +npm run format:write --uncommitted || exit 1