bridge_ui: support terra source
Change-Id: Ia137e1c161851b946f86d08355fc197f43ae4fbf
This commit is contained in:
parent
69349ab5c7
commit
0b9a2e05ad
|
@ -1,6 +1,10 @@
|
||||||
//import Autocomplete from '@material-ui/lab/Autocomplete';
|
//import Autocomplete from '@material-ui/lab/Autocomplete';
|
||||||
import { CHAIN_ID_ETH, CHAIN_ID_SOLANA } from "@certusone/wormhole-sdk";
|
import {
|
||||||
import { TextField } from "@material-ui/core";
|
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 { useCallback } from "react";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import useGetSourceParsedTokens from "../../hooks/useGetSourceParsedTokenAccounts";
|
import useGetSourceParsedTokens from "../../hooks/useGetSourceParsedTokenAccounts";
|
||||||
|
@ -14,6 +18,7 @@ import {
|
||||||
} from "../../store/transferSlice";
|
} from "../../store/transferSlice";
|
||||||
import EthereumSourceTokenSelector from "./EthereumSourceTokenSelector";
|
import EthereumSourceTokenSelector from "./EthereumSourceTokenSelector";
|
||||||
import SolanaSourceTokenSelector from "./SolanaSourceTokenSelector";
|
import SolanaSourceTokenSelector from "./SolanaSourceTokenSelector";
|
||||||
|
import TerraSourceTokenSelector from "./TerraSourceTokenSelector";
|
||||||
|
|
||||||
type TokenSelectorProps = {
|
type TokenSelectorProps = {
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
|
@ -37,29 +42,37 @@ export const TokenSelector = (props: TokenSelectorProps) => {
|
||||||
|
|
||||||
const maps = useGetSourceParsedTokens();
|
const maps = useGetSourceParsedTokens();
|
||||||
|
|
||||||
const content =
|
//This is only for errors so bad that we shouldn't even mount the component
|
||||||
lookupChain === CHAIN_ID_SOLANA ? (
|
const fatalError = maps?.tokenAccounts?.error;
|
||||||
<SolanaSourceTokenSelector
|
|
||||||
value={sourceParsedTokenAccount || null}
|
const content = fatalError ? (
|
||||||
onChange={handleSolanaOnChange}
|
<Typography>{fatalError}</Typography>
|
||||||
accounts={maps?.tokenAccounts?.data || []}
|
) : lookupChain === CHAIN_ID_SOLANA ? (
|
||||||
solanaTokenMap={maps?.tokenMap}
|
<SolanaSourceTokenSelector
|
||||||
metaplexData={maps?.metaplex}
|
value={sourceParsedTokenAccount || null}
|
||||||
/>
|
onChange={handleSolanaOnChange}
|
||||||
) : lookupChain === CHAIN_ID_ETH ? (
|
accounts={maps?.tokenAccounts?.data || []}
|
||||||
<EthereumSourceTokenSelector
|
solanaTokenMap={maps?.tokenMap}
|
||||||
value={sourceParsedTokenAccount || null}
|
metaplexData={maps?.metaplex}
|
||||||
onChange={handleSolanaOnChange}
|
/>
|
||||||
/>
|
) : lookupChain === CHAIN_ID_ETH ? (
|
||||||
) : (
|
<EthereumSourceTokenSelector
|
||||||
<TextField
|
value={sourceParsedTokenAccount || null}
|
||||||
placeholder="Asset"
|
onChange={handleSolanaOnChange}
|
||||||
fullWidth
|
/>
|
||||||
value={"hardcoded"}
|
) : lookupChain === CHAIN_ID_TERRA ? (
|
||||||
onChange={() => {}}
|
<TerraSourceTokenSelector
|
||||||
disabled={true}
|
value={sourceParsedTokenAccount || null}
|
||||||
/>
|
onChange={handleSolanaOnChange}
|
||||||
);
|
/>
|
||||||
|
) : (
|
||||||
|
<TextField
|
||||||
|
placeholder="Asset"
|
||||||
|
fullWidth
|
||||||
|
value={"Not Implemented"}
|
||||||
|
disabled={true}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
return <div>{content}</div>;
|
return <div>{content}</div>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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>;
|
||||||
|
}
|
|
@ -89,7 +89,6 @@ const getMetaplexData = async (mintAddresses: string[]) => {
|
||||||
connection,
|
connection,
|
||||||
metaAddresses.map((pair) => pair && pair[0])
|
metaAddresses.map((pair) => pair && pair[0])
|
||||||
);
|
);
|
||||||
console.log(results, "metaplex results");
|
|
||||||
|
|
||||||
const output = results.map((account) => {
|
const output = results.map((account) => {
|
||||||
if (account === null) {
|
if (account === null) {
|
||||||
|
@ -109,7 +108,6 @@ const getMetaplexData = async (mintAddresses: string[]) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(output, "metaplex output");
|
|
||||||
return output;
|
return output;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import {
|
||||||
ChainId,
|
ChainId,
|
||||||
getOriginalAssetEth as getOriginalAssetEthTx,
|
getOriginalAssetEth as getOriginalAssetEthTx,
|
||||||
getOriginalAssetSol as getOriginalAssetSolTx,
|
getOriginalAssetSol as getOriginalAssetSolTx,
|
||||||
|
getOriginalAssetTerra as getOriginalAssetTerraTx,
|
||||||
WormholeWrappedInfo,
|
WormholeWrappedInfo,
|
||||||
} from "@certusone/wormhole-sdk";
|
} from "@certusone/wormhole-sdk";
|
||||||
import { Connection } from "@solana/web3.js";
|
import { Connection } from "@solana/web3.js";
|
||||||
|
@ -11,8 +12,10 @@ import {
|
||||||
ETH_TOKEN_BRIDGE_ADDRESS,
|
ETH_TOKEN_BRIDGE_ADDRESS,
|
||||||
SOLANA_HOST,
|
SOLANA_HOST,
|
||||||
SOL_TOKEN_BRIDGE_ADDRESS,
|
SOL_TOKEN_BRIDGE_ADDRESS,
|
||||||
|
TERRA_HOST,
|
||||||
TERRA_TEST_TOKEN_ADDRESS,
|
TERRA_TEST_TOKEN_ADDRESS,
|
||||||
} from "./consts";
|
} from "./consts";
|
||||||
|
import { LCDClient } from "@terra-money/terra.js";
|
||||||
|
|
||||||
export interface StateSafeWormholeWrappedInfo {
|
export interface StateSafeWormholeWrappedInfo {
|
||||||
isWrapped: boolean;
|
isWrapped: boolean;
|
||||||
|
@ -57,9 +60,6 @@ export async function getOriginalAssetSol(
|
||||||
export async function getOriginalAssetTerra(
|
export async function getOriginalAssetTerra(
|
||||||
mintAddress: string
|
mintAddress: string
|
||||||
): Promise<StateSafeWormholeWrappedInfo> {
|
): Promise<StateSafeWormholeWrappedInfo> {
|
||||||
return {
|
const lcd = new LCDClient(TERRA_HOST);
|
||||||
assetAddress: TERRA_TEST_TOKEN_ADDRESS,
|
return makeStateSafe(await getOriginalAssetTerraTx(lcd, mintAddress));
|
||||||
chainId: 3,
|
|
||||||
isWrapped: false,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue