diff --git a/package.json b/package.json index 4e62add..5fdc9be 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "format": "biome format --write .", "generate-client-factory": "tsx --env-file .env scripts/generate-client-factory.ts", "generate-routes": "tsr generate", - "generate-tradingview-symbols": "tsx --env-file .env scripts/generate-tradingview-symbols.ts" + "generate-tradingview-symbols": "tsx --env-file .env scripts/generate-tradingview-symbols/index.ts" }, "dependencies": { "@base-ui/react": "^1.1.0", diff --git a/scripts/generate-tradingview-symbols.ts b/scripts/generate-tradingview-symbols/index.ts similarity index 71% rename from scripts/generate-tradingview-symbols.ts rename to scripts/generate-tradingview-symbols/index.ts index 58cd37c..3e09b62 100644 --- a/scripts/generate-tradingview-symbols.ts +++ b/scripts/generate-tradingview-symbols/index.ts @@ -7,69 +7,19 @@ import { HttpClientRequest, HttpClientResponse, } from "@effect/platform"; +import { Array as _Array, Config, Effect, Layer, Logger } from "effect"; import { - Array as _Array, - Config, - Data, - Effect, - Layer, - Logger, - Order, - Schema, -} from "effect"; - -const DEFAULT_LIMIT = 50; - -const exchangePriorityRecord: Record = { - Coinbase: 0, - Binance: 1, - CRYPTOCAP: 2, - "Crypto.com": 3, -}; - -// ----------------------------------------------------------------------------- -// Schemas -// ----------------------------------------------------------------------------- -const TokenDto = Schema.Struct({ symbol: Schema.String }); - -const ProviderDto = Schema.Struct({ - id: Schema.String, - name: Schema.optionalWith(Schema.String, { nullable: true }), -}); - -const MarketDto = Schema.Struct({ - id: Schema.String, - providerId: Schema.String, - baseAsset: TokenDto, - quoteAsset: TokenDto, -}); - -const MarketsResponse = Schema.Struct({ - total: Schema.Number, - offset: Schema.Number, - limit: Schema.Number, - items: Schema.optionalWith(Schema.Array(MarketDto), { nullable: true }), -}); - -const ProvidersResponse = Schema.Array(ProviderDto); - -const TradingViewSearchResponse = Schema.Struct({ - symbols: Schema.Array( - Schema.Struct({ - symbol: Schema.String, - exchange: Schema.String, - provider_id: Schema.String, - }), - ), -}); - -// ----------------------------------------------------------------------------- -// Error Types -// ----------------------------------------------------------------------------- -class HttpError extends Data.TaggedError("HttpError")<{ - message: string; - cause?: unknown; -}> {} + type BaseSymbolSchema, + byProviderAndCurrency, + compareSymbolsFromBaseSymbol, + DEFAULT_LIMIT, + HttpError, + MarketsResponse, + makeResult, + normalizeSymbol, + ProvidersResponse, + TradingViewSearchResponse, +} from "scripts/generate-tradingview-symbols/utils"; // ----------------------------------------------------------------------------- // HttpClient Services @@ -123,11 +73,6 @@ class TradingViewClient extends Effect.Service()( // ----------------------------------------------------------------------------- // API Functions // ----------------------------------------------------------------------------- -const normalizeSymbol = (symbol: string) => - symbol - .replace(/<\/?em>/g, "") - .trim() - .toUpperCase(); const getProviders = Effect.gen(function* () { const perpsClient = yield* PerpsClient; @@ -226,50 +171,23 @@ const searchTradingViewSymbol = ( ), ); -const CheckTradingViewSymbolResult = Schema.Union( - Schema.Struct({ - status: Schema.Literal("match"), - perpsSymbol: Schema.String, - tradingViewSymbol: Schema.String, - providerId: Schema.String, - }), - Schema.Struct({ - status: Schema.Literal("noMatch"), - perpsSymbol: Schema.String, - }), - Schema.Struct({ - status: Schema.Literal("error"), - perpsSymbol: Schema.String, - }), -); - -const makeResult = Schema.decodeSync(CheckTradingViewSymbolResult); - -const checkTradingViewSymbol = Effect.fn(function* (baseSymbol: string) { +const checkTradingViewSymbol = Effect.fn(function* ( + baseSymbol: typeof BaseSymbolSchema.Type, +) { const tvClient = yield* TradingViewClient; const normalizedBase = normalizeSymbol(baseSymbol); return yield* searchTradingViewSymbol(tvClient, normalizedBase).pipe( Effect.map((response) => { - const results = _Array.sort( - response.symbols, - Order.mapInput( - Order.number, - (v: (typeof response.symbols)[number]) => - exchangePriorityRecord[v.exchange] ?? 999, - ), - ); + const results = _Array.sort(response.symbols, byProviderAndCurrency); + + const compareSymbols = compareSymbolsFromBaseSymbol(normalizedBase); const matchedResult = _Array.findFirst(results, (result) => { const resultSymbol = normalizeSymbol(result.symbol); - return [ - normalizedBase, - `${normalizedBase}USD`, - `${normalizedBase}USDC`, - `${normalizedBase}USDT`, - ].some((symbol) => resultSymbol === symbol); + return _Array.some(compareSymbols, (symbol) => resultSymbol === symbol); }); if (matchedResult._tag === "Some") { @@ -324,11 +242,12 @@ const program = Effect.gen(function* () { const nonMatched = results.filter((result) => result.status !== "match"); - yield* Effect.log("Non matched: ", JSON.stringify(nonMatched, null, 2)); + yield* Effect.log("Not matched: ", JSON.stringify(nonMatched, null, 2)); const path = join( dirname(fileURLToPath(import.meta.url)), "..", + "..", "src", "assets", "tradingview-symbols.json", diff --git a/scripts/generate-tradingview-symbols/utils.ts b/scripts/generate-tradingview-symbols/utils.ts new file mode 100644 index 0000000..8396f6a --- /dev/null +++ b/scripts/generate-tradingview-symbols/utils.ts @@ -0,0 +1,147 @@ +import { Data, Option, Order, Record, Schema } from "effect"; + +export const DEFAULT_LIMIT = 50; + +// ----------------------------------------------------------------------------- +// Schemas +// ----------------------------------------------------------------------------- +export const ProviderId = Schema.String.pipe(Schema.brand("ProviderId")); + +export const CompareCurrencySchema = Schema.Literal("USD", "USDC", "USDT"); + +export const currencyPriorityRecord: Record< + typeof CompareCurrencySchema.Type, + number +> = { + USD: 0, + USDC: 1, + USDT: 2, +}; + +export const BaseSymbolSchema = Schema.String.pipe(Schema.brand("BaseSymbol")); + +export const TokenDto = Schema.Struct({ symbol: BaseSymbolSchema }); + +export const ProviderDto = Schema.Struct({ + id: Schema.String, + name: Schema.optionalWith(Schema.String, { nullable: true }), +}); + +export const MarketDto = Schema.Struct({ + id: Schema.String, + providerId: Schema.String, + baseAsset: TokenDto, + quoteAsset: TokenDto, +}); + +export const MarketsResponse = Schema.Struct({ + total: Schema.Number, + offset: Schema.Number, + limit: Schema.Number, + items: Schema.optionalWith(Schema.Array(MarketDto), { nullable: true }), +}); + +export const ProvidersResponse = Schema.Array(ProviderDto); + +export const TradingViewSearchResponse = Schema.Struct({ + symbols: Schema.Array( + Schema.Struct({ + symbol: Schema.String, // e.g. ETHUSD + exchange: Schema.String, + provider_id: ProviderId, + }), + ), +}); + +const CheckTradingViewSymbolResult = Schema.Union( + Schema.Struct({ + status: Schema.Literal("match"), + perpsSymbol: Schema.String, + tradingViewSymbol: Schema.String, + providerId: Schema.String, + }), + Schema.Struct({ + status: Schema.Literal("noMatch"), + perpsSymbol: Schema.String, + }), + Schema.Struct({ + status: Schema.Literal("error"), + perpsSymbol: Schema.String, + }), +); + +// ----------------------------------------------------------------------------- +// Error Types +// ----------------------------------------------------------------------------- +export class HttpError extends Data.TaggedError("HttpError")<{ + message: string; + cause?: unknown; +}> {} + +// ----------------------------------------------------------------------------- +// Utilities +// ----------------------------------------------------------------------------- + +export const exchangePriorityRecord: Record = { + [ProviderId.make("coinbase")]: 0, + [ProviderId.make("binance")]: 1, + [ProviderId.make("cryptocom")]: 2, + [ProviderId.make("kraken")]: 3, + [ProviderId.make("okx")]: 4, + [ProviderId.make("cryptocap")]: 5, +}; + +export const normalizeSymbol = (symbol: T): T => + symbol + .replace(/<\/?em>/g, "") + .trim() + .toUpperCase() as T; + +export const makeResult = Schema.decodeSync(CheckTradingViewSymbolResult); + +const byCurrency = Order.mapInput( + Order.number, + (val: (typeof TradingViewSearchResponse.Type)["symbols"][number]) => { + const compareSymbol = Schema.decodeUnknownOption( + Schema.TemplateLiteralParser( + Schema.String, + Schema.Literal("USD", "USDC", "USDT"), + ), + )(val.symbol).pipe( + Option.map((v) => v[1]), + Option.getOrElse(() => null), + ); + + if (!compareSymbol) return 999; + + return Record.get(currencyPriorityRecord, compareSymbol).pipe( + Option.getOrElse(() => 999), + ); + }, +); + +const byProvider = Order.mapInput( + Order.number, + (val: (typeof TradingViewSearchResponse.Type)["symbols"][number]) => + Record.get(exchangePriorityRecord, val.provider_id).pipe( + Option.getOrElse(() => 999), + ), +); + +export const byProviderAndCurrency = Order.combine(byCurrency, byProvider); + +export const compareSymbolsFromBaseSymbol = ( + baseSymbol: typeof BaseSymbolSchema.Type, +) => { + const compareSymbols = Schema.decodeSync( + Schema.Array( + Schema.TemplateLiteral(BaseSymbolSchema, CompareCurrencySchema), + ), + )( + CompareCurrencySchema.literals.map( + (currency) => `${baseSymbol}${currency}` as const, + ), + ); + + return [...compareSymbols, baseSymbol]; +}; diff --git a/src/assets/tradingview-symbols.json b/src/assets/tradingview-symbols.json index baa7ac5..1098d8d 100644 --- a/src/assets/tradingview-symbols.json +++ b/src/assets/tradingview-symbols.json @@ -20,8 +20,8 @@ { "status": "match", "perpsSymbol": "DYDX", - "tradingViewSymbol": "DYDXUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "DYDXUSD", + "providerId": "KRAKEN" }, { "status": "match", @@ -116,19 +116,19 @@ { "status": "match", "perpsSymbol": "CFX", - "tradingViewSymbol": "CFXUSDT", + "tradingViewSymbol": "CFXUSD", "providerId": "BINANCE" }, { "status": "match", "perpsSymbol": "GMX", - "tradingViewSymbol": "GMXUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "GMXUSD", + "providerId": "KRAKEN" }, { "status": "match", "perpsSymbol": "SNX", - "tradingViewSymbol": "SNXUSDT", + "tradingViewSymbol": "SNXUSDC", "providerId": "BINANCE" }, { @@ -170,13 +170,13 @@ { "status": "match", "perpsSymbol": "YGG", - "tradingViewSymbol": "YGGUSDT", + "tradingViewSymbol": "YGGUSD", "providerId": "BINANCE" }, { "status": "match", "perpsSymbol": "TRX", - "tradingViewSymbol": "TRXUSDT", + "tradingViewSymbol": "TRXUSD", "providerId": "BINANCE" }, { @@ -194,7 +194,7 @@ { "status": "match", "perpsSymbol": "RUNE", - "tradingViewSymbol": "RUNEUSDT", + "tradingViewSymbol": "RUNEUSD", "providerId": "BINANCE" }, { @@ -212,7 +212,7 @@ { "status": "match", "perpsSymbol": "BANANA", - "tradingViewSymbol": "BANANAUSDT", + "tradingViewSymbol": "BANANAUSD", "providerId": "BINANCE" }, { @@ -230,8 +230,8 @@ { "status": "match", "perpsSymbol": "ARK", - "tradingViewSymbol": "ARKUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "ARKUSD", + "providerId": "CRYPTOCOM" }, { "status": "match", @@ -242,13 +242,13 @@ { "status": "match", "perpsSymbol": "KAS", - "tradingViewSymbol": "KAS", - "providerId": "TVC" + "tradingViewSymbol": "KASUSD", + "providerId": "KRAKEN" }, { "status": "match", "perpsSymbol": "BLUR", - "tradingViewSymbol": "BLURUSDC", + "tradingViewSymbol": "BLURUSD", "providerId": "COINBASE" }, { @@ -284,19 +284,19 @@ { "status": "match", "perpsSymbol": "POLYX", - "tradingViewSymbol": "POLYXUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "POLYXUSD", + "providerId": "CRYPTOCOM" }, { "status": "match", "perpsSymbol": "GAS", - "tradingViewSymbol": "GASUSDT", + "tradingViewSymbol": "GASUSD", "providerId": "BINANCE" }, { "status": "match", "perpsSymbol": "PENDLE", - "tradingViewSymbol": "PENDLEUSDC", + "tradingViewSymbol": "PENDLEUSD", "providerId": "COINBASE" }, { @@ -314,19 +314,19 @@ { "status": "match", "perpsSymbol": "MEME", - "tradingViewSymbol": "MEMEUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "MEMEUSD", + "providerId": "KRAKEN" }, { "status": "match", "perpsSymbol": "ORDI", - "tradingViewSymbol": "ORDIUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "ORDIUSD", + "providerId": "OKX" }, { "status": "match", "perpsSymbol": "NEO", - "tradingViewSymbol": "NEOUSDT", + "tradingViewSymbol": "NEOUSD", "providerId": "BINANCE" }, { @@ -344,13 +344,13 @@ { "status": "match", "perpsSymbol": "PYTH", - "tradingViewSymbol": "PYTHUSDC", + "tradingViewSymbol": "PYTHUSD", "providerId": "COINBASE" }, { "status": "match", "perpsSymbol": "SUSHI", - "tradingViewSymbol": "SUSHIUSDC", + "tradingViewSymbol": "SUSHIUSD", "providerId": "COINBASE" }, { @@ -380,14 +380,14 @@ { "status": "match", "perpsSymbol": "USTC", - "tradingViewSymbol": "USTCUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "USTCUSD", + "providerId": "TVC" }, { "status": "match", "perpsSymbol": "JUP", - "tradingViewSymbol": "JUPUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "JUPUSD", + "providerId": "KRAKEN" }, { "status": "match", @@ -398,8 +398,8 @@ { "status": "match", "perpsSymbol": "GALA", - "tradingViewSymbol": "GALAUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "GALAUSD", + "providerId": "KRAKEN" }, { "status": "match", @@ -410,13 +410,13 @@ { "status": "match", "perpsSymbol": "ACE", - "tradingViewSymbol": "ACEUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "ACEUSD", + "providerId": "OKX" }, { "status": "match", "perpsSymbol": "MAV", - "tradingViewSymbol": "MAVUSDC", + "tradingViewSymbol": "MAVUSD", "providerId": "BINANCE" }, { @@ -434,8 +434,8 @@ { "status": "match", "perpsSymbol": "PEOPLE", - "tradingViewSymbol": "PEOPLEUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "PEOPLEUSD", + "providerId": "OKX" }, { "status": "match", @@ -452,13 +452,13 @@ { "status": "match", "perpsSymbol": "XAI", - "tradingViewSymbol": "XAIUSDT", + "tradingViewSymbol": "XAIUSDC", "providerId": "BINANCE" }, { "status": "match", "perpsSymbol": "MANTA", - "tradingViewSymbol": "MANTAUSDT", + "tradingViewSymbol": "MANTAUSD", "providerId": "BINANCE" }, { @@ -482,20 +482,20 @@ { "status": "match", "perpsSymbol": "ZETA", - "tradingViewSymbol": "ZETAUSDC", + "tradingViewSymbol": "ZETAUSD", "providerId": "COINBASE" }, { "status": "match", "perpsSymbol": "DYM", - "tradingViewSymbol": "DYMUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "DYMUSD", + "providerId": "CRYPTOCOM" }, { "status": "match", "perpsSymbol": "MAVIA", - "tradingViewSymbol": "MAVIA", - "providerId": "TVC" + "tradingViewSymbol": "MAVIAUSD", + "providerId": "CRYPTOCOM" }, { "status": "match", @@ -518,14 +518,14 @@ { "status": "match", "perpsSymbol": "AR", - "tradingViewSymbol": "ARUSDT", + "tradingViewSymbol": "ARUSD", "providerId": "BINANCE" }, { "status": "match", "perpsSymbol": "BOME", - "tradingViewSymbol": "BOMEUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "BOMEUSD", + "providerId": "OKX" }, { "status": "match", @@ -542,8 +542,8 @@ { "status": "match", "perpsSymbol": "MNT", - "tradingViewSymbol": "MNT", - "providerId": "TVC" + "tradingViewSymbol": "MNTUSD", + "providerId": "KRAKEN" }, { "status": "match", @@ -554,14 +554,14 @@ { "status": "match", "perpsSymbol": "SAGA", - "tradingViewSymbol": "SAGAUSDT", + "tradingViewSymbol": "SAGAUSD", "providerId": "BINANCE" }, { "status": "match", "perpsSymbol": "MERL", - "tradingViewSymbol": "MERL", - "providerId": "TVC" + "tradingViewSymbol": "MERLUSD", + "providerId": "KRAKEN" }, { "status": "match", @@ -572,13 +572,13 @@ { "status": "match", "perpsSymbol": "POPCAT", - "tradingViewSymbol": "POPCATUSDC", + "tradingViewSymbol": "POPCATUSD", "providerId": "COINBASE" }, { "status": "match", "perpsSymbol": "EIGEN", - "tradingViewSymbol": "EIGENUSDC", + "tradingViewSymbol": "EIGENUSD", "providerId": "COINBASE" }, { @@ -590,19 +590,19 @@ { "status": "match", "perpsSymbol": "NOT", - "tradingViewSymbol": "NOTUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "NOTUSD", + "providerId": "CRYPTOCOM" }, { "status": "match", "perpsSymbol": "TURBO", - "tradingViewSymbol": "TURBOUSDC", + "tradingViewSymbol": "TURBOUSD", "providerId": "COINBASE" }, { "status": "match", "perpsSymbol": "BRETT", - "tradingViewSymbol": "BRETTUSDT", + "tradingViewSymbol": "BRETTUSDC", "providerId": "BYBIT" }, { @@ -620,14 +620,14 @@ { "status": "match", "perpsSymbol": "BLAST", - "tradingViewSymbol": "BLASTUSDC", + "tradingViewSymbol": "BLASTUSD", "providerId": "COINBASE" }, { "status": "match", "perpsSymbol": "MEW", - "tradingViewSymbol": "MEW", - "providerId": "TVC" + "tradingViewSymbol": "MEWUSD", + "providerId": "KRAKEN" }, { "status": "match", @@ -644,44 +644,44 @@ { "status": "match", "perpsSymbol": "CELO", - "tradingViewSymbol": "CELOUSDT", + "tradingViewSymbol": "CELOUSD", "providerId": "BINANCE" }, { "status": "match", "perpsSymbol": "HMSTR", - "tradingViewSymbol": "HMSTRUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "HMSTRUSD", + "providerId": "CRYPTOCOM" }, { "status": "match", "perpsSymbol": "SCR", - "tradingViewSymbol": "SCRUSDT", + "tradingViewSymbol": "SCRUSD", "providerId": "BINANCE" }, { "status": "match", "perpsSymbol": "GOAT", - "tradingViewSymbol": "GOATUSDC", - "providerId": "GEMINI" + "tradingViewSymbol": "GOATUSD", + "providerId": "KRAKEN" }, { "status": "match", "perpsSymbol": "MOODENG", - "tradingViewSymbol": "MOODENG", - "providerId": "TVC" + "tradingViewSymbol": "MOODENGUSD", + "providerId": "KRAKEN" }, { "status": "match", "perpsSymbol": "GRASS", - "tradingViewSymbol": "GRASSUSDT", - "providerId": "BYBIT" + "tradingViewSymbol": "GRASSUSD", + "providerId": "KRAKEN" }, { "status": "match", "perpsSymbol": "PURR", - "tradingViewSymbol": "PURRUSDT", - "providerId": "KUCOIN" + "tradingViewSymbol": "PURRUSD", + "providerId": "PYTH" }, { "status": "match", @@ -698,8 +698,8 @@ { "status": "match", "perpsSymbol": "CHILLGUY", - "tradingViewSymbol": "CHILLGUY", - "providerId": "TVC" + "tradingViewSymbol": "CHILLGUYUSD", + "providerId": "CRYPTOCOM" }, { "status": "match", @@ -710,7 +710,7 @@ { "status": "match", "perpsSymbol": "IOTA", - "tradingViewSymbol": "IOTAUSDT", + "tradingViewSymbol": "IOTAUSD", "providerId": "BINANCE" }, { @@ -722,26 +722,26 @@ { "status": "match", "perpsSymbol": "HYPE", - "tradingViewSymbol": "HYPEUSDT", - "providerId": "KUCOIN" + "tradingViewSymbol": "HYPEUSD", + "providerId": "BINANCE" }, { "status": "match", "perpsSymbol": "ME", - "tradingViewSymbol": "MEUSDC", + "tradingViewSymbol": "MEUSD", "providerId": "COINBASE" }, { "status": "match", "perpsSymbol": "MOVE", - "tradingViewSymbol": "MOVEUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "MOVEUSD", + "providerId": "KRAKEN" }, { "status": "match", "perpsSymbol": "VIRTUAL", - "tradingViewSymbol": "VIRTUALUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "VIRTUALUSD", + "providerId": "KRAKEN" }, { "status": "match", @@ -752,8 +752,8 @@ { "status": "match", "perpsSymbol": "USUAL", - "tradingViewSymbol": "USUALUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "USUALUSD", + "providerId": "KRAKEN" }, { "status": "match", @@ -764,14 +764,14 @@ { "status": "match", "perpsSymbol": "AIXBT", - "tradingViewSymbol": "AIXBTUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "AIXBTUSD", + "providerId": "KRAKEN" }, { "status": "match", "perpsSymbol": "ZEREBRO", - "tradingViewSymbol": "ZEREBRO", - "providerId": "TVC" + "tradingViewSymbol": "ZEREBROUSD", + "providerId": "KRAKEN" }, { "status": "match", @@ -782,8 +782,8 @@ { "status": "match", "perpsSymbol": "GRIFFAIN", - "tradingViewSymbol": "GRIFFAIN", - "providerId": "TVC" + "tradingViewSymbol": "GRIFFAINUSD", + "providerId": "KRAKEN" }, { "status": "match", @@ -800,7 +800,7 @@ { "status": "match", "perpsSymbol": "MORPHO", - "tradingViewSymbol": "MORPHOUSDC", + "tradingViewSymbol": "MORPHOUSD", "providerId": "COINBASE" }, { @@ -813,19 +813,19 @@ "status": "match", "perpsSymbol": "MELANIA", "tradingViewSymbol": "MELANIAUSD", - "providerId": "BITSTAMP" + "providerId": "KRAKEN" }, { "status": "match", "perpsSymbol": "ANIME", - "tradingViewSymbol": "ANIMEUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "ANIMEUSD", + "providerId": "KRAKEN" }, { "status": "match", "perpsSymbol": "VINE", - "tradingViewSymbol": "VINE", - "providerId": "TVC" + "tradingViewSymbol": "VINEUSD", + "providerId": "KRAKEN" }, { "status": "match", @@ -836,14 +836,14 @@ { "status": "match", "perpsSymbol": "BERA", - "tradingViewSymbol": "BERAUSDC", + "tradingViewSymbol": "BERAUSD", "providerId": "COINBASE" }, { "status": "match", "perpsSymbol": "TST", - "tradingViewSymbol": "TSTUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "TSTUSD", + "providerId": "PYTH" }, { "status": "match", @@ -860,26 +860,26 @@ { "status": "match", "perpsSymbol": "OM", - "tradingViewSymbol": "OMUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "OMUSD", + "providerId": "KRAKEN" }, { "status": "match", "perpsSymbol": "KAITO", - "tradingViewSymbol": "KAITOUSDC", + "tradingViewSymbol": "KAITOUSD", "providerId": "COINBASE" }, { "status": "match", "perpsSymbol": "NIL", - "tradingViewSymbol": "NILUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "NILUSD", + "providerId": "KRAKEN" }, { "status": "match", "perpsSymbol": "PAXG", - "tradingViewSymbol": "PAXGUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "PAXGUSD", + "providerId": "CAPITALCOM" }, { "status": "match", @@ -890,8 +890,8 @@ { "status": "match", "perpsSymbol": "BABY", - "tradingViewSymbol": "BABYUSDC", - "providerId": "BINANCE" + "tradingViewSymbol": "BABYUSD", + "providerId": "KRAKEN" }, { "status": "match", @@ -914,32 +914,32 @@ { "status": "match", "perpsSymbol": "INIT", - "tradingViewSymbol": "INITUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "INITUSD", + "providerId": "CRYPTOCOM" }, { "status": "match", "perpsSymbol": "DOOD", - "tradingViewSymbol": "DOOD", - "providerId": "TVC" + "tradingViewSymbol": "DOODUSD", + "providerId": "OKX" }, { "status": "match", "perpsSymbol": "NXPC", - "tradingViewSymbol": "NXPCUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "NXPCUSD", + "providerId": "CRYPTOCOM" }, { "status": "match", "perpsSymbol": "SOPH", - "tradingViewSymbol": "SOPHUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "SOPHUSD", + "providerId": "OKX" }, { "status": "match", "perpsSymbol": "RESOLV", - "tradingViewSymbol": "RESOLVUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "RESOLVUSD", + "providerId": "OKX" }, { "status": "match", @@ -962,8 +962,8 @@ { "status": "match", "perpsSymbol": "YZY", - "tradingViewSymbol": "YZYUSDT", - "providerId": "POLONIEX" + "tradingViewSymbol": "YZYUSD", + "providerId": "PYTH" }, { "status": "match", @@ -992,7 +992,7 @@ { "status": "match", "perpsSymbol": "ASTER", - "tradingViewSymbol": "ASTERUSDC", + "tradingViewSymbol": "ASTERUSD", "providerId": "COINBASE" }, { @@ -1004,25 +1004,25 @@ { "status": "match", "perpsSymbol": "STBL", - "tradingViewSymbol": "STBL", - "providerId": "TVC" + "tradingViewSymbol": "STBLUSD", + "providerId": "KRAKEN" }, { "status": "match", "perpsSymbol": "0G", - "tradingViewSymbol": "0GUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "0GUSD", + "providerId": "KRAKEN" }, { "status": "match", "perpsSymbol": "HEMI", - "tradingViewSymbol": "HEMIUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "HEMIUSD", + "providerId": "CRYPTOCOM" }, { "status": "match", "perpsSymbol": "APEX", - "tradingViewSymbol": "APEX", + "tradingViewSymbol": "APEXUSD", "providerId": "TVC" }, { @@ -1058,8 +1058,8 @@ { "status": "match", "perpsSymbol": "CC", - "tradingViewSymbol": "CCUSDT", - "providerId": "MEXC" + "tradingViewSymbol": "CCUSD", + "providerId": "KRAKEN" }, { "status": "match", @@ -1077,25 +1077,25 @@ "status": "match", "perpsSymbol": "STABLE", "tradingViewSymbol": "STABLEUSD", - "providerId": "BITFINEX" + "providerId": "KRAKEN" }, { "status": "match", "perpsSymbol": "FOGO", - "tradingViewSymbol": "FOGOUSDT", - "providerId": "BINANCE" + "tradingViewSymbol": "FOGOUSD", + "providerId": "CRYPTOCOM" }, { "status": "match", "perpsSymbol": "LIT", - "tradingViewSymbol": "LIT", - "providerId": "TVC" + "tradingViewSymbol": "LITUSD", + "providerId": "KRAKEN" }, { "status": "match", "perpsSymbol": "XMR", - "tradingViewSymbol": "XMR", - "providerId": "TVC" + "tradingViewSymbol": "XMRUSD", + "providerId": "KRAKEN" }, { "status": "match", diff --git a/src/components/modules/Home/Positions/order-card.tsx b/src/components/modules/Home/Positions/order-card.tsx index 186a17a..8badcc4 100644 --- a/src/components/modules/Home/Positions/order-card.tsx +++ b/src/components/modules/Home/Positions/order-card.tsx @@ -25,6 +25,7 @@ export function OrderCard({ params: { marketId: market.id }, search: {}, }} + className="hover:bg-white/2.5 rounded-2xl" > {/* Top section with order type and value */} diff --git a/src/components/modules/Home/Positions/position-card.tsx b/src/components/modules/Home/Positions/position-card.tsx index 5e1f085..a265e2c 100644 --- a/src/components/modules/Home/Positions/position-card.tsx +++ b/src/components/modules/Home/Positions/position-card.tsx @@ -43,7 +43,7 @@ export function PositionCard({ params: { marketId: position.marketId }, search: {}, }} - className="w-full text-left" + className="w-full text-left hover:bg-white/2.5 rounded-2xl" > {/* Top section with token info and price */} diff --git a/src/components/modules/PositionDetails/Overview/Chart/index.tsx b/src/components/modules/PositionDetails/Overview/Chart/index.tsx index 1172623..4a98ca2 100644 --- a/src/components/modules/PositionDetails/Overview/Chart/index.tsx +++ b/src/components/modules/PositionDetails/Overview/Chart/index.tsx @@ -1,5 +1,6 @@ import { useAtomValue } from "@effect-atom/atom-react"; import { Option } from "effect"; +import { TriangleAlertIcon } from "lucide-react"; import { useLayoutEffect, useRef, useState } from "react"; import { CHART_INTERVALS, @@ -90,20 +91,13 @@ function createTradingViewWidget({ }; } -export function Chart({ symbol }: { symbol: string }) { - const { providerId, tradingViewSymbol } = useAtomValue( - tradingViewSymbolAtom(symbol), - ).pipe( - Option.map((v) => ({ - providerId: v.providerId, - tradingViewSymbol: v.tradingViewSymbol, - })), - Option.getOrElse(() => ({ - providerId: "COINBASE", - tradingViewSymbol: `${symbol}USD`, - })), - ); - +function ChartAvailable({ + providerId, + tradingViewSymbol, +}: { + providerId: string; + tradingViewSymbol: string; +}) { const containerRef = useRef(null); const iframeRef = useRef(null); @@ -148,7 +142,7 @@ export function Chart({ symbol }: { symbol: string }) { {/* Loading overlay */} {isLoading && ( -
+
Loading chart... @@ -169,3 +163,26 @@ export function Chart({ symbol }: { symbol: string }) { ); } + +const ChartNotAvailable = () => { + return ( +
+
+ + Chart not available +
+
+ ); +}; + +export const Chart = ({ symbol }: { symbol: string }) => { + const chartMeta = useAtomValue(tradingViewSymbolAtom(symbol)).pipe( + Option.map((v) => ({ + providerId: v.providerId, + tradingViewSymbol: v.tradingViewSymbol, + })), + Option.getOrNull, + ); + + return chartMeta ? : ; +};