native coin added to wallet tab
Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
parent
e153760532
commit
0925c79ff8
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ghost-dao-interface",
|
"name": "ghost-dao-interface",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.3.4",
|
"version": "0.3.5",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import { ChangeEvent, useState, useEffect } from "react";
|
|||||||
import { useNavigate, createSearchParams } from "react-router-dom";
|
import { useNavigate, createSearchParams } from "react-router-dom";
|
||||||
import { useQuery } from "react-query";
|
import { useQuery } from "react-query";
|
||||||
import { formatCurrency, formatNumber } from "../../../helpers";
|
import { formatCurrency, formatNumber } from "../../../helpers";
|
||||||
|
import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber"
|
||||||
import { tokenNameConverter } from "../../../helpers/tokenConverter";
|
import { tokenNameConverter } from "../../../helpers/tokenConverter";
|
||||||
import { isNetworkLegacy } from "../../../constants";
|
import { isNetworkLegacy } from "../../../constants";
|
||||||
|
|
||||||
@ -21,9 +22,15 @@ import TokenStack from "../../TokenStack/TokenStack";
|
|||||||
import { PrimaryButton, SecondaryButton } from "../../Button";
|
import { PrimaryButton, SecondaryButton } from "../../Button";
|
||||||
|
|
||||||
import { useBalance, useTokenSymbol } from "../../../hooks/tokens";
|
import { useBalance, useTokenSymbol } from "../../../hooks/tokens";
|
||||||
import { useDaiPrice, useFtsoPrice, useStnkPrice, useGhstPrice } from "../../../hooks/prices";
|
import {
|
||||||
|
useNativePrice,
|
||||||
|
useReservePrice,
|
||||||
|
useFtsoPrice,
|
||||||
|
useStnkPrice,
|
||||||
|
useGhstPrice
|
||||||
|
} from "../../../hooks/prices";
|
||||||
import { useLpValuation } from "../../../hooks/treasury";
|
import { useLpValuation } from "../../../hooks/treasury";
|
||||||
import { useAccount } from "wagmi";
|
import { useAccount, useBalance as useNativeBalance, useConfig } from "wagmi";
|
||||||
|
|
||||||
const addTokenToWallet = async (token, userAddress) => {
|
const addTokenToWallet = async (token, userAddress) => {
|
||||||
if (!window.ethereum) return;
|
if (!window.ethereum) return;
|
||||||
@ -62,6 +69,7 @@ const BalanceValue = ({
|
|||||||
|
|
||||||
export const Token = (props) => {
|
export const Token = (props) => {
|
||||||
const {
|
const {
|
||||||
|
isNative,
|
||||||
symbol,
|
symbol,
|
||||||
icons,
|
icons,
|
||||||
address,
|
address,
|
||||||
@ -100,8 +108,11 @@ export const Token = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Accordion expanded={expanded} onChange={onChangeExpanded}>
|
<Accordion expanded={isNative ? false : expanded} onChange={onChangeExpanded}>
|
||||||
<AccordionSummary expandIcon={<GhostStyledIcon component={ExpandMoreIcon} color="disabled" />}>
|
<AccordionSummary
|
||||||
|
sx={{ paddingRight: isNative ? "37.43px" : "" }}
|
||||||
|
expandIcon={isNative ? null : <GhostStyledIcon component={ExpandMoreIcon} color="disabled" />}
|
||||||
|
>
|
||||||
<Box sx={{ display: "flex", justifyContent: "space-between", width: "100%", marginRight: "10px" }}>
|
<Box sx={{ display: "flex", justifyContent: "space-between", width: "100%", marginRight: "10px" }}>
|
||||||
<Box sx={{ display: "flex", alignItems: "center", gap: "15px" }}>
|
<Box sx={{ display: "flex", alignItems: "center", gap: "15px" }}>
|
||||||
<TokenStack
|
<TokenStack
|
||||||
@ -119,7 +130,7 @@ export const Token = (props) => {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</AccordionSummary>
|
</AccordionSummary>
|
||||||
<AccordionDetails style={{ margin: "auto", padding: theme.spacing(1, 0) }}>
|
{!isNative && <AccordionDetails style={{ margin: "auto", padding: theme.spacing(1, 0) }}>
|
||||||
<Box
|
<Box
|
||||||
sx={{ display: "flex", flexDirection: "column", flex: 1, mx: "32px", justifyContent: "center" }}
|
sx={{ display: "flex", flexDirection: "column", flex: 1, mx: "32px", justifyContent: "center" }}
|
||||||
style={{ gap: theme.spacing(1) }}
|
style={{ gap: theme.spacing(1) }}
|
||||||
@ -139,7 +150,7 @@ export const Token = (props) => {
|
|||||||
</SecondaryButton>
|
</SecondaryButton>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</AccordionDetails>
|
</AccordionDetails>}
|
||||||
</Accordion>
|
</Accordion>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -148,6 +159,11 @@ const sumObjValues = (obj: Record<string, string> = {}) =>
|
|||||||
Object.values(obj).reduce((sum, b = "0.0") => sum + (parseFloat(b) || 0), 0);
|
Object.values(obj).reduce((sum, b = "0.0") => sum + (parseFloat(b) || 0), 0);
|
||||||
|
|
||||||
export const useWallet = (chainId, userAddress) => {
|
export const useWallet = (chainId, userAddress) => {
|
||||||
|
const {
|
||||||
|
data: nativeBalanceRaw,
|
||||||
|
refetch: nativeBalanceRefetch
|
||||||
|
} = useNativeBalance({ address: userAddress });
|
||||||
|
const nativeBalance = new DecimalBigNumber(nativeBalanceRaw?.value ?? 0n, 18);
|
||||||
const {
|
const {
|
||||||
balance: reserveBalance,
|
balance: reserveBalance,
|
||||||
refetch: reserveRefetch,
|
refetch: reserveRefetch,
|
||||||
@ -174,12 +190,16 @@ export const useWallet = (chainId, userAddress) => {
|
|||||||
contractAddress: lpReserveFtsoBalanceAddress,
|
contractAddress: lpReserveFtsoBalanceAddress,
|
||||||
} = useBalance(chainId, "RESERVE_FTSO", userAddress);
|
} = useBalance(chainId, "RESERVE_FTSO", userAddress);
|
||||||
|
|
||||||
const reservePrice = useDaiPrice(chainId);
|
const nativePrice = useNativePrice(chainId);
|
||||||
|
const reservePrice = useReservePrice(chainId);
|
||||||
const ftsoPrice = useFtsoPrice(chainId);
|
const ftsoPrice = useFtsoPrice(chainId);
|
||||||
const stnkPrice = useStnkPrice(chainId);
|
const stnkPrice = useStnkPrice(chainId);
|
||||||
const ghstPrice = useGhstPrice(chainId);
|
const ghstPrice = useGhstPrice(chainId);
|
||||||
const lpReserveFtsoPrice = useLpValuation(chainId, "RESERVE_FTSO", 1000000000000000000n);
|
const lpReserveFtsoPrice = useLpValuation(chainId, "RESERVE_FTSO", 1000000000000000000n);
|
||||||
|
|
||||||
|
const config = useConfig();
|
||||||
|
|
||||||
|
const nativeSymbol = config?.getClient()?.chain?.nativeCurrency?.symbol;
|
||||||
const { symbol: reserveSymbol } = useTokenSymbol(chainId, "RESERVE");
|
const { symbol: reserveSymbol } = useTokenSymbol(chainId, "RESERVE");
|
||||||
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
||||||
const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK");
|
const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK");
|
||||||
@ -187,6 +207,13 @@ export const useWallet = (chainId, userAddress) => {
|
|||||||
const { symbol: lpReserveFtsoSymbol } = useTokenSymbol(chainId, "RESERVE_FTSO");
|
const { symbol: lpReserveFtsoSymbol } = useTokenSymbol(chainId, "RESERVE_FTSO");
|
||||||
|
|
||||||
const tokens = {
|
const tokens = {
|
||||||
|
native: {
|
||||||
|
symbol: nativeSymbol,
|
||||||
|
icons: [nativeSymbol],
|
||||||
|
balance: nativeBalance,
|
||||||
|
price: nativePrice,
|
||||||
|
refetch: nativeBalanceRefetch
|
||||||
|
},
|
||||||
reserve: {
|
reserve: {
|
||||||
symbol: reserveSymbol,
|
symbol: reserveSymbol,
|
||||||
address: reserveAddress,
|
address: reserveAddress,
|
||||||
@ -250,7 +277,7 @@ export const useWallet = (chainId, userAddress) => {
|
|||||||
|
|
||||||
export const Tokens = ({ address, tokens, onClose }) => {
|
export const Tokens = ({ address, tokens, onClose }) => {
|
||||||
const [expanded, setExpanded] = useState(null);
|
const [expanded, setExpanded] = useState(null);
|
||||||
const alwaysShowTokens = [tokens.reserve, tokens.ftso, tokens.stnk, tokens.ghst, tokens.reserveFtso];
|
const alwaysShowTokens = [tokens.native, tokens.reserve, tokens.ftso, tokens.stnk, tokens.ghst, tokens.reserveFtso];
|
||||||
|
|
||||||
const tokenProps = (token) => ({
|
const tokenProps = (token) => ({
|
||||||
...token,
|
...token,
|
||||||
@ -264,7 +291,7 @@ export const Tokens = ({ address, tokens, onClose }) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{alwaysShowTokens.map((token, i) => (
|
{alwaysShowTokens.map((token, i) => (
|
||||||
<Token key={i} {...tokenProps(token)} />
|
<Token key={i} isNative={i === 0} {...tokenProps(token)} />
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -95,6 +95,21 @@ export const UNISWAP_V2_FACTORY = {
|
|||||||
[NetworkId.TESTNET_MORDOR]: "0x909f96C1a436B3386E9962e30f3Ce753070ff524",
|
[NetworkId.TESTNET_MORDOR]: "0x909f96C1a436B3386E9962e30f3Ce753070ff524",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const NATIVE_TICKERS = {
|
||||||
|
[NetworkId.TESTNET_SEPOLIA]: [
|
||||||
|
"https://api.binance.com/api/v3/ticker/price?symbol=ETHUSDT",
|
||||||
|
"https://api.coinbase.com/v2/prices/ETH-USDT/spot",
|
||||||
|
],
|
||||||
|
[NetworkId.TESTNET_HOODI]: [
|
||||||
|
"https://api.binance.com/api/v3/ticker/price?symbol=ETHUSDT",
|
||||||
|
"https://api.coinbase.com/v2/prices/ETH-USDT/spot",
|
||||||
|
],
|
||||||
|
[NetworkId.TESTNET_MORDOR]: [
|
||||||
|
"https://api.binance.com/api/v3/ticker/price?symbol=ETCUSDT",
|
||||||
|
"https://api.coinbase.com/v2/prices/ETC-USDT/spot",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
export const CEX_TICKERS = {
|
export const CEX_TICKERS = {
|
||||||
[NetworkId.TESTNET_MORDOR]: [
|
[NetworkId.TESTNET_MORDOR]: [
|
||||||
"https://api.binance.com/api/v3/ticker/price?symbol=ETCUSDT",
|
"https://api.binance.com/api/v3/ticker/price?symbol=ETCUSDT",
|
||||||
|
|||||||
@ -13,7 +13,8 @@ import {
|
|||||||
useFtsoPrice,
|
useFtsoPrice,
|
||||||
useStnkPrice,
|
useStnkPrice,
|
||||||
useGhstPrice,
|
useGhstPrice,
|
||||||
useDaiPrice,
|
useReservePrice,
|
||||||
|
useNativePrice,
|
||||||
} from "../../../hooks/prices";
|
} from "../../../hooks/prices";
|
||||||
import { tokenNameConverter } from "../../../helpers/tokenConverter";
|
import { tokenNameConverter } from "../../../helpers/tokenConverter";
|
||||||
|
|
||||||
@ -79,10 +80,11 @@ const TokenInfo = ({ chainId, isMobileScreen }) => {
|
|||||||
const config = useConfig();
|
const config = useConfig();
|
||||||
const nativeSymbol = config?.getClient()?.chain?.nativeCurrency?.symbol;
|
const nativeSymbol = config?.getClient()?.chain?.nativeCurrency?.symbol;
|
||||||
|
|
||||||
|
const nativePrice = useNativePrice(chainId);
|
||||||
const ftsoPrice = useFtsoPrice(chainId);
|
const ftsoPrice = useFtsoPrice(chainId);
|
||||||
const stnkPrice = useStnkPrice(chainId);
|
const stnkPrice = useStnkPrice(chainId);
|
||||||
const ghstPrice = useGhstPrice(chainId);
|
const ghstPrice = useGhstPrice(chainId);
|
||||||
const reservePrice = useDaiPrice(chainId);
|
const reservePrice = useReservePrice(chainId);
|
||||||
|
|
||||||
const { symbol: reserveSymbol } = useTokenSymbol(chainId, "RESERVE");
|
const { symbol: reserveSymbol } = useTokenSymbol(chainId, "RESERVE");
|
||||||
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
||||||
|
|||||||
@ -8,12 +8,13 @@ import {
|
|||||||
FTSO_DAI_LP_ADDRESSES,
|
FTSO_DAI_LP_ADDRESSES,
|
||||||
RESERVE_ADDRESSES,
|
RESERVE_ADDRESSES,
|
||||||
FTSO_ADDRESSES,
|
FTSO_ADDRESSES,
|
||||||
CEX_TICKERS
|
CEX_TICKERS,
|
||||||
|
NATIVE_TICKERS,
|
||||||
} from "../../constants/addresses";
|
} from "../../constants/addresses";
|
||||||
|
|
||||||
const cexPriceGetters = new Map();
|
const cexPriceGetters = new Map();
|
||||||
|
|
||||||
function callWithCacheTTL(fn, ttlMs = 5000) {
|
function callWithCacheTTL(fn, ttlMs = 10000) {
|
||||||
let lastFetchTime = 0;
|
let lastFetchTime = 0;
|
||||||
let cachedValue;
|
let cachedValue;
|
||||||
let inFlight = null;
|
let inFlight = null;
|
||||||
@ -41,13 +42,13 @@ function callWithCacheTTL(fn, ttlMs = 5000) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useDaiPrice = (chainId) => {
|
export const useNativePrice = (chainId) => {
|
||||||
const [daiPrice, setDaiPrice] = useState(new DecimalBigNumber(1000000000000000000n, 18));
|
const [nativePrice, setNativePrice] = useState(new DecimalBigNumber(1000000000000000000n, 18));
|
||||||
const cexApis = CEX_TICKERS[chainId];
|
const cexApis = NATIVE_TICKERS[chainId];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!cexApis) {
|
if (!cexApis) {
|
||||||
setDaiPrice(new DecimalBigNumber(1000000000000000000n, 18));
|
setNativePrice(new DecimalBigNumber(1000000000000000000n, 18));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,27 +71,73 @@ export const useDaiPrice = (chainId) => {
|
|||||||
if ('data' in response) {
|
if ('data' in response) {
|
||||||
const coinPrice = Number(response?.data?.amount ?? 0.0);
|
const coinPrice = Number(response?.data?.amount ?? 0.0);
|
||||||
const priceInWei = Math.floor(coinPrice * 1e18 / 0.99);
|
const priceInWei = Math.floor(coinPrice * 1e18 / 0.99);
|
||||||
setDaiPrice(new DecimalBigNumber(BigInt(priceInWei), 18));
|
setNativePrice(new DecimalBigNumber(BigInt(priceInWei), 18));
|
||||||
} else if ('price' in response) {
|
} else if ('price' in response) {
|
||||||
const coinPrice = Number(response?.price ?? 0.0);
|
const coinPrice = Number(response?.price ?? 0.0);
|
||||||
const priceInWei = Math.floor(coinPrice * 1e18)
|
const priceInWei = Math.floor(coinPrice * 1e18)
|
||||||
setDaiPrice(new DecimalBigNumber(BigInt(priceInWei), 18));
|
setNativePrice(new DecimalBigNumber(BigInt(priceInWei), 18));
|
||||||
} else {
|
} else {
|
||||||
throw Error("Unexpected json in response.");
|
throw Error("Unexpected json in response.");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
setDaiPrice(new DecimalBigNumber(0n, 18));
|
setNativePrice(new DecimalBigNumber(0n, 18));
|
||||||
});
|
});
|
||||||
}, [chainId, cexApis])
|
}, [chainId, cexApis])
|
||||||
|
|
||||||
return daiPrice;
|
return nativePrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useReservePrice = (chainId) => {
|
||||||
|
const [reservePrice, setReservePrice] = useState(new DecimalBigNumber(1000000000000000000n, 18));
|
||||||
|
const cexApis = CEX_TICKERS[chainId];
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!cexApis) {
|
||||||
|
setReservePrice(new DecimalBigNumber(1000000000000000000n, 18));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let getCexPriceCached = cexPriceGetters.get(chainId);
|
||||||
|
if (!getCexPriceCached) {
|
||||||
|
getCexPriceCached = callWithCacheTTL(() => {
|
||||||
|
const fetchPromises = cexApis.map(url => fetch(url)
|
||||||
|
.then(res => {
|
||||||
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
||||||
|
return res.json();
|
||||||
|
})
|
||||||
|
)
|
||||||
|
return Promise.any(fetchPromises);
|
||||||
|
}, 5000);
|
||||||
|
cexPriceGetters.set(chainId, getCexPriceCached);
|
||||||
|
}
|
||||||
|
|
||||||
|
getCexPriceCached()
|
||||||
|
.then(response => {
|
||||||
|
if ('data' in response) {
|
||||||
|
const coinPrice = Number(response?.data?.amount ?? 0.0);
|
||||||
|
const priceInWei = Math.floor(coinPrice * 1e18 / 0.99);
|
||||||
|
setReservePrice(new DecimalBigNumber(BigInt(priceInWei), 18));
|
||||||
|
} else if ('price' in response) {
|
||||||
|
const coinPrice = Number(response?.price ?? 0.0);
|
||||||
|
const priceInWei = Math.floor(coinPrice * 1e18)
|
||||||
|
setReservePrice(new DecimalBigNumber(BigInt(priceInWei), 18));
|
||||||
|
} else {
|
||||||
|
throw Error("Unexpected json in response.");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
setReservePrice(new DecimalBigNumber(0n, 18));
|
||||||
|
});
|
||||||
|
}, [chainId, cexApis])
|
||||||
|
|
||||||
|
return reservePrice;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useFtsoPrice = (chainId) => {
|
export const useFtsoPrice = (chainId) => {
|
||||||
const { reserves, tokens, refetch } = useUniswapV2PairReserves(chainId, FTSO_DAI_LP_ADDRESSES[chainId]);
|
const { reserves, tokens, refetch } = useUniswapV2PairReserves(chainId, FTSO_DAI_LP_ADDRESSES[chainId]);
|
||||||
|
|
||||||
const reservePrice = useDaiPrice(chainId);
|
const reservePrice = useReservePrice(chainId);
|
||||||
const reserveAddress = RESERVE_ADDRESSES[chainId];
|
const reserveAddress = RESERVE_ADDRESSES[chainId];
|
||||||
const ftsoAddress = FTSO_ADDRESSES[chainId];
|
const ftsoAddress = FTSO_ADDRESSES[chainId];
|
||||||
if (!reserveAddress || !ftsoAddress) {
|
if (!reserveAddress || !ftsoAddress) {
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { useReadContract } from "wagmi";
|
|||||||
import { DAO_TREASURY_ADDRESSES } from "../../constants/addresses";
|
import { DAO_TREASURY_ADDRESSES } from "../../constants/addresses";
|
||||||
import { abi as TreasuryAbi } from "../../abi/GhostTreasury.json";
|
import { abi as TreasuryAbi } from "../../abi/GhostTreasury.json";
|
||||||
|
|
||||||
import { useDaiPrice } from "../prices/index";
|
import { useReservePrice } from "../prices/index";
|
||||||
|
|
||||||
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||||
import { getTokenAddress } from "../helpers";
|
import { getTokenAddress } from "../helpers";
|
||||||
@ -30,7 +30,7 @@ export const useTotalReserves = (chainId) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const original = useOrinalCoefficient(chainId);
|
const original = useOrinalCoefficient(chainId);
|
||||||
const price = useDaiPrice(chainId);
|
const price = useReservePrice(chainId);
|
||||||
|
|
||||||
const totalReservesPrepared = totalReservesRaw ? totalReservesRaw : 0n;
|
const totalReservesPrepared = totalReservesRaw ? totalReservesRaw : 0n;
|
||||||
const totalReserves = new DecimalBigNumber(totalReservesPrepared, 9);
|
const totalReserves = new DecimalBigNumber(totalReservesPrepared, 9);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user