diff --git a/components/liquidity/lands.tsx b/components/liquidity/lands.tsx index 9e3eb1a2..705f0a8c 100644 --- a/components/liquidity/lands.tsx +++ b/components/liquidity/lands.tsx @@ -1,3 +1,4 @@ +import { useState } from 'react'; import { Slider } from '@components/ui/slider'; import Link from 'next/link'; import { Button } from '@components/ui/button'; @@ -12,28 +13,63 @@ const LandControls = ({ metadata, hadLand }: any) => { - const hasRequiredTokens = Math.abs(min) !== Math.abs(max) + const tokenPrecision = Math.pow(10, metadata.wraps.decimals); + const [manualInput, setManualInput] = useState(tokensSelected / tokenPrecision); + const handleInputChange = (e: React.ChangeEvent) => { + let value = parseFloat(e.target.value); + if (isNaN(value)) { + value = 0; + } + value = Math.max(min / tokenPrecision, Math.min(value, max / tokenPrecision)); + setManualInput(value); + onSetTokensSelected(value * tokenPrecision); + }; + + const handleSliderChange = (value: number[]) => { + setManualInput(value[0] / tokenPrecision); + onSetTokensSelected(value[0]); + }; return (
- {hasRequiredTokens &&
-
-
Token Amount
-
{Math.abs(tokensSelected) / Math.pow(10, metadata.wraps.decimals)} {metadata.wraps.symbol}
-
-
- onSetTokensSelected(v[0])} - /> + {Math.abs(min) !== Math.abs(max) && ( +
+
+
Token Amount
+
{(tokensSelected / tokenPrecision).toLocaleString()} {metadata.wraps.symbol}
+
+
+ +
+
+ +
+ + {metadata.wraps.symbol} +
+
-
} + )}
- ) -} + ); +}; -export default LandControls \ No newline at end of file +export default LandControls; diff --git a/components/quest/token-select-dialog.tsx b/components/quest/token-select-dialog.tsx index 039bc745..f36ef6f5 100644 --- a/components/quest/token-select-dialog.tsx +++ b/components/quest/token-select-dialog.tsx @@ -69,16 +69,16 @@ export const TokenSelectDialog = ({ lands, contractId, buttonText = 'Complete Qu {lands.map((land: any) => ( -
+
{'token-logo'} (land.whitelisted && !tapped[land.id] && tap(land.id))} - className={`z-20 border rounded-full h-32 w-32 ${(land.whitelisted && !tapped[land.id]) && 'group-hover/token:z-40 group-hover/token:shadow-xl group-hover/token:scale-110 transition-all'}`} + onClick={() => (land.whitelisted && !tapped[land.id] && land.balances?.energy && tap(land.id))} + className={`z-20 border rounded-full h-32 w-32 ${(land.whitelisted && !tapped[land.id] && land.balances?.energy) && 'group-hover/token:z-40 group-hover/token:shadow-xl group-hover/token:scale-110 transition-all'}`} /> -
+
{numeral(land.balances?.energy).format('0a')} ⚡
diff --git a/lib/events/utils.ts b/lib/events/utils.ts index 9dc60f31..5c684c6c 100644 --- a/lib/events/utils.ts +++ b/lib/events/utils.ts @@ -72,6 +72,7 @@ export const handleContractEvent = async (event: any, builder: any) => { // contract ids const kraqenLottoContractId = 'SPGYCP878RYFVT03ZT8TWGPKNYTSQB1578VVXHGE.kraqen-lotto'; const spellScrollsContractId = 'SP2ZNGJ85ENDY6QRHQ5P2D4FXKGZWCKTB2T0Z55KS.spell-scrolls-fire-bolt'; + const pixelRozarContractId = 'SP2ZNGJ85ENDY6QRHQ5P2D4FXKGZWCKTB2T0Z55KS.pixel-rozar'; if (contractId === kraqenLottoContractId) { symbol = '🐙' @@ -84,7 +85,7 @@ export const handleContractEvent = async (event: any, builder: any) => { builder.addField({ name: `${symbol} ${event.type}`, - value: `${event.data.recipient} gained ${event.data.amount / Math.pow(10, 6)} experience.` + value: JSON.stringify(event.data).slice(0, 300) }); } @@ -102,7 +103,24 @@ export const handleContractEvent = async (event: any, builder: any) => { builder.addField({ name: `${symbol} ${event.type}`, - value: `${event.data.recipient} gained ${event.data.amount / Math.pow(10, 6)} experience.` + value: JSON.stringify(event.data).slice(0, 300) + }); + + } + + else if (contractId === pixelRozarContractId) { + symbol = '💩' + + const pixelRozarContract = contractFactory(contracts.kraqenLotto, pixelRozarContractId); + const tokensMinted = await clarigen.roOk(pixelRozarContract.getLastTokenId()); + const nftMetadata = await getNftCollectionMetadata(pixelRozarContractId) + nftMetadata.properties.minted = Number(tokensMinted) + await setNftCollectionMetadata(pixelRozarContractId, nftMetadata) + + builder.setThumbnail({ url: 'https://beta.charisma.rocks/quests/pixel-rozar/pixel-rozar.png' }) + builder.addField({ + name: `${symbol} ${event.type}`, + value: JSON.stringify(event.data).slice(0, 300) }); } diff --git a/pages/api/v0/lands/index.ts b/pages/api/v0/lands/index.ts index 6b3b4899..b81010a1 100644 --- a/pages/api/v0/lands/index.ts +++ b/pages/api/v0/lands/index.ts @@ -82,8 +82,7 @@ export default async function landsIndexApi( if (tx.metadata.success) { let builder = new EmbedBuilder() // send message to discord - builder.setAuthor({ name: `Stake-to-Earn Pools`, icon_url: 'https://beta.charisma.rocks/charisma.png', url: 'https://beta.charisma.rocks/staking' }) - builder.setTitle('New Event') + builder.setAuthor({ name: `Charisma Event`, icon_url: 'https://beta.charisma.rocks/charisma.png', url: 'https://beta.charisma.rocks/staking' }) builder.setThumbnail({ url: 'https://beta.charisma.rocks/charisma.png' }) for (const event of tx.metadata.receipt.events) { diff --git a/pages/quest-deployer/index.tsx b/pages/quest-deployer/index.tsx index f602e490..e0a86827 100644 --- a/pages/quest-deployer/index.tsx +++ b/pages/quest-deployer/index.tsx @@ -197,13 +197,13 @@ export default function ContractDeployer({ data }: any) {

- NFT{" "} + Utility{" "} - Collection + NFT Collection

- Create an NFT collection to sell on Charisma + Create non-unique utility NFTs to sell on Charisma

diff --git a/pages/quest-deployer/nfts.tsx b/pages/quest-deployer/nfts.tsx index 99ced002..5e5f89d7 100644 --- a/pages/quest-deployer/nfts.tsx +++ b/pages/quest-deployer/nfts.tsx @@ -25,11 +25,13 @@ const proposalFormSchema = z.object({ collectionImage: z.string().url("Must be a valid URL"), energyRequired: z.coerce.number().min(1, "Amount must be at least 1"), nftName: z.string(), + stxPerMint: z.coerce.number().min(0.000001, "Amount must be at least 0.000001"), + maxMintsPerTx: z.coerce.number().min(1, "Amount must be at least 1").max(20, "Amount must be at most 20"), }) type ProposalFormValues = z.infer -const generateTemplate = ({ contractAddress, totalSupply, stxAddress, description, energyRequired, nftName }: ProposalFormValues) => { +const generateTemplate = ({ contractAddress, totalSupply, stxAddress, description, energyRequired, nftName, stxPerMint, maxMintsPerTx }: ProposalFormValues) => { // Your template generation logic here return `;; Description: ;; ${description} @@ -46,10 +48,10 @@ const generateTemplate = ({ contractAddress, totalSupply, stxAddress, descriptio ;; Define constants (define-constant COLLECTION_LIMIT u${totalSupply}) ;; Limit to series of ${totalSupply} (define-constant ENERGY_PER_NFT u${energyRequired}) ;; ${energyRequired} energy per NFT -(define-constant STX_PER_MINT u1000000) ;; 1 STX per MINT for DAO -(define-constant MAX_NFTS_PER_TX u4) ;; Maximum 4 NFTs per transaction +(define-constant STX_PER_MINT u${stxPerMint * 1000000}) ;; ${stxPerMint} STX per MINT for DAO +(define-constant MAX_NFTS_PER_TX u${maxMintsPerTx}) ;; Maximum ${maxMintsPerTx} NFTs per transaction (define-constant OWNER '${stxAddress}) ;; Collection creator -(define-constant CHA_AMOUNT u5000000) ;; 5 CHA per mint to creator +(define-constant CHA_AMOUNT (* u5 STX_PER_MINT)) ;; ${(5 * stxPerMint).toFixed(6)} CHA per mint to creator (define-constant ERR_UNAUTHORIZED (err u100)) (define-constant ERR_NOT_TOKEN_OWNER (err u101)) @@ -139,34 +141,7 @@ const generateTemplate = ({ contractAddress, totalSupply, stxAddress, descriptio ) ) -;; Mint multiple NFTs based on the count (1 to 4) -(define-private (mint-multiple (recipient principal) (count uint)) - (if (is-eq count u1) - (mint recipient) - (if (is-eq count u2) - (begin - (try! (mint recipient)) - (mint recipient) - ) - (if (is-eq count u3) - (begin - (try! (mint recipient)) - (try! (mint recipient)) - (mint recipient) - ) - (if (is-eq count u4) - (begin - (try! (mint recipient)) - (try! (mint recipient)) - (try! (mint recipient)) - (mint recipient) - ) - (err u500) ;; Invalid count - ) - ) - ) - ) -) +${generateMintMultipleFunction(maxMintsPerTx)} ;; Quest logic (define-public (tap (land-id uint) (edk-contract )) @@ -198,6 +173,43 @@ const generateTemplate = ({ contractAddress, totalSupply, stxAddress, descriptio `; } +const generateMintMultipleFunction = (maxCount: number) => ` +;; Mint multiple NFTs based on the count (1 to ${maxCount}) +(define-private (mint-multiple (recipient principal) (count uint)) + ${generateMintCases(maxCount)}`; + +const generateMintCases = (maxCount: number) => { + let cases = ''; + for (let i = 1; i <= maxCount; i++) { + if (i === 1) { + cases += `(if (is-eq count u1) (mint recipient)`; + } else { + cases += `\n (if (is-eq count u${i}) (begin ${generateMintCalls(i)})`; + } + } + cases += `\n (err u500)\n`; + for (let i = 0; i <= maxCount; i++) { + cases += ')'; + } + return cases; +}; + +const generateMintCalls = (count: number) => { + let calls = ''; + for (let i = 1; i <= count; i++) { + if (i === count) { + calls += `(mint recipient)`; + } else { + calls += `(try! (mint recipient)) `; + } + } + return calls; +}; + +function multdec(val1: number, val2: number) { + return Number(BigInt(val1 * 1000000) * BigInt(val2 * 1000000)) / 1000000 +} + const ImagePreview = ({ src }: { src: string }) => { const [isLoading, setIsLoading] = React.useState(true); const [error, setError] = React.useState(false); @@ -249,7 +261,7 @@ export default function NftTemplate({ form: parentForm, onFormChange }: any) { const handleChange = () => { const collectionName = form.getValues().collectionName - const safeName = collectionName.toLowerCase().replace(/[^a-zA-Z0-9 ]/g, "").replace(/\s+/g, "-") + const safeName = collectionName.toLowerCase().replace(/[^a-zA-Z0-9\- ]/g, "").replace(/\s+/g, "-") const contractAddress = `${stxAddress}.${safeName}` parentForm.setValue('name', collectionName) @@ -262,7 +274,7 @@ export default function NftTemplate({ form: parentForm, onFormChange }: any) { const handleSubmitCollection = async (e: React.MouseEvent) => { e.preventDefault() const { collectionName, collectionImage, description, nftItems } = form.getValues(); - const safeName = collectionName.toLowerCase().replace(/[^a-zA-Z0-9 ]/g, "").replace(/\s+/g, "-") + const safeName = collectionName.toLowerCase().replace(/[^a-zA-Z0-9\- ]/g, "").replace(/\s+/g, "-") const contractAddress = `${stxAddress}.${safeName}` // Calculate total supply @@ -323,7 +335,7 @@ export default function NftTemplate({ form: parentForm, onFormChange }: any) { useEffect(() => { const collectionName = form.getValues().collectionName - const safeName = collectionName.toLowerCase().replace(/[^a-zA-Z0-9 ]/g, "").replace(/\s+/g, "-") + const safeName = collectionName.toLowerCase().replace(/[^a-zA-Z0-9\- ]/g, "").replace(/\s+/g, "-") const contractAddress = `${stxAddress}.${safeName}` loadExistingCollection(contractAddress) }, [watcher]) @@ -445,27 +457,40 @@ export default function NftTemplate({ form: parentForm, onFormChange }: any) { name={`energyRequired`} render={({ field }) => ( - Energy Required per NFT Minted + Energy Required to Mint - + + + + + )} + /> + ( + + Cost to Mint (STX) + + + + + + )} + /> + ( + + Maximum Mints per Tx + + )} /> - {/* ( - - Amount - - - - - - )} - /> */}
{/* + + + {!isMintedOut && stxAddress && + + } + + {'quest-background-image'} +
+ + + + + ); +} \ No newline at end of file diff --git a/pages/quests/index.tsx b/pages/quests/index.tsx index e10188b5..0a711a98 100644 --- a/pages/quests/index.tsx +++ b/pages/quests/index.tsx @@ -21,6 +21,7 @@ import mooningSharkIcon from '@public/quests/mooning-shark/mooningshark-icon.jpe import mooningSharkCard from '@public/quests/mooning-shark/mooning-shark-card.png' import krakenLottoIcon from '@public/quests/raven-raffle/ticket.png' import krakenLottoCard from '@public/quests/raven-raffle/kraken-lotto.png' +import pixelRozar from '@public/quests/pixel-rozar/pixel-rozar.png' export const getStaticProps: GetStaticProps = async () => { // get all quests from db @@ -62,6 +63,13 @@ export const getStaticProps: GetStaticProps = async () => { image: krakenLottoIcon, cardImage: krakenLottoCard, }, + { + name: `Mint a Pixel Rozar`, + description: "Collect a bunch of completely useless stickers.", + ca: "SP2ZNGJ85ENDY6QRHQ5P2D4FXKGZWCKTB2T0Z55KS.pixel-rozar", + image: pixelRozar, + cardImage: 'https://media.tenor.com/qwMy5HS9LIYAAAAM/funny-corgi-lol-moment.gif', + }, { name: `King of the Hill`, description: "Team up with your community to claim the hill.", diff --git a/public/quests/pixel-rozar/pixel-rozar.png b/public/quests/pixel-rozar/pixel-rozar.png new file mode 100644 index 00000000..6a53e818 Binary files /dev/null and b/public/quests/pixel-rozar/pixel-rozar.png differ