bridge_ui: xdefi and leap wallet support (#866)
* bridge_ui: xdefi and leap wallet support * bridge_ui: wallet connect feature refactor * bridge_ui: terra native balance fix * bridge_ui: bumped max polygon confirmations to 512
This commit is contained in:
parent
2ea41b8176
commit
d4b7dbf98b
|
@ -0,0 +1,126 @@
|
|||
import {
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
IconButton,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
makeStyles,
|
||||
} from "@material-ui/core";
|
||||
import CloseIcon from "@material-ui/icons/Close";
|
||||
import { ConnectType, useWallet } from "@terra-money/wallet-provider";
|
||||
import { useCallback } from "react";
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
flexTitle: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
"& > div": {
|
||||
flexGrow: 1,
|
||||
marginRight: theme.spacing(4),
|
||||
},
|
||||
"& > button": {
|
||||
marginRight: theme.spacing(-1),
|
||||
},
|
||||
},
|
||||
icon: {
|
||||
height: 24,
|
||||
width: 24,
|
||||
},
|
||||
}));
|
||||
|
||||
const WalletOptions = ({
|
||||
type,
|
||||
identifier,
|
||||
connect,
|
||||
onClose,
|
||||
icon,
|
||||
name,
|
||||
}: {
|
||||
type: ConnectType;
|
||||
identifier: string;
|
||||
connect: (
|
||||
type: ConnectType | undefined,
|
||||
identifier: string | undefined
|
||||
) => void;
|
||||
onClose: () => void;
|
||||
icon: string;
|
||||
name: string;
|
||||
}) => {
|
||||
const classes = useStyles();
|
||||
|
||||
const handleClick = useCallback(() => {
|
||||
connect(type, identifier);
|
||||
onClose();
|
||||
}, [connect, onClose, type, identifier]);
|
||||
return (
|
||||
<ListItem button onClick={handleClick}>
|
||||
<ListItemIcon>
|
||||
<img src={icon} alt={name} className={classes.icon} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>{name}</ListItemText>
|
||||
</ListItem>
|
||||
);
|
||||
};
|
||||
|
||||
const TerraConnectWalletDialog = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
}: {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
}) => {
|
||||
const { availableConnections, availableInstallations, connect } = useWallet();
|
||||
const classes = useStyles();
|
||||
|
||||
const filteredConnections = availableConnections
|
||||
.filter(({ type }) => type !== ConnectType.READONLY)
|
||||
.map(({ type, name, icon, identifier = "" }) => (
|
||||
<WalletOptions
|
||||
type={type}
|
||||
identifier={identifier}
|
||||
connect={connect}
|
||||
onClose={onClose}
|
||||
icon={icon}
|
||||
name={name}
|
||||
key={"connection-" + type + identifier}
|
||||
/>
|
||||
));
|
||||
|
||||
const filteredInstallations = availableInstallations
|
||||
.filter(({ type }) => type !== ConnectType.READONLY)
|
||||
.map(({ type, name, icon, url, identifier = "" }) => (
|
||||
<ListItem
|
||||
button
|
||||
component="a"
|
||||
key={"install-" + type + identifier}
|
||||
href={url}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<ListItemIcon>
|
||||
<img src={icon} alt={name} className={classes.icon} />
|
||||
</ListItemIcon>
|
||||
<ListItemText>{"Install " + name}</ListItemText>
|
||||
</ListItem>
|
||||
));
|
||||
return (
|
||||
<Dialog open={isOpen} onClose={onClose}>
|
||||
<DialogTitle>
|
||||
<div className={classes.flexTitle}>
|
||||
<div>Select your wallet</div>
|
||||
<IconButton onClick={onClose}>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
</DialogTitle>
|
||||
<List>
|
||||
{filteredConnections}
|
||||
{filteredInstallations}
|
||||
</List>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default TerraConnectWalletDialog;
|
|
@ -1,29 +1,31 @@
|
|||
import { Typography } from "@material-ui/core";
|
||||
import { useTerraWallet } from "../contexts/TerraWalletContext";
|
||||
import { useConnectedWallet, useWallet } from "@terra-money/wallet-provider";
|
||||
import { useCallback, useState } from "react";
|
||||
import TerraConnectWalletDialog from "./TerraConnectWalletDialog";
|
||||
import ToggleConnectedButton from "./ToggleConnectedButton";
|
||||
|
||||
const TerraWalletKey = () => {
|
||||
const { connect, disconnect, connected, wallet, providerError } =
|
||||
useTerraWallet();
|
||||
const pk =
|
||||
(wallet &&
|
||||
wallet.wallets &&
|
||||
wallet.wallets.length > 0 &&
|
||||
wallet.wallets[0].terraAddress) ||
|
||||
"";
|
||||
const wallet = useWallet();
|
||||
const connectedWallet = useConnectedWallet();
|
||||
|
||||
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
||||
|
||||
const connect = useCallback(() => {
|
||||
setIsDialogOpen(true);
|
||||
}, [setIsDialogOpen]);
|
||||
|
||||
const closeDialog = useCallback(() => {
|
||||
setIsDialogOpen(false);
|
||||
}, [setIsDialogOpen]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ToggleConnectedButton
|
||||
connect={connect}
|
||||
disconnect={disconnect}
|
||||
connected={connected}
|
||||
pk={pk}
|
||||
disconnect={wallet.disconnect}
|
||||
connected={!!connectedWallet}
|
||||
pk={connectedWallet?.terraAddress || ""}
|
||||
/>
|
||||
{providerError ? (
|
||||
<Typography variant="body2" color="error">
|
||||
{providerError}
|
||||
</Typography>
|
||||
) : null}
|
||||
<TerraConnectWalletDialog isOpen={isDialogOpen} onClose={closeDialog} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -72,7 +72,7 @@ export default function TransactionProgress({
|
|||
tx && tx.block && currentBlock ? currentBlock - tx.block : undefined;
|
||||
const expectedBlocks =
|
||||
chainId === CHAIN_ID_POLYGON
|
||||
? 256 // minimum confirmations enforced by guardians
|
||||
? 512 // minimum confirmations enforced by guardians
|
||||
: chainId === CHAIN_ID_SOLANA
|
||||
? 32
|
||||
: isEVMChain(chainId)
|
||||
|
|
|
@ -1,102 +1,24 @@
|
|||
import {
|
||||
NetworkInfo,
|
||||
Wallet,
|
||||
WalletProvider,
|
||||
useWallet,
|
||||
ConnectType,
|
||||
} from "@terra-money/wallet-provider";
|
||||
import React, {
|
||||
ReactChildren,
|
||||
useCallback,
|
||||
useContext,
|
||||
useMemo,
|
||||
useState,
|
||||
} from "react";
|
||||
import { TERRA_HOST } from "../utils/consts";
|
||||
import { NetworkInfo, WalletProvider } from "@terra-money/wallet-provider";
|
||||
import { ReactChildren } from "react";
|
||||
import { CLUSTER } from "../utils/consts";
|
||||
|
||||
const mainnet = {
|
||||
const mainnet: NetworkInfo = {
|
||||
name: "mainnet",
|
||||
chainID: "columbus-4",
|
||||
chainID: "columbus-5",
|
||||
lcd: "https://lcd.terra.dev",
|
||||
};
|
||||
|
||||
const localnet = {
|
||||
name: "localnet",
|
||||
chainID: "localnet",
|
||||
lcd: TERRA_HOST.URL,
|
||||
const testnet: NetworkInfo = {
|
||||
name: "testnet",
|
||||
chainID: "bombay-12",
|
||||
lcd: "https://bombay-lcd.terra.dev",
|
||||
};
|
||||
|
||||
const walletConnectChainIds: Record<number, NetworkInfo> = {
|
||||
0: localnet,
|
||||
0: testnet,
|
||||
1: mainnet,
|
||||
};
|
||||
|
||||
interface ITerraWalletContext {
|
||||
connect(): void;
|
||||
disconnect(): void;
|
||||
connected: boolean;
|
||||
wallet: any;
|
||||
providerError: string | null;
|
||||
}
|
||||
|
||||
const TerraWalletContext = React.createContext<ITerraWalletContext>({
|
||||
connect: () => {},
|
||||
disconnect: () => {},
|
||||
connected: false,
|
||||
wallet: null,
|
||||
providerError: null,
|
||||
});
|
||||
|
||||
export const TerraWalletWrapper = ({
|
||||
children,
|
||||
}: {
|
||||
children: ReactChildren;
|
||||
}) => {
|
||||
// TODO: Use wallet instead of useConnectedWallet.
|
||||
const terraWallet = useWallet();
|
||||
const [, setWallet] = useState<Wallet | undefined>(undefined);
|
||||
const [connected, setConnected] = useState(false);
|
||||
const [providerError, setProviderError] = useState<string | null>(null);
|
||||
|
||||
const connect = useCallback(() => {
|
||||
if (terraWallet) {
|
||||
// TODO: Support other connect types
|
||||
if (terraWallet.availableConnectTypes.includes(ConnectType.EXTENSION)) {
|
||||
terraWallet.connect(ConnectType.EXTENSION);
|
||||
setConnected(true);
|
||||
setProviderError(null);
|
||||
} else {
|
||||
setConnected(false);
|
||||
setProviderError("Please install the Terra Station Extension");
|
||||
}
|
||||
setWallet(terraWallet);
|
||||
}
|
||||
}, [terraWallet]);
|
||||
|
||||
const disconnect = useCallback(() => {
|
||||
setConnected(false);
|
||||
setWallet(undefined);
|
||||
setProviderError(null);
|
||||
}, []);
|
||||
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
connect,
|
||||
disconnect,
|
||||
connected,
|
||||
wallet: terraWallet,
|
||||
providerError,
|
||||
}),
|
||||
[connect, disconnect, connected, terraWallet, providerError]
|
||||
);
|
||||
|
||||
return (
|
||||
<TerraWalletContext.Provider value={contextValue}>
|
||||
{children}
|
||||
</TerraWalletContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const TerraWalletProvider = ({
|
||||
children,
|
||||
}: {
|
||||
|
@ -104,14 +26,10 @@ export const TerraWalletProvider = ({
|
|||
}) => {
|
||||
return (
|
||||
<WalletProvider
|
||||
defaultNetwork={localnet}
|
||||
defaultNetwork={CLUSTER === "testnet" ? testnet : mainnet}
|
||||
walletConnectChainIds={walletConnectChainIds}
|
||||
>
|
||||
<TerraWalletWrapper>{children}</TerraWalletWrapper>
|
||||
{children}
|
||||
</WalletProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useTerraWallet = () => {
|
||||
return useContext(TerraWalletContext);
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@ import {
|
|||
CHAIN_ID_SOLANA,
|
||||
CHAIN_ID_TERRA,
|
||||
isEVMChain,
|
||||
isNativeDenom,
|
||||
TokenImplementation__factory,
|
||||
} from "@certusone/wormhole-sdk";
|
||||
import { Connection, PublicKey } from "@solana/web3.js";
|
||||
|
@ -18,6 +19,7 @@ import {
|
|||
} from "../store/selectors";
|
||||
import { setTargetParsedTokenAccount } from "../store/transferSlice";
|
||||
import { getEvmChainId, SOLANA_HOST, TERRA_HOST } from "../utils/consts";
|
||||
import { NATIVE_TERRA_DECIMALS } from "../utils/terra";
|
||||
import { createParsedTokenAccount } from "./useGetSourceParsedTokenAccounts";
|
||||
import useMetadata from "./useMetadata";
|
||||
|
||||
|
@ -56,37 +58,72 @@ function useGetTargetParsedTokenAccounts() {
|
|||
|
||||
if (targetChain === CHAIN_ID_TERRA && terraWallet) {
|
||||
const lcd = new LCDClient(TERRA_HOST);
|
||||
lcd.wasm
|
||||
.contractQuery(targetAsset, {
|
||||
token_info: {},
|
||||
})
|
||||
.then((info: any) =>
|
||||
lcd.wasm
|
||||
.contractQuery(targetAsset, {
|
||||
balance: {
|
||||
address: terraWallet.walletAddress,
|
||||
},
|
||||
})
|
||||
.then((balance: any) => {
|
||||
if (balance && info) {
|
||||
dispatch(
|
||||
setTargetParsedTokenAccount(
|
||||
createParsedTokenAccount(
|
||||
"",
|
||||
"",
|
||||
balance.balance.toString(),
|
||||
info.decimals,
|
||||
Number(formatUnits(balance.balance, info.decimals)),
|
||||
formatUnits(balance.balance, info.decimals),
|
||||
symbol,
|
||||
tokenName,
|
||||
logo
|
||||
)
|
||||
if (isNativeDenom(targetAsset)) {
|
||||
lcd.bank
|
||||
.balance(terraWallet.walletAddress)
|
||||
.then(([coins]) => {
|
||||
const balance = coins.get(targetAsset)?.amount?.toString();
|
||||
if (balance && !cancelled) {
|
||||
dispatch(
|
||||
setTargetParsedTokenAccount(
|
||||
createParsedTokenAccount(
|
||||
"",
|
||||
"",
|
||||
balance,
|
||||
NATIVE_TERRA_DECIMALS,
|
||||
Number(formatUnits(balance, NATIVE_TERRA_DECIMALS)),
|
||||
formatUnits(balance, NATIVE_TERRA_DECIMALS),
|
||||
symbol,
|
||||
tokenName,
|
||||
logo
|
||||
)
|
||||
);
|
||||
}
|
||||
})
|
||||
);
|
||||
)
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
if (!cancelled) {
|
||||
// TODO: error state
|
||||
}
|
||||
});
|
||||
} else {
|
||||
lcd.wasm
|
||||
.contractQuery(targetAsset, {
|
||||
token_info: {},
|
||||
})
|
||||
.then((info: any) =>
|
||||
lcd.wasm
|
||||
.contractQuery(targetAsset, {
|
||||
balance: {
|
||||
address: terraWallet.walletAddress,
|
||||
},
|
||||
})
|
||||
.then((balance: any) => {
|
||||
if (balance && info && !cancelled) {
|
||||
dispatch(
|
||||
setTargetParsedTokenAccount(
|
||||
createParsedTokenAccount(
|
||||
"",
|
||||
"",
|
||||
balance.balance.toString(),
|
||||
info.decimals,
|
||||
Number(formatUnits(balance.balance, info.decimals)),
|
||||
formatUnits(balance.balance, info.decimals),
|
||||
symbol,
|
||||
tokenName,
|
||||
logo
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
})
|
||||
)
|
||||
.catch(() => {
|
||||
if (!cancelled) {
|
||||
// TODO: error state
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (targetChain === CHAIN_ID_SOLANA && solPK) {
|
||||
let mint;
|
||||
|
|
Loading…
Reference in New Issue