diff --git a/.prettierrc b/.prettierrc index 30f191d91..6a8ad9afa 100644 --- a/.prettierrc +++ b/.prettierrc @@ -9,6 +9,7 @@ ], "attributeSort": "ASC", "endOfLine": "auto", + "plugins": ["prettier-plugin-organize-attributes"], "printWidth": 80, "singleQuote": true, "tabWidth": 2, diff --git a/CHANGELOG.md b/CHANGELOG.md index a9b1e371e..307c79272 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,67 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +- Added support for the cryptocurrency _CyberConnect_ + ### Changed -- Removed the deprecated environment variable `BASE_CURRENCY` +- **Breaking Change**: Removed the deprecated environment variable `BASE_CURRENCY` +- Improved the validation in the activities import +- Deactivated _Internet Identity_ as a social login provider for the account registration +- Improved the language localization for German (`de`) +- Refreshed the cryptocurrencies list +- Changed the version in the `docker-compose` files from `3.7` to `3.9` + +### Fixed + +- Fixed an issue in the _Yahoo Finance_ data enhancer where countries and sectors have been removed + +## 1.305.0 - 2023-09-03 + +### Added + +- Added _Hacker News_ to the _As seen in_ section on the landing page + +### Changed + +- Shortened the page titles +- Improved the language localization for German (`de`) +- Upgraded `prisma` from version `4.16.2` to `5.2.0` +- Upgraded `replace-in-file` from version `6.3.5` to `7.0.1` +- Upgraded `yahoo-finance2` from version `2.4.3` to `2.4.4` + +### Fixed + +- Fixed the alignment in the header navigation +- Fixed the alignment in the menu of the impersonation mode + +## 1.304.0 - 2023-08-27 + +### Added + +- Added health check endpoints for data enhancers + +### Changed + +- Upgraded `Nx` from version `16.7.2` to `16.7.4` +- Upgraded `prettier` from version `2.8.4` to `3.0.2` + +## 1.303.0 - 2023-08-23 + +### Added + +- Added a blog post: _Ghostfolio joins OSS Friends_ + +### Changed + +- Refreshed the cryptocurrencies list +- Improved the _OSS Friends_ page + +### Fixed + +- Fixed an issue with the _Trackinsight_ data enhancer for asset profile data ## 1.302.0 - 2023-08-20 diff --git a/apps/api/src/app/auth/auth.controller.ts b/apps/api/src/app/auth/auth.controller.ts index 0c6b047bf..376109b8d 100644 --- a/apps/api/src/app/auth/auth.controller.ts +++ b/apps/api/src/app/auth/auth.controller.ts @@ -41,9 +41,8 @@ export class AuthController { @Param('accessToken') accessToken: string ): Promise { try { - const authToken = await this.authService.validateAnonymousLogin( - accessToken - ); + const authToken = + await this.authService.validateAnonymousLogin(accessToken); return { authToken }; } catch { throw new HttpException( diff --git a/apps/api/src/app/auth/auth.service.ts b/apps/api/src/app/auth/auth.service.ts index 2f31e722b..c7270f8c3 100644 --- a/apps/api/src/app/auth/auth.service.ts +++ b/apps/api/src/app/auth/auth.service.ts @@ -55,7 +55,7 @@ export class AuthService { const isUserSignupEnabled = await this.propertyService.isUserSignupEnabled(); - if (!isUserSignupEnabled) { + if (!isUserSignupEnabled || true) { throw new Error('Sign up forbidden'); } diff --git a/apps/api/src/app/exchange-rate/exchange-rate.controller.ts b/apps/api/src/app/exchange-rate/exchange-rate.controller.ts index 40ff9d3c8..8e01c4ca9 100644 --- a/apps/api/src/app/exchange-rate/exchange-rate.controller.ts +++ b/apps/api/src/app/exchange-rate/exchange-rate.controller.ts @@ -7,10 +7,10 @@ import { UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; +import { parseISO } from 'date-fns'; import { StatusCodes, getReasonPhrase } from 'http-status-codes'; import { ExchangeRateService } from './exchange-rate.service'; -import { parseISO } from 'date-fns'; @Controller('exchange-rate') export class ExchangeRateController { diff --git a/apps/api/src/app/health/health.controller.ts b/apps/api/src/app/health/health.controller.ts index d9af97981..cc430c0dc 100644 --- a/apps/api/src/app/health/health.controller.ts +++ b/apps/api/src/app/health/health.controller.ts @@ -18,6 +18,19 @@ export class HealthController { @Get() public async getHealth() {} + @Get('data-enhancer/:name') + public async getHealthOfDataEnhancer(@Param('name') name: string) { + const hasResponse = + await this.healthService.hasResponseFromDataEnhancer(name); + + if (hasResponse !== true) { + throw new HttpException( + getReasonPhrase(StatusCodes.SERVICE_UNAVAILABLE), + StatusCodes.SERVICE_UNAVAILABLE + ); + } + } + @Get('data-provider/:dataSource') @UseInterceptors(TransformDataSourceInRequestInterceptor) public async getHealthOfDataProvider( @@ -30,9 +43,8 @@ export class HealthController { ); } - const hasResponse = await this.healthService.hasResponseFromDataProvider( - dataSource - ); + const hasResponse = + await this.healthService.hasResponseFromDataProvider(dataSource); if (hasResponse !== true) { throw new HttpException( diff --git a/apps/api/src/app/health/health.module.ts b/apps/api/src/app/health/health.module.ts index 1c5292027..b6952c3b5 100644 --- a/apps/api/src/app/health/health.module.ts +++ b/apps/api/src/app/health/health.module.ts @@ -1,4 +1,5 @@ import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; +import { DataEnhancerModule } from '@ghostfolio/api/services/data-provider/data-enhancer/data-enhancer.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { Module } from '@nestjs/common'; @@ -7,7 +8,7 @@ import { HealthService } from './health.service'; @Module({ controllers: [HealthController], - imports: [ConfigurationModule, DataProviderModule], + imports: [ConfigurationModule, DataEnhancerModule, DataProviderModule], providers: [HealthService] }) export class HealthModule {} diff --git a/apps/api/src/app/health/health.service.ts b/apps/api/src/app/health/health.service.ts index afbcc0a74..8fac2dde9 100644 --- a/apps/api/src/app/health/health.service.ts +++ b/apps/api/src/app/health/health.service.ts @@ -1,3 +1,4 @@ +import { DataEnhancerService } from '@ghostfolio/api/services/data-provider/data-enhancer/data-enhancer.service'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; import { Injectable } from '@nestjs/common'; import { DataSource } from '@prisma/client'; @@ -5,9 +6,14 @@ import { DataSource } from '@prisma/client'; @Injectable() export class HealthService { public constructor( + private readonly dataEnhancerService: DataEnhancerService, private readonly dataProviderService: DataProviderService ) {} + public async hasResponseFromDataEnhancer(aName: string) { + return this.dataEnhancerService.enhance(aName); + } + public async hasResponseFromDataProvider(aDataSource: DataSource) { return this.dataProviderService.checkQuote(aDataSource); } diff --git a/apps/api/src/app/import/import.service.ts b/apps/api/src/app/import/import.service.ts index 026f3610e..da0e4806c 100644 --- a/apps/api/src/app/import/import.service.ts +++ b/apps/api/src/app/import/import.service.ts @@ -566,7 +566,7 @@ export class ImportService { ]) )?.[symbol]; - if (!assetProfile) { + if (!assetProfile?.name) { throw new Error( `activities.${index}.symbol ("${symbol}") is not valid for the specified data source ("${dataSource}")` ); diff --git a/apps/api/src/app/info/info.module.ts b/apps/api/src/app/info/info.module.ts index 75d681b56..a6b5b5b0b 100644 --- a/apps/api/src/app/info/info.module.ts +++ b/apps/api/src/app/info/info.module.ts @@ -1,6 +1,7 @@ import { BenchmarkModule } from '@ghostfolio/api/app/benchmark/benchmark.module'; import { PlatformModule } from '@ghostfolio/api/app/platform/platform.module'; import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; +import { UserModule } from '@ghostfolio/api/app/user/user.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { DataGatheringModule } from '@ghostfolio/api/services/data-gathering/data-gathering.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; @@ -28,11 +29,11 @@ import { InfoService } from './info.service'; signOptions: { expiresIn: '30 days' } }), PlatformModule, - PrismaModule, PropertyModule, RedisCacheModule, SymbolProfileModule, - TagModule + TagModule, + UserModule ], providers: [InfoService] }) diff --git a/apps/api/src/app/info/info.service.ts b/apps/api/src/app/info/info.service.ts index 7af5e284a..ec294bc25 100644 --- a/apps/api/src/app/info/info.service.ts +++ b/apps/api/src/app/info/info.service.ts @@ -1,9 +1,9 @@ import { BenchmarkService } from '@ghostfolio/api/app/benchmark/benchmark.service'; import { PlatformService } from '@ghostfolio/api/app/platform/platform.service'; import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { UserService } from '@ghostfolio/api/app/user/user.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; -import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; import { PropertyService } from '@ghostfolio/api/services/property/property.service'; import { TagService } from '@ghostfolio/api/services/tag/tag.service'; import { @@ -45,10 +45,10 @@ export class InfoService { private readonly exchangeRateDataService: ExchangeRateDataService, private readonly jwtService: JwtService, private readonly platformService: PlatformService, - private readonly prismaService: PrismaService, private readonly propertyService: PropertyService, private readonly redisCacheService: RedisCacheService, - private readonly tagService: TagService + private readonly tagService: TagService, + private readonly userService: UserService ) {} public async get(): Promise { @@ -146,12 +146,7 @@ export class InfoService { } private async countActiveUsers(aDays: number) { - return await this.prismaService.user.count({ - orderBy: { - Analytics: { - updatedAt: 'desc' - } - }, + return this.userService.count({ where: { AND: [ { @@ -224,10 +219,7 @@ export class InfoService { } private async countNewUsers(aDays: number) { - return await this.prismaService.user.count({ - orderBy: { - createdAt: 'desc' - }, + return this.userService.count({ where: { AND: [ { @@ -318,11 +310,10 @@ export class InfoService { return undefined; } - const stripeConfig = (await this.prismaService.property.findUnique({ - where: { key: PROPERTY_STRIPE_CONFIG } - })) ?? { value: '{}' }; - - return JSON.parse(stripeConfig.value); + return ( + ((await this.propertyService.getByKey(PROPERTY_STRIPE_CONFIG)) as any) ?? + {} + ); } private async getUptime(): Promise { diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index c40ff2d22..6deda49b7 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -465,9 +465,8 @@ export class PortfolioService { transactionPoints[0]?.date ?? format(new Date(), DATE_FORMAT) ); const startDate = this.getStartDate(dateRange, portfolioStart); - const currentPositions = await portfolioCalculator.getCurrentPositions( - startDate - ); + const currentPositions = + await portfolioCalculator.getCurrentPositions(startDate); const cashDetails = await this.accountService.getCashDetails({ filters, @@ -805,9 +804,8 @@ export class PortfolioService { const transactionPoints = portfolioCalculator.getTransactionPoints(); const portfolioStart = parseDate(transactionPoints[0].date); - const currentPositions = await portfolioCalculator.getCurrentPositions( - portfolioStart - ); + const currentPositions = + await portfolioCalculator.getCurrentPositions(portfolioStart); const position = currentPositions.positions.find( (item) => item.symbol === aSymbol @@ -1041,9 +1039,8 @@ export class PortfolioService { const portfolioStart = parseDate(transactionPoints[0].date); const startDate = this.getStartDate(dateRange, portfolioStart); - const currentPositions = await portfolioCalculator.getCurrentPositions( - startDate - ); + const currentPositions = + await portfolioCalculator.getCurrentPositions(startDate); const positions = currentPositions.positions.filter( (item) => !item.quantity.eq(0) @@ -1233,9 +1230,8 @@ export class PortfolioService { portfolioCalculator.setTransactionPoints(transactionPoints); const portfolioStart = parseDate(transactionPoints[0].date); - const currentPositions = await portfolioCalculator.getCurrentPositions( - portfolioStart - ); + const currentPositions = + await portfolioCalculator.getCurrentPositions(portfolioStart); const positions = currentPositions.positions.filter( (item) => !item.quantity.eq(0) diff --git a/apps/api/src/app/subscription/subscription.service.ts b/apps/api/src/app/subscription/subscription.service.ts index c3e01851d..d94dd68ad 100644 --- a/apps/api/src/app/subscription/subscription.service.ts +++ b/apps/api/src/app/subscription/subscription.service.ts @@ -93,9 +93,8 @@ export class SubscriptionService { public async createSubscriptionViaStripe(aCheckoutSessionId: string) { try { - const session = await this.stripe.checkout.sessions.retrieve( - aCheckoutSessionId - ); + const session = + await this.stripe.checkout.sessions.retrieve(aCheckoutSessionId); await this.createSubscription({ price: session.amount_total / 100, diff --git a/apps/api/src/app/symbol/symbol.controller.ts b/apps/api/src/app/symbol/symbol.controller.ts index e09b08f5b..ad9042991 100644 --- a/apps/api/src/app/symbol/symbol.controller.ts +++ b/apps/api/src/app/symbol/symbol.controller.ts @@ -15,13 +15,13 @@ import { import { REQUEST } from '@nestjs/core'; import { AuthGuard } from '@nestjs/passport'; import { DataSource } from '@prisma/client'; +import { parseISO } from 'date-fns'; import { StatusCodes, getReasonPhrase } from 'http-status-codes'; import { isDate, isEmpty } from 'lodash'; import { LookupItem } from './interfaces/lookup-item.interface'; import { SymbolItem } from './interfaces/symbol-item.interface'; import { SymbolService } from './symbol.service'; -import { parseISO } from 'date-fns'; @Controller('symbol') export class SymbolController { diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index 2645c88f7..c5cc3c8ce 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -33,6 +33,10 @@ export class UserService { private readonly tagService: TagService ) {} + public async count(args?: Prisma.UserCountArgs) { + return this.prismaService.user.count(args); + } + public async getUser( { Account, id, permissions, Settings, subscription }: UserWithSettings, aLocale = locale diff --git a/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json b/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json index 413425f68..7b1f42e31 100644 --- a/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json +++ b/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json @@ -51,7 +51,9 @@ "3FT": "ThreeFold Token", "3ULL": "3ULL Coin", "3XD": "3DChain", + "420CHAN": "420chan", "4ART": "4ART Coin", + "4CHAN": "4Chan", "4JNET": "4JNET", "77G": "GraphenTech", "7E": "7ELEVEN", @@ -60,6 +62,7 @@ "8BT": "8 Circuit Studios", "8PAY": "8Pay", "8X8": "8X8 Protocol", + "9GAG": "9GAG", "A5T": "Alpha5", "AAA": "Moon Rabbit", "AAB": "AAX Token", @@ -101,6 +104,7 @@ "ACN": "AvonCoin", "ACOIN": "ACoin", "ACP": "Anarchists Prime", + "ACQ": "Acquire.Fi", "ACS": "Access Protocol", "ACT": "Achain", "ACTIN": "Actinium", @@ -180,7 +184,7 @@ "AGX": "Agricoin", "AHOO": "Ahoolee", "AHT": "AhaToken", - "AI": "Multiverse", + "AI": "AiDoge", "AIB": "AdvancedInternetBlock", "AIBB": "AiBB", "AIBK": "AIB Utility Token", @@ -213,6 +217,7 @@ "AKA": "Akroma", "AKITA": "Akita Inu", "AKN": "Akoin", + "AKNC": "Aave KNC v1", "AKRO": "Akropolis", "AKT": "Akash Network", "AKTIO": "AKTIO Coin", @@ -237,12 +242,14 @@ "ALIC": "AliCoin", "ALICE": "My Neighbor Alice", "ALIEN": "AlienCoin", + "ALINK": "Aave LINK v1", "ALIS": "ALISmedia", "ALITA": "Alita Network", "ALIX": "AlinX", "ALKI": "Alkimi", "ALLBI": "ALL BEST ICO", "ALLEY": "NFT Alley", + "ALLIN": "All in", "ALN": "Aluna", "ALOHA": "Aloha", "ALP": "Alphacon", @@ -410,12 +417,14 @@ "ARIX": "Arix", "ARK": "ARK", "ARKER": "Arker", + "ARKM": "Arkham", "ARKN": "Ark Rivals", "ARM": "Armory Coin", "ARMOR": "ARMOR", "ARMR": "ARMR", "ARMS": "2Acoin", "ARNA": "ARNA Panacea", + "ARNM": "Arenum", "ARNO": "ARNO", "ARNX": "Aeron", "ARNXM": "Armor NXM", @@ -472,6 +481,7 @@ "ASTO": "Altered State Token", "ASTON": "Aston", "ASTR": "Astar", + "ASTRAFER": "Astrafer", "ASTRAL": "Astral", "ASTRO": "AstroSwap", "ASTROC": "Astroport Classic", @@ -531,6 +541,7 @@ "AURY": "Aurory", "AUSCM": "Auric Network", "AUSD": "Appeal dollar", + "AUSDC": "Aave USDC v1", "AUT": "Autoria", "AUTHORSHIP": "Authorship", "AUTO": "Auto", @@ -612,6 +623,7 @@ "BACK": "DollarBack", "BACOIN": "BACoin", "BACON": "BaconDAO (BACON)", + "BAD": "Bad Idea AI", "BADGER": "Badger DAO", "BAG": "BondAppetit", "BAGS": "Basis Gold Share", @@ -662,6 +674,7 @@ "BBCT": "TraDove B2BCoin", "BBDT": "BBD Token", "BBF": "Bubblefong", + "BBFT": "Block Busters Tech Token", "BBG": "BigBang", "BBGC": "BigBang Game", "BBI": "BelugaPay", @@ -725,6 +738,7 @@ "BDX": "Beldex", "BDY": "Buddy DAO", "BEACH": "BeachCoin", + "BEAI": "BeNFT Solutions", "BEAM": "Beam", "BEAN": "BeanCash", "BEAST": "CryptoBeast", @@ -806,6 +820,7 @@ "BIDR": "Binance IDR Stable Coin", "BIFI": "Beefy.Finance", "BIFIF": "BiFi", + "BIG": "Big Eyes", "BIGHAN": "BighanCoin", "BIGSB": "BigShortBets", "BIGUP": "BigUp", @@ -1090,6 +1105,7 @@ "BRNK": "Brank", "BRNX": "Bronix", "BRO": "Bitradio", + "BROCK": "Bitrock", "BRONZ": "BitBronze", "BRT": "Bikerush", "BRTR": "Barter", @@ -1226,7 +1242,7 @@ "BULL": "Bullieverse", "BULLC": "BuySell", "BULLION": "BullionFX", - "BULLS": "BullshitCoin", + "BULLS": "Bull Coin", "BULLSH": "Bullshit Inu", "BUMN": "BUMooN", "BUMP": "Bumper", @@ -1277,6 +1293,7 @@ "BZKY": "Bizkey", "BZL": "BZLCoin", "BZNT": "Bezant", + "BZR": "Bazaars", "BZRX": "bZx Protocol", "BZX": "Bitcoin Zero", "BZZ": "Swarmv", @@ -1319,8 +1336,10 @@ "CAP": "BottleCaps", "CAPD": "Capdax", "CAPP": "Cappasity", + "CAPRICOIN": "CapriCoin", "CAPS": "Ternoa", "CAPT": "Bitcoin Captain", + "CAPTAINPLANET": "Captain Planet", "CAR": "CarBlock", "CARAT": "Carats Token", "CARBON": "Carboncoin", @@ -1478,6 +1497,7 @@ "CHECKR": "CheckerChain", "CHECOIN": "CheCoin", "CHEDDA": "Chedda", + "CHEEL": "Cheelee", "CHEESE": "CHEESE", "CHEESUS": "Cheesus", "CHEQ": "CHEQD Network", @@ -1520,7 +1540,8 @@ "CHX": "Own", "CHY": "Concern Poverty Chain", "CHZ": "Chiliz", - "CIC": "CIChain", + "CIC": "Crazy Internet Coin", + "CICHAIN": "CIChain", "CIF": "Crypto Improvement Fund", "CIM": "COINCOME", "CIN": "CinderCoin", @@ -1630,7 +1651,6 @@ "COB": "Cobinhood", "COC": "Coin of the champions", "COCK": "Shibacock", - "COCOS": "COCOS BCX", "CODEO": "Codeo Token", "CODEX": "CODEX Finance", "CODI": "Codi Finance", @@ -1659,7 +1679,7 @@ "COLX": "ColossusCoinXT", "COM": "Coliseum", "COMB": "Combo", - "COMBO": "Furucombo", + "COMBO": "COMBO", "COMFI": "CompliFi", "COMM": "Community Coin", "COMMUNITYCOIN": "Community Coin", @@ -1672,7 +1692,6 @@ "CONI": "CoinBene", "CONS": "ConSpiracy Coin", "CONSENTIUM": "Consentium", - "CONT": "Contentos", "CONUN": "CONUN", "CONV": "Convergence", "COOK": "Cook", @@ -1683,17 +1702,19 @@ "COPS": "Cops Finance", "COR": "Corion", "CORAL": "CoralPay", - "CORE": "Coreum", + "CORE": "Core", "COREDAO": "coreDAO", "COREG": "Core Group Asset", + "COREUM": "Coreum", "CORGI": "Corgi Inu", "CORN": "CORN", "CORX": "CorionX", - "COS": "COS", + "COS": "Contentos", "COSHI": "CoShi Inu", "COSM": "CosmoChain", "COSMIC": "CosmicSwap", "COSP": "Cosplay Token", + "COSS": "COS", "COSX": "Cosmecoin", "COT": "CoTrader", "COTI": "COTI", @@ -1729,7 +1750,7 @@ "CPOOL": "Clearpool", "CPROP": "CPROP", "CPRX": "Crypto Perx", - "CPS": "CapriCoin", + "CPS": "Cryptostone", "CPT": "Cryptaur", "CPU": "CPUcoin", "CPX": "Apex Token", @@ -1796,6 +1817,7 @@ "CRTS": "Cratos", "CRU": "Crust Network", "CRV": "Curve DAO Token", + "CRVUSD": "crvUSD", "CRW": "Crown Coin", "CRWD": "CRWD Network", "CRWNY": "Crowny Token", @@ -1843,7 +1865,7 @@ "CTLX": "Cash Telex", "CTN": "Continuum Finance", "CTO": "Crypto", - "CTP": "Captain Planet", + "CTP": "Ctomorrow Platform", "CTPL": "Cultiplan", "CTPT": "Contents Protocol", "CTR": "Creator Platform", @@ -2007,6 +2029,7 @@ "DBC": "DeepBrain Chain", "DBCCOIN": "Datablockchain", "DBD": "Day By Day", + "DBEAR": "DBear Coin", "DBET": "Decent.bet", "DBIC": "DubaiCoin", "DBIX": "DubaiCoin", @@ -2058,6 +2081,7 @@ "DEEP": "DeepCloud AI", "DEEPG": "Deep Gold", "DEEX": "DEEX", + "DEEZ": "DEEZ NUTS", "DEFI": "Defi", "DEFI5": "DEFI Top 5 Tokens Index", "DEFIL": "DeFIL", @@ -2162,11 +2186,12 @@ "DIEM": "Facebook Diem", "DIESEL": "Diesel", "DIFX": "Digital Financial Exchange", - "DIG": "Dignity", + "DIG": "DIEGO", "DIGG": "DIGG", "DIGIC": "DigiCube", "DIGIF": "DigiFel", "DIGITAL": "Digital Reserve Currency", + "DIGNITY": "Dignity", "DIGS": "Diggits", "DIKO": "Arkadiko", "DILI": "D Community", @@ -2246,6 +2271,7 @@ "DOGBOSS": "Dog Boss", "DOGDEFI": "DogDeFiCoin", "DOGE": "Dogecoin", + "DOGE20": "Doge 2.0", "DOGEBNB": "DogeBNB", "DOGEC": "DogeCash", "DOGECEO": "Doge CEO", @@ -2539,7 +2565,7 @@ "ELONGT": "Elon GOAT", "ELONONE": "AstroElon", "ELP": "Ellerium", - "ELS": "Elysium", + "ELS": "Ethlas", "ELT": "Element Black", "ELTC2": "eLTC", "ELTCOIN": "ELTCOIN", @@ -2548,6 +2574,7 @@ "ELVN": "11Minutes", "ELX": "Energy Ledger", "ELY": "Elysian", + "ELYSIUM": "Elysium", "EM": "Eminer", "EMANATE": "EMANATE", "EMAR": "EmaratCoin", @@ -2559,6 +2586,7 @@ "EMC2": "Einsteinium", "EMD": "Emerald", "EMIGR": "EmiratesGoldCoin", + "EML": "EML Protocol", "EMN.CUR": "Eastman Chemical", "EMON": "Ethermon", "EMOT": "Sentigraph.io", @@ -2692,6 +2720,7 @@ "ETHD": "Ethereum Dark", "ETHER": "Etherparty", "ETHERDELTA": "EtherDelta", + "ETHERKING": "Ether Kingdoms Token", "ETHERNITY": "Ethernity Chain", "ETHF": "EthereumFair", "ETHIX": "EthicHub", @@ -2709,6 +2738,7 @@ "ETHSHIB": "Eth Shiba", "ETHV": "Ethverse", "ETHW": "Ethereum PoW", + "ETHX": "Stader ETHx", "ETHY": "Ethereum Yield", "ETI": "EtherInc", "ETK": "Energi Token", @@ -2722,7 +2752,7 @@ "ETR": "Electric Token", "ETRNT": "Eternal Trusts", "ETS": "ETH Share", - "ETSC": "​Ether star blockchain", + "ETSC": "Ether star blockchain", "ETT": "EncryptoTel", "ETY": "Ethereum Cloud", "ETZ": "EtherZero", @@ -2773,6 +2803,7 @@ "EXB": "ExaByte (EXB)", "EXC": "Eximchain", "EXCC": "ExchangeCoin", + "EXCHANGEN": "ExchangeN", "EXCL": "Exclusive Coin", "EXE": "ExeCoin", "EXFI": "Flare Finance", @@ -2781,7 +2812,7 @@ "EXLT": "ExtraLovers", "EXM": "EXMO Coin", "EXMR": "EXMR FDN", - "EXN": "ExchangeN", + "EXN": "Exeno", "EXO": "Exosis", "EXP": "Expanse", "EXRD": "Radix", @@ -2814,6 +2845,7 @@ "FAIR": "FairCoin", "FAIRC": "Faireum Token", "FAIRG": "FairGame", + "FAKE": "FAKE COIN", "FAKT": "Medifakt", "FALCONS": "Falcon Swaps", "FAME": "Fame MMA", @@ -2860,6 +2892,7 @@ "FDO": "Firdaos", "FDR": "French Digital Reserve", "FDT": "Frutti Dino", + "FDUSD": "First Digital USD", "FDX": "fidentiaX", "FDZ": "Friendz", "FEAR": "Fear", @@ -2870,6 +2903,7 @@ "FEN": "First Ever NFT", "FENOMY": "Fenomy", "FER": "Ferro", + "FERC": "FairERC20", "FERMA": "Ferma", "FESS": "Fesschain", "FET": "Fetch.AI", @@ -2931,7 +2965,7 @@ "FLASH": "Flashstake", "FLASHC": "FLASH coin", "FLC": "FlowChainCoin", - "FLD": "FLUID", + "FLD": "FluidAI", "FLDC": "Folding Coin", "FLDT": "FairyLand", "FLETA": "FLETA", @@ -3091,6 +3125,7 @@ "FUEL": "Jetfuel Finance", "FUJIN": "Fujinto", "FUKU": "Furukuru", + "FUMO": "Alien Milady Fumo", "FUN": "FUN Token", "FUNC": "FunCoin", "FUND": "Unification", @@ -3101,6 +3136,7 @@ "FUNDZ": "FundFantasy", "FUNK": "Cypherfunks Coin", "FUR": "Furio", + "FURU": "Furucombo", "FURY": "Engines of Fury", "FUS": "Fus", "FUSE": "Fuse Network Token", @@ -3118,6 +3154,7 @@ "FXP": "FXPay", "FXS": "Frax Share", "FXT": "FuzeX", + "FXY": "Floxypay", "FYN": "Affyn", "FYP": "FlypMe", "FYZ": "Fyooz", @@ -3172,6 +3209,7 @@ "GAT": "GATCOIN", "GATE": "GATENet", "GATEWAY": "Gateway Protocol", + "GAYPEPE": "Gay Pepe", "GAZE": "GazeTV", "GB": "GoldBlocks", "GBA": "Geeba", @@ -3222,6 +3260,7 @@ "GEMZ": "Gemz Social", "GEN": "DAOstack", "GENE": "Genopets", + "GENIE": "The Genie", "GENIX": "Genix", "GENS": "Genshiro", "GENSTAKE": "Genstake", @@ -3261,6 +3300,7 @@ "GHCOLD": "Galaxy Heroes Coin", "GHD": "Giftedhands", "GHNY": "Grizzly Honey", + "GHO": "GHO", "GHOST": "GhostbyMcAfee", "GHOSTCOIN": "GhostCoin", "GHOSTM": "GhostMarket", @@ -3274,6 +3314,7 @@ "GIFT": "GiftNet", "GIG": "GigaCoin", "GIGA": "GigaSwap", + "GIGX": "GigXCoin", "GIM": "Gimli", "GIMMER": "Gimmer", "GIN": "GINcoin", @@ -3385,6 +3426,7 @@ "GOVT": "The Government Network", "GOZ": "Göztepe S.K. Fan Token", "GP": "Wizards And Dragons", + "GPBP": "Genius Playboy Billionaire Philanthropist", "GPKR": "Gold Poker", "GPL": "Gold Pressed Latinum", "GPPT": "Pluto Project Coin", @@ -3501,7 +3543,8 @@ "HALF": "0.5X Long Bitcoin Token", "HALFSHIT": "0.5X Long Shitcoin Index Token", "HALLO": "Halloween Coin", - "HALO": "Halo Platform", + "HALO": "Halo Coin", + "HALOPLATFORM": "Halo Platform", "HAM": "Hamster", "HAMS": "HamsterCoin", "HANA": "Hanacoin", @@ -3598,6 +3641,7 @@ "HILL": "President Clinton", "HINA": "Hina Inu", "HINT": "Hintchain", + "HIPPO": "HIPPO", "HIRE": "HireMatch", "HIT": "HitChain", "HITBTC": "HitBTC Token", @@ -3634,6 +3678,7 @@ "HNTR": "Hunter", "HNY": "Honey", "HNZO": "Hanzo Inu", + "HOBO": "HOBO THE BEAR", "HOD": "HoDooi.com", "HODL": "HOdlcoin", "HOGE": "Hoge Finance", @@ -3839,7 +3884,7 @@ "IMPCN": "Brain Space", "IMPER": "Impermax", "IMPS": "Impulse Coin", - "IMPT": "Ether Kingdoms Token", + "IMPT": "IMPT", "IMPULSE": "IMPULSE by FDR", "IMS": "Independent Money System", "IMST": "Imsmart", @@ -4001,6 +4046,7 @@ "JAM": "Tune.Fm", "JANE": "JaneCoin", "JAR": "Jarvis+", + "JARED": "Jared From Subway", "JASMY": "JasmyCoin", "JBS": "JumBucks Coin", "JBX": "Juicebox", @@ -4163,9 +4209,10 @@ "KIN": "Kin", "KIND": "Kind Ads", "KINE": "Kine Protocol", - "KING": "King Finance", + "KING": "KING", "KING93": "King93", "KINGDOMQUEST": "Kingdom Quest", + "KINGF": "King Finance", "KINGSHIB": "King Shiba", "KINGSWAP": "KingSwap", "KINT": "Kintsugi", @@ -4175,6 +4222,7 @@ "KISC": "Kaiser", "KISHIMOTO": "Kishimoto Inu", "KISHU": "Kishu Inu", + "KITA": "KITA INU", "KITSU": "Kitsune Inu", "KITTY": "Kitty Inu", "KKO": "Kineko", @@ -4267,10 +4315,12 @@ "KUBO": "KUBO", "KUBOS": "KubosCoin", "KUE": "Kuende", + "KUJI": "Kujira", "KUMA": "Kuma Inu", "KUNCI": "Kunci Coin", "KUR": "Kuro", "KURT": "Kurrent", + "KUSA": "Kusa Inu", "KUSD": "Kowala", "KUSH": "KushCoin", "KUV": "Kuverit", @@ -4280,6 +4330,7 @@ "KVT": "Kinesis Velocity Token", "KWATT": "4New", "KWD": "KIWI DEFI", + "KWENTA": "Kwenta", "KWH": "KWHCoin", "KWIK": "KwikSwap", "KWS": "Knight War Spirits", @@ -4299,7 +4350,9 @@ "LABX": "Stakinglab", "LACCOIN": "LocalAgro", "LACE": "Lovelace World", + "LADYS": "Milady Meme Coin", "LAEEB": "LaEeb", + "LAELAPS": "Laelaps", "LAIKA": "Laika Protocol", "LALA": "LaLa World", "LAMB": "Lambda", @@ -4455,13 +4508,14 @@ "LLAND": "Lyfe Land", "LLG": "Loligo", "LLION": "Lydian Lion", - "LM": "LM Token", + "LM": "LeisureMeta", "LMAO": "LMAO Finance", "LMC": "LomoCoin", "LMCH": "Latamcash", "LMCSWAP": "LimoCoin SWAP", "LMR": "Lumerin", "LMT": "Lympo Market Token", + "LMTOKEN": "LM Token", "LMXC": "LimonX", "LMY": "Lunch Money", "LN": "LINK", @@ -4530,6 +4584,7 @@ "LRG": "Largo Coin", "LRN": "Loopring [NEO]", "LSD": "LightSpeedCoin", + "LSETH": "Liquid Staked ETH", "LSK": "Lisk", "LSP": "Lumenswap", "LSS": "Lossless", @@ -4626,6 +4681,7 @@ "MAEP": "Maester Protocol", "MAG": "Magnet", "MAGIC": "Magic", + "MAGICF": "MagicFox", "MAHA": "MahaDAO", "MAI": "Mindsync", "MAID": "MaidSafe Coin", @@ -4639,6 +4695,7 @@ "MANDOX": "MandoX", "MANGA": "Manga Token", "MANNA": "Manna", + "MANTLE": "Mantle", "MAP": "MAP Protocol", "MAPC": "MapCoin", "MAPE": "Mecha Morphing", @@ -4672,6 +4729,7 @@ "MATIC": "Polygon", "MATPAD": "MaticPad", "MATTER": "AntiMatter", + "MAV": "Maverick Protocol", "MAX": "MaxCoin", "MAXR": "Max Revive", "MAY": "Theresa May Coin", @@ -4776,6 +4834,7 @@ "MESA": "MetaVisa", "MESG": "MESG", "MESH": "MeshBox", + "MESSI": "MESSI COIN", "MET": "Metronome", "META": "Metadium", "METAC": "Metacoin", @@ -4881,6 +4940,7 @@ "MIODIO": "MIODIOCOIN", "MIOTA": "IOTA", "MIR": "Mirror Protocol", + "MIRACLE": "MIRACLE", "MIRC": "MIR COIN", "MIS": "Mithril Share", "MISA": "Sangkara", @@ -4938,7 +4998,6 @@ "MNRB": "MoneyRebel", "MNS": "Monnos", "MNST": "MoonStarter", - "MNT": "microNFT", "MNTC": "Manet Coin", "MNTG": "Monetas", "MNTL": "AssetMantle", @@ -4967,6 +5026,7 @@ "MOF": "Molecular Future (TRC20)", "MOFI": "MobiFi", "MOFOLD": "Molecular Future (ERC20)", + "MOG": "Mog Coin", "MOGU": "Mogu", "MOGX": "Mogu", "MOI": "MyOwnItem", @@ -4989,9 +5049,11 @@ "MONEYIMT": "MoneyToken", "MONF": "Monfter", "MONG": "MongCoin", + "MONG20": "Mongoose 2.0", "MONI": "Monsta Infinite", "MONK": "Monkey Project", "MONKEY": "Monkey", + "MONKEYS": "Monkeys Token", "MONO": "MonoX", "MONONOKEINU": "Mononoke Inu", "MONS": "Monsters Clan", @@ -5011,11 +5073,13 @@ "MOONSHOT": "Moonshot", "MOOO": "Hashtagger", "MOOV": "dotmoovs", + "MOOX": "Moox Protocol", "MOPS": "Mops", "MORA": "Meliora", "MORE": "More Coin", "MOS": "MOS Coin", "MOT": "Olympus Labs", + "MOTG": "MetaOctagon", "MOTI": "Motion", "MOTO": "Motocoin", "MOV": "MovieCoin", @@ -5076,6 +5140,7 @@ "MSWAP": "MoneySwap", "MT": "MyToken", "MTA": "Meta", + "MTB": "MetaBridge", "MTBC": "Metabolic", "MTC": "MEDICAL TOKEN CURRENCY", "MTCMN": "MTC Mesh", @@ -5108,6 +5173,7 @@ "MUE": "MonetaryUnit", "MULTI": "Multichain", "MULTIBOT": "Multibot", + "MULTIV": "Multiverse", "MUN": "MUNcoin", "MUNCH": "Munch Token", "MUSD": "mStable USD", @@ -5648,6 +5714,7 @@ "OZP": "OZAPHYRE", "P202": "Project 202", "P2PS": "P2P Solutions Foundation", + "PAAL": "PAAL AI", "PAC": "PAC Protocol", "PACOCA": "Pacoca", "PAD": "NearPad", @@ -5736,6 +5803,7 @@ "PEARL": "Pearl Finance", "PEC": "PeaceCoin", "PEEL": "Meta Apes", + "PEEPA": "Peepa", "PEEPS": "The People’s Coin", "PEG": "PegNet", "PEGS": "PegShares", @@ -5748,6 +5816,7 @@ "PEOPLE": "ConstitutionDAO", "PEOS": "pEOS", "PEPE": "Pepe", + "PEPE20": "Pepe 2.0", "PEPECASH": "Pepe Cash", "PEPPER": "Pepper Token", "PEPS": "PEPS Coin", @@ -5822,6 +5891,7 @@ "PINK": "PinkCoin", "PINKX": "PantherCoin", "PINMO": "Pinmo", + "PINO": "Pinocchu", "PINU": "Piccolo Inu", "PIO": "Pioneershares", "PIPI": "Pippi Finance", @@ -5885,6 +5955,7 @@ "PLS": "Pulsechain", "PLSD": "PulseDogecoin", "PLSPAD": "PulsePad", + "PLSX": "PulseX", "PLT": "Poollotto.finance", "PLTC": "PlatonCoin", "PLTX": "PlutusX", @@ -5911,7 +5982,6 @@ "PNK": "Kleros", "PNL": "True PNL", "PNODE": "Pinknode", - "PNP": "LogisticsX", "PNT": "pNetwork Token", "PNX": "PhantomX", "PNY": "Peony Coin", @@ -5927,6 +5997,7 @@ "POINTS": "Cryptsy Points", "POK": "Pokmonsters", "POKEM": "Pokemonio", + "POKEMON": "Pokemon", "POKER": "PokerCoin", "POKT": "Pocket Network", "POL": "Pool-X", @@ -6010,6 +6081,7 @@ "PRIME": "Echelon Prime", "PRIMECHAIN": "PrimeChain", "PRINT": "Printer.Finance", + "PRINTERIUM": "Printerium", "PRINTS": "FingerprintsDAO", "PRISM": "Prism", "PRIX": "Privatix", @@ -6033,7 +6105,7 @@ "PROTON": "Proton", "PROUD": "PROUD Money", "PROXI": "PROXI", - "PRP": "Papyrus", + "PRP": "Pepe Prime", "PRPS": "Purpose", "PRPT": "Purple Token", "PRQ": "PARSIQ", @@ -6042,7 +6114,7 @@ "PRTG": "Pre-Retogeum", "PRV": "PrivacySwap", "PRVS": "Previse", - "PRX": "Printerium", + "PRX": "Parex", "PRXY": "Proxy", "PRY": "PRIMARY", "PSB": "Planet Sandbox", @@ -6120,6 +6192,7 @@ "PYRAM": "Pyram Token", "PYRK": "Pyrk", "PYT": "Payther", + "PYUSD": "PayPal USD", "PZM": "Prizm", "Q1S": "Quantum1Net", "Q2C": "QubitCoin", @@ -6178,6 +6251,7 @@ "QUA": "Quantum Tech", "QUACK": "Rich Quack", "QUAM": "Quam Network", + "QUANT": "Quant Finance", "QUARASHI": "Quarashi Network", "QUARTZ": "Sandclock", "QUASA": "Quasacoin", @@ -6201,7 +6275,7 @@ "RAC": "RAcoin", "RACA": "Radio Caca", "RACEFI": "RaceFi", - "RAD": "Radicle", + "RAD": "Radworks", "RADAR": "DappRadar", "RADI": "RadicalCoin", "RADIO": "RadioShack", @@ -6220,7 +6294,7 @@ "RAM": "Ramifi Protocol", "RAMP": "RAMP", "RANKER": "RankerDao", - "RAP": "Rapture", + "RAP": "Philosoraptor", "RAPDOGE": "RapDoge", "RARE": "SuperRare", "RARI": "Rarible", @@ -6277,6 +6351,7 @@ "REA": "Realisto", "REAL": "RealLink", "REALM": "Realm", + "REALMS": "Realms of Ethernity", "REALPLATFORM": "REAL", "REALY": "Realy Metaverse", "REAP": "ReapChain", @@ -6287,6 +6362,7 @@ "RED": "RED TOKEN", "REDC": "RedCab", "REDCO": "Redcoin", + "REDDIT": "Reddit", "REDI": "REDi", "REDLANG": "RED", "REDLC": "Redlight Chain", @@ -6324,7 +6400,7 @@ "REST": "Restore", "RET": "RealTract", "RETAIL": "Retail.Global", - "RETH": "Realms of Ethernity", + "RETH": "Rocket Pool ETH", "RETH2": "rETH2", "RETIRE": "Retire Token", "REU": "REUCOIN", @@ -6351,6 +6427,7 @@ "RGP": "Rigel Protocol", "RGT": "Rari Governance Token", "RHEA": "Rhea", + "RHINO": "RHINO", "RHOC": "RChain", "RHP": "Rhypton Club", "RIC": "Riecoin", @@ -6490,6 +6567,7 @@ "RWE": "Real-World Evidence", "RWN": "Rowan Token", "RWS": "Robonomics Web Services", + "RXD": "Radiant", "RXT": "RIMAUNANGIS", "RYC": "RoyalCoin", "RYCN": "RoyalCoin 2.0", @@ -6564,6 +6642,7 @@ "SBTC": "Super Bitcoin", "SC": "Siacoin", "SCA": "SiaClassic", + "SCAM": "Scam Coin", "SCAP": "SafeCapital", "SCAR": "Velhalla", "SCASH": "SpaceCash", @@ -6624,6 +6703,7 @@ "SEER": "SEER", "SEI": "Sei", "SEL": "SelenCoin", + "SELF": "SELFCrypto", "SEM": "Semux", "SEN": "Sentaro", "SENATE": "SENATE", @@ -6665,6 +6745,7 @@ "SGE": "Society of Galactic Exploration", "SGLY": "Singularity", "SGN": "Signals Network", + "SGO": "SafuuGO", "SGOLD": "SpaceGold", "SGP": "SGPay", "SGR": "Sogur Currency", @@ -6684,6 +6765,7 @@ "SHEESH": "Sheesh it is bussin bussin", "SHEESHA": "Sheesha Finance", "SHELL": "Shell Token", + "SHERA": "Shera Tokens", "SHFL": "SHUFFLE!", "SHFT": "Shyft Network", "SHI": "Shirtum", @@ -6719,6 +6801,8 @@ "SHR": "ShareToken", "SHREK": "ShrekCoin", "SHROOM": "Shroom.Finance", + "SHROOMFOX": "Magic Shroom", + "SHS": "SHEESH", "SHX": "Stronghold Token", "SI": "Siren", "SIB": "SibCoin", @@ -7018,9 +7102,11 @@ "STEN": "Steneum Coin", "STEP": "Step Finance", "STEPH": "Step Hero", + "STEPR": "Step", "STEPS": "Steps", "STERLINGCOIN": "SterlingCoin", "STETH": "Staked Ether", + "STEWIE": "Stewie Coin", "STEX": "STEX", "STF": "Structure Finance", "STFX": "STFX", @@ -7055,7 +7141,7 @@ "STR": "Sourceless", "STRAKS": "Straks", "STRAX": "Stratis", - "STRAY": "Animal Token", + "STRAY": "Stray Dog", "STREAM": "STREAMIT COIN", "STRIP": "Stripto", "STRK": "Strike", @@ -7361,6 +7447,7 @@ "TOM": "TOM Finance", "TOMAHAWKCOIN": "Tomahawkcoin", "TOMB": "Tomb", + "TOMI": "tomiNet", "TOMO": "TomoChain", "TOMOE": "TomoChain ERC20", "TOMS": "TomTomCoin", @@ -7385,6 +7472,7 @@ "TOTM": "Totem", "TOWER": "Tower", "TOWN": "Town Star", + "TOX": "INTOverse", "TOZ": "Tozex", "TP": "Token Swap", "TPAD": "TrustPad", @@ -7600,6 +7688,7 @@ "UNITY": "SuperNET", "UNIVRS": "Universe", "UNIX": "UniX", + "UNLEASH": "UnleashClub", "UNN": "UNION Protocol Governance Token", "UNO": "Unobtanium", "UNORE": "UnoRe", @@ -7673,6 +7762,7 @@ "UTT": "United Traders Token", "UTU": "UTU Protocol", "UUU": "U Network", + "UWU": "uwu", "UZUMAKI": "Uzumaki Inu", "VAB": "Vabble", "VADER": "Vader Protocol", @@ -7695,6 +7785,7 @@ "VCF": "Valencia CF Fan Token", "VCG": "VCGamers", "VCK": "28VCK", + "VCORE": "VCORE", "VDG": "VeriDocGlobal", "VDL": "Vidulum", "VDO": "VidioCoin", @@ -7710,6 +7801,7 @@ "VEIL": "VEIL", "VELA": "Vela Token", "VELO": "Velo", + "VELOD": "Velodrome Finance", "VELOX": "Velox", "VELOXPROJECT": "Velox", "VEMP": "vEmpire DDAO", @@ -7782,6 +7874,7 @@ "VNT": "VNT Chain", "VNTW": "Value Network Token", "VNX": "VisionX", + "VNXAU": "VNX Gold", "VNXLU": "VNX Exchange", "VOCO": "Provoco", "VODKA": "Vodka Token", @@ -7902,7 +7995,8 @@ "WEC": "Whole Earth Coin", "WEGEN": "WeGen Platform", "WELD": "Weld", - "WELL": "Well", + "WELL": "Moonwell", + "WELLTOKEN": "Well", "WELT": "Fabwelt", "WELUPS": "Welups Blockchain", "WEMIX": "WEMIX", @@ -7958,6 +8052,7 @@ "WIX": "Wixlar", "WIZ": "WIZ Protocol", "WKD": "Wakanda Inu", + "WLD": "Worldcoin", "WLF": "Wolfs Group", "WLITI": "wLITI", "WLK": "Wolk", @@ -7983,6 +8078,7 @@ "WNZ": "Winerz", "WOA": "Wrapped Origin Axie", "WOD": "World of Defish", + "WOID": "WORLD ID", "WOJ": "Wojak Finance", "WOLF": "Insanity Coin", "WOLFILAND": "Wolfiland", @@ -8000,6 +8096,7 @@ "WOOFY": "Woofy", "WOOL": "Wolf Game Wool", "WOONK": "Woonkly", + "WOOO": "wooonen", "WOOP": "Woonkly Power", "WOP": "WorldPay", "WORLD": "World Token", @@ -8010,6 +8107,7 @@ "WOZX": "Efforce", "WPC": "WePiggy Coin", "WPE": "OPES (Wrapped PE)", + "WPLS": "Wrapped Pulse", "WPP": "Green Energy Token", "WPR": "WePower", "WQT": "Work Quest", @@ -8049,6 +8147,7 @@ "WZEC": "Wrapped Zcash", "WZENIQ": "Wrapped Zeniq (ETH)", "WZRD": "Wizardia", + "X": "AI-X", "X2": "X2Coin", "X2Y2": "X2Y2", "X42": "X42 Protocol", @@ -8096,7 +8195,7 @@ "XCI": "Cannabis Industry Coin", "XCLR": "ClearCoin", "XCM": "CoinMetro", - "XCN": "Chain", + "XCN": "Onyxcoin", "XCO": "XCoin", "XCONSOL": "X-Consoles", "XCP": "CounterParty", @@ -8365,6 +8464,7 @@ "YUANG": "Yuang Coin", "YUCJ": "Yu Coin", "YUCT": "Yucreat", + "YUDI": "Yudi", "YUM": "Yumerium", "YUMMY": "Yummy", "YUP": "Crowdholding", diff --git a/apps/api/src/assets/cryptocurrencies/custom.json b/apps/api/src/assets/cryptocurrencies/custom.json index 2ccad3881..1215114bb 100644 --- a/apps/api/src/assets/cryptocurrencies/custom.json +++ b/apps/api/src/assets/cryptocurrencies/custom.json @@ -1,4 +1,5 @@ { + "CYBER24781": "CyberConnect", "LUNA1": "Terra", "LUNA2": "Terra", "SGB1": "Songbird", diff --git a/apps/api/src/assets/sitemap.xml b/apps/api/src/assets/sitemap.xml index 10f20ca46..71d14696a 100644 --- a/apps/api/src/assets/sitemap.xml +++ b/apps/api/src/assets/sitemap.xml @@ -50,6 +50,110 @@ https://ghostfol.io/de/ressourcen ${currentDate}T00:00:00+00:00 + + https://ghostfol.io/de/ressourcen/personal-finance-tools + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-altoo + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-copilot-money + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-delta + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-divvydiary + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-exirio + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-folishare + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-getquin + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-gospatz + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-justetf + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-kubera + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-markets.sh + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-maybe-finance + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-monse + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-parqet + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-plannix + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-portfolio-dividend-tracker + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-portseido + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-projectionlab + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-seeking-alpha + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-sharesight + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-simple-portfolio + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-snowball-analytics + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-sumio + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-utluna + ${currentDate}T00:00:00+00:00 + + + https://ghostfol.io/de/ressourcen/personal-finance-tools/open-source-alternative-zu-yeekatee + ${currentDate}T00:00:00+00:00 + https://ghostfol.io/de/ueber-uns ${currentDate}T00:00:00+00:00 @@ -142,6 +246,10 @@ https://ghostfol.io/en/blog/2023/07/exploring-the-path-to-fire ${currentDate}T00:00:00+00:00 + + https://ghostfol.io/en/blog/2023/08/ghostfolio-joins-oss-friends + ${currentDate}T00:00:00+00:00 + https://ghostfol.io/en/faq ${currentDate}T00:00:00+00:00 @@ -492,6 +600,10 @@ https://ghostfol.io/nl/vaak-gestelde-vragen ${currentDate}T00:00:00+00:00 + + https://ghostfol.io/pt + ${currentDate}T00:00:00+00:00 + https://ghostfol.io/pt/blog ${currentDate}T00:00:00+00:00 diff --git a/apps/api/src/middlewares/html-template.middleware.ts b/apps/api/src/middlewares/html-template.middleware.ts index efbd60fa7..acb3f5aa0 100644 --- a/apps/api/src/middlewares/html-template.middleware.ts +++ b/apps/api/src/middlewares/html-template.middleware.ts @@ -71,6 +71,10 @@ const locales = { '/en/blog/2023/07/exploring-the-path-to-fire': { featureGraphicPath: 'assets/images/blog/20230701.jpg', title: `Exploring the Path to FIRE - ${titleShort}` + }, + '/en/blog/2023/08/ghostfolio-joins-oss-friends': { + featureGraphicPath: 'assets/images/blog/ghostfolio-joins-oss-friends.png', + title: `Ghostfolio joins OSS Friends - ${titleShort}` } }; diff --git a/apps/api/src/services/data-gathering/data-gathering.service.ts b/apps/api/src/services/data-gathering/data-gathering.service.ts index 7718ef394..77b79835d 100644 --- a/apps/api/src/services/data-gathering/data-gathering.service.ts +++ b/apps/api/src/services/data-gathering/data-gathering.service.ts @@ -127,12 +127,10 @@ export class DataGatheringService { uniqueAssets = await this.getUniqueAssets(); } - const assetProfiles = await this.dataProviderService.getAssetProfiles( - uniqueAssets - ); - const symbolProfiles = await this.symbolProfileService.getSymbolProfiles( - uniqueAssets - ); + const assetProfiles = + await this.dataProviderService.getAssetProfiles(uniqueAssets); + const symbolProfiles = + await this.symbolProfileService.getSymbolProfiles(uniqueAssets); for (const [symbol, assetProfile] of Object.entries(assetProfiles)) { const symbolMapping = symbolProfiles.find((symbolProfile) => { diff --git a/apps/api/src/services/data-provider/data-enhancer/data-enhancer.module.ts b/apps/api/src/services/data-provider/data-enhancer/data-enhancer.module.ts index a658ef448..069309508 100644 --- a/apps/api/src/services/data-provider/data-enhancer/data-enhancer.module.ts +++ b/apps/api/src/services/data-provider/data-enhancer/data-enhancer.module.ts @@ -4,14 +4,18 @@ import { TrackinsightDataEnhancerService } from '@ghostfolio/api/services/data-p import { YahooFinanceDataEnhancerService } from '@ghostfolio/api/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service'; import { Module } from '@nestjs/common'; +import { DataEnhancerService } from './data-enhancer.service'; + @Module({ exports: [ - 'DataEnhancers', + DataEnhancerService, TrackinsightDataEnhancerService, - YahooFinanceDataEnhancerService + YahooFinanceDataEnhancerService, + 'DataEnhancers' ], imports: [ConfigurationModule, CryptocurrencyModule], providers: [ + DataEnhancerService, TrackinsightDataEnhancerService, YahooFinanceDataEnhancerService, { diff --git a/apps/api/src/services/data-provider/data-enhancer/data-enhancer.service.ts b/apps/api/src/services/data-provider/data-enhancer/data-enhancer.service.ts new file mode 100644 index 000000000..e5038c7c6 --- /dev/null +++ b/apps/api/src/services/data-provider/data-enhancer/data-enhancer.service.ts @@ -0,0 +1,44 @@ +import { DataEnhancerInterface } from '@ghostfolio/api/services/data-provider/interfaces/data-enhancer.interface'; +import { HttpException, Inject, Injectable } from '@nestjs/common'; +import { Prisma } from '@prisma/client'; +import { StatusCodes, getReasonPhrase } from 'http-status-codes'; + +@Injectable() +export class DataEnhancerService { + public constructor( + @Inject('DataEnhancers') + private readonly dataEnhancers: DataEnhancerInterface[] + ) {} + + public async enhance(aName: string) { + const dataEnhancer = this.dataEnhancers.find((dataEnhancer) => { + return dataEnhancer.getName() === aName; + }); + + if (!dataEnhancer) { + throw new HttpException( + getReasonPhrase(StatusCodes.NOT_FOUND), + StatusCodes.NOT_FOUND + ); + } + + try { + const assetProfile = await dataEnhancer.enhance({ + response: { + assetClass: 'EQUITY', + assetSubClass: 'ETF' + }, + symbol: dataEnhancer.getTestSymbol() + }); + + if ( + (assetProfile.countries as unknown as Prisma.JsonArray)?.length > 0 && + (assetProfile.sectors as unknown as Prisma.JsonArray)?.length > 0 + ) { + return true; + } + } catch {} + + return false; + } +} 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 a18d82449..07c0234b6 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 @@ -7,7 +7,7 @@ import got from 'got'; @Injectable() export class TrackinsightDataEnhancerService implements DataEnhancerInterface { - private static baseUrl = 'https://data.trackinsight.com'; + private static baseUrl = 'https://www.trackinsight.com/data-api'; private static countries = require('countries-list/dist/countries.json'); private static countriesMapping = { 'Russian Federation': 'Russia' @@ -33,14 +33,22 @@ export class TrackinsightDataEnhancerService implements DataEnhancerInterface { } const profile = await got( - `${TrackinsightDataEnhancerService.baseUrl}/data-api/funds/${symbol}.json` + `${TrackinsightDataEnhancerService.baseUrl}/funds/${symbol}.json` ) .json() .catch(() => { - return {}; + return got( + `${TrackinsightDataEnhancerService.baseUrl}/funds/${symbol.split( + '.' + )?.[0]}.json` + ) + .json() + .catch(() => { + return {}; + }); }); - const isin = profile.isin?.split(';')?.[0]; + const isin = profile?.isin?.split(';')?.[0]; if (isin) { response.isin = isin; @@ -52,10 +60,14 @@ export class TrackinsightDataEnhancerService implements DataEnhancerInterface { .json() .catch(() => { return got( - `${TrackinsightDataEnhancerService.baseUrl}/holdings/${ - symbol.split('.')?.[0] - }.json` - ); + `${TrackinsightDataEnhancerService.baseUrl}/holdings/${symbol.split( + '.' + )?.[0]}.json` + ) + .json() + .catch(() => { + return {}; + }); }); if (holdings?.weight < 0.95) { @@ -114,4 +126,8 @@ export class TrackinsightDataEnhancerService implements DataEnhancerInterface { public getName() { return 'TRACKINSIGHT'; } + + public getTestSymbol() { + return 'QQQ'; + } } diff --git a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts index 5109823cc..8731e709c 100644 --- a/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts +++ b/apps/api/src/services/data-provider/data-enhancer/yahoo-finance/yahoo-finance.service.ts @@ -7,6 +7,7 @@ import { AssetClass, AssetSubClass, DataSource, + Prisma, SymbolProfile } from '@prisma/client'; import { countries } from 'countries-list'; @@ -90,15 +91,14 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { yahooSymbol = quotes[0].symbol; } - const { countries, sectors, url } = await this.getAssetProfile( - yahooSymbol - ); + const { countries, sectors, url } = + await this.getAssetProfile(yahooSymbol); - if (countries) { + if ((countries as unknown as Prisma.JsonArray)?.length > 0) { response.countries = countries; } - if (sectors) { + if ((sectors as unknown as Prisma.JsonArray)?.length > 0) { response.sectors = sectors; } @@ -225,6 +225,10 @@ export class YahooFinanceDataEnhancerService implements DataEnhancerInterface { return DataSource.YAHOO; } + public getTestSymbol() { + return 'AAPL'; + } + public parseAssetClass({ quoteType, shortName diff --git a/apps/api/src/services/data-provider/interfaces/data-enhancer.interface.ts b/apps/api/src/services/data-provider/interfaces/data-enhancer.interface.ts index 4e5ce8cba..9c6db9196 100644 --- a/apps/api/src/services/data-provider/interfaces/data-enhancer.interface.ts +++ b/apps/api/src/services/data-provider/interfaces/data-enhancer.interface.ts @@ -10,4 +10,6 @@ export interface DataEnhancerInterface { }): Promise>; getName(): string; + + getTestSymbol(): string; } diff --git a/apps/api/src/services/twitter-bot/twitter-bot.service.ts b/apps/api/src/services/twitter-bot/twitter-bot.service.ts index 218dd291f..d3e7fb91c 100644 --- a/apps/api/src/services/twitter-bot/twitter-bot.service.ts +++ b/apps/api/src/services/twitter-bot/twitter-bot.service.ts @@ -65,9 +65,8 @@ export class TwitterBotService { status += benchmarkListing; } - const { data: createdTweet } = await this.twitterClient.v2.tweet( - status - ); + const { data: createdTweet } = + await this.twitterClient.v2.tweet(status); Logger.log( `Fear & Greed Index has been tweeted: https://twitter.com/ghostfolio_/status/${createdTweet.id}`, diff --git a/apps/client/src/app/components/admin-market-data-detail/admin-market-data-detail.component.html b/apps/client/src/app/components/admin-market-data-detail/admin-market-data-detail.component.html index dc64ed120..d6f67faa3 100644 --- a/apps/client/src/app/components/admin-market-data-detail/admin-market-data-detail.component.html +++ b/apps/client/src/app/components/admin-market-data-detail/admin-market-data-detail.component.html @@ -29,7 +29,7 @@ }" [title]=" (itemByMonth.key + '-' + (i + 1 < 10 ? '0' + (i + 1) : i + 1) - | date : defaultDateFormat) ?? '' + | date: defaultDateFormat) ?? '' " (click)=" onOpenMarketDataDetail({ diff --git a/apps/client/src/app/components/header/header.component.html b/apps/client/src/app/components/header/header.component.html index 554668bf0..5c412a1b9 100644 --- a/apps/client/src/app/components/header/header.component.html +++ b/apps/client/src/app/components/header/header.component.html @@ -26,7 +26,7 @@

  • @@ -256,7 +260,7 @@
    • -
    • (); diff --git a/apps/client/src/app/pages/about/oss-friends/oss-friends-page.html b/apps/client/src/app/pages/about/oss-friends/oss-friends-page.html index 30db4c5ff..0248a8b46 100644 --- a/apps/client/src/app/pages/about/oss-friends/oss-friends-page.html +++ b/apps/client/src/app/pages/about/oss-friends/oss-friends-page.html @@ -14,26 +14,27 @@ *ngFor="let ossFriend of ossFriends" class="col-xs-12 col-md-4 mb-3" > - - - {{ ossFriend.name }} - - -

      {{ ossFriend.description }}

      -
      - - - Visit {{ ossFriend.name - }} - - - + + + + {{ ossFriend.name }} + + +

      {{ ossFriend.description }}

      +
      + +
      + Visit {{ ossFriend.name + }} + + + + diff --git a/apps/client/src/app/pages/about/oss-friends/oss-friends-page.module.ts b/apps/client/src/app/pages/about/oss-friends/oss-friends-page.module.ts index 1af5631b0..95cf9c3c3 100644 --- a/apps/client/src/app/pages/about/oss-friends/oss-friends-page.module.ts +++ b/apps/client/src/app/pages/about/oss-friends/oss-friends-page.module.ts @@ -1,10 +1,10 @@ import { CommonModule } from '@angular/common'; import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; import { OpenSourceSoftwareFriendsPageRoutingModule } from './oss-friends-page-routing.module'; import { OpenSourceSoftwareFriendsPageComponent } from './oss-friends-page.component'; -import { MatCardModule } from '@angular/material/card'; -import { MatButtonModule } from '@angular/material/button'; @NgModule({ declarations: [OpenSourceSoftwareFriendsPageComponent], diff --git a/apps/client/src/app/pages/about/oss-friends/oss-friends-page.scss b/apps/client/src/app/pages/about/oss-friends/oss-friends-page.scss index 5d4e87f30..a4de10587 100644 --- a/apps/client/src/app/pages/about/oss-friends/oss-friends-page.scss +++ b/apps/client/src/app/pages/about/oss-friends/oss-friends-page.scss @@ -1,3 +1,9 @@ :host { display: block; + + .mat-mdc-card { + &:hover { + border-color: var(--gf-theme-primary-500); + } + } } diff --git a/apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html b/apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html index 9f4dc39df..0c147ded3 100644 --- a/apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html +++ b/apps/client/src/app/pages/blog/2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.html @@ -10,7 +10,7 @@
      2023-07-01
      Exploring the Path to Financial Independence and Retiring Early (FIRE) Teaser diff --git a/apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component.ts b/apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component.ts new file mode 100644 index 000000000..682a1fdd8 --- /dev/null +++ b/apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component.ts @@ -0,0 +1,14 @@ +import { Component } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { RouterModule } from '@angular/router'; + +@Component({ + host: { class: 'page' }, + imports: [MatButtonModule, RouterModule], + selector: 'gf-ghostfolio-joins-oss-friends-page', + standalone: true, + templateUrl: './ghostfolio-joins-oss-friends-page.html' +}) +export class GhostfolioJoinsOssFriendsPageComponent { + public routerLinkAboutOssFriends = ['/' + $localize`about`, 'oss-friends']; +} diff --git a/apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html b/apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html new file mode 100644 index 000000000..b7ce5b67e --- /dev/null +++ b/apps/client/src/app/pages/blog/2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.html @@ -0,0 +1,167 @@ +
      +
      +
      +
      +
      +

      Ghostfolio joins OSS Friends

      +
      2023-08-23
      + Ghostfolio joins OSS Friends Teaser +
      +
      +

      + We are excited to announce that Ghostfolio is now part of the + OSS Friends. This + new initiative is all about helping open source projects grow and + become more popular. +

      +
      +
      +

      The Story of OSS Friends

      +

      + OSS Friends started as a simple + post + on X (formerly known as Twitter). The idea came from + Formbricks, an + open source experience management platform to create surveys in + minutes, and is all about giving open source projects a boost. +

      +

      + If you are excited about the OSS Friends movement and want to bring + your own open source project along, just take a moment to fill out + this form. Let’s work and learn together – all the open source way. +

      +
      +
      +

      + Ghostfolio – Next Generation Software for your Personal Finances +

      +

      + Money management can be tricky, especially when you have various + investments like cryptocurrencies, ETFs and stocks in your + portfolio. But guess what? There are cooler ways than staring at + boring spreadsheets. Say hello to Ghostfolio, a privacy-first, open + source dashboard for your personal finances. +

      +
      +
      +

      + Would you like to simplify asset tracking? +

      +

      + Ghostfolio empowers you to make informed investment decisions. +

      + +
      +
      +
        +
      • + Asset +
      • +
      • + Collaboration +
      • +
      • + Cryptocurrency +
      • +
      • + Community +
      • +
      • + Dashboard +
      • +
      • + ETF +
      • +
      • + Finance +
      • +
      • + Fintech +
      • +
      • + Ghostfolio +
      • +
      • + Initiative +
      • +
      • + Innovation +
      • +
      • + Investment +
      • +
      • + Open Source +
      • +
      • + OSS +
      • +
      • + OSS Friends +
      • +
      • + Personal Finance +
      • +
      • + Platform +
      • +
      • + Portfolio +
      • +
      • + Privacy +
      • +
      • + Software +
      • +
      • + Stock +
      • +
      • + Technology +
      • +
      • + Tracking +
      • +
      • + Wealth Management +
      • +
      • + Web3 +
      • +
      +
      + +
      +
      +
      +
      diff --git a/apps/client/src/app/pages/blog/blog-page-routing.module.ts b/apps/client/src/app/pages/blog/blog-page-routing.module.ts index 4c41b423e..30d9eb3b5 100644 --- a/apps/client/src/app/pages/blog/blog-page-routing.module.ts +++ b/apps/client/src/app/pages/blog/blog-page-routing.module.ts @@ -136,6 +136,15 @@ const routes: Routes = [ './2023/07/exploring-the-path-to-fire/exploring-the-path-to-fire-page.component' ).then((c) => c.ExploringThePathToFirePageComponent), title: 'Exploring the Path to FIRE' + }, + { + canActivate: [AuthGuard], + path: '2023/08/ghostfolio-joins-oss-friends', + loadComponent: () => + import( + './2023/08/ghostfolio-joins-oss-friends/ghostfolio-joins-oss-friends-page.component' + ).then((c) => c.GhostfolioJoinsOssFriendsPageComponent), + title: 'Ghostfolio joins OSS Friends' } ]; diff --git a/apps/client/src/app/pages/blog/blog-page.html b/apps/client/src/app/pages/blog/blog-page.html index 26c262c1a..b5dfae39e 100644 --- a/apps/client/src/app/pages/blog/blog-page.html +++ b/apps/client/src/app/pages/blog/blog-page.html @@ -8,6 +8,32 @@ finance + + + + +
      diff --git a/apps/client/src/app/pages/landing/landing-page.html b/apps/client/src/app/pages/landing/landing-page.html index d5f9cee05..79e461334 100644 --- a/apps/client/src/app/pages/landing/landing-page.html +++ b/apps/client/src/app/pages/landing/landing-page.html @@ -134,6 +134,14 @@ title="DEV Community - A constructive and inclusive social network for software developers" >
      +
      + +