197 lines
5.4 KiB
TypeScript
197 lines
5.4 KiB
TypeScript
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: <Alert severity="success">Transaction confirmed</Alert>,
|
|
});
|
|
} catch (e) {
|
|
enqueueSnackbar(null, {
|
|
content: <Alert severity="error">{parseError(e)}</Alert>,
|
|
});
|
|
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: <Alert severity="success">Transaction confirmed</Alert>,
|
|
});
|
|
} catch (e) {
|
|
enqueueSnackbar(null, {
|
|
content: <Alert severity="error">{parseError(e)}</Alert>,
|
|
});
|
|
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: <Alert severity="success">Transaction confirmed</Alert>,
|
|
});
|
|
} catch (e) {
|
|
enqueueSnackbar(null, {
|
|
content: <Alert severity="error">{parseError(e)}</Alert>,
|
|
});
|
|
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]
|
|
);
|
|
}
|