111 lines
3.4 KiB
TypeScript
111 lines
3.4 KiB
TypeScript
import {
|
|
CHAIN_ID_ETH,
|
|
CHAIN_ID_SOLANA,
|
|
CHAIN_ID_TERRA,
|
|
} from "@certusone/wormhole-sdk";
|
|
import { arrayify, zeroPad } from "@ethersproject/bytes";
|
|
import {
|
|
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
Token,
|
|
TOKEN_PROGRAM_ID,
|
|
} from "@solana/spl-token";
|
|
import { PublicKey } from "@solana/web3.js";
|
|
import { useConnectedWallet } from "@terra-money/wallet-provider";
|
|
import { useEffect } from "react";
|
|
import { useDispatch, useSelector } from "react-redux";
|
|
import { useEthereumProvider } from "../contexts/EthereumProviderContext";
|
|
import { useSolanaWallet } from "../contexts/SolanaWalletContext";
|
|
import {
|
|
selectTransferTargetAsset,
|
|
selectTransferTargetChain,
|
|
selectTransferTargetParsedTokenAccount,
|
|
} from "../store/selectors";
|
|
import { setTargetAddressHex } from "../store/transferSlice";
|
|
import { uint8ArrayToHex } from "../utils/array";
|
|
import bech32 from "bech32";
|
|
|
|
function useSyncTargetAddress(shouldFire: boolean) {
|
|
const dispatch = useDispatch();
|
|
const targetChain = useSelector(selectTransferTargetChain);
|
|
const { signerAddress } = useEthereumProvider();
|
|
const solanaWallet = useSolanaWallet();
|
|
const solPK = solanaWallet?.publicKey;
|
|
const targetAsset = useSelector(selectTransferTargetAsset);
|
|
const targetParsedTokenAccount = useSelector(
|
|
selectTransferTargetParsedTokenAccount
|
|
);
|
|
const targetTokenAccountPublicKey = targetParsedTokenAccount?.publicKey;
|
|
const terraWallet = useConnectedWallet();
|
|
useEffect(() => {
|
|
if (shouldFire) {
|
|
let cancelled = false;
|
|
if (targetChain === CHAIN_ID_ETH && signerAddress) {
|
|
dispatch(
|
|
setTargetAddressHex(
|
|
uint8ArrayToHex(zeroPad(arrayify(signerAddress), 32))
|
|
)
|
|
);
|
|
}
|
|
// TODO: have the user explicitly select an account on solana
|
|
else if (targetChain === CHAIN_ID_SOLANA && targetTokenAccountPublicKey) {
|
|
// use the target's TokenAccount if it exists
|
|
dispatch(
|
|
setTargetAddressHex(
|
|
uint8ArrayToHex(
|
|
zeroPad(new PublicKey(targetTokenAccountPublicKey).toBytes(), 32)
|
|
)
|
|
)
|
|
);
|
|
} else if (targetChain === CHAIN_ID_SOLANA && solPK && targetAsset) {
|
|
// otherwise, use the associated token account (which we create in the case it doesn't exist)
|
|
(async () => {
|
|
const associatedTokenAccount = await Token.getAssociatedTokenAddress(
|
|
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
TOKEN_PROGRAM_ID,
|
|
new PublicKey(targetAsset),
|
|
solPK
|
|
);
|
|
if (!cancelled) {
|
|
dispatch(
|
|
setTargetAddressHex(
|
|
uint8ArrayToHex(zeroPad(associatedTokenAccount.toBytes(), 32))
|
|
)
|
|
);
|
|
}
|
|
})();
|
|
} else if (
|
|
targetChain === CHAIN_ID_TERRA &&
|
|
terraWallet &&
|
|
terraWallet.walletAddress
|
|
) {
|
|
dispatch(
|
|
setTargetAddressHex(
|
|
uint8ArrayToHex(
|
|
zeroPad(
|
|
new Uint8Array(bech32.decode(terraWallet.walletAddress).words),
|
|
32
|
|
)
|
|
)
|
|
)
|
|
);
|
|
} else {
|
|
dispatch(setTargetAddressHex(undefined));
|
|
}
|
|
return () => {
|
|
cancelled = true;
|
|
};
|
|
}
|
|
}, [
|
|
dispatch,
|
|
shouldFire,
|
|
targetChain,
|
|
signerAddress,
|
|
solPK,
|
|
targetAsset,
|
|
targetTokenAccountPublicKey,
|
|
terraWallet,
|
|
]);
|
|
}
|
|
|
|
export default useSyncTargetAddress;
|