diff --git a/lp_ui/src/utils/consts.ts b/lp_ui/src/utils/consts.ts index e4d683f6..ff13e7ea 100644 --- a/lp_ui/src/utils/consts.ts +++ b/lp_ui/src/utils/consts.ts @@ -1,11 +1,15 @@ import { clusterApiUrl } from "@solana/web3.js"; export const MIGRATION_PROGRAM_ADDRESS = - process.env.REACT_APP_CLUSTER === "testnet" + process.env.REACT_APP_CLUSTER === "mainnet" + ? "" + : process.env.REACT_APP_CLUSTER === "testnet" ? "" : "Ex9bCdVMSfx7EzB3pgSi2R4UHwJAXvTw18rBQm5YQ8gK"; export const SOLANA_URL = - process.env.REACT_APP_CLUSTER === "testnet" + process.env.REACT_APP_CLUSTER === "mainnet" + ? clusterApiUrl("mainnet-beta") + : process.env.REACT_APP_CLUSTER === "testnet" ? clusterApiUrl("testnet") : "http://localhost:8899"; diff --git a/lp_ui/src/views/Main.tsx b/lp_ui/src/views/Main.tsx index 12230946..e0b02a84 100644 --- a/lp_ui/src/views/Main.tsx +++ b/lp_ui/src/views/Main.tsx @@ -1,6 +1,7 @@ import addLiquidityTx from "@certusone/wormhole-sdk/lib/migration/addLiquidity"; import getAuthorityAddress from "@certusone/wormhole-sdk/lib/migration/authorityAddress"; import claimSharesTx from "@certusone/wormhole-sdk/lib/migration/claimShares"; +import removeLiquidityTx from "@certusone/wormhole-sdk/lib/migration/removeLiquidity"; import createPoolAccount from "@certusone/wormhole-sdk/lib/migration/createPool"; import getFromCustodyAddress from "@certusone/wormhole-sdk/lib/migration/fromCustodyAddress"; import migrateTokensTx from "@certusone/wormhole-sdk/lib/migration/migrateTokens"; @@ -166,10 +167,13 @@ function Main() { const [toggleAllData, setToggleAllData] = useState(false); const [liquidityAmount, setLiquidityAmount] = useState(""); + const [removeLiquidityAmount, setRemoveLiquidityAmount] = useState(""); const [migrationAmount, setMigrationAmount] = useState(""); const [redeemAmount, setRedeemAmount] = useState(""); const [liquidityIsProcessing, setLiquidityIsProcessing] = useState(false); + const [removeLiquidityIsProcessing, setRemoveLiquidityIsProcessing] = + useState(false); const [migrationIsProcessing, setMigrationIsProcessing] = useState(false); const [redeemIsProcessing, setRedeemIsProcessing] = useState(false); const [createPoolIsProcessing, setCreatePoolIsProcessing] = useState(false); @@ -445,6 +449,56 @@ function Main() { toCustodyAddress, ]); + const removeLiquidity = useCallback(async () => { + try { + const instruction = await removeLiquidityTx( + connection, + wallet?.publicKey?.toString() || "", + MIGRATION_PROGRAM_ADDRESS, + fromMint, + toMint, + toTokenAccount || "", + shareTokenAccount || "", + parseUnits(removeLiquidityAmount, shareMintDecimals).toBigInt() + ); + setRemoveLiquidityIsProcessing(true); + signSendAndConfirm(wallet, connection, instruction).then( + (transaction: any) => { + log("Successfully removed liquidity to the pool."); + getBalance( + connection, + fromCustodyAddress, + setFromCustodyBalance, + log + ); + getBalance(connection, toCustodyAddress, setToCustodyBalance, log); + setRemoveLiquidityIsProcessing(false); + }, + (error) => { + log("Could not complete the removeLiquidity transaction"); + console.error(error); + setRemoveLiquidityIsProcessing(false); + } + ); + } catch (e) { + log("Could not complete the removeLiquidity transaction"); + console.error(e); + setRemoveLiquidityIsProcessing(false); + } + }, [ + connection, + fromMint, + removeLiquidityAmount, + shareTokenAccount, + toMint, + toTokenAccount, + wallet, + log, + shareMintDecimals, + fromCustodyAddress, + toCustodyAddress, + ]); + const migrateTokens = useCallback(async () => { try { const instruction = await migrateTokensTx( @@ -610,6 +664,30 @@ function Main() { ); + const removeLiquidityUI = ( + <> + Remove Liquidity + + This will remove 'Share' tokens from your wallet, and give you an equal + number of 'To' tokens. + + setRemoveLiquidityAmount(event.target.value)} + label={"Amount to remove"} + > + + {removeLiquidityIsProcessing ? : null} + + ); + const migrateTokensUI = ( <> Migrate Tokens @@ -736,6 +814,8 @@ function Main() { {addLiquidityUI} + {removeLiquidityUI} + {redeemSharesUI} {migrateTokensUI} diff --git a/sdk/js/src/migration/removeLiquidity.ts b/sdk/js/src/migration/removeLiquidity.ts new file mode 100644 index 00000000..5d7e9348 --- /dev/null +++ b/sdk/js/src/migration/removeLiquidity.ts @@ -0,0 +1,41 @@ +import { Token, TOKEN_PROGRAM_ID } from "@solana/spl-token"; +import { Connection, PublicKey, Transaction } from "@solana/web3.js"; +import { ixFromRust } from "../solana"; + +export default async function removeLiquidity( + connection: Connection, + payerAddress: string, + program_id: string, + from_mint: string, + to_mint: string, + liquidity_token_account: string, + lp_share_token_account: string, + amount: BigInt +) { + const { authority_address, remove_liquidity } = await import( + "../solana/migration/wormhole_migration" + ); + const approvalIx = Token.createApproveInstruction( + TOKEN_PROGRAM_ID, + new PublicKey(lp_share_token_account), + new PublicKey(authority_address(program_id)), + new PublicKey(payerAddress), + [], + Number(amount) + ); + const ix = ixFromRust( + remove_liquidity( + program_id, + from_mint, + to_mint, + liquidity_token_account, + lp_share_token_account, + amount + ) + ); + const transaction = new Transaction().add(approvalIx, ix); + const { blockhash } = await connection.getRecentBlockhash(); + transaction.recentBlockhash = blockhash; + transaction.feePayer = new PublicKey(payerAddress); + return transaction; +}