import mangoStore, { CLUSTER } from '@store/mangoStore' import { ModalProps } from '../../types/modal' import Modal from '../shared/Modal' import { OPENBOOK_PROGRAM_ID, createComputeBudgetIx, } 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 Switch from '@components/forms/Switch' import { sendTxAndConfirm } from 'utils/governance/tools' type CreateObMarketForm = { programId: string baseMint: string quoteMint: string minimumOrderSize: string minimumPriceTickSize: string xlMarket: boolean } 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: '', xlMarket: false, } 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 fee = mangoStore((s) => s.priorityFee) const { connect, signAllTransactions, connected, publicKey } = useWallet() const client = mangoStore((s) => s.client) 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 (!publicKey || !signAllTransactions) { return } setCreating(true) try { const ixObj = await makeCreateOpenBookMarketInstructionSimple({ connection, 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), xlSize: form.xlMarket, }) const txChunks = ixObj.innerTransactions const transactions: Transaction[] = [] const latestBlockhash = await connection.getLatestBlockhash('processed') for (const chunk of txChunks) { const tx = new Transaction() tx.add(createComputeBudgetIx(fee)) tx.add(...chunk.instructions) tx.lastValidBlockHeight = latestBlockhash.lastValidBlockHeight tx.recentBlockhash = latestBlockhash.blockhash tx.feePayer = publicKey tx.sign(...chunk.signers) transactions.push(tx) } const signedTransactions = await signAllTransactions(transactions) for (const tx of signedTransactions) { await sendTxAndConfirm( client.opts.multipleConnections, connection, tx, latestBlockhash, ) } onClose() notify({ title: t('market-created-successful'), type: 'success', }) } catch (e) { console.log(e) notify({ title: t('error-creating-market'), description: `${e}`, type: 'error', }) } setCreating(false) } useEffect(() => { setForm({ programId: OPENBOOK_PROGRAM_ID[CLUSTER].toBase58(), baseMint: baseMint || '', quoteMint: quoteMint || '', minimumOrderSize: tradingParams.minOrderSize.toString(), minimumPriceTickSize: tradingParams.priceIncrement.toString(), xlMarket: false, }) }, [ 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 })}

{t('create-bigger-market')}

setForm({ ...form, xlMarket: checked, }) } />
{connected ? ( ) : ( )}
) } export default CreateOpenbookMarketModal