2021-09-10 17:53:50 -07:00
|
|
|
import {
|
|
|
|
Container,
|
|
|
|
makeStyles,
|
|
|
|
Typography,
|
|
|
|
Paper,
|
2021-09-12 18:29:11 -07:00
|
|
|
TextField,
|
|
|
|
Button,
|
2021-09-10 17:53:50 -07:00
|
|
|
} from "@material-ui/core";
|
2021-09-12 18:29:11 -07:00
|
|
|
//import { pool_address } from "@certusone/wormhole-sdk/lib/solana/migration/wormhole_migration";
|
|
|
|
import { useCallback, useEffect, useState } from "react";
|
2021-09-10 17:53:50 -07:00
|
|
|
import LogWatcher from "../components/LogWatcher";
|
|
|
|
import SolanaWalletKey from "../components/SolanaWalletKey";
|
|
|
|
import { useSolanaWallet } from "../contexts/SolanaWalletContext";
|
|
|
|
import TabContext from "@material-ui/lab/TabContext";
|
|
|
|
import TabList from "@material-ui/lab/TabList";
|
|
|
|
import TabPanel from "@material-ui/lab/TabPanel";
|
2021-09-12 18:29:11 -07:00
|
|
|
import { MIGRATION_PROGRAM_ADDRESS, SOLANA_URL } from "../utils/consts";
|
|
|
|
import { PublicKey, Connection } from "@solana/web3.js";
|
|
|
|
import { useLogger } from "../contexts/Logger";
|
|
|
|
import { getMultipleAccounts, signSendAndConfirm } from "../utils/solana";
|
|
|
|
import getAuthorityAddress from "@certusone/wormhole-sdk/lib/migration/authorityAddress";
|
|
|
|
import createPoolAccount from "@certusone/wormhole-sdk/lib/migration/createPool";
|
|
|
|
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";
|
2021-09-10 17:53:50 -07:00
|
|
|
|
2021-09-12 18:29:11 -07:00
|
|
|
const useStyles = makeStyles(() => ({
|
|
|
|
rootContainer: {},
|
|
|
|
mainPaper: {
|
|
|
|
"& > *": {
|
|
|
|
margin: "1rem",
|
|
|
|
},
|
|
|
|
padding: "2rem",
|
|
|
|
},
|
|
|
|
}));
|
2021-09-10 17:53:50 -07:00
|
|
|
|
|
|
|
function Main() {
|
|
|
|
const classes = useStyles();
|
|
|
|
const wallet = useSolanaWallet();
|
2021-09-12 18:29:11 -07:00
|
|
|
const logger = useLogger();
|
|
|
|
const connection = new Connection(SOLANA_URL, "finalized");
|
|
|
|
|
|
|
|
const [fromMint, setFromMint] = useState("");
|
|
|
|
const [toMint, setToMint] = useState("");
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
//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);
|
|
|
|
|
|
|
|
/*
|
|
|
|
Effects***
|
|
|
|
|
|
|
|
These are generally data fetchers which fire when requisite data populates.
|
|
|
|
|
|
|
|
*/
|
|
|
|
//Retrieve pool address on selectedTokens change
|
|
|
|
useEffect(() => {
|
|
|
|
if (toMint && fromMint) {
|
|
|
|
setPoolAddress("");
|
|
|
|
getPoolAddress(MIGRATION_PROGRAM_ADDRESS, fromMint, toMint).then(
|
|
|
|
(result) => {
|
|
|
|
const key = new PublicKey(result).toString();
|
|
|
|
logger.log("Calculated the pool address at: " + key);
|
|
|
|
setPoolAddress(key);
|
|
|
|
},
|
|
|
|
(error) => logger.log("ERROR, could not calculate pool address.")
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}, [toMint, fromMint, setPoolAddress]);
|
|
|
|
|
|
|
|
//Retrieve the poolAccount every time the pool address changes.
|
|
|
|
useEffect(() => {
|
|
|
|
if (poolAddress) {
|
|
|
|
setPoolAccountInfo(null);
|
|
|
|
setPoolExists(null);
|
|
|
|
try {
|
|
|
|
getMultipleAccounts(
|
|
|
|
connection,
|
|
|
|
[new PublicKey(poolAddress)],
|
|
|
|
"finalized"
|
|
|
|
).then((result) => {
|
|
|
|
if (result.length && result[0] !== null) {
|
|
|
|
setPoolAccountInfo(result[0]);
|
|
|
|
setPoolExists(true);
|
|
|
|
logger.log("Successfully found account info for the pool.");
|
|
|
|
} else if (result.length && result[0] === null) {
|
|
|
|
logger.log("Confirmed that the pool does not exist.");
|
|
|
|
setPoolExists(false);
|
|
|
|
} else {
|
|
|
|
logger.log(
|
|
|
|
"unexpected error in fetching pool address. Please reload and try again"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
logger.log("Could not fetch pool address");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, [poolAddress]);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
getAuthorityAddress(MIGRATION_PROGRAM_ADDRESS).then((result: any) =>
|
|
|
|
setAuthorityAddress(result)
|
|
|
|
);
|
|
|
|
|
|
|
|
getToCustodyAddress(MIGRATION_PROGRAM_ADDRESS, poolAddress).then(
|
|
|
|
(result: any) => setToCustodyAddress(result)
|
|
|
|
);
|
|
|
|
getFromCustodyAddress(MIGRATION_PROGRAM_ADDRESS, poolAddress).then(
|
|
|
|
(result: any) => setFromCustodyAddress(result)
|
|
|
|
);
|
|
|
|
getShareMintAddress(MIGRATION_PROGRAM_ADDRESS, poolAddress).then(
|
|
|
|
(result: any) => setShareMintAddress(result)
|
|
|
|
);
|
|
|
|
}, [poolAddress]);
|
|
|
|
/*
|
|
|
|
End Effects!
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
Actions:
|
|
|
|
|
|
|
|
These are generally onClick actions which the user can perform. They read things off the state, do something,
|
|
|
|
and then potentially update something on the state.
|
|
|
|
|
|
|
|
*/
|
|
|
|
const createPool = async () => {
|
|
|
|
try {
|
|
|
|
const instruction = await createPoolAccount(
|
|
|
|
connection,
|
|
|
|
wallet?.publicKey?.toString() || "",
|
|
|
|
MIGRATION_PROGRAM_ADDRESS,
|
|
|
|
wallet?.publicKey?.toString() || "",
|
|
|
|
fromMint,
|
|
|
|
toMint
|
|
|
|
);
|
|
|
|
|
|
|
|
signSendAndConfirm(wallet, connection, instruction).then(
|
|
|
|
(transaction: any) => {
|
|
|
|
setPoolExists(null); //Set these to null to force a fetch on them
|
|
|
|
setPoolAccountInfo(null);
|
|
|
|
logger.log("Successfully created the pool.");
|
|
|
|
},
|
|
|
|
(error) => {
|
|
|
|
logger.log("Could not create the pool");
|
|
|
|
console.error(error);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
} catch (e) {
|
|
|
|
logger.log("Failed to create the pool.");
|
|
|
|
console.error(e);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
/*
|
|
|
|
End actions!
|
|
|
|
*/
|
|
|
|
|
|
|
|
const toAndFromSelector = (
|
|
|
|
<>
|
|
|
|
<Typography>
|
|
|
|
Please enter the mint addresses for the 'To' and 'From' tokens you're
|
|
|
|
interested in.
|
|
|
|
</Typography>
|
|
|
|
<TextField
|
|
|
|
value={fromMint}
|
|
|
|
onChange={(event) => setFromMint(event.target.value)}
|
|
|
|
label={"From Token"}
|
|
|
|
fullWidth
|
|
|
|
style={{ display: "block" }}
|
|
|
|
></TextField>
|
|
|
|
<TextField
|
|
|
|
value={toMint}
|
|
|
|
onChange={(event) => setToMint(event.target.value)}
|
|
|
|
label={"To Token"}
|
|
|
|
fullWidth
|
|
|
|
style={{ display: "block" }}
|
|
|
|
></TextField>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
|
|
|
|
const createPoolButton = (
|
|
|
|
<div>
|
|
|
|
<Button
|
|
|
|
variant="contained"
|
|
|
|
onClick={() => createPool()}
|
|
|
|
disabled={poolExists || !poolAddress}
|
|
|
|
>
|
|
|
|
Click here to instantiate the pool for these tokens.
|
|
|
|
</Button>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
|
|
|
|
const addLiquidity = (
|
|
|
|
<>
|
|
|
|
<Typography>
|
|
|
|
Add 'to' tokens to this pool, and receive liquidity tokens.
|
|
|
|
</Typography>
|
|
|
|
<TextField
|
|
|
|
value={toMint}
|
|
|
|
onChange={(event) => setToMint(event.target.value)}
|
|
|
|
label={"To Token"}
|
|
|
|
></TextField>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
|
|
|
|
const mainContent = (
|
|
|
|
<>
|
|
|
|
{toAndFromSelector}
|
|
|
|
{createPoolButton}
|
|
|
|
</>
|
2021-09-10 17:53:50 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
const content = !wallet.publicKey ? (
|
|
|
|
<Typography>Please connect your wallet.</Typography>
|
|
|
|
) : (
|
2021-09-12 18:29:11 -07:00
|
|
|
mainContent
|
2021-09-10 17:53:50 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
return (
|
2021-09-12 18:29:11 -07:00
|
|
|
<Container maxWidth="md" className={classes.rootContainer}>
|
|
|
|
<Paper className={classes.mainPaper}>
|
2021-09-10 17:53:50 -07:00
|
|
|
<SolanaWalletKey />
|
|
|
|
{content}
|
|
|
|
</Paper>
|
|
|
|
<LogWatcher />
|
|
|
|
</Container>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export default Main;
|