bridge_ui: allow force create account on redeem

Change-Id: I6f01fd350dd18339ba0b5659ab43bd5c2a2a22c7
This commit is contained in:
Evan Gray 2021-10-19 17:27:13 -04:00
parent fb030b3351
commit 9bc408ca19
2 changed files with 83 additions and 9 deletions

View File

@ -9,6 +9,7 @@ import { Button, makeStyles, Tooltip, Typography } from "@material-ui/core";
import { FileCopy, OpenInNew } from "@material-ui/icons";
import { withStyles } from "@material-ui/styles";
import clsx from "clsx";
import { ReactChild } from "react";
import useCopyToClipboard from "../hooks/useCopyToClipboard";
import { ParsedTokenAccount } from "../store/transferSlice";
import { CLUSTER, getExplorerName } from "../utils/consts";
@ -57,6 +58,7 @@ export default function SmartAddress({
variant,
noGutter,
noUnderline,
extraContent,
}: {
chainId: ChainId;
parsedTokenAccount?: ParsedTokenAccount;
@ -67,6 +69,7 @@ export default function SmartAddress({
variant?: any;
noGutter?: boolean;
noUnderline?: boolean;
extraContent?: ReactChild;
}) {
const classes = useStyles();
const useableAddress = parsedTokenAccount?.mintKey || address || "";
@ -148,6 +151,7 @@ export default function SmartAddress({
{explorerButton}
{copyButton}
</div>
{extraContent ? extraContent : null}
</>
);

View File

@ -5,13 +5,15 @@ import {
hexToNativeString,
hexToUint8Array,
} from "@certusone/wormhole-sdk";
import { Typography } from "@material-ui/core";
import { Button, Typography } from "@material-ui/core";
import { Alert } from "@material-ui/lab";
import {
ASSOCIATED_TOKEN_PROGRAM_ID,
Token,
TOKEN_PROGRAM_ID,
} from "@solana/spl-token";
import { Connection, PublicKey, Transaction } from "@solana/web3.js";
import { useSnackbar } from "notistack";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useSelector } from "react-redux";
import { useSolanaWallet } from "../contexts/SolanaWalletContext";
@ -21,6 +23,7 @@ import {
selectTransferTargetAddressHex,
} from "../store/selectors";
import { SOLANA_HOST, SOL_TOKEN_BRIDGE_ADDRESS } from "../utils/consts";
import parseError from "../utils/parseError";
import { signSendAndConfirm } from "../utils/solana";
import ButtonWithLoader from "./ButtonWithLoader";
import SmartAddress from "./SmartAddress";
@ -163,6 +166,7 @@ export default function SolanaCreateAssociatedAddress({
}
export function SolanaCreateAssociatedAddressAlternate() {
const { enqueueSnackbar } = useSnackbar();
const originChain = useSelector(selectTransferOriginChain);
const originAsset = useSelector(selectTransferOriginAsset);
const addressHex = useSelector(selectTransferTargetAddressHex);
@ -215,7 +219,62 @@ export function SolanaCreateAssociatedAddressAlternate() {
base58TargetAddress
);
return targetAsset && !associatedAccountExists ? (
const solanaWallet = useSolanaWallet();
const solPK = solanaWallet?.publicKey;
const handleForceCreateClick = useCallback(() => {
if (!targetAsset || !base58TargetAddress || !solPK) return;
(async () => {
const connection = new Connection(SOLANA_HOST, "confirmed");
const mintPublicKey = new PublicKey(targetAsset);
const payerPublicKey = new PublicKey(solPK); // currently assumes the wallet is the owner
const associatedAddress = await Token.getAssociatedTokenAddress(
ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
mintPublicKey,
payerPublicKey
);
const match = associatedAddress.toString() === base58TargetAddress;
if (match) {
try {
const transaction = new Transaction().add(
await Token.createAssociatedTokenAccountInstruction(
ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
mintPublicKey,
associatedAddress,
payerPublicKey, // owner
payerPublicKey // payer
)
);
const { blockhash } = await connection.getRecentBlockhash();
transaction.recentBlockhash = blockhash;
transaction.feePayer = new PublicKey(payerPublicKey);
await signSendAndConfirm(solanaWallet, connection, transaction);
setAssociatedAccountExists(true);
enqueueSnackbar(null, {
content: (
<Alert severity="success">
Successfully created associated token account
</Alert>
),
});
} catch (e) {
enqueueSnackbar(null, {
content: <Alert severity="error">{parseError(e)}</Alert>,
});
}
}
})();
}, [
setAssociatedAccountExists,
targetAsset,
solPK,
base58TargetAddress,
solanaWallet,
enqueueSnackbar,
]);
return targetAsset ? (
<div style={{ textAlign: "center" }}>
<Typography variant="subtitle2">Recipient Address:</Typography>
<Typography component="div">
@ -223,15 +282,26 @@ export function SolanaCreateAssociatedAddressAlternate() {
chainId={CHAIN_ID_SOLANA}
address={base58TargetAddress}
variant="h6"
extraContent={
<Button
size="small"
variant="outlined"
onClick={handleForceCreateClick}
disabled={!targetAsset || !base58TargetAddress || !solPK}
>
Force Create Account
</Button>
}
/>
</Typography>
<SolanaCreateAssociatedAddress
mintAddress={targetAsset}
readableTargetAddress={base58TargetAddress}
associatedAccountExists={associatedAccountExists}
setAssociatedAccountExists={setAssociatedAccountExists}
/>
{associatedAccountExists ? null : (
<SolanaCreateAssociatedAddress
mintAddress={targetAsset}
readableTargetAddress={base58TargetAddress}
associatedAccountExists={associatedAccountExists}
setAssociatedAccountExists={setAssociatedAccountExists}
/>
)}
</div>
) : null;
}