diff --git a/cspell-config/cspell-misc.txt b/cspell-config/cspell-misc.txt index 80a1e34..28f192e 100644 --- a/cspell-config/cspell-misc.txt +++ b/cspell-config/cspell-misc.txt @@ -27,3 +27,4 @@ usdc // examples/nft-quest Fren fren +nfts diff --git a/examples/nft-quest/components/zk/panel/section.vue b/examples/nft-quest/components/zk/panel/section.vue index 64521c1..54627fc 100644 --- a/examples/nft-quest/components/zk/panel/section.vue +++ b/examples/nft-quest/components/zk/panel/section.vue @@ -32,7 +32,7 @@ const props = defineProps<{ }>(); const headerUI = twMerge( - "px-4 flex items-center bg-neutral-100 rounded-t-zk py-2 dark:bg-neutral-950", + "p-4 flex items-center bg-neutral-100 rounded-t-zk dark:bg-neutral-950", props.ui?.header, ); @@ -51,7 +51,7 @@ const bodyUI = computed(() => { }); const footerUI = twMerge( - "bg-neutral-100 rounded-b-zk p-2 px-4 dark:bg-neutral-950", + "flex justify-center bg-neutral-100 rounded-b-zk p-2 px-4 dark:bg-neutral-950", props.ui?.footer, ); diff --git a/packages/auth-server/abi/ZeekNFTQuest.ts b/packages/auth-server/abi/ZeekNFTQuest.ts new file mode 100644 index 0000000..162d1d2 --- /dev/null +++ b/packages/auth-server/abi/ZeekNFTQuest.ts @@ -0,0 +1,427 @@ +export const ZeekNftQuestAbi = [ + { + inputs: [ + { + internalType: "string", + name: "baseTokenURI", + type: "string", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "approved", + type: "address", + }, + { + indexed: true, + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "operator", + type: "address", + }, + { + indexed: false, + internalType: "bool", + name: "approved", + type: "bool", + }, + ], + name: "ApprovalForAll", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "previousOwner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "OwnershipTransferred", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "to", + type: "address", + }, + { + indexed: true, + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "approve", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "getApproved", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "operator", + type: "address", + }, + ], + name: "isApprovedForAll", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "to", + type: "address", + }, + ], + name: "mint", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "ownerOf", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "safeTransferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + internalType: "bytes", + name: "data", + type: "bytes", + }, + ], + name: "safeTransferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "operator", + type: "address", + }, + { + internalType: "bool", + name: "approved", + type: "bool", + }, + ], + name: "setApprovalForAll", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes4", + name: "interfaceId", + type: "bytes4", + }, + ], + name: "supportsInterface", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "tokenURI", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "tokenURI", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "transferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/packages/auth-server/components/dashboard/assets.vue b/packages/auth-server/components/dashboard/assets.vue index a59ebce..eb37f76 100644 --- a/packages/auth-server/components/dashboard/assets.vue +++ b/packages/auth-server/components/dashboard/assets.vue @@ -1,72 +1,73 @@ diff --git a/packages/auth-server/components/nft/zeek-nft-quest.vue b/packages/auth-server/components/nft/zeek-nft-quest.vue new file mode 100644 index 0000000..ef0560a --- /dev/null +++ b/packages/auth-server/components/nft/zeek-nft-quest.vue @@ -0,0 +1,80 @@ + + + diff --git a/packages/auth-server/composables/useNftMetadata.ts b/packages/auth-server/composables/useNftMetadata.ts new file mode 100644 index 0000000..1b28b1b --- /dev/null +++ b/packages/auth-server/composables/useNftMetadata.ts @@ -0,0 +1,23 @@ +import type { Abi, Address } from "viem"; + +export const useNftMetadata = async ({ + chainId, + address, + abi, +}: { chainId?: SupportedChainId; address: Address; abi: Abi }) => { + const { getPublicClient, defaultChain } = useClientStore(); + + const client = getPublicClient({ chainId: chainId ?? defaultChain.id }); + const res = await client.readContract({ + address: address, + abi, + functionName: "tokenURI", + }); + + return await useFetch<{ animation_url: string; background_color: string; description: string; image: string }>(res, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); +}; diff --git a/packages/auth-server/nuxt.config.ts b/packages/auth-server/nuxt.config.ts index 4c4cbe4..9b3ac8b 100644 --- a/packages/auth-server/nuxt.config.ts +++ b/packages/auth-server/nuxt.config.ts @@ -1,5 +1,5 @@ import { defineNuxtConfig } from "nuxt/config"; -import { zksyncInMemoryNode } from "viem/chains"; +import { zksyncInMemoryNode, zksyncSepoliaTestnet } from "viem/chains"; // https://nuxt.com/docs/api/configuration/nuxt-config export default defineNuxtConfig({ @@ -55,6 +55,12 @@ export default defineNuxtConfig({ runtimeConfig: { public: { chainId: parseInt(process.env.NUXT_PUBLIC_DEFAULT_CHAIN_ID || "") || zksyncInMemoryNode.id, + [zksyncInMemoryNode.id]: { + nftQuestAddress: "", + }, + [zksyncSepoliaTestnet.id]: { + nftQuestAddress: "0x4D533d3B20b50b57268f189F93bFaf8B39c36AB6", + }, }, }, }); diff --git a/packages/auth-server/pages/dashboard/index.vue b/packages/auth-server/pages/dashboard/index.vue index fcf9b72..3317f06 100644 --- a/packages/auth-server/pages/dashboard/index.vue +++ b/packages/auth-server/pages/dashboard/index.vue @@ -10,7 +10,11 @@ - +
+ + + +