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",
|
||||
"private": true,
|
||||
"version": "0.3.4",
|
||||
"version": "0.3.5",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@ -13,6 +13,7 @@ import { ChangeEvent, useState, useEffect } from "react";
|
||||
import { useNavigate, createSearchParams } from "react-router-dom";
|
||||
import { useQuery } from "react-query";
|
||||
import { formatCurrency, formatNumber } from "../../../helpers";
|
||||
import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber"
|
||||
import { tokenNameConverter } from "../../../helpers/tokenConverter";
|
||||
import { isNetworkLegacy } from "../../../constants";
|
||||
|
||||
@ -21,9 +22,15 @@ import TokenStack from "../../TokenStack/TokenStack";
|
||||
import { PrimaryButton, SecondaryButton } from "../../Button";
|
||||
|
||||
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 { useAccount } from "wagmi";
|
||||
import { useAccount, useBalance as useNativeBalance, useConfig } from "wagmi";
|
||||
|
||||
const addTokenToWallet = async (token, userAddress) => {
|
||||
if (!window.ethereum) return;
|
||||
@ -62,6 +69,7 @@ const BalanceValue = ({
|
||||
|
||||
export const Token = (props) => {
|
||||
const {
|
||||
isNative,
|
||||
symbol,
|
||||
icons,
|
||||
address,
|
||||
@ -100,8 +108,11 @@ export const Token = (props) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Accordion expanded={expanded} onChange={onChangeExpanded}>
|
||||
<AccordionSummary expandIcon={<GhostStyledIcon component={ExpandMoreIcon} color="disabled" />}>
|
||||
<Accordion expanded={isNative ? false : expanded} onChange={onChangeExpanded}>
|
||||
<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", alignItems: "center", gap: "15px" }}>
|
||||
<TokenStack
|
||||
@ -119,7 +130,7 @@ export const Token = (props) => {
|
||||
/>
|
||||
</Box>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails style={{ margin: "auto", padding: theme.spacing(1, 0) }}>
|
||||
{!isNative && <AccordionDetails style={{ margin: "auto", padding: theme.spacing(1, 0) }}>
|
||||
<Box
|
||||
sx={{ display: "flex", flexDirection: "column", flex: 1, mx: "32px", justifyContent: "center" }}
|
||||
style={{ gap: theme.spacing(1) }}
|
||||
@ -139,7 +150,7 @@ export const Token = (props) => {
|
||||
</SecondaryButton>
|
||||
</Box>
|
||||
</Box>
|
||||
</AccordionDetails>
|
||||
</AccordionDetails>}
|
||||
</Accordion>
|
||||
);
|
||||
};
|
||||
@ -148,6 +159,11 @@ const sumObjValues = (obj: Record<string, string> = {}) =>
|
||||
Object.values(obj).reduce((sum, b = "0.0") => sum + (parseFloat(b) || 0), 0);
|
||||
|
||||
export const useWallet = (chainId, userAddress) => {
|
||||
const {
|
||||
data: nativeBalanceRaw,
|
||||
refetch: nativeBalanceRefetch
|
||||
} = useNativeBalance({ address: userAddress });
|
||||
const nativeBalance = new DecimalBigNumber(nativeBalanceRaw?.value ?? 0n, 18);
|
||||
const {
|
||||
balance: reserveBalance,
|
||||
refetch: reserveRefetch,
|
||||
@ -174,12 +190,16 @@ export const useWallet = (chainId, userAddress) => {
|
||||
contractAddress: lpReserveFtsoBalanceAddress,
|
||||
} = useBalance(chainId, "RESERVE_FTSO", userAddress);
|
||||
|
||||
const reservePrice = useDaiPrice(chainId);
|
||||
const nativePrice = useNativePrice(chainId);
|
||||
const reservePrice = useReservePrice(chainId);
|
||||
const ftsoPrice = useFtsoPrice(chainId);
|
||||
const stnkPrice = useStnkPrice(chainId);
|
||||
const ghstPrice = useGhstPrice(chainId);
|
||||
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: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
||||
const { symbol: stnkSymbol } = useTokenSymbol(chainId, "STNK");
|
||||
@ -187,6 +207,13 @@ export const useWallet = (chainId, userAddress) => {
|
||||
const { symbol: lpReserveFtsoSymbol } = useTokenSymbol(chainId, "RESERVE_FTSO");
|
||||
|
||||
const tokens = {
|
||||
native: {
|
||||
symbol: nativeSymbol,
|
||||
icons: [nativeSymbol],
|
||||
balance: nativeBalance,
|
||||
price: nativePrice,
|
||||
refetch: nativeBalanceRefetch
|
||||
},
|
||||
reserve: {
|
||||
symbol: reserveSymbol,
|
||||
address: reserveAddress,
|
||||
@ -250,7 +277,7 @@ export const useWallet = (chainId, userAddress) => {
|
||||
|
||||
export const Tokens = ({ address, tokens, onClose }) => {
|
||||
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) => ({
|
||||
...token,
|
||||
@ -264,7 +291,7 @@ export const Tokens = ({ address, tokens, onClose }) => {
|
||||
return (
|
||||
<>
|
||||
{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",
|
||||
};
|
||||
|
||||
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 = {
|
||||
[NetworkId.TESTNET_MORDOR]: [
|
||||
"https://api.binance.com/api/v3/ticker/price?symbol=ETCUSDT",
|
||||
|
||||
@ -13,7 +13,8 @@ import {
|
||||
useFtsoPrice,
|
||||
useStnkPrice,
|
||||
useGhstPrice,
|
||||
useDaiPrice,
|
||||
useReservePrice,
|
||||
useNativePrice,
|
||||
} from "../../../hooks/prices";
|
||||
import { tokenNameConverter } from "../../../helpers/tokenConverter";
|
||||
|
||||
@ -79,10 +80,11 @@ const TokenInfo = ({ chainId, isMobileScreen }) => {
|
||||
const config = useConfig();
|
||||
const nativeSymbol = config?.getClient()?.chain?.nativeCurrency?.symbol;
|
||||
|
||||
const nativePrice = useNativePrice(chainId);
|
||||
const ftsoPrice = useFtsoPrice(chainId);
|
||||
const stnkPrice = useStnkPrice(chainId);
|
||||
const ghstPrice = useGhstPrice(chainId);
|
||||
const reservePrice = useDaiPrice(chainId);
|
||||
const reservePrice = useReservePrice(chainId);
|
||||
|
||||
const { symbol: reserveSymbol } = useTokenSymbol(chainId, "RESERVE");
|
||||
const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
|
||||
|
||||
@ -8,12 +8,13 @@ import {
|
||||
FTSO_DAI_LP_ADDRESSES,
|
||||
RESERVE_ADDRESSES,
|
||||
FTSO_ADDRESSES,
|
||||
CEX_TICKERS
|
||||
CEX_TICKERS,
|
||||
NATIVE_TICKERS,
|
||||
} from "../../constants/addresses";
|
||||
|
||||
const cexPriceGetters = new Map();
|
||||
|
||||
function callWithCacheTTL(fn, ttlMs = 5000) {
|
||||
function callWithCacheTTL(fn, ttlMs = 10000) {
|
||||
let lastFetchTime = 0;
|
||||
let cachedValue;
|
||||
let inFlight = null;
|
||||
@ -41,13 +42,13 @@ function callWithCacheTTL(fn, ttlMs = 5000) {
|
||||
}
|
||||
}
|
||||
|
||||
export const useDaiPrice = (chainId) => {
|
||||
const [daiPrice, setDaiPrice] = useState(new DecimalBigNumber(1000000000000000000n, 18));
|
||||
const cexApis = CEX_TICKERS[chainId];
|
||||
export const useNativePrice = (chainId) => {
|
||||
const [nativePrice, setNativePrice] = useState(new DecimalBigNumber(1000000000000000000n, 18));
|
||||
const cexApis = NATIVE_TICKERS[chainId];
|
||||
|
||||
useEffect(() => {
|
||||
if (!cexApis) {
|
||||
setDaiPrice(new DecimalBigNumber(1000000000000000000n, 18));
|
||||
setNativePrice(new DecimalBigNumber(1000000000000000000n, 18));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -70,27 +71,73 @@ export const useDaiPrice = (chainId) => {
|
||||
if ('data' in response) {
|
||||
const coinPrice = Number(response?.data?.amount ?? 0.0);
|
||||
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) {
|
||||
const coinPrice = Number(response?.price ?? 0.0);
|
||||
const priceInWei = Math.floor(coinPrice * 1e18)
|
||||
setDaiPrice(new DecimalBigNumber(BigInt(priceInWei), 18));
|
||||
setNativePrice(new DecimalBigNumber(BigInt(priceInWei), 18));
|
||||
} else {
|
||||
throw Error("Unexpected json in response.");
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
setDaiPrice(new DecimalBigNumber(0n, 18));
|
||||
setNativePrice(new DecimalBigNumber(0n, 18));
|
||||
});
|
||||
}, [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) => {
|
||||
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 ftsoAddress = FTSO_ADDRESSES[chainId];
|
||||
if (!reserveAddress || !ftsoAddress) {
|
||||
|
||||
@ -3,7 +3,7 @@ import { useReadContract } from "wagmi";
|
||||
import { DAO_TREASURY_ADDRESSES } from "../../constants/addresses";
|
||||
import { abi as TreasuryAbi } from "../../abi/GhostTreasury.json";
|
||||
|
||||
import { useDaiPrice } from "../prices/index";
|
||||
import { useReservePrice } from "../prices/index";
|
||||
|
||||
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
|
||||
import { getTokenAddress } from "../helpers";
|
||||
@ -30,7 +30,7 @@ export const useTotalReserves = (chainId) => {
|
||||
});
|
||||
|
||||
const original = useOrinalCoefficient(chainId);
|
||||
const price = useDaiPrice(chainId);
|
||||
const price = useReservePrice(chainId);
|
||||
|
||||
const totalReservesPrepared = totalReservesRaw ? totalReservesRaw : 0n;
|
||||
const totalReserves = new DecimalBigNumber(totalReservesPrepared, 9);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user