Skip to content

Commit

Permalink
feat(docs): mint ctf completion nft (#4521)
Browse files Browse the repository at this point in the history
* Mint CTF completion NFT
  • Loading branch information
vivekjain23 authored Jan 16, 2025
1 parent 0e58f67 commit ffd581a
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 40 deletions.
2 changes: 1 addition & 1 deletion docs/content/developer/iota-move-ctf/challenge_1.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ Good luck in capturing your first flag!



<ChallengeVerifier expectedObjectType="0xed1bbeb067ea89b70859641557700997a39bf749b5eedf91e221d56a5d961622::checkin::Flag" />
<ChallengeVerifier challengeNumber="1" nftName="Checkin" expectedObjectType="0xed1bbeb067ea89b70859641557700997a39bf749b5eedf91e221d56a5d961622::checkin::Flag" />
2 changes: 1 addition & 1 deletion docs/content/developer/iota-move-ctf/challenge_2.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ Good luck in capturing your second flag!



<ChallengeVerifier expectedObjectType="0x2d902cb948748fd2b92ff98e5d0fd46a9ceb4b7501050ef8513b9bc60f515ef8::luckynumber::Flag" />
<ChallengeVerifier expectedObjectType="0x2d902cb948748fd2b92ff98e5d0fd46a9ceb4b7501050ef8513b9bc60f515ef8::luckynumber::Flag" challengeNumber="2" nftName="Lucky_Number"/>
2 changes: 1 addition & 1 deletion docs/content/developer/iota-move-ctf/challenge_3.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ Good luck in capturing your third flag!



<ChallengeVerifier expectedObjectType="0x871d4332aeb888fafa0c90280a3b2d301213e3352c11493b2ac59002264c2d20::mintcoin::Flag" />
<ChallengeVerifier expectedObjectType="0x871d4332aeb888fafa0c90280a3b2d301213e3352c11493b2ac59002264c2d20::mintcoin::Flag" challengeNumber="3" nftName="MintCoin_Mechanics"/>
2 changes: 1 addition & 1 deletion docs/content/developer/iota-move-ctf/challenge_4.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,4 @@ Good luck in capturing your fourth flag!
Under `Deployed Contract Addresses`, you can find the addresses of the package as well as the `Vault`. Carefully check what the constraints are for the `get_flag` function to work, as it has some assertions that need to be met.
:::

<ChallengeVerifier expectedObjectType="0x817e64f33b784f0c4a3d2cd18f62cc4409bc869efa715f29e93eff52343fb7b2::airdrop::Flag" />
<ChallengeVerifier expectedObjectType="0x817e64f33b784f0c4a3d2cd18f62cc4409bc869efa715f29e93eff52343fb7b2::airdrop::Flag" challengeNumber="4" nftName="Airdrop"/>
2 changes: 1 addition & 1 deletion docs/content/developer/iota-move-ctf/challenge_5.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ After taking a look at the challenge's usage of [bcs::to_bytes](../../references
Good luck in capturing your fifth flag!


<ChallengeVerifier expectedObjectType="0xdd29ddb70eec2828bf8375c9bb3e4c3546f94d9090113fc760adce8010d69762::pizza::Flag" />
<ChallengeVerifier expectedObjectType="0xdd29ddb70eec2828bf8375c9bb3e4c3546f94d9090113fc760adce8010d69762::pizza::Flag" number="5" nftName="Perfect_Pizza"/>
2 changes: 1 addition & 1 deletion docs/content/developer/iota-move-ctf/challenge_6.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ Good luck in capturing your sixth flag!
Make sure you recycle enough pizza boxes!
:::

<ChallengeVerifier expectedObjectType="0x5b3571ccaf942310691ca034fbfa381ccd724029396e329910a789b1d25ece3d::recycle::Flag" />
<ChallengeVerifier expectedObjectType="0x5b3571ccaf942310691ca034fbfa381ccd724029396e329910a789b1d25ece3d::recycle::Flag" challengeNumber="6" nftName="Go_Recycle"/>
2 changes: 1 addition & 1 deletion docs/content/developer/iota-move-ctf/challenge_7.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ Good luck in capturing your seventh flag!



<ChallengeVerifier expectedObjectType="0x2fce22869e453ec5bb6de2b3bee4cb94b2c3605abad9e9bbda477a75306bef2c::ptb::Flag" />
<ChallengeVerifier expectedObjectType="0x2fce22869e453ec5bb6de2b3bee4cb94b2c3605abad9e9bbda477a75306bef2c::ptb::Flag" challengeNumber="7" nftName="PTBs"/>
2 changes: 1 addition & 1 deletion docs/content/developer/iota-move-ctf/challenge_8.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,4 @@ The DEX programmer pulled an all-nighter before writing the flash loan mechanism



<ChallengeVerifier expectedObjectType="0xfd9284dd49737957297ebb10a9bbf73964453696c037b9e59f0fb4d23fc13aee::vault::Flag" />
<ChallengeVerifier expectedObjectType="0xfd9284dd49737957297ebb10a9bbf73964453696c037b9e59f0fb4d23fc13aee::vault::Flag" challengeNumber="8" nftName="Flash"/>
76 changes: 47 additions & 29 deletions docs/site/src/components/CTF/ctf-verifier.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,64 @@
import React, { useState, useMemo } from 'react';
import {
IotaClientProvider,
useSignAndExecuteTransaction,
WalletProvider,
} from '@iota/dapp-kit';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { getFullnodeUrl, IotaClient } from '@iota/iota-sdk/client';
import { getFullnodeUrl } from '@iota/iota-sdk/client';
import clsx from 'clsx';
import { useConnectWallet, useWallets } from '@iota/dapp-kit';
import Popup from './popup';
import { handleChallengeSubmit } from "../../utils/ctf-utils"

// Define props interface
interface ChallengeVerifierProps {
expectedObjectType: string; // Prop for the expected Object Type
expectedObjectType: string;
nftName: string;
challengeNumber: string
}

// Define network configurations
const NETWORKS = {
testnet: { url: getFullnodeUrl('testnet') },
};

// Main ChallengeVerifier component
const ChallengeVerifier: React.FC<ChallengeVerifierProps> = ({ expectedObjectType }) => {
const ChallengeVerifier: React.FC<ChallengeVerifierProps> = ({
expectedObjectType,
nftName,
challengeNumber,
}) => {
const [inputText, setInputText] = useState('');
const [coins, setCoins] = useState<string | null>(null);
const [showPopup, setShowPopup] = useState<boolean>(false);
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const [error, setError] = useState<{
status: 'success' | 'error';
description: string;
title: string;
}>({
status: 'success',
description: '',
title: '',
});

const wallets = useWallets();
const { mutate } = useConnectWallet();
const { mutate: signAndExecuteTransaction} = useSignAndExecuteTransaction();
const [digest,setDigest] = useState<string>('');
const handleSubmit = async () => {
setLoading(true);
setError('');
setCoins(null);

try {
const client = new IotaClient({ url: NETWORKS.testnet.url });
const result = await client.getObject({ id: inputText, options: { showType: true } });

const message = result.data.type === expectedObjectType
? 'Congratulations! You have successfully completed this level!'
: 'Invalid Flag Object Id. Please try again.';

setCoins(message);
} catch (err: any) {
setError(err.message || 'An error occurred. Please try again.');
} finally {
setLoading(false);
}
await handleChallengeSubmit({
inputText,
expectedObjectType,
nftName,
challengeNumber,
wallets,
mutate,
signAndExecuteTransaction,
setLoading,
setCoins,
setError,
setShowPopup,
setDigest
});
};

return (
Expand All @@ -57,7 +73,7 @@ const ChallengeVerifier: React.FC<ChallengeVerifierProps> = ({ expectedObjectTyp
placeholder="Enter Flag Object Id"
className="input-field"
/>
{<p className={`text-red-500 mb-0 mt-1 text-sm ${error ? 'visible' : 'invisible'}`}>{error}</p>}
{<p className={`text-red-500 mb-0 mt-1 text-sm ${error.description!=='' ? 'visible' : 'invisible'}`}>{error.description}</p>}
<button
onClick={handleSubmit}
className={`${clsx("button", { "button-disabled": inputText=='' || loading })} min-w-28 mt-4`}
Expand All @@ -71,7 +87,6 @@ const ChallengeVerifier: React.FC<ChallengeVerifierProps> = ({ expectedObjectTyp
);
};

// Higher-order function to provide necessary context
const withProviders = (Component: React.FC<ChallengeVerifierProps>) => {
return ({ expectedObjectType }: ChallengeVerifierProps) => {
if (typeof window === 'undefined') {
Expand All @@ -84,13 +99,16 @@ const withProviders = (Component: React.FC<ChallengeVerifierProps>) => {
<QueryClientProvider client={queryClient}>
<IotaClientProvider networks={NETWORKS}>
<WalletProvider>
<Component expectedObjectType={expectedObjectType} />
<Component
expectedObjectType={expectedObjectType}
challengeNumber="1"
nftName="Checkin"
/>
</WalletProvider>
</IotaClientProvider>
</QueryClientProvider>
);
};
};

// Export the component wrapped in providers
export default withProviders(ChallengeVerifier);
17 changes: 15 additions & 2 deletions docs/site/src/components/CTF/popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ interface PropTypes {
description: string,
title: string,
setShowPopup: React.Dispatch<React.SetStateAction<boolean>>,
showPopup: boolean
showPopup: boolean,
digest:string
}

const Popup = ({ status, description, title, setShowPopup, showPopup }: PropTypes) => {
const Popup = ({ status, description, title, setShowPopup, showPopup,digest }: PropTypes) => {
return (
<div className="relative z-10" aria-labelledby="modal-title" role="dialog" aria-modal="true">
<div className="fixed inset-0 dark:bg-gray-500/75 bg-gray-200/75 transition-opacity" aria-hidden="true"></div>
Expand All @@ -33,6 +34,15 @@ const Popup = ({ status, description, title, setShowPopup, showPopup }: PropType
{description}
</p>
<div>
<button
type='button'
className="inline-flex cursor-pointer w-full border-none justify-center rounded-md bg-[#017195] px-4 py-2 text-sm my-2">
<a
target='blank'
href={`https://explorer.rebased.iota.org/txblock/${digest}?network=testnet`}
className='font-semibold text-white hover:text-black'
>Check transaction on explorer</a>
</button>
<button
type="button"
className="inline-flex cursor-pointer w-full border-none justify-center rounded-md bg-[#017195] px-4 py-2 text-sm font-semibold text-white hover:text-black"
Expand All @@ -41,6 +51,9 @@ const Popup = ({ status, description, title, setShowPopup, showPopup }: PropType
Close
</button>
</div>
<div className='text-black'>
<p className='text-xs text-gray-700 mt-4'>Note: Transactions may take some time to appear on the explorer.</p>
</div>
</div>
</div>
</div>
Expand Down
4 changes: 3 additions & 1 deletion docs/site/src/utils/ctf-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const handleChallengeSubmit = async ({
setCoins,
setError,
setShowPopup,
setDigest
}: any) => {
setLoading(true);
setError({
Expand Down Expand Up @@ -57,6 +58,7 @@ export const handleChallengeSubmit = async ({
{
onSuccess: ({ digest }: any) => {
client.waitForTransaction({ digest, options: { showEffects: true } }).then(() => {
setDigest(digest)
setError({
status: 'success',
description: 'An NFT reward was minted and transferred to your IOTA wallet address for completing the challenge.',
Expand Down Expand Up @@ -178,4 +180,4 @@ export const handleMintLeapFrogSubmit = async ({
});
setLoading(false);
}
};
};

0 comments on commit ffd581a

Please sign in to comment.