diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d5674673..5ecf2a57d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,63 @@ 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 + +- Changed the build executor of the client from `@nx/angular:webpack-browser` to `@nx/angular:browser-esbuild` + +### Fixed + +- Fixed the style of the safe withdrawal rate selector in the _FIRE_ section (experimental) + +## 2.214.0 - 2025-11-01 + +### Changed + +- Improved the icon of the _View Holding_ menu item in the activities table +- Ensured atomic data replacement during historical market data gathering +- Removed _Internet Identity_ as a social login provider +- Refreshed the cryptocurrencies list +- Upgraded `countries-list` from version `3.1.1` to `3.2.0` +- Upgraded `ng-extract-i18n-merge` from version `3.0.0` to `3.1.0` +- Upgraded `twitter-api-v2` from version `1.23.0` to `1.27.0` + +## 2.213.0 - 2025-10-30 + +### Added + +- Extended the activities table menu with a _View Holding_ item +- Added the error logging to the symbol lookup in the _Trackinsight_ data enhancer + +### Changed + +- Improved the icon of the holdings tab on the home page +- Improved the icon of the holdings tab on the home page for the _Zen Mode_ +- Improved the icon of the holdings tab in the account detail dialog +- Migrated the tags selector component in the holding detail dialog to form control +- Improved the language localization for German (`de`) +- Upgraded `nestjs` from version `11.1.3` to `11.1.8` + +## 2.212.0 - 2025-10-29 + +### Added + +- Added a close holding button to the holding detail dialog +- Added the _Sponsors_ section to the about page +- Extended the user detail dialog in the users section of the admin control panel + +### Changed + +- Refactored the generation of the holdings table in the _Copy AI prompt to clipboard for analysis_ action on the analysis page (experimental) +- Refactored the generation of the holdings table in the _Copy portfolio data to clipboard for AI prompt_ action on the analysis page (experimental) +- Improved the usability of the user detail dialog in the users section of the admin control panel +- Improved the language localization for German (`de`) + +### Fixed + +- Ensured the locale is available in the settings dialog to customize the rule thresholds of the _X-ray_ page + ## 2.211.0 - 2025-10-25 ### Added diff --git a/README.md b/README.md index 82d5710d1..1a5cc6e95 100644 --- a/README.md +++ b/README.md @@ -297,7 +297,18 @@ Ghostfolio is **100% free** and **open source**. We encourage and support an act Not sure what to work on? We have [some ideas](https://github.com/ghostfolio/ghostfolio/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22%20no%3Aassignee), even for [newcomers](https://github.com/ghostfolio/ghostfolio/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22%20no%3Aassignee). Please join the Ghostfolio [Slack](https://join.slack.com/t/ghostfolio/shared_invite/zt-vsaan64h-F_I0fEo5M0P88lP9ibCxFg) channel or post to [@ghostfolio\_](https://x.com/ghostfolio_) on _X_. We would love to hear from you. -If you like to support this project, get [**Ghostfolio Premium**](https://ghostfol.io/en/pricing) or [**Buy me a coffee**](https://www.buymeacoffee.com/ghostfolio). +If you like to support this project, become a [**Sponsor**](https://github.com/sponsors/ghostfolio), get [**Ghostfolio Premium**](https://ghostfol.io/en/pricing) or [**Buy me a coffee**](https://www.buymeacoffee.com/ghostfolio). + +## Sponsors + +
+

+ Browser testing via
+ + LambdaTest Logo + +

