bridge_ui: support terra source

Change-Id: Ia137e1c161851b946f86d08355fc197f43ae4fbf
This commit is contained in:
chase-45 2021-08-30 19:58:06 -04:00
parent 69349ab5c7
commit 0b9a2e05ad
4 changed files with 154 additions and 32 deletions

View File

@ -1,6 +1,10 @@
//import Autocomplete from '@material-ui/lab/Autocomplete';
import { CHAIN_ID_ETH, CHAIN_ID_SOLANA } from "@certusone/wormhole-sdk";
import { TextField } from "@material-ui/core";
import {
CHAIN_ID_ETH,
CHAIN_ID_SOLANA,
CHAIN_ID_TERRA,
} from "@certusone/wormhole-sdk";
import { TextField, Typography } from "@material-ui/core";
import { useCallback } from "react";
import { useDispatch, useSelector } from "react-redux";
import useGetSourceParsedTokens from "../../hooks/useGetSourceParsedTokenAccounts";
@ -14,6 +18,7 @@ import {
} from "../../store/transferSlice";
import EthereumSourceTokenSelector from "./EthereumSourceTokenSelector";
import SolanaSourceTokenSelector from "./SolanaSourceTokenSelector";
import TerraSourceTokenSelector from "./TerraSourceTokenSelector";
type TokenSelectorProps = {
disabled: boolean;
@ -37,29 +42,37 @@ export const TokenSelector = (props: TokenSelectorProps) => {
const maps = useGetSourceParsedTokens();
const content =
lookupChain === CHAIN_ID_SOLANA ? (
<SolanaSourceTokenSelector
value={sourceParsedTokenAccount || null}
onChange={handleSolanaOnChange}
accounts={maps?.tokenAccounts?.data || []}
solanaTokenMap={maps?.tokenMap}
metaplexData={maps?.metaplex}
/>
) : lookupChain === CHAIN_ID_ETH ? (
<EthereumSourceTokenSelector
value={sourceParsedTokenAccount || null}
onChange={handleSolanaOnChange}
/>
) : (
<TextField
placeholder="Asset"
fullWidth
value={"hardcoded"}
onChange={() => {}}
disabled={true}
/>
);
//This is only for errors so bad that we shouldn't even mount the component
const fatalError = maps?.tokenAccounts?.error;
const content = fatalError ? (
<Typography>{fatalError}</Typography>
) : lookupChain === CHAIN_ID_SOLANA ? (
<SolanaSourceTokenSelector
value={sourceParsedTokenAccount || null}
onChange={handleSolanaOnChange}
accounts={maps?.tokenAccounts?.data || []}
solanaTokenMap={maps?.tokenMap}
metaplexData={maps?.metaplex}
/>
) : lookupChain === CHAIN_ID_ETH ? (
<EthereumSourceTokenSelector
value={sourceParsedTokenAccount || null}
onChange={handleSolanaOnChange}
/>
) : lookupChain === CHAIN_ID_TERRA ? (
<TerraSourceTokenSelector
value={sourceParsedTokenAccount || null}
onChange={handleSolanaOnChange}
/>
) : (
<TextField
placeholder="Asset"
fullWidth
value={"Not Implemented"}
disabled={true}
/>
);
return <div>{content}</div>;
};

View File

@ -0,0 +1,111 @@
import { Button, TextField, Typography } from "@material-ui/core";
import { LCDClient } from "@terra-money/terra.js";
import {
ConnectedWallet,
useConnectedWallet,
} from "@terra-money/wallet-provider";
import { formatUnits } from "ethers/lib/utils";
import React, { useCallback, useState } from "react";
import { createParsedTokenAccount } from "../../hooks/useGetSourceParsedTokenAccounts";
import { ParsedTokenAccount } from "../../store/transferSlice";
import { TERRA_HOST } from "../../utils/consts";
type TerraSourceTokenSelectorProps = {
value: ParsedTokenAccount | null;
onChange: (newValue: ParsedTokenAccount | null) => void;
};
//TODO move elsewhere
//TODO async
const lookupTerraAddress = (
lookupAsset: string,
terraWallet: ConnectedWallet
) => {
const lcd = new LCDClient(TERRA_HOST);
return lcd.wasm
.contractQuery(lookupAsset, {
token_info: {},
})
.then((info: any) =>
lcd.wasm
.contractQuery(lookupAsset, {
balance: {
address: terraWallet.walletAddress,
},
})
.then((balance: any) => {
if (balance && info) {
return createParsedTokenAccount(
terraWallet.walletAddress,
lookupAsset,
balance.balance.toString(),
info.decimals,
Number(formatUnits(balance.balance, info.decimals)),
formatUnits(balance.balance, info.decimals)
);
} else {
throw new Error("Failed to retrieve Terra account.");
}
})
)
.catch(() => {
return Promise.reject();
});
};
export default function TerraSourceTokenSelector(
props: TerraSourceTokenSelectorProps
) {
const { onChange, value } = props;
//const advancedMode = true; //const [advancedMode, setAdvancedMode] = useState(true);
const [advancedModeHolderString, setAdvancedModeHolderString] = useState("");
const [advancedModeError, setAdvancedModeError] = useState("");
const terraWallet = useConnectedWallet();
const handleClick = useCallback(() => {
onChange(null);
setAdvancedModeHolderString("");
}, [onChange]);
const handleOnChange = useCallback(
(event) => setAdvancedModeHolderString(event.target.value),
[]
);
const handleConfirm = () => {
if (terraWallet === undefined) {
setAdvancedModeError("Terra wallet not connected.");
return;
}
lookupTerraAddress(advancedModeHolderString, terraWallet).then(
(result) => {
onChange(result);
},
(error) => {
setAdvancedModeError("Unable to retrieve address.");
}
);
setAdvancedModeError("");
};
const content = value ? (
<>
<Typography>{value.mintKey}</Typography>
<Button onClick={handleClick}>Clear</Button>
</>
) : (
<>
<TextField
fullWidth
label="Asset Address"
value={advancedModeHolderString}
onChange={handleOnChange}
error={advancedModeHolderString !== "" && !!advancedModeError}
helperText={advancedModeError === "" ? undefined : advancedModeError}
/>
<Button onClick={handleConfirm}>Confirm</Button>
</>
);
return <React.Fragment>{content}</React.Fragment>;
}

View File

@ -89,7 +89,6 @@ const getMetaplexData = async (mintAddresses: string[]) => {
connection,
metaAddresses.map((pair) => pair && pair[0])
);
console.log(results, "metaplex results");
const output = results.map((account) => {
if (account === null) {
@ -109,7 +108,6 @@ const getMetaplexData = async (mintAddresses: string[]) => {
}
});
console.log(output, "metaplex output");
return output;
};

View File

@ -2,6 +2,7 @@ import {
ChainId,
getOriginalAssetEth as getOriginalAssetEthTx,
getOriginalAssetSol as getOriginalAssetSolTx,
getOriginalAssetTerra as getOriginalAssetTerraTx,
WormholeWrappedInfo,
} from "@certusone/wormhole-sdk";
import { Connection } from "@solana/web3.js";
@ -11,8 +12,10 @@ import {
ETH_TOKEN_BRIDGE_ADDRESS,
SOLANA_HOST,
SOL_TOKEN_BRIDGE_ADDRESS,
TERRA_HOST,
TERRA_TEST_TOKEN_ADDRESS,
} from "./consts";
import { LCDClient } from "@terra-money/terra.js";
export interface StateSafeWormholeWrappedInfo {
isWrapped: boolean;
@ -57,9 +60,6 @@ export async function getOriginalAssetSol(
export async function getOriginalAssetTerra(
mintAddress: string
): Promise<StateSafeWormholeWrappedInfo> {
return {
assetAddress: TERRA_TEST_TOKEN_ADDRESS,
chainId: 3,
isWrapped: false,
};
const lcd = new LCDClient(TERRA_HOST);
return makeStateSafe(await getOriginalAssetTerraTx(lcd, mintAddress));
}