bridge_ui: compile TVL hook
Change-Id: I706f37155d2e09312998aef9725226928eeeefb1
This commit is contained in:
parent
b641101158
commit
7e6123a3a8
|
@ -0,0 +1,188 @@
|
|||
import { CHAIN_ID_ETH, CHAIN_ID_SOLANA } from "@certusone/wormhole-sdk";
|
||||
import { formatUnits } from "@ethersproject/units";
|
||||
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
|
||||
import {
|
||||
AccountInfo,
|
||||
Connection,
|
||||
ParsedAccountData,
|
||||
PublicKey,
|
||||
} from "@solana/web3.js";
|
||||
import axios from "axios";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { DataWrapper } from "../store/helpers";
|
||||
import {
|
||||
COVALENT_GET_TOKENS_URL,
|
||||
ETH_TOKEN_BRIDGE_ADDRESS,
|
||||
SOLANA_HOST,
|
||||
SOL_CUSTODY_ADDRESS,
|
||||
} from "../utils/consts";
|
||||
import useMetadata, { GenericMetadata } from "./useMetadata";
|
||||
|
||||
export type TVL = {
|
||||
logo?: string;
|
||||
symbol?: string;
|
||||
name?: string;
|
||||
amount: string;
|
||||
totalValue?: number;
|
||||
quotePrice?: number;
|
||||
assetAddress: string;
|
||||
originChain: string;
|
||||
};
|
||||
|
||||
const calcEthTVL = (covalentReport: any): TVL[] => {
|
||||
const output: TVL[] = [];
|
||||
if (!covalentReport?.data?.items?.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
covalentReport.data.items.forEach((item: any) => {
|
||||
if (item.balance > 0 && item.contract_address) {
|
||||
output.push({
|
||||
logo: item.logo_url || undefined,
|
||||
symbol: item.contract_ticker_symbol || undefined,
|
||||
name: item.contract_name || undefined,
|
||||
amount: formatUnits(item.balance, item.contract_decimals),
|
||||
totalValue: item.quote,
|
||||
quotePrice: item.quote_rate,
|
||||
assetAddress: item.contract_address,
|
||||
originChain: "Ethereum",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return output;
|
||||
};
|
||||
const calcSolanaTVL = (
|
||||
accounts:
|
||||
| { pubkey: PublicKey; account: AccountInfo<ParsedAccountData> }[]
|
||||
| undefined,
|
||||
metaData: DataWrapper<Map<string, GenericMetadata>>
|
||||
) => {
|
||||
const output: TVL[] = [];
|
||||
if (
|
||||
!accounts ||
|
||||
!accounts.length ||
|
||||
metaData.isFetching ||
|
||||
metaData.error ||
|
||||
!metaData.data
|
||||
) {
|
||||
return output;
|
||||
}
|
||||
|
||||
accounts.forEach((item) => {
|
||||
const genericMetadata = metaData.data?.get(
|
||||
item.account.data.parsed?.info?.mint?.toString()
|
||||
);
|
||||
output.push({
|
||||
logo: genericMetadata?.logo || undefined,
|
||||
symbol: genericMetadata?.symbol || undefined,
|
||||
name: genericMetadata?.tokenName || undefined,
|
||||
amount: item.account.data.parsed?.info?.tokenAmount?.uiAmount || "0", //Should always be defined.
|
||||
totalValue: undefined,
|
||||
quotePrice: undefined,
|
||||
assetAddress: item.account.data.parsed?.info?.mint?.toString(),
|
||||
originChain: "Solana",
|
||||
});
|
||||
});
|
||||
|
||||
return output;
|
||||
};
|
||||
|
||||
const useTVL = (): DataWrapper<TVL[]> => {
|
||||
const [covalentData, setCovalentData] = useState(undefined);
|
||||
const [covalentIsLoading, setCovalentIsLoading] = useState(false);
|
||||
const [covalentError, setCovalentError] = useState("");
|
||||
|
||||
const [solanaCustodyTokens, setSolanaCustodyTokens] = useState<
|
||||
{ pubkey: PublicKey; account: AccountInfo<ParsedAccountData> }[] | undefined
|
||||
>(undefined);
|
||||
const [solanaCustodyTokensLoading, setSolanaCustodyTokensLoading] =
|
||||
useState(false);
|
||||
const [solanaCustodyTokensError, setSolanaCustodyTokensError] = useState("");
|
||||
const mintAddresses = useMemo(() => {
|
||||
const addresses: string[] = [];
|
||||
solanaCustodyTokens?.forEach((item) => {
|
||||
const mintKey = item.account.data.parsed?.info?.mint?.toString();
|
||||
if (mintKey) {
|
||||
addresses.push(mintKey);
|
||||
}
|
||||
});
|
||||
return addresses;
|
||||
}, [solanaCustodyTokens]);
|
||||
|
||||
const solanaMetadata = useMetadata(CHAIN_ID_SOLANA, mintAddresses);
|
||||
|
||||
const solanaTVL = useMemo(
|
||||
() => calcSolanaTVL(solanaCustodyTokens, solanaMetadata),
|
||||
[solanaCustodyTokens, solanaMetadata]
|
||||
);
|
||||
const ethTVL = useMemo(() => calcEthTVL(covalentData), [covalentData]);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
setCovalentIsLoading(true);
|
||||
axios
|
||||
.get(
|
||||
COVALENT_GET_TOKENS_URL(CHAIN_ID_ETH, ETH_TOKEN_BRIDGE_ADDRESS, false)
|
||||
)
|
||||
.then(
|
||||
(results) => {
|
||||
if (!cancelled) {
|
||||
setCovalentData(results.data);
|
||||
setCovalentIsLoading(false);
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
if (!cancelled) {
|
||||
setCovalentError("Unable to retrieve Ethereum TVL.");
|
||||
setCovalentIsLoading(false);
|
||||
}
|
||||
}
|
||||
);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
const connection = new Connection(SOLANA_HOST, "confirmed");
|
||||
connection
|
||||
.getParsedTokenAccountsByOwner(new PublicKey(SOL_CUSTODY_ADDRESS), {
|
||||
programId: TOKEN_PROGRAM_ID,
|
||||
})
|
||||
.then(
|
||||
(results) => {
|
||||
if (!cancelled) {
|
||||
setSolanaCustodyTokens(results.value);
|
||||
setSolanaCustodyTokensLoading(false);
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
if (!cancelled) {
|
||||
setSolanaCustodyTokensLoading(false);
|
||||
setSolanaCustodyTokensError(
|
||||
"Unable to retrieve Solana locked tokens."
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}, []);
|
||||
|
||||
return useMemo(() => {
|
||||
const tvlArray = [...ethTVL, ...solanaTVL];
|
||||
|
||||
return {
|
||||
isFetching: covalentIsLoading || solanaCustodyTokensLoading,
|
||||
error: covalentError || solanaCustodyTokensError,
|
||||
receivedAt: null,
|
||||
data: tvlArray,
|
||||
};
|
||||
}, [
|
||||
covalentError,
|
||||
covalentIsLoading,
|
||||
ethTVL,
|
||||
solanaTVL,
|
||||
solanaCustodyTokensError,
|
||||
solanaCustodyTokensLoading,
|
||||
]);
|
||||
};
|
||||
|
||||
export default useTVL;
|
|
@ -138,6 +138,9 @@ export const SOL_TOKEN_BRIDGE_ADDRESS =
|
|||
: CLUSTER === "testnet"
|
||||
? "A4Us8EhCC76XdGAN17L4KpRNEK423nMivVHZzZqFqqBg"
|
||||
: "B6RHG3mfcckmrYN1UhmJzyS1XX3fZKbkeUcpJe9Sy3FE";
|
||||
|
||||
export const SOL_CUSTODY_ADDRESS =
|
||||
"GugU1tP7doLeTw9hQP51xRJyS8Da1fWxuiy2rVrnMD2m";
|
||||
export const TERRA_TEST_TOKEN_ADDRESS =
|
||||
"terra13nkgqrfymug724h8pprpexqj9h629sa3ncw7sh";
|
||||
export const TERRA_BRIDGE_ADDRESS =
|
||||
|
|
Loading…
Reference in New Issue