bridge_ui: fetch on-chain terra name and symbol

Change-Id: Iaf211735a4e6ebf720d0d8ba6972211edcf6e220
This commit is contained in:
Evan Gray 2021-11-10 17:32:24 -05:00
parent 0d7e145c63
commit 181c107b50
4 changed files with 105 additions and 12 deletions

View File

@ -122,7 +122,9 @@ export default function TerraTokenPicker(props: TerraTokenPickerProps) {
balance.balance.toString(),
info.decimals,
Number(formatUnits(balance.balance, info.decimals)),
formatUnits(balance.balance, info.decimals)
formatUnits(balance.balance, info.decimals),
info.symbol,
info.name
);
} else {
throw new Error("Failed to retrieve Terra account.");

View File

@ -131,7 +131,7 @@ export const BasicAccountRender = (
</div>
<div>
<Typography>{mintPrettyString}</Typography>
<Typography>{tokenId}</Typography>
<Typography style={{ wordBreak: "break-all" }}>{tokenId}</Typography>
</div>
</div>
);

View File

@ -11,6 +11,7 @@ import { Metadata } from "../utils/metaplex";
import useEvmMetadata, { EvmMetadata } from "./useEvmMetadata";
import useMetaplexData from "./useMetaplexData";
import useSolanaTokenMap from "./useSolanaTokenMap";
import useTerraMetadata, { TerraMetadata } from "./useTerraMetadata";
import useTerraTokenMap, { TerraTokenMap } from "./useTerraTokenMap";
export type GenericMetadata = {
@ -55,19 +56,21 @@ const constructSolanaMetadata = (
const constructTerraMetadata = (
addresses: string[],
tokenMap: DataWrapper<TerraTokenMap>
tokenMap: DataWrapper<TerraTokenMap>,
terraMetadata: DataWrapper<Map<string, TerraMetadata>>
) => {
const isFetching = tokenMap.isFetching;
const error = tokenMap.error;
const receivedAt = tokenMap.receivedAt;
const isFetching = tokenMap.isFetching || terraMetadata.isFetching;
const error = tokenMap.error || terraMetadata.error;
const receivedAt = tokenMap.receivedAt && terraMetadata.receivedAt;
const data = new Map<string, GenericMetadata>();
addresses.forEach((address) => {
const meta = tokenMap.data?.mainnet[address];
const metadata = terraMetadata.data?.get(address);
const tokenInfo = tokenMap.data?.mainnet[address];
const obj = {
symbol: meta?.symbol || undefined,
logo: meta?.icon || undefined,
tokenName: meta?.token || undefined,
decimals: undefined, //TODO find a way to get this on terra
symbol: metadata?.symbol || tokenInfo?.symbol || undefined,
logo: metadata?.logo || tokenInfo?.icon || undefined,
tokenName: metadata?.tokenName || tokenInfo?.token || undefined,
decimals: metadata?.decimals || undefined,
};
data.set(address, obj);
});
@ -125,6 +128,7 @@ export default function useMetadata(
}, [chainId, addresses]);
const metaplexData = useMetaplexData(solanaAddresses);
const terraMetadata = useTerraMetadata(terraAddresses);
const ethMetadata = useEvmMetadata(ethereumAddresses, chainId);
const output: DataWrapper<Map<string, GenericMetadata>> = useMemo(
@ -134,7 +138,7 @@ export default function useMetadata(
: isEVMChain(chainId)
? constructEthMetadata(ethereumAddresses, ethMetadata)
: chainId === CHAIN_ID_TERRA
? constructTerraMetadata(terraAddresses, terraTokenMap)
? constructTerraMetadata(terraAddresses, terraTokenMap, terraMetadata)
: getEmptyDataWrapper(),
[
chainId,
@ -144,6 +148,7 @@ export default function useMetadata(
ethereumAddresses,
ethMetadata,
terraAddresses,
terraMetadata,
terraTokenMap,
]
);

View File

@ -0,0 +1,86 @@
import { LCDClient } from "@terra-money/terra.js";
import { useLayoutEffect, useMemo, useState } from "react";
import { DataWrapper } from "../store/helpers";
import { TERRA_HOST } from "../utils/consts";
export type TerraMetadata = {
symbol?: string;
logo?: string;
tokenName?: string;
decimals?: number;
};
const fetchSingleMetadata = async (address: string, lcd: LCDClient) =>
lcd.wasm
.contractQuery(address, {
token_info: {},
})
.then(
({ symbol, name: tokenName, decimals }: any) =>
({
symbol,
tokenName,
decimals,
} as TerraMetadata)
);
const fetchTerraMetadata = async (addresses: string[]) => {
const lcd = new LCDClient(TERRA_HOST);
const promises: Promise<TerraMetadata>[] = [];
addresses.forEach((address) => {
promises.push(fetchSingleMetadata(address, lcd));
});
const resultsArray = await Promise.all(promises);
const output = new Map<string, TerraMetadata>();
addresses.forEach((address, index) => {
output.set(address, resultsArray[index]);
});
return output;
};
const useTerraMetadata = (
addresses: string[]
): DataWrapper<Map<string, TerraMetadata>> => {
const [isFetching, setIsFetching] = useState(false);
const [error, setError] = useState("");
const [data, setData] = useState<Map<string, TerraMetadata> | null>(null);
useLayoutEffect(() => {
let cancelled = false;
if (addresses.length) {
setIsFetching(true);
setError("");
setData(null);
fetchTerraMetadata(addresses).then(
(results) => {
if (!cancelled) {
setData(results);
setIsFetching(false);
}
},
() => {
if (!cancelled) {
setError("Could not retrieve contract metadata");
setIsFetching(false);
}
}
);
}
return () => {
cancelled = true;
};
}, [addresses]);
return useMemo(
() => ({
data,
isFetching,
error,
receivedAt: null,
}),
[data, isFetching, error]
);
};
export default useTerraMetadata;