import mangoStore, { CLUSTER } from '@store/mangoStore' import { ModalProps } from '../../types/modal' import Modal from '../shared/Modal' import { OPENBOOK_PROGRAM_ID } from '@blockworks-foundation/mango-v4' import { ChangeEvent, useEffect, useState } from 'react' import Label from '@components/forms/Label' import Input from '@components/forms/Input' import { useTranslation } from 'next-i18next' import Button from '@components/shared/Button' import { makeCreateOpenBookMarketInstructionSimple } from 'utils/governance/market/createOpenBookMarket' import { useWallet } from '@solana/wallet-adapter-react' import { LAMPORTS_PER_SOL, PublicKey, Transaction } from '@solana/web3.js' import { MARKET_STATE_LAYOUT_V2 } from '@project-serum/serum' import { notify } from 'utils/notifications' import InlineNotification from '@components/shared/InlineNotification' import { useEnhancedWallet } from '@components/wallet/EnhancedWalletProvider' type CreateObMarketForm = { programId: string baseMint: string quoteMint: string minimumOrderSize: string minimumPriceTickSize: string } type TradingParams = { baseLots: number quoteLots: number minOrderValue: number baseLotExponent: number quoteLotExponent: number minOrderSize: number priceIncrement: number priceIncrementRelative: number } type FormErrors = Partial> const defaultFormValues: CreateObMarketForm = { programId: '', baseMint: '', quoteMint: '', minimumOrderSize: '', minimumPriceTickSize: '', } type CreateOpenbookMarketModalProps = { baseMint: string baseDecimals: number quoteMint: string quoteDecimals: number tradingParams: TradingParams } const CreateOpenbookMarketModal = ({ isOpen, onClose, baseMint, baseDecimals, quoteMint, quoteDecimals, tradingParams, }: ModalProps & CreateOpenbookMarketModalProps) => { const { t } = useTranslation(['governance']) const connection = mangoStore((s) => s.connection) const wallet = useWallet() const { handleConnect } = useEnhancedWallet() const [form, setForm] = useState({ ...defaultFormValues }) const [formErrors, setFormErrors] = useState({}) const [creating, setCreating] = useState(false) const [solNeededToCreateMarket, setSolNeededToCreateMarket] = useState(0) const handleSetAdvForm = (propertyName: string, value: string | number) => { setFormErrors({}) setForm({ ...form, [propertyName]: value }) } const handleCreate = async () => { if (!wallet || !wallet.signAllTransactions) { return } let sig = '' setCreating(true) try { const ixObj = await makeCreateOpenBookMarketInstructionSimple({ connection, wallet: wallet.publicKey!, baseInfo: { mint: new PublicKey(baseMint), decimals: baseDecimals, }, quoteInfo: { mint: new PublicKey(quoteMint), decimals: quoteDecimals, }, lotSize: Number(form.minimumOrderSize), tickSize: Number(form.minimumPriceTickSize), dexProgramId: new PublicKey(form.programId), }) const txChunks = ixObj.innerTransactions const transactions: Transaction[] = [] const latestBlockhash = await connection.getLatestBlockhash('confirmed') for (const chunk of txChunks) { const tx = new Transaction() tx.add(...chunk.instructions) tx.lastValidBlockHeight = latestBlockhash.lastValidBlockHeight tx.recentBlockhash = latestBlockhash.blockhash tx.feePayer = wallet.publicKey! tx.sign(...chunk.signers) transactions.push(tx) } const signedTransactions = await wallet.signAllTransactions(transactions) for (const tx of signedTransactions) { const rawTransaction = tx.serialize() sig = await connection.sendRawTransaction(rawTransaction, { skipPreflight: true, }) await connection.confirmTransaction({ blockhash: latestBlockhash.blockhash, lastValidBlockHeight: latestBlockhash.lastValidBlockHeight, signature: sig, }) } onClose() notify({ title: t('market-created-successful'), type: 'success', }) } catch (e) { notify({ title: t('error-creating-market'), description: `${e}`, txid: sig, type: 'error', }) } setCreating(false) } useEffect(() => { setForm({ programId: OPENBOOK_PROGRAM_ID[CLUSTER].toBase58(), baseMint: baseMint || '', quoteMint: quoteMint || '', minimumOrderSize: tradingParams.minOrderSize.toString(), minimumPriceTickSize: tradingParams.priceIncrement.toString(), }) }, [ baseMint, quoteMint, tradingParams.minOrderSize, tradingParams.priceIncrement, ]) useEffect(() => { const getMinLamportsToCreateMarket = async () => { const accountsSpace = 84522 + MARKET_STATE_LAYOUT_V2.span const minLamports = await connection.getMinimumBalanceForRentExemption( accountsSpace ) setSolNeededToCreateMarket( Math.round((minLamports / LAMPORTS_PER_SOL + Number.EPSILON) * 100) / 100 ) } getMinLamportsToCreateMarket() }, [connection]) return (

{t('create-openbook')}

{t('create-market-sol-cost', { cost: solNeededToCreateMarket })}

{wallet.connected ? ( ) : ( )}
) } export default CreateOpenbookMarketModal