+
## Analytics diff --git a/apps/api/src/app/admin/admin.controller.ts b/apps/api/src/app/admin/admin.controller.ts index d7c4c5d3d..2419b0a7d 100644 --- a/apps/api/src/app/admin/admin.controller.ts +++ b/apps/api/src/app/admin/admin.controller.ts @@ -17,7 +17,7 @@ import { getAssetProfileIdentifier } from '@ghostfolio/common/helper'; import { AdminData, AdminMarketData, - AdminUsers, + AdminUsersResponse, EnhancedSymbolProfile, ScraperConfiguration } from '@ghostfolio/common/interfaces'; @@ -315,7 +315,7 @@ export class AdminController { public async getUsers( @Query('skip') skip?: number, @Query('take') take?: number - ): Promise { + ): Promise { return this.adminService.getUsers({ skip: isNaN(skip) ? undefined : skip, take: isNaN(take) ? undefined : take diff --git a/apps/api/src/app/admin/admin.service.ts b/apps/api/src/app/admin/admin.service.ts index 11f6f0599..683e72cb8 100644 --- a/apps/api/src/app/admin/admin.service.ts +++ b/apps/api/src/app/admin/admin.service.ts @@ -23,7 +23,7 @@ import { AdminMarketData, AdminMarketDataDetails, AdminMarketDataItem, - AdminUsers, + AdminUsersResponse, AssetProfileIdentifier, EnhancedSymbolProfile, Filter @@ -513,7 +513,7 @@ export class AdminService { }: { skip?: number; take?: number; - }): Promise { + }): Promise { const [count, users] = await Promise.all([ this.countUsersWithAnalytics(), this.getUsersWithAnalytics({ skip, take }) @@ -818,7 +818,7 @@ export class AdminService { }: { skip?: number; take?: number; - }): Promise { + }): Promise { let orderBy: Prisma.Enumerable = [ { createdAt: 'desc' } ]; diff --git a/apps/api/src/app/auth/auth.controller.ts b/apps/api/src/app/auth/auth.controller.ts index 13d8e37f6..57fd04bc7 100644 --- a/apps/api/src/app/auth/auth.controller.ts +++ b/apps/api/src/app/auth/auth.controller.ts @@ -102,23 +102,6 @@ export class AuthController { } } - @Post('internet-identity') - public async internetIdentityLogin( - @Body() body: { principalId: string } - ): Promise { - try { - const authToken = await this.authService.validateInternetIdentityLogin( - body.principalId - ); - return { authToken }; - } catch { - throw new HttpException( - getReasonPhrase(StatusCodes.FORBIDDEN), - StatusCodes.FORBIDDEN - ); - } - } - @Get('webauthn/generate-registration-options') @UseGuards(AuthGuard('jwt'), HasPermissionGuard) public async generateRegistrationOptions() { diff --git a/apps/api/src/app/auth/auth.service.ts b/apps/api/src/app/auth/auth.service.ts index ceff492a0..a6ee5d260 100644 --- a/apps/api/src/app/auth/auth.service.ts +++ b/apps/api/src/app/auth/auth.service.ts @@ -4,7 +4,6 @@ import { PropertyService } from '@ghostfolio/api/services/property/property.serv import { Injectable, InternalServerErrorException } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; -import { Provider } from '@prisma/client'; import { ValidateOAuthLoginParams } from './interfaces/interfaces'; @@ -44,42 +43,6 @@ export class AuthService { }); } - public async validateInternetIdentityLogin(principalId: string) { - try { - const provider: Provider = 'INTERNET_IDENTITY'; - - let [user] = await this.userService.users({ - where: { provider, thirdPartyId: principalId } - }); - - if (!user) { - const isUserSignupEnabled = - await this.propertyService.isUserSignupEnabled(); - - if (!isUserSignupEnabled || true) { - throw new Error('Sign up forbidden'); - } - - // Create new user if not found - user = await this.userService.createUser({ - data: { - provider, - thirdPartyId: principalId - } - }); - } - - return this.jwtService.sign({ - id: user.id - }); - } catch (error) { - throw new InternalServerErrorException( - 'validateInternetIdentityLogin', - error.message - ); - } - } - public async validateOAuthLogin({ provider, thirdPartyId diff --git a/apps/api/src/app/auth/google.strategy.ts b/apps/api/src/app/auth/google.strategy.ts index 02f82a7a8..3e4b4ca0d 100644 --- a/apps/api/src/app/auth/google.strategy.ts +++ b/apps/api/src/app/auth/google.strategy.ts @@ -3,6 +3,7 @@ import { ConfigurationService } from '@ghostfolio/api/services/configuration/con import { Injectable, Logger } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { Provider } from '@prisma/client'; +import { DoneCallback } from 'passport'; import { Profile, Strategy } from 'passport-google-oauth20'; import { AuthService } from './auth.service'; @@ -29,7 +30,7 @@ export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { _token: string, _refreshToken: string, profile: Profile, - done: Function + done: DoneCallback ) { try { const jwt = await this.authService.validateOAuthLogin({ diff --git a/apps/api/src/app/endpoints/ai/ai.service.ts b/apps/api/src/app/endpoints/ai/ai.service.ts index 4cc4fde65..d07768d69 100644 --- a/apps/api/src/app/endpoints/ai/ai.service.ts +++ b/apps/api/src/app/endpoints/ai/ai.service.ts @@ -14,6 +14,27 @@ import type { ColumnDescriptor } from 'tablemark'; @Injectable() export class AiService { + private static readonly HOLDINGS_TABLE_COLUMN_DEFINITIONS: ({ + key: + | 'ALLOCATION_PERCENTAGE' + | 'ASSET_CLASS' + | 'ASSET_SUB_CLASS' + | 'CURRENCY' + | 'NAME' + | 'SYMBOL'; + } & ColumnDescriptor)[] = [ + { key: 'NAME', name: 'Name' }, + { key: 'SYMBOL', name: 'Symbol' }, + { key: 'CURRENCY', name: 'Currency' }, + { key: 'ASSET_CLASS', name: 'Asset Class' }, + { key: 'ASSET_SUB_CLASS', name: 'Asset Sub Class' }, + { + align: 'right', + key: 'ALLOCATION_PERCENTAGE', + name: 'Allocation in Percentage' + } + ]; + public constructor( private readonly portfolioService: PortfolioService, private readonly propertyService: PropertyService @@ -59,14 +80,10 @@ export class AiService { userId }); - const holdingsTableColumns: ColumnDescriptor[] = [ - { name: 'Name' }, - { name: 'Symbol' }, - { name: 'Currency' }, - { name: 'Asset Class' }, - { name: 'Asset Sub Class' }, - { align: 'right', name: 'Allocation in Percentage' } - ]; + const holdingsTableColumns: ColumnDescriptor[] = + AiService.HOLDINGS_TABLE_COLUMN_DEFINITIONS.map(({ align, name }) => { + return { name, align: align ?? 'left' }; + }); const holdingsTableRows = Object.values(holdings) .sort((a, b) => { @@ -78,17 +95,45 @@ export class AiService { assetClass, assetSubClass, currency, - name, + name: label, symbol }) => { - return { - Name: name, - Symbol: symbol, - Currency: currency, - 'Asset Class': assetClass ?? '', - 'Asset Sub Class': assetSubClass ?? '', - 'Allocation in Percentage': `${(allocationInPercentage * 100).toFixed(3)}%` - }; + return AiService.HOLDINGS_TABLE_COLUMN_DEFINITIONS.reduce( + (row, { key, name }) => { + switch (key) { + case 'ALLOCATION_PERCENTAGE': + row[name] = `${(allocationInPercentage * 100).toFixed(3)}%`; + break; + + case 'ASSET_CLASS': + row[name] = assetClass ?? ''; + break; + + case 'ASSET_SUB_CLASS': + row[name] = assetSubClass ?? ''; + break; + + case 'CURRENCY': + row[name] = currency; + break; + + case 'NAME': + row[name] = label; + break; + + case 'SYMBOL': + row[name] = symbol; + break; + + default: + row[name] = ''; + break; + } + + return row; + }, + {} as Record + ); } ); diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btceur-in-base-currency-eur.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btceur-in-base-currency-eur.spec.ts new file mode 100644 index 000000000..87893e647 --- /dev/null +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btceur-in-base-currency-eur.spec.ts @@ -0,0 +1,140 @@ +import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; +import { + activityDummyData, + loadExportFile, + symbolProfileDummyData, + userDummyData +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; +import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { ExchangeRateDataServiceMock } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service.mock'; +import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; +import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock'; +import { parseDate } from '@ghostfolio/common/helper'; +import { ExportResponse } from '@ghostfolio/common/interfaces'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; + +import { Big } from 'big.js'; +import { join } from 'node:path'; + +jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { + return { + CurrentRateService: jest.fn().mockImplementation(() => { + return CurrentRateServiceMock; + }) + }; +}); + +jest.mock( + '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service', + () => { + return { + ExchangeRateDataService: jest.fn().mockImplementation(() => { + return ExchangeRateDataServiceMock; + }) + }; + } +); + +jest.mock( + '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service', + () => { + return { + PortfolioSnapshotService: jest.fn().mockImplementation(() => { + return PortfolioSnapshotServiceMock; + }) + }; + } +); + +jest.mock('@ghostfolio/api/app/redis-cache/redis-cache.service', () => { + return { + RedisCacheService: jest.fn().mockImplementation(() => { + return RedisCacheServiceMock; + }) + }; +}); + +describe('PortfolioCalculator', () => { + let exportResponse: ExportResponse; + + let configurationService: ConfigurationService; + let currentRateService: CurrentRateService; + let exchangeRateDataService: ExchangeRateDataService; + let portfolioCalculatorFactory: PortfolioCalculatorFactory; + let portfolioSnapshotService: PortfolioSnapshotService; + let redisCacheService: RedisCacheService; + + beforeAll(() => { + exportResponse = loadExportFile( + join(__dirname, '../../../../../../../test/import/ok/btceur.json') + ); + }); + + beforeEach(() => { + configurationService = new ConfigurationService(); + + currentRateService = new CurrentRateService(null, null, null, null); + + exchangeRateDataService = new ExchangeRateDataService( + null, + null, + null, + null + ); + + portfolioSnapshotService = new PortfolioSnapshotService(null); + + redisCacheService = new RedisCacheService(null, null); + + portfolioCalculatorFactory = new PortfolioCalculatorFactory( + configurationService, + currentRateService, + exchangeRateDataService, + portfolioSnapshotService, + redisCacheService + ); + }); + + describe('get current positions', () => { + it.only('with BTCUSD buy (in EUR)', async () => { + jest.useFakeTimers().setSystemTime(parseDate('2022-01-14').getTime()); + + const activities: Activity[] = exportResponse.activities.map( + (activity) => ({ + ...activityDummyData, + ...activity, + date: parseDate(activity.date), + feeInAssetProfileCurrency: 4.46, + SymbolProfile: { + ...symbolProfileDummyData, + currency: 'USD', + dataSource: activity.dataSource, + name: 'Bitcoin', + symbol: activity.symbol + }, + unitPriceInAssetProfileCurrency: 44558.42 + }) + ); + + const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ + activities, + calculationType: PerformanceCalculationType.ROAI, + currency: 'EUR', + userId: userDummyData.id + }); + + const portfolioSnapshot = await portfolioCalculator.computeSnapshot(); + + expect(portfolioSnapshot.positions[0].fee).toEqual(new Big(4.46)); + expect( + portfolioSnapshot.positions[0].feeInBaseCurrency.toNumber() + ).toBeCloseTo(3.94, 1); + }); + }); +}); diff --git a/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json b/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json index a6db74dfd..9a7a0eb77 100644 --- a/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json +++ b/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json @@ -1,7 +1,9 @@ { "1": "just buy $1 worth of this coin", "3": "The Three Musketeers", + "4": "4", "7": "Lucky7", + "8": "8", "32": "Project 32", "42": "42 Coin", "47": "President Trump", @@ -28,6 +30,7 @@ "00": "ZER0ZER0", "007": "007 coin", "0DOG": "Bitcoin Dogs", + "0G": "0G", "0KN": "0 Knowledge Network", "0LNETWORK": "0L Network", "0NE": "Stone", @@ -95,6 +98,7 @@ "2OMB": "2omb Finance", "2SHARES": "2SHARE", "2TF": "2TF", + "2Z": "DoubleZero", "300F": "300FIT", "314DAO": "Tonken 314 DAO", "32BIT": "32Bitcoin", @@ -133,6 +137,7 @@ "50TRUMP": "50TRUMP", "50X": "50x.com", "5IRE": "5ire", + "5PT": "Five Pillars Token", "69MINUTES": "69 Minutes", "77G": "GraphenTech", "7E": "7ELEVEN", @@ -222,6 +227,7 @@ "ACAT": "Alphacat", "ACATO": "ACA Token", "ACCEL": "Accel Defi", + "ACCES": "Metacces", "ACCN": "Accelerator Network", "ACD": "Alliance Cargo Direct", "ACDC": "Volt", @@ -407,7 +413,8 @@ "AI23T": "23 Turtles", "AI3": "Autonomys Network", "AI69SAKURA": "Sakura", - "AIA": "AIA Chain", + "AIA": "DeAgentAI", + "AIACHAIN": "AIA Chain", "AIAF": "AI Agent Factory", "AIAGENT": "AI Agents", "AIAGENTAPP": "Aiagent.app", @@ -533,6 +540,7 @@ "AIX": "ALIENX", "AIX9": "AthenaX9", "AIXBT": "aixbt by Virtuals", + "AIXCB": "aixCB by Virtuals", "AIXERC": "AI-X", "AIXT": "AIXTerminal", "AJNA": "Ajna Protocol", @@ -624,6 +632,7 @@ "ALNV1": "Aluna v1", "ALOHA": "Aloha", "ALON": "Alon", + "ALOR": "The Algorix", "ALOT": "Dexalot", "ALP": "Alphacon", "ALPA": "Alpaca", @@ -641,6 +650,7 @@ "ALPHAS": "Alpha Shards", "ALPHR": "Alphr", "ALPINE": "Alpine F1 Team Fan Token", + "ALPRO": "Assets Alphabet", "ALPS": "Alpenschillling", "ALT": "Altlayer", "ALTA": "Alta Finance", @@ -651,12 +661,13 @@ "ALTMAN": "SAM", "ALTOCAR": "AltoCar", "ALTR": "Altranium", + "ALTT": "Altcoinist", "ALU": "Altura", "ALUSD": "Alchemix USD", "ALUX": "Alux Bank", "ALV": "Allive", "ALV1": "ArchLoot v1", - "ALVA": "Alvara Protocol", + "ALVACOIN": "Alvara Protocol", "ALWAYS": "Always Evolving", "ALX": "ALAX", "ALY": "Ally", @@ -764,6 +775,7 @@ "ANML": "Animal Concerts", "ANN": "Annex Finance", "ANNE": "ANNE", + "ANOME": "Anome", "ANON": "HeyAnon", "ANONCOIN": "Anoncoin", "ANONCRYPTO": "ANON", @@ -786,6 +798,7 @@ "ANUS": "URANUS", "ANV": "Aniverse", "ANVL": "Anvil", + "ANVLV1": "Anvil v1", "ANW": "Anchor Neural World", "ANY": "Anyswap", "ANYONE": "ANyONe Protocol", @@ -795,7 +808,7 @@ "AOG": "AgeOfGods", "AOK": "AOK", "AOL": "AOL (America Online)", - "AOP": "Averopay", + "AOP": "Ark Of Panda", "AOS": "AOS", "AOT": "Age of Tanks", "AP": "America Party", @@ -917,7 +930,8 @@ "AREN": "Arenon", "ARENA": "Arena", "AREPA": "Arepacoin", - "ARES": "Ares Protocol", + "ARES": "ARES", + "ARESP": "Ares Protocol", "ARG": "Argentine Football Association Fan Token", "ARGENTUM": "Argentum", "ARGO": "ArGoApp", @@ -964,7 +978,7 @@ "ARRR": "Pirate Chain", "ARSL": "Aquarius Loan", "ARSW": "ArthSwap", - "ART": "Genify ART", + "ART": "LiveArt", "ARTC": "Artcoin", "ARTDECO": "ARTDECO", "ARTDRAW": "ArtDraw", @@ -1037,6 +1051,8 @@ "ASST": "AssetStream", "AST": "AirSwap", "ASTA": "ASTA", + "ASTER": "Aster", + "ASTERINU": "Aster INU", "ASTO": "Altered State Token", "ASTON": "Aston", "ASTONV": "Aston Villa Fan Token", @@ -1187,6 +1203,7 @@ "AVE": "Avesta", "AVEN": "Aventis AI", "AVENT": "Aventa", + "AVEROPAY": "Averopay", "AVERY": "Avery Games", "AVG": "Avocado DAO", "AVGOX": "Broadcom xStock", @@ -1241,8 +1258,11 @@ "AXNT": "Axentro", "AXO": "Axo", "AXOL": "Axol", + "AXOME": "Axolotl Meme", "AXON": "AxonDAO Governance Token", + "AXP": "aXpire v1", "AXPR": "aXpire", + "AXPRV2": "aXpire v2", "AXR": "AXRON", "AXS": "Axie Infinity Shards", "AXSV1": "Axie Infinity Shards v1", @@ -1286,7 +1306,9 @@ "BABI": "Babylons", "BABL": "Babylon Finance", "BABY": "Babylon", + "BABY4": "Baby 4", "BABYANDY": "Baby Andy", + "BABYASTER": "Baby Aster", "BABYB": "Baby Bali", "BABYBI": "Baby Bitcoin", "BABYBINANCE": "BABYBINANCE", @@ -1311,6 +1333,7 @@ "BABYCEO": "Baby Doge CEO", "BABYCRASH": "BabyCrash", "BABYCRAZYT": "BABY CRAZY TIGER", + "BABYCREPE": "BABY CREPE", "BABYCUBAN": "Baby Cuban", "BABYCZHAO": "Baby Czhao", "BABYD": "Baby Dragon", @@ -1411,6 +1434,7 @@ "BAFC": "BabyApeFunClub", "BAG": "Bag", "BAGS": "Basis Gold Share", + "BAGWORK": "Bagwork", "BAHAMAS": "Bahamas", "BAHIA": "Esporte Clube Bahia Fan Token", "BAI": "BearAI", @@ -1470,15 +1494,17 @@ "BANNER": "BannerCoin", "BANUS": "Banus.Finance", "BANX": "Banx.gg", - "BAO": "Bao Finance", + "BAO": "Bao Token V2", "BAOBAO": "BaoBao", "BAOE": "Business Age of Empires", "BAOM": "Battle of Memes", "BAOS": "BaoBaoSol", + "BAOV1": "BaoToken v1", "BAR": "FC Barcelona Fan Token", "BARA": "Capybara", "BARAKATUH": "Barakatuh", "BARC": "The Blu Arctic Water Company", + "BARD": "Lombard", "BAREBEARS": "BAREBEARS", "BARIO": "Bario", "BARK": "Bored Ark", @@ -1517,6 +1543,7 @@ "BASID": "Basid Coin", "BASIL": "Basilisk", "BASIS": "Basis", + "BASISCOIN": "Basis Coin", "BASK": "BasketDAO", "BAST": "Bast", "BASTET": "Bastet Goddess", @@ -1703,6 +1730,7 @@ "BEIBEI": "Chinese BEIBEI", "BEL": "Bella Protocol", "BELA": "Bela", + "BELG": "Belgian Malinois", "BELL": "Bellscoin", "BELLE": "Isabelle", "BELLS": "Bellscoin", @@ -1759,6 +1787,7 @@ "BETS": "BetSwirl", "BETT": "Bettium", "BETU": "Betu", + "BETURA": "BETURA", "BETZ": "Bet Lounge", "BEX": "BEX token", "BEY": "NBX", @@ -1772,7 +1801,7 @@ "BFEX": "BFEX", "BFG": "BFG Token", "BFHT": "BeFaster Holder Token", - "BFI": "BitDefi", + "BFI": "BlockFi-Ai", "BFIC": "Bficoin", "BFICGOLD": "BFICGOLD", "BFK WARZONE": "BFK Warzone", @@ -1861,6 +1890,7 @@ "BIGPUMP": "Big Pump", "BIGSB": "BigShortBets", "BIGTIME": "Big Time", + "BIGTOWN": "Burp", "BIGUP": "BigUp", "BIH": "BitHostCoin", "BIHU": "Key", @@ -1910,6 +1940,7 @@ "BISKIT": "Biskit Protocol", "BISO": "BISOSwap", "BIST": "Bistroo", + "BISTOX": "Bistox Exchange Token", "BIT": "BitDAO", "BIT16": "16BitCoin", "BITAIR": "Bitair", @@ -1923,6 +1954,7 @@ "BITBURN": "Bitburn", "BITC": "BitCash", "BITCAR": "BitCar", + "BITCARBON": "Bitcarbon", "BITCAT": "Bitcat", "BITCATONSOL": "Bitcat", "BITCCA": "Bitcci Cash", @@ -1939,12 +1971,14 @@ "BITCONNECT": "BitConnect Coin", "BITCORE": "BitCore", "BITCRATIC": "Bitcratic Token", + "BITDEFI": "BitDefi", "BITDEGREE": "BitDegree", "BITE": "Bitether", "BITF": "Bit Financial", "BITFLIP": "BitFlip", "BITG": "Bitcoin Green", "BITGOLD": "bitGold", + "BITGRIN": "BitGrin", "BITHER": "Bither", "BITL": "BitLux", "BITM": "BitMoney", @@ -2035,6 +2069,7 @@ "BLEPE": "Blepe", "BLERF": "BLERF", "BLES": "Blind Boxes", + "BLESS": "Bless Token", "BLET": "Brainlet", "BLF": "Baby Luffy", "BLHC": "BlackholeCoin", @@ -2060,6 +2095,7 @@ "BLOC": "Blockcloud", "BLOCK": "Blockasset", "BLOCKB": "Block Browser", + "BLOCKBID": "Blockbid", "BLOCKF": "Block Farm Club", "BLOCKG": "BlockGames", "BLOCKIFY": "Blockify.Games", @@ -2069,7 +2105,9 @@ "BLOCKS": "BLOCKS", "BLOCKSSPACE": "Blocks Space", "BLOCKSTAMP": "BlockStamp", + "BLOCKSV1": "BLOCKS v1", "BLOCKT": "Blocktools", + "BLOCKTRADE": "Blocktrade", "BLOCKW": "Blockwise", "BLOCM": "BLOC.MONEY", "BLOCX": "BLOCX.", @@ -2082,6 +2120,7 @@ "BLOVELY": "Baby Lovely Inu", "BLOX": "BLOX", "BLOXT": "Blox Token", + "BLOXWAP": "BLOXWAP", "BLP": "BullPerks", "BLPAI": "BullPerks AI", "BLPT": "Blockprompt", @@ -2093,6 +2132,7 @@ "BLTG": "Block-Logic", "BLTV": "BLTV Token", "BLU": "BlueCoin", + "BLUAI": "Bluwhale AI", "BLUB": "BLUB", "BLUE": "Bluefin", "BLUEBASE": "Blue", @@ -2106,6 +2146,7 @@ "BLUESPARROW": "BlueSparrow Token", "BLUESPARROWOLD": "BlueSparrowToken", "BLUEW": "Blue Whale", + "BLUEY": "BlueyonBase", "BLUFF": "BluffCat", "BLUI": "Blui", "BLUM": "Blum", @@ -2171,6 +2212,7 @@ "BNBFLOKI": "BNB FLOKI", "BNBFROG": "BNBFROG", "BNBH": "BnbHeroes Token", + "BNBHOLDER": "币安Holder", "BNBLION": "BNB LION", "BNBOLYMPIC": "BNB OLYMPIC", "BNBP": "BNBPot", @@ -2192,6 +2234,7 @@ "BNK": "Bankera", "BNKR": "BankrCoin", "BNKV1": "Bankera v1", + "BNL": "BitNational Token", "BNN": "Banyan Network", "BNOM": "BitNomad", "BNP": "BenePit", @@ -2388,6 +2431,7 @@ "BOU": "Boulle", "BOUNCE": "Bounce Token", "BOUNTY": "ChainBounty", + "BOUNTYK": "BOUNTYKINDS", "BOUTS": "BoutsPro", "BOW": "Archer Swap", "BOWE": "Book of Whales", @@ -2594,11 +2638,13 @@ "BST": "Blocksquare Token", "BSTAR": "Blackstar", "BSTC": "BST Chain", + "BSTER": "Bster", "BSTK": "BattleStake", "BSTN": "BitStation", "BSTR": "BSTR", "BSTS": "Magic Beasties", "BSTY": "GlobalBoost", + "BSU": "Baby Shark Universe Token", "BSV": "Bitcoin SV", "BSVBRC": "BSVBRC", "BSW": "Biswap", @@ -2670,6 +2716,7 @@ "BTDX": "Bitcloud 2.0", "BTE": "Betero", "BTECOIN": "BTEcoin", + "BTELEGRAM": "BetterTelegram Token", "BTEV1": "Betero v1", "BTEX": "BTEX", "BTF": "Blockchain Traded Fund", @@ -2772,6 +2819,7 @@ "BULLBEAR": "BullBear AI", "BULLC": "BuySell", "BULLF": "BULL FINANCE", + "BULLGOD": "Bull God", "BULLI": "Bullish On Ethereum", "BULLIEVERSE": "Bullieverse", "BULLINU": "Bull inu", @@ -2820,6 +2868,7 @@ "BUTT": "Buttercat", "BUTTCOIN": "The Next Bitcoin", "BUTTHOLE": "Butthole Coin", + "BUTTPLUG": "fartcoin killer", "BUX": "BUX", "BUXCOIN": "Buxcoin", "BUY": "Burency", @@ -2860,6 +2909,7 @@ "BXT": "BitTokens", "BXTB": "BXTB Foundation", "BXX": "Baanx", + "BXXV1": "Baanx v1", "BXY": "Beaxy", "BYAT": "Byat", "BYB": "BiorBank", @@ -2902,6 +2952,7 @@ "CACHE": "Cache", "CACHEGOLD": "CACHE Gold", "CACTUS": "CACTUS", + "CACXT": "Convertible ACXT", "CADAI": "CADAI", "CADC": "CAD Coin", "CADINU": "Canadian Inuit Dog", @@ -2930,6 +2981,7 @@ "CALCI": "Calcium", "CALI": "CaliCoin", "CALL": "Global Crypto Alliance", + "CALLISTO": "Callisto Network", "CALLS": "OnlyCalls by Virtuals", "CALO": "Calo", "CAM": "Consumption Avatar Matrix", @@ -2951,6 +3003,7 @@ "CANTI": "Cantina Royale", "CANTO": "CANTO", "CANYA": "CanYaCoin", + "CAOCAO": "CaoCao", "CAP": "Capverto", "CAPA": "Cake Panda", "CAPD": "Capdax", @@ -3003,6 +3056,7 @@ "CASIO": "CasinoXMetaverse", "CASPER": "Casper DeFi", "CASPERTOKEN": "Casper Token", + "CASPUR": "Caspur Zoomies", "CAST": "Castello Coin", "CASTLE": "bitCastle", "CAT": "Simon's Cat", @@ -3110,6 +3164,7 @@ "CBUCKS": "CRYPTOBUCKS", "CBUK": "CurveBlock", "CBX": "CropBytes", + "CBXRP": "Coinbase Wrapped XRP", "CBY": "Carbify", "CC": "CloudChat", "CC10": "Cryptocurrency Top 10 Tokens Index", @@ -3144,12 +3199,12 @@ "CCX": "Conceal", "CCXC": "CoolinDarkCoin", "CCXX": "CounosX", + "CDAG": "CannDollar", "CDAI": "Compound Dai", "CDBIO": "CDbio", "CDCETH": "Crypto.com Staked ETH", "CDCSOL": "Crypto.com Staked SOL", "CDEX": "Cryptodex", - "CDL": "CoinDeal Token", "CDN": "Canada eCoin", "CDOG": "Corn Dog", "CDOGE": "cyberdoge", @@ -3220,6 +3275,7 @@ "CGG": "Chain Guardians", "CGL": "Crypto Gladiator Shards", "CGLD": "Celo Gold", + "CGN": "CYGNUS", "CGO": "Comtech Gold", "CGPT": "ChainGPT", "CGPU": "ChainGPU", @@ -3239,6 +3295,7 @@ "CHAI": "Chroma AI", "CHAIN": "Chain Games", "CHAINCADE": "ChainCade", + "CHAINSOFWAR": "Chains of War", "CHAL": "Chalice Finance", "CHAM": "Champion", "CHAMP": "NFT Champions", @@ -3253,6 +3310,7 @@ "CHAPZ": "Chappyz", "CHARGED": "GoCharge Tech", "CHARIZARD": "Charizard Inu", + "CHARLIE": "Charlie Kirk", "CHARM": "Charm Coin", "CHARS": "CHARS", "CHART": "BetOnChart", @@ -3428,7 +3486,8 @@ "CLANKER": "tokenbot", "CLAP": "Clap Cat", "CLAS": "Classic USDC", - "CLASH": "Clashub", + "CLASH": "GeorgePlaysClashRoyale", + "CLASHUB": "Clashub", "CLASS": "Class Coin", "CLAY": "Clayton", "CLAYN": "Clay Nation", @@ -3465,7 +3524,7 @@ "CLND": "COLEND", "CLNX": "Coloniume Network", "CLNY": "Colony", - "CLO": "Callisto Network", + "CLO": "Yei Finance", "CLOA": "Cloak", "CLOAK": "CloakCoin", "CLOKI": "CATLOKI", @@ -3552,7 +3611,8 @@ "CNYX": "eToro Chinese Yuan", "CO": "Corite", "CO2": "CO2 Token", - "COAI": "CodeMong Ai", + "COA": "Alliance Games", + "COAI": "ChainOpera AI", "COAL": "BitCoal", "COB": "Cobinhood", "COBE": "Castle of Blackwater", @@ -3571,6 +3631,7 @@ "CODAI": "CODAI", "CODE": "Code Token", "CODEG": "CodeGenie", + "CODEMONG": "CodeMong Ai", "CODEO": "Codeo Token", "CODEXTOKEN": "CodexToken", "CODI": "Codi Finance", @@ -3592,7 +3653,9 @@ "COINB": "Coinbidex", "COINBT": "CoinBot", "COINBUCK": "Coinbuck", + "COINDEALTOKEN": "CoinDeal Token", "COINDEFI": "Coin", + "COINDEPO": "CoinDepo Token", "COING": "Coingrid", "COINH": "Coinhound", "COINLION": "CoinLion", @@ -3632,6 +3695,7 @@ "COMEW": "Coin In Meme World", "COMFI": "CompliFi", "COMM": "Community Coin", + "COMMON": "COMMON", "COMMS": "CallofMeme", "COMMUNITYCOIN": "Community Coin", "COMP": "Compound", @@ -3690,6 +3754,7 @@ "CORGIAI": "CorgiAI", "CORGIB": "The Corgi of PolkaBridge", "CORION": "Corion", + "CORL": "Coral Finance", "CORN": "Corn", "CORNELLA": "CORNELLA", "CORNFIELDFARM": "CORN", @@ -3721,7 +3786,7 @@ "COVA": "COVA", "COVAL": "Circuits of Value", "COVER": "Cover Protocol", - "COVEROLD": " Cover Protocol (old)", + "COVERV1": "Cover Protocol (old)", "COVEX": "CoVEX", "COVIDTOKEN": "Covid Token", "COVIR": "COVIR", @@ -3814,16 +3879,18 @@ "CREAM": "Cream", "CREAML": "Creamlands", "CREATIVE": "Creative Token", - "CRED": "Verify", + "CRED": "Credia Layer", "CREDI": "Credefi", "CREDIT": "Credit", "CREDITS": "Credits", "CREDO": "Credo", "CREED": "Thecreed", "CREMAT": "Cremation Coin", + "CREMEPUFF": "Creme Puff", "CREO": "Creo Engine", "CREP": "Compound Augur", - "CREPE": "Crepe Coin", + "CREPE": "CREPE", + "CREPECOIN": "Crepe Coin", "CRES": "Cresio", "CRESV1": "Cresio v1", "CREV": "CryptoRevolution", @@ -3873,6 +3940,7 @@ "CRP": "Crypton", "CRPS": "CryptoPennies", "CRPT": "Crypterium", + "CRPTC": "CRPT Classic", "CRS": "CYRUS", "CRSP": "CryptoSpots", "CRT": "Carr.Finance", @@ -3929,6 +3997,7 @@ "CRYPTOSDG": "Crypto SDG", "CRYPTOT": "Crypto Trump", "CRYPTOTANKS": "CryptoTanks", + "CRYPTOTR": "Crypto Trump", "CRYPTOU": "CryptoUnity", "CRYSTAL": "Crystal", "CRYSTALCLEAR": "Crystal Clear Token", @@ -4080,6 +4149,7 @@ "CWIF": "catwifhat", "CWIS": "Crypto Wisdom Coin", "CWN": "CryptoWorldNews", + "CWOIN": "cwoin", "CWR": "Cowrium", "CWS": "Crowns", "CWT": "CrossWallet", @@ -4127,6 +4197,7 @@ "CYP": "CypherPunkCoin", "CYPEPE": "CyPepe", "CYPHER": "CYPHER•GENESIS (Runes)", + "CYPR": "Cypher", "CYRS": "Cyrus Token", "CYRUS": "Cyrus Exchange", "CYS": "BlooCYS", @@ -4192,7 +4263,6 @@ "DAL": "DAOLaunch", "DALI": "Dalichain", "DALMA": "Dalma Inu", - "DAM": "Datamine", "DAMEX": "DAMEX", "DAMN": "Sol Killer", "DAMO": "Coinzen", @@ -4212,6 +4282,7 @@ "DAOLITY": "Daolity", "DAOP": "Dao Space", "DAOSOL": "MonkeDAO", + "DAOSQUARE": "DAOSquare Governance Token", "DAOVC": "DAO.VC", "DAOX": "Daox", "DAPP": "Pencils Protocol", @@ -4250,7 +4321,9 @@ "DAT": "Datum", "DATA": "Streamr", "DATAB": "Databot", + "DATAEC": "DATA Economy Index", "DATAMALL": "Datamall Coin", + "DATAMINE": "Datamine", "DATAO": "Data Ownership Protocol", "DATAWALLET": "DataWallet", "DATBOI": "Dat Boi", @@ -4347,6 +4420,7 @@ "DDRST": "DigiDinar StableToken", "DDRT": "DigiDinar Token", "DDS": "DDS.Store", + "DDUSDV1": "Decentralized USD", "DDX": "DerivaDAO", "DEA": "Degas Coin", "DEAI": "Zero1 Lab", @@ -4379,6 +4453,7 @@ "DEEPSEEK": "Global DePIN Chain", "DEEPSEEKAI": "DeepSeek AI Agent", "DEEPSEEKR1": "DeepSeek R1", + "DEEPSPACE": "DeepSpace", "DEER": "ToxicDeer Finance", "DEERSEIZED": "Deer Seized by US Government", "DEESSE": "Deesse", @@ -4475,6 +4550,7 @@ "DEVT": "DeHorizon", "DEVVE": "Devve", "DEVX": "Developeo", + "DEW": "DEW", "DEX": "DEX", "DEX223": "DEX223", "DEXA": "DEXA COIN", @@ -4531,6 +4607,7 @@ "DGLD": "Digital Gold", "DGLN": "Dogelana", "DGM": "DigiMoney", + "DGMA": "daGama", "DGME": "GameStop Tokenized Stock Defichain", "DGMS": "Digigems", "DGMT": "DigiMax DGMT", @@ -4629,6 +4706,7 @@ "DIPA": "Doge Ipa", "DIRTY": "Dirty Street Cats", "DIS": "DisChain", + "DISCO": "Disco By Matt Furie", "DISCOVERY": "DiscoveryIoT", "DISK": "Dark Lisk", "DISPEPE": "Disabled Pepe", @@ -4658,6 +4736,7 @@ "DKS": "DarkShield", "DKT": "Duelist King", "DKUMA": "KumaDex Token", + "DL": "Dill", "DLA": "Dolla", "DLANCE": "DeeLance", "DLB": "DiemLibre", @@ -4867,6 +4946,7 @@ "DONJR": "Don Jr.", "DONK": "Don-key", "DONKE": "DONKE", + "DONKEY": "donkey", "DONNIEFIN": "Donnie Finance", "DONS": "The Dons", "DONT": "Donald Trump (dont.cash)", @@ -4887,9 +4967,10 @@ "DOPEX": "DOPE", "DOPU": "DOPU The Dog with A Purpose", "DOR": "Dorado", - "DORA": "Dora Factory", + "DORA": "DORA", "DORAEMON": "Doraemon", "DORAV1": "Dora Factory v1", + "DORAV2": "Dora Factory", "DORK": "DORK", "DORKL": "DORK LORD", "DORKVADER": "DorkVader", @@ -5038,6 +5119,7 @@ "DTRC": "Datarius", "DTRUMP": "Degen Trump", "DTSLA": "Tesla Tokenized Stock Defichain", + "DTV": "DraperTV", "DTX": "DataBroker DAO", "DUA": "Brillion", "DUAL": "Dual Finance", @@ -5050,14 +5132,14 @@ "DUC": "DucatusCoin", "DUCAT": "Ducat", "DUCATO": "Ducato Protocol Token", - "DUCK": "Unit Protocol New", + "DUCK": "DuckChain Token", "DUCKAI": "Duck AI", "DUCKC": "DuckCoin", "DUCKD": "DuckDuckCoin", "DUCKER": "Ducker", "DUCKIES": "Yellow Duckies", "DUCKO": "Duck Off Coin", - "DUCKV1": "COL", + "DUCKV1": "UNITPROV1", "DUCKY": "Ducky Duck", "DUCX": "DucatusX", "DUDE": "DuDe", @@ -5082,9 +5164,10 @@ "DUREV": "Povel Durev", "DUROV": "FREE DUROV", "DURTH": "iShares MSCI World ETF Tokenized Stock Defichain", - "DUSD": "Decentralized USD", + "DUSD": "StandX DUSD", "DUSK": "Dusk Network", - "DUST": "DUST Protocol", + "DUST": "Dust", + "DUSTPROTOCOL": "DUST Protocol", "DUSTY": "Dusty", "DUX": "DuxCoin", "DUZCE": "Duzce Token", @@ -5140,6 +5223,7 @@ "DYNA": "Dynamix", "DYNAM": "Dynamic Crypto Index", "DYNAMICTRADING": "Dynamic Trading Rights", + "DYNASTYGLOB": "Dynasty Global Investments AG", "DYNCOIN": "Dyncoin", "DYNEX": "Dynex GPU", "DYNMT": "Dynamite", @@ -5180,6 +5264,7 @@ "EARNM": "EARNM", "EARTH": "Earth Token", "EARTHCOIN": "EarthCoin", + "EASY": "EASY", "EASYF": "EasyFeedback", "EASYMINE": "EasyMine", "EAT": "EDGE Activity Token", @@ -5250,7 +5335,9 @@ "EDDIE": "Eddie coin", "EDE": "El Dorado Exchange", "EDEL": "Coin Edelweis", - "EDEN": "EDEN", + "EDEN": "Eden Token", + "EDENA": "EDENA", + "EDENNETWORK": "EDEN", "EDEXA": "edeXa Security Token", "EDFI": "EdFi", "EDG": "Edgeless", @@ -5266,6 +5353,7 @@ "EDNS": "EDNS Token", "EDOG": "EDOG", "EDOGE": "ElonDoge", + "EDOM": "EDOM", "EDR": "Endor Protocol Token", "EDRC": "EDRCoin", "EDSE": "Eddie Seal", @@ -5317,6 +5405,7 @@ "EGOCOIN": "EGOcoin", "EGOD": "EgodCoin", "EGOLD": "EGOLD", + "EGOLDGG": "eGold", "EGON": "EgonCoin", "EGR": "Egoras Rights", "EGRN": "Energreen", @@ -5453,6 +5542,7 @@ "EMP": "Emp Money", "EMPC": "EmporiumCoin", "EMPH": "Emphy", + "EMPI": "Emperor", "EMPIRE": "Empire Token", "EMPR": "empowr", "EMR": "Emorya Finance", @@ -5473,11 +5563,13 @@ "ENCX": "Encrybit", "ENDCEX": "Endpoint CeX Fan Token", "ENDLESS": "Endless Board Game", + "ENDOR": "Endor Protocol Token", "ENE": "EneCoin", "ENEAR": "Near (Energiswap)", "ENEDEX": "Enedex", "ENERGYLEDGER": "Energy Ledger", "ENERGYX": "Safe Energy", + "ENF": "enfineo", "ENG": "Enigma", "ENGT": "Engagement Token", "ENIGMA": "ENIGMA", @@ -5493,6 +5585,7 @@ "ENRON": "Enron", "ENRX": "Enrex", "ENS": "Ethereum Name Service", + "ENSO": "Enso", "ENT": "Eternity", "ENTC": "EnterButton", "ENTER": "EnterCoin", @@ -5616,6 +5709,7 @@ "ET": "ENDO", "ET4": "Eticket4", "ETALON": "Etalon", + "ETAN": "Etarn", "ETBS": "EthBits", "ETBT": "Ethereum Black", "ETC": "Ethereum Classic", @@ -5708,6 +5802,7 @@ "EURE": "Monerium EUR emoney", "EUREV1": "Monerium EUR emoney v1", "EURI": "Eurite", + "EURL": "LUGH", "EURN": "NOKU EUR", "EURO3": "EURO3", "EUROB": "Etherfuse EUROB", @@ -5719,14 +5814,17 @@ "EURR": "StablR Euro", "EURRV1": "StablR Euro v1", "EURS": "STASIS EURS", + "EURST": "EURO Stable Token", "EURT": "Euro Tether", "EURTV1": "Euro Tether v1", "EURU": "Upper Euro", "EURX": "eToro Euro", "EUSD": "Egoras Dollar", + "EUT": "EarnUp Token", "EUTBL": "Spiko EU T-Bills Money Market Fund", "EV": "EVAI", "EVA": "Evadore", + "EVAA": "EVAA Protocol", "EVAI": "EVA Intelligence", "EVAL": "Chromia's EVAL by Virtuals", "EVAN": "Evanesco Network", @@ -5848,6 +5946,7 @@ "FACTORY": "ChainFactory", "FACTR": "Defactor", "FACTRPAY": "FactR", + "FACY": "ArAIstotle Fact Checker", "FADO": "FADO Go", "FAFO": "FAFO", "FAFOSOL": "Fafo", @@ -5877,6 +5976,7 @@ "FANG": "FANG Token", "FANS": "Fantasy Cash", "FANT": "Phantasia", + "FANTC": "FANtium Tennis Coin", "FANTOM": "Fantom Maker", "FANV": "FanVerse", "FANX": "FrontFanz", @@ -5982,11 +6082,12 @@ "FET": "Artificial Superintelligence Alliance", "FETCH": "Fetch", "FETS": "FE TECH", + "FETV1": "Fetch v1", "FEUSD": "Felix feUSD", "FEVR": "RealFevr", "FEX": "FEX Token", "FEY": "Feyorra", - "FF": "Forefront", + "FF": "Falcon Finance", "FF1": "Two Prime FF1 Token", "FFA": "Cryptofifa", "FFC": "FireflyCoin", @@ -5999,6 +6100,7 @@ "FGC": "FantasyGold", "FGD": "Freedom God DAO", "FGM": "Feels Good Man", + "FGPT": "FurGPT", "FGT": "Flozo Game Token", "FGZ": "Free Game Zone", "FHB": "FHB", @@ -6006,6 +6108,7 @@ "FHM": "FantOHM", "FI": "Fideum", "FIA": "FIA Protocol", + "FIATDAO": "FIAT DAO Token", "FIBO": "FibSWAP DEx", "FIBOS": "FIBOS", "FIBRE": "FIBRE", @@ -6126,6 +6229,7 @@ "FLIP": "Chainflip", "FLIX": "OmniFlix Network", "FLIXX": "Flixxo", + "FLK": "Fleek", "FLL": "Feellike", "FLLW": "Follow Coin", "FLM": "Flamingo", @@ -6202,6 +6306,7 @@ "FMC": "Fimarkcoin", "FME": "FME", "FMEX": "FMex", + "FMF": "Formosa Financial Token", "FMG": "FM Gallery", "FML": "FormulA", "FMT": "Finminity", @@ -6263,6 +6368,7 @@ "FORCE": "TriForce Tokens", "FORCEC": "Force Coin", "FORE": "FORE Protocol", + "FOREFRONT": "Forefront", "FOREST": "FOREST", "FORESTPLUS": "The Forbidden Forest", "FOREVER": "Forever Coin", @@ -6320,6 +6426,7 @@ "FRANK": "Frank", "FRANKLIN": "Franklin", "FRATT": "Frogg and Ratt", + "FRAX": "Frax Share", "FRAXLEGACY": "Frax", "FRAZ": "FrazCoin", "FRBK": " FreeBnk", @@ -6346,6 +6453,7 @@ "FREN": "FREN", "FRENC": "Frencoin", "FRENCH": "French On Base", + "FRENLY": "Frenly", "FRENPET": "Fren Pet", "FRENS": "Farmer Friends", "FRESCO": "Fresco", @@ -6498,6 +6606,7 @@ "FVT": "Finance Vote", "FWATCH": "Foliowatch", "FWB": "Friends With Benefits Pro", + "FWBV1": "Friends With Benefits Pro v1", "FWC": "Qatar 2022", "FWH": "FigureWifHat", "FWOG": "Fwog", @@ -6513,7 +6622,6 @@ "FXI": "FX1 Sports", "FXN": "FXN", "FXP": "FXPay", - "FXS": "Frax Share", "FXST": "FX Stock Token", "FXT": "Frog X Toad 6900", "FXUSD": "f(x) Protocol fxUSD", @@ -6541,7 +6649,8 @@ "GAIA": "Gaia Token", "GAIAE": "Gaia Everworld", "GAIAPLATFORM": "GAIA Platform", - "GAIN": "Gainfy", + "GAIN": "GriffinAI", + "GAINFY": "Gainfy", "GAINS": "Gains", "GAINSV1": "Gains v1", "GAJ": "Gaj Finance", @@ -6636,6 +6745,7 @@ "GBIT": "GravityBit", "GBK": "Goldblock", "GBL": "Global Token", + "GBNB": "GOLD BNB", "GBO": "Gabro.io", "GBOT": "GBOT", "GBOY": "GameBoy", @@ -6710,6 +6820,9 @@ "GENI": "Genius", "GENIE": "The Genie", "GENIEC": "GenieCoin", + "GENIESWAP": "GenieSwap", + "GENIESWAPV1": "GenieSwap v1", + "GENIFYART": "Genify ART", "GENIX": "Genix", "GENO": "GenomeFi", "GENOME": "GenomesDao", @@ -6793,7 +6906,7 @@ "GHNY": "Grizzly Honey", "GHO": "GHO", "GHOAD": "GhoadCoin", - "GHOST": "GhostbyMcAfee", + "GHOSTBY": "GhostbyMcAfee", "GHOSTCOIN": "GhostCoin", "GHOSTM": "GhostMarket", "GHOUL": "Ghoul Coin", @@ -6816,7 +6929,8 @@ "GIGACHAD": "GigaChad", "GIGAG": "GIGAGEEK", "GIGASWAP": "GigaSwap", - "GIGGLE": "Giggle Academy", + "GIGGLE": "Giggle Fund", + "GIGGLEACADEMY": "Giggle Academy", "GIGS": "Climate101", "GIGX": "GigXCoin", "GIKO": "Giko Cat", @@ -6958,6 +7072,7 @@ "GOAT": "Goatseus Maximus", "GOATAI": "GOAT AI", "GOATCOIN": "Goat", + "GOATED": "Goat Network", "GOATS": "GOATS", "GOATSE": "GOATSE", "GOB": "gob", @@ -6980,6 +7095,7 @@ "GOFX": "GooseFX", "GOG": "Guild of Guardians", "GOGLZ": "GOGGLES", + "GOGLZV1": "GOGGLES v1", "GOGO": "GOGO Finance", "GOGU": "GOGU Coin", "GOHOME": "GOHOME", @@ -6996,7 +7112,6 @@ "GOLDEN": "Golden Inu", "GOLDENC": "GoldenCat", "GOLDENG": "Golden Goose", - "GOLDENPACT": "GOLDEN PACT", "GOLDEX": "Goldex", "GOLDF": "Gold Fever", "GOLDMIN": "GoldMiner", @@ -7052,7 +7167,7 @@ "GOS": "Gosama", "GOSS": "GOSSIP-Coin", "GOST": "SoulCoin", - "GOT": "ParkinGo", + "GOT": "GOLDEN PACT", "GOTEM": "gotEM", "GOTG": "Got Guaranteed", "GOTTI": "Gotti Token", @@ -7137,6 +7252,7 @@ "GRIMEX": "SpaceGrime", "GRIN": "Grin", "GRIND": "Self Improving", + "GRIPPY": "GRIPPY", "GRL": "Greelance", "GRLC": "Garlicoin", "GRM": "GridMaster", @@ -7276,6 +7392,7 @@ "GVC": "Global Virtual Coin", "GVE": "Globalvillage Ecosystem", "GVL": "Greever", + "GVNR": "GVNR", "GVR": "Grove [OLD]", "GVRV1": "Grove v1", "GVT": "Genesis Vision", @@ -7346,8 +7463,8 @@ "HAMSTERB": "HamsterBase", "HAMSTR": "Hamster Coin", "HAN": "HanChain", - "HANA": "Hana", "HANACOIN": "Hanacoin", + "HANAETH": "Hana", "HANAETHCTO": "HANA", "HAND": "ShowHand", "HANDY": "Handy", @@ -7364,6 +7481,7 @@ "HARD": "Kava Lend", "HARE": "Hare Token", "HAREPLUS": "Hare Plus", + "HARIKO": "Inu Hariko", "HAROLD": "Harold", "HAROLDDUCK": "Harold", "HARPER": "Harper", @@ -7826,6 +7944,7 @@ "HYDRO": "Hydro", "HYDROMINER": "Hydrominer", "HYDROP": "Hydro Protocol", + "HYDX": "Hydrex", "HYGH": "HYGH", "HYN": "Hyperion", "HYP": "HyperX", @@ -7838,6 +7957,7 @@ "HYPERD": "HyperDAO", "HYPERFLY": "HyperFly", "HYPERIONX": "HyperionX", + "HYPERLEND": "HyperLend", "HYPERS": "HyperSpace", "HYPERSKIDS": "HYPERSKIDS", "HYPERSTAKE": "HyperStake", @@ -7851,6 +7971,7 @@ "HZ": "Horizon", "HZD": "HorizonDollar", "HZM": "HZM Coin", + "HZMV1": "HZM Coin v1", "HZN": "Horizon Protocol", "HZT": "HazMatCoin", "I0C": "I0coin", @@ -8025,13 +8146,14 @@ "INA": "pepeinatux", "INARI": "Inari", "INB": "Insight Chain", - "INC": "Incrementum", + "INC": "WAT Income token", "INCAKE": "InfinityCAKE", "INCEPT": "Incept", "INCNT": "Incent", "INCO": "InfinitiCoin", "INCORGNITO": "Incorgnito", "INCP": "InceptionCoin", + "INCREMENTUM": "Incrementum", "IND": "Indorse", "INDAY": "Independence Day", "INDEPENDENCEDAY": "Independence Day", @@ -8099,7 +8221,7 @@ "INTE": "InteractWith", "INTELLIQUE": "KARASOU", "INTER": "Inter Milan Fan Token", - "INTERN": "Interns", + "INTERN": "intern", "INTL": "Intelly", "INTO": "Influ Token", "INTR": "Interlay", @@ -8150,6 +8272,7 @@ "IP": "Story", "IP3": "Cripco", "IPAD": "Infinity Pad", + "IPAX": "Icopax", "IPC": "IPChain", "IPDN": "IPDnetwork", "IPL": "VouchForMe", @@ -8182,6 +8305,7 @@ "IRONBSC": "Iron BSC", "IRONCOIN": "IRONCOIN", "IRT": "Infinity Rocket", + "IRWA": "IncomRWA", "IRYDE": "iRYDE COIN", "ISA": "Islander", "ISDT": "ISTARDUST", @@ -8271,6 +8395,7 @@ "JADE": "Jade Protocol", "JADEC": "Jade Currency", "JAE": "JaeCoin", + "JAGER": "Jager Hunter", "JAGO": "Jagotrack", "JAI": "Japanese Akita Inu", "JAIHO": "Jaiho Crypto", @@ -8386,6 +8511,7 @@ "JNX": "Janex", "JNY": "JNY", "JOB": "Jobchain", + "JOBIESS": "JobIess", "JOBS": "JobsCoin", "JOBSEEK": "JobSeek AI", "JOC": "Speed Star JOC", @@ -8558,6 +8684,7 @@ "KASPY": "KASPY", "KASSIAHOME": "Kassia Home", "KASTA": "Kasta", + "KASTER": "King Aster", "KAT": "Karat", "KATA": "Katana Inu", "KATANA": "Katana Finance", @@ -8656,6 +8783,7 @@ "KFX": "KnoxFS", "KGB": "KGB protocol", "KGC": "Krypton Galaxy Coin", + "KGEN": "KGeN", "KGO": "Kiwigo", "KGT": "Kaby Gaming Token", "KHAI": "khai", @@ -8756,6 +8884,8 @@ "KLEVA": "KLEVA Protocol", "KLICKZIE": "Klickzie", "KLIMA": "KlimaDAO", + "KLINK": "Klink Finance", + "KLIP": "KLIP AI", "KLK": "Klickl Token", "KLKS": "Kalkulus", "KLKSYNC": "KLK Sync Protocol", @@ -8797,6 +8927,7 @@ "KNTO": "Kento", "KNU": "Keanu", "KNUT": "Knut From Zoo", + "KNUXX": "Knuxx Bully of ETH", "KNW": "Knowledge", "KOAI": "KOI", "KOALA": "KOALA", @@ -8974,9 +9105,10 @@ "L3USD": "L3USD", "L7": "L7", "LA": "Lagrange", - "LAB": "Labrys", + "LAB": "LAB", "LABORCRYPTO": "LaborCrypto", "LABRA": "LabraCoin", + "LABRYS": "Labrys", "LABS": "LABS Group", "LABUBU": "Labubu", "LABX": "Stakinglab", @@ -9146,6 +9278,7 @@ "LET": "LinkEye", "LETIT": "Letit", "LETS": "Let's WIN This", + "LETSBONK": "Let's BONK", "LETSGO": "Lets Go Brandon", "LEU": "CryptoLEU", "LEV": "Levante U.D. Fan Token", @@ -9215,8 +9348,9 @@ "LIFETOKEN": "LIFE", "LIFT": "Uplift", "LIGER": "Ligercoin", - "LIGHT": "Light", + "LIGHT": "LIGHT", "LIGHTCHAIN": "LightChain", + "LIGHTHEAVEN": "Light", "LIGHTSPEED": "LightSpeedCoin", "LIGMA": "Ligma Node", "LIGO": "Ligo", @@ -9280,6 +9414,7 @@ "LITION": "Lition", "LITT": "LitLab Games", "LITTLEGUY": "just a little guy", + "LITTLEMANYU": "Little Manyu", "LIV": "LiviaCoin", "LIVE": "TRONbetLive", "LIVENCOIN": "LivenPay", @@ -9320,6 +9455,7 @@ "LMR": "Lumerin", "LMT": "LIMITUS", "LMTOKEN": "LM Token", + "LMTS": "Limitless Official Token", "LMWR": "LimeWire Token", "LMXC": "LimonX", "LMY": "Lunch Money", @@ -9384,7 +9520,7 @@ "LONGM": "Long Mao", "LONGSHINE": "LongShine", "LOOBY": "Looby by Stephen Bliss", - "LOOK": "LookCoin", + "LOOK": "LOOK", "LOOKS": "LooksRare", "LOOM": "Loom Network", "LOOMV1": "Loom Network v1", @@ -9551,6 +9687,7 @@ "LUNG": "LunaGens", "LUNR": "Lunr Token", "LUPIN": "LUPIN", + "LUR": "Lumera", "LUS": "Luna Rush", "LUSD": "Liquity USD", "LUSH": "Lush AI", @@ -9590,7 +9727,8 @@ "LYL": "LoyalCoin", "LYM": "Lympo", "LYMPO": "Lympo Market Token", - "LYN": "LYNCHPIN Token", + "LYN": "Everlyn Token", + "LYNCHPIN": "LYNCHPIN Token", "LYNK": "Lynked.World", "LYNX": "Lynex", "LYNXCOIN": "Lynx", @@ -9609,6 +9747,7 @@ "LZM": "LoungeM", "LZUSDC": "LayerZero Bridged USDC (Fantom)", "M": "MemeCore", + "M0": "M by M^0", "M1": "SupplyShock", "M2O": "M2O Token", "M3M3": "M3M3", @@ -9672,6 +9811,7 @@ "MAI": "MAI", "MAIA": "Maia", "MAID": "MaidSafe Coin", + "MAIGA": "MAIGA Token", "MAIL": "CHAINMAIL", "MAINSTON": "Ston", "MAIV": "MAIV", @@ -9713,7 +9853,6 @@ "MANTI": "Mantis", "MANTLE": "Mantle", "MANUSAI": "Manus AI Agent", - "MANYU": "Little Manyu", "MANYUDOG": "MANYU", "MAO": "Mao", "MAOW": "MAOW", @@ -9891,6 +10030,7 @@ "MCONTENT": "MContent", "MCP": "My Crypto Play", "MCPC": "Mobile Crypto Pay Coin", + "MCQ": "Mecha Conquest", "MCRC": "MyCreditChain", "MCRN": "MacronCoin", "MCRT": "MagicCraft", @@ -10055,6 +10195,7 @@ "METADOGEV1": "MetaDoge V1", "METADOGEV2": "MetaDoge V2", "METAF": "MetaFastest", + "METAFIGHTER": "MetaFighter", "METAG": "MetagamZ", "METAGEAR": "MetaGear", "METAIVERSE": "MetAIverse", @@ -10072,6 +10213,7 @@ "METATR": "MetaTrace Utility Token", "METAUFO": "MetaUFO", "METAV": "METAVERSE", + "METAV1": "META v1", "METAVE": "Metaverse Convergence", "METAVERSEM": "MetaVerse-M", "METAVERSEX": "MetaverseX", @@ -10088,6 +10230,7 @@ "METO": "Metafluence", "METRO": "Metropoly", "METV1": "Metronome", + "METYA": "Metya Token", "MEU": "MetaUnit", "MEV": "MEVerse", "MEVETH": "mevETH", @@ -10100,8 +10243,9 @@ "MEX": "MEX", "MEXC": "MEXC Token", "MEXP": "MOJI Experience Points", + "MEY": "Mey Network", "MEZZ": "MEZZ Token", - "MF": "MetaFighter", + "MF": "Moonwalk Fitness", "MF1": "Meta Finance", "MFAM": "Moonwell Apollo", "MFC": "MFCoin", @@ -10130,7 +10274,7 @@ "MGLC": "MetaverseMGL", "MGLD": "Metallurgy", "MGN": "MagnaCoin", - "MGO": "MobileGo", + "MGO": "Mango Network", "MGOD": "MetaGods", "MGP": "MangoChain", "MGPT": "MotoGP Fan Token", @@ -10254,7 +10398,7 @@ "MIODIO": "MIODIOCOIN", "MIOTA": "IOTA", "MIR": "Mirror Protocol", - "MIRA": "Chains of War", + "MIRA": "Mira", "MIRACLE": "MIRACLE", "MIRACLETELE": "Miracle Tele", "MIRAI": "Project MIRAI", @@ -10328,6 +10472,7 @@ "MMAPS": "MapMetrics", "MMATIC": "Wrapped Polygon (Multichain)", "MMC": "Monopoly Millionaire Control", + "MMDAO": "MMDAO", "MMETA": "Duckie Land Multi Metaverse", "MMF": "MMFinance", "MMG": "Monopoly Millionaire Game", @@ -10397,6 +10542,7 @@ "MOBIC": "Mobility Coin", "MOBIE": "MobieCoin", "MOBILE": "Helium Mobile", + "MOBILEGO": "MobileGo", "MOBIU": "Mobius Money", "MOBU": "MOBU", "MOBX": "MOBIX", @@ -10461,6 +10607,7 @@ "MOMO2025": "momo", "MON": "MON Protocol", "MONA": "MonaCoin", + "MONAI": "MONAI", "MONAIZE": "Monaize", "MONARCH": "TRUEMONARCH", "MONART": "Monart", @@ -10620,12 +10767,14 @@ "MRBOB": "MR BOB COIN", "MRCH": "MerchDAO", "MRCR": "Mercor Finance", + "MRDN": "Meridian", "MRF": "Moonradar.finance", "MRFOX": "Mr.FOX Token", "MRHB": "MarhabaDeFi", "MRI": "Marshall Inu", "MRK": "MARK.SPACE", "MRKX": "Merck xStock", + "MRLN": "Merlin Token", "MRM": "Mr Mint", "MRN": "Mercoin", "MRNA": "Moderna", @@ -10666,6 +10815,7 @@ "MSQ": "MSquare Global", "MSR": "Masari", "MST": "Idle Mystic", + "MSTABLEUSD": "mStable USD", "MSTAR": "MerlinStarter", "MSTETH": "Eigenpie mstETH", "MSTO": "Millennium Sapphire", @@ -10753,7 +10903,7 @@ "MURA": "Murasaki", "MURATIAI": "MuratiAI", "MUSCAT": "MusCat", - "MUSD": "mStable USD", + "MUSD": "MetaMask USD", "MUSDC": "USD Coin (Multichain)", "MUSDCOIN": "MUSDcoin", "MUSE": "Muse DAO", @@ -10797,6 +10947,7 @@ "MWD": "MEW WOOF DAO", "MWETH": "Moonwell Flagship ETH (Morpho Vault)", "MWH": "Melania Wif Hat", + "MWXT": "MWX Token", "MX": "MX Token", "MXC": "Machine Xchange Coin", "MXD": "Denarius", @@ -10895,6 +11046,7 @@ "NATI": "IlluminatiCoin", "NATION": "Nation3", "NATIX": "NATIX Network", + "NATO": "The Nation Token", "NATOR": "Pepenator", "NAUSICAA": "Nausicaa-Inu", "NAUT": "Nautilus Coin", @@ -11028,6 +11180,7 @@ "NETRUM": "Netrum", "NETT": "Netswap", "NETVR": "Netvrk", + "NETX": "NetX Token", "NETZ": "MainnetZ", "NETZ1": "NETZERO", "NEU": "Neumark", @@ -11231,6 +11384,7 @@ "NOGS": "Noggles", "NOHAT": "DogWifNoHat", "NOIA": "Syntropy", + "NOICE": "noice", "NOIS": "Nois Network", "NOIZ": "NOIZ", "NOKA": "Noka Solana AI", @@ -11355,6 +11509,7 @@ "NUMBERS": "NumbersCoin", "NUMI": "NUMINE Token", "NUMITOR": "Numitor", + "NUNU": "nunu", "NUR": "Nurcoin", "NURA": "Nura Labs", "NUSA": "Nusa", @@ -11450,7 +11605,6 @@ "OBSI": "Obsidium", "OBSR": "OBSERVER Coin", "OBSUSHI": "Sushi (OmniBridge)", - "OBT": "Oobit", "OBTC": "Obitan Chain", "OBVIOUS": "OBVIOUS COIN", "OBX": "OpenBlox", @@ -11645,12 +11799,14 @@ "ONTACT": "OnTact", "ONUS": "ONUS", "ONX": "OnX.finance", + "OOB": "Oobit", "OOE": "OpenOcean", "OOFP": "OOFP", "OOGI": "OOGI", "OOKI": "Ooki", "OOKS": "Onooks", "OOM": "OomerBot", + "OOPS": "OOPS", "OORC": "Orbit Bridge Klaytn Orbit Chain", "OORT": "OORT", "OOT": "Utrum", @@ -11724,6 +11880,7 @@ "ORAO": "ORAO Network", "ORARE": "OneRare", "ORB": "KlayCity ORB", + "ORBD": "OrbitEdge", "ORBI": "Orbs", "ORBIS": "Orbis", "ORBIT": "Orbit Protocol", @@ -11816,6 +11973,7 @@ "OUSG": "OUSG", "OUT": "Netscouters", "OUTL": "Outlanders Token", + "OUTLAW": "OUTLAW Crypto Games", "OVATO": "Ovato", "OVC": "OVCODE", "OVER": "OverProtocol", @@ -11825,6 +11983,7 @@ "OVO": "OVO", "OVPP": "OpenVPP", "OVR": "Ovr", + "OWB": "OWB", "OWC": "Oduwa", "OWD": "Owlstand", "OWL": "OWL Token", @@ -11855,7 +12014,7 @@ "OZONE": "Ozone metaverse", "OZONEC": "Ozonechain", "OZP": "OZAPHYRE", - "P": "PUPS•WORLD•PEACE", + "P": "PoP Planet", "P1": "PEPE ONE", "P202": "Project 202", "P2P": "Sentinel", @@ -11900,6 +12059,7 @@ "PALMP": "PalmPay", "PALMV1": "PaLM AI v1", "PALMY": "Palmy", + "PALU": "Palu", "PAM": "PAM", "PAMBI": "Pambicoin", "PAMP": "PAMP Network", @@ -11912,6 +12072,7 @@ "PANDO": "Pando", "PANDOP": "PandoProject", "PANDORA": "Pandora", + "PANDU": "Pandu Pandas", "PANGEA": "PANGEA", "PANIC": "PanicSwap", "PANO": "PanoVerse", @@ -11944,6 +12105,7 @@ "PARETO": "Pareto Network Token", "PARI": "Paribus", "PARKGENE": "PARKGENE", + "PARKINGO": "ParkinGo", "PARLAY": "Parlay", "PARMA": "PARMA Fan Token", "PARQ": "PARQ", @@ -11980,6 +12142,7 @@ "PAXU": "Pax Unitas", "PAXW": "pax.world", "PAY": "TenX", + "PAYAI": "PayAI Network", "PAYB": "Paybswap", "PAYCENT": "Paycent", "PAYCON": "Paycon", @@ -12322,6 +12485,7 @@ "PINEYE": "PinEye", "PING": "CryptoPing", "PINGO": "PinGo", + "PINGPONG": "PINGPONG Token", "PINK": "PINK - The Panther", "PINKCOIN": "PinkCoin", "PINKSALE": "PinkSale", @@ -12334,6 +12498,7 @@ "PIO": "Pioneershares", "PIP": "Pip", "PIPA": "Pipa Coin", + "PIPE": "Pipe", "PIPI": "Pippi Finance", "PIPL": "PiplCoin", "PIPO": "Pipo", @@ -12376,6 +12541,7 @@ "PKF": "PolkaFoundry", "PKG": "PKG Token", "PKIN": "PUMPKIN", + "PKM": "Pockemy", "PKN": "Poken", "PKOIN": "Pocketcoin", "PKT": "PKT", @@ -12482,6 +12648,7 @@ "PNDR": "Pandora Finance", "PNFT": "Pawn My NFT", "PNG": "Pangolin", + "PNGDA": "Pengda Yellow Panda", "PNGN": "SpacePenguin", "PNIC": "Phoenic", "PNK": "Kleros", @@ -12499,7 +12666,8 @@ "POC": "POC Blockchain", "POCAT": "Polite Cat", "POCC": "POC Chain", - "POCHITA": "Pochita", + "POCHITA": "pochita", + "POCHITAV1": "Pochita", "POCKET": "XPocket", "POCO": "Pocoland", "POD": "Podo Point", @@ -12508,6 +12676,7 @@ "PODO": "Power Of Deep Ocean", "POE": "Portal Network", "POET": "Po.et", + "POFU": "POFU", "POG": "PolygonumOnline", "POGAI": "POGAI", "POGS": "POG", @@ -12603,6 +12772,7 @@ "PORT": "Port Finance", "PORT3": "Port3 Network", "PORTAL": "Portal", + "PORTALS": "Portals", "PORTALTOKEN": "Portal", "PORTO": "FC Porto", "PORTU": "Portuma", @@ -12679,6 +12849,7 @@ "PRG": "Paragon", "PRI": "PRIVATEUM INITIATIVE", "PRIA": "PRIA", + "PRICELESS": "Priceless", "PRICK": "Pickle Rick", "PRIDE": "Nomad Exiles", "PRIMAL": "PRIMAL", @@ -12819,6 +12990,7 @@ "PUMPAI": "PumpAI", "PUMPB": "Pump", "PUMPBTC": "pumpBTC", + "PUMPBTCXYZ": "PumpBTC", "PUMPFUNBAN": "Pump Fun Ban", "PUMPIT": "BOGDANOFF", "PUMPTRUMP": "PUMP TRUMP", @@ -12842,6 +13014,7 @@ "PUPPETS": "Puppets Coin", "PUPPIES": "I love puppies", "PUPS": "PUPS (Ordinals)", + "PUPSWORLD": "PUPS•WORLD•PEACE", "PUPU": "Pepe's Dog", "PURA": "Pura", "PURE": "Puriever", @@ -12918,6 +13091,7 @@ "Q2C": "QubitCoin", "QA": "Quantum Assets", "QAC": "Quasarcoin", + "QACE": "Qace Dynamics", "QAI": "QuantixAI", "QANX": "QANplatform", "QANXV2": "QANplatform v2", @@ -12968,6 +13142,7 @@ "QOOB": "QOOBER", "QORA": "QoraCoin", "QORPO": "QORPO WORLD", + "QPAY": "QPAY SOL", "QQBC": "QQBC IPFS BLOCKCHAIN", "QQQ": "Poseidon Network", "QQQF": "Standard Crypto Fund", @@ -12994,7 +13169,8 @@ "QTK": "QuantCheck", "QTL": "Quatloo", "QTLX": "Quantlytica", - "QTO": "QToken", + "QTO": "Quanto", + "QTOK": "QToken", "QTUM": "QTUM", "QTZ": "Quartz", "QU3": "QU3ai", @@ -13161,6 +13337,7 @@ "RCT": "RealChain", "RCX": "RedCrowCoin", "RD": "Round Dollar", + "RDAC": "Redacted Coin", "RDC": "Ordocoin", "RDD": "Reddcoin", "RDDT": "Reddit", @@ -13196,6 +13373,7 @@ "REALUSDV1": "Real USD v1", "REALUSDV2": "Real USD v2", "REALY": "Realy Metaverse", + "REALYN": "Real", "REAP": "ReapChain", "REAPER": "Grim Finance", "REAU": "Vira-lata Finance", @@ -13204,6 +13382,7 @@ "REBUS": "Rebuschain", "REC": "Rec Token (REC)", "RECA": "The Resistance Cat", + "RECALL": "Recall", "RECKOON": "Reckoon", "RECOM": "Recom", "RECON": "RECON", @@ -13244,6 +13423,7 @@ "REGEN": "Regen Network", "REGENT": "REGENT COIN", "REGI": "Resistance Girl", + "REGRET": "Regret", "REHA": "Resistance Hamster", "REHAB": "NFT Rehab", "REI": "REI Network", @@ -13357,7 +13537,6 @@ "RIBB": "Ribbit", "RIBBIT": "Ribbit", "RIC": "Riecoin", - "RICE": "DAOSquare Governance Token", "RICECOIN": "RiceCoin", "RICEFARM": "RiceFarm", "RICH": "GET RICH QUICK", @@ -13409,6 +13588,8 @@ "RITE": "ritestream", "RITO": "Ritocoin", "RITZ": "Ritz.Game", + "RIVER": "River", + "RIVERPTS": "River Point Reward Token", "RIVUS": "RivusDAO", "RIYA": "Etheriya", "RIZ": "Rivalz Network", @@ -13649,6 +13830,7 @@ "RVR": "Revolution VR", "RVST": "Revest Finance", "RVT": "Rivetz", + "RVV": "REVIVE", "RVX": "Rivex", "RWA": "Allo", "RWAECO": "RWA Ecosystem", @@ -13680,6 +13862,7 @@ "RYU": "The Blue Dragon", "RYZ": "Anryze", "RZR": "RazorCoin", + "RZTO": "RZTO Token", "RZUSD": "RZUSD", "RedFlokiCEO": "Red Floki CEO", "S": "Sonic Labs", @@ -13740,14 +13923,16 @@ "SAKAI": "Sakai Vault", "SAKATA": "Sakata Inu", "SAKE": "SakeToken", - "SAL": "SalPay", + "SAL": "Salvium", "SALD": "Salad", "SALE": "DxSale Network", "SALL": "Sallar", "SALLY": "SALAMANDER", "SALMAN": "Mohameme Bit Salman", "SALMON": "Salmon", + "SALPAY": "SalPay", "SALT": "Salt Lending", + "SALUTE": "Salute", "SAM": "Samsunspor Fan Token", "SAMA": "Moonsama", "SAMMY": "Samoyed", @@ -14232,6 +14417,7 @@ "SIFT": "Smart Investment Fund Token", "SIFU": "SIFU", "SIG": "Signal", + "SIGM": "Sigma", "SIGMA": "SIGMA", "SIGN": "Sign", "SIGNA": "Signa", @@ -14340,6 +14526,7 @@ "SKT": "Sukhavati Network", "SKU": "Sakura", "SKULL": "Pirate Blocks", + "SKUY": "Token Sekuya", "SKX": "SKPANAX", "SKY": "Sky", "SKYA": "Sekuya Multiverse", @@ -14394,7 +14581,7 @@ "SLRS": "Solrise Finance", "SLS": "SaluS", "SLST": "SmartLands", - "SLT": "Salute", + "SLT": "SLT", "SLUGDENG": "SLUG DENG", "SLUMBO": "SLUMBO", "SLVLUSD": "Staked Level USD", @@ -14558,6 +14745,7 @@ "SOFI": "RAI Finance", "SOFTCO": "SOFT COQ INU", "SOFTT": "Wrapped FTT (Sollet)", + "SOGNI": "Sogni AI", "SOGUR": "Sogur Currency", "SOH": "Stohn Coin", "SOHOT": "SOHOTRN", @@ -14630,6 +14818,7 @@ "SOLSCC": "sols", "SOLSPONGE": "Solsponge", "SOLT": "Soltalk AI", + "SOLTAN": "SOLTAN", "SOLTR": "SolTrump", "SOLV": "Solv Protocol", "SOLVBTC": "Solv Protocol SolvBTC", @@ -14803,6 +14992,7 @@ "SPRITZMOON": "SpritzMoon Crypto Token", "SPRKL": "Sparkle Loyalty", "SPROUT": "Sprout", + "SPRSTR": "SprotoStrategy", "SPRT": "Sportium", "SPRTS": "Sprouts", "SPRTZ": "SpritzCoin", @@ -14950,6 +15140,7 @@ "STAX": "Staxcoin", "STAY": "NFsTay", "STB": "stabble", + "STBL": "STBL Governance Token", "STBOT": "SolTradingBot", "STBTC": "Lorenzo stBTC", "STBU": "Stobox Token", @@ -15052,7 +15243,8 @@ "STREAMIT": "STREAMIT COIN", "STREETH": "STREETH", "STRI": "Strite", - "STRIKE": "Strike", + "STRIKE": "StrikeBit", + "STRIKETOKEN": "Strike", "STRIP": "Stripto", "STRK": "Starknet", "STRM": "StreamCoin", @@ -15062,6 +15254,7 @@ "STRONGX": "StrongX", "STRP": "Strips Finance", "STRS": "STARS", + "STRSZN": "Stream SZN", "STRUMP": "Super Trump", "STRX": "StrikeX", "STS": "SBank", @@ -15099,6 +15292,7 @@ "SUBA": "Yotsuba", "SUBAWU": "Subawu Token", "SUBF": "Super Best Friends", + "SUBHUB": "SUBHUB", "SUBS": "Substratum Network", "SUCR": "Sucre", "SUD": "Sudo Labs", @@ -15151,8 +15345,9 @@ "SUNTRON": "TRON MASCOT", "SUNV1": "Sun Token v1", "SUNWUKONG": "SunWukong", - "SUP": "Supcoin", + "SUP": "Superp", "SUP8EME": "SUP8EME Token", + "SUPCOIN": "Supcoin", "SUPE": "Supe Infinity", "SUPER": "SuperVerse", "SUPERBID": "SuperBid", @@ -15194,6 +15389,7 @@ "SVNN": "Savanna Haus", "SVPN": "Shadow Node", "SVS": "GivingToServices SVS", + "SVSA": "SavannaSurvival", "SVT": "Solvent", "SVTS": "Syncvault", "SVX": "Savix", @@ -15291,6 +15487,7 @@ "SYNCG": "SyncGPT", "SYNCN": "Sync Network", "SYNCO": "Synco", + "SYND": "Syndicate", "SYNDOG": "Synthesizer Dog", "SYNK": "Synk", "SYNLEV": "SynLev", @@ -15305,8 +15502,10 @@ "SYRAX": "Syrax AI", "SYRUP": "Syrup", "SYRUPUSDC": "SyrupUSDC", + "SYRUPUSDT": "Syrup USDT", "SYS": "Syscoin", "SZCB": "Zugacoin", + "SZN": "BNB SZN", "T": "Threshold Network Token", "T1": "Trump Mobile", "T23": "T23", @@ -15315,7 +15514,7 @@ "TAAS": "Token as a Service", "TAB": "MollyCoin", "TABOO": "Taboo Token", - "TAC": "Traceability Chain", + "TAC": "TAC", "TACC": "TACC", "TACHYON": "Tachyon Protocol", "TAD": "Tadpole", @@ -15411,6 +15610,7 @@ "TBEER": "TRON BEER", "TBFT": "Türkiye Basketbol Federasyon Token", "TBILL": "OpenEden T-Bills", + "TBILLV1": "OpenEden T-Bills v1", "TBIS": "TBIS token", "TBL": "Tombola", "TBR": "Tuebor", @@ -15490,6 +15690,7 @@ "TENDIE": "TendieSwap", "TENET": "TENET", "TENFI": "TEN", + "TENGE": "TENGE TENGE", "TENNET": "Tennet", "TENS": "TensorScan", "TENSHI": "Tenshi", @@ -15569,6 +15770,7 @@ "THEFARM": "FARM", "THEG": "The GameHub", "THEHARAMBE": "Harambe", + "THEINTERNS": "Interns", "THEM": "The Meta DAO", "THEMIS": "Themis", "THEN": "THENA", @@ -15639,6 +15841,7 @@ "TIM": "TIMTIM GAMES", "TIME": "Chrono.tech", "TIMEFUN": "timefun", + "TIMELESS": "Timeless", "TIMES": "DARKTIMES", "TIMESW": "Timeswap", "TIMI": "This Is My Iguana", @@ -15787,7 +15990,8 @@ "TOPIA": "Hytopia", "TOPN": "TOP Network", "TOR": "TOR", - "TORA": "TORA NEKO", + "TORA": "Tensora", + "TORAN": "TORA NEKO", "TORCH": "Hercules Token", "TORE": "Toreus Finance", "TORG": "TORG", @@ -15844,6 +16048,7 @@ "TRAC": "OriginTrail", "TRACE": "Trace Network Labs", "TRACEA": "Trace AI", + "TRACEABILITY": "Traceability Chain", "TRACKEDBIO": "TrackedBio", "TRACN": "trac (Ordinals)", "TRADE": "Polytrade", @@ -15860,6 +16065,7 @@ "TRANQ": "Tranquil Finance", "TRANS": "Trans Pepe", "TRANSFER": "TransferCoin", + "TRASH": "TrashCoin", "TRAT": "Tratok", "TRAVA": "Trava Finance", "TRAXIA": "Traxia Membership Token", @@ -16002,8 +16208,9 @@ "TRUST": "TrustDAO", "TRUSTNFT": "TrustNFT", "TRUT": "Truth", - "TRUTH": "TruthGPT", + "TRUTH": "Swarm Network", "TRUTHFI": "Truthfi", + "TRUTHGPT": "TruthGPT", "TRV": "TrustVerse", "TRVC": "Trivechain", "TRVL": "TRVL", @@ -16037,6 +16244,7 @@ "TSR": "Tesra", "TST": "Test", "TSTAI": "Test AI", + "TSTON": "Tonstakers TON", "TSTS": "Test", "TSUBASAUT": "TSUBASA Utility Token", "TSUGT": "Captain Tsubasa", @@ -16078,6 +16286,7 @@ "TURBOS": "Turbos Finance", "TURBOW": "Turbo Wallet", "TURT": "TurtSat", + "TURTLE": "Turtle", "TUS": "Treasure Under Sea", "TUSD": "True USD", "TUSDV1": "True USD v1", @@ -16142,14 +16351,13 @@ "TZKI": "Tsuzuki Inu", "TZPEPE": "Tezos Pepe", "TZU": "Sun Tzu", - "U": "Unidef", "U2U": "U2U Network", "U8D": "Universal Dollar", "UA1": "UA1", "UAEC": "United Arab Emirates Coin", "UAHG": "UAHg", "UAT": "UltrAlpha", - "UB": "UBit Token", + "UB": "Unibase", "UBA": "Unbox.Art", "UBC": "Universal Basic Compute", "UBCOIN": "Ubcoin", @@ -16158,6 +16366,7 @@ "UBI": "Universal Basic Income", "UBIQ": "Ubiqoin", "UBIT": "UBIT", + "UBITTOKEN": "UBit Token", "UBQ": "Ubiq", "UBT": "UniBright", "UBTC": "UnitedBitcoin", @@ -16169,11 +16378,12 @@ "UCA": "UCA Coin", "UCAP": "Unicap.finance", "UCASH": "U.CASH", + "UCCOIN": "UC Coin", "UCG": "Universe Crystal Gene", "UCH": "UChain", "UCJL": "Utility Cjournal", "UCM": "UCROWDME", - "UCN": "UC Coin", + "UCN": "UCHAIN", "UCO": "Uniris", "UCOIN": "Ucoin", "UCON": "YouCoin Metaverse", @@ -16272,7 +16482,9 @@ "UNIBTC": "uniBTC", "UNIC": "Unicly", "UNICE": "UNICE", + "UNICEF": "united normies in crypto extending funds", "UNICORN": "UNICORN Token", + "UNIDEF": "Unidef", "UNIDEXAI": "UniDexAI", "UNIDX": "UniDex", "UNIDXV1": "UniDex v1", @@ -16297,6 +16509,7 @@ "UNITARYSTATUS": "UnitaryStatus Dollar", "UNITE": "Unite", "UNITED": "UnitedCoins", + "UNITPROV2": "Unit Protocol New", "UNITRADE": "UniTrade", "UNITREEAI": "Unitree G1 AI", "UNITREEDOG": "Unitree AI Robot Dog", @@ -16361,11 +16574,13 @@ "USC": "Ultimate Secure Cash", "USCC": "USC", "USCOIN": "USCoin", + "USCR": "United States Crypto Reserve", "USD0": "Usual", "USD1": "World Liberty Financial USD", "USD3": "Web 3 Dollar", "USDA": "USDa", "USDACC": "USDA", + "USDAI": "USDai", "USDAP": "Bond Appetite USD", "USDB": "USD Bancor", "USDBC": "Bridged USDC", @@ -16421,6 +16636,7 @@ "USDUC": "Unstable Coin", "USDV": "Verified USD", "USDW": "USD DWIN", + "USDWON": "Won Chang", "USDX": "USDX Stablecoin", "USDXL": "Last USD", "USDY": "Ondo US Dollar Yield", @@ -16471,6 +16687,7 @@ "UTMDOGE": "UltramanDoge", "UTNP": "Universa", "UTON": "uTON", + "UTOPIA": "UCOIN", "UTT": "United Traders Token", "UTU": "UTU Protocol", "UTX": "UTIX", @@ -16485,6 +16702,7 @@ "UWUCOIN": "uwu", "UX": "Umee", "UXLINK": "UXLINK", + "UXLINKV1": "UXLINK v1", "UXOS": "UXOS", "UXP": "UXD Protocol", "UZUMAKI": "Uzumaki Inu", @@ -16508,6 +16726,7 @@ "VALORBIT": "Valorbit", "VALU": "Value", "VALUE": "Value Liquidity", + "VALYR": "Valyr", "VAMPIRE": "Vampire Inu", "VAN": "Vanspor Token", "VANA": "Vana", @@ -16605,6 +16824,7 @@ "VERA": "Vera", "VERI": "Veritaseum", "VERIC": "VeriCoin", + "VERIFY": "Verify", "VERO": "VEROPAD", "VERSA": "Versa Token", "VERSACE": "VERSACE", @@ -16628,9 +16848,12 @@ "VFIL": "Venus Filecoin", "VFOX": "VFOX", "VFT": "Value Finance", + "VFY": "zkVerify", + "VFYV1": "Verify Token", "VG": "Viu Ganhou", "VGO": "Vagabond", "VGX": "Voyager Token", + "VGXV1": "Voyager v1", "VHC": "Vault Hill City", "VI": "Vid", "VIA": "Octavia AI", @@ -16693,6 +16916,7 @@ "VITALIK": "OFFICIAL VITALIK", "VITAMINS": "Vitamins", "VITARNA": "VitaRNA", + "VITASTEM": "VitaStem", "VITE": "VITE", "VITEX": "ViteX Coin", "VITRA": "Vitra Studios", @@ -16737,6 +16961,7 @@ "VNO": "Veno Finance", "VNST": "VNST Stablecoin", "VNT": "VNT Chain", + "VNTR": "Venture Mind AI", "VNTW": "Value Network Token", "VNX": "VisionX", "VNXAU": "VNX Gold", @@ -16776,6 +17001,7 @@ "VOYACOIN": "Voyacoin", "VP": "Torah Network", "VPAD": "VLaunch", + "VPAY": "VPay by Virtuals", "VPK": "Vulture Peak", "VPND": "VaporNodes", "VPP": "Virtue Poker Points", @@ -16786,7 +17012,9 @@ "VR": "Victoria", "VR1": "VR1", "VRA": "Verasity", + "VRAV1": "Verasity v1", "VRC": "Virtual Coin", + "VRFY": "VERIFY", "VRGW": "Virtual Reality Game World", "VRH": "Versailles Heroes", "VRL": "Virtual X", @@ -16974,6 +17202,7 @@ "WBT": "WhiteBIT Token", "WBTC": "Wrapped Bitcoin", "WBTCWXG": "WBTC-WXG", + "WBULL": "BNB Wallstreet Bull", "WBX": "WiBX", "WCA": "WCAPES", "WCANTO": "Wrapped CANTO", @@ -17034,6 +17263,7 @@ "WEL": "Welsh Corgi", "WELA": "Wrapped Elastos", "WELD": "Weld", + "WELF": "welf", "WELL": "Moonwell", "WELL3": "WELL3", "WELLTOKEN": "Well", @@ -17069,6 +17299,7 @@ "WFAI": "WaifuAI", "WFBTC": "Wrapped Fantom Bitcoin", "WFDP": "WFDP", + "WFI": "WeFi", "WFIL": "Wrapped Filecoin", "WFLAMA": "WIFLAMA", "WFLOW": "Wrapped Flow", @@ -17208,6 +17439,7 @@ "WLUNA": "Wrapped LUNA Token", "WLUNC": "Wrapped LUNA Classic", "WLXT": "Wallex Token", + "WM": "WrappedM by M^0", "WMATIC": "Wrapped Matic", "WMB": "WatermelonBlock", "WMC": "Wrapped MistCoin", @@ -17343,6 +17575,7 @@ "WSI": "WeSendit", "WSIENNA": "Sienna ERC20", "WSM": "Wall Street Memes", + "WSOL": "Wrapped Solana", "WSPP": "Wolf Safe Poor People", "WSTA": "Wrapped Statera", "WSTETH": "Lido wstETH", @@ -17378,6 +17611,7 @@ "WUK": "WUKONG", "WUKONG": "Sun Wukong", "WULFY": "Wulfy", + "WUM": "Unicorn Meat", "WUSD": "Worldwide USD", "WUST": "Wrapped UST Token", "WVG0": "Wrapped Virgin Gen-0 CryptoKittties", @@ -17397,6 +17631,7 @@ "WXDAI": "Wrapped XDAI", "WXDC": "Wrapped XDC", "WXM": "WeatherXM", + "WXPL": "Wrapped XPL", "WXRP": "Wrapped XRP", "WXT": "WXT", "WXTZ": "Wrapped Tezos", @@ -17434,6 +17669,7 @@ "XALGO": "Wrapped ALGO", "XALPHA": "XAlpha AI", "XAMP": "Antiample", + "XAN": "Anoma", "XAND": "Xandeum", "XANK": "Xank", "XAP": "Apollon", @@ -17453,7 +17689,7 @@ "XBB": "BrickBlock", "XBC": "BitcoinPlus", "XBE": "XBE Token", - "XBG": "BitGrin", + "XBG": "XBorg Token", "XBI": "Bitcoin Incognito", "XBL": "Billionaire Token", "XBLAZE": "Trailblaze", @@ -17503,6 +17739,7 @@ "XCT": "C-Bits", "XCUR": "Curate", "XCV": "XCarnival", + "XCX": "Xeleb AI", "XCXT": "CoinonatX", "XD": "Data Transaction Token", "XDAG": "Dagger", @@ -17621,6 +17858,7 @@ "XMX": "XMax", "XMY": "MyriadCoin", "XNA": "Neurai", + "XNAP": "SNAPX", "XNB": "Xeonbit", "XNC": "Xenios", "XNET": "XNET Mobile", @@ -17662,6 +17900,7 @@ "XPH": "PharmaCoin", "XPHX": "PhoenixCo Token", "XPI": "XPi", + "XPIN": "XPIN Token", "XPL": "Plasma", "XPLA": "XPLA", "XPLL": "ParallelChain", @@ -17820,8 +18059,10 @@ "YAXIS": "yAxis", "YAY": "YAY Games", "YAYCOIN": "YAYcoin", + "YB": "Yield Basis", "YBC": "YbCoin", "YBDBD": "YBDBD", + "YBNB": "Yellow BNB 4", "YBO": "Young Boys Fan Token", "YBR": "YieldBricks", "YCC": "Yuan Chain Coin", @@ -17931,7 +18172,7 @@ "YTJIA": "Jia Yueting", "YTN": "YENTEN", "YTS": "YetiSwap", - "YU": "BOUNTYKINDS", + "YU": "Yala stablecoin", "YUANG": "Yuang Coin", "YUCHEN": "Sun Yuchen", "YUCJ": "Yu Coin", @@ -17991,6 +18232,7 @@ "ZBC": "Zebec Protocol", "ZBCN": "Zebec Network", "ZBIT": "zbit", + "ZBT": "ZEROBASE", "ZBU": "Zeebu", "ZBUV1": "ZEEBU v1", "ZCC": "ZCC Coin", @@ -18037,6 +18279,7 @@ "ZENI": "Zennies", "ZENIQ": "Zeniq Coin", "ZENITH": "Zenith Chain", + "ZENIX": "ZENIX", "ZENPROTOCOL": "Zen Protocol", "ZENQ": "Zenqira", "ZENT": "Zentry", @@ -18044,6 +18287,7 @@ "ZEP": "Zeppelin Dao", "ZEPH": "Zephyr Protocol", "ZER": "Zero", + "ZERA": "ZERA", "ZERC": "zkRace Coin", "ZEREBRO": "Zerebro", "ZERO": "ZeroLend", @@ -18235,5 +18479,7 @@ "redBUX": "redBUX", "sOHM": "Staked Olympus", "vXDEFI": "vXDEFI", - "wsOHM": "Wrapped Staked Olympus" + "wsOHM": "Wrapped Staked Olympus", + "修仙": "修仙", + "币安人生": "币安人生" } diff --git a/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts b/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts index 8b885c013..1e297b93b 100644 --- a/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts +++ b/apps/api/src/services/data-provider/data-enhancer/trackinsight/trackinsight.service.ts @@ -4,7 +4,7 @@ import { Holding } from '@ghostfolio/common/interfaces'; import { Country } from '@ghostfolio/common/interfaces/country.interface'; import { Sector } from '@ghostfolio/common/interfaces/sector.interface'; -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { SymbolProfile } from '@prisma/client'; import { countries } from 'countries-list'; @@ -202,7 +202,12 @@ export class TrackinsightDataEnhancerService implements DataEnhancerInterface { return undefined; }) - .catch(() => { + .catch(({ message }) => { + Logger.error( + `Failed to search Trackinsight symbol for ${symbol} (${message})`, + 'TrackinsightDataEnhancerService' + ); + return undefined; }); } diff --git a/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.mock.ts b/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.mock.ts index 8f5d1c28a..076375523 100644 --- a/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.mock.ts +++ b/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.mock.ts @@ -17,11 +17,21 @@ export const ExchangeRateDataServiceMock = { '2023-07-10': 0.8854 } }); + } else if (targetCurrency === 'EUR') { + return Promise.resolve({ + EUREUR: { + '2021-12-12': 1 + }, + USDEUR: { + '2021-12-12': 0.8855 + } + }); } else if (targetCurrency === 'USD') { return Promise.resolve({ USDUSD: { '2018-01-01': 1, '2021-11-16': 1, + '2021-12-12': 1, '2023-07-10': 1 } }); diff --git a/apps/api/src/services/i18n/i18n.service.ts b/apps/api/src/services/i18n/i18n.service.ts index 0f1f6239d..cf340d7c6 100644 --- a/apps/api/src/services/i18n/i18n.service.ts +++ b/apps/api/src/services/i18n/i18n.service.ts @@ -65,7 +65,7 @@ export class I18nService { } private parseLanguageCode(aFileName: string) { - const match = aFileName.match(/\.([a-zA-Z]+)\.xlf$/); + const match = /\.([a-zA-Z]+)\.xlf$/.exec(aFileName); return match ? match[1] : DEFAULT_LANGUAGE_CODE; } diff --git a/apps/api/src/services/interfaces/interfaces.ts b/apps/api/src/services/interfaces/interfaces.ts index 7469754b5..492c2bd35 100644 --- a/apps/api/src/services/interfaces/interfaces.ts +++ b/apps/api/src/services/interfaces/interfaces.ts @@ -20,4 +20,5 @@ export interface DataProviderResponse { export interface DataGatheringItem extends AssetProfileIdentifier { date?: Date; + force?: boolean; } diff --git a/apps/api/src/services/market-data/market-data.service.ts b/apps/api/src/services/market-data/market-data.service.ts index 38ad61663..d318b9a70 100644 --- a/apps/api/src/services/market-data/market-data.service.ts +++ b/apps/api/src/services/market-data/market-data.service.ts @@ -132,6 +132,61 @@ export class MarketDataService { }); } + /** + * Atomically replace market data for a symbol within a date range. + * Deletes existing data in the range and inserts new data within a single + * transaction to prevent data loss if the operation fails. + */ + public async replaceForSymbol({ + data, + dataSource, + symbol + }: AssetProfileIdentifier & { data: Prisma.MarketDataUpdateInput[] }) { + await this.prismaService.$transaction(async (prisma) => { + if (data.length > 0) { + let minTime = Infinity; + let maxTime = -Infinity; + + for (const { date } of data) { + const time = (date as Date).getTime(); + + if (time < minTime) { + minTime = time; + } + + if (time > maxTime) { + maxTime = time; + } + } + + const minDate = new Date(minTime); + const maxDate = new Date(maxTime); + + await prisma.marketData.deleteMany({ + where: { + dataSource, + symbol, + date: { + gte: minDate, + lte: maxDate + } + } + }); + + await prisma.marketData.createMany({ + data: data.map(({ date, marketPrice, state }) => ({ + dataSource, + symbol, + date: date as Date, + marketPrice: marketPrice as number, + state: state as MarketDataState + })), + skipDuplicates: true + }); + } + }); + } + public async updateAssetProfileIdentifier( oldAssetProfileIdentifier: AssetProfileIdentifier, newAssetProfileIdentifier: AssetProfileIdentifier 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 1a172f3ea..1a4038652 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 @@ -100,7 +100,7 @@ export class DataGatheringProcessor { name: GATHER_HISTORICAL_MARKET_DATA_PROCESS_JOB_NAME }) public async gatherHistoricalMarketData(job: Job) { - const { dataSource, date, symbol } = job.data; + const { dataSource, date, force, symbol } = job.data; try { let currentDate = parseISO(date as unknown as string); @@ -109,7 +109,7 @@ export class DataGatheringProcessor { `Historical market data gathering has been started for ${symbol} (${dataSource}) at ${format( currentDate, DATE_FORMAT - )}`, + )}${force ? ' (forced update)' : ''}`, `DataGatheringProcessor (${GATHER_HISTORICAL_MARKET_DATA_PROCESS_JOB_NAME})` ); @@ -157,7 +157,15 @@ export class DataGatheringProcessor { currentDate = addDays(currentDate, 1); } - await this.marketDataService.updateMany({ data }); + if (force) { + await this.marketDataService.replaceForSymbol({ + data, + dataSource, + symbol + }); + } else { + await this.marketDataService.updateMany({ data }); + } Logger.log( `Historical market data gathering has been completed for ${symbol} (${dataSource}) at ${format( diff --git a/apps/api/src/services/queues/data-gathering/data-gathering.service.ts b/apps/api/src/services/queues/data-gathering/data-gathering.service.ts index 2d3ec45ad..c433f692f 100644 --- a/apps/api/src/services/queues/data-gathering/data-gathering.service.ts +++ b/apps/api/src/services/queues/data-gathering/data-gathering.service.ts @@ -2,7 +2,6 @@ import { DataProviderService } from '@ghostfolio/api/services/data-provider/data import { DataEnhancerInterface } from '@ghostfolio/api/services/data-provider/interfaces/data-enhancer.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { DataGatheringItem } from '@ghostfolio/api/services/interfaces/interfaces'; -import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; import { PropertyService } from '@ghostfolio/api/services/property/property.service'; import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service'; @@ -41,7 +40,6 @@ export class DataGatheringService { private readonly dataGatheringQueue: Queue, private readonly dataProviderService: DataProviderService, private readonly exchangeRateDataService: ExchangeRateDataService, - private readonly marketDataService: MarketDataService, private readonly prismaService: PrismaService, private readonly propertyService: PropertyService, private readonly symbolProfileService: SymbolProfileService @@ -95,8 +93,6 @@ export class DataGatheringService { } public async gatherSymbol({ dataSource, date, symbol }: DataGatheringItem) { - await this.marketDataService.deleteMany({ dataSource, symbol }); - const dataGatheringItems = (await this.getSymbolsMax()) .filter((dataGatheringItem) => { return ( @@ -111,6 +107,7 @@ export class DataGatheringService { await this.gatherSymbols({ dataGatheringItems, + force: true, priority: DATA_GATHERING_QUEUE_PRIORITY_HIGH }); } @@ -274,9 +271,11 @@ export class DataGatheringService { public async gatherSymbols({ dataGatheringItems, + force = false, priority }: { dataGatheringItems: DataGatheringItem[]; + force?: boolean; priority: number; }) { await this.addJobsToQueue( @@ -285,6 +284,7 @@ export class DataGatheringService { data: { dataSource, date, + force, symbol }, name: GATHER_HISTORICAL_MARKET_DATA_PROCESS_JOB_NAME, diff --git a/apps/client/project.json b/apps/client/project.json index adb63d5c1..0d3571cdf 100644 --- a/apps/client/project.json +++ b/apps/client/project.json @@ -61,30 +61,30 @@ }, "targets": { "build": { - "executor": "@nx/angular:webpack-browser", + "executor": "@nx/angular:browser-esbuild", "options": { - "deleteOutputPath": false, - "localize": true, - "outputPath": "dist/apps/client", "index": "apps/client/src/index.html", "main": "apps/client/src/main.ts", - "polyfills": "apps/client/src/polyfills.ts", + "outputPath": "dist/apps/client", "tsConfig": "apps/client/tsconfig.app.json", + "buildOptimizer": false, + "deleteOutputPath": false, + "extractLicenses": false, + "localize": true, + "namedChunks": true, + "ngswConfigPath": "apps/client/ngsw-config.json", + "optimization": false, + "polyfills": "apps/client/src/polyfills.ts", + "scripts": ["node_modules/marked/marked.min.js"], + "serviceWorker": true, + "sourceMap": true, "styles": [ "apps/client/src/assets/fonts/inter.css", "apps/client/src/styles/theme.scss", "apps/client/src/styles.scss", "node_modules/open-color/open-color.css" ], - "scripts": ["node_modules/marked/marked.min.js"], - "vendorChunk": true, - "extractLicenses": false, - "buildOptimizer": false, - "sourceMap": true, - "optimization": false, - "namedChunks": true, - "serviceWorker": true, - "ngswConfigPath": "apps/client/ngsw-config.json" + "vendorChunk": true }, "configurations": { "development-ca": { @@ -136,19 +136,6 @@ "localize": ["zh"] }, "production": { - "fileReplacements": [ - { - "replace": "apps/client/src/environments/environment.ts", - "with": "apps/client/src/environments/environment.prod.ts" - } - ], - "optimization": true, - "outputHashing": "all", - "sourceMap": false, - "namedChunks": false, - "extractLicenses": true, - "vendorChunk": false, - "buildOptimizer": true, "budgets": [ { "type": "initial", @@ -160,7 +147,20 @@ "maximumWarning": "6kb", "maximumError": "10kb" } - ] + ], + "buildOptimizer": true, + "extractLicenses": true, + "fileReplacements": [ + { + "replace": "apps/client/src/environments/environment.ts", + "with": "apps/client/src/environments/environment.prod.ts" + } + ], + "namedChunks": false, + "optimization": true, + "outputHashing": "all", + "sourceMap": false, + "vendorChunk": false } }, "outputs": ["{options.outputPath}"], diff --git a/apps/client/src/app/app.component.ts b/apps/client/src/app/app.component.ts index bddd7d3da..5ecb7bf8b 100644 --- a/apps/client/src/app/app.component.ts +++ b/apps/client/src/app/app.component.ts @@ -276,7 +276,10 @@ export class AppComponent implements OnDestroy, OnInit { .subscribe((user) => { this.user = user; - const dialogRef = this.dialog.open(GfHoldingDetailDialogComponent, { + const dialogRef = this.dialog.open< + GfHoldingDetailDialogComponent, + HoldingDetailDialogParams + >(GfHoldingDetailDialogComponent, { autoFocus: false, data: { dataSource, @@ -302,7 +305,7 @@ export class AppComponent implements OnDestroy, OnInit { hasPermission(this.user?.permissions, permissions.updateOrder) && !this.user?.settings?.isRestrictedView, locale: this.user?.settings?.locale - } as HoldingDetailDialogParams, + }, height: this.deviceType === 'mobile' ? '98vh' : '80vh', width: this.deviceType === 'mobile' ? '100vw' : '50rem' }); diff --git a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts index bdc2424f5..94cb22699 100644 --- a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts +++ b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts @@ -43,9 +43,9 @@ import { Big } from 'big.js'; import { format, parseISO } from 'date-fns'; import { addIcons } from 'ionicons'; import { + albumsOutline, cashOutline, - swapVerticalOutline, - walletOutline + swapVerticalOutline } from 'ionicons/icons'; import { isNumber } from 'lodash'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; @@ -129,7 +129,7 @@ export class GfAccountDetailDialogComponent implements OnDestroy, OnInit { } }); - addIcons({ cashOutline, swapVerticalOutline, walletOutline }); + addIcons({ albumsOutline, cashOutline, swapVerticalOutline }); } public ngOnInit() { diff --git a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html index eff500d0a..07ea17038 100644 --- a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html +++ b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html @@ -98,7 +98,7 @@ > - +
Holdings
{ this.user = user; - const dialogRef = this.dialog.open(GfAssetProfileDialogComponent, { + const dialogRef = this.dialog.open< + GfAssetProfileDialogComponent, + AssetProfileDialogParams + >(GfAssetProfileDialogComponent, { autoFocus: false, data: { dataSource, @@ -438,7 +441,7 @@ export class GfAdminMarketDataComponent colorScheme: this.user?.settings.colorScheme, deviceType: this.deviceType, locale: this.user?.settings?.locale - } as AssetProfileDialogParams, + }, height: this.deviceType === 'mobile' ? '98vh' : '80vh', width: this.deviceType === 'mobile' ? '100vw' : '50rem' }); @@ -465,17 +468,17 @@ export class GfAdminMarketDataComponent .subscribe((user) => { this.user = user; - const dialogRef = this.dialog.open( + const dialogRef = this.dialog.open< GfCreateAssetProfileDialogComponent, - { - autoFocus: false, - data: { - deviceType: this.deviceType, - locale: this.user?.settings?.locale - } as CreateAssetProfileDialogParams, - width: this.deviceType === 'mobile' ? '100vw' : '50rem' - } - ); + CreateAssetProfileDialogParams + >(GfCreateAssetProfileDialogComponent, { + autoFocus: false, + data: { + deviceType: this.deviceType, + locale: this.user?.settings?.locale + }, + width: this.deviceType === 'mobile' ? '100vw' : '50rem' + }); dialogRef .afterClosed() diff --git a/apps/client/src/app/components/admin-platform/admin-platform.component.ts b/apps/client/src/app/components/admin-platform/admin-platform.component.ts index 845c7f375..6c95cee0b 100644 --- a/apps/client/src/app/components/admin-platform/admin-platform.component.ts +++ b/apps/client/src/app/components/admin-platform/admin-platform.component.ts @@ -34,6 +34,7 @@ import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject, takeUntil } from 'rxjs'; import { GfCreateOrUpdatePlatformDialogComponent } from './create-or-update-platform-dialog/create-or-update-platform-dialog.component'; +import { CreateOrUpdatePlatformDialogParams } from './create-or-update-platform-dialog/interfaces/interfaces'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, @@ -153,19 +154,20 @@ export class GfAdminPlatformComponent implements OnInit, OnDestroy { } private openCreatePlatformDialog() { - const dialogRef = this.dialog.open( + const dialogRef = this.dialog.open< GfCreateOrUpdatePlatformDialogComponent, - { - data: { - platform: { - name: null, - url: null - } - }, - height: this.deviceType === 'mobile' ? '98vh' : undefined, - width: this.deviceType === 'mobile' ? '100vw' : '50rem' - } - ); + CreateOrUpdatePlatformDialogParams + >(GfCreateOrUpdatePlatformDialogComponent, { + data: { + platform: { + id: null, + name: null, + url: null + } + }, + height: this.deviceType === 'mobile' ? '98vh' : undefined, + width: this.deviceType === 'mobile' ? '100vw' : '50rem' + }); dialogRef .afterClosed() @@ -191,21 +193,29 @@ export class GfAdminPlatformComponent implements OnInit, OnDestroy { }); } - private openUpdatePlatformDialog({ id, name, url }) { - const dialogRef = this.dialog.open( + private openUpdatePlatformDialog({ + id, + name, + url + }: { + id: string; + name: string; + url: string; + }) { + const dialogRef = this.dialog.open< GfCreateOrUpdatePlatformDialogComponent, - { - data: { - platform: { - id, - name, - url - } - }, - height: this.deviceType === 'mobile' ? '98vh' : undefined, - width: this.deviceType === 'mobile' ? '100vw' : '50rem' - } - ); + CreateOrUpdatePlatformDialogParams + >(GfCreateOrUpdatePlatformDialogComponent, { + data: { + platform: { + id, + name, + url + } + }, + height: this.deviceType === 'mobile' ? '98vh' : undefined, + width: this.deviceType === 'mobile' ? '100vw' : '50rem' + }); dialogRef .afterClosed() diff --git a/apps/client/src/app/components/admin-tag/admin-tag.component.ts b/apps/client/src/app/components/admin-tag/admin-tag.component.ts index de4c8cedc..5552fa01b 100644 --- a/apps/client/src/app/components/admin-tag/admin-tag.component.ts +++ b/apps/client/src/app/components/admin-tag/admin-tag.component.ts @@ -32,6 +32,7 @@ import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject, takeUntil } from 'rxjs'; import { GfCreateOrUpdateTagDialogComponent } from './create-or-update-tag-dialog/create-or-update-tag-dialog.component'; +import { CreateOrUpdateTagDialogParams } from './create-or-update-tag-dialog/interfaces/interfaces'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, @@ -149,9 +150,13 @@ export class GfAdminTagComponent implements OnInit, OnDestroy { } private openCreateTagDialog() { - const dialogRef = this.dialog.open(GfCreateOrUpdateTagDialogComponent, { + const dialogRef = this.dialog.open< + GfCreateOrUpdateTagDialogComponent, + CreateOrUpdateTagDialogParams + >(GfCreateOrUpdateTagDialogComponent, { data: { tag: { + id: null, name: null } }, @@ -183,8 +188,11 @@ export class GfAdminTagComponent implements OnInit, OnDestroy { }); } - private openUpdateTagDialog({ id, name }) { - const dialogRef = this.dialog.open(GfCreateOrUpdateTagDialogComponent, { + private openUpdateTagDialog({ id, name }: { id: string; name: string }) { + const dialogRef = this.dialog.open< + GfCreateOrUpdateTagDialogComponent, + CreateOrUpdateTagDialogParams + >(GfCreateOrUpdateTagDialogComponent, { data: { tag: { id, diff --git a/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/interfaces/interfaces.ts b/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/interfaces/interfaces.ts index bd7214786..4b7f83e93 100644 --- a/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/interfaces/interfaces.ts +++ b/apps/client/src/app/components/admin-tag/create-or-update-tag-dialog/interfaces/interfaces.ts @@ -1,5 +1,5 @@ import { Tag } from '@prisma/client'; export interface CreateOrUpdateTagDialogParams { - tag: Tag; + tag: Pick; } diff --git a/apps/client/src/app/components/admin-users/admin-users.component.ts b/apps/client/src/app/components/admin-users/admin-users.component.ts index fce97877b..94b5839c6 100644 --- a/apps/client/src/app/components/admin-users/admin-users.component.ts +++ b/apps/client/src/app/components/admin-users/admin-users.component.ts @@ -5,7 +5,11 @@ import { getDateFormatString, getEmojiFlag } from '@ghostfolio/common/helper'; -import { AdminUsers, InfoItem, User } from '@ghostfolio/common/interfaces'; +import { + AdminUsersResponse, + InfoItem, + User +} from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; import { GfValueComponent } from '@ghostfolio/ui/value'; @@ -75,7 +79,7 @@ import { GfUserDetailDialogComponent } from '../user-detail-dialog/user-detail-d export class GfAdminUsersComponent implements OnDestroy, OnInit { @ViewChild(MatPaginator) paginator: MatPaginator; - public dataSource = new MatTableDataSource(); + public dataSource = new MatTableDataSource(); public defaultDateFormat: string; public deviceType: string; public displayedColumns: string[] = []; @@ -278,9 +282,9 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit { }); } - private openUserDetailDialog(userId: string) { + private openUserDetailDialog(aUserId: string) { const userData = this.dataSource.data.find(({ id }) => { - return id === userId; + return id === aUserId; }); if (!userData) { @@ -288,13 +292,17 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit { return; } - const dialogRef = this.dialog.open(GfUserDetailDialogComponent, { + const dialogRef = this.dialog.open< + GfUserDetailDialogComponent, + UserDetailDialogParams + >(GfUserDetailDialogComponent, { autoFocus: false, data: { userData, deviceType: this.deviceType, + hasPermissionForSubscription: this.hasPermissionForSubscription, locale: this.user?.settings?.locale - } as UserDetailDialogParams, + }, height: this.deviceType === 'mobile' ? '98vh' : '60vh', width: this.deviceType === 'mobile' ? '100vw' : '50rem' }); @@ -303,7 +311,6 @@ export class GfAdminUsersComponent implements OnDestroy, OnInit { .afterClosed() .pipe(takeUntil(this.unsubscribeSubject)) .subscribe(() => { - this.fetchUsers(); this.router.navigate(['.'], { relativeTo: this.route }); }); } diff --git a/apps/client/src/app/components/header/header.component.ts b/apps/client/src/app/components/header/header.component.ts index 6e1a909a1..3f011fec4 100644 --- a/apps/client/src/app/components/header/header.component.ts +++ b/apps/client/src/app/components/header/header.component.ts @@ -1,4 +1,5 @@ import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto'; +import { LoginWithAccessTokenDialogParams } from '@ghostfolio/client/components/login-with-access-token-dialog/interfaces/interfaces'; import { GfLoginWithAccessTokenDialogComponent } from '@ghostfolio/client/components/login-with-access-token-dialog/login-with-access-token-dialog.component'; import { LayoutService } from '@ghostfolio/client/core/layout.service'; import { NotificationService } from '@ghostfolio/client/core/notification/notification.service'; @@ -271,7 +272,10 @@ export class GfHeaderComponent implements OnChanges { } public openLoginDialog() { - const dialogRef = this.dialog.open(GfLoginWithAccessTokenDialogComponent, { + const dialogRef = this.dialog.open< + GfLoginWithAccessTokenDialogComponent, + LoginWithAccessTokenDialogParams + >(GfLoginWithAccessTokenDialogComponent, { autoFocus: false, data: { accessToken: '', diff --git a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts index d4c1c59c1..b443a37e7 100644 --- a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts +++ b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts @@ -1,3 +1,4 @@ +import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto'; import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface'; import { GfDialogFooterComponent } from '@ghostfolio/client/components/dialog-footer/dialog-footer.component'; import { GfDialogHeaderComponent } from '@ghostfolio/client/components/dialog-header/dialog-header.component'; @@ -38,7 +39,7 @@ import { OnDestroy, OnInit } from '@angular/core'; -import { FormBuilder, FormGroup } from '@angular/forms'; +import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; import { MatChipsModule } from '@angular/material/chips'; import { @@ -57,6 +58,7 @@ import { isUUID } from 'class-validator'; import { format, isSameMonth, isToday, parseISO } from 'date-fns'; import { addIcons } from 'ionicons'; import { + arrowDownCircleOutline, createOutline, flagOutline, readerOutline, @@ -92,6 +94,7 @@ import { HoldingDetailDialogParams } from './interfaces/interfaces'; MatFormFieldModule, MatTabsModule, NgxSkeletonLoaderModule, + ReactiveFormsModule, RouterModule ], schemas: [CUSTOM_ELEMENTS_SCHEMA], @@ -101,7 +104,6 @@ import { HoldingDetailDialogParams } from './interfaces/interfaces'; }) export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { public activitiesCount: number; - public activityForm: FormGroup; public accounts: Account[]; public assetClass: string; public assetSubClass: string; @@ -122,6 +124,7 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { public hasPermissionToCreateOwnTag: boolean; public hasPermissionToReadMarketDataOfOwnAssetProfile: boolean; public historicalDataItems: LineChartItem[]; + public holdingForm: FormGroup; public investmentInBaseCurrencyWithCurrencyEffect: number; public investmentInBaseCurrencyWithCurrencyEffectPrecision = 2; public isUUID = isUUID; @@ -167,6 +170,7 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { private userService: UserService ) { addIcons({ + arrowDownCircleOutline, createOutline, flagOutline, readerOutline, @@ -177,16 +181,16 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { } public ngOnInit() { - this.activityForm = this.formBuilder.group({ - tags: [] as string[] - }); - const filters: Filter[] = [ { id: this.data.dataSource, type: 'DATA_SOURCE' }, { id: this.data.symbol, type: 'SYMBOL' } ]; - this.activityForm + this.holdingForm = this.formBuilder.group({ + tags: [] as string[] + }); + + this.holdingForm .get('tags') .valueChanges.pipe(takeUntil(this.unsubscribeSubject)) .subscribe((tags: Tag[]) => { @@ -427,7 +431,7 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { }; }); - this.activityForm.setValue({ tags: this.tags }, { emitEvent: false }); + this.holdingForm.setValue({ tags: this.tags }, { emitEvent: false }); this.value = value; @@ -557,6 +561,37 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { this.dialogRef.close(); } + public onCloseHolding() { + const today = new Date(); + + const activity: CreateOrderDto = { + accountId: this.accounts.length === 1 ? this.accounts[0].id : null, + comment: null, + currency: this.SymbolProfile.currency, + dataSource: this.SymbolProfile.dataSource, + date: today.toISOString(), + fee: 0, + quantity: this.quantity, + symbol: this.SymbolProfile.symbol, + tags: this.tags.map(({ id }) => { + return id; + }), + type: 'SELL', + unitPrice: this.marketPrice + }; + + this.dataService + .postOrder(activity) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(() => { + this.router.navigate( + internalRoutes.portfolio.subRoutes.activities.routerLink + ); + + this.dialogRef.close(); + }); + } + public onExport() { const activityIds = this.dataSource.data.map(({ id }) => { return id; @@ -583,10 +618,6 @@ export class GfHoldingDetailDialogComponent implements OnDestroy, OnInit { } } - public onTagsChanged(tags: Tag[]) { - this.activityForm.get('tags').setValue(tags); - } - public onUpdateActivity(aActivity: Activity) { this.router.navigate( internalRoutes.portfolio.subRoutes.activities.routerLink, diff --git a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html index 298692303..f52286160 100644 --- a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html +++ b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -411,13 +411,14 @@ } - +
+ + @if ( data.hasPermissionToAccessAdminControl || @@ -428,6 +429,29 @@
+ @if (data.hasPermissionToCreateActivity && quantity > 0) { + + } + @if ( + dataSource?.data.length > 0 && + data.hasPermissionToReportDataGlitch === true + ) { + Report Data Glitch... + } @if (data.hasPermissionToAccessAdminControl) { ... } - @if ( - dataSource?.data.length > 0 && - data.hasPermissionToReportDataGlitch === true - ) { - Report Data Glitch... - }
diff --git a/apps/client/src/app/components/home-watchlist/home-watchlist.component.ts b/apps/client/src/app/components/home-watchlist/home-watchlist.component.ts index 4c0b614c0..ab43e54dd 100644 --- a/apps/client/src/app/components/home-watchlist/home-watchlist.component.ts +++ b/apps/client/src/app/components/home-watchlist/home-watchlist.component.ts @@ -149,17 +149,17 @@ export class GfHomeWatchlistComponent implements OnDestroy, OnInit { .subscribe((user) => { this.user = user; - const dialogRef = this.dialog.open( + const dialogRef = this.dialog.open< GfCreateWatchlistItemDialogComponent, - { - autoFocus: false, - data: { - deviceType: this.deviceType, - locale: this.user?.settings?.locale - } as CreateWatchlistItemDialogParams, - width: this.deviceType === 'mobile' ? '100vw' : '50rem' - } - ); + CreateWatchlistItemDialogParams + >(GfCreateWatchlistItemDialogComponent, { + autoFocus: false, + data: { + deviceType: this.deviceType, + locale: this.user?.settings?.locale + }, + width: this.deviceType === 'mobile' ? '100vw' : '50rem' + }); dialogRef .afterClosed() diff --git a/apps/client/src/app/components/login-with-access-token-dialog/interfaces/interfaces.ts b/apps/client/src/app/components/login-with-access-token-dialog/interfaces/interfaces.ts new file mode 100644 index 000000000..2fa8b7ea4 --- /dev/null +++ b/apps/client/src/app/components/login-with-access-token-dialog/interfaces/interfaces.ts @@ -0,0 +1,5 @@ +export interface LoginWithAccessTokenDialogParams { + accessToken: string; + hasPermissionToUseSocialLogin: boolean; + title: string; +} diff --git a/apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.component.ts b/apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.component.ts index 3812a18b9..c0926150f 100644 --- a/apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.component.ts +++ b/apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.component.ts @@ -1,10 +1,8 @@ import { GfDialogHeaderComponent } from '@ghostfolio/client/components/dialog-header/dialog-header.component'; -import { InternetIdentityService } from '@ghostfolio/client/services/internet-identity.service'; import { KEY_STAY_SIGNED_IN, SettingsStorageService } from '@ghostfolio/client/services/settings-storage.service'; -import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service'; import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'; @@ -21,11 +19,12 @@ import { } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; -import { Router } from '@angular/router'; import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { eyeOffOutline, eyeOutline } from 'ionicons/icons'; +import { LoginWithAccessTokenDialogParams } from './interfaces/interfaces'; + @Component({ changeDetection: ChangeDetectionStrategy.OnPush, imports: [ @@ -51,12 +50,9 @@ export class GfLoginWithAccessTokenDialogComponent { public isAccessTokenHidden = true; public constructor( - @Inject(MAT_DIALOG_DATA) public data: any, + @Inject(MAT_DIALOG_DATA) public data: LoginWithAccessTokenDialogParams, public dialogRef: MatDialogRef, - private internetIdentityService: InternetIdentityService, - private router: Router, - private settingsStorageService: SettingsStorageService, - private tokenStorageService: TokenStorageService + private settingsStorageService: SettingsStorageService ) { addIcons({ eyeOffOutline, eyeOutline }); } @@ -79,14 +75,4 @@ export class GfLoginWithAccessTokenDialogComponent { }); } } - - public async onLoginWithInternetIdentity() { - try { - const { authToken } = await this.internetIdentityService.login(); - - this.tokenStorageService.saveToken(authToken); - this.dialogRef.close(); - this.router.navigate(['/']); - } catch {} - } } diff --git a/apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html b/apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html index b51802caf..15e68822a 100644 --- a/apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html +++ b/apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -26,17 +26,6 @@ @if (data.hasPermissionToUseSocialLogin) {
or
- (GfRuleSettingsDialogComponent, { data: { rule, categoryName: this.categoryName, + locale: this.locale, settings: this.settings - } as RuleSettingsDialogParams, + }, width: this.deviceType === 'mobile' ? '100vw' : '50rem' }); diff --git a/apps/client/src/app/components/rules/rules.component.html b/apps/client/src/app/components/rules/rules.component.html index d0cf7ece5..0c3153c52 100644 --- a/apps/client/src/app/components/rules/rules.component.html +++ b/apps/client/src/app/components/rules/rules.component.html @@ -12,6 +12,7 @@ [hasPermissionToUpdateUserSettings]=" hasPermissionToUpdateUserSettings " + [locale]="locale" [rule]="rule" [settings]="settings?.[rule.key]" (ruleUpdated)="onRuleUpdated($event)" diff --git a/apps/client/src/app/components/rules/rules.component.ts b/apps/client/src/app/components/rules/rules.component.ts index 6379a40fb..80a59740b 100644 --- a/apps/client/src/app/components/rules/rules.component.ts +++ b/apps/client/src/app/components/rules/rules.component.ts @@ -26,6 +26,7 @@ export class GfRulesComponent { @Input() categoryName: string; @Input() hasPermissionToUpdateUserSettings: boolean; @Input() isLoading: boolean; + @Input() locale: string; @Input() rules: PortfolioReportRule[]; @Input() settings: XRayRulesSettings; diff --git a/apps/client/src/app/components/user-account-access/user-account-access.component.ts b/apps/client/src/app/components/user-account-access/user-account-access.component.ts index bdb9af6ed..afcb9d9c8 100644 --- a/apps/client/src/app/components/user-account-access/user-account-access.component.ts +++ b/apps/client/src/app/components/user-account-access/user-account-access.component.ts @@ -31,6 +31,7 @@ import { EMPTY, Subject } from 'rxjs'; import { catchError, takeUntil } from 'rxjs/operators'; import { GfCreateOrUpdateAccessDialogComponent } from './create-or-update-access-dialog/create-or-update-access-dialog.component'; +import { CreateOrUpdateAccessDialogParams } from './create-or-update-access-dialog/interfaces/interfaces'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, @@ -187,10 +188,15 @@ export class GfUserAccountAccessComponent implements OnDestroy, OnInit { } private openCreateAccessDialog() { - const dialogRef = this.dialog.open(GfCreateOrUpdateAccessDialogComponent, { + const dialogRef = this.dialog.open< + GfCreateOrUpdateAccessDialogComponent, + CreateOrUpdateAccessDialogParams + >(GfCreateOrUpdateAccessDialogComponent, { data: { access: { alias: '', + grantee: null, + id: null, permissions: ['READ_RESTRICTED'], type: 'PRIVATE' } @@ -219,12 +225,15 @@ export class GfUserAccountAccessComponent implements OnDestroy, OnInit { return; } - const dialogRef = this.dialog.open(GfCreateOrUpdateAccessDialogComponent, { + const dialogRef = this.dialog.open< + GfCreateOrUpdateAccessDialogComponent, + CreateOrUpdateAccessDialogParams + >(GfCreateOrUpdateAccessDialogComponent, { data: { access: { alias: access.alias, - id: access.id, grantee: access.grantee === 'Public' ? null : access.grantee, + id: access.id, permissions: access.permissions, type: access.type } diff --git a/apps/client/src/app/components/user-detail-dialog/interfaces/interfaces.ts b/apps/client/src/app/components/user-detail-dialog/interfaces/interfaces.ts index 81cf84d12..d29bc01bc 100644 --- a/apps/client/src/app/components/user-detail-dialog/interfaces/interfaces.ts +++ b/apps/client/src/app/components/user-detail-dialog/interfaces/interfaces.ts @@ -1,7 +1,8 @@ -import { AdminUsers } from '@ghostfolio/common/interfaces'; +import { AdminUsersResponse } from '@ghostfolio/common/interfaces'; export interface UserDetailDialogParams { deviceType: string; + hasPermissionForSubscription: boolean; locale: string; - userData: AdminUsers['users'][0]; + userData: AdminUsersResponse['users'][0]; } diff --git a/apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html b/apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html index d90a6abf6..6bc468b59 100644 --- a/apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html +++ b/apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html @@ -8,9 +8,9 @@
- User ID + + User ID +
Registration Date + Registration Date +
+ +
+
+ + Role + +
+ @if (data.hasPermissionForSubscription) { +
+ + Country + +
+ } +
+ +
+
+ + Accounts + +
+
+ + Activities + +
+
+ + @if (data.hasPermissionForSubscription) { +
+
+ + Engagement per Day + +
+
+ + API Requests Today + +
+
+ }
diff --git a/apps/client/src/app/core/module-preload.service.ts b/apps/client/src/app/core/module-preload.service.ts index fcba48c52..85d9c5e33 100644 --- a/apps/client/src/app/core/module-preload.service.ts +++ b/apps/client/src/app/core/module-preload.service.ts @@ -7,7 +7,7 @@ export class ModulePreloadService implements PreloadingStrategy { /** * Preloads all lazy loading modules with the attribute 'preload' set to true */ - preload(route: Route, load: Function): Observable { + preload(route: Route, load: () => Observable): Observable { return route.data?.preload ? load() : of(null); } } diff --git a/apps/client/src/app/pages/about/overview/about-overview-page.html b/apps/client/src/app/pages/about/overview/about-overview-page.html index 4085498a9..185becba7 100644 --- a/apps/client/src/app/pages/about/overview/about-overview-page.html +++ b/apps/client/src/app/pages/about/overview/about-overview-page.html @@ -175,7 +175,7 @@ -
+ diff --git a/apps/client/src/app/pages/accounts/accounts-page.component.ts b/apps/client/src/app/pages/accounts/accounts-page.component.ts index f09901e45..3a1616b6f 100644 --- a/apps/client/src/app/pages/accounts/accounts-page.component.ts +++ b/apps/client/src/app/pages/accounts/accounts-page.component.ts @@ -23,6 +23,8 @@ import { EMPTY, Subject, Subscription } from 'rxjs'; import { catchError, takeUntil } from 'rxjs/operators'; import { GfCreateOrUpdateAccountDialogComponent } from './create-or-update-account-dialog/create-or-update-account-dialog.component'; +import { CreateOrUpdateAccountDialogParams } from './create-or-update-account-dialog/interfaces/interfaces'; +import { TransferBalanceDialogParams } from './transfer-balance/interfaces/interfaces'; import { GfTransferBalanceDialogComponent } from './transfer-balance/transfer-balance-dialog.component'; @Component({ @@ -179,7 +181,10 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit { name, platformId }: AccountModel) { - const dialogRef = this.dialog.open(GfCreateOrUpdateAccountDialogComponent, { + const dialogRef = this.dialog.open< + GfCreateOrUpdateAccountDialogComponent, + CreateOrUpdateAccountDialogParams + >(GfCreateOrUpdateAccountDialogComponent, { data: { account: { balance, @@ -227,7 +232,10 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit { } private openAccountDetailDialog(aAccountId: string) { - const dialogRef = this.dialog.open(GfAccountDetailDialogComponent, { + const dialogRef = this.dialog.open< + GfAccountDetailDialogComponent, + AccountDetailDialogParams + >(GfAccountDetailDialogComponent, { autoFocus: false, data: { accountId: aAccountId, @@ -237,7 +245,7 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit { !this.hasImpersonationId && hasPermission(this.user?.permissions, permissions.createOrder) && !this.user?.settings?.isRestrictedView - } as AccountDetailDialogParams, + }, height: this.deviceType === 'mobile' ? '98vh' : '80vh', width: this.deviceType === 'mobile' ? '100vw' : '50rem' }); @@ -253,12 +261,16 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit { } private openCreateAccountDialog() { - const dialogRef = this.dialog.open(GfCreateOrUpdateAccountDialogComponent, { + const dialogRef = this.dialog.open< + GfCreateOrUpdateAccountDialogComponent, + CreateOrUpdateAccountDialogParams + >(GfCreateOrUpdateAccountDialogComponent, { data: { account: { balance: 0, comment: null, currency: this.user?.settings?.baseCurrency, + id: null, isExcluded: false, name: null, platformId: null @@ -295,7 +307,10 @@ export class GfAccountsPageComponent implements OnDestroy, OnInit { } private openTransferBalanceDialog() { - const dialogRef = this.dialog.open(GfTransferBalanceDialogComponent, { + const dialogRef = this.dialog.open< + GfTransferBalanceDialogComponent, + TransferBalanceDialogParams + >(GfTransferBalanceDialogComponent, { data: { accounts: this.accounts }, diff --git a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/interfaces/interfaces.ts b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/interfaces/interfaces.ts index ffe4f14f6..a3e6272f8 100644 --- a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/interfaces/interfaces.ts +++ b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/interfaces/interfaces.ts @@ -1,5 +1,5 @@ import { Account } from '@prisma/client'; export interface CreateOrUpdateAccountDialogParams { - account: Account; + account: Omit; } diff --git a/apps/client/src/app/pages/home/home-page.component.ts b/apps/client/src/app/pages/home/home-page.component.ts index eb1ad62d9..fd860ced5 100644 --- a/apps/client/src/app/pages/home/home-page.component.ts +++ b/apps/client/src/app/pages/home/home-page.component.ts @@ -16,11 +16,11 @@ import { RouterModule } from '@angular/router'; import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; import { + albumsOutline, analyticsOutline, bookmarkOutline, newspaperOutline, - readerOutline, - walletOutline + readerOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject } from 'rxjs'; @@ -61,7 +61,7 @@ export class GfHomePageComponent implements OnDestroy, OnInit { routerLink: internalRoutes.home.routerLink }, { - iconName: 'wallet-outline', + iconName: 'albums-outline', label: internalRoutes.home.subRoutes.holdings.title, routerLink: internalRoutes.home.subRoutes.holdings.routerLink }, @@ -97,11 +97,11 @@ export class GfHomePageComponent implements OnDestroy, OnInit { }); addIcons({ + albumsOutline, analyticsOutline, bookmarkOutline, newspaperOutline, - readerOutline, - walletOutline + readerOutline }); } diff --git a/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts b/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts index ce99fbf77..6ee02bd8e 100644 --- a/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts +++ b/apps/client/src/app/pages/portfolio/activities/activities-page.component.ts @@ -28,6 +28,7 @@ import { Subject, Subscription } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { GfCreateOrUpdateActivityDialogComponent } from './create-or-update-activity-dialog/create-or-update-activity-dialog.component'; +import { CreateOrUpdateActivityDialogParams } from './create-or-update-activity-dialog/interfaces/interfaces'; import { GfImportActivitiesDialogComponent } from './import-activities-dialog/import-activities-dialog.component'; import { ImportActivitiesDialogParams } from './import-activities-dialog/interfaces/interfaces'; @@ -245,11 +246,14 @@ export class GfActivitiesPageComponent implements OnDestroy, OnInit { } public onImport() { - const dialogRef = this.dialog.open(GfImportActivitiesDialogComponent, { + const dialogRef = this.dialog.open< + GfImportActivitiesDialogComponent, + ImportActivitiesDialogParams + >(GfImportActivitiesDialogComponent, { data: { deviceType: this.deviceType, user: this.user - } as ImportActivitiesDialogParams, + }, height: this.deviceType === 'mobile' ? '98vh' : undefined, width: this.deviceType === 'mobile' ? '100vw' : '50rem' }); @@ -268,12 +272,15 @@ export class GfActivitiesPageComponent implements OnDestroy, OnInit { } public onImportDividends() { - const dialogRef = this.dialog.open(GfImportActivitiesDialogComponent, { + const dialogRef = this.dialog.open< + GfImportActivitiesDialogComponent, + ImportActivitiesDialogParams + >(GfImportActivitiesDialogComponent, { data: { activityTypes: ['DIVIDEND'], deviceType: this.deviceType, user: this.user - } as ImportActivitiesDialogParams, + }, height: this.deviceType === 'mobile' ? '98vh' : undefined, width: this.deviceType === 'mobile' ? '100vw' : '50rem' }); @@ -306,18 +313,18 @@ export class GfActivitiesPageComponent implements OnDestroy, OnInit { } public openUpdateActivityDialog(aActivity: Activity) { - const dialogRef = this.dialog.open( + const dialogRef = this.dialog.open< GfCreateOrUpdateActivityDialogComponent, - { - data: { - activity: aActivity, - accounts: this.user?.accounts, - user: this.user - }, - height: this.deviceType === 'mobile' ? '98vh' : '80vh', - width: this.deviceType === 'mobile' ? '100vw' : '50rem' - } - ); + CreateOrUpdateActivityDialogParams + >(GfCreateOrUpdateActivityDialogComponent, { + data: { + activity: aActivity, + accounts: this.user?.accounts, + user: this.user + }, + height: this.deviceType === 'mobile' ? '98vh' : '80vh', + width: this.deviceType === 'mobile' ? '100vw' : '50rem' + }); dialogRef .afterClosed() @@ -350,26 +357,26 @@ export class GfActivitiesPageComponent implements OnDestroy, OnInit { .subscribe((user) => { this.updateUser(user); - const dialogRef = this.dialog.open( + const dialogRef = this.dialog.open< GfCreateOrUpdateActivityDialogComponent, - { - data: { - accounts: this.user?.accounts, - activity: { - ...aActivity, - accountId: aActivity?.accountId, - date: new Date(), - id: null, - fee: 0, - type: aActivity?.type ?? 'BUY', - unitPrice: null - }, - user: this.user + CreateOrUpdateActivityDialogParams + >(GfCreateOrUpdateActivityDialogComponent, { + data: { + accounts: this.user?.accounts, + activity: { + ...aActivity, + accountId: aActivity?.accountId, + date: new Date(), + id: null, + fee: 0, + type: aActivity?.type ?? 'BUY', + unitPrice: null }, - height: this.deviceType === 'mobile' ? '98vh' : '80vh', - width: this.deviceType === 'mobile' ? '100vw' : '50rem' - } - ); + user: this.user + }, + height: this.deviceType === 'mobile' ? '98vh' : '80vh', + width: this.deviceType === 'mobile' ? '100vw' : '50rem' + }); dialogRef .afterClosed() diff --git a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/interfaces/interfaces.ts b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/interfaces/interfaces.ts index 60a39d361..cc454a66a 100644 --- a/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/interfaces/interfaces.ts +++ b/apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/interfaces/interfaces.ts @@ -4,7 +4,6 @@ import { User } from '@ghostfolio/common/interfaces'; import { Account } from '@prisma/client'; export interface CreateOrUpdateActivityDialogParams { - accountId: string; accounts: Account[]; activity: Activity; user: User; diff --git a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/interfaces/interfaces.ts b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/interfaces/interfaces.ts index a2131db88..051345e60 100644 --- a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/interfaces/interfaces.ts +++ b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/interfaces/interfaces.ts @@ -3,7 +3,7 @@ import { User } from '@ghostfolio/common/interfaces'; import { Type } from '@prisma/client'; export interface ImportActivitiesDialogParams { - activityTypes: Type[]; + activityTypes?: Type[]; deviceType: string; user: User; } diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts index da909a78d..b4de51701 100644 --- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts +++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts @@ -558,7 +558,10 @@ export class GfAllocationsPageComponent implements OnDestroy, OnInit { } private openAccountDetailDialog(aAccountId: string) { - const dialogRef = this.dialog.open(GfAccountDetailDialogComponent, { + const dialogRef = this.dialog.open< + GfAccountDetailDialogComponent, + AccountDetailDialogParams + >(GfAccountDetailDialogComponent, { autoFocus: false, data: { accountId: aAccountId, @@ -568,7 +571,7 @@ export class GfAllocationsPageComponent implements OnDestroy, OnInit { !this.hasImpersonationId && hasPermission(this.user?.permissions, permissions.createOrder) && !this.user?.settings?.isRestrictedView - } as AccountDetailDialogParams, + }, height: this.deviceType === 'mobile' ? '98vh' : '80vh', width: this.deviceType === 'mobile' ? '100vw' : '50rem' }); diff --git a/apps/client/src/app/pages/portfolio/fire/fire-page.scss b/apps/client/src/app/pages/portfolio/fire/fire-page.scss index 2892885c9..3a0618ed6 100644 --- a/apps/client/src/app/pages/portfolio/fire/fire-page.scss +++ b/apps/client/src/app/pages/portfolio/fire/fire-page.scss @@ -1,9 +1,21 @@ +@use '../../../../styles/variables.scss' as variables; + +@mixin select-arrow($color) { + background-image: url("data:image/svg+xml;utf8,"); +} + :host { display: block; .safe-withdrawal-rate-select { + @include select-arrow(variables.$dark-primary-text); + + appearance: none; background-color: transparent; + background-position: right 0 center; + background-repeat: no-repeat; color: rgb(var(--dark-primary-text)); + padding: 0 0.75rem 0 0.25rem; &:focus { box-shadow: none; @@ -14,6 +26,8 @@ :host-context(.theme-dark) { .safe-withdrawal-rate-select { + @include select-arrow(variables.$light-primary-text); + color: rgb(var(--light-primary-text)); } } diff --git a/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html b/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html index d4820b59e..af74137d1 100644 --- a/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html +++ b/apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html @@ -76,6 +76,7 @@ !hasImpersonationId && hasPermissionToUpdateUserSettings " [isLoading]="isLoading" + [locale]="user?.settings?.locale" [rules]="category.rules" [settings]="user?.settings?.xRayRules" (rulesUpdated)="onRulesUpdated($event)" @@ -90,6 +91,7 @@ !hasImpersonationId && hasPermissionToUpdateUserSettings " [isLoading]="isLoading" + [locale]="user?.settings?.locale" [rules]="inactiveRules" [settings]="user?.settings?.xRayRules" (rulesUpdated)="onRulesUpdated($event)" diff --git a/apps/client/src/app/pages/register/register-page.component.ts b/apps/client/src/app/pages/register/register-page.component.ts index eff4e308b..78162487d 100644 --- a/apps/client/src/app/pages/register/register-page.component.ts +++ b/apps/client/src/app/pages/register/register-page.component.ts @@ -1,5 +1,4 @@ import { DataService } from '@ghostfolio/client/services/data.service'; -import { InternetIdentityService } from '@ghostfolio/client/services/internet-identity.service'; import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service'; import { InfoItem, LineChartItem } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; @@ -43,7 +42,6 @@ export class GfRegisterPageComponent implements OnDestroy, OnInit { private dataService: DataService, private deviceService: DeviceDetectorService, private dialog: MatDialog, - private internetIdentityService: InternetIdentityService, private router: Router, private tokenStorageService: TokenStorageService ) { @@ -73,29 +71,19 @@ export class GfRegisterPageComponent implements OnDestroy, OnInit { ); } - public async onLoginWithInternetIdentity() { - try { - const { authToken } = await this.internetIdentityService.login(); - - this.tokenStorageService.saveToken(authToken); - - await this.router.navigate(['/']); - } catch {} - } - public openShowAccessTokenDialog() { - const dialogRef = this.dialog.open( + const dialogRef = this.dialog.open< GfUserAccountRegistrationDialogComponent, - { - data: { - deviceType: this.deviceType, - needsToAcceptTermsOfService: this.hasPermissionForSubscription - } as UserAccountRegistrationDialogParams, - disableClose: true, - height: this.deviceType === 'mobile' ? '98vh' : undefined, - width: this.deviceType === 'mobile' ? '100vw' : '30rem' - } - ); + UserAccountRegistrationDialogParams + >(GfUserAccountRegistrationDialogComponent, { + data: { + deviceType: this.deviceType, + needsToAcceptTermsOfService: this.hasPermissionForSubscription + }, + disableClose: true, + height: this.deviceType === 'mobile' ? '98vh' : undefined, + width: this.deviceType === 'mobile' ? '100vw' : '30rem' + }); dialogRef .afterClosed() diff --git a/apps/client/src/app/pages/register/register-page.html b/apps/client/src/app/pages/register/register-page.html index eee49083a..de53777fa 100644 --- a/apps/client/src/app/pages/register/register-page.html +++ b/apps/client/src/app/pages/register/register-page.html @@ -28,20 +28,6 @@ @if (hasPermissionForSocialLogin) {
or
- @if (false) { - - }
-

Buy and Hold

+

Buy and Hold

Buy and hold is a passive investment strategy where you buy assets and hold them for a long period regardless of fluctuations in the @@ -22,7 +22,7 @@
-

Deflation

+

Deflation

Deflation is a decrease of the general price level for goods and services in an economy over a period of time. @@ -38,7 +38,7 @@
-

Dollar-Cost Averaging (DCA)

+

Dollar-Cost Averaging (DCA)

Dollar-cost averaging is an investment strategy where you split the total amount to be invested across periodic purchases of a @@ -56,7 +56,7 @@
-

Financial Independence

+

Financial Independence

Financial independence is the status of having enough income, for example with a passive income like dividends, to cover your living @@ -73,7 +73,7 @@
-

FIRE

+

FIRE

FIRE is a movement that promotes saving and investing to achieve financial independence and early retirement. @@ -85,7 +85,7 @@
-

Inflation

+

Inflation

Inflation is an increase of the general price level for goods and services in an economy over a period of time. @@ -102,7 +102,7 @@ @if (hasPermissionForSubscription) {
-

Personal Finance Tools

+

Personal Finance Tools

Personal finance tools are software applications that help manage your money, track expenses, set budgets, monitor @@ -118,7 +118,7 @@ }
-

Stagflation

+

Stagflation

Stagflation describes a situation in which there is a stagnant economy with high unemployment and high inflation. @@ -134,7 +134,7 @@
-

Stealth Wealth

+

Stealth Wealth

Stealth wealth is a lifestyle choice where you don’t openly show off your wealth, but instead live quietly to maintain privacy and diff --git a/apps/client/src/app/pages/resources/guides/resources-guides.component.html b/apps/client/src/app/pages/resources/guides/resources-guides.component.html index 3bd8efec6..54b3d1f3e 100644 --- a/apps/client/src/app/pages/resources/guides/resources-guides.component.html +++ b/apps/client/src/app/pages/resources/guides/resources-guides.component.html @@ -5,7 +5,7 @@
-

Boringly Getting Rich

+

Boringly Getting Rich

The Boringly Getting Rich guide supports you to get started with investing. It introduces a strategy utilizing a broadly @@ -21,7 +21,7 @@
-

How do I get my finances in order?

+

How do I get my finances in order?

Before you can think of long-term investing, you have to get your finances in order. Learn how you can reach your financial goals diff --git a/apps/client/src/app/pages/resources/markets/resources-markets.component.html b/apps/client/src/app/pages/resources/markets/resources-markets.component.html index 74d4bb82b..ce780aedf 100644 --- a/apps/client/src/app/pages/resources/markets/resources-markets.component.html +++ b/apps/client/src/app/pages/resources/markets/resources-markets.component.html @@ -3,7 +3,7 @@
-

Crypto Coins Heatmap

+

Crypto Coins Heatmap

With the Crypto Coins Heatmap you can track the daily market movements of cryptocurrencies as a visual snapshot. @@ -17,7 +17,7 @@
-

Fear & Greed Index

+

Fear & Greed Index

The fear and greed index was developed by CNNMoney to measure the primary emotions (fear and greed) that influence how much @@ -32,7 +32,7 @@
-

Inflation Chart

+

Inflation Chart

Inflation Chart helps you find the intrinsic value of stock markets, stock prices, goods and services by adjusting them to the @@ -48,7 +48,7 @@
-

Stock Heatmap

+

Stock Heatmap

With the Stock Heatmap you can track the daily market movements of stocks as a visual snapshot. diff --git a/apps/client/src/app/pages/resources/overview/resources-overview.component.html b/apps/client/src/app/pages/resources/overview/resources-overview.component.html index 39d7c1e62..3a6f18d40 100644 --- a/apps/client/src/app/pages/resources/overview/resources-overview.component.html +++ b/apps/client/src/app/pages/resources/overview/resources-overview.component.html @@ -5,7 +5,7 @@
@for (item of overviewItems; track item) {
-

{{ item.title }}

+

{{ item.title }}

{{ item.description }}

Explore {{ item.title }} →
diff --git a/apps/client/src/app/pages/zen/zen-page.component.ts b/apps/client/src/app/pages/zen/zen-page.component.ts index 0224c13c7..5ed9fe09c 100644 --- a/apps/client/src/app/pages/zen/zen-page.component.ts +++ b/apps/client/src/app/pages/zen/zen-page.component.ts @@ -8,7 +8,7 @@ import { MatTabsModule } from '@angular/material/tabs'; import { RouterModule } from '@angular/router'; import { IonIcon } from '@ionic/angular/standalone'; import { addIcons } from 'ionicons'; -import { analyticsOutline, walletOutline } from 'ionicons/icons'; +import { albumsOutline, analyticsOutline } from 'ionicons/icons'; import { DeviceDetectorService } from 'ngx-device-detector'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @@ -43,7 +43,7 @@ export class GfZenPageComponent implements OnDestroy, OnInit { routerLink: internalRoutes.zen.routerLink }, { - iconName: 'wallet-outline', + iconName: 'albums-outline', label: internalRoutes.zen.subRoutes.holdings.title, routerLink: internalRoutes.zen.subRoutes.holdings.routerLink } @@ -54,7 +54,7 @@ export class GfZenPageComponent implements OnDestroy, OnInit { } }); - addIcons({ analyticsOutline, walletOutline }); + addIcons({ albumsOutline, analyticsOutline }); } public ngOnInit() { diff --git a/apps/client/src/app/services/admin.service.ts b/apps/client/src/app/services/admin.service.ts index a04ad8d56..2f3040ba3 100644 --- a/apps/client/src/app/services/admin.service.ts +++ b/apps/client/src/app/services/admin.service.ts @@ -12,7 +12,7 @@ import { AdminData, AdminJobs, AdminMarketData, - AdminUsers, + AdminUsersResponse, DataProviderGhostfolioStatusResponse, EnhancedSymbolProfile, Filter @@ -154,7 +154,7 @@ export class AdminService { params = params.append('skip', skip); params = params.append('take', take); - return this.http.get('/api/v1/admin/user', { params }); + return this.http.get('/api/v1/admin/user', { params }); } public gather7Days() { diff --git a/apps/client/src/app/services/internet-identity.service.ts b/apps/client/src/app/services/internet-identity.service.ts deleted file mode 100644 index 30ae13679..000000000 --- a/apps/client/src/app/services/internet-identity.service.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { OAuthResponse } from '@ghostfolio/common/interfaces'; - -import { HttpClient } from '@angular/common/http'; -import { Injectable, OnDestroy } from '@angular/core'; -import { AuthClient } from '@dfinity/auth-client'; -import { EMPTY, Subject } from 'rxjs'; -import { catchError, takeUntil } from 'rxjs/operators'; - -@Injectable({ - providedIn: 'root' -}) -export class InternetIdentityService implements OnDestroy { - private unsubscribeSubject = new Subject(); - - public constructor(private http: HttpClient) {} - - public async login(): Promise { - const authClient = await AuthClient.create({ - idleOptions: { - disableDefaultIdleCallback: true, - disableIdle: true - } - }); - - return new Promise((resolve, reject) => { - authClient.login({ - onError: async () => { - return reject(); - }, - onSuccess: () => { - const principalId = authClient.getIdentity().getPrincipal(); - - this.http - .post(`/api/v1/auth/internet-identity`, { - principalId: principalId.toText() - }) - .pipe( - catchError(() => { - reject(); - return EMPTY; - }), - takeUntil(this.unsubscribeSubject) - ) - .subscribe((response) => { - resolve(response); - }); - } - }); - }); - } - - public ngOnDestroy() { - this.unsubscribeSubject.next(); - this.unsubscribeSubject.complete(); - } -} diff --git a/apps/client/src/app/services/user/user.service.ts b/apps/client/src/app/services/user/user.service.ts index f52a52975..bd9d7d04c 100644 --- a/apps/client/src/app/services/user/user.service.ts +++ b/apps/client/src/app/services/user/user.service.ts @@ -116,18 +116,18 @@ export class UserService extends ObservableStore { permissions.enableSubscriptionInterstitial ) ) { - const dialogRef = this.dialog.open( + const dialogRef = this.dialog.open< GfSubscriptionInterstitialDialogComponent, - { - autoFocus: false, - data: { - user - } as SubscriptionInterstitialDialogParams, - disableClose: true, - height: this.deviceType === 'mobile' ? '98vh' : '80vh', - width: this.deviceType === 'mobile' ? '100vw' : '50rem' - } - ); + SubscriptionInterstitialDialogParams + >(GfSubscriptionInterstitialDialogComponent, { + autoFocus: false, + data: { + user + }, + disableClose: true, + height: this.deviceType === 'mobile' ? '98vh' : '80vh', + width: this.deviceType === 'mobile' ? '100vw' : '50rem' + }); dialogRef .afterClosed() diff --git a/apps/client/src/assets/icons/internet-computer.svg b/apps/client/src/assets/icons/internet-computer.svg deleted file mode 100644 index 6a1bf6c86..000000000 --- a/apps/client/src/assets/icons/internet-computer.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/apps/client/src/assets/images/sponsors/logo-lambdatest.png b/apps/client/src/assets/images/sponsors/logo-lambdatest.png new file mode 100644 index 000000000..9e05b1cde Binary files /dev/null and b/apps/client/src/assets/images/sponsors/logo-lambdatest.png differ diff --git a/apps/client/src/assets/oss-friends.json b/apps/client/src/assets/oss-friends.json index 827b56c3a..2fbf5e27d 100644 --- a/apps/client/src/assets/oss-friends.json +++ b/apps/client/src/assets/oss-friends.json @@ -1,5 +1,5 @@ { - "createdAt": "2025-09-17T00:00:00.000Z", + "createdAt": "2025-10-31T00:00:00.000Z", "data": [ { "name": "Activepieces", @@ -16,6 +16,11 @@ "description": "Argos provides the developer tools to debug tests and detect visual regressions.", "href": "https://argos-ci.com" }, + { + "name": "Bifrost", + "description": "Fastest LLM gateway with adaptive load balancer, cluster mode, guardrails, 1000+ models support & <100 µs overhead at 5k RPS.", + "href": "https://www.getmaxim.ai/bifrost" + }, { "name": "Cal.com", "description": "Cal.com is a scheduling tool that helps you schedule meetings without the back-and-forth emails.", @@ -56,11 +61,6 @@ "description": "Inbox Zero makes it easy to clean up your inbox and reach inbox zero fast. It provides bulk newsletter unsubscribe, cold email blocking, email analytics, and AI automations.", "href": "https://getinboxzero.com" }, - { - "name": "Infisical", - "description": "Open source, end-to-end encrypted platform that lets you securely manage secrets and configs across your team, devices, and infrastructure.", - "href": "https://infisical.com" - }, { "name": "KeepHQ", "description": "Keep is an open-source AIOps (AI for IT operations) platform", diff --git a/apps/client/src/locales/messages.ca.xlf b/apps/client/src/locales/messages.ca.xlf index c68b369d4..7c676e092 100644 --- a/apps/client/src/locales/messages.ca.xlf +++ b/apps/client/src/locales/messages.ca.xlf @@ -38,7 +38,7 @@ apps/client/src/app/components/header/header.component.ts - 279 + 283 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -603,7 +603,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 443 + 451 @@ -639,7 +639,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 470 + 478 libs/ui/src/lib/benchmark/benchmark.component.html @@ -1366,6 +1366,14 @@ 200 + + Activities + Activities + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 61 + + Add Platform Afegeix Plataforma @@ -1379,7 +1387,7 @@ Està segur que vol eliminar aquesta plataforma? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 107 + 108 @@ -1443,7 +1451,7 @@ Està segur que vol eliminar aquesta etiqueta? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 104 @@ -1651,11 +1659,11 @@ Oooh! El testimoni de seguretat és incorrecte. apps/client/src/app/components/header/header.component.ts - 294 + 298 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 153 + 154 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts @@ -1739,7 +1747,7 @@ Informar d’un Problema amb les Dades apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 452 + 450 @@ -2409,10 +2417,6 @@ apps/client/src/app/components/user-account-settings/user-account-settings.html 252 - - apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 12 - Granted Access @@ -2891,7 +2895,7 @@ Vaja, la transferència del saldo en efectiu ha fallat. apps/client/src/app/pages/accounts/accounts-page.component.ts - 324 + 339 @@ -4451,6 +4455,14 @@ 91 + + Close Holding + Close Holding + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 441 + + Absolute Asset Performance Rendiment absolut dels actius @@ -5112,6 +5124,14 @@ 210 + + User ID + User ID + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 12 + + Free Plan Pla gratuït @@ -5305,7 +5325,7 @@ Clonar libs/ui/src/lib/activities-table/activities-table.component.html - 449 + 457 @@ -5313,7 +5333,7 @@ Exporta l’esborrany com a ICS libs/ui/src/lib/activities-table/activities-table.component.html - 459 + 467 @@ -5321,7 +5341,7 @@ De veritat vols suprimir aquestes activitats? libs/ui/src/lib/activities-table/activities-table.component.ts - 270 + 276 @@ -5329,7 +5349,7 @@ Realment vols suprimir aquesta activitat? libs/ui/src/lib/activities-table/activities-table.component.ts - 280 + 286 @@ -6408,6 +6428,14 @@ 83 + + View Holding + View Holding + + libs/ui/src/lib/activities-table/activities-table.component.html + 444 + + Canada Canada @@ -6565,7 +6593,7 @@ Inactive apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 87 + 88 @@ -6668,6 +6696,14 @@ 11 + + Role + Role + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 31 + + Yes Yes @@ -6679,6 +6715,10 @@ Accounts Accounts + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 51 + libs/ui/src/lib/assistant/assistant.html 84 @@ -6972,6 +7012,14 @@ 293 + + Engagement per Day + Engagement per Day + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 76 + + Guides Guides @@ -7110,6 +7158,14 @@ 167 + + Country + Country + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 37 + + API Key API Key @@ -7199,7 +7255,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 251 + 260 @@ -7258,6 +7314,14 @@ 234 + + API Requests Today + API Requests Today + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 86 + + Default Market Price Default Market Price @@ -7455,7 +7519,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 169 + 170 @@ -8072,7 +8136,7 @@ Do you really want to generate a new security token? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 174 + 175 @@ -8128,7 +8192,7 @@ Manage Asset Profile apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 442 + 465 @@ -8152,7 +8216,7 @@ Average Unit Price apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts - 111 + 113 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -8543,12 +8607,12 @@ 128 - + Registration Date Registration Date apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 22 + 23 diff --git a/apps/client/src/locales/messages.de.xlf b/apps/client/src/locales/messages.de.xlf index 2db1d100f..fa47cc6a6 100644 --- a/apps/client/src/locales/messages.de.xlf +++ b/apps/client/src/locales/messages.de.xlf @@ -242,7 +242,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 443 + 451 @@ -278,7 +278,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 470 + 478 libs/ui/src/lib/benchmark/benchmark.component.html @@ -633,6 +633,14 @@ 200 + + Activities + Aktivitäten + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 61 + + Do you really want to delete this user? Möchtest du diesen Benutzer wirklich löschen? @@ -710,7 +718,7 @@ apps/client/src/app/components/header/header.component.ts - 279 + 283 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -730,11 +738,11 @@ Ups! Falsches Sicherheits-Token. apps/client/src/app/components/header/header.component.ts - 294 + 298 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 153 + 154 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts @@ -982,7 +990,7 @@ Datenfehler melden apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 452 + 450 @@ -1280,10 +1288,6 @@ apps/client/src/app/components/user-account-settings/user-account-settings.html 252 - - apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 12 - Granted Access @@ -2238,7 +2242,7 @@ Kopieren libs/ui/src/lib/activities-table/activities-table.component.html - 449 + 457 @@ -2246,7 +2250,7 @@ Geplante Aktivität als ICS exportieren libs/ui/src/lib/activities-table/activities-table.component.html - 459 + 467 @@ -2254,7 +2258,7 @@ Möchtest du diese Aktivität wirklich löschen? libs/ui/src/lib/activities-table/activities-table.component.ts - 280 + 286 @@ -3746,7 +3750,7 @@ Möchtest du diese Aktivitäten wirklich löschen? libs/ui/src/lib/activities-table/activities-table.component.ts - 270 + 276 @@ -3806,7 +3810,7 @@ Möchtest du diese Plattform wirklich löschen? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 107 + 108 @@ -4313,6 +4317,14 @@ 210 + + User ID + Benutzer ID + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 12 + + Free Plan Kostenlose Nutzung @@ -5364,7 +5376,7 @@ Möchtest du diesen Tag wirklich löschen? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 104 @@ -5556,7 +5568,7 @@ Ups, der Cash-Bestand Transfer ist fehlgeschlagen. apps/client/src/app/pages/accounts/accounts-page.component.ts - 324 + 339 @@ -5771,6 +5783,14 @@ 364 + + Close Holding + Position abschliessen + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 441 + + Absolute Asset Performance Absolute Anlage Performance @@ -6432,6 +6452,14 @@ 83 + + View Holding + Position ansehen + + libs/ui/src/lib/activities-table/activities-table.component.html + 444 + + Canada Kanada @@ -6589,7 +6617,7 @@ Inaktiv apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 87 + 88 @@ -6692,6 +6720,14 @@ 11 + + Role + Rolle + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 31 + + Yes Ja @@ -6703,6 +6739,10 @@ Accounts Konten + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 51 + libs/ui/src/lib/assistant/assistant.html 84 @@ -6996,6 +7036,14 @@ 293 + + Engagement per Day + Engagement pro Tag + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 76 + + Guides Ratgeber @@ -7134,6 +7182,14 @@ 167 + + Country + Land + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 37 + + API Key API-Schlüssel @@ -7223,7 +7279,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 251 + 260 @@ -7282,6 +7338,14 @@ 234 + + API Requests Today + Heutige API Anfragen + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 86 + + Default Market Price Standardmarktpreis @@ -7479,7 +7543,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 169 + 170 @@ -8072,7 +8136,7 @@ Möchtest du wirklich ein neues Sicherheits-Token generieren? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 174 + 175 @@ -8128,7 +8192,7 @@ Anlageprofil verwalten apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 442 + 465 @@ -8152,7 +8216,7 @@ Ø Preis pro Einheit apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts - 111 + 113 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -8543,12 +8607,12 @@ 128 - + Registration Date Registrierungsdatum apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 22 + 23 diff --git a/apps/client/src/locales/messages.es.xlf b/apps/client/src/locales/messages.es.xlf index 29746f597..4c380b007 100644 --- a/apps/client/src/locales/messages.es.xlf +++ b/apps/client/src/locales/messages.es.xlf @@ -243,7 +243,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 443 + 451 @@ -279,7 +279,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 470 + 478 libs/ui/src/lib/benchmark/benchmark.component.html @@ -618,6 +618,14 @@ 200 + + Activities + Activities + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 61 + + Do you really want to delete this user? ¿Estás seguro de eliminar este usuario? @@ -695,7 +703,7 @@ apps/client/src/app/components/header/header.component.ts - 279 + 283 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -715,11 +723,11 @@ Vaya! Token de seguridad incorrecto. apps/client/src/app/components/header/header.component.ts - 294 + 298 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 153 + 154 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts @@ -967,7 +975,7 @@ Reporta un anomalía de los datos apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 452 + 450 @@ -1265,10 +1273,6 @@ apps/client/src/app/components/user-account-settings/user-account-settings.html 252 - - apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 12 - Granted Access @@ -2223,7 +2227,7 @@ Clonar libs/ui/src/lib/activities-table/activities-table.component.html - 449 + 457 @@ -2231,7 +2235,7 @@ Exportar borrador como ICS libs/ui/src/lib/activities-table/activities-table.component.html - 459 + 467 @@ -2239,7 +2243,7 @@ ¿Estás seguro de eliminar esta operación? libs/ui/src/lib/activities-table/activities-table.component.ts - 280 + 286 @@ -3723,7 +3727,7 @@ ¿Realmente deseas eliminar estas actividades? libs/ui/src/lib/activities-table/activities-table.component.ts - 270 + 276 @@ -3783,7 +3787,7 @@ ¿Realmente deseas eliminar esta plataforma? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 107 + 108 @@ -4290,6 +4294,14 @@ 210 + + User ID + User ID + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 12 + + Free Plan Plan gratuito @@ -5341,7 +5353,7 @@ ¿Realmente deseas eliminar esta etiqueta? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 104 @@ -5533,7 +5545,7 @@ Oops, el saldo de efectivo no se ha transferido. apps/client/src/app/pages/accounts/accounts-page.component.ts - 324 + 339 @@ -5748,6 +5760,14 @@ 364 + + Close Holding + Close Holding + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 441 + + Absolute Asset Performance Rendimiento absoluto de los activos @@ -6409,6 +6429,14 @@ 83 + + View Holding + View Holding + + libs/ui/src/lib/activities-table/activities-table.component.html + 444 + + Canada Canadá @@ -6566,7 +6594,7 @@ Inactiva apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 87 + 88 @@ -6669,6 +6697,14 @@ 11 + + Role + Role + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 31 + + Yes @@ -6680,6 +6716,10 @@ Accounts Accounts + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 51 + libs/ui/src/lib/assistant/assistant.html 84 @@ -6973,6 +7013,14 @@ 293 + + Engagement per Day + Engagement per Day + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 76 + + Guides Guías @@ -7111,6 +7159,14 @@ 167 + + Country + Country + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 37 + + API Key Clave API @@ -7200,7 +7256,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 251 + 260 @@ -7259,6 +7315,14 @@ 234 + + API Requests Today + API Requests Today + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 86 + + Default Market Price Precio de mercado por defecto @@ -7456,7 +7520,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 169 + 170 @@ -8073,7 +8137,7 @@ ¿Realmente deseas generar un nuevo token de seguridad? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 174 + 175 @@ -8129,7 +8193,7 @@ Gestionar perfil de activo apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 442 + 465 @@ -8153,7 +8217,7 @@ Precio medio por unidad apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts - 111 + 113 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -8544,12 +8608,12 @@ 128 - + Registration Date Registration Date apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 22 + 23 diff --git a/apps/client/src/locales/messages.fr.xlf b/apps/client/src/locales/messages.fr.xlf index 9b40a3031..b25a87570 100644 --- a/apps/client/src/locales/messages.fr.xlf +++ b/apps/client/src/locales/messages.fr.xlf @@ -298,7 +298,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 443 + 451 @@ -334,7 +334,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 470 + 478 libs/ui/src/lib/benchmark/benchmark.component.html @@ -825,6 +825,14 @@ 200 + + Activities + Activities + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 61 + + Do you really want to delete this user? Voulez-vous vraiment supprimer cet·te utilisateur·rice ? @@ -942,7 +950,7 @@ apps/client/src/app/components/header/header.component.ts - 279 + 283 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -962,11 +970,11 @@ Oups! Jeton de Sécurité Incorrect. apps/client/src/app/components/header/header.component.ts - 294 + 298 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 153 + 154 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts @@ -1254,7 +1262,7 @@ Signaler une Erreur de Données apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 452 + 450 @@ -1612,10 +1620,6 @@ apps/client/src/app/components/user-account-settings/user-account-settings.html 252 - - apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 12 - Granted Access @@ -2698,7 +2702,7 @@ Dupliquer libs/ui/src/lib/activities-table/activities-table.component.html - 449 + 457 @@ -2706,7 +2710,7 @@ Exporter Brouillon sous ICS libs/ui/src/lib/activities-table/activities-table.component.html - 459 + 467 @@ -2714,7 +2718,7 @@ Voulez-vous vraiment supprimer cette activité ? libs/ui/src/lib/activities-table/activities-table.component.ts - 280 + 286 @@ -3722,7 +3726,7 @@ Voulez-vous vraiment supprimer toutes vos activités ? libs/ui/src/lib/activities-table/activities-table.component.ts - 270 + 276 @@ -3782,7 +3786,7 @@ Voulez-vous vraiment supprimer cette plateforme ? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 107 + 108 @@ -4289,6 +4293,14 @@ 210 + + User ID + User ID + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 12 + + Free Plan Plan gratuit @@ -5340,7 +5352,7 @@ Confirmez la suppression de ce tag ? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 104 @@ -5532,7 +5544,7 @@ Oops, échec du transfert de la cash balance. apps/client/src/app/pages/accounts/accounts-page.component.ts - 324 + 339 @@ -5747,6 +5759,14 @@ 364 + + Close Holding + Close Holding + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 441 + + Absolute Asset Performance Performance des Actifs en valeur absolue @@ -6408,6 +6428,14 @@ 83 + + View Holding + View Holding + + libs/ui/src/lib/activities-table/activities-table.component.html + 444 + + Canada Canada @@ -6565,7 +6593,7 @@ Inactif apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 87 + 88 @@ -6668,6 +6696,14 @@ 11 + + Role + Role + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 31 + + Yes Oui @@ -6679,6 +6715,10 @@ Accounts Accounts + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 51 + libs/ui/src/lib/assistant/assistant.html 84 @@ -6972,6 +7012,14 @@ 293 + + Engagement per Day + Engagement per Day + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 76 + + Guides Guides @@ -7110,6 +7158,14 @@ 167 + + Country + Country + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 37 + + API Key Clé API @@ -7199,7 +7255,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 251 + 260 @@ -7258,6 +7314,14 @@ 234 + + API Requests Today + API Requests Today + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 86 + + Default Market Price Prix du marché par défaut @@ -7455,7 +7519,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 169 + 170 @@ -8072,7 +8136,7 @@ Voulez-vous vraiment générer un nouveau jeton de sécurité? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 174 + 175 @@ -8128,7 +8192,7 @@ Gérer le profil d’actif apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 442 + 465 @@ -8152,7 +8216,7 @@ Average Unit Price apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts - 111 + 113 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -8543,12 +8607,12 @@ 128 - + Registration Date Registration Date apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 22 + 23 diff --git a/apps/client/src/locales/messages.it.xlf b/apps/client/src/locales/messages.it.xlf index f720742c8..f5c8f799c 100644 --- a/apps/client/src/locales/messages.it.xlf +++ b/apps/client/src/locales/messages.it.xlf @@ -243,7 +243,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 443 + 451 @@ -279,7 +279,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 470 + 478 libs/ui/src/lib/benchmark/benchmark.component.html @@ -618,6 +618,14 @@ 200 + + Activities + Activities + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 61 + + Do you really want to delete this user? Vuoi davvero eliminare questo utente? @@ -695,7 +703,7 @@ apps/client/src/app/components/header/header.component.ts - 279 + 283 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -715,11 +723,11 @@ Ops! Token di sicurezza errato. apps/client/src/app/components/header/header.component.ts - 294 + 298 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 153 + 154 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts @@ -967,7 +975,7 @@ Segnala un’anomalia dei dati apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 452 + 450 @@ -1265,10 +1273,6 @@ apps/client/src/app/components/user-account-settings/user-account-settings.html 252 - - apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 12 - Granted Access @@ -2223,7 +2227,7 @@ Clona libs/ui/src/lib/activities-table/activities-table.component.html - 449 + 457 @@ -2231,7 +2235,7 @@ Esporta la bozza come ICS libs/ui/src/lib/activities-table/activities-table.component.html - 459 + 467 @@ -2239,7 +2243,7 @@ Vuoi davvero eliminare questa attività? libs/ui/src/lib/activities-table/activities-table.component.ts - 280 + 286 @@ -3723,7 +3727,7 @@ Vuoi davvero eliminare tutte le tue attività? libs/ui/src/lib/activities-table/activities-table.component.ts - 270 + 276 @@ -3783,7 +3787,7 @@ Vuoi davvero eliminare questa piattaforma? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 107 + 108 @@ -4290,6 +4294,14 @@ 210 + + User ID + User ID + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 12 + + Free Plan Piano gratuito @@ -5341,7 +5353,7 @@ Sei sicuro di voler eliminare questo tag? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 104 @@ -5533,7 +5545,7 @@ Ops, il trasferimento del saldo di cassa è fallito. apps/client/src/app/pages/accounts/accounts-page.component.ts - 324 + 339 @@ -5748,6 +5760,14 @@ 364 + + Close Holding + Close Holding + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 441 + + Absolute Asset Performance Rendimento assoluto dell’Asset @@ -6409,6 +6429,14 @@ 83 + + View Holding + View Holding + + libs/ui/src/lib/activities-table/activities-table.component.html + 444 + + Canada Canada @@ -6566,7 +6594,7 @@ Inattivo apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 87 + 88 @@ -6669,6 +6697,14 @@ 11 + + Role + Role + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 31 + + Yes Si @@ -6680,6 +6716,10 @@ Accounts Accounts + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 51 + libs/ui/src/lib/assistant/assistant.html 84 @@ -6973,6 +7013,14 @@ 293 + + Engagement per Day + Engagement per Day + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 76 + + Guides Guide @@ -7111,6 +7159,14 @@ 167 + + Country + Country + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 37 + + API Key API Key @@ -7200,7 +7256,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 251 + 260 @@ -7259,6 +7315,14 @@ 234 + + API Requests Today + API Requests Today + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 86 + + Default Market Price Prezzo di mercato predefinito @@ -7456,7 +7520,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 169 + 170 @@ -8073,7 +8137,7 @@ Vuoi davvero generare un nuovo token di sicurezza? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 174 + 175 @@ -8129,7 +8193,7 @@ Gestisci profilo risorsa apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 442 + 465 @@ -8153,7 +8217,7 @@ Average Unit Price apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts - 111 + 113 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -8544,12 +8608,12 @@ 128 - + Registration Date Registration Date apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 22 + 23 diff --git a/apps/client/src/locales/messages.nl.xlf b/apps/client/src/locales/messages.nl.xlf index 869b932aa..1ec127b22 100644 --- a/apps/client/src/locales/messages.nl.xlf +++ b/apps/client/src/locales/messages.nl.xlf @@ -242,7 +242,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 443 + 451 @@ -278,7 +278,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 470 + 478 libs/ui/src/lib/benchmark/benchmark.component.html @@ -617,6 +617,14 @@ 200 + + Activities + Activities + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 61 + + Do you really want to delete this user? Wilt je deze gebruiker echt verwijderen? @@ -694,7 +702,7 @@ apps/client/src/app/components/header/header.component.ts - 279 + 283 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -714,11 +722,11 @@ Oeps! Onjuiste beveiligingstoken. apps/client/src/app/components/header/header.component.ts - 294 + 298 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 153 + 154 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts @@ -966,7 +974,7 @@ Gegevensstoring melden apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 452 + 450 @@ -1264,10 +1272,6 @@ apps/client/src/app/components/user-account-settings/user-account-settings.html 252 - - apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 12 - Granted Access @@ -2222,7 +2226,7 @@ Kloon libs/ui/src/lib/activities-table/activities-table.component.html - 449 + 457 @@ -2230,7 +2234,7 @@ Concept exporteren als ICS libs/ui/src/lib/activities-table/activities-table.component.html - 459 + 467 @@ -2238,7 +2242,7 @@ Wil je deze activiteit echt verwijderen? libs/ui/src/lib/activities-table/activities-table.component.ts - 280 + 286 @@ -3722,7 +3726,7 @@ Weet je zeker dat je alle activiteiten wilt verwijderen? libs/ui/src/lib/activities-table/activities-table.component.ts - 270 + 276 @@ -3782,7 +3786,7 @@ Wil je dit platform echt verwijderen? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 107 + 108 @@ -4289,6 +4293,14 @@ 210 + + User ID + User ID + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 12 + + Free Plan Gratis abonnement @@ -5340,7 +5352,7 @@ Weet u zetker dat u dit label wilt verwijderen? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 104 @@ -5532,7 +5544,7 @@ Oeps, geldoverdracht is mislukt. apps/client/src/app/pages/accounts/accounts-page.component.ts - 324 + 339 @@ -5747,6 +5759,14 @@ 364 + + Close Holding + Close Holding + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 441 + + Absolute Asset Performance Absolute Activaprestaties @@ -6408,6 +6428,14 @@ 83 + + View Holding + View Holding + + libs/ui/src/lib/activities-table/activities-table.component.html + 444 + + Canada Canada @@ -6565,7 +6593,7 @@ Inactief apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 87 + 88 @@ -6668,6 +6696,14 @@ 11 + + Role + Role + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 31 + + Yes Ja @@ -6679,6 +6715,10 @@ Accounts Accounts + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 51 + libs/ui/src/lib/assistant/assistant.html 84 @@ -6972,6 +7012,14 @@ 293 + + Engagement per Day + Engagement per Day + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 76 + + Guides Gidsen @@ -7110,6 +7158,14 @@ 167 + + Country + Country + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 37 + + API Key API-sleutel @@ -7199,7 +7255,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 251 + 260 @@ -7258,6 +7314,14 @@ 234 + + API Requests Today + API Requests Today + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 86 + + Default Market Price Standaard Marktprijs @@ -7455,7 +7519,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 169 + 170 @@ -8072,7 +8136,7 @@ Wilt u echt een nieuwe securitytoken genereren? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 174 + 175 @@ -8128,7 +8192,7 @@ Beheer activaprofiel apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 442 + 465 @@ -8152,7 +8216,7 @@ Gemiddelde eenheidsprijs apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts - 111 + 113 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -8543,12 +8607,12 @@ 128 - + Registration Date Registration Date apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 22 + 23 diff --git a/apps/client/src/locales/messages.pl.xlf b/apps/client/src/locales/messages.pl.xlf index 87c485b25..d8e342569 100644 --- a/apps/client/src/locales/messages.pl.xlf +++ b/apps/client/src/locales/messages.pl.xlf @@ -519,7 +519,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 443 + 451 @@ -555,7 +555,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 470 + 478 libs/ui/src/lib/benchmark/benchmark.component.html @@ -1166,6 +1166,14 @@ 200 + + Activities + Activities + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 61 + + Add Platform Dodaj Platformę @@ -1199,7 +1207,7 @@ Czy naprawdę chcesz usunąć tę platformę? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 107 + 108 @@ -1263,7 +1271,7 @@ Czy naprawdę chcesz usunąć ten tag? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 104 @@ -1431,7 +1439,7 @@ apps/client/src/app/components/header/header.component.ts - 279 + 283 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1451,11 +1459,11 @@ Ups! Nieprawidłowy token bezpieczeństwa. apps/client/src/app/components/header/header.component.ts - 294 + 298 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 153 + 154 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts @@ -1875,7 +1883,7 @@ Zgłoś Błąd Danych apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 452 + 450 @@ -2353,10 +2361,6 @@ apps/client/src/app/components/user-account-settings/user-account-settings.html 252 - - apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 12 - Export Data @@ -2559,7 +2563,7 @@ Ups, transfer salda nie powiódł się. apps/client/src/app/pages/accounts/accounts-page.component.ts - 324 + 339 @@ -3563,7 +3567,7 @@ Czy na pewno chcesz usunąć te aktywności? libs/ui/src/lib/activities-table/activities-table.component.ts - 270 + 276 @@ -4643,6 +4647,14 @@ 210 + + User ID + User ID + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 12 + + Free Plan Plan Darmowy @@ -4832,7 +4844,7 @@ Sklonuj libs/ui/src/lib/activities-table/activities-table.component.html - 449 + 457 @@ -4840,7 +4852,7 @@ Eksportuj Wersję Roboczą jako ICS libs/ui/src/lib/activities-table/activities-table.component.html - 459 + 467 @@ -4848,7 +4860,7 @@ Czy na pewno chcesz usunąć tę działalność? libs/ui/src/lib/activities-table/activities-table.component.ts - 280 + 286 @@ -5747,6 +5759,14 @@ 364 + + Close Holding + Close Holding + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 441 + + Absolute Asset Performance Łączny wynik aktywów @@ -6408,6 +6428,14 @@ 83 + + View Holding + View Holding + + libs/ui/src/lib/activities-table/activities-table.component.html + 444 + + Canada Kanada @@ -6565,7 +6593,7 @@ Nieaktywny apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 87 + 88 @@ -6668,6 +6696,14 @@ 11 + + Role + Role + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 31 + + Yes Tak @@ -6679,6 +6715,10 @@ Accounts Accounts + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 51 + libs/ui/src/lib/assistant/assistant.html 84 @@ -6972,6 +7012,14 @@ 293 + + Engagement per Day + Engagement per Day + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 76 + + Guides Poradniki @@ -7110,6 +7158,14 @@ 167 + + Country + Country + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 37 + + API Key Klucz API @@ -7199,7 +7255,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 251 + 260 @@ -7258,6 +7314,14 @@ 234 + + API Requests Today + API Requests Today + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 86 + + Default Market Price Domyślna cena rynkowa @@ -7455,7 +7519,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 169 + 170 @@ -8072,7 +8136,7 @@ Czy na pewno chcesz wygenerować nowy token bezpieczeństwa? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 174 + 175 @@ -8128,7 +8192,7 @@ Zarządzaj profilem aktywów apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 442 + 465 @@ -8152,7 +8216,7 @@ Średnia cena jednostkowa apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts - 111 + 113 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -8543,12 +8607,12 @@ 128 - + Registration Date Registration Date apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 22 + 23 diff --git a/apps/client/src/locales/messages.pt.xlf b/apps/client/src/locales/messages.pt.xlf index 8d93b9ecb..9280de1dd 100644 --- a/apps/client/src/locales/messages.pt.xlf +++ b/apps/client/src/locales/messages.pt.xlf @@ -298,7 +298,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 443 + 451 @@ -334,7 +334,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 470 + 478 libs/ui/src/lib/benchmark/benchmark.component.html @@ -697,6 +697,14 @@ 200 + + Activities + Activities + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 61 + + Do you really want to delete this user? Deseja realmente excluir este utilizador? @@ -814,7 +822,7 @@ apps/client/src/app/components/header/header.component.ts - 279 + 283 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -834,11 +842,11 @@ Oops! Token de Segurança Incorreto. apps/client/src/app/components/header/header.component.ts - 294 + 298 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 153 + 154 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts @@ -1214,7 +1222,7 @@ Dados do Relatório com Problema apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 452 + 450 @@ -1608,10 +1616,6 @@ apps/client/src/app/components/user-account-settings/user-account-settings.html 252 - - apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 12 - Granted Access @@ -2598,7 +2602,7 @@ Clonar libs/ui/src/lib/activities-table/activities-table.component.html - 449 + 457 @@ -2606,7 +2610,7 @@ Exportar Rascunho como ICS libs/ui/src/lib/activities-table/activities-table.component.html - 459 + 467 @@ -2614,7 +2618,7 @@ Deseja realmente eliminar esta atividade? libs/ui/src/lib/activities-table/activities-table.component.ts - 280 + 286 @@ -3722,7 +3726,7 @@ Deseja mesmo eliminar estas atividades? libs/ui/src/lib/activities-table/activities-table.component.ts - 270 + 276 @@ -3782,7 +3786,7 @@ Deseja mesmo eliminar esta plataforma? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 107 + 108 @@ -4289,6 +4293,14 @@ 210 + + User ID + User ID + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 12 + + Free Plan Plano gratuito @@ -5340,7 +5352,7 @@ Você realmente deseja excluir esta tag? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 104 @@ -5532,7 +5544,7 @@ Ops, a transferência do saldo em dinheiro falhou. apps/client/src/app/pages/accounts/accounts-page.component.ts - 324 + 339 @@ -5747,6 +5759,14 @@ 364 + + Close Holding + Close Holding + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 441 + + Absolute Asset Performance Desempenho absoluto de ativos @@ -6408,6 +6428,14 @@ 83 + + View Holding + View Holding + + libs/ui/src/lib/activities-table/activities-table.component.html + 444 + + Canada Canadá @@ -6565,7 +6593,7 @@ Inativo apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 87 + 88 @@ -6668,6 +6696,14 @@ 11 + + Role + Role + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 31 + + Yes Sim @@ -6679,6 +6715,10 @@ Accounts Accounts + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 51 + libs/ui/src/lib/assistant/assistant.html 84 @@ -6972,6 +7012,14 @@ 293 + + Engagement per Day + Engagement per Day + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 76 + + Guides Guias @@ -7110,6 +7158,14 @@ 167 + + Country + Country + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 37 + + API Key Chave de API @@ -7199,7 +7255,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 251 + 260 @@ -7258,6 +7314,14 @@ 234 + + API Requests Today + API Requests Today + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 86 + + Default Market Price Preço de mercado padrão @@ -7455,7 +7519,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 169 + 170 @@ -8072,7 +8136,7 @@ Do you really want to generate a new security token? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 174 + 175 @@ -8128,7 +8192,7 @@ Gerenciar perfil de ativos apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 442 + 465 @@ -8152,7 +8216,7 @@ Preço médio unitário apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts - 111 + 113 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -8543,12 +8607,12 @@ 128 - + Registration Date Registration Date apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 22 + 23 diff --git a/apps/client/src/locales/messages.tr.xlf b/apps/client/src/locales/messages.tr.xlf index fd87792f9..b867b8da8 100644 --- a/apps/client/src/locales/messages.tr.xlf +++ b/apps/client/src/locales/messages.tr.xlf @@ -479,7 +479,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 443 + 451 @@ -515,7 +515,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 470 + 478 libs/ui/src/lib/benchmark/benchmark.component.html @@ -1078,6 +1078,14 @@ 200 + + Activities + Activities + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 61 + + Add Platform Platform Ekle @@ -1111,7 +1119,7 @@ Bu platformu silmeyi gerçekten istiyor musunuz? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 107 + 108 @@ -1287,7 +1295,7 @@ apps/client/src/app/components/header/header.component.ts - 279 + 283 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1307,11 +1315,11 @@ Hay Allah! Güvenlik anahtarı yanlış. apps/client/src/app/components/header/header.component.ts - 294 + 298 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 153 + 154 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts @@ -1731,7 +1739,7 @@ Rapor Veri Sorunu apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 452 + 450 @@ -3063,7 +3071,7 @@ Tüm işlemlerinizi silmeyi gerçekten istiyor musunuz? libs/ui/src/lib/activities-table/activities-table.component.ts - 270 + 276 @@ -4131,6 +4139,14 @@ 210 + + User ID + User ID + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 12 + + Free Plan Ücretsiz Plan @@ -4470,10 +4486,6 @@ apps/client/src/app/components/user-account-settings/user-account-settings.html 252 - - apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 12 - Export Data @@ -4552,7 +4564,7 @@ Klonla libs/ui/src/lib/activities-table/activities-table.component.html - 449 + 457 @@ -4560,7 +4572,7 @@ Taslakları ICS Olarak Dışa Aktar libs/ui/src/lib/activities-table/activities-table.component.html - 459 + 467 @@ -4568,7 +4580,7 @@ TBu işlemi silmeyi gerçekten istiyor musunuz? libs/ui/src/lib/activities-table/activities-table.component.ts - 280 + 286 @@ -5340,7 +5352,7 @@ Bu etiketi silmeyi gerçekten istiyor musunuz? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 104 @@ -5532,7 +5544,7 @@ Hay Allah, Nakit bakiyesi tranferi başarısız oldu. apps/client/src/app/pages/accounts/accounts-page.component.ts - 324 + 339 @@ -5747,6 +5759,14 @@ 364 + + Close Holding + Close Holding + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 441 + + Absolute Asset Performance Mutlak Varlık Performansı @@ -6408,6 +6428,14 @@ 83 + + View Holding + View Holding + + libs/ui/src/lib/activities-table/activities-table.component.html + 444 + + Canada Kanada @@ -6565,7 +6593,7 @@ Pasif apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 87 + 88 @@ -6668,6 +6696,14 @@ 11 + + Role + Role + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 31 + + Yes Evet @@ -6679,6 +6715,10 @@ Accounts Accounts + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 51 + libs/ui/src/lib/assistant/assistant.html 84 @@ -6972,6 +7012,14 @@ 293 + + Engagement per Day + Engagement per Day + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 76 + + Guides Kılavuzlar @@ -7110,6 +7158,14 @@ 167 + + Country + Country + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 37 + + API Key API Anahtarı @@ -7199,7 +7255,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 251 + 260 @@ -7258,6 +7314,14 @@ 234 + + API Requests Today + API Requests Today + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 86 + + Default Market Price Varsayılan Piyasa Fiyatı @@ -7455,7 +7519,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 169 + 170 @@ -8072,7 +8136,7 @@ Do you really want to generate a new security token? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 174 + 175 @@ -8128,7 +8192,7 @@ Manage Asset Profile apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 442 + 465 @@ -8152,7 +8216,7 @@ Average Unit Price apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts - 111 + 113 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -8543,12 +8607,12 @@ 128 - + Registration Date Registration Date apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 22 + 23 diff --git a/apps/client/src/locales/messages.uk.xlf b/apps/client/src/locales/messages.uk.xlf index 61c9be112..0305608c2 100644 --- a/apps/client/src/locales/messages.uk.xlf +++ b/apps/client/src/locales/messages.uk.xlf @@ -38,7 +38,7 @@ apps/client/src/app/components/header/header.component.ts - 279 + 283 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -345,6 +345,10 @@ Accounts Accounts + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 51 + libs/ui/src/lib/assistant/assistant.html 84 @@ -627,7 +631,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 443 + 451 @@ -663,7 +667,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 470 + 478 libs/ui/src/lib/benchmark/benchmark.component.html @@ -1362,6 +1366,14 @@ 200 + + Activities + Activities + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 61 + + Add Platform Додати платформу @@ -1375,7 +1387,7 @@ Ви дійсно хочете видалити цю платформу? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 107 + 108 @@ -1559,7 +1571,7 @@ Ви дійсно хочете видалити цей тег? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 104 @@ -1763,11 +1775,11 @@ Упс! Неправильний Секретний Токен. apps/client/src/app/components/header/header.component.ts - 294 + 298 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 153 + 154 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts @@ -1875,7 +1887,7 @@ Повідомити про збій даних apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 452 + 450 @@ -2625,10 +2637,6 @@ apps/client/src/app/components/user-account-settings/user-account-settings.html 252 - - apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 12 - Me @@ -2639,7 +2647,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 251 + 260 @@ -3175,7 +3183,7 @@ Упс, перенесення балансу готівки не вдалося. apps/client/src/app/pages/accounts/accounts-page.component.ts - 324 + 339 @@ -4779,6 +4787,14 @@ 91 + + Close Holding + Close Holding + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 441 + + Absolute Asset Performance Абсолютна прибутковість активів @@ -4936,7 +4952,7 @@ Неактивний apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 87 + 88 @@ -5255,6 +5271,14 @@ 293 + + Engagement per Day + Engagement per Day + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 76 + + Guides Посібники @@ -5786,6 +5810,14 @@ 210 + + User ID + User ID + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 12 + + can be used anonymously може використовуватися анонімно @@ -6035,7 +6067,7 @@ Клонувати libs/ui/src/lib/activities-table/activities-table.component.html - 449 + 457 @@ -6043,7 +6075,7 @@ Експортувати чернетку як ICS libs/ui/src/lib/activities-table/activities-table.component.html - 459 + 467 @@ -6051,7 +6083,7 @@ Ви дійсно хочете видалити ці дії? libs/ui/src/lib/activities-table/activities-table.component.ts - 270 + 276 @@ -6059,7 +6091,7 @@ Ви дійсно хочете видалити цю активність? libs/ui/src/lib/activities-table/activities-table.component.ts - 280 + 286 @@ -6750,6 +6782,14 @@ 33 + + Role + Role + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 31 + + Yes Так @@ -7014,6 +7054,14 @@ 83 + + View Holding + View Holding + + libs/ui/src/lib/activities-table/activities-table.component.html + 444 + + Canada Канада @@ -7166,6 +7214,14 @@ 110 + + Country + Country + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 37 + + API Key Ключ API @@ -7258,6 +7314,14 @@ 234 + + API Requests Today + API Requests Today + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 86 + + Default Market Price Default Market Price @@ -7455,7 +7519,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 169 + 170 @@ -8072,7 +8136,7 @@ Do you really want to generate a new security token? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 174 + 175 @@ -8128,7 +8192,7 @@ Manage Asset Profile apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 442 + 465 @@ -8152,7 +8216,7 @@ Average Unit Price apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts - 111 + 113 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -8543,12 +8607,12 @@ 128 - + Registration Date Registration Date apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 22 + 23 diff --git a/apps/client/src/locales/messages.xlf b/apps/client/src/locales/messages.xlf index b9b3fb451..34502dbc9 100644 --- a/apps/client/src/locales/messages.xlf +++ b/apps/client/src/locales/messages.xlf @@ -498,7 +498,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 443 + 451 @@ -533,7 +533,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 470 + 478 libs/ui/src/lib/benchmark/benchmark.component.html @@ -1106,6 +1106,13 @@ 200 + + Activities + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 61 + + Add Platform @@ -1136,7 +1143,7 @@ Do you really want to delete this platform? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 107 + 108 @@ -1193,7 +1200,7 @@ Do you really want to delete this tag? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 104 @@ -1344,7 +1351,7 @@ apps/client/src/app/components/header/header.component.ts - 279 + 283 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1363,11 +1370,11 @@ Oops! Incorrect Security Token. apps/client/src/app/components/header/header.component.ts - 294 + 298 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 153 + 154 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts @@ -1747,7 +1754,7 @@ Report Data Glitch apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 452 + 450 @@ -2181,10 +2188,6 @@ apps/client/src/app/components/user-account-settings/user-account-settings.html 252 - - apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 12 - Export Data @@ -2372,7 +2375,7 @@ Oops, cash balance transfer has failed. apps/client/src/app/pages/accounts/accounts-page.component.ts - 324 + 339 @@ -3287,7 +3290,7 @@ Do you really want to delete these activities? libs/ui/src/lib/activities-table/activities-table.component.ts - 270 + 276 @@ -4261,6 +4264,13 @@ 210 + + User ID + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 12 + + Free Plan @@ -4449,21 +4459,21 @@ Clone libs/ui/src/lib/activities-table/activities-table.component.html - 449 + 457 Export Draft as ICS libs/ui/src/lib/activities-table/activities-table.component.html - 459 + 467 Do you really want to delete this activity? libs/ui/src/lib/activities-table/activities-table.component.ts - 280 + 286 @@ -5233,6 +5243,13 @@ 193 + + Close Holding + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 441 + + Absolute Asset Performance @@ -5790,6 +5807,13 @@ 99 + + View Holding + + libs/ui/src/lib/activities-table/activities-table.component.html + 444 + + Canada @@ -6000,6 +6024,13 @@ 9 + + Role + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 31 + + Yes @@ -6018,7 +6049,7 @@ Inactive apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 87 + 88 @@ -6136,6 +6167,10 @@ Accounts + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 51 + libs/ui/src/lib/assistant/assistant.html 84 @@ -6361,6 +6396,13 @@ 291 + + Engagement per Day + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 76 + + Guides @@ -6444,6 +6486,13 @@ 26 + + Country + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 37 + + API Key @@ -6569,7 +6618,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 251 + 260 @@ -6600,6 +6649,13 @@ 450 + + API Requests Today + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 86 + + Default Market Price @@ -6796,7 +6852,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 169 + 170 @@ -7322,7 +7378,7 @@ Do you really want to generate a new security token? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 174 + 175 @@ -7358,7 +7414,7 @@ Manage Asset Profile apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 442 + 465 @@ -7379,7 +7435,7 @@ Average Unit Price apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts - 111 + 113 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -7723,11 +7779,11 @@ 128 - + Registration Date apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 22 + 23 diff --git a/apps/client/src/locales/messages.zh.xlf b/apps/client/src/locales/messages.zh.xlf index 90e239595..6d490fc0e 100644 --- a/apps/client/src/locales/messages.zh.xlf +++ b/apps/client/src/locales/messages.zh.xlf @@ -528,7 +528,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 443 + 451 @@ -564,7 +564,7 @@ libs/ui/src/lib/activities-table/activities-table.component.html - 470 + 478 libs/ui/src/lib/benchmark/benchmark.component.html @@ -1175,6 +1175,14 @@ 200 + + Activities + Activities + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 61 + + Add Platform 添加平台 @@ -1208,7 +1216,7 @@ 您真的要删除这个平台吗? apps/client/src/app/components/admin-platform/admin-platform.component.ts - 107 + 108 @@ -1272,7 +1280,7 @@ 您真的要删除此标签吗? apps/client/src/app/components/admin-tag/admin-tag.component.ts - 103 + 104 @@ -1440,7 +1448,7 @@ apps/client/src/app/components/header/header.component.ts - 279 + 283 apps/client/src/app/components/login-with-access-token-dialog/login-with-access-token-dialog.html @@ -1460,11 +1468,11 @@ 哎呀!安全令牌不正确。 apps/client/src/app/components/header/header.component.ts - 294 + 298 apps/client/src/app/components/user-account-access/user-account-access.component.ts - 153 + 154 apps/client/src/app/components/user-account-settings/user-account-settings.component.ts @@ -1884,7 +1892,7 @@ 报告数据故障 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 452 + 450 @@ -2362,10 +2370,6 @@ apps/client/src/app/components/user-account-settings/user-account-settings.html 252 - - apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 12 - Export Data @@ -2568,7 +2572,7 @@ 糟糕,现金余额转账失败。 apps/client/src/app/pages/accounts/accounts-page.component.ts - 324 + 339 @@ -3572,7 +3576,7 @@ 您确定要删除这些活动吗? libs/ui/src/lib/activities-table/activities-table.component.ts - 270 + 276 @@ -4652,6 +4656,14 @@ 210 + + User ID + User ID + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 12 + + Free Plan 免费计划 @@ -4861,7 +4873,7 @@ 克隆 libs/ui/src/lib/activities-table/activities-table.component.html - 449 + 457 @@ -4869,7 +4881,7 @@ 将汇票导出为 ICS libs/ui/src/lib/activities-table/activities-table.component.html - 459 + 467 @@ -4877,7 +4889,7 @@ 您确实要删除此活动吗? libs/ui/src/lib/activities-table/activities-table.component.ts - 280 + 286 @@ -5732,6 +5744,14 @@ 193 + + Close Holding + Close Holding + + apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html + 441 + + Absolute Asset Performance 绝对资产回报 @@ -6409,6 +6429,14 @@ 83 + + View Holding + View Holding + + libs/ui/src/lib/activities-table/activities-table.component.html + 444 + + Canada 加拿大 @@ -6566,7 +6594,7 @@ 非活跃 apps/client/src/app/pages/portfolio/x-ray/x-ray-page.component.html - 87 + 88 @@ -6669,6 +6697,14 @@ 11 + + Role + Role + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 31 + + Yes @@ -6680,6 +6716,10 @@ Accounts Accounts + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 51 + libs/ui/src/lib/assistant/assistant.html 84 @@ -6973,6 +7013,14 @@ 293 + + Engagement per Day + Engagement per Day + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 76 + + Guides 指南 @@ -7111,6 +7159,14 @@ 167 + + Country + Country + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 37 + + API Key API 密钥 @@ -7200,7 +7256,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 251 + 260 @@ -7259,6 +7315,14 @@ 234 + + API Requests Today + API Requests Today + + apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html + 86 + + Default Market Price 默认市场价格 @@ -7456,7 +7520,7 @@ apps/client/src/app/components/user-account-access/user-account-access.component.ts - 169 + 170 @@ -8073,7 +8137,7 @@ 您真的想要生成一个新的安全令牌吗? apps/client/src/app/components/user-account-access/user-account-access.component.ts - 174 + 175 @@ -8129,7 +8193,7 @@ 管理资产概况 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html - 442 + 465 @@ -8153,7 +8217,7 @@ 平均单位价格 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts - 111 + 113 apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html @@ -8544,12 +8608,12 @@ 128 - + Registration Date Registration Date apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html - 22 + 23 diff --git a/apps/client/src/styles/theme.scss b/apps/client/src/styles/theme.scss index fe9fd44a5..8dd6d8e36 100644 --- a/apps/client/src/styles/theme.scss +++ b/apps/client/src/styles/theme.scss @@ -1,9 +1,6 @@ @use '@angular/material' as mat; -$dark-primary-text: rgba(black, 0.87); -$light-primary-text: white; - -$mat-css-dark-theme-selector: '.theme-dark'; +@use './variables.scss' as variables; $gf-primary: ( 50: var(--gf-theme-primary-50), @@ -21,20 +18,20 @@ $gf-primary: ( A400: var(--gf-theme-primary-A400), A700: var(--gf-theme-primary-A700), contrast: ( - 50: $dark-primary-text, - 100: $dark-primary-text, - 200: $dark-primary-text, - 300: $light-primary-text, - 400: $light-primary-text, - 500: $light-primary-text, - 600: $light-primary-text, - 700: $light-primary-text, - 800: $light-primary-text, - 900: $light-primary-text, - A100: $dark-primary-text, - A200: $light-primary-text, - A400: $light-primary-text, - A700: $light-primary-text + 50: variables.$dark-primary-text, + 100: variables.$dark-primary-text, + 200: variables.$dark-primary-text, + 300: variables.$light-primary-text, + 400: variables.$light-primary-text, + 500: variables.$light-primary-text, + 600: variables.$light-primary-text, + 700: variables.$light-primary-text, + 800: variables.$light-primary-text, + 900: variables.$light-primary-text, + A100: variables.$dark-primary-text, + A200: variables.$light-primary-text, + A400: variables.$light-primary-text, + A700: variables.$light-primary-text ) ); @@ -54,20 +51,20 @@ $gf-secondary: ( A400: var(--gf-theme-secondary-A400), A700: var(--gf-theme-secondary-A700), contrast: ( - 50: $dark-primary-text, - 100: $dark-primary-text, - 200: $dark-primary-text, - 300: $light-primary-text, - 400: $light-primary-text, - 500: $light-primary-text, - 600: $light-primary-text, - 700: $light-primary-text, - 800: $light-primary-text, - 900: $light-primary-text, - A100: $dark-primary-text, - A200: $light-primary-text, - A400: $light-primary-text, - A700: $light-primary-text + 50: variables.$dark-primary-text, + 100: variables.$dark-primary-text, + 200: variables.$dark-primary-text, + 300: variables.$light-primary-text, + 400: variables.$light-primary-text, + 500: variables.$light-primary-text, + 600: variables.$light-primary-text, + 700: variables.$light-primary-text, + 800: variables.$light-primary-text, + 900: variables.$light-primary-text, + A100: variables.$dark-primary-text, + A200: variables.$light-primary-text, + A400: variables.$light-primary-text, + A700: variables.$light-primary-text ) ); diff --git a/apps/client/src/styles/variables.scss b/apps/client/src/styles/variables.scss new file mode 100644 index 000000000..dcf26eecc --- /dev/null +++ b/apps/client/src/styles/variables.scss @@ -0,0 +1,4 @@ +$dark-primary-text: rgba(black, 0.87); +$light-primary-text: white; + +$mat-css-dark-theme-selector: '.theme-dark'; diff --git a/eslint.config.cjs b/eslint.config.cjs index c7e08821c..a88d0cc85 100644 --- a/eslint.config.cjs +++ b/eslint.config.cjs @@ -152,7 +152,6 @@ module.exports = [ // The following rules are part of eslint:recommended // and can be remove once solved - 'no-constant-binary-expression': 'warn', 'no-loss-of-precision': 'warn', // The following rules are part of @typescript-eslint/recommended-type-checked @@ -170,7 +169,6 @@ module.exports = [ '@typescript-eslint/no-unsafe-argument': 'warn', '@typescript-eslint/no-unsafe-assignment': 'warn', '@typescript-eslint/no-unsafe-enum-comparison': 'warn', - '@typescript-eslint/no-unsafe-function-type': 'warn', '@typescript-eslint/no-unsafe-member-access': 'warn', '@typescript-eslint/no-unsafe-return': 'warn', '@typescript-eslint/no-unsafe-call': 'warn', @@ -189,8 +187,7 @@ module.exports = [ // The following rules are part of @typescript-eslint/stylistic-type-checked // and can be remove once solved - '@typescript-eslint/prefer-nullish-coalescing': 'warn', // TODO: Requires strictNullChecks: true - '@typescript-eslint/prefer-regexp-exec': 'warn' + '@typescript-eslint/prefer-nullish-coalescing': 'warn' // TODO: Requires strictNullChecks: true } })) ]; diff --git a/libs/common/src/lib/helper.ts b/libs/common/src/lib/helper.ts index 97b762267..7452b604c 100644 --- a/libs/common/src/lib/helper.ts +++ b/libs/common/src/lib/helper.ts @@ -375,7 +375,7 @@ export function parseDate(date: string): Date { // Transform 'yyyyMMdd' format to supported format by parse function if (date?.length === 8) { - const match = date.match(/^(\d{4})(\d{2})(\d{2})$/); + const match = /^(\d{4})(\d{2})(\d{2})$/.exec(date); if (match) { const [, year, month, day] = match; diff --git a/libs/common/src/lib/interfaces/index.ts b/libs/common/src/lib/interfaces/index.ts index eac5db68c..06ecf32e8 100644 --- a/libs/common/src/lib/interfaces/index.ts +++ b/libs/common/src/lib/interfaces/index.ts @@ -7,7 +7,6 @@ import type { AdminMarketData, AdminMarketDataItem } from './admin-market-data.interface'; -import type { AdminUsers } from './admin-users.interface'; import type { AssetClassSelectorOption } from './asset-class-selector-option.interface'; import type { AssetProfileIdentifier } from './asset-profile-identifier.interface'; import type { BenchmarkProperty } from './benchmark-property.interface'; @@ -39,6 +38,7 @@ import type { AccountBalancesResponse } from './responses/account-balances-respo import type { AccountsResponse } from './responses/accounts-response.interface'; import type { ActivitiesResponse } from './responses/activities-response.interface'; import type { ActivityResponse } from './responses/activity-response.interface'; +import type { AdminUsersResponse } from './responses/admin-users-response.interface'; import type { AiPromptResponse } from './responses/ai-prompt-response.interface'; import type { ApiKeyResponse } from './responses/api-key-response.interface'; import type { AssetResponse } from './responses/asset-response.interface'; @@ -92,7 +92,7 @@ export { AdminMarketData, AdminMarketDataDetails, AdminMarketDataItem, - AdminUsers, + AdminUsersResponse, AiPromptResponse, ApiKeyResponse, AssetClassSelectorOption, diff --git a/libs/common/src/lib/interfaces/admin-users.interface.ts b/libs/common/src/lib/interfaces/responses/admin-users-response.interface.ts similarity index 88% rename from libs/common/src/lib/interfaces/admin-users.interface.ts rename to libs/common/src/lib/interfaces/responses/admin-users-response.interface.ts index 79031425a..d9f58ee18 100644 --- a/libs/common/src/lib/interfaces/admin-users.interface.ts +++ b/libs/common/src/lib/interfaces/responses/admin-users-response.interface.ts @@ -1,6 +1,6 @@ import { Role } from '@prisma/client'; -export interface AdminUsers { +export interface AdminUsersResponse { count: number; users: { accountCount: number; 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 843832e1a..46e1de875 100644 --- a/libs/ui/src/lib/activities-table/activities-table.component.html +++ b/libs/ui/src/lib/activities-table/activities-table.component.html @@ -437,6 +437,14 @@ class="no-max-width" xPosition="before" > + @if (canClickActivity(element)) { + + }