bridge_ui: compile TVL hook

Change-Id: I706f37155d2e09312998aef9725226928eeeefb1
This commit is contained in:
Chase Moran 2021-09-28 12:31:24 -04:00 committed by Evan Gray
parent b641101158
commit 7e6123a3a8
2 changed files with 191 additions and 0 deletions

View File

@ -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;

View File

@ -138,6 +138,9 @@ export const SOL_TOKEN_BRIDGE_ADDRESS =
: CLUSTER === "testnet" : CLUSTER === "testnet"
? "A4Us8EhCC76XdGAN17L4KpRNEK423nMivVHZzZqFqqBg" ? "A4Us8EhCC76XdGAN17L4KpRNEK423nMivVHZzZqFqqBg"
: "B6RHG3mfcckmrYN1UhmJzyS1XX3fZKbkeUcpJe9Sy3FE"; : "B6RHG3mfcckmrYN1UhmJzyS1XX3fZKbkeUcpJe9Sy3FE";
export const SOL_CUSTODY_ADDRESS =
"GugU1tP7doLeTw9hQP51xRJyS8Da1fWxuiy2rVrnMD2m";
export const TERRA_TEST_TOKEN_ADDRESS = export const TERRA_TEST_TOKEN_ADDRESS =
"terra13nkgqrfymug724h8pprpexqj9h629sa3ncw7sh"; "terra13nkgqrfymug724h8pprpexqj9h629sa3ncw7sh";
export const TERRA_BRIDGE_ADDRESS = export const TERRA_BRIDGE_ADDRESS =