diff --git a/pages/create_market.tsx b/pages/create_market.tsx index 81c3d97..a900c0d 100644 --- a/pages/create_market.tsx +++ b/pages/create_market.tsx @@ -1,8 +1,6 @@ import { useState } from "react"; -// import { useOpenbookClient } from "../hooks/useOpenbookClient"; import { Keypair, - LAMPORTS_PER_SOL, PublicKey, SystemProgram, } from "@solana/web3.js"; @@ -15,348 +13,138 @@ import toast from "react-hot-toast"; const CreateMarket = () => { const { publicKey } = useWallet(); - const [name, setName] = useState(""); - const [quoteMint, setQuoteMint] = useState(PublicKey.default); - const [baseMint, setBaseMint] = useState(PublicKey.default); - const [quoteLotSize, setQuoteLotSize] = useState(""); - const [baseLotSize, setBaseLotSize] = useState(""); - const [makerFee, setMakerFee] = useState("0"); - const [takerFee, setTakerFee] = useState("0"); - const [timeExpiry, setTimeExpiry] = useState("0"); - const [oracleA, setOracleA] = useState(null); - const [oracleB, setOracleB] = useState(null); - const [openOrdersAdmin, setOpenOrdersAdmin] = useState(PublicKey.default); - const [consumeEventsAdmin, setConsumeEventsAdmin] = useState( - PublicKey.default - ); - const [closeMarketAdmin, setCloseMarketAdmin] = useState(PublicKey.default); - const [confFilter, setConfFilter] = useState("0.1"); - const [maxStalenessSlots, setMaxStalenessSlots] = useState("100"); + const [formState, setFormState] = useState({ + name: '', + quoteMint: PublicKey.default, + baseMint: PublicKey.default, + quoteLotSize: '', + baseLotSize: '', + makerFee: '0', + takerFee: '0', + timeExpiry: '0', + oracleA: null, + oracleB: null, + openOrdersAdmin: PublicKey.default, + consumeEventsAdmin: PublicKey.default, + closeMarketAdmin: PublicKey.default, + confFilter: '0.1', + maxStalenessSlots: '100', + }); const openbookClient = useOpenbookClient(); - const handleSubmit = async (event) => { - event.preventDefault(); + const fields = [ + { label: 'Name', field: 'name', type: 'text', isPublicKey: false }, + { label: 'Quote Mint', field: 'quoteMint', type: 'text', isPublicKey: true }, + { label: 'Base Mint', field: 'baseMint', type: 'text', isPublicKey: true }, + { label: 'Quote Lot Size', field: 'quoteLotSize', type: 'text', isPublicKey: false }, + { label: 'Base Lot Size', field: 'baseLotSize', type: 'text', isPublicKey: false }, + { label: 'Maker Fee', field: 'makerFee', type: 'text', isPublicKey: false }, + { label: 'Taker Fee', field: 'takerFee', type: 'text', isPublicKey: false }, + { label: 'Time Expiry (Only for markets that can be closed)', field: 'timeExpiry', type: 'text', isPublicKey: false }, + { label: 'Oracle A (Optional)', field: 'oracleA', type: 'text', isPublicKey: true }, + { label: 'Oracle B (Optional)', field: 'oracleB', type: 'text', isPublicKey: true }, + { label: 'Max Staleness Slots (Optional)', field: 'maxStalenessSlots', type: 'text', isPublicKey: false }, + { label: 'Configuration Filter (Optional)', field: 'confFilter', type: 'text', isPublicKey: false }, + { label: 'Open Orders Admin (Permissioned Markets)', field: 'openOrdersAdmin', type: 'text', isPublicKey: true }, + { label: 'Consume Events Admin (Permissioned Markets)', field: 'consumeEventsAdmin', type: 'text', isPublicKey: true }, + { label: 'Close Market Admin (Permissioned Markets)', field: 'closeMarketAdmin', type: 'text', isPublicKey: true }, + ]; + + const handleChange = (e, field, isPublicKey) => { + let value; + if (isPublicKey) { + try { + value = new PublicKey(e.target.value); + } catch (error) { + console.error("Invalid PublicKey:", e.target.value); + value = e.target.value; + } + } else { + value = e.target.value; + } + + setFormState((prevState) => ({ + ...prevState, + [field]: value, + })); + }; + + + const handleSubmit = (e) => { + e.preventDefault(); + const oracleConfigParams: OracleConfigParams = { - confFilter: Number(confFilter), - maxStalenessSlots: Number(maxStalenessSlots), + confFilter: Number(formState.confFilter), + maxStalenessSlots: Number(formState.maxStalenessSlots), }; - try { + try { console.log(JSON.stringify(formState, null, 2)); openbookClient .createMarket( - publicKey, - name, - quoteMint, - baseMint, - new BN(quoteLotSize), - new BN(baseLotSize), - new BN(makerFee), - new BN(takerFee), - new BN(timeExpiry), - oracleA, - oracleB, - openOrdersAdmin, - consumeEventsAdmin, - closeMarketAdmin, - oracleConfigParams + formState.publicKey, + formState.name, + formState.quoteMint, + formState.baseMint, + new BN(formState.quoteLotSize), + new BN(formState.baseLotSize), + new BN(formState.makerFee), + new BN(formState.takerFee), + new BN(formState.timeExpiry), + formState.oracleA, + formState.oracleB, + formState.openOrdersAdmin, + formState.consumeEventsAdmin, + formState.closeMarketAdmin, + formState.oracleConfigParams ) .then(async ([transactionInstructions, signers]) => { - // Process the results here - const ixTransfer = SystemProgram.transfer({ - fromPubkey: publicKey, - toPubkey: new PublicKey( - "2fmQLSF1xR5FK3Yc5VhGvnrx7mjXbNSJN3d3WySYnzr6" - ), - lamports: LAMPORTS_PER_SOL, - }); const tx = await openbookClient.sendAndConfirmTransaction( - [ixTransfer, ...transactionInstructions], + [...transactionInstructions], { additionalSigners: signers, } ); console.log("Create Market tx", tx); - toast("Create Market tx: " + tx.toString()); + toast("Create Market tx: " + tx); }) .catch((error) => { - // Handle any errors that might occur during the execution of the promise console.error("Error:", error); }); } catch (error) { console.log("Error on the form", error); - // Handle errors } }; return ( -
+

