22 * Centralized token configuration
33 * This file defines all token names, symbols, and peg-related text
44 * to make the frontend generic and configurable.
5- *
5+ *
66 * Configuration can be overridden via environment variables:
77 * - NEXT_PUBLIC_PROTOCOL_NAME: Protocol name (default: GLUON GOLD)
88 * - NEXT_PUBLIC_NEUTRON_TICKER: Stable token symbol (default: GAU)
99 * - NEXT_PUBLIC_PROTON_TICKER: Volatile token symbol (default: GAUC)
1010 * - NEXT_PUBLIC_PEG_ASSET: Peg asset name (default: Gold)
1111 * - NEXT_PUBLIC_PEG_UNIT: Peg unit (default: 1g)
1212 * - NEXT_PUBLIC_PEG_DESCRIPTION: Peg description (default: "Pegged to 1 gram of gold.")
13+ * - NEXT_PUBLIC_THEME_PRIMARY: Primary UI color (default: #ffd007)
14+ * - NEXT_PUBLIC_THEME_GLOW: Glow and highlight color (default: #ffd007)
15+ * - NEXT_PUBLIC_THEME_STABLE_TOKEN: Stable token color (default: #ffd007)
16+ * - NEXT_PUBLIC_THEME_VOLATILE_TOKEN: Volatile token color (default: #ff3b3b)
17+ * - NEXT_PUBLIC_THEME_ACCENT_LIGHT: Light-mode accent token channels (default: 48 16.129% 93.9216%)
18+ * - NEXT_PUBLIC_THEME_ACCENT_FOREGROUND_LIGHT: Light-mode accent foreground channels (default: 55 100% 40%)
19+ * - NEXT_PUBLIC_THEME_ACCENT_DARK: Dark-mode accent token channels (default: 30 5.2632% 14.902%)
20+ * - NEXT_PUBLIC_THEME_ACCENT_FOREGROUND_DARK: Dark-mode accent foreground channels (default: 48 100% 45.098%)
21+ * - NEXT_PUBLIC_THEME_SIDEBAR_ACCENT_LIGHT: Light-mode sidebar accent channels (default: 48 100% 96.0784%)
22+ * - NEXT_PUBLIC_THEME_SIDEBAR_ACCENT_FOREGROUND_LIGHT: Light-mode sidebar accent foreground channels (default: 22.7273 82.5% 31.3725%)
23+ * - NEXT_PUBLIC_THEME_SIDEBAR_ACCENT_DARK: Dark-mode sidebar accent channels (default: 22.7273 82.5% 31.3725%)
24+ * - NEXT_PUBLIC_THEME_SIDEBAR_ACCENT_FOREGROUND_DARK: Dark-mode sidebar accent foreground channels (default: 48 96.6387% 76.6667%)
25+ * - NEXT_PUBLIC_THEME_CHART_3: Chart color 3 HSL channels (default: 25.9649 90.4762% 37.0588%)
26+ * - NEXT_PUBLIC_THEME_CHART_4: Chart color 4 HSL channels (default: 22.7273 82.5% 31.3725%)
27+ * - NEXT_PUBLIC_THEME_CHART_5: Chart color 5 HSL channels (default: 21.7143 77.7778% 26.4706%)
28+ * - NEXT_PUBLIC_THEME_BUTTON_HOVER_FOREGROUND_LIGHT: Light-mode button hover text channels (default: 48 100% 51%)
29+ * - NEXT_PUBLIC_THEME_BUTTON_HOVER_FOREGROUND_DARK: Dark-mode button hover text channels (default: 48 100% 51%)
1330 */
1431
1532export interface TokenConfig {
1633 // Protocol name
1734 protocolName : string ;
35+
36+ // Protocol favicon path
37+ favicon : string ;
1838
1939 // Base asset (e.g., ERG)
2040 baseAsset : {
@@ -50,6 +70,27 @@ export interface TokenConfig {
5070 name : string ;
5171 symbol : string ;
5272 } ;
73+
74+ // Theme colors for protocol-specific UI variants
75+ theme : {
76+ primary : string ;
77+ glow : string ;
78+ stableToken : string ;
79+ volatileToken : string ;
80+ accentLight : string ;
81+ accentForegroundLight : string ;
82+ accentDark : string ;
83+ accentForegroundDark : string ;
84+ sidebarAccentLight : string ;
85+ sidebarAccentForegroundLight : string ;
86+ sidebarAccentDark : string ;
87+ sidebarAccentForegroundDark : string ;
88+ chart3 : string ;
89+ chart4 : string ;
90+ chart5 : string ;
91+ buttonHoverForegroundLight : string ;
92+ buttonHoverForegroundDark : string ;
93+ } ;
5394}
5495
5596// Read configuration from environment variables with defaults
@@ -58,6 +99,69 @@ const neutronTicker = process.env.NEXT_PUBLIC_NEUTRON_TICKER || "GAU";
5899const protonTicker = process . env . NEXT_PUBLIC_PROTON_TICKER || "GAUC" ;
59100const pegAsset = process . env . NEXT_PUBLIC_PEG_ASSET || "Gold" ;
60101const pegUnit = process . env . NEXT_PUBLIC_PEG_UNIT || "1g" ;
102+ const favicon = process . env . NEXT_PUBLIC_FAVICON || "/logo/gluon.png" ;
103+ const themePrimary = process . env . NEXT_PUBLIC_THEME_PRIMARY || "#ffd007" ;
104+ const themeGlow = process . env . NEXT_PUBLIC_THEME_GLOW || "#ffd007" ;
105+ const themeStableToken = process . env . NEXT_PUBLIC_THEME_STABLE_TOKEN || "#ffd007" ;
106+ const themeVolatileToken = process . env . NEXT_PUBLIC_THEME_VOLATILE_TOKEN || "#ff3b3b" ;
107+ const themeAccentLight = process . env . NEXT_PUBLIC_THEME_ACCENT_LIGHT || "48 16.129% 93.9216%" ;
108+ const themeAccentForegroundLight = process . env . NEXT_PUBLIC_THEME_ACCENT_FOREGROUND_LIGHT || "55 100% 40%" ;
109+ const themeAccentDark = process . env . NEXT_PUBLIC_THEME_ACCENT_DARK || "30 5.2632% 14.902%" ;
110+ const themeAccentForegroundDark = process . env . NEXT_PUBLIC_THEME_ACCENT_FOREGROUND_DARK || "48 100% 45.098%" ;
111+ const themeSidebarAccentLight = process . env . NEXT_PUBLIC_THEME_SIDEBAR_ACCENT_LIGHT || "48 100% 96.0784%" ;
112+ const themeSidebarAccentForegroundLight = process . env . NEXT_PUBLIC_THEME_SIDEBAR_ACCENT_FOREGROUND_LIGHT || "22.7273 82.5% 31.3725%" ;
113+ const themeSidebarAccentDark = process . env . NEXT_PUBLIC_THEME_SIDEBAR_ACCENT_DARK || "22.7273 82.5% 31.3725%" ;
114+ const themeSidebarAccentForegroundDark = process . env . NEXT_PUBLIC_THEME_SIDEBAR_ACCENT_FOREGROUND_DARK || "48 96.6387% 76.6667%" ;
115+ const themeChart3 = process . env . NEXT_PUBLIC_THEME_CHART_3 || "25.9649 90.4762% 37.0588%" ;
116+ const themeChart4 = process . env . NEXT_PUBLIC_THEME_CHART_4 || "22.7273 82.5% 31.3725%" ;
117+ const themeChart5 = process . env . NEXT_PUBLIC_THEME_CHART_5 || "21.7143 77.7778% 26.4706%" ;
118+ const themeButtonHoverForegroundLight = process . env . NEXT_PUBLIC_THEME_BUTTON_HOVER_FOREGROUND_LIGHT || "48 100% 51%" ;
119+ const themeButtonHoverForegroundDark = process . env . NEXT_PUBLIC_THEME_BUTTON_HOVER_FOREGROUND_DARK || "48 100% 51%" ;
120+
121+ const hexToHslChannels = ( hexColor : string ) : string => {
122+ const normalized = hexColor . replace ( "#" , "" ) ;
123+ const expanded =
124+ normalized . length === 3
125+ ? normalized
126+ . split ( "" )
127+ . map ( ( c ) => c + c )
128+ . join ( "" )
129+ : normalized ;
130+
131+ if ( ! / ^ [ 0 - 9 a - f A - F ] { 6 } $ / . test ( expanded ) ) {
132+ return "48 100% 51%" ;
133+ }
134+
135+ const r = parseInt ( expanded . slice ( 0 , 2 ) , 16 ) / 255 ;
136+ const g = parseInt ( expanded . slice ( 2 , 4 ) , 16 ) / 255 ;
137+ const b = parseInt ( expanded . slice ( 4 , 6 ) , 16 ) / 255 ;
138+
139+ const max = Math . max ( r , g , b ) ;
140+ const min = Math . min ( r , g , b ) ;
141+ const delta = max - min ;
142+ const l = ( max + min ) / 2 ;
143+
144+ let h = 0 ;
145+ if ( delta !== 0 ) {
146+ switch ( max ) {
147+ case r :
148+ h = ( ( g - b ) / delta + ( g < b ? 6 : 0 ) ) / 6 ;
149+ break ;
150+ case g :
151+ h = ( ( b - r ) / delta + 2 ) / 6 ;
152+ break ;
153+ case b :
154+ h = ( ( r - g ) / delta + 4 ) / 6 ;
155+ break ;
156+ default :
157+ h = 0 ;
158+ }
159+ }
160+
161+ const s = delta === 0 ? 0 : delta / ( 1 - Math . abs ( 2 * l - 1 ) ) ;
162+
163+ return `${ ( h * 360 ) . toFixed ( 4 ) } ${ ( s * 100 ) . toFixed ( 4 ) } % ${ ( l * 100 ) . toFixed ( 4 ) } %` ;
164+ } ;
61165
62166/**
63167 * Smart formatting for peg asset names.
@@ -69,7 +173,7 @@ const formatPegAssetForSentence = (asset: string): string => {
69173 // - 2-4 characters
70174 // - All uppercase or title case
71175 // - Common currency codes
72- const currencyCodes = [ ' USD' , ' EUR' , ' GBP' , ' JPY' , ' CHF' , ' AUD' , ' CAD' , ' CNY' , ' INR' ] ;
176+ const currencyCodes = [ " USD" , " EUR" , " GBP" , " JPY" , " CHF" , " AUD" , " CAD" , " CNY" , " INR" ] ;
73177
74178 if ( currencyCodes . includes ( asset . toUpperCase ( ) ) ) {
75179 return asset . toUpperCase ( ) ;
@@ -101,14 +205,14 @@ const generateStableDescription = () => {
101205 return `The stablecoin pegged to ${ pegUnit } of ${ formattedAsset } .` ;
102206} ;
103207
104- const pegDescription = process . env . NEXT_PUBLIC_PEG_DESCRIPTION ||
105- ( pegUnit . toLowerCase ( ) . includes ( pegAsset . toLowerCase ( ) )
106- ? `Pegged to ${ pegUnit } .`
107- : `Pegged to ${ pegUnit } of ${ formatPegAssetForSentence ( pegAsset ) } .` ) ;
208+ const pegDescription =
209+ process . env . NEXT_PUBLIC_PEG_DESCRIPTION ||
210+ ( pegUnit . toLowerCase ( ) . includes ( pegAsset . toLowerCase ( ) ) ? `Pegged to ${ pegUnit } .` : `Pegged to ${ pegUnit } of ${ formatPegAssetForSentence ( pegAsset ) } .` ) ;
108211
109212// Protocol configuration - configurable via environment variables
110213export const tokenConfig : TokenConfig = {
111214 protocolName,
215+ favicon,
112216 baseAsset : {
113217 name : "Ergo" ,
114218 symbol : "ERG" ,
@@ -134,8 +238,49 @@ export const tokenConfig: TokenConfig = {
134238 name : `${ neutronTicker } -${ protonTicker } Pair` ,
135239 symbol : `${ neutronTicker } -${ protonTicker } ` ,
136240 } ,
241+ theme : {
242+ primary : themePrimary ,
243+ glow : themeGlow ,
244+ stableToken : themeStableToken ,
245+ volatileToken : themeVolatileToken ,
246+ accentLight : themeAccentLight ,
247+ accentForegroundLight : themeAccentForegroundLight ,
248+ accentDark : themeAccentDark ,
249+ accentForegroundDark : themeAccentForegroundDark ,
250+ sidebarAccentLight : themeSidebarAccentLight ,
251+ sidebarAccentForegroundLight : themeSidebarAccentForegroundLight ,
252+ sidebarAccentDark : themeSidebarAccentDark ,
253+ sidebarAccentForegroundDark : themeSidebarAccentForegroundDark ,
254+ chart3 : themeChart3 ,
255+ chart4 : themeChart4 ,
256+ chart5 : themeChart5 ,
257+ buttonHoverForegroundLight : themeButtonHoverForegroundLight ,
258+ buttonHoverForegroundDark : themeButtonHoverForegroundDark ,
259+ } ,
137260} ;
138261
262+ export const tokenThemeCssVariables = {
263+ "--primary" : hexToHslChannels ( tokenConfig . theme . primary ) ,
264+ "--ring" : hexToHslChannels ( tokenConfig . theme . glow ) ,
265+ "--chart-1" : hexToHslChannels ( tokenConfig . theme . stableToken ) ,
266+ "--chart-2" : hexToHslChannels ( tokenConfig . theme . volatileToken ) ,
267+ "--sidebar-primary" : hexToHslChannels ( tokenConfig . theme . primary ) ,
268+ "--sidebar-ring" : hexToHslChannels ( tokenConfig . theme . glow ) ,
269+ "--theme-accent-light" : tokenConfig . theme . accentLight ,
270+ "--theme-accent-foreground-light" : tokenConfig . theme . accentForegroundLight ,
271+ "--theme-accent-dark" : tokenConfig . theme . accentDark ,
272+ "--theme-accent-foreground-dark" : tokenConfig . theme . accentForegroundDark ,
273+ "--theme-sidebar-accent-light" : tokenConfig . theme . sidebarAccentLight ,
274+ "--theme-sidebar-accent-foreground-light" : tokenConfig . theme . sidebarAccentForegroundLight ,
275+ "--theme-sidebar-accent-dark" : tokenConfig . theme . sidebarAccentDark ,
276+ "--theme-sidebar-accent-foreground-dark" : tokenConfig . theme . sidebarAccentForegroundDark ,
277+ "--theme-chart-3" : tokenConfig . theme . chart3 ,
278+ "--theme-chart-4" : tokenConfig . theme . chart4 ,
279+ "--theme-chart-5" : tokenConfig . theme . chart5 ,
280+ "--theme-button-hover-foreground-light" : tokenConfig . theme . buttonHoverForegroundLight ,
281+ "--theme-button-hover-foreground-dark" : tokenConfig . theme . buttonHoverForegroundDark ,
282+ } as const ;
283+
139284// Helper functions to get token symbols (for backward compatibility during migration)
140285export const getStableAssetSymbol = ( ) : string => tokenConfig . stableAsset . symbol ;
141286export const getVolatileAssetSymbol = ( ) : string => tokenConfig . volatileAsset . symbol ;
@@ -151,7 +296,7 @@ export const getPegDescription = (): string => tokenConfig.peg.description;
151296 */
152297export const formatPegAsset = ( ) : string => {
153298 const asset = tokenConfig . peg . type ;
154- const currencyCodes = [ ' USD' , ' EUR' , ' GBP' , ' JPY' , ' CHF' , ' AUD' , ' CAD' , ' CNY' , ' INR' , ' BTC' , ' ETH' ] ;
299+ const currencyCodes = [ " USD" , " EUR" , " GBP" , " JPY" , " CHF" , " AUD" , " CAD" , " CNY" , " INR" , " BTC" , " ETH" ] ;
155300
156301 if ( currencyCodes . includes ( asset . toUpperCase ( ) ) ) {
157302 return asset . toUpperCase ( ) ;
0 commit comments