Compare commits

...

5 Commits

Author SHA1 Message Date
Thomas Kaul b7c18ca44e
Task/improve entity logos in Storybook (#8088) 1 day ago
Thomas Kaul 75f0b0cf53
Task/extend personal finance tools (20261008) (#8092) 1 day ago
Thomas Kaul 26f9e6e1c9
Bugfix/add missing country mapping for Korea in FMP service (#8096) 1 day ago
Thomas Kaul 696d5d9882
Bugfix/missing first data point in portfolio evolution chart (#8089) 1 day ago
Lyndros d81484881d
Task/improve language localization for ES (20261008) (#8087) 1 day ago
  1. 10
      CHANGELOG.md
  2. 1
      apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts
  3. 48
      apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts
  4. 106
      apps/client/src/locales/messages.es.xlf
  5. 90
      libs/common/src/lib/personal-finance-tools.ts
  6. 27
      libs/ui/src/lib/account-selector/account-selector.component.stories.ts
  7. 10
      libs/ui/src/lib/accounts-table/accounts-table.component.stories.ts
  8. 10
      libs/ui/src/lib/activities-table/activities-table.component.stories.ts
  9. 5
      libs/ui/src/lib/entity-logo/entity-logo-image-source.service.ts
  10. 46
      libs/ui/src/lib/mocks/entity-logo-image-source.service.mock.ts

10
CHANGELOG.md

@ -11,6 +11,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Extended the content of the _General_ section by information about the import of activities from _Interactive Brokers_ on the Frequently Asked Questions (FAQ) page
### Changed
- Improved the _Storybook_ stories of the account selector, accounts table, activities table and holdings table components
- Improved the language localization for Spanish (`es`)
### Fixed
- Fixed the missing first data point in the portfolio evolution chart on the analysis page
- Fixed the missing mapping for Korea in the country weightings of the _Financial Modeling Prep_ service
## 3.81.0 - 2026-10-07
### Changed

1
apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts

@ -58,6 +58,7 @@ export class FinancialModelingPrepService
'Congo (Dem. Rep. of the)': 'CD',
'Congo (Rep. of)': 'CG',
'Czech Republic': 'CZ',
Korea: 'KR',
'Korea (the Republic of)': 'KR',
Macau: 'MO',
'Russian Federation': 'RU',

48
apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts

@ -329,36 +329,30 @@ export class GfAnalysisPageComponent implements OnInit {
this.performanceDataItems = [];
this.performanceDataItemsInPercentage = [];
for (const [
index,
{
date,
dividendInPercentageWithCurrencyEffect,
netPerformanceInPercentageWithCurrencyEffect,
totalInvestmentValueWithCurrencyEffect,
valueInPercentage,
valueWithCurrencyEffect
for (const {
date,
dividendInPercentageWithCurrencyEffect,
netPerformanceInPercentageWithCurrencyEffect,
totalInvestmentValueWithCurrencyEffect,
valueInPercentage,
valueWithCurrencyEffect
} of chart ?? []) {
if (totalInvestmentValueWithCurrencyEffect !== undefined) {
this.investments.push({
date,
investment: totalInvestmentValueWithCurrencyEffect
});
}
] of (chart ?? []).entries()) {
// Ignore first item where value is 0
if (index > 0 || this.user?.settings?.dateRange === 'max') {
if (totalInvestmentValueWithCurrencyEffect !== undefined) {
this.investments.push({
date,
investment: totalInvestmentValueWithCurrencyEffect
});
}
const value = isNumber(valueWithCurrencyEffect)
? valueWithCurrencyEffect
: valueInPercentage;
const value = isNumber(valueWithCurrencyEffect)
? valueWithCurrencyEffect
: valueInPercentage;
if (isNumber(value)) {
this.performanceDataItems.push({
date,
value
});
}
if (isNumber(value)) {
this.performanceDataItems.push({
date,
value
});
}
if (isNumber(netPerformanceInPercentageWithCurrencyEffect)) {

106
apps/client/src/locales/messages.es.xlf

@ -100,7 +100,7 @@
</trans-unit>
<trans-unit id="8264632476919693099" datatype="html">
<source>Any person who has the link can view the data.</source>
<target state="new">Any person who has the link can view the data.</target>
<target state="translated">Cualquier persona que tenga el enlace puede ver los datos.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html</context>
<context context-type="linenumber">42</context>
@ -388,7 +388,7 @@
</trans-unit>
<trans-unit id="4472298507300372923" datatype="html">
<source>View and manage</source>
<target state="new">View and manage</target>
<target state="translated">Ver y administrar</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/access-level-icon/access-level-icon.component.html</context>
<context context-type="linenumber">9</context>
@ -648,7 +648,7 @@
</trans-unit>
<trans-unit id="6249687295240367729" datatype="html">
<source>Explore our guides to help you get started with investing and managing your finances.</source>
<target state="new">Explore our guides to help you get started with investing and managing your finances.</target>
<target state="translated">Explora nuestras guías para ayudarte a empezar a invertir y gestionar tus finanzas.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/overview/resources-overview.component.ts</context>
<context context-type="linenumber">21</context>
@ -892,7 +892,7 @@
</trans-unit>
<trans-unit id="1022809987579838138" datatype="html">
<source>Last Used</source>
<target state="new">Last Used</target>
<target state="translated">Último uso</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/access-table/access-table.component.html</context>
<context context-type="linenumber">31</context>
@ -900,7 +900,7 @@
</trans-unit>
<trans-unit id="1029620928611278483" datatype="html">
<source>An error occurred while merging this asset profile into <x id="PH" equiv-text="symbol"/> (<x id="PH_1" equiv-text="dataSource"/>).</source>
<target state="new">An error occurred while merging this asset profile into <x id="PH" equiv-text="symbol"/> (<x id="PH_1" equiv-text="dataSource"/>).</target>
<target state="translated">Se produjo un error al fusionar este perfil de activo en <x id="PH" equiv-text="symbol"/> (<x id="PH_1" equiv-text="dataSource"/>).</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">946</context>
@ -944,7 +944,7 @@
</trans-unit>
<trans-unit id="6623155069376115284" datatype="html">
<source>Find quick answers to commonly asked questions about Ghostfolio in our Frequently Asked Questions (FAQ) section.</source>
<target state="new">Find quick answers to commonly asked questions about Ghostfolio in our Frequently Asked Questions (FAQ) section.</target>
<target state="translated">Encuentra respuestas rápidas a las preguntas más frecuentes sobre Ghostfolio en nuestra sección de preguntas frecuentes (FAQ).</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/overview/resources-overview.component.ts</context>
<context context-type="linenumber">16</context>
@ -2188,7 +2188,7 @@
</trans-unit>
<trans-unit id="4882027922359285902" datatype="html">
<source>Restricted view and manage</source>
<target state="new">Restricted view and manage</target>
<target state="translated">Vista restringida y administración</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/access-level-icon/access-level-icon.component.html</context>
<context context-type="linenumber">5</context>
@ -2744,7 +2744,7 @@
</trans-unit>
<trans-unit id="5298486223740169185" datatype="html">
<source>By <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="INTERPOLATION" equiv-text="{{ retirementDateLabel }}"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/>, this is projected to increase to <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot; hasPermissionToShowValues ? withdrawalRatePerYearProjected?.toNumber() : null &quot; /&gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isPercent]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [precision]=&quot;2&quot; [value]=&quot;user?.settings?.annualInterestRate / 100&quot; /&gt;"/> per year<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/> or <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot; hasPermissionToShowValues ? withdrawalRatePerMonthProjected?.toNumber() : null &quot; /&gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isPercent]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [precision]=&quot;2&quot; [value]=&quot;user?.settings?.annualInterestRate / 100&quot; /&gt;"/> per month<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/>, assuming a <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isPercent]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [precision]=&quot;2&quot; [value]=&quot;user?.settings?.annualInterestRate / 100&quot; /&gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isPercent]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [precision]=&quot;2&quot; [value]=&quot;user?.settings?.annualInterestRate / 100&quot; /&gt;"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/> annual interest rate.</source>
<target state="new">Para <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="INTERPOLATION" equiv-text="{{ retirementDateLabel }}"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/>, se prevé que esto aumente a <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot;withdrawalRatePerYearProjected?.toNumber()&quot; /&gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isPercent]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [precision]=&quot;2&quot; [value]=&quot;user?.settings?.annualInterestRate / 100&quot; /&gt;"/> por año<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/> o <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot;withdrawalRatePerMonthProjected?.toNumber()&quot; /&gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isPercent]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [precision]=&quot;2&quot; [value]=&quot;user?.settings?.annualInterestRate / 100&quot; /&gt;"/> por mes<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/>, asumiendo una tasa de interés anual del <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isPercent]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [precision]=&quot;2&quot; [value]=&quot;user?.settings?.annualInterestRate / 100&quot; /&gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isPercent]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [precision]=&quot;2&quot; [value]=&quot;user?.settings?.annualInterestRate / 100&quot; /&gt;"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/>.</target>
<target state="translated">Para <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="INTERPOLATION" equiv-text="{{ retirementDateLabel }}"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/>, se prevé que esto aumente a <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot;withdrawalRatePerYearProjected?.toNumber()&quot; /&gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isPercent]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [precision]=&quot;2&quot; [value]=&quot;user?.settings?.annualInterestRate / 100&quot; /&gt;"/> por año<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/> o <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot;withdrawalRatePerMonthProjected?.toNumber()&quot; /&gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isPercent]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [precision]=&quot;2&quot; [value]=&quot;user?.settings?.annualInterestRate / 100&quot; /&gt;"/> por mes<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/>, asumiendo una tasa de interés anual del <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isPercent]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [precision]=&quot;2&quot; [value]=&quot;user?.settings?.annualInterestRate / 100&quot; /&gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isPercent]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [precision]=&quot;2&quot; [value]=&quot;user?.settings?.annualInterestRate / 100&quot; /&gt;"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/>.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/fire/fire-page.html</context>
<context context-type="linenumber">144</context>
@ -3032,7 +3032,7 @@
</trans-unit>
<trans-unit id="3885497195825665706" datatype="html">
<source>Next</source>
<target state="new">Next</target>
<target state="translated">Siguiente</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page.html</context>
<context context-type="linenumber">406</context>
@ -3160,7 +3160,7 @@
</trans-unit>
<trans-unit id="1825717711340685842" datatype="html">
<source>Export <x id="INTERPOLATION" equiv-text="{{ (totalItems ?? 0) &gt; 1 ? totalItems : &apos;&apos; }}"/> <x id="ICU" equiv-text="{totalItems, plural, =1 {Activity} other {Activities}}"/></source>
<target state="new">Exportar <x id="INTERPOLATION" equiv-text="{{ totalItems &gt; 1 ? totalItems : &apos;&apos; }}"/> <x id="ICU" equiv-text="{totalItems, plural, =1 {Actividad} other {Actividades}}"/></target>
<target state="translated">Exportar <x id="INTERPOLATION" equiv-text="{{ totalItems &gt; 1 ? totalItems : &apos;&apos; }}"/> <x id="ICU" equiv-text="{totalItems, plural, =1 {Actividad} other {Actividades}}"/></target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/activities-table/activities-table.component.html</context>
<context context-type="linenumber">72</context>
@ -3304,7 +3304,7 @@
</trans-unit>
<trans-unit id="3358797625330883274" datatype="html">
<source>Find quick answers to commonly asked questions about self-hosting Ghostfolio in our Frequently Asked Questions (FAQ) section.</source>
<target state="new">Find quick answers to commonly asked questions about self-hosting Ghostfolio in our Frequently Asked Questions (FAQ) section.</target>
<target state="translated">Encuentra respuestas rápidas a las preguntas más frecuentes sobre el autoalojamiento de Ghostfolio en nuestra sección de preguntas frecuentes (FAQ).</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html</context>
<context context-type="linenumber">8</context>
@ -3328,7 +3328,7 @@
</trans-unit>
<trans-unit id="5552246967241337741" datatype="html">
<source>If you retire today, you would be able to withdraw <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot; hasPermissionToShowValues ? withdrawalRatePerYear?.toNumber() : null &quot; /&gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot; hasPermissionToShowValues ? fireWealth?.today.valueInBaseCurrency : null &quot; /&gt;"/> per year<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/> or <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot; hasPermissionToShowValues ? withdrawalRatePerMonth?.toNumber() : null &quot; /&gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot; hasPermissionToShowValues ? fireWealth?.today.valueInBaseCurrency : null &quot; /&gt;"/> per month<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/>, based on your total assets of <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot; hasPermissionToShowValues ? fireWealth?.today.valueInBaseCurrency : null &quot; /&gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot; hasPermissionToShowValues ? fireWealth?.today.valueInBaseCurrency : null &quot; /&gt;"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/> and a safe withdrawal rate (SWR) of</source>
<target state="new">Si te jubilas hoy, podrías retirar <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot;withdrawalRatePerYear?.toNumber()&quot; /&gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot;fireWealth?.today.valueInBaseCurrency&quot; /&gt;"/> por año<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/> o <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot;withdrawalRatePerMonth?.toNumber()&quot; /&gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot;fireWealth?.today.valueInBaseCurrency&quot; /&gt;"/> por mes<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/>, basado en tus activos totales de <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot;fireWealth?.today.valueInBaseCurrency&quot; /&gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot;fireWealth?.today.valueInBaseCurrency&quot; /&gt;"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/> y una tasa de retiro segura (SWR) de</target>
<target state="translated">Si te jubilas hoy, podrías retirar <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot;withdrawalRatePerYear?.toNumber()&quot; /&gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot;fireWealth?.today.valueInBaseCurrency&quot; /&gt;"/> por año<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/> o <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_1" ctype="x-gf_value_1" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot;withdrawalRatePerMonth?.toNumber()&quot; /&gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot;fireWealth?.today.valueInBaseCurrency&quot; /&gt;"/> por mes<x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/>, basado en tus activos totales de <x id="START_TAG_SPAN" ctype="x-span" equiv-text="&lt;span class=&quot;font-weight-bold&quot; &gt;"/><x id="START_TAG_GF_VALUE_2" ctype="x-gf_value_2" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot;fireWealth?.today.valueInBaseCurrency&quot; /&gt;"/><x id="CLOSE_TAG_GF_VALUE" ctype="x-gf_value" equiv-text="&lt;gf-value class=&quot;d-inline-block&quot; [isCurrency]=&quot;true&quot; [locale]=&quot;user?.settings?.locale&quot; [unit]=&quot;user?.settings?.baseCurrency&quot; [value]=&quot;fireWealth?.today.valueInBaseCurrency&quot; /&gt;"/><x id="CLOSE_TAG_SPAN" ctype="x-span" equiv-text="&lt;/span&gt;"/> y una tasa de retiro segura (SWR) de</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/fire/fire-page.html</context>
<context context-type="linenumber">69</context>
@ -3404,7 +3404,7 @@
</trans-unit>
<trans-unit id="641154803270226443" datatype="html">
<source>Find quick answers to commonly asked questions about the fully managed Ghostfolio cloud offering in our Frequently Asked Questions (FAQ) section.</source>
<target state="new">Find quick answers to commonly asked questions about the fully managed Ghostfolio cloud offering in our Frequently Asked Questions (FAQ) section.</target>
<target state="translated">Encuentra respuestas rápidas a las preguntas más frecuentes sobre la oferta de Ghostfolio en la nube totalmente gestionada en nuestra sección de preguntas frecuentes (FAQ).</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/faq/saas/saas-page.html</context>
<context context-type="linenumber">8</context>
@ -3484,7 +3484,7 @@
</trans-unit>
<trans-unit id="7771702342975481710" datatype="html">
<source>Add your first activity</source>
<target state="new">Add your first activity</target>
<target state="translated">Añade tu primera operación</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/no-activities-info/no-activities-info.component.html</context>
<context context-type="linenumber">12</context>
@ -3584,7 +3584,7 @@
</trans-unit>
<trans-unit id="472895619516205802" datatype="html">
<source>This action cannot be undone.</source>
<target state="new">This action cannot be undone.</target>
<target state="translated">Esta acción no se puede deshacer.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">965</context>
@ -4108,7 +4108,7 @@
</trans-unit>
<trans-unit id="5521091503920831865" datatype="html">
<source>Add to Watchlist</source>
<target state="new">Add to Watchlist</target>
<target state="translated">Añadir a la lista de seguimiento</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/common/src/lib/routes/routes.ts</context>
<context context-type="linenumber">163</context>
@ -4132,7 +4132,7 @@
</trans-unit>
<trans-unit id="9099220454364126737" datatype="html">
<source>This asset profile cannot be merged into <x id="PH" equiv-text="symbol"/> (<x id="PH_1" equiv-text="dataSource"/>).</source>
<target state="new">This asset profile cannot be merged into <x id="PH" equiv-text="symbol"/> (<x id="PH_1" equiv-text="dataSource"/>).</target>
<target state="translated">Este perfil de activo no se puede fusionar en <x id="PH" equiv-text="symbol"/> (<x id="PH_1" equiv-text="dataSource"/>).</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">924</context>
@ -4184,7 +4184,7 @@
</trans-unit>
<trans-unit id="6962264495000055621" datatype="html">
<source>Do you really want to remove this received access?</source>
<target state="new">Do you really want to remove this received access?</target>
<target state="translated">¿Seguro que quieres eliminar este acceso recibido?</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/access-table/access-table.component.ts</context>
<context context-type="linenumber">152</context>
@ -4216,7 +4216,7 @@
</trans-unit>
<trans-unit id="7719274775614264692" datatype="html">
<source>The data of this asset profile is moved to <x id="PH" equiv-text="symbol"/> (<x id="PH_1" equiv-text="dataSource"/>) and this asset profile is deleted.</source>
<target state="new">The data of this asset profile is moved to <x id="PH" equiv-text="symbol"/> (<x id="PH_1" equiv-text="dataSource"/>) and this asset profile is deleted.</target>
<target state="translated">Los datos de este perfil de activo se trasladan a <x id="PH" equiv-text="symbol"/> (<x id="PH_1" equiv-text="dataSource"/>) y este perfil de activo se elimina.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">963</context>
@ -4308,7 +4308,7 @@
</trans-unit>
<trans-unit id="5176578390795646240" datatype="html">
<source>thereof Dividend Performance</source>
<target state="new">thereof Dividend Performance</target>
<target state="translated">del cual, rendimiento de dividendos</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context>
<context context-type="linenumber">178</context>
@ -4696,7 +4696,7 @@
</trans-unit>
<trans-unit id="5918319622596548216" datatype="html">
<source>Financial Advisor</source>
<target state="new">Financial Advisor</target>
<target state="translated">Asesor financiero</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">110</context>
@ -5384,7 +5384,7 @@
</trans-unit>
<trans-unit id="6952711292901447467" datatype="html">
<source>Learn key financial terms and concepts in our comprehensive glossary.</source>
<target state="new">Learn key financial terms and concepts in our comprehensive glossary.</target>
<target state="translated">Aprende términos y conceptos financieros clave en nuestro completo glosario.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/overview/resources-overview.component.ts</context>
<context context-type="linenumber">31</context>
@ -5829,7 +5829,7 @@
</trans-unit>
<trans-unit id="5106905229162288681" datatype="html">
<source>Expiration Date</source>
<target state="new">Expiration Date</target>
<target state="translated">Fecha de caducidad</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html</context>
<context context-type="linenumber">54</context>
@ -5926,7 +5926,7 @@
</trans-unit>
<trans-unit id="4272904080612853299" datatype="html">
<source>Do you really want to merge this asset profile into it?</source>
<target state="new">Do you really want to merge this asset profile into it?</target>
<target state="translated">¿Seguro que quieres fusionar este perfil de activo en él?</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">969</context>
@ -6194,7 +6194,7 @@
</trans-unit>
<trans-unit id="assetClass.ALTERNATIVE_INVESTMENT" datatype="html">
<source>Alternative Investment</source>
<target state="new">Alternative Investment</target>
<target state="translated">Inversión alternativa</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">52</context>
@ -6202,7 +6202,7 @@
</trans-unit>
<trans-unit id="assetClass.COMMODITY" datatype="html">
<source>Commodity</source>
<target state="new">Commodity</target>
<target state="translated">Materia prima</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">53</context>
@ -6210,7 +6210,7 @@
</trans-unit>
<trans-unit id="assetClass.EQUITY" datatype="html">
<source>Equity</source>
<target state="new">Equity</target>
<target state="translated">Renta variable</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">54</context>
@ -6218,7 +6218,7 @@
</trans-unit>
<trans-unit id="assetClass.FIXED_INCOME" datatype="html">
<source>Fixed Income</source>
<target state="new">Fixed Income</target>
<target state="translated">Renta fija</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">55</context>
@ -6226,7 +6226,7 @@
</trans-unit>
<trans-unit id="assetClass.LIQUIDITY" datatype="html">
<source>Liquidity</source>
<target state="new">Liquidity</target>
<target state="translated">Liquidez</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">56</context>
@ -6234,7 +6234,7 @@
</trans-unit>
<trans-unit id="assetClass.REAL_ESTATE" datatype="html">
<source>Real Estate</source>
<target state="new">Real Estate</target>
<target state="translated">Inmobiliario</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">57</context>
@ -6242,7 +6242,7 @@
</trans-unit>
<trans-unit id="assetSubClass.BOND" datatype="html">
<source>Bond</source>
<target state="new">Bond</target>
<target state="translated">Bono</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">60</context>
@ -6250,7 +6250,7 @@
</trans-unit>
<trans-unit id="assetSubClass.CASH" datatype="html">
<source>Cash</source>
<target state="new">Cash</target>
<target state="translated">Efectivo</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">61</context>
@ -6258,7 +6258,7 @@
</trans-unit>
<trans-unit id="assetSubClass.COLLECTIBLE" datatype="html">
<source>Collectible</source>
<target state="new">Collectible</target>
<target state="translated">Objeto de colección</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">62</context>
@ -6266,7 +6266,7 @@
</trans-unit>
<trans-unit id="assetSubClass.COMMODITY" datatype="html">
<source>Commodity</source>
<target state="new">Commodity</target>
<target state="translated">Materia prima</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/i18n/i18n-page.html</context>
<context context-type="linenumber">5</context>
@ -6274,7 +6274,7 @@
</trans-unit>
<trans-unit id="assetSubClass.CRYPTOCURRENCY" datatype="html">
<source>Cryptocurrency</source>
<target state="new">Cryptocurrency</target>
<target state="translated">Criptomoneda</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">63</context>
@ -6282,7 +6282,7 @@
</trans-unit>
<trans-unit id="assetSubClass.ETF" datatype="html">
<source>ETF</source>
<target state="new">ETF</target>
<target state="translated">ETF</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">64</context>
@ -6290,7 +6290,7 @@
</trans-unit>
<trans-unit id="assetSubClass.LOAN" datatype="html">
<source>Loan</source>
<target state="new">Loan</target>
<target state="translated">Préstamo</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">65</context>
@ -6298,7 +6298,7 @@
</trans-unit>
<trans-unit id="assetSubClass.MUTUALFUND" datatype="html">
<source>Mutual Fund</source>
<target state="new">Mutual Fund</target>
<target state="translated">Fondo de inversión</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">66</context>
@ -6306,7 +6306,7 @@
</trans-unit>
<trans-unit id="assetSubClass.PRECIOUS_METAL" datatype="html">
<source>Precious Metal</source>
<target state="new">Precious Metal</target>
<target state="translated">Metal precioso</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">67</context>
@ -6314,7 +6314,7 @@
</trans-unit>
<trans-unit id="assetSubClass.PRIVATE_EQUITY" datatype="html">
<source>Private Equity</source>
<target state="new">Private Equity</target>
<target state="translated">Capital privado</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">68</context>
@ -6322,7 +6322,7 @@
</trans-unit>
<trans-unit id="assetSubClass.STOCK" datatype="html">
<source>Stock</source>
<target state="new">Stock</target>
<target state="translated">Acción</target>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
<context context-type="linenumber">69</context>
@ -6666,7 +6666,7 @@
</trans-unit>
<trans-unit id="3995811497329884593" datatype="html">
<source>Expires <x id="INTERPOLATION" equiv-text="{{ formatRelativeTime({ date: element.subscription.expiresAt, language: user?.settings?.language }) }}"/> (<x id="INTERPOLATION_1" equiv-text="{{ element.subscription.expiresAt | date: defaultDateFormat }}"/>)</source>
<target state="new">Caduca <x id="INTERPOLATION" equiv-text="{{ formatDistanceToNow(element.subscription.expiresAt) }}"/> (<x id="INTERPOLATION_1" equiv-text="{{ element.subscription.expiresAt | date: defaultDateFormat }}"/>)</target>
<target state="translated">Caduca <x id="INTERPOLATION" equiv-text="{{ formatDistanceToNow(element.subscription.expiresAt) }}"/> (<x id="INTERPOLATION_1" equiv-text="{{ element.subscription.expiresAt | date: defaultDateFormat }}"/>)</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-users/admin-users.html</context>
<context context-type="linenumber">34</context>
@ -6690,7 +6690,7 @@
</trans-unit>
<trans-unit id="251113330629316982" datatype="html">
<source>Date must be in the future.</source>
<target state="new">Date must be in the future.</target>
<target state="translated">La fecha debe estar en el futuro.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html</context>
<context context-type="linenumber">70</context>
@ -7071,7 +7071,7 @@
</trans-unit>
<trans-unit id="4452427314943113135" datatype="html">
<source>Previous</source>
<target state="new">Previous</target>
<target state="translated">Anterior</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page.html</context>
<context context-type="linenumber">396</context>
@ -7243,7 +7243,7 @@
</trans-unit>
<trans-unit id="2655368253225791055" datatype="html">
<source>Find quick answers to commonly asked questions about Ghostfolio in our Frequently Asked Questions (FAQ) section. Discover what Ghostfolio is, explore its features, and learn about our privacy practices. Get all the information you need in one place.</source>
<target state="new">Find quick answers to commonly asked questions about Ghostfolio in our Frequently Asked Questions (FAQ) section. Discover what Ghostfolio is, explore its features, and learn about our privacy practices. Get all the information you need in one place.</target>
<target state="translated">Encuentra respuestas rápidas a las preguntas más frecuentes sobre Ghostfolio en nuestra sección de preguntas frecuentes (FAQ). Descubre qué es Ghostfolio, explora sus funciones y conoce nuestras prácticas de privacidad. Obtén toda la información que necesitas en un solo lugar.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/faq/overview/faq-overview-page.html</context>
<context context-type="linenumber">8</context>
@ -7395,7 +7395,7 @@
</trans-unit>
<trans-unit id="7803225195017107428" datatype="html">
<source>thereof Dividend</source>
<target state="new">thereof Dividend</target>
<target state="translated">de los cuales, dividendos</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context>
<context context-type="linenumber">102</context>
@ -7937,7 +7937,7 @@
</trans-unit>
<trans-unit id="9179002757707456211" datatype="html">
<source>Access various market resources and tools to stay informed about financial markets.</source>
<target state="new">Access various market resources and tools to stay informed about financial markets.</target>
<target state="translated">Accede a diversos recursos y herramientas del mercado para mantenerte informado sobre los mercados financieros.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/overview/resources-overview.component.ts</context>
<context context-type="linenumber">26</context>
@ -8217,7 +8217,7 @@
</trans-unit>
<trans-unit id="1308755238280799396" datatype="html">
<source>Oops! Could not remove the received access.</source>
<target state="new">Oops! Could not remove the received access.</target>
<target state="translated">¡Vaya! No se pudo eliminar el acceso recibido.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/user-account-access/user-account-access.component.ts</context>
<context context-type="linenumber">156</context>
@ -8301,7 +8301,7 @@
</trans-unit>
<trans-unit id="8816331549575943119" datatype="html">
<source>Additional requests are granted while you are setting up your instance</source>
<target state="new">Additional requests are granted while you are setting up your instance</target>
<target state="translated">Se conceden solicitudes adicionales mientras configuras tu instancia</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-settings/admin-settings.component.ts</context>
<context context-type="linenumber">88</context>
@ -8402,7 +8402,7 @@
</trans-unit>
<trans-unit id="3606972039333274390" datatype="html">
<source><x id="PH" equiv-text="symbol"/> (<x id="PH_1" equiv-text="dataSource"/>) is already in use.</source>
<target state="new"><x id="PH" equiv-text="assetProfileIdentifier.symbol"/> (<x id="PH_1" equiv-text="assetProfileIdentifier.dataSource"/>) ya está en uso.</target>
<target state="translated"><x id="PH" equiv-text="assetProfileIdentifier.symbol"/> (<x id="PH_1" equiv-text="assetProfileIdentifier.dataSource"/>) ya está en uso.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts</context>
<context context-type="linenumber">967</context>
@ -8833,7 +8833,7 @@
</trans-unit>
<trans-unit id="7387635272539030076" datatype="html">
<source>new</source>
<target state="new">new</target>
<target state="translated">nuevo</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/features/features-page.html</context>
<context context-type="linenumber">223</context>
@ -9154,7 +9154,7 @@
</trans-unit>
<trans-unit id="5814001514445505929" datatype="html">
<source>Return on Average Investment (total return with dividends)</source>
<target state="new">Return on Average Investment (total return with dividends)</target>
<target state="translated">Rentabilidad sobre la inversión media (rentabilidad total con dividendos)</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html</context>
<context context-type="linenumber">159</context>
@ -9466,7 +9466,7 @@
</trans-unit>
<trans-unit id="3394346142616268152" datatype="html">
<source>Oops! Could not revoke the granted access.</source>
<target state="new">Oops! Could not revoke the granted access.</target>
<target state="translated">¡Vaya! No se pudo revocar el acceso concedido.</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/components/user-account-access/user-account-access.component.ts</context>
<context context-type="linenumber">135</context>

90
libs/common/src/lib/personal-finance-tools.ts

@ -794,6 +794,28 @@ export const personalFinanceTools: Product[] = (
updatedAt: '2026-09-23',
url: 'https://www.comarch.com/finance/banking/comarch-wealth-management'
},
{
categories: [
'BUDGETING',
'CRYPTOCURRENCY',
'DIVIDEND_TRACKING',
'ETF_TRACKING',
'NET_WORTH_TRACKING',
'STOCK_TRACKING'
],
founded: 2019,
hasFreePlan: true,
key: 'compiledsanity-personal-finance',
languages: ['English'],
name: 'CompiledSanity Personal Finance',
note: 'License is a perpetual license',
origin: 'AU',
platforms: ['WEB'],
pricingPerYear: 'AUD 12',
slogan: 'Understand Your Money. Grow Your Wealth.',
updatedAt: '2026-10-08',
url: 'https://cspersonalfinance.io'
},
{
categories: ['WEALTH_MANAGEMENT'],
founded: 2019,
@ -1458,6 +1480,26 @@ export const personalFinanceTools: Product[] = (
updatedAt: '2026-07-05',
url: 'https://finateka.com'
},
{
categories: [
'BUDGETING',
'CRYPTOCURRENCY',
'DIVIDEND_TRACKING',
'NET_WORTH_TRACKING',
'STOCK_TRACKING'
],
hasFreePlan: true,
hasSelfHostingAbility: false,
key: 'finboard',
languages: ['Deutsch', 'English', 'Español'],
name: 'FinBoard',
origin: 'ES',
platforms: ['WEB'],
pricingPerYear: '€49.90',
slogan: 'Your Personal Finance Dashboard',
updatedAt: '2026-10-08',
url: 'https://finboard.me'
},
{
categories: ['NET_WORTH_TRACKING', 'STOCK_TRACKING'],
founded: 2022,
@ -2576,6 +2618,33 @@ export const personalFinanceTools: Product[] = (
updatedAt: '2026-09-02',
url: 'https://neontra.com'
},
{
categories: [
'BUDGETING',
'CRYPTOCURRENCY',
'ETF_TRACKING',
'NET_WORTH_TRACKING',
'STOCK_TRACKING'
],
hasFreePlan: true,
hasSelfHostingAbility: false,
key: 'neto',
languages: [
'Deutsch',
'English',
'Español',
'Français',
'Italiano',
'Português'
],
name: 'Neto',
origin: 'ES',
platforms: ['ANDROID', 'IOS'],
pricingPerYear: '€49.99',
slogan: 'Tus gastos, tus ahorros y tu patrimonio en una sola app',
updatedAt: '2026-10-08',
url: 'https://netoapp.es'
},
{
categories: ['INVESTMENT_RESEARCH', 'STOCK_TRACKING'],
hasFreePlan: true,
@ -2672,6 +2741,27 @@ export const personalFinanceTools: Product[] = (
updatedAt: '2026-09-23',
url: 'https://orion.com/advisor-tech/risk-intelligence'
},
{
categories: [
'CRYPTOCURRENCY',
'ETF_TRACKING',
'FAMILY_OFFICE',
'NET_WORTH_TRACKING',
'STOCK_TRACKING',
'WEALTH_MANAGEMENT'
],
hasFreePlan: false,
hasSelfHostingAbility: false,
key: 'ormax',
languages: ['English'],
name: 'Ormax',
origin: 'CY',
platforms: ['WEB'],
pricingPerYear: '$240',
slogan: 'AI Wealth Management',
updatedAt: '2026-10-08',
url: 'https://ormax.ai'
},
{
categories: [
'CRYPTOCURRENCY',

27
libs/ui/src/lib/account-selector/account-selector.component.stories.ts

@ -24,7 +24,7 @@ const ACCOUNTS: AccountWithPlatform[] = [
platform: {
id: '9da3a8a7-4795-43e3-a6db-ccb914189737',
name: 'Coinbase',
url: 'https://coinbase.com'
url: 'https://www.coinbase.com'
},
platformId: '9da3a8a7-4795-43e3-a6db-ccb914189737',
updatedAt: new Date('2024-01-01'),
@ -33,13 +33,28 @@ const ACCOUNTS: AccountWithPlatform[] = [
{
comment: null,
createdAt: new Date('2024-01-01'),
currency: 'CHF',
currency: 'USD',
id: 'd191b2d5-9d5a-4c5f-9d55-6f0e5f6a7b8c',
name: 'Private Banking Account',
platform: {
id: '43e8fcd1-5b79-4100-b678-d2229bd1660d',
name: 'J.P. Morgan',
url: 'https://www.jpmorgan.com'
},
platformId: '43e8fcd1-5b79-4100-b678-d2229bd1660d',
updatedAt: new Date('2024-01-01'),
userId: '081aa387-487d-4438-83a4-3060eb2a016e'
},
{
comment: null,
createdAt: new Date('2024-01-01'),
currency: 'USD',
id: '9da3a8a7-4795-43e3-a6db-ccb914189737',
name: 'Ghostfolio Account',
name: 'Trading Account',
platform: {
id: 'f3e9d0e5-1e0f-4a3c-8b12-1f2a3b4c5d6e',
name: 'Ghostfolio',
url: 'https://ghostfol.io'
name: 'Interactive Brokers',
url: 'https://interactivebrokers.com'
},
platformId: 'f3e9d0e5-1e0f-4a3c-8b12-1f2a3b4c5d6e',
updatedAt: new Date('2024-01-01'),
@ -49,7 +64,7 @@ const ACCOUNTS: AccountWithPlatform[] = [
comment: null,
createdAt: new Date('2024-01-01'),
currency: 'EUR',
id: 'd191b2d5-9d5a-4c5f-9d55-6f0e5f6a7b8c',
id: '267ec888-cb57-45d0-8085-938017417a2e',
name: 'Savings Account',
platformId: null,
updatedAt: new Date('2024-01-01'),

10
libs/ui/src/lib/accounts-table/accounts-table.component.stories.ts

@ -12,6 +12,8 @@ import type { Meta, StoryObj } from '@storybook/angular';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { GfEntityLogoComponent } from '../entity-logo';
import { EntityLogoImageSourceService } from '../entity-logo/entity-logo-image-source.service';
import { EntityLogoImageSourceServiceMock } from '../mocks/entity-logo-image-source.service.mock';
import { NotificationService } from '../notifications';
import { GfValueComponent } from '../value';
import { GfAccountsTableComponent } from './accounts-table.component';
@ -108,7 +110,13 @@ export default {
NgxSkeletonLoaderModule,
RouterModule.forChild([])
],
providers: [NotificationService]
providers: [
NotificationService,
{
provide: EntityLogoImageSourceService,
useValue: new EntityLogoImageSourceServiceMock()
}
]
})
]
} as Meta<GfAccountsTableComponent>;

10
libs/ui/src/lib/activities-table/activities-table.component.stories.ts

@ -16,6 +16,8 @@ import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { GfActivityTypeComponent } from '../activity-type/activity-type.component';
import { GfEntityLogoComponent } from '../entity-logo';
import { EntityLogoImageSourceService } from '../entity-logo/entity-logo-image-source.service';
import { EntityLogoImageSourceServiceMock } from '../mocks/entity-logo-image-source.service.mock';
import { GfNoActivitiesInfoComponent } from '../no-activities-info/no-activities-info.component';
import { NotificationService } from '../notifications';
import { GfValueComponent } from '../value';
@ -371,7 +373,13 @@ export default {
NgxSkeletonLoaderModule,
RouterModule.forChild([])
],
providers: [NotificationService]
providers: [
NotificationService,
{
provide: EntityLogoImageSourceService,
useValue: new EntityLogoImageSourceServiceMock()
}
]
})
]
} as Meta<GfActivitiesTableComponent>;

5
libs/ui/src/lib/entity-logo/entity-logo-image-source.service.ts

@ -2,8 +2,9 @@ import { AssetProfileIdentifier } from '@ghostfolio/common/interfaces';
import { Service } from '@angular/core';
// Must stay auto-provided: several table stories render gf-entity-logo
// without providing an override and resolve this from the root injector
// Must stay auto-provided: the currency selector and portfolio filter form
// stories render gf-entity-logo without providing an override and resolve
// this from the root injector
@Service()
export class EntityLogoImageSourceService {
public getLogoUrlByAssetProfileIdentifier({

46
libs/ui/src/lib/mocks/entity-logo-image-source.service.mock.ts

@ -1,3 +1,4 @@
import { getAssetProfileIdentifier } from '@ghostfolio/common/helper';
import { AssetProfileIdentifier } from '@ghostfolio/common/interfaces';
import { DataSource } from '@ghostfolio/prisma/enums';
@ -9,18 +10,47 @@ export class EntityLogoImageSourceServiceMock {
dataSource,
symbol
}: AssetProfileIdentifier) {
if (dataSource === DataSource.YAHOO && symbol === 'AAPL') {
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAJa0lEQVR4nM2bW2wU1xnHf3vx2t61za5nL/bGKwx2jQnwUh5Q3bqyHYhzIVLUFoIaSKtGSrkkNaQJqlQSKaHQFygQJamUSomaRKpSlYekqSF1HGix6EOktIldOQs0OCEs3ssw48Ve8F77MGuwza4ve2Y3/KR92Ln8z/d9OnPmnG/OZ/jss2FKRA3QCiwDPEAtUAEkgWvAGKAAF4HPgWgpjDIXUdsF3AN0Zn/NVmuFoazMgtlswmw2YTAYyGQgnU6TSqVIpdIkEnFisRsZ4AJwGjgFfAiEi2GkQeceUAn8CPgJ0GG315hsNis2m5XycsuihCYn40xMxJiYiKGq0RRaMP4I/AW4rpfBegXAAfQAu+z2JU6HowabzYbBoIc0ZDIwMTGBokRR1bEI8ApwDO2REUI0AGbgKeB5t1uyS1ItZrNJ1KY5SSZTyPJVQiFZBfYDL6GNIwUhEoDvAr+XJMcaSXIsuouLEo/HiUQUZFkZBHYCA4XoGAu4xwS8APzD5/Ou8Xo9JXcewGKx4PV68Pm8a9DGhxezti2KxfYAF/COJDk63W5n0bv7QkkmU4RCEWRZOQU8wiLeGIvpAY3AgNvt7PR6PXeM8wBmswmv14Pb7exEexQaF3rvQgOwCjhbV+dq8XicBZhYGjweJ3V1rhbgLJrN87KQADQBJ71eT73LJYnYVxJcLgmv11MPnASa57t+vgC4gJP19e4GSXLoYV9JkCQH9fXuBuAEmg95mSsAZcBxt9vZ7HTW6mlfXsbHJzh27CU6Ojppbm7h4sWLBWs5nbW43c5m4DiaLzmZay2wX5Ic7aV65s+dO8fu3U8zNDQEgM1mo7q6WkjT43GSSqXaZVnZD/wq1zX5esD3gGfr6ubsPbpx/vx5tm597KbzAK2tK6itFe95WR+eRfPpNnIFwAy86vN5jUZjIfOkxTE5Ocnu3U8zOjo64/hDD21Ej/aNRiM+n9cIvEqOHp+rhR5Jcqyx22uEG18IfX19DA4OzjhWX1/Pww8/rFsbdnsNkuRYA/xi9rnZAagB9pVq0AN4//3eGf+rq6s5cuSwLt1/Ok6nA+A5NB9vMjsAO10uyW6x5B00dSWRSPDpp/+5+b+lpYW3336LtrY23duyWCy4XJIdbeF0k+nPRCWwR5Lsujeej3Q6zbJly1m6dCnd3d1s27YVs7l4SSpJshMOy3uAo8ANmLkY2mK31/zJ5/Pq1qAsy/T1fcjg4CCKomK1VrJy5Uo6Ojpoalp+2/VDQ0P09X2I33+O8fFrlJdX4PXW09bWRldXJ+Xl5cI2ffVVgLGx6BbgHZgZgL81NjY8UF1dJdxIMpnktdf+wOuvv0EoFLrtfEVFBV1dXWzc+AB33dXA4OAg7733Vz7++GMymUxOzdbWVvbufYb169cL2Xbt2jgjI1/3Ag/CrQC4gMDq1SvMBsE81uTkJDt3PklfX5+QTj4OHjzA1q2PFnx/JpNhaMifBLxAeGoQvMdurxF2PpVK0dOzp2jOA+zb9xx+v7/g+w0GA3Z7jRktY33zLdBls1mFjXvrrbfp7e2d/8ICMRgMHDjwG5qamoR0sr52wa23QGdVlVgAotEoL7/8ipDGfDz//HM8+uiPhXWyAegArQdYgeUWi1he78SJkzkHPL3o7r6Xxx//mS5a2RxmE1BpBJorKsqFJ939/f2iEnkxmUw89dSTumpmff6WEWjVI6s7MvKlsEY+li9fzqpVC8pwLZiszyuMQH1ZmfjsKxodE9bIR3NzEyaTvknY7Iyz3gg49BCfnIwLa+SjslL8DTWbrM8OI1Au+v4HdFm750NRruquaTQaACqMQCrP7HNR2Gw2cZE8DA9/TiwW01Uz63PSCFxLp9PCgnb7EmGNfIyOjnL69GldNbM+jxuBaDqdEhZctmyZsMZcHDlyTNdekPU5agTkZFI8AOvWrRPWmAu/309Pz24SiYQuelmfw0bgcz1G8La271BWVtxM0gcf/J0nntjO5cuXhbWyPp8zAhdu3JgUHgQaGxtZu/bbwobNR39/P5s2PSKsk/X5vBGIAV/E4+K9YMuWLcIaCyGZLHhDCKBtrgC+AK5PvbxPjY+LDzD33deNz+cT1pmPzZs3Cd2f9fUU3MoHfDQxIR4Aq9XKrl07hHXmora2lm3btgppZH2dEYB+VY0m8+XjFsPmzZtZvXq1sE4+duzYjsfjKfj+TCaDqkaTQD/cCkAY6NPjMTCbzezf/0JR0tt3372Sxx7bJqSR9bEPCMHMDyNvqqo+K7q1a9eyd++zumhNUVVl4/DhQ1RWVgrpZH18c+r/9AC8q6rRsF4Tje3bfy78rE5hNps5evSocE4gkUigqtEQ8O5N7WnnrwO/k2X1t3p9Fn/xxReIxa5z/PjxGcdtNhvr199De3s7DQ0NxONx/H4/J06c4JNP/j3j2qoqGwcPHuTeezcI2yPLKsARpm21nb1Nrgb4csWKJl2/D/b29nLmzACJRIKWlhY2bFifc+2QyWQYGBjg7Nl/oSgqdXUeNm58kObmebf6zEs8nsDv/58KLGXaTvRc+wR/KUmOQ15v4SPtnUggEESWlWeAw9OP58piHJNlZUhVS7JdvySoanRqS+2x2edyBSAJ7Lh0KZDWI0/wTZNOp7l0KZBG+yx+2xw6Xx5rADg0OlqUGoWSEgyGAQ6RZzP1XIm8fbKsnAkGI8WwqyQEgxEiEWUAbWdITuYKQAL4YSgUuRCJ6J+ULDaRyFVCocgF4AdA3qXufKncMHD/lSuhr2VZuDijZMiywpUrocvA/cyzc3whuewLwH2BQPBKOCzrYV9RCYdlAoHgFaAbzfY5WWgy/79A2+ho+NydPCYEgxFGR8MXgDY0m+dlMV8zRoD2UChyKhAIokciVS+SyRSBQJBQKHIKrZRnZKH3LvZzTgjYIMvK/uHh8+k7YbKkqlGGh8+ns/uBN5Bd5i4UkaKpduBVSXKsdjprKdXewini8QSRyFVkWRlCm+ScKURHj7K5HuDXLpfkkCQHenxpnotEIoksK4TDsgIcQJvefiNlc9OpAZ4EehyOJW6HYwlWq1XXwslYLIaijKEoYyE0p19Gh/riYpTObgJ+Cnx/qnS2qsrKYrfgxONxxsdnlM7+E6109s/cgaWzufCg7cTqAjqMRmNzRUU5ZWVllJWZMJnyFU8nuHFjknQ6PVU8/VH2FyyGkcUMwGxqgJVoJW11gARYuL18fgQYpkTl8/8HqhBYlUKrXOwAAAAASUVORK5CYII=';
switch (getAssetProfileIdentifier({ dataSource, symbol })) {
case getAssetProfileIdentifier({
dataSource: DataSource.YAHOO,
symbol: 'AAPL'
}):
return 'data:image/png;base64,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';
case getAssetProfileIdentifier({
dataSource: DataSource.YAHOO,
symbol: 'BNDW'
}):
case getAssetProfileIdentifier({
dataSource: DataSource.YAHOO,
symbol: 'VT'
}):
case getAssetProfileIdentifier({
dataSource: DataSource.YAHOO,
symbol: 'VTI'
}):
return 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJx8fLT0tMTU3Ojo6Iys/RD84QzQ5OjcBCgoKDQwNGg8PGjclHyU3Nzc3Nzc3Nzc3Nzc3Nzc3Njc3Nzc3Nzc4NzU3Nzc3MDU1NTc1NTE3Ny0rMC0tLTctLf/AABEIACAAIAMBEQACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAEBwMFBgD/xAArEAACAQQAAggHAAAAAAAAAAABAgMABAURElEGBxMhQWFxgSIxMoKRkqH/xAAaAQACAwEBAAAAAAAAAAAAAAABAwIEBgAF/8QAKBEAAgICAAQEBwAAAAAAAAAAAQIAEQMEBTFBwRIhQnEGEyOhsdHh/9oADAMBAAIRAxEAPwB1XdzHaW8lxOWEcalmKoWIA8gCTQupJELsFXmZT4jpjgMxerZY7ICa4YEqnZOuwBs97KBURkVjQMt5+G7WunjyLQ9x2MNzWax+Dt1uMpM0MLNwhxE7jfnwg6oswXnE6+rl2W8OIWfcD8wmwvbfI2cV5ZuXgmXijYqV2Oej30QbFiLy4mxOUfyIhFGQiAyCN0N6wC0YKxW1yJEA8Ym79fqSKon6bzd4iN/Qo8yPuP7Nz1qXDZOXCdH7NwWvpxIxHgv0qfT4mP207MbpR1nicFQYRl2X9Ir9xg2tvHa20NvAvDFCgRF5KBoD8U8Cp4LuXYs3MyajIxWddOFZ47TNQxk9mOwnIHyG9qT7kj3FVthes03w9sgFsBPPzHeBdVqXOd6SLkb08aYqzWCI8joqv846GG2az0juMlNbW+UnrN9z2jgq1MnOrp0imijnieKaNZI3GmR1BDDkRXQqxU2poiB4rDY7ELMuMtI7ZZn43Cb0TrXt6DuoKoXlHZ9nLno5WupY0Yif/9k=';
case getAssetProfileIdentifier({
dataSource: DataSource.YAHOO,
symbol: 'IBIT'
}):
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAbklEQVRYhe3UsQ2AMAwEwA8iksdhgzASozASbMA4llKEhtbFS0Ru/lsr9ilRXMYYYFLNLgAtKN/dfWf6LdT0CRFAgML+gr+TfgMre6CanQC2oPx092Mq4BseLSI66U8ggAACCCCAAAIIIIAA6YAXmvMQrFvWq40AAAAASUVORK5CYII=';
default:
return UNAVAILABLE_LOGO_URL;
}
return UNAVAILABLE_LOGO_URL;
}
public getLogoUrlByUrl(url: string) {
if (url === 'https://ghostfol.io') {
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAP1BMVEU2z8v////x/Pspzcn0/Px73drR8/KC3tz6/v6e5eOl5+WM4d7n+PhI08/i9/eu6edV1dJk2NVx2teV4+G87evvttLSAAABDElEQVRYhe2V3Y6EIAyFrQXlTwHd93/WpeBsdiKbtF7tJJwbCKFfDlKO0zQ0NPQJwqrn1ZO2zlk9PWPgusClRcsJmHb4pWUTItDDu4zMBJ5w0yog4HGvB0gCgOoBZrYFdL16AMsmmD5AcQ3ofj3AwbOAX38BIhMw02ZjtQ+tLnht66mCAGA2eka1G3eabUZwD/PLbeuHenKMBODVV0Dru/TTQLgKAc1BvQ/9yAEkOnlon66oehEBIHp7dbSyPoIc0NEADMDnAa4wAvVK+CADRGx/VpNSi+iF3jMTUH4rJQ0aISPmVk+JoJiZeJw1QnaqL2OmWKSFkxnrZWsbXK4TzO5tmS+8TYaGhv6xvgEEfAgHGc7HRgAAAABJRU5ErkJggg==';
switch (url) {
case 'https://ghostfol.io':
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAP1BMVEU2z8v////x/Pspzcn0/Px73drR8/KC3tz6/v6e5eOl5+WM4d7n+PhI08/i9/eu6edV1dJk2NVx2teV4+G87evvttLSAAABDElEQVRYhe2V3Y6EIAyFrQXlTwHd93/WpeBsdiKbtF7tJJwbCKFfDlKO0zQ0NPQJwqrn1ZO2zlk9PWPgusClRcsJmHb4pWUTItDDu4zMBJ5w0yog4HGvB0gCgOoBZrYFdL16AMsmmD5AcQ3ofj3AwbOAX38BIhMw02ZjtQ+tLnht66mCAGA2eka1G3eabUZwD/PLbeuHenKMBODVV0Dru/TTQLgKAc1BvQ/9yAEkOnlon66oehEBIHp7dbSyPoIc0NEADMDnAa4wAvVK+CADRGx/VpNSi+iF3jMTUH4rJQ0aISPmVk+JoJiZeJw1QnaqL2OmWKSFkxnrZWsbXK4TzO5tmS+8TYaGhv6xvgEEfAgHGc7HRgAAAABJRU5ErkJggg==';
case 'https://interactivebrokers.com':
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAkFBMVEXZICceHh4dHR0fHx8gICAUFBQTExMZGRkhISEaGhoVFRUYGBgSEhIXFxcWFhYcHBwbGxsiIiIRERG5HyTiICiyHyPEHyWtHiO/HyUvGxzOICYAFBMVGRkKFhYAGRgQFRVdGRtxHR+JHiGDHiI/HB2UHyJYGhxmGBolGxtIGxw2GxulHyN4HSCcHSIPHBxRHB764qjxAAADtUlEQVRYhYWXbZeiOBCFa5zpYW1X6W0gvBhAFBQV8f//u00RSFIh0HX6S3vOfby3kpQJ/Kfrn7H+DPUb6xfWBsvH+sLaivKwdqL28LNeA+Z6E+DQuwxsJ4DUrwOIvk2JgVGvAUsGNiNgU7UuAwrwU4DiXPUu/QSg+nmAosp8p34ErOs3fn+HSzFfAVEHAvizEKC/Z2HhNHCQgB8C8DoIm8IZgAIWAvDHE6DmzgASsL4CPG0gfPoLBhCwrv/aXDKAE1/QG4CFBvKb0McPvnUGQMCqAVwAAOgsA3tl4BN+aECP+uDOFwJ8KoCp12eA+0zo4Sz11MCBANxbiLcx6pNrv2iAAmb6BvXwWlqBTwVwbiG/xQUEyKp+McAImOmlgWrQQ9RyMgWJ3gTY+uvQQMi6YrYDNOADFhtQJ4MeWDozcNAGbIAy4PuR1MO5mAXYaz0CnPo+DqU+ww54Cx34QIA7wHnUh6+5ASOABVAGeAdTPfhaAAFwjfF+XEBRcWFvIf39BoAG6E9s0oe4i1cCEIDSvwMVIBAtdAwBrZcAEqCvY6UPK74e4OMv2Ab88QQNldRogPO8KHLuCvB3ANAVnBYQDVzE93Pe3qtLd033pUOPAKL3U60H9u493p6iECvrHuUsAAJ+LwOalvPdWf0b1+VMPwH0EDAA2a33Cr2lxGRBD8YKDAD7EBuAOOV8mxkAuJW23gTInwENyLre629GInEw0pIGGAHm74gGBCn3itg0AOxeWgY0YLxJGICm8LyCEQC8c8vAv0ACmAD24AJAWgDhADD1CCB3MQ14CQNeERFAhhE+XAB1F9QA0ULPO3ZmE+H5KC0DAvBrAfB8596Ot8RBZ3+/AFiXUQVIotc73+2KS0gNOAHGZVYBoih43fMdNw5n8J7rNWC8DE+ARACCV53vedqxUHwWQlNTvQZsHIAIAUHTlnu+T0/N81XVh0lvGlCA6TY+ApgEJOdWzJEyP4oqP+cdlABymx8BgQQE7CImkTUFiV4A6HNCAlg8AhJWcXuMEsA3WO8ZCQgUIGG3fM2AAZDPiQHAIgMQ3I4regkw3kMDIIkNAItOR3sIqAASYL6HEJBFBMDi69GtNwFfBoDFFJDFde5s4LcEkAedAKABCsBD4GzAAPBtABogAEEQw9DVAAXQDzoBCOaADJqydAUQAOtFytPs6QBkcN7PG0gA2wkw7MJRnQxiORfPucvAACAPyu3pKusk63YTf1in0qVHwBcB7PJ54WE85q4ACrBym7anKNV//w9w4apH/GbnrAAAAABJRU5ErkJggg==';
case 'https://www.coinbase.com':
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAclBMVEVHcEz////////////////////////9/v////////////////////////////////////////////////8AUv8AUP8ATP/4+/8ARv9sjv8laP/F1f8KWv+rwf9Mgf/u9f/R3v/h6f80c/91nv+8zf+Pq/9HDuvmAAAAE3RSTlMAxpwd5o4v/gZyD0axz8tb2NVC3+ryxwAAA01JREFUWIWlV2uXgiAQ1cxIa2tLQFTEZ///L64C0qBonvZ+6RybGWCedzzPiXMcXKKrf0RJgo63Q3QJ4rNb0ongEv4kI1Bi8BM+g53qp+iauID86LRHPfx1qks8wviT/v24rj7iGG0f71t3TjUQ/Oivv+McvY9Pm6bsRMsx5rnoyqZJwSVWAnIOzSlV/2oJo5SSEZQyLF59Zf4OnRbOh0mgKjM86GIAQhnPSmPi4LDw1i8Et7UnGzwrpjssLRj9tHOqSxMEZ+nKHcz7G85W1CVYXmvBmR8ifbUipxvqA2he6KBaCXFS8UP9J/3hHXkvLaAjzAedPx/P13dQ0v7iAXW+9Xxwh0bJ3yf9WD0g3XO+vANXsTCP0BHI2PIwicVn1ulIaA8+lAPwTHLIPpIPwGyeGIQrN/yegAeqbCZFqSiLekBRCjx7HBXVO5SBCkHJ7eRnoq7QVFuFsNOL8FL+cx273BNJmYy6JEwBzuzTTF3hYpK4twRIWyQzFFaMiU6GIaFj2X/TFwwB4fVcf34EfclQ/sReoGpIwBewcqk/eAmeQYXKpsC7KAMw2lS49FHagkMIbrQTooV1ghcOUKhhPrBefos82UhQR+EFKreBSoxtUoN1MshX7yZ9CF3ASuQ2gPoM4CWlfE8WUmrFaOUFYFC8h8XRk78pCBHJHTFcBfLkT4q/NZD838C/n6CcCHJkNQ1GOQj55aj66b4wpo4w3jzJRr5PpIMrlemKE3pYTbrgov3FlCS5s5gCeZOm/bqcY1UML2hg6roWCquhMNNQppaG7Za2cEPfWk2Rm5amnfChqc6btm6q6Dm29atTgoni3dbrlbbuB2CwiPnwwO/BQmf/kQwMFu+kqKlrtOHt0fY4WcO1+3a4Tvwk5XvHe6sLyRDnuzLY7CMIpt4BS/qG4iBAcQDJ+khyJpKVWCTrC5qHbN5viGadbxFNwrgmWHOiCahuhh2BU+qUd2tU1yLb2RrZFqZIXXTdg3Sfszndp/gD3YcLRzIsHGLI4GnfGHK6BQvH4v3GwmLlyceVp9Urz9SrV1ceb9fSlWwsXSOiT2vffVN9QBw+1tV/w127a+S7R9N11+o7Injq5Rv4ww8ve5fvEXL9P9zU+u9fN9b/P6gEACs+iQ7UAAAAAElFTkSuQmCC';
case 'https://www.jpmorgan.com':
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAY1BMVEUkJSb///8hIiMvMDHd3d0AAACoqaknKCmzs7SioqIODxGlpaYZGxxub2+XmJiNjY0TFRY4ODk/QEDn5+fu7u7V1tb29vbBwcGCg4NTU1TP0NB4eXpdXV5kZGQDBwlqamtGR0icW6P1AAACGElEQVRYhe2Ua5qrIAyGDYpYGhFBxVqr7n+VJ/HWqT3zjAvw+yOE8BJDSBRdunTp0qX/SKx6j5bZNv/2PQCcK0nOxWoeOVYZC+QVNvzwF/Hs+Ml0iW8AGp88+9oDQOV91UBiHlh2vAJOvPcn7Hmzn38gpQG4SYkoLTm85BD3GUAyopT0BaM3V3zRNBt0dNQN4K63E3KMBNoCIMRCZRRCNWx+MjBAfafxCOCwGvAvVPfgV8u8DN1ZQCRrgNaq1NCh9RqzNlVxGqDJVjAgr6AaZ5MQjWlPA4awRmAplDCbbNvE5yNYc5AaSXuSfs5LF+xpwPBcbiE1WtFFGLJh75+nAKO2Wj4bqHpkgNUpQDeJSN+TCc8ATG5SD00a06kMoMujdKCY6sKKM4CQpmkxqoELmAERZvw72FImTgFGqbXFpf4XwEgh9CoEJU4BtrrbAcJR/aVT1dLwALBSir8BEacObp5e8QFgW6jnt00AdvwV8KiZQEccAUuVipiyNFfrNyAL/BQt3WTFbeETIBQBckrSlICfl5Es0Oq9gSB2gWf48hAkO6Rc1/sJXO9ZJF0GzZP3lz2/d99O2xkP01SG0dgBlVI0tXRAYx57CI42UAODkCtatiYkrC57LC21zOokqQvCYR40zzter7O9TQrlXmPel2putNQx41nlFsEyXbIh9vlqWQgCSVuf/mjpb8My/OkQXbp06dKlD/0Do0chlGcV4zUAAAAASUVORK5CYII=';
default:
return UNAVAILABLE_LOGO_URL;
}
return UNAVAILABLE_LOGO_URL;
}
}

Loading…
Cancel
Save