Create a market

-

- You will be able to create a permissioned or permissionles market. - You will need at least 3 SOL in your account. There is 1 SOL fee for - creating a market using this UI. Run it locally or fork it to avoid - the fee. -

-
-
- -
- setName(e.target.value)} - className="block w-full rounded-md py-1.5 pl-2 pl-2 text-black font-bold shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" - /> -
-
- -
- -
- setQuoteMint(new PublicKey(e.target.value))} - className="block w-full rounded-md py-1.5 pl-2 text-black shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-black-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" - /> + {fields.map(({ label, field, type, isPublicKey }, index) => ( +
+ +
+ handleChange(e, field, isPublicKey)} + className="block w-full rounded-md py-1.5 pl-2 text-black shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" + /> +
-
- -
- -
- setBaseMint(new PublicKey(e.target.value))} - className="block w-full rounded-md border-0 py-1.5 pl-2 text-black shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-white-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" - /> -
-
- -
- -
- setQuoteLotSize(e.target.value)} - className="block w-full rounded-md py-1.5 pl-2 text-black shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-black-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" - /> -
-
- -
- -
- setBaseLotSize(e.target.value)} - className="block w-full rounded-md border-0 py-1.5 pl-2 text-black shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-white-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" - /> -
-
- -
- -
- setMakerFee(e.target.value)} - className="block w-full rounded-md py-1.5 pl-2 text-black shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-black-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" - /> -
-
- -
- -
- setTakerFee(e.target.value)} - className="block w-full rounded-md border-0 py-1.5 pl-2 text-black shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-white-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" - /> -
-
- -
- -
- setTimeExpiry(e.target.value)} - className="block w-full rounded-md border-0 py-1.5 pl-2 text-black shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-white-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" - /> -
-
- -
- -
- setOracleA(new PublicKey(e.target.value))} - className="block w-full rounded-md py-1.5 pl-2 text-black shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-black-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" - /> -
-
- -
- -
- setOracleB(new PublicKey(e.target.value))} - className="block w-full rounded-md border-0 py-1.5 pl-2 text-black shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-white-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" - /> -
-
- -
- -
- setMaxStalenessSlots(e.target.value)} - className="block w-full rounded-md py-1.5 pl-2 text-black shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-black-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" - /> -
-
- -
- -
- setConfFilter(e.target.value)} - className="block w-full rounded-md border-0 py-1.5 pl-2 text-black shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-white-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" - /> -
-
- -
- -
- - setOpenOrdersAdmin(new PublicKey(e.target.value)) - } - className="block w-full rounded-md py-1.5 pl-2 text-black shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-black-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" - /> -
-
- -
- -
- - setConsumeEventsAdmin(new PublicKey(e.target.value)) - } - className="block w-full rounded-md border-0 py-1.5 pl-2 text-black shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-white-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" - /> -
-
- -
- -
- - setCloseMarketAdmin(new PublicKey(e.target.value)) - } - className="block w-full rounded-md border-0 py-1.5 pl-2 text-black shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-white-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" - /> -
-
+ ))}
-