all the ui components for lp_ui
Change-Id: I60b6f95f480c28f245e87f35fd7ae4ebdced535d
This commit is contained in:
parent
8a90b50aeb
commit
1230ea6fa3
|
@ -0,0 +1,72 @@
|
|||
import {
|
||||
Button,
|
||||
CircularProgress,
|
||||
makeStyles,
|
||||
Typography,
|
||||
} from "@material-ui/core";
|
||||
import { ReactChild } from "react";
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
position: "relative",
|
||||
},
|
||||
button: {
|
||||
marginTop: theme.spacing(2),
|
||||
textTransform: "none",
|
||||
width: "100%",
|
||||
},
|
||||
loader: {
|
||||
position: "absolute",
|
||||
bottom: 0,
|
||||
left: "50%",
|
||||
marginLeft: -12,
|
||||
marginBottom: 6,
|
||||
},
|
||||
error: {
|
||||
marginTop: theme.spacing(1),
|
||||
textAlign: "center",
|
||||
},
|
||||
}));
|
||||
|
||||
export default function ButtonWithLoader({
|
||||
disabled,
|
||||
onClick,
|
||||
showLoader,
|
||||
error,
|
||||
children,
|
||||
}: {
|
||||
disabled?: boolean;
|
||||
onClick: () => void;
|
||||
showLoader?: boolean;
|
||||
error?: string;
|
||||
children: ReactChild;
|
||||
}) {
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<>
|
||||
<div className={classes.root}>
|
||||
<Button
|
||||
color="primary"
|
||||
variant="contained"
|
||||
className={classes.button}
|
||||
disabled={disabled}
|
||||
onClick={onClick}
|
||||
>
|
||||
{children}
|
||||
</Button>
|
||||
{showLoader ? (
|
||||
<CircularProgress
|
||||
size={24}
|
||||
color="inherit"
|
||||
className={classes.loader}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
{error ? (
|
||||
<Typography color="error" className={classes.error}>
|
||||
{error}
|
||||
</Typography>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
import { Typography } from "@material-ui/core";
|
||||
import React from "react";
|
||||
|
||||
export default class ErrorBoundary extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { hasError: false };
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(error) {
|
||||
return { hasError: true };
|
||||
}
|
||||
|
||||
componentDidCatch(error, errorInfo) {
|
||||
console.error(error, errorInfo);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
return (
|
||||
<Typography variant="h5" style={{ textAlign: "center", marginTop: 24 }}>
|
||||
"An unexpected error has occurred. Please refresh the page."
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
import { ChainId, CHAIN_ID_SOLANA } from "@certusone/wormhole-sdk";
|
||||
import { Typography } from "@material-ui/core";
|
||||
import {
|
||||
ASSOCIATED_TOKEN_PROGRAM_ID,
|
||||
Token,
|
||||
TOKEN_PROGRAM_ID,
|
||||
} from "@solana/spl-token";
|
||||
import { Connection, PublicKey, Transaction } from "@solana/web3.js";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useSolanaWallet } from "../contexts/SolanaWalletContext";
|
||||
import { SOLANA_URL } from "../utils/consts";
|
||||
import { signSendAndConfirm } from "../utils/solana";
|
||||
import ButtonWithLoader from "./ButtonWithLoader";
|
||||
|
||||
export function useAssociatedAccountExistsState(
|
||||
mintAddress: string | null | undefined,
|
||||
readableTargetAddress: string | undefined
|
||||
) {
|
||||
const [associatedAccountExists, setAssociatedAccountExists] = useState(true); // for now, assume it exists until we confirm it doesn't
|
||||
const solanaWallet = useSolanaWallet();
|
||||
const solPK = solanaWallet?.publicKey;
|
||||
useEffect(() => {
|
||||
setAssociatedAccountExists(true);
|
||||
if (!mintAddress || !readableTargetAddress || !solPK) return;
|
||||
let cancelled = false;
|
||||
(async () => {
|
||||
const connection = new Connection(SOLANA_URL, "confirmed");
|
||||
const mintPublicKey = new PublicKey(mintAddress);
|
||||
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() === readableTargetAddress;
|
||||
if (match) {
|
||||
const associatedAddressInfo = await connection.getAccountInfo(
|
||||
associatedAddress
|
||||
);
|
||||
if (!associatedAddressInfo) {
|
||||
if (!cancelled) {
|
||||
setAssociatedAccountExists(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [mintAddress, readableTargetAddress, solPK]);
|
||||
return useMemo(
|
||||
() => ({ associatedAccountExists, setAssociatedAccountExists }),
|
||||
[associatedAccountExists]
|
||||
);
|
||||
}
|
||||
|
||||
export default function SolanaCreateAssociatedAddress({
|
||||
mintAddress,
|
||||
readableTargetAddress,
|
||||
associatedAccountExists,
|
||||
setAssociatedAccountExists,
|
||||
}: {
|
||||
mintAddress: string | undefined;
|
||||
readableTargetAddress: string | undefined;
|
||||
associatedAccountExists: boolean;
|
||||
setAssociatedAccountExists: (associatedAccountExists: boolean) => void;
|
||||
}) {
|
||||
const [isCreating, setIsCreating] = useState(false);
|
||||
const solanaWallet = useSolanaWallet();
|
||||
const solPK = solanaWallet?.publicKey;
|
||||
const handleClick = useCallback(() => {
|
||||
if (
|
||||
associatedAccountExists ||
|
||||
!mintAddress ||
|
||||
!readableTargetAddress ||
|
||||
!solPK
|
||||
)
|
||||
return;
|
||||
(async () => {
|
||||
try {
|
||||
const connection = new Connection(SOLANA_URL, "confirmed");
|
||||
const mintPublicKey = new PublicKey(mintAddress);
|
||||
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() === readableTargetAddress;
|
||||
if (match) {
|
||||
const associatedAddressInfo = await connection.getAccountInfo(
|
||||
associatedAddress
|
||||
);
|
||||
if (!associatedAddressInfo) {
|
||||
setIsCreating(true);
|
||||
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);
|
||||
setIsCreating(false);
|
||||
setAssociatedAccountExists(true);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("cannot create specified spl token account");
|
||||
console.error(e);
|
||||
}
|
||||
})();
|
||||
}, [
|
||||
associatedAccountExists,
|
||||
setAssociatedAccountExists,
|
||||
mintAddress,
|
||||
solPK,
|
||||
readableTargetAddress,
|
||||
solanaWallet,
|
||||
]);
|
||||
if (associatedAccountExists) return null;
|
||||
return (
|
||||
<>
|
||||
<Typography color="error" variant="body2">
|
||||
This associated token account doesn't exist.
|
||||
</Typography>
|
||||
<ButtonWithLoader
|
||||
disabled={
|
||||
!mintAddress || !readableTargetAddress || !solPK || isCreating
|
||||
}
|
||||
onClick={handleClick}
|
||||
showLoader={isCreating}
|
||||
>
|
||||
Create Associated Token Account
|
||||
</ButtonWithLoader>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -2,17 +2,20 @@ import { CssBaseline } from "@material-ui/core";
|
|||
import { ThemeProvider } from "@material-ui/core/styles";
|
||||
import ReactDOM from "react-dom";
|
||||
import App from "./App";
|
||||
import ErrorBoundary from "./components/ErrorBoundary";
|
||||
import { LoggerProvider } from "./contexts/Logger";
|
||||
import { SolanaWalletProvider } from "./contexts/SolanaWalletContext";
|
||||
import { theme } from "./muiTheme";
|
||||
ReactDOM.render(
|
||||
<ThemeProvider theme={theme}>
|
||||
<CssBaseline />
|
||||
<SolanaWalletProvider>
|
||||
<LoggerProvider>
|
||||
<App />
|
||||
</LoggerProvider>
|
||||
</SolanaWalletProvider>
|
||||
</ThemeProvider>,
|
||||
<ErrorBoundary>
|
||||
<ThemeProvider theme={theme}>
|
||||
<CssBaseline />
|
||||
<SolanaWalletProvider>
|
||||
<LoggerProvider>
|
||||
<App />
|
||||
</LoggerProvider>
|
||||
</SolanaWalletProvider>
|
||||
</ThemeProvider>
|
||||
</ErrorBoundary>,
|
||||
document.getElementById("root")
|
||||
);
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
Paper,
|
||||
TextField,
|
||||
Button,
|
||||
Divider,
|
||||
} from "@material-ui/core";
|
||||
//import { pool_address } from "@certusone/wormhole-sdk/lib/solana/migration/wormhole_migration";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
|
@ -24,6 +25,19 @@ import getPoolAddress from "@certusone/wormhole-sdk/lib/migration/poolAddress";
|
|||
import getFromCustodyAddress from "@certusone/wormhole-sdk/lib/migration/fromCustodyAddress";
|
||||
import getToCustodyAddress from "@certusone/wormhole-sdk/lib/migration/toCustodyAddress";
|
||||
import getShareMintAddress from "@certusone/wormhole-sdk/lib/migration/shareMintAddress";
|
||||
import parsePool from "@certusone/wormhole-sdk/lib/migration/parsePool";
|
||||
import addLiquidityTx from "@certusone/wormhole-sdk/lib/migration/addLiquidity";
|
||||
import claimSharesTx from "@certusone/wormhole-sdk/lib/migration/claimShares";
|
||||
import migrateTokensTx from "@certusone/wormhole-sdk/lib/migration/migrateTokens";
|
||||
|
||||
import SolanaCreateAssociatedAddress, {
|
||||
useAssociatedAccountExistsState,
|
||||
} from "../components/SolanaCreateAssociatedAddress";
|
||||
import {
|
||||
ASSOCIATED_TOKEN_PROGRAM_ID,
|
||||
Token,
|
||||
TOKEN_PROGRAM_ID,
|
||||
} from "@solana/spl-token";
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
rootContainer: {},
|
||||
|
@ -33,6 +47,9 @@ const useStyles = makeStyles(() => ({
|
|||
},
|
||||
padding: "2rem",
|
||||
},
|
||||
divider: {
|
||||
margin: "2rem",
|
||||
},
|
||||
}));
|
||||
|
||||
function Main() {
|
||||
|
@ -43,20 +60,56 @@ function Main() {
|
|||
|
||||
const [fromMint, setFromMint] = useState("");
|
||||
const [toMint, setToMint] = useState("");
|
||||
const [shareMintAddress, setShareMintAddress] = useState<string | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
const [poolAddress, setPoolAddress] = useState("");
|
||||
const [poolExists, setPoolExists] = useState<boolean | null>(null);
|
||||
const [poolAccountInfo, setPoolAccountInfo] = useState(null);
|
||||
const [shareTokenMint, setShareTokenMint] = useState(null);
|
||||
const [toTokenAccount, setToTokenAccount] = useState(null);
|
||||
const [fromTokenAccount, setFromTokenAccount] = useState(null);
|
||||
const [shareTokenAccount, setShareTokenAccount] = useState(null);
|
||||
const [poolExists, setPoolExists] = useState<boolean | undefined>(undefined);
|
||||
const [poolAccountInfo, setPoolAccountInfo] = useState(undefined);
|
||||
const [parsedPoolData, setParsedPoolData] = useState(undefined);
|
||||
|
||||
//These are the user's personal token accounts corresponding to the mints for the connected wallet
|
||||
const [fromTokenAccount, setFromTokenAccount] = useState<string | undefined>(
|
||||
undefined
|
||||
);
|
||||
const [toTokenAccount, setToTokenAccount] = useState<string | undefined>(
|
||||
undefined
|
||||
);
|
||||
const [shareTokenAccount, setShareTokenAccount] = useState<
|
||||
string | undefined
|
||||
>(undefined);
|
||||
|
||||
//These hooks detect if the connected wallet has the requisite token accounts
|
||||
const {
|
||||
associatedAccountExists: fromTokenAccountExists,
|
||||
setAssociatedAccountExists: setFromTokenAccountExists,
|
||||
} = useAssociatedAccountExistsState(fromMint, fromTokenAccount);
|
||||
const {
|
||||
associatedAccountExists: toTokenAccountExists,
|
||||
setAssociatedAccountExists: setToTokenAccountExists,
|
||||
} = useAssociatedAccountExistsState(toMint, toTokenAccount);
|
||||
const {
|
||||
associatedAccountExists: shareTokenAccountExists,
|
||||
setAssociatedAccountExists: setShareTokenAccountExists,
|
||||
} = useAssociatedAccountExistsState(shareMintAddress, shareTokenAccount);
|
||||
|
||||
//these are all the other derived information
|
||||
const [authorityAddress, setAuthorityAddress] = useState(null);
|
||||
const [fromCustodyAddress, setFromCustodyAddress] = useState(null);
|
||||
const [toCustodyAddress, setToCustodyAddress] = useState(null);
|
||||
const [shareMintAddress, setShareMintAddress] = useState(null);
|
||||
const [authorityAddress, setAuthorityAddress] = useState<string | undefined>(
|
||||
undefined
|
||||
);
|
||||
const [fromCustodyAddress, setFromCustodyAddress] = useState<
|
||||
string | undefined
|
||||
>(undefined);
|
||||
const [toCustodyAddress, setToCustodyAddress] = useState<string | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
const [toggleAllData, setToggleAllData] = useState(false);
|
||||
|
||||
const [liquidityAmount, setLiquidityAmount] = useState("");
|
||||
const [migrationAmount, setMigrationAmount] = useState("");
|
||||
const [redeemAmount, setRedeemAmount] = useState("");
|
||||
|
||||
/*
|
||||
Effects***
|
||||
|
@ -82,8 +135,8 @@ function Main() {
|
|||
//Retrieve the poolAccount every time the pool address changes.
|
||||
useEffect(() => {
|
||||
if (poolAddress) {
|
||||
setPoolAccountInfo(null);
|
||||
setPoolExists(null);
|
||||
setPoolAccountInfo(undefined);
|
||||
setPoolExists(undefined);
|
||||
try {
|
||||
getMultipleAccounts(
|
||||
connection,
|
||||
|
@ -92,6 +145,13 @@ function Main() {
|
|||
).then((result) => {
|
||||
if (result.length && result[0] !== null) {
|
||||
setPoolAccountInfo(result[0]);
|
||||
parsePool(result[0].data).then(
|
||||
(parsed) => setParsedPoolData(parsed),
|
||||
(error) => {
|
||||
logger.log("Failed to parse the pool data.");
|
||||
console.error(error);
|
||||
}
|
||||
);
|
||||
setPoolExists(true);
|
||||
logger.log("Successfully found account info for the pool.");
|
||||
} else if (result.length && result[0] === null) {
|
||||
|
@ -109,21 +169,71 @@ function Main() {
|
|||
}
|
||||
}, [poolAddress]);
|
||||
|
||||
//Set all the addresses which derive from poolAddress
|
||||
useEffect(() => {
|
||||
getAuthorityAddress(MIGRATION_PROGRAM_ADDRESS).then((result: any) =>
|
||||
setAuthorityAddress(result)
|
||||
setAuthorityAddress(new PublicKey(result).toString())
|
||||
);
|
||||
|
||||
getToCustodyAddress(MIGRATION_PROGRAM_ADDRESS, poolAddress).then(
|
||||
(result: any) => setToCustodyAddress(result)
|
||||
(result: any) => setToCustodyAddress(new PublicKey(result).toString())
|
||||
);
|
||||
getFromCustodyAddress(MIGRATION_PROGRAM_ADDRESS, poolAddress).then(
|
||||
(result: any) => setFromCustodyAddress(result)
|
||||
(result: any) => setFromCustodyAddress(new PublicKey(result).toString())
|
||||
);
|
||||
getShareMintAddress(MIGRATION_PROGRAM_ADDRESS, poolAddress).then(
|
||||
(result: any) => setShareMintAddress(result)
|
||||
(result: any) => setShareMintAddress(new PublicKey(result).toString())
|
||||
);
|
||||
}, [poolAddress]);
|
||||
|
||||
//Set the associated token accounts when the designated mint changes
|
||||
useEffect(() => {
|
||||
if (wallet?.publicKey && fromMint) {
|
||||
Token.getAssociatedTokenAddress(
|
||||
ASSOCIATED_TOKEN_PROGRAM_ID,
|
||||
TOKEN_PROGRAM_ID,
|
||||
new PublicKey(fromMint),
|
||||
wallet?.publicKey || new PublicKey([])
|
||||
).then(
|
||||
(result) => {
|
||||
setFromTokenAccount(result.toString());
|
||||
},
|
||||
(error) => {}
|
||||
);
|
||||
}
|
||||
}, [fromMint, wallet?.publicKey]);
|
||||
|
||||
useEffect(() => {
|
||||
if (wallet?.publicKey && toMint) {
|
||||
Token.getAssociatedTokenAddress(
|
||||
ASSOCIATED_TOKEN_PROGRAM_ID,
|
||||
TOKEN_PROGRAM_ID,
|
||||
new PublicKey(toMint),
|
||||
wallet?.publicKey || new PublicKey([])
|
||||
).then(
|
||||
(result) => {
|
||||
setToTokenAccount(result.toString());
|
||||
},
|
||||
(error) => {}
|
||||
);
|
||||
}
|
||||
}, [toMint, wallet?.publicKey]);
|
||||
|
||||
useEffect(() => {
|
||||
if (wallet?.publicKey && shareMintAddress) {
|
||||
Token.getAssociatedTokenAddress(
|
||||
ASSOCIATED_TOKEN_PROGRAM_ID,
|
||||
TOKEN_PROGRAM_ID,
|
||||
new PublicKey(shareMintAddress || ""),
|
||||
wallet?.publicKey || new PublicKey([])
|
||||
).then(
|
||||
(result) => {
|
||||
setShareTokenAccount(result.toString());
|
||||
},
|
||||
(error) => {}
|
||||
);
|
||||
}
|
||||
}, [shareMintAddress, wallet?.publicKey]);
|
||||
/*
|
||||
End Effects!
|
||||
*/
|
||||
|
@ -136,6 +246,14 @@ function Main() {
|
|||
|
||||
*/
|
||||
const createPool = async () => {
|
||||
console.log(
|
||||
"createPool with these args",
|
||||
connection,
|
||||
wallet?.publicKey?.toString(),
|
||||
MIGRATION_PROGRAM_ADDRESS,
|
||||
fromMint,
|
||||
toMint
|
||||
);
|
||||
try {
|
||||
const instruction = await createPoolAccount(
|
||||
connection,
|
||||
|
@ -148,8 +266,8 @@ function Main() {
|
|||
|
||||
signSendAndConfirm(wallet, connection, instruction).then(
|
||||
(transaction: any) => {
|
||||
setPoolExists(null); //Set these to null to force a fetch on them
|
||||
setPoolAccountInfo(null);
|
||||
setPoolExists(undefined); //Set these to null to force a fetch on them
|
||||
setPoolAccountInfo(undefined);
|
||||
logger.log("Successfully created the pool.");
|
||||
},
|
||||
(error) => {
|
||||
|
@ -162,6 +280,96 @@ function Main() {
|
|||
console.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
const addLiquidity = async () => {
|
||||
try {
|
||||
const instruction = await addLiquidityTx(
|
||||
connection,
|
||||
wallet?.publicKey?.toString() || "",
|
||||
MIGRATION_PROGRAM_ADDRESS,
|
||||
fromMint,
|
||||
toMint,
|
||||
toTokenAccount || "",
|
||||
shareTokenAccount || "",
|
||||
BigInt(liquidityAmount)
|
||||
);
|
||||
|
||||
signSendAndConfirm(wallet, connection, instruction).then(
|
||||
(transaction: any) => {
|
||||
setPoolExists(undefined); //Set these to null to force a fetch on them
|
||||
setPoolAccountInfo(undefined);
|
||||
logger.log("Successfully added liquidity to the pool.");
|
||||
},
|
||||
(error) => {
|
||||
logger.log("Could not complete the addLiquidity transaction");
|
||||
console.error(error);
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
logger.log("Could not complete the addLiquidity transaction");
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
const migrateTokens = async () => {
|
||||
try {
|
||||
const instruction = await migrateTokensTx(
|
||||
connection,
|
||||
wallet?.publicKey?.toString() || "",
|
||||
MIGRATION_PROGRAM_ADDRESS,
|
||||
fromMint,
|
||||
toMint,
|
||||
fromTokenAccount || "",
|
||||
toTokenAccount || "",
|
||||
BigInt(migrationAmount)
|
||||
);
|
||||
|
||||
signSendAndConfirm(wallet, connection, instruction).then(
|
||||
(transaction: any) => {
|
||||
setPoolExists(undefined); //Set these to null to force a fetch on them
|
||||
setPoolAccountInfo(undefined);
|
||||
logger.log("Successfully migrated the tokens.");
|
||||
},
|
||||
(error) => {
|
||||
logger.log("Could not complete the migrateTokens transaction.");
|
||||
console.error(error);
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
logger.log("Could not complete the migrateTokens transaction.");
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
const redeemShares = async () => {
|
||||
try {
|
||||
const instruction = await claimSharesTx(
|
||||
connection,
|
||||
wallet?.publicKey?.toString() || "",
|
||||
MIGRATION_PROGRAM_ADDRESS,
|
||||
fromMint,
|
||||
toMint,
|
||||
toTokenAccount || "",
|
||||
shareTokenAccount || "",
|
||||
BigInt(redeemAmount)
|
||||
);
|
||||
|
||||
signSendAndConfirm(wallet, connection, instruction).then(
|
||||
(transaction: any) => {
|
||||
setPoolExists(undefined); //Set these to null to force a fetch on them
|
||||
setPoolAccountInfo(undefined);
|
||||
logger.log("Successfully redeemed the shares.");
|
||||
},
|
||||
(error) => {
|
||||
logger.log("Could not complete the claimShares transaction.");
|
||||
console.error(error);
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
logger.log("Could not complete the claimShares transaction.");
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
/*
|
||||
End actions!
|
||||
*/
|
||||
|
@ -194,35 +402,156 @@ function Main() {
|
|||
<Button
|
||||
variant="contained"
|
||||
onClick={() => createPool()}
|
||||
disabled={poolExists || !poolAddress}
|
||||
disabled={poolExists}
|
||||
>
|
||||
Click here to instantiate the pool for these tokens.
|
||||
{poolExists
|
||||
? "This Pool is instantiated."
|
||||
: "This pool has not been instantiated! Click here to create it."}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
|
||||
const addLiquidity = (
|
||||
const addLiquidityUI = (
|
||||
<>
|
||||
<Typography>
|
||||
Add 'to' tokens to this pool, and receive liquidity tokens.
|
||||
<Typography variant="h4">Add Liquidity</Typography>
|
||||
<Typography variant="body1">
|
||||
This will remove 'To' tokens from your wallet, and give you an equal
|
||||
number of 'Share' tokens.
|
||||
</Typography>
|
||||
<TextField
|
||||
value={toMint}
|
||||
onChange={(event) => setToMint(event.target.value)}
|
||||
label={"To Token"}
|
||||
value={liquidityAmount}
|
||||
type="number"
|
||||
onChange={(event) => setLiquidityAmount(event.target.value)}
|
||||
label={"Amount to add"}
|
||||
></TextField>
|
||||
<Button variant="contained" onClick={addLiquidity}>
|
||||
Add Liquidity
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
|
||||
const migrateTokensUI = (
|
||||
<>
|
||||
<Typography variant="h4">Migrate Tokens</Typography>
|
||||
<Typography variant="body1">
|
||||
This will remove 'From' tokens from your wallet, and give you an equal
|
||||
number of 'To' tokens.
|
||||
</Typography>
|
||||
<TextField
|
||||
value={migrationAmount}
|
||||
type="number"
|
||||
onChange={(event) => setMigrationAmount(event.target.value)}
|
||||
label={"Amount to add"}
|
||||
></TextField>
|
||||
<Button variant="contained" onClick={migrateTokens}>
|
||||
Migrate Tokens
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
|
||||
const redeemSharesUI = (
|
||||
<>
|
||||
<Typography variant="h4">Redeem Shares</Typography>
|
||||
<Typography variant="body1">
|
||||
This will remove 'Share' tokens from your wallet, and give you an equal
|
||||
number of 'From' tokens.
|
||||
</Typography>
|
||||
<TextField
|
||||
type="number"
|
||||
value={redeemAmount}
|
||||
onChange={(event) => setRedeemAmount(event.target.value)}
|
||||
label={"Amount to add"}
|
||||
></TextField>
|
||||
<Button variant="contained" onClick={redeemShares}>
|
||||
Redeem Shares
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
|
||||
const relevantTokenAccounts = (
|
||||
<>
|
||||
<Typography variant="h4">Your Relevant Token Accounts: </Typography>
|
||||
<Typography variant="body1">
|
||||
{"'From' SPL Token Account: " + fromTokenAccount}
|
||||
</Typography>
|
||||
<SolanaCreateAssociatedAddress
|
||||
mintAddress={fromMint}
|
||||
readableTargetAddress={fromTokenAccount}
|
||||
associatedAccountExists={fromTokenAccountExists}
|
||||
setAssociatedAccountExists={setFromTokenAccountExists}
|
||||
/>
|
||||
<Typography variant="body1">
|
||||
{"'To' SPL Token Account: " + toTokenAccount}
|
||||
</Typography>
|
||||
<SolanaCreateAssociatedAddress
|
||||
mintAddress={toMint}
|
||||
readableTargetAddress={toTokenAccount}
|
||||
associatedAccountExists={toTokenAccountExists}
|
||||
setAssociatedAccountExists={setToTokenAccountExists}
|
||||
/>
|
||||
<Typography variant="body1">
|
||||
{"Share SPL Token Account: " + shareTokenAccount}
|
||||
</Typography>
|
||||
<SolanaCreateAssociatedAddress
|
||||
mintAddress={shareMintAddress}
|
||||
readableTargetAddress={shareTokenAccount}
|
||||
associatedAccountExists={shareTokenAccountExists}
|
||||
setAssociatedAccountExists={setShareTokenAccountExists}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
const poolInfo = (
|
||||
<div>
|
||||
{
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={() => setToggleAllData(!toggleAllData)}
|
||||
>
|
||||
{toggleAllData ? "Hide Verbose Pool Data" : "Show Verbose Pool Data"}
|
||||
</Button>
|
||||
}
|
||||
{toggleAllData ? (
|
||||
<>
|
||||
<Typography>{"Pool Address: " + poolAddress}</Typography>
|
||||
<Typography>{"Pool has been instantiated: " + poolExists}</Typography>
|
||||
<Typography>{"'From' Token Mint Address: " + fromMint}</Typography>
|
||||
<Typography>{"'To' Token Mint Address: " + toMint}</Typography>
|
||||
<Typography>{"Share Token Mint: " + shareMintAddress}</Typography>
|
||||
<Typography>{"Authority Address: " + authorityAddress}</Typography>
|
||||
<Typography>
|
||||
{"'From' Custody Mint: " + fromCustodyAddress}
|
||||
</Typography>
|
||||
<Typography>{"'To' Custody Mint: " + toCustodyAddress}</Typography>
|
||||
<Typography>
|
||||
{"Full Parsed Data for Pool: " + JSON.stringify(parsedPoolData)}
|
||||
</Typography>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
|
||||
const mainContent = (
|
||||
<>
|
||||
{toAndFromSelector}
|
||||
<Divider className={classes.divider} />
|
||||
{poolInfo}
|
||||
{createPoolButton}
|
||||
<Divider className={classes.divider} />
|
||||
{relevantTokenAccounts}
|
||||
<Divider className={classes.divider} />
|
||||
{addLiquidityUI}
|
||||
<Divider className={classes.divider} />
|
||||
{redeemSharesUI}
|
||||
<Divider className={classes.divider} />
|
||||
{migrateTokensUI}
|
||||
</>
|
||||
);
|
||||
|
||||
const content = !wallet.publicKey ? (
|
||||
<Typography>Please connect your wallet.</Typography>
|
||||
) : !poolAddress ? (
|
||||
toAndFromSelector
|
||||
) : (
|
||||
mainContent
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue