diff --git a/src/lib/components/blockchain/swap/ReactorSwap.tsx b/src/lib/components/blockchain/swap/ReactorSwap.tsx index a775be6..f609dd1 100644 --- a/src/lib/components/blockchain/swap/ReactorSwap.tsx +++ b/src/lib/components/blockchain/swap/ReactorSwap.tsx @@ -109,8 +109,8 @@ export function ReactorSwap() { const [toToken, setToToken] = useState(tokens[3]); const [fromAmount, setFromAmount] = useState(""); const [toAmount, setToAmount] = useState(""); - const [gauAmount, setGauAmount] = useState("0"); - const [gaucAmount, setGaucAmount] = useState("0"); + const [neutronAmount, setNeutronAmount] = useState("0"); + const [protonAmount, setProtonAmount] = useState("0"); const [isLoading, setIsLoading] = useState(false); const [isCalculating, setIsCalculating] = useState(false); const [gluonInstance, setGluonInstance] = useState(null); @@ -123,7 +123,7 @@ export function ReactorSwap() { const [boxesReady, setBoxesReady] = useState(false); const [receiptDetails, setReceiptDetails] = useState({ inputAmount: 0, - outputAmount: { gau: 0, gauc: 0, erg: 0 }, + outputAmount: { neutron: 0, proton: 0, erg: 0 }, fees: { devFee: 0, uiFee: 0, @@ -147,60 +147,57 @@ export function ReactorSwap() { } }, [hasPendingTransactions]); // Helper function to capture current wallet state + // Note: WalletState still uses gau/gauc keys for backward compatibility with transaction-listener storage const captureWalletState = async (): Promise => { const balances = await getBalance(); const ergBalance = balances.find((b: any) => b.tokenId === "ERG" || !b.tokenId)?.balance || "0"; - const gauBalance = balances.find((b: any) => b.tokenId === TOKEN_ADDRESS.gau)?.balance || "0"; - const gaucBalance = balances.find((b: any) => b.tokenId === TOKEN_ADDRESS.gauc)?.balance || "0"; + const neutronBalance = balances.find((b: any) => b.tokenId === TOKEN_ADDRESS.gau)?.balance || "0"; + const protonBalance = balances.find((b: any) => b.tokenId === TOKEN_ADDRESS.gauc)?.balance || "0"; return { erg: ergBalance, - gau: gauBalance, - gauc: gaucBalance, + gau: neutronBalance, // Map neutron → gau for storage compatibility + gauc: protonBalance, // Map proton → gauc for storage compatibility timestamp: Date.now(), }; }; // Helper function to calculate expected changes based on transaction type + // Note: ExpectedChanges still uses gau/gauc keys for backward compatibility with transaction-listener storage const calculateExpectedChanges = ( actionType: string, inputAmount: string, - outputAmounts: { gau?: string; gauc?: string; erg?: string }, + outputAmounts: { neutron?: string; proton?: string; erg?: string }, fees: number | BigNumber ): ExpectedChanges => { const feeAmount = typeof fees === "number" ? fees : fees.toNumber(); - const changes: ExpectedChanges = { - erg: "0", - gau: "0", - gauc: "0", - fees: (-Math.abs(feeAmount * 1000000000)).toString(), // Convert to nanoERGs and make negative - }; + const changes: ExpectedChanges = { erg: "0", gau: "0", gauc: "0", fees: (-Math.abs(feeAmount * 1000000000)).toString() }; switch (actionType) { case "fission": // ERG → GAU + GAUC - changes.erg = (-parseFloat(inputAmount) * 1000000000).toString(); // Input ERG converted to nanoERGs and negative - changes.gau = convertToDecimals(outputAmounts.gau || "0").toString(); - changes.gauc = convertToDecimals(outputAmounts.gauc || "0").toString(); + changes.erg = (-parseFloat(inputAmount) * 1000000000).toString(); + changes.gau = convertToDecimals(outputAmounts.neutron || "0").toString(); + changes.gauc = convertToDecimals(outputAmounts.proton || "0").toString(); break; case "fusion": // GAU + GAUC → ERG - changes.erg = (parseFloat(outputAmounts.erg || "0") * 1000000000).toString(); // Output ERG to nanoERGs - changes.gau = (-convertToDecimals(gauAmount)).toString(); // Used GAU tokens - changes.gauc = (-convertToDecimals(gaucAmount)).toString(); // Used GAUC tokens + changes.erg = (parseFloat(outputAmounts.erg || "0") * 1000000000).toString(); + changes.gau = (-convertToDecimals(neutronAmount)).toString(); + changes.gauc = (-convertToDecimals(protonAmount)).toString(); break; case "transmute-to-gold": // GAUC → GAU changes.gauc = (-convertToDecimals(inputAmount)).toString(); - changes.gau = convertToDecimals(outputAmounts.gau || "0").toString(); + changes.gau = convertToDecimals(outputAmounts.neutron || "0").toString(); break; case "transmute-from-gold": // GAU → GAUC changes.gau = (-convertToDecimals(inputAmount)).toString(); - changes.gauc = convertToDecimals(outputAmounts.gauc || "0").toString(); + changes.gauc = convertToDecimals(outputAmounts.proton || "0").toString(); break; } @@ -228,11 +225,11 @@ export function ReactorSwap() { console.log("⚠️ Invalid input value, resetting"); setIsCalculating(false); setToAmount(""); - setGauAmount("0"); - setGaucAmount("0"); + setNeutronAmount("0"); + setProtonAmount("0"); setReceiptDetails({ inputAmount: 0, - outputAmount: { gau: 0, gauc: 0, erg: 0 }, + outputAmount: { neutron: 0, proton: 0, erg: 0 }, fees: { devFee: 0, uiFee: 0, oracleFee: 0, minerFee: 0, totalFee: 0 }, maxErgOutput: maxErgOutput, }); @@ -259,27 +256,27 @@ export function ReactorSwap() { gluonInstance, gluonBox, value: calculationValue, - gauBalance: tokens.find((t) => t.symbol === "GAU")?.balance || "0", - gaucBalance: tokens.find((t) => t.symbol === "GAUC")?.balance || "0", + neutronBalance: tokens.find((t) => t.symbol === "GAU")?.balance || "0", + protonBalance: tokens.find((t) => t.symbol === "GAUC")?.balance || "0", }); if ("error" in result) { console.error("❌ Fusion calculation error:", result.error); setToAmount(""); - setGauAmount("0"); - setGaucAmount("0"); + setNeutronAmount("0"); + setProtonAmount("0"); return; } console.log("✅ Fusion calculation result:", { - gauAmount: result.gauAmount, - gaucAmount: result.gaucAmount, + neutronAmount: result.neutronAmount, + protonAmount: result.protonAmount, receiptDetails: result.receiptDetails, }); // Update the amounts based on the ERG output target - setGauAmount(result.gauAmount); - setGaucAmount(result.gaucAmount); + setNeutronAmount(result.neutronAmount); + setProtonAmount(result.protonAmount); setReceiptDetails(result.receiptDetails); } else if (fromToken.symbol === "ERG" && toToken.symbol === "GAU-GAUC") { console.log("🔄 Calculating Fission amounts"); @@ -293,18 +290,18 @@ export function ReactorSwap() { console.error(result.error); setToAmount(""); if (result.resetValues) { - if (result.resetValues.gauAmount) setGauAmount(result.resetValues.gauAmount); - if (result.resetValues.gaucAmount) setGaucAmount(result.resetValues.gaucAmount); + if (result.resetValues.neutronAmount) setNeutronAmount(result.resetValues.neutronAmount); + if (result.resetValues.protonAmount) setProtonAmount(result.resetValues.protonAmount); } else { - setGauAmount("0"); - setGaucAmount("0"); + setNeutronAmount("0"); + setProtonAmount("0"); } return; } - const minOutput = Math.min(parseFloat(result.gauAmount), parseFloat(result.gaucAmount)); + const minOutput = Math.min(parseFloat(result.neutronAmount), parseFloat(result.protonAmount)); setToAmount(isNaN(minOutput) ? "" : minOutput.toString()); - setGauAmount(result.gauAmount); - setGaucAmount(result.gaucAmount); + setNeutronAmount(result.neutronAmount); + setProtonAmount(result.protonAmount); setReceiptDetails(result.receiptDetails); } else if ((fromToken.symbol === "GAUC" && toToken.symbol === "GAU") || (fromToken.symbol === "GAU" && toToken.symbol === "GAUC")) { // Only calculate if we're changing the input amount @@ -354,11 +351,11 @@ export function ReactorSwap() { } if (floatValue === undefined || floatValue === 0) { setToAmount(""); - setGauAmount("0"); - setGaucAmount("0"); + setNeutronAmount("0"); + setProtonAmount("0"); setReceiptDetails({ inputAmount: 0, - outputAmount: { gau: 0, gauc: 0, erg: 0 }, + outputAmount: { neutron: 0, proton: 0, erg: 0 }, fees: { devFee: 0, uiFee: 0, oracleFee: 0, minerFee: 0, totalFee: 0 }, maxErgOutput: maxErgOutput, }); @@ -456,12 +453,12 @@ export function ReactorSwap() { } }); - const gauToken = updatedTokens.find((t) => t.symbol === "GAU"); - const gaucToken = updatedTokens.find((t) => t.symbol === "GAUC"); - if (gauToken && gaucToken) { - const gauBalanceNum = parseFloat(gauToken.balance); - const gaucBalanceNum = parseFloat(gaucToken.balance); - const pairBalanceVal = Math.min(Number.isNaN(gauBalanceNum) ? 0 : gauBalanceNum, Number.isNaN(gaucBalanceNum) ? 0 : gaucBalanceNum); + const neutronToken = updatedTokens.find((t) => t.symbol === "GAU"); + const protonToken = updatedTokens.find((t) => t.symbol === "GAUC"); + if (neutronToken && protonToken) { + const neutronBalanceNum = parseFloat(neutronToken.balance); + const protonBalanceNum = parseFloat(protonToken.balance); + const pairBalanceVal = Math.min(Number.isNaN(neutronBalanceNum) ? 0 : neutronBalanceNum, Number.isNaN(protonBalanceNum) ? 0 : protonBalanceNum); const pairBalance = formatTokenAmount(pairBalanceVal.toString()); updatedTokens = updatedTokens.map((t) => (t.symbol === "GAU-GAUC" ? { ...t, balance: pairBalance } : t)); } @@ -533,8 +530,8 @@ export function ReactorSwap() { setToToken(zeroBalanceTokens[3]); setFromAmount(""); setToAmount(""); - setGauAmount("0"); - setGaucAmount("0"); + setNeutronAmount("0"); + setProtonAmount("0"); } }, [isConnected]); @@ -551,7 +548,7 @@ export function ReactorSwap() { debouncedCalculateAmounts.cancel(); setReceiptDetails({ inputAmount: 0, - outputAmount: { gau: 0, gauc: 0, erg: 0 }, + outputAmount: { neutron: 0, proton: 0, erg: 0 }, fees: { devFee: 0, uiFee: 0, oracleFee: 0, minerFee: 0, totalFee: 0 }, maxErgOutput, }); @@ -569,7 +566,7 @@ export function ReactorSwap() { debouncedCalculateAmounts.cancel(); setReceiptDetails({ inputAmount: 0, - outputAmount: { gau: 0, gauc: 0, erg: 0 }, + outputAmount: { neutron: 0, proton: 0, erg: 0 }, fees: { devFee: 0, uiFee: 0, oracleFee: 0, minerFee: 0, totalFee: 0 }, maxErgOutput, }); @@ -587,11 +584,11 @@ export function ReactorSwap() { // Reset all values when switching directions setFromAmount(""); setToAmount(""); - setGauAmount("0"); - setGaucAmount("0"); + setNeutronAmount("0"); + setProtonAmount("0"); setReceiptDetails({ inputAmount: 0, - outputAmount: { gau: 0, gauc: 0, erg: 0 }, + outputAmount: { neutron: 0, proton: 0, erg: 0 }, fees: { devFee: 0, uiFee: 0, oracleFee: 0, minerFee: 0, totalFee: 0 }, maxErgOutput, }); @@ -679,11 +676,11 @@ export function ReactorSwap() { await calculateAmounts(maxAmount, isFromCard); } else { setToAmount(""); - setGauAmount("0"); - setGaucAmount("0"); + setNeutronAmount("0"); + setProtonAmount("0"); setReceiptDetails({ inputAmount: 0, - outputAmount: { gau: 0, gauc: 0, erg: 0 }, + outputAmount: { neutron: 0, proton: 0, erg: 0 }, fees: { devFee: 0, uiFee: 0, oracleFee: 0, minerFee: 0, totalFee: 0 }, maxErgOutput: maxErgOutput, }); @@ -713,24 +710,24 @@ export function ReactorSwap() { // Determine action type for transaction listener let actionType = ""; let inputAmount = ""; - let outputAmounts = { gau: "", gauc: "", erg: "" }; + let outputAmounts = { neutron: "", proton: "", erg: "" }; if (fromToken.symbol === "ERG" && toToken.symbol === "GAU-GAUC") { actionType = "fission"; inputAmount = fromAmount; - outputAmounts = { gau: gauAmount, gauc: gaucAmount, erg: "0" }; + outputAmounts = { neutron: neutronAmount, proton: protonAmount, erg: "0" }; } else if (fromToken.symbol === "GAU-GAUC" && toToken.symbol === "ERG") { actionType = "fusion"; inputAmount = toAmount; // For fusion, we target ERG output - outputAmounts = { gau: "0", gauc: "0", erg: toAmount }; + outputAmounts = { neutron: "0", proton: "0", erg: toAmount }; } else if (fromToken.symbol === "GAUC" && toToken.symbol === "GAU") { actionType = "transmute-to-gold"; inputAmount = fromAmount; - outputAmounts = { gau: toAmount, gauc: "0", erg: "0" }; + outputAmounts = { neutron: toAmount, proton: "0", erg: "0" }; } else if (fromToken.symbol === "GAU" && toToken.symbol === "GAUC") { actionType = "transmute-from-gold"; inputAmount = fromAmount; - outputAmounts = { gau: "0", gauc: toAmount, erg: "0" }; + outputAmounts = { neutron: "0", proton: toAmount, erg: "0" }; } // Calculate expected changes for transaction listener @@ -795,11 +792,11 @@ export function ReactorSwap() { // Reset form immediately (UI responsiveness) setFromAmount(""); setToAmount(""); - setGauAmount("0"); - setGaucAmount("0"); + setNeutronAmount("0"); + setProtonAmount("0"); setReceiptDetails({ inputAmount: 0, - outputAmount: { gau: 0, gauc: 0, erg: 0 }, + outputAmount: { neutron: 0, proton: 0, erg: 0 }, fees: { devFee: 0, uiFee: 0, oracleFee: 0, minerFee: 0, totalFee: 0 }, maxErgOutput: maxErgOutput, }); @@ -819,14 +816,14 @@ export function ReactorSwap() { const calculateMaxErgForFusion = async () => { if (!boxesReady || !gluonInstance || !gluonBox) return; try { - const gauBalanceStr = tokens.find((t) => t.symbol === "GAU")?.balance || "0"; - const gaucBalanceStr = tokens.find((t) => t.symbol === "GAUC")?.balance || "0"; + const neutronBalanceStr = tokens.find((t) => t.symbol === "GAU")?.balance || "0"; + const protonBalanceStr = tokens.find((t) => t.symbol === "GAUC")?.balance || "0"; const result = await calculateFusionAmounts({ gluonInstance, gluonBox, value: "0", - gauBalance: gauBalanceStr, - gaucBalance: gaucBalanceStr, + neutronBalance: neutronBalanceStr, + protonBalance: protonBalanceStr, }); if (!("error" in result) && result.maxErgOutput) { const valuePair = createValuePair(result.maxErgOutput); @@ -1133,14 +1130,14 @@ export function ReactorSwap() { - {formatTokenAmount(gauAmount)} + {formatTokenAmount(neutronAmount)} - {formatTokenAmount(gaucAmount)} + {formatTokenAmount(protonAmount)} t.symbol === "GAU")?.balance || "0"); - const gaucBalance = parseFloat(tokens.find((t) => t.symbol === "GAUC")?.balance || "0"); + const neutronRequired = parseFloat(neutronAmount); + const protonRequired = parseFloat(protonAmount); + const neutronBalance = parseFloat(tokens.find((t) => t.symbol === "GAU")?.balance || "0"); + const protonBalance = parseFloat(tokens.find((t) => t.symbol === "GAUC")?.balance || "0"); if (isNaN(ergOutput) || ergOutput <= 0) return true; - if (isNaN(gauRequired) || gauRequired <= 0) return true; - if (isNaN(gaucRequired) || gaucRequired <= 0) return true; - if (gauRequired > gauBalance || gaucRequired > gaucBalance) return true; + if (isNaN(neutronRequired) || neutronRequired <= 0) return true; + if (isNaN(protonRequired) || protonRequired <= 0) return true; + if (neutronRequired > neutronBalance || protonRequired > protonBalance) return true; // Use precise comparison but allow for display value tolerance try { @@ -1241,17 +1238,17 @@ export function ReactorSwap() { return false; } if (fromToken.symbol === "GAUC" && toToken.symbol === "GAU") { - const gaucInput = fromVal; - const gaucBalance = parseFloat(tokens.find((t) => t.symbol === "GAUC")?.balance || "0"); - if (Number.isNaN(gaucInput) || gaucInput <= 0) return true; - if (gaucInput > gaucBalance) return true; + const protonInput = fromVal; + const protonBalance = parseFloat(tokens.find((t) => t.symbol === "GAUC")?.balance || "0"); + if (Number.isNaN(protonInput) || protonInput <= 0) return true; + if (protonInput > protonBalance) return true; return false; } if (fromToken.symbol === "GAU" && toToken.symbol === "GAUC") { - const gauInput = fromVal; - const gauBalance = parseFloat(tokens.find((t) => t.symbol === "GAU")?.balance || "0"); - if (Number.isNaN(gauInput) || gauInput <= 0) return true; - if (gauInput > gauBalance) return true; + const neutronInput = fromVal; + const neutronBalance = parseFloat(tokens.find((t) => t.symbol === "GAU")?.balance || "0"); + if (Number.isNaN(neutronInput) || neutronInput <= 0) return true; + if (neutronInput > neutronBalance) return true; return false; } return true; @@ -1471,7 +1468,7 @@ export function ReactorSwap() { > {fromToken.symbol !== "GAU-GAUC" ? `${formatTokenAmount(formatValue(receiptDetails.inputAmount))} ${fromToken.symbol}` - : `${formatTokenAmount(gauAmount)} GAU - ${formatTokenAmount(gaucAmount)} GAUC`} + : `${formatTokenAmount(neutronAmount)} ${protocolConfig.tokens.neutron.ticker} - ${formatTokenAmount(protonAmount)} ${protocolConfig.tokens.proton.ticker}`} @@ -1578,40 +1575,40 @@ export function ReactorSwap() { {toToken.symbol === "GAU-GAUC" && ( -
{formatTokenAmount(formatValue(receiptDetails.outputAmount.gau))} GAU
-
{formatTokenAmount(formatValue(receiptDetails.outputAmount.gauc))} GAUC
+
{formatTokenAmount(formatValue(receiptDetails.outputAmount.neutron))} GAU
+
{formatTokenAmount(formatValue(receiptDetails.outputAmount.proton))} GAUC
)}
{toToken.symbol === "GAU" && currentAction === "gauc-to-gau" && ( - {formatTokenAmount(formatValue(receiptDetails.outputAmount.gau))} GAU + {formatTokenAmount(formatValue(receiptDetails.outputAmount.neutron))} GAU )} {toToken.symbol === "GAUC" && currentAction === "gau-to-gauc" && ( - {formatTokenAmount(formatValue(receiptDetails.outputAmount.gauc))} GAUC + {formatTokenAmount(formatValue(receiptDetails.outputAmount.proton))} GAUC )} diff --git a/src/lib/components/blocks/dashboard/GluonStats.tsx b/src/lib/components/blocks/dashboard/GluonStats.tsx index 2aa5063..76c1a92 100644 --- a/src/lib/components/blocks/dashboard/GluonStats.tsx +++ b/src/lib/components/blocks/dashboard/GluonStats.tsx @@ -12,6 +12,7 @@ import BigNumber from "bignumber.js"; import { motion, AnimatePresence } from "framer-motion"; import GauIcon from "@/lib/components/icons/GauIcon"; import GaucIcon from "@/lib/components/icons/GaucIcon"; +import { protocolConfig } from "@/lib/config/protocol"; interface GluonStats { ergPrice: number | null; @@ -151,10 +152,7 @@ export function GluonStats() { "7Day": { fissions: volume7DayPN, fusions: volume7DayNP }, "14Day": { fissions: volume14DayPN, fusions: volume14DayNP }, }, - circulatingSupply: { - gau: Number(circNeutrons), - gauc: Number(circProtons), - }, + circulatingSupply: { gau: Number(circNeutrons), gauc: Number(circProtons) }, volumeArrays: volumeArrays, prices: { gold: goldPriceBN.toNumber(), @@ -305,11 +303,32 @@ export function GluonStats() { {/* Token Grid - Responsive */}
- {renderStatCard("Gram of Gold", "Gold (from Oracle)", stats.goldPrice, , "ERG", 0.1)} + {renderStatCard( + protocolConfig.ui.labels.assetPriceTitle, + protocolConfig.ui.labels.assetPriceSubtitle, + stats.goldPrice, + , + "ERG", + 0.1 + )} - {renderStatCard("GAU", "Gold Pegged Token", stats.gauPrice, , "ERG", 0.2)} + {renderStatCard( + protocolConfig.tokens.neutron.ticker, + protocolConfig.ui.labels.neutronSubtitle, + stats.gauPrice, + , + "ERG", + 0.2 + )} - {renderStatCard("GAUC", "Leveraged Yield Token", stats.gaucPrice, , "ERG", 0.3)} + {renderStatCard( + protocolConfig.tokens.proton.ticker, + protocolConfig.ui.labels.protonSubtitle, + stats.gaucPrice, + , + "ERG", + 0.3 + )}
{/* Stats */} @@ -360,25 +379,29 @@ export function GluonStats() {
{isLoading ? : hasError ? "—" : nanoErgsToErgs(protocolMetrics.volume14Day.neutronsToProtons).toFixed(2)}
-
14d GAU to GAUC Volume (ERG)
+
+ 14d {protocolConfig.tokens.neutron.ticker} to {protocolConfig.tokens.proton.ticker} Volume (ERG) +
{isLoading ? : hasError ? "—" : nanoErgsToErgs(protocolMetrics.volume14Day.protonsToNeutrons).toFixed(2)}
-
14d GAUC to GAU Volume (ERG)
+
+ 14d {protocolConfig.tokens.proton.ticker} to {protocolConfig.tokens.neutron.ticker} Volume (ERG) +
{isLoading ? : hasError ? "—" : convertFromDecimals(protocolMetrics.circulatingSupply.neutrons).toFixed(2)}
-
GAU Supply
+
{protocolConfig.ui.labels.neutronSupplyLabel}
{isLoading ? : hasError ? "—" : convertFromDecimals(protocolMetrics.circulatingSupply.protons).toFixed(2)}
-
GAUC Supply
+
{protocolConfig.ui.labels.protonSupplyLabel}
@@ -434,8 +457,18 @@ export function GluonStats() { transition={{ duration: 0.3 }} className="text-center" > -
{hasError ? "—" : stats.priceCrashCushion ? Math.round(+stats.priceCrashCushion) : "—" }%
-
{renderTooltip("Price Crash Cushion", "Maximum drop in the price of ERG w.r.t. Gold that can be tolerated for GAU to remain pegged to Gold. When 0%, GAU depegs to prevent bank runs and maintain non-zero GAUC price.")}
+
+ {hasError + ? "—" + : stats.reserveRatio + ? Math.round(-(100 / (100 - Number(stats.reserveRatio))) * 100) / 100 + : "—"} + x
+
+
+ Reserve-Implied {protocolConfig.tokens.proton.ticker} Leverage +
+
)} diff --git a/src/lib/components/blocks/dashboard/MyStats.tsx b/src/lib/components/blocks/dashboard/MyStats.tsx index 28e569e..e9cd175 100644 --- a/src/lib/components/blocks/dashboard/MyStats.tsx +++ b/src/lib/components/blocks/dashboard/MyStats.tsx @@ -12,6 +12,7 @@ import BigNumber from "bignumber.js"; import ErgIcon from "@/lib/components/icons/ErgIcon"; import GauIcon from "@/lib/components/icons/GauIcon"; import GaucIcon from "@/lib/components/icons/GaucIcon"; +import { protocolConfig } from "@/lib/config/protocol"; interface WalletStats { ergBalance: string; @@ -197,16 +198,16 @@ export function MyStats() { case "GAU": return { icon: , - name: "GAU", - symbol: "GAU", - fullName: "Gold Pegged", + name: protocolConfig.tokens.neutron.ticker, + symbol: protocolConfig.tokens.neutron.ticker, + fullName: protocolConfig.ui.labels.neutronSubtitle, }; case "GAUC": return { icon: , - name: "GAUC", - symbol: "GAUC", - fullName: "Collateral", + name: protocolConfig.tokens.proton.ticker, + symbol: protocolConfig.tokens.proton.ticker, + fullName: protocolConfig.ui.labels.protonSubtitle, }; } }; diff --git a/src/lib/components/blocks/home/Features.tsx b/src/lib/components/blocks/home/Features.tsx index 7886834..7030a16 100644 --- a/src/lib/components/blocks/home/Features.tsx +++ b/src/lib/components/blocks/home/Features.tsx @@ -8,6 +8,7 @@ import GaucIcon from "@/lib/components/icons/GaucIcon"; import { useRef, forwardRef, useState, useEffect } from "react"; import { cn } from "@/lib/utils/utils"; import { motion } from "framer-motion"; +import { protocolConfig } from "@/lib/config/protocol"; const Circle = forwardRef(({ className, children }, ref) => { return ( @@ -185,17 +186,17 @@ export const Features = () => ( animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.5, duration: 0.5 }} > - Get exposure to Gold with GAU. + Get exposure to {protocolConfig.peg.asset} with {protocolConfig.tokens.neutron.ticker}.
- GAU is the stablecoin pegged to 1g of Gold. + {protocolConfig.tokens.neutron.ticker} is the stable token pegged to {protocolConfig.peg.asset}.

- Get leveraged volatility and yield with GAUC. + Get leveraged volatility and yield with {protocolConfig.tokens.proton.ticker}.
- GAUC tokenizes the reserve surplus. + {protocolConfig.tokens.proton.ticker} tokenizes the reserve surplus.

- Both GAU and GAUC are fully backed by ERG. + Both {protocolConfig.tokens.neutron.ticker} and {protocolConfig.tokens.proton.ticker} are fully backed by ERG. @@ -204,22 +205,22 @@ export const Features = () => ( { icon: Maximize2, title: "Fission", - description: "Splits $ERG tokens into $GAU stable tokeons and $GAUC volatile tokeons", + description: "Split ERG into the stable and leveraged tokens of the Gluon protocol.", }, { icon: Minimize2, title: "Fusion", - description: "Merges $GAU stable tokeons and $GAUC volatile tokeons into $ERG tokens", + description: "Merge the stable and leveraged tokens back into ERG.", }, { icon: Repeat, - title: "Transmute to Gold", - description: "Transmutes $GAUC volatile tokeons into $GAU stable tokeons", + title: "Transmute to Stable", + description: "Convert the leveraged token into the stable token.", }, { icon: Repeat, - title: "Transmute from Gold", - description: "Transmutes $GAU stable tokeons into $GAUC volatile tokeons", + title: "Transmute to Leveraged", + description: "Convert the stable token into the leveraged token.", }, ].map((item, index) => ( ( animate={{ opacity: 1, x: 0 }} transition={{ delay: 0.4, duration: 0.5 }} > - {/* Fission: ERG -> GAU + GAUC */} - {/* Fusion: GAU + GAUC -> ERG */} - {/* Transmute To Gold: GAUC -> GAU */} - + - {/* Transmute From Gold: GAU -> GAUC */} - + diff --git a/src/lib/components/blocks/home/Hero.tsx b/src/lib/components/blocks/home/Hero.tsx index 3665cae..4210eee 100644 --- a/src/lib/components/blocks/home/Hero.tsx +++ b/src/lib/components/blocks/home/Hero.tsx @@ -2,6 +2,7 @@ import { Button } from "@/lib/components/ui/button"; import { useRouter } from "next/navigation"; import { HeroText } from "../../ui/hero-text"; import { motion } from "framer-motion"; +import { protocolConfig } from "@/lib/config/protocol"; export default function Hero() { const router = useRouter(); @@ -21,8 +22,9 @@ export default function Hero() {

- Trade and transact with digital gold-pegged tokens.
- Secured by the Ergo blockchain and its decentralized gold price oracle. + {protocolConfig.ui.hero.tagline} +
+ {protocolConfig.ui.hero.subTagline}

diff --git a/src/lib/components/layout/BottomNavbar.tsx b/src/lib/components/layout/BottomNavbar.tsx index e74554d..088a731 100644 --- a/src/lib/components/layout/BottomNavbar.tsx +++ b/src/lib/components/layout/BottomNavbar.tsx @@ -5,6 +5,7 @@ import { cn } from "@/lib/utils/utils"; import { useMediaQuery } from "usehooks-ts"; import { useTheme } from "next-themes"; import { useEffect, useState } from "react"; +import { protocolConfig } from "@/lib/config/protocol"; const socialLinks = [ { @@ -20,7 +21,7 @@ const socialLinks = [ iconDark: "/logo/Discord-White.svg", }, { - href: "https://t.me/GluonGold", + href: `https://t.me/${protocolConfig.ui.labels.telegramHandle}`, label: "Telegram", iconLight: "/logo/Telegram-Black.svg", iconDark: "/logo/Telegram-White.svg", diff --git a/src/lib/components/layout/SEO.tsx b/src/lib/components/layout/SEO.tsx index 9d48c8c..4ec8f73 100644 --- a/src/lib/components/layout/SEO.tsx +++ b/src/lib/components/layout/SEO.tsx @@ -1,4 +1,5 @@ import Head from "next/head"; +import { protocolConfig } from "@/lib/config/protocol"; interface SEOProps { title?: string; @@ -10,11 +11,12 @@ interface SEOProps { } export function SEO({ - title = "Gluon Gold | Gold-Pegged Stablecoin on the Ergo Blockchain", - description = "Gluon Gold on Ergo is a fully autonomous stablecoin based on the novel Gluon Stablecoin Protocol, pegged to Gold, backed by the ERG cryptocurrency and running in a fully decentralized manner on the Ergo blockchain. Mint, swap and trade gold-pegged stable tokens or leveraged yield tokens according to your stability or volatility needs.", - keywords = "Blockchain, Cryptocurrency, Stablecoin, DeFi, Decentralized Finance, Digital Assets, Tokens, Gold, Gluon, Stability, GAU, CAUC, Gold-Pegged Stablecoin, Gold-Pegged Token, Crypto-Backed Stablecoin", - image = "/logo/gluon.png", - url = "https://www.gluon.gold/", + title = protocolConfig.seo.defaultTitle, + description = protocolConfig.seo.defaultDescription, + keywords = protocolConfig.seo.defaultKeywords, + image = protocolConfig.seo.defaultImage, + url = protocolConfig.seo.defaultUrl, + type = "website", }: SEOProps) { const siteTitle = title.includes("Gluon") ? title : `${title} | Gluon`; diff --git a/src/lib/components/layout/TopNavbar.tsx b/src/lib/components/layout/TopNavbar.tsx index 65e6d8c..ebf859a 100644 --- a/src/lib/components/layout/TopNavbar.tsx +++ b/src/lib/components/layout/TopNavbar.tsx @@ -9,6 +9,7 @@ import { cn } from "@/lib/utils/utils"; import { useRouter } from "next/router"; import { WalletConnector } from "../blockchain/connector/WalletConnector"; import { useTheme } from "next-themes"; +import { protocolConfig } from "@/lib/config/protocol"; const navItems = [ { href: "/reactor", label: "Reactor" }, @@ -54,7 +55,7 @@ export function TopNavbar() {
Gluon Logo - {isDesktop &&

GLUON GOLD

} + {isDesktop &&

{protocolConfig.ui.labels.navbarTitle}

}
diff --git a/src/lib/components/ui/hero-text.tsx b/src/lib/components/ui/hero-text.tsx index f15ffc1..f7c08e7 100644 --- a/src/lib/components/ui/hero-text.tsx +++ b/src/lib/components/ui/hero-text.tsx @@ -1,9 +1,13 @@ import { useEffect, useMemo, useState } from "react"; import { motion } from "framer-motion"; +import { protocolConfig } from "@/lib/config/protocol"; function HeroText() { const [titleNumber, setTitleNumber] = useState(0); - const titles = useMemo(() => ["Decentralized", "Autonomous", "Permissionless", "Transparent", "Fully Crypto Backed", "Gold-Pegged"], []); + const titles = useMemo( + () => ["Decentralized", "Autonomous", "Permissionless", "Transparent", "Fully Crypto Backed", protocolConfig.peg.adjective], + [] + ); useEffect(() => { const timeoutId = setTimeout(() => { diff --git a/src/lib/config/protocol.ts b/src/lib/config/protocol.ts new file mode 100644 index 0000000..2f7594c --- /dev/null +++ b/src/lib/config/protocol.ts @@ -0,0 +1,55 @@ +export const protocolConfig = { + peg: { + asset: "Gold", + adjective: "Gold-Pegged", + description: "digital gold-pegged tokens", + }, + tokens: { + /** + * Neutron = stable token in the Gluon protocol. + * For the current deployment this corresponds to GAU. + */ + neutron: { + ticker: "GAU", + name: "Gluon Gold", + shortDescription: "Stable token pegged to 1g of Gold.", + }, + /** + * Proton = volatile token in the Gluon protocol. + * For the current deployment this corresponds to GAUC. + */ + proton: { + ticker: "GAUC", + name: "Gluon Gold Certificate", + shortDescription: "Volatile token that tokenizes the reserve surplus.", + }, + }, + seo: { + defaultTitle: "Gluon | Gold Protocol on Ergo", + defaultDescription: + "Gluon is a decentralized finance protocol on Ergo blockchain that enables users to trade, swap, and manage gold-backed tokens.", + defaultKeywords: "Gluon, Ergo, DeFi, Blockchain, Cryptocurrency, Gold-backed tokens, GAU, GAUC, Digital Assets", + defaultUrl: "https://www.gluon.gold/", + defaultImage: "/logo/gluon.png", + }, + ui: { + hero: { + tagline: "Trade and transact with digital gold-pegged tokens.", + subTagline: "Secured by the Ergo blockchain and its decentralized gold price oracle.", + }, + labels: { + navbarTitle: "GLUON GOLD", + telegramHandle: "GluonGold", + assetPriceTitle: "1 kg of Gold", + assetPriceSubtitle: "Oracle Gold Price", + neutronSubtitle: "Gold Pegged Token", + protonSubtitle: "Leveraged Yield Token", + neutronSupplyLabel: "GAU Supply", + protonSupplyLabel: "GAUC Supply", + }, + }, +} as const; + +export type ProtocolConfig = typeof protocolConfig; + + diff --git a/src/lib/functions/reactor/handleFission.ts b/src/lib/functions/reactor/handleFission.ts index c1ba2f6..3f654ef 100644 --- a/src/lib/functions/reactor/handleFission.ts +++ b/src/lib/functions/reactor/handleFission.ts @@ -25,7 +25,7 @@ export const calculateFissionAmounts = async ({ gluonInstance, gluonBox, value } type: typeof ergToFission, }); - // Get prediction of GAU/GAUC amounts + // Get prediction of stable/leveraged token amounts const willGet = await gluonInstance.fissionWillGet(gluonBox, Number(ergToFission)); console.log("🔍 FISSION PREDICTION RAW:", willGet); @@ -33,12 +33,12 @@ export const calculateFissionAmounts = async ({ gluonInstance, gluonBox, value } throw new Error("Failed to get fission prediction from SDK"); } - // Format the values using our utility - NOTE: protons are GAUC, neutrons are GAU - const formattedGau = formatMicroNumber(convertFromDecimals(willGet.neutrons)); - const formattedGauc = formatMicroNumber(convertFromDecimals(willGet.protons)); + // Format the values using our utility - NOTE: neutrons are the stable token (GAU), protons are the leveraged token (GAUC) + const formattedNeutron = formatMicroNumber(convertFromDecimals(willGet.neutrons)); + const formattedProton = formatMicroNumber(convertFromDecimals(willGet.protons)); console.log("🔍 FISSION FORMATTED:", { - gau: formattedGau, - gauc: formattedGauc, + neutron: formattedNeutron, + proton: formattedProton, rawNeutrons: willGet.neutrons.toString(), rawProtons: willGet.protons.toString(), }); @@ -50,8 +50,8 @@ export const calculateFissionAmounts = async ({ gluonInstance, gluonBox, value } const receiptDetails: ReceiptDetails = { inputAmount: numValue, outputAmount: { - gau: convertFromDecimals(willGet.neutrons), // neutrons are GAU - gauc: convertFromDecimals(willGet.protons), // protons are GAUC + neutron: convertFromDecimals(willGet.neutrons), + proton: convertFromDecimals(willGet.protons), erg: 0, }, fees: { @@ -64,8 +64,8 @@ export const calculateFissionAmounts = async ({ gluonInstance, gluonBox, value } }; return { - gauAmount: formattedGau.display, - gaucAmount: formattedGauc.display, + neutronAmount: formattedNeutron.display, + protonAmount: formattedProton.display, toAmount: "0", // Not used in fission receiptDetails, maxErgOutput: "0", // Not applicable for fission @@ -79,8 +79,8 @@ export const calculateFissionAmounts = async ({ gluonInstance, gluonBox, value } return { error: errorDetails.userMessage, resetValues: { - gauAmount: "0", - gaucAmount: "0", + neutronAmount: "0", + protonAmount: "0", }, }; } diff --git a/src/lib/functions/reactor/handleFusion.ts b/src/lib/functions/reactor/handleFusion.ts index d79e26a..7518d59 100644 --- a/src/lib/functions/reactor/handleFusion.ts +++ b/src/lib/functions/reactor/handleFusion.ts @@ -7,28 +7,22 @@ interface FusionParams { gluonInstance: any; gluonBox: any; value: string; - gauBalance: string; - gaucBalance: string; + neutronBalance: string; + protonBalance: string; } /** - * Calculate the maximum possible ERG output based on available GAU/GAUC balances + * Calculate the maximum possible ERG output based on available neutron/proton balances */ -const calculateMaxErgOutput = async (gluonInstance: any, gluonBox: any, gauBalance: string, gaucBalance: string): Promise => { +const calculateMaxErgOutput = async (gluonInstance: any, gluonBox: any, neutronBalance: string, protonBalance: string): Promise => { try { // Convert our balances to blockchain decimals (these are BigInts) - const gauAmount = BigInt(convertToDecimals(gauBalance)); - const gaucAmount = BigInt(convertToDecimals(gaucBalance)); + const neutronAmount = BigInt(convertToDecimals(neutronBalance)); + const protonAmount = BigInt(convertToDecimals(protonBalance)); console.log("Input Validation:", { - displayValues: { - gau: gauBalance, - gauc: gaucBalance, - }, - nanoValues: { - gauNano: gauAmount.toString(), - gaucNano: gaucAmount.toString(), - }, + displayValues: { neutron: neutronBalance, proton: protonBalance }, + nanoValues: { neutronNano: neutronAmount.toString(), protonNano: protonAmount.toString() }, }); // Get token ratio for 1 ERG @@ -42,9 +36,9 @@ const calculateMaxErgOutput = async (gluonInstance: any, gluonBox: any, gauBalan // Calculate maximum ERG we can get based on our token ratios // All calculations done in BigInt - const maxFromGau = (gauAmount * oneErg) / neutronsNeeded; - const maxFromGauc = (gaucAmount * oneErg) / protonsNeeded; - const maxPossibleNanoErgs = maxFromGau < maxFromGauc ? maxFromGau : maxFromGauc; + const maxFromNeutron = (neutronAmount * oneErg) / neutronsNeeded; + const maxFromProton = (protonAmount * oneErg) / protonsNeeded; + const maxPossibleNanoErgs = maxFromNeutron < maxFromProton ? maxFromNeutron : maxFromProton; console.log("Max ERG Calculation:", { maxErg: new BigNumber(maxPossibleNanoErgs.toString()).dividedBy(1e9).toFixed(), @@ -59,12 +53,12 @@ const calculateMaxErgOutput = async (gluonInstance: any, gluonBox: any, gauBalan }; /** - * Calculate the amounts of GAU and GAUC needed for fusion to get the desired ERG amount + * Calculate the amounts of neutron and proton tokens needed for fusion to get the desired ERG amount */ -export const calculateFusionAmounts = async ({ gluonInstance, gluonBox, value, gauBalance, gaucBalance }: FusionParams): Promise => { +export const calculateFusionAmounts = async ({ gluonInstance, gluonBox, value, neutronBalance, protonBalance }: FusionParams): Promise => { try { // Get maximum possible ERG output - const maxNanoErgs = await calculateMaxErgOutput(gluonInstance, gluonBox, gauBalance, gaucBalance); + const maxNanoErgs = await calculateMaxErgOutput(gluonInstance, gluonBox, neutronBalance, protonBalance); // Use BigNumber to preserve precision instead of converting to Number const maxErgStr = maxNanoErgs.dividedBy(1e9).toFixed(); @@ -75,17 +69,17 @@ export const calculateFusionAmounts = async ({ gluonInstance, gluonBox, value, g const { neutrons, protons } = await gluonInstance.fusionWillNeed(gluonBox, Number(desiredNanoErgs)); // Convert to display values - const requiredGau = convertFromDecimals(BigInt(neutrons)).toString(); - const requiredGauc = convertFromDecimals(BigInt(protons)).toString(); + const requiredNeutron = convertFromDecimals(BigInt(neutrons)).toString(); + const requiredProton = convertFromDecimals(BigInt(protons)).toString(); // Get fee prediction (using Number since the SDK expects it) const fees = await gluonInstance.getTotalFeeAmountFusion(gluonBox, Number(desiredNanoErgs)); const receiptDetails: ReceiptDetails = { - inputAmount: parseFloat(requiredGau), + inputAmount: parseFloat(requiredNeutron), outputAmount: { - gau: parseFloat(requiredGau), - gauc: parseFloat(requiredGauc), + neutron: parseFloat(requiredNeutron), + proton: parseFloat(requiredProton), erg: parseFloat(value), }, fees: { @@ -99,8 +93,8 @@ export const calculateFusionAmounts = async ({ gluonInstance, gluonBox, value, g }; return { - gauAmount: requiredGau, - gaucAmount: requiredGauc, + neutronAmount: requiredNeutron, + protonAmount: requiredProton, toAmount: value, maxErgOutput: maxErgStr, receiptDetails, @@ -114,8 +108,8 @@ export const calculateFusionAmounts = async ({ gluonInstance, gluonBox, value, g return { error: errorDetails.userMessage, resetValues: { - gauAmount: "0", - gaucAmount: "0", + neutronAmount: "0", + protonAmount: "0", toAmount: "0", }, }; diff --git a/src/lib/functions/reactor/handleTransmutation.ts b/src/lib/functions/reactor/handleTransmutation.ts index 1ccc418..0098af9 100644 --- a/src/lib/functions/reactor/handleTransmutation.ts +++ b/src/lib/functions/reactor/handleTransmutation.ts @@ -31,14 +31,14 @@ export const calculateTransmutationAmounts = async ({ }); if (numValue <= 0) { - return { - error: "Amount must be greater than zero.", - resetValues: { - gauAmount: "0", - gaucAmount: "0", - toAmount: "0", - }, - }; + return { + error: "Amount must be greater than zero.", + resetValues: { + neutronAmount: "0", + protonAmount: "0", + toAmount: "0", + }, + }; } // Convert input amount to blockchain decimals @@ -103,8 +103,8 @@ export const calculateTransmutationAmounts = async ({ const receiptDetails: ReceiptDetails = { inputAmount: numValue, outputAmount: { - gau: fromTokenSymbol === "GAUC" ? parseFloat(formattedOutput.display) : numValue, - gauc: fromTokenSymbol === "GAU" ? parseFloat(formattedOutput.display) : numValue, + neutron: fromTokenSymbol === "GAUC" ? parseFloat(formattedOutput.display) : numValue, + proton: fromTokenSymbol === "GAU" ? parseFloat(formattedOutput.display) : numValue, erg: 0, }, fees: { @@ -117,15 +117,15 @@ export const calculateTransmutationAmounts = async ({ }; console.log("🔍 [DEBUG] FINAL OUTPUT", { - gauAmount: fromTokenSymbol === "GAUC" ? formattedOutput.display : value, - gaucAmount: fromTokenSymbol === "GAU" ? formattedOutput.display : value, + neutronAmount: fromTokenSymbol === "GAUC" ? formattedOutput.display : value, + protonAmount: fromTokenSymbol === "GAU" ? formattedOutput.display : value, toAmount: formattedOutput.display, receiptDetails, }); return { - gauAmount: fromTokenSymbol === "GAUC" ? formattedOutput.display : value, - gaucAmount: fromTokenSymbol === "GAU" ? formattedOutput.display : value, + neutronAmount: fromTokenSymbol === "GAUC" ? formattedOutput.display : value, + protonAmount: fromTokenSymbol === "GAU" ? formattedOutput.display : value, toAmount: formattedOutput.display, receiptDetails, maxErgOutput: "0", // Transmutation doesn't involve ERG, so this is always 0 @@ -139,8 +139,8 @@ export const calculateTransmutationAmounts = async ({ return { error: errorDetails.userMessage, resetValues: { - gauAmount: "0", - gaucAmount: "0", + neutronAmount: "0", + protonAmount: "0", toAmount: "0", }, }; diff --git a/src/lib/functions/reactor/types.ts b/src/lib/functions/reactor/types.ts index c1117b7..022a846 100644 --- a/src/lib/functions/reactor/types.ts +++ b/src/lib/functions/reactor/types.ts @@ -20,8 +20,8 @@ export interface TokenPair { export interface ReceiptDetails { inputAmount: number | BigNumber; outputAmount: { - gau: number | BigNumber; - gauc: number | BigNumber; + neutron: number | BigNumber; + proton: number | BigNumber; erg: number | BigNumber; }; fees: { @@ -46,8 +46,8 @@ export interface GluonBoxes { } export interface SwapResult { - gauAmount: string; - gaucAmount: string; + neutronAmount: string; + protonAmount: string; toAmount: string; maxErgOutput: string; receiptDetails: ReceiptDetails; @@ -56,8 +56,8 @@ export interface SwapResult { export interface SwapError { error: string; resetValues?: { - gauAmount?: string; - gaucAmount?: string; + neutronAmount?: string; + protonAmount?: string; toAmount?: string; }; }