import { ChainId, CHAIN_ID_SOLANA, CHAIN_ID_TERRA, createWrappedOnEth, createWrappedOnSolana, createWrappedOnTerra, postVaaSolana, } from "@certusone/wormhole-sdk"; import { WalletContextState } from "@solana/wallet-adapter-react"; import { Connection } from "@solana/web3.js"; import { ConnectedWallet, useConnectedWallet, } from "@terra-money/wallet-provider"; import { Signer } from "ethers"; import { useSnackbar } from "notistack"; import { useCallback, useMemo } from "react"; import { useDispatch, useSelector } from "react-redux"; import { useEthereumProvider } from "../contexts/EthereumProviderContext"; import { useSolanaWallet } from "../contexts/SolanaWalletContext"; import useAttestSignedVAA from "./useAttestSignedVAA"; import { setCreateTx, setIsCreating } from "../store/attestSlice"; import { selectAttestIsCreating, selectAttestTargetChain, } from "../store/selectors"; import { getTokenBridgeAddressForChain, SOLANA_HOST, SOL_BRIDGE_ADDRESS, SOL_TOKEN_BRIDGE_ADDRESS, TERRA_TOKEN_BRIDGE_ADDRESS, } from "../utils/consts"; import { isEVMChain } from "../utils/ethereum"; import parseError from "../utils/parseError"; import { signSendAndConfirm } from "../utils/solana"; import { Alert } from "@material-ui/lab"; import { postWithFees } from "../utils/terra"; async function evm( dispatch: any, enqueueSnackbar: any, signer: Signer, signedVAA: Uint8Array, chainId: ChainId ) { dispatch(setIsCreating(true)); try { const receipt = await createWrappedOnEth( getTokenBridgeAddressForChain(chainId), signer, signedVAA ); dispatch( setCreateTx({ id: receipt.transactionHash, block: receipt.blockNumber }) ); enqueueSnackbar(null, { content: Transaction confirmed, }); } catch (e) { enqueueSnackbar(null, { content: {parseError(e)}, }); dispatch(setIsCreating(false)); } } async function solana( dispatch: any, enqueueSnackbar: any, wallet: WalletContextState, payerAddress: string, // TODO: we may not need this since we have wallet signedVAA: Uint8Array ) { dispatch(setIsCreating(true)); try { if (!wallet.signTransaction) { throw new Error("wallet.signTransaction is undefined"); } const connection = new Connection(SOLANA_HOST, "confirmed"); await postVaaSolana( connection, wallet.signTransaction, SOL_BRIDGE_ADDRESS, payerAddress, Buffer.from(signedVAA) ); const transaction = await createWrappedOnSolana( connection, SOL_BRIDGE_ADDRESS, SOL_TOKEN_BRIDGE_ADDRESS, payerAddress, signedVAA ); const txid = await signSendAndConfirm(wallet, connection, transaction); // TODO: didn't want to make an info call we didn't need, can we get the block without it by modifying the above call? dispatch(setCreateTx({ id: txid, block: 1 })); enqueueSnackbar(null, { content: Transaction confirmed, }); } catch (e) { enqueueSnackbar(null, { content: {parseError(e)}, }); dispatch(setIsCreating(false)); } } async function terra( dispatch: any, enqueueSnackbar: any, wallet: ConnectedWallet, signedVAA: Uint8Array ) { dispatch(setIsCreating(true)); try { const msg = await createWrappedOnTerra( TERRA_TOKEN_BRIDGE_ADDRESS, wallet.terraAddress, signedVAA ); const result = await postWithFees( wallet, [msg], "Wormhole - Create Wrapped" ); dispatch( setCreateTx({ id: result.result.txhash, block: result.result.height }) ); enqueueSnackbar(null, { content: Transaction confirmed, }); } catch (e) { enqueueSnackbar(null, { content: {parseError(e)}, }); dispatch(setIsCreating(false)); } } export function useHandleCreateWrapped() { const dispatch = useDispatch(); const { enqueueSnackbar } = useSnackbar(); const targetChain = useSelector(selectAttestTargetChain); const solanaWallet = useSolanaWallet(); const solPK = solanaWallet?.publicKey; const signedVAA = useAttestSignedVAA(); const isCreating = useSelector(selectAttestIsCreating); const { signer } = useEthereumProvider(); const terraWallet = useConnectedWallet(); const handleCreateClick = useCallback(() => { if (isEVMChain(targetChain) && !!signer && !!signedVAA) { evm(dispatch, enqueueSnackbar, signer, signedVAA, targetChain); } else if ( targetChain === CHAIN_ID_SOLANA && !!solanaWallet && !!solPK && !!signedVAA ) { solana( dispatch, enqueueSnackbar, solanaWallet, solPK.toString(), signedVAA ); } else if (targetChain === CHAIN_ID_TERRA && !!terraWallet && !!signedVAA) { terra(dispatch, enqueueSnackbar, terraWallet, signedVAA); } else { // enqueueSnackbar( // "Creating wrapped tokens on this chain is not yet supported", // { // variant: "error", // } // ); } }, [ dispatch, enqueueSnackbar, targetChain, solanaWallet, solPK, terraWallet, signedVAA, signer, ]); return useMemo( () => ({ handleClick: handleCreateClick, disabled: !!isCreating, showLoader: !!isCreating, }), [handleCreateClick, isCreating] ); }