From ce0045082f256117917f50a7976d444964cc9005 Mon Sep 17 00:00:00 2001 From: Vivek Jain Date: Tue, 17 Dec 2024 19:52:23 +0530 Subject: [PATCH 1/7] Add ctf nft mint logic --- docs/site/src/components/CTF/ctf-verifier.tsx | 98 ++++++++++++------- 1 file changed, 62 insertions(+), 36 deletions(-) diff --git a/docs/site/src/components/CTF/ctf-verifier.tsx b/docs/site/src/components/CTF/ctf-verifier.tsx index d6ee34965ca..cefda2f1f19 100644 --- a/docs/site/src/components/CTF/ctf-verifier.tsx +++ b/docs/site/src/components/CTF/ctf-verifier.tsx @@ -1,52 +1,67 @@ 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 = ({ expectedObjectType }) => { +const ChallengeVerifier: React.FC = ({ + expectedObjectType, + nftName, + challengeNumber, +}) => { const [inputText, setInputText] = useState(''); const [coins, setCoins] = useState(null); + const [showPopup, setShowPopup] = useState(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 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.'; + const wallets = useWallets(); + const { mutate } = useConnectWallet(); + const { mutate: signAndExecuteTransaction } = useSignAndExecuteTransaction(); - setCoins(message); - } catch (err: any) { - setError(err.message || 'An error occurred. Please try again.'); - } finally { - setLoading(false); - } + const handleSubmit = async () => { + await handleChallengeSubmit({ + inputText, + expectedObjectType, + nftName, + challengeNumber, + wallets, + mutate, + signAndExecuteTransaction, + setLoading, + setCoins, + setError, + setShowPopup, + }); }; return ( -
+
= ({ expectedObjectTyp placeholder="Enter Flag Object Id" className="input-field mr-2" /> - - {error &&

{error}

} + {error.status === 'error' &&

{error.description}

} + + {coins && !loading &&
{coins}
} - {coins && ( -
-

Result

-
{JSON.stringify(coins, null, 2)}
-
+ {showPopup && ( + )}
); }; -// Higher-order function to provide necessary context const withProviders = (Component: React.FC) => { return ({ expectedObjectType }: ChallengeVerifierProps) => { if (typeof window === 'undefined') { @@ -83,7 +106,11 @@ const withProviders = (Component: React.FC) => { - + @@ -91,5 +118,4 @@ const withProviders = (Component: React.FC) => { }; }; -// Export the component wrapped in providers export default withProviders(ChallengeVerifier); \ No newline at end of file From 9d6129e807a2ffafd76da87db5604f58881ba985 Mon Sep 17 00:00:00 2001 From: Vivek Jain Date: Tue, 17 Dec 2024 19:52:36 +0530 Subject: [PATCH 2/7] Add ctf nft mint util --- docs/site/src/utils/ctf-utils.ts | 95 ++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 docs/site/src/utils/ctf-utils.ts diff --git a/docs/site/src/utils/ctf-utils.ts b/docs/site/src/utils/ctf-utils.ts new file mode 100644 index 00000000000..959e229c47b --- /dev/null +++ b/docs/site/src/utils/ctf-utils.ts @@ -0,0 +1,95 @@ +import { getFullnodeUrl, IotaClient } from '@iota/iota-sdk/client'; +import { Transaction } from '@iota/iota-sdk/transactions'; + +export const handleChallengeSubmit = async ({ + inputText, + expectedObjectType, + nftName, + challengeNumber, + wallets, + mutate, + signAndExecuteTransaction, + setLoading, + setCoins, + setError, + setShowPopup, +}: any) => { + setLoading(true); + setError({ + status: 'success', + description: '', + title: '', + }); + setCoins(null); + + try { + const NETWORKS = { + testnet: { url: getFullnodeUrl('testnet') }, + }; + + const client = new IotaClient({ url: NETWORKS.testnet.url }); + const result = await client.getObject({ id: inputText, options: { showType: true } }); + + if (result.data.type === expectedObjectType) { + const message = 'Congratulations! You have successfully completed this level!'; + const wallet = wallets[0]; + + mutate( + { wallet }, + { + onSuccess: () => { + const tx = () => { + const tx = new Transaction(); + const arg0 = new TextEncoder().encode(`Challenge_${challengeNumber}_${nftName}_NFT`); + const arg1 = new TextEncoder().encode('NFT Reward for completing challenge'); + tx.setGasBudget(50000000); + tx.moveCall({ + target: `0x6e4d9fbc71192a1220bf836672f16022b25cdc8548acaa7a9fd19510d34391e9::testnet_nft::mint_to_sender`, + arguments: [tx.pure.vector('u8', arg0), tx.pure.vector('u8', arg1)], + }); + return tx; + }; + + signAndExecuteTransaction( + { + transaction: tx(), + }, + { + onSuccess: ({ digest }: any) => { + client.waitForTransaction({ digest, options: { showEffects: true } }).then(() => { + setError({ + status: 'success', + description: 'An NFT reward is minted to your IOTA wallet address upon completing the challenge.', + title: 'NFT Minted', + }); + setCoins(message); + setLoading(false); + setShowPopup(true); + }); + }, + onError: (error: any) => { + setError({ + status: 'error', + description: `Failed to execute transaction : ${error}`, + title: 'Submission failed', + }); + setLoading(false); + setShowPopup(true); + }, + } + ); + }, + } + ); + } else { + setCoins('Invalid Flag Object Id. Please try again.'); + } + } catch (err: any) { + setError({ + status: 'error', + description: err.message || 'An error occurred. Please try again.', + title: 'Submission failed', + }); + setLoading(false); + } +}; From ca79412b87c28f8ba7b25a0bc8a817385acbc16e Mon Sep 17 00:00:00 2001 From: Vivek Jain Date: Tue, 17 Dec 2024 19:53:01 +0530 Subject: [PATCH 3/7] Add popup --- docs/site/src/components/CTF/popup.tsx | 53 ++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 docs/site/src/components/CTF/popup.tsx diff --git a/docs/site/src/components/CTF/popup.tsx b/docs/site/src/components/CTF/popup.tsx new file mode 100644 index 00000000000..b8eb42e14b1 --- /dev/null +++ b/docs/site/src/components/CTF/popup.tsx @@ -0,0 +1,53 @@ +import React from 'react' + +interface PropTypes { + status: 'success' | 'error', + description: string, + title: string, + setShowPopup: React.Dispatch>, + showPopup: boolean +} + +const Popup = ({ status, description, title, setShowPopup, showPopup }: PropTypes) => { + return ( +
+ +
+
+
+
+
+ +
+
+ +
+ +

+ {description} +

+
+ +
+
+
+
+
+
+ + ) +} + +export default Popup \ No newline at end of file From 43082fc2fcff35b3ba4bac0339c5d96b4e60c2ad Mon Sep 17 00:00:00 2001 From: Vivek Jain Date: Tue, 17 Dec 2024 19:53:22 +0530 Subject: [PATCH 4/7] Add nft mint component to challenges --- docs/content/developer/iota-move-ctf/challenge_1.mdx | 3 ++- docs/content/developer/iota-move-ctf/challenge_2.mdx | 2 +- docs/content/developer/iota-move-ctf/challenge_3.mdx | 2 +- docs/content/developer/iota-move-ctf/challenge_4.mdx | 2 +- docs/content/developer/iota-move-ctf/challenge_5.mdx | 2 +- docs/content/developer/iota-move-ctf/challenge_6.mdx | 2 +- docs/content/developer/iota-move-ctf/challenge_7.mdx | 2 +- docs/content/developer/iota-move-ctf/challenge_8.mdx | 2 +- 8 files changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/content/developer/iota-move-ctf/challenge_1.mdx b/docs/content/developer/iota-move-ctf/challenge_1.mdx index 074825eb770..5f192b0363a 100644 --- a/docs/content/developer/iota-move-ctf/challenge_1.mdx +++ b/docs/content/developer/iota-move-ctf/challenge_1.mdx @@ -1,5 +1,6 @@ import ChallengeVerifier from '@site/src/components/CTF/ctf-verifier'; +import Popup from '@site/src/components/CTF/popup'; # Challenge 1: Checkin @@ -35,4 +36,4 @@ Good luck in capturing your first flag! - \ No newline at end of file + \ No newline at end of file diff --git a/docs/content/developer/iota-move-ctf/challenge_2.mdx b/docs/content/developer/iota-move-ctf/challenge_2.mdx index b00a5bd9983..046822df864 100644 --- a/docs/content/developer/iota-move-ctf/challenge_2.mdx +++ b/docs/content/developer/iota-move-ctf/challenge_2.mdx @@ -42,4 +42,4 @@ Good luck in capturing your second flag! - \ No newline at end of file + \ No newline at end of file diff --git a/docs/content/developer/iota-move-ctf/challenge_3.mdx b/docs/content/developer/iota-move-ctf/challenge_3.mdx index 172ca441ff7..5627115e415 100644 --- a/docs/content/developer/iota-move-ctf/challenge_3.mdx +++ b/docs/content/developer/iota-move-ctf/challenge_3.mdx @@ -45,4 +45,4 @@ Good luck in capturing your third flag! - \ No newline at end of file + \ No newline at end of file diff --git a/docs/content/developer/iota-move-ctf/challenge_4.mdx b/docs/content/developer/iota-move-ctf/challenge_4.mdx index 511a948e5cc..66fe23e263c 100644 --- a/docs/content/developer/iota-move-ctf/challenge_4.mdx +++ b/docs/content/developer/iota-move-ctf/challenge_4.mdx @@ -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. ::: - \ No newline at end of file + \ No newline at end of file diff --git a/docs/content/developer/iota-move-ctf/challenge_5.mdx b/docs/content/developer/iota-move-ctf/challenge_5.mdx index 5404f6f582f..34975a77e06 100644 --- a/docs/content/developer/iota-move-ctf/challenge_5.mdx +++ b/docs/content/developer/iota-move-ctf/challenge_5.mdx @@ -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! - \ No newline at end of file + \ No newline at end of file diff --git a/docs/content/developer/iota-move-ctf/challenge_6.mdx b/docs/content/developer/iota-move-ctf/challenge_6.mdx index ffade8fdfe7..2c8d253a92c 100644 --- a/docs/content/developer/iota-move-ctf/challenge_6.mdx +++ b/docs/content/developer/iota-move-ctf/challenge_6.mdx @@ -44,4 +44,4 @@ Good luck in capturing your sixth flag! Make sure you recycle enough pizza boxes! ::: - \ No newline at end of file + \ No newline at end of file diff --git a/docs/content/developer/iota-move-ctf/challenge_7.mdx b/docs/content/developer/iota-move-ctf/challenge_7.mdx index a6ba9de785a..62b2900bbd4 100644 --- a/docs/content/developer/iota-move-ctf/challenge_7.mdx +++ b/docs/content/developer/iota-move-ctf/challenge_7.mdx @@ -35,4 +35,4 @@ Good luck in capturing your seventh flag! - \ No newline at end of file + \ No newline at end of file diff --git a/docs/content/developer/iota-move-ctf/challenge_8.mdx b/docs/content/developer/iota-move-ctf/challenge_8.mdx index d8015702836..0417f08574a 100644 --- a/docs/content/developer/iota-move-ctf/challenge_8.mdx +++ b/docs/content/developer/iota-move-ctf/challenge_8.mdx @@ -53,4 +53,4 @@ The DEX programmer pulled an all-nighter before writing the flash loan mechanism - \ No newline at end of file + \ No newline at end of file From 0de26538285364ad2da3e1726c1b54ae86621678 Mon Sep 17 00:00:00 2001 From: Vivek Jain Date: Tue, 17 Dec 2024 20:17:03 +0530 Subject: [PATCH 5/7] Update nft package address --- docs/site/src/utils/ctf-utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/site/src/utils/ctf-utils.ts b/docs/site/src/utils/ctf-utils.ts index 959e229c47b..c4071f35470 100644 --- a/docs/site/src/utils/ctf-utils.ts +++ b/docs/site/src/utils/ctf-utils.ts @@ -26,7 +26,7 @@ export const handleChallengeSubmit = async ({ const NETWORKS = { testnet: { url: getFullnodeUrl('testnet') }, }; - + const NFTPackageAddress = "0xedeca9d6897cf86917e45f5c5cd596da48a5c4e3e1d9425aee42bed37c9ee44d" const client = new IotaClient({ url: NETWORKS.testnet.url }); const result = await client.getObject({ id: inputText, options: { showType: true } }); @@ -44,7 +44,7 @@ export const handleChallengeSubmit = async ({ const arg1 = new TextEncoder().encode('NFT Reward for completing challenge'); tx.setGasBudget(50000000); tx.moveCall({ - target: `0x6e4d9fbc71192a1220bf836672f16022b25cdc8548acaa7a9fd19510d34391e9::testnet_nft::mint_to_sender`, + target: `${NFTPackageAddress}::ctf_nft::mint_to_sender`, arguments: [tx.pure.vector('u8', arg0), tx.pure.vector('u8', arg1)], }); return tx; From 84715d0b8bf018163f1d654ec89c56346542a4b6 Mon Sep 17 00:00:00 2001 From: Vivek Jain Date: Tue, 17 Dec 2024 20:36:39 +0530 Subject: [PATCH 6/7] Update nft package address --- docs/site/src/utils/ctf-utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/site/src/utils/ctf-utils.ts b/docs/site/src/utils/ctf-utils.ts index c4071f35470..f723be1a38c 100644 --- a/docs/site/src/utils/ctf-utils.ts +++ b/docs/site/src/utils/ctf-utils.ts @@ -26,7 +26,7 @@ export const handleChallengeSubmit = async ({ const NETWORKS = { testnet: { url: getFullnodeUrl('testnet') }, }; - const NFTPackageAddress = "0xedeca9d6897cf86917e45f5c5cd596da48a5c4e3e1d9425aee42bed37c9ee44d" + const NFTPackageAddress = "0x61b31360fb89cae585b8cb593edde20dfc690a3f260c12693bbb8b33ebf4707d" const client = new IotaClient({ url: NETWORKS.testnet.url }); const result = await client.getObject({ id: inputText, options: { showType: true } }); @@ -44,7 +44,7 @@ export const handleChallengeSubmit = async ({ const arg1 = new TextEncoder().encode('NFT Reward for completing challenge'); tx.setGasBudget(50000000); tx.moveCall({ - target: `${NFTPackageAddress}::ctf_nft::mint_to_sender`, + target: `${NFTPackageAddress}::CTF_NFT::mint_to_sender`, arguments: [tx.pure.vector('u8', arg0), tx.pure.vector('u8', arg1)], }); return tx; From 92f1b02fdd0996e858253959a193dd8bb9280ce9 Mon Sep 17 00:00:00 2001 From: Vivek Jain Date: Wed, 18 Dec 2024 11:28:49 +0530 Subject: [PATCH 7/7] Fix linting --- docs/content/developer/iota-move-ctf/challenge_1.mdx | 1 - docs/content/developer/iota-move-ctf/challenge_5.mdx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/content/developer/iota-move-ctf/challenge_1.mdx b/docs/content/developer/iota-move-ctf/challenge_1.mdx index 5f192b0363a..141a2791a6e 100644 --- a/docs/content/developer/iota-move-ctf/challenge_1.mdx +++ b/docs/content/developer/iota-move-ctf/challenge_1.mdx @@ -1,6 +1,5 @@ import ChallengeVerifier from '@site/src/components/CTF/ctf-verifier'; -import Popup from '@site/src/components/CTF/popup'; # Challenge 1: Checkin diff --git a/docs/content/developer/iota-move-ctf/challenge_5.mdx b/docs/content/developer/iota-move-ctf/challenge_5.mdx index 34975a77e06..bfe79236979 100644 --- a/docs/content/developer/iota-move-ctf/challenge_5.mdx +++ b/docs/content/developer/iota-move-ctf/challenge_5.mdx @@ -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! - \ No newline at end of file + \ No newline at end of file