diff --git a/.pnp.cjs b/.pnp.cjs index afb7e12..2bf0c06 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -36,6 +36,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@next/eslint-plugin-next", "npm:13.0.5"],\ ["@sentry/nextjs", "virtual:4b77e00d446246df1ed27001550885fbf1b51be18c660c1b5c357d3d763078ecef2a676194291a120f149b87573081e5af0621dc83cf1f83383639f39ac133c7#npm:7.27.0"],\ ["@svgr/webpack", "npm:6.5.1"],\ + ["@types/cors", "npm:2.8.13"],\ ["@types/eslint", "npm:8.4.10"],\ ["@types/node", "npm:18.11.9"],\ ["@types/react", "npm:18.0.25"],\ @@ -47,6 +48,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@typescript-eslint/parser", "virtual:4b77e00d446246df1ed27001550885fbf1b51be18c660c1b5c357d3d763078ecef2a676194291a120f149b87573081e5af0621dc83cf1f83383639f39ac133c7#npm:5.45.0"],\ ["axios", "npm:0.27.2"],\ ["buffer", "npm:6.0.3"],\ + ["cors", "npm:2.8.5"],\ ["crypto", "npm:1.0.1"],\ ["eslint", "npm:8.28.0"],\ ["eslint-config-next", "virtual:4b77e00d446246df1ed27001550885fbf1b51be18c660c1b5c357d3d763078ecef2a676194291a120f149b87573081e5af0621dc83cf1f83383639f39ac133c7#npm:13.0.5"],\ @@ -62,6 +64,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["next", "virtual:4b77e00d446246df1ed27001550885fbf1b51be18c660c1b5c357d3d763078ecef2a676194291a120f149b87573081e5af0621dc83cf1f83383639f39ac133c7#npm:13.0.5"],\ ["prettier", "npm:2.8.0"],\ ["react", "npm:18.2.0"],\ + ["react-countup", "virtual:4b77e00d446246df1ed27001550885fbf1b51be18c660c1b5c357d3d763078ecef2a676194291a120f149b87573081e5af0621dc83cf1f83383639f39ac133c7#npm:6.4.0"],\ ["react-dom", "virtual:4b77e00d446246df1ed27001550885fbf1b51be18c660c1b5c357d3d763078ecef2a676194291a120f149b87573081e5af0621dc83cf1f83383639f39ac133c7#npm:18.2.0"],\ ["react-is", "npm:18.2.0"],\ ["react-modal", "virtual:4b77e00d446246df1ed27001550885fbf1b51be18c660c1b5c357d3d763078ecef2a676194291a120f149b87573081e5af0621dc83cf1f83383639f39ac133c7#npm:3.16.1"],\ @@ -3292,6 +3295,34 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["@rollup/plugin-babel", [\ + ["npm:6.0.3", {\ + "packageLocation": "./.yarn/cache/@rollup-plugin-babel-npm-6.0.3-1259d28dd2-412c1c3bb5.zip/node_modules/@rollup/plugin-babel/",\ + "packageDependencies": [\ + ["@rollup/plugin-babel", "npm:6.0.3"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:9555373101f58738ea803ff9e79b0d8b52a66e88c21dac99d127fd080df7e60c5efb4c82f30a042556261bfb95e0c5292626cc000800b004d622753bbf9e02e5#npm:6.0.3", {\ + "packageLocation": "./.yarn/__virtual__/@rollup-plugin-babel-virtual-082525a879/0/cache/@rollup-plugin-babel-npm-6.0.3-1259d28dd2-412c1c3bb5.zip/node_modules/@rollup/plugin-babel/",\ + "packageDependencies": [\ + ["@rollup/plugin-babel", "virtual:9555373101f58738ea803ff9e79b0d8b52a66e88c21dac99d127fd080df7e60c5efb4c82f30a042556261bfb95e0c5292626cc000800b004d622753bbf9e02e5#npm:6.0.3"],\ + ["@babel/core", null],\ + ["@babel/helper-module-imports", "npm:7.18.6"],\ + ["@rollup/pluginutils", "virtual:082525a8792b89cbfd614faa6bcd1a9496584eedab2ae9d69d9f4375690e041544351047f44ef6dab868f44ac8fb8bbc2f5d9aa598e4e4521132888b2cfef8a9#npm:5.0.2"],\ + ["@types/babel__core", null],\ + ["@types/rollup", null],\ + ["rollup", null]\ + ],\ + "packagePeers": [\ + "@babel/core",\ + "@types/babel__core",\ + "@types/rollup",\ + "rollup"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@rollup/plugin-sucrase", [\ ["npm:4.0.4", {\ "packageLocation": "./.yarn/cache/@rollup-plugin-sucrase-npm-4.0.4-11cf77c62a-ccb01d7eb3.zip/node_modules/@rollup/plugin-sucrase/",\ @@ -3347,6 +3378,29 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["picomatch", "npm:2.3.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:5.0.2", {\ + "packageLocation": "./.yarn/cache/@rollup-pluginutils-npm-5.0.2-6aa9d0ddd4-edea15e543.zip/node_modules/@rollup/pluginutils/",\ + "packageDependencies": [\ + ["@rollup/pluginutils", "npm:5.0.2"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:082525a8792b89cbfd614faa6bcd1a9496584eedab2ae9d69d9f4375690e041544351047f44ef6dab868f44ac8fb8bbc2f5d9aa598e4e4521132888b2cfef8a9#npm:5.0.2", {\ + "packageLocation": "./.yarn/__virtual__/@rollup-pluginutils-virtual-7805b1dbc6/0/cache/@rollup-pluginutils-npm-5.0.2-6aa9d0ddd4-edea15e543.zip/node_modules/@rollup/pluginutils/",\ + "packageDependencies": [\ + ["@rollup/pluginutils", "virtual:082525a8792b89cbfd614faa6bcd1a9496584eedab2ae9d69d9f4375690e041544351047f44ef6dab868f44ac8fb8bbc2f5d9aa598e4e4521132888b2cfef8a9#npm:5.0.2"],\ + ["@types/estree", "npm:1.0.0"],\ + ["@types/rollup", null],\ + ["estree-walker", "npm:2.0.2"],\ + ["picomatch", "npm:2.3.1"],\ + ["rollup", null]\ + ],\ + "packagePeers": [\ + "@types/rollup",\ + "rollup"\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@rushstack/eslint-patch", [\ @@ -3957,6 +4011,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["@types/cors", [\ + ["npm:2.8.13", {\ + "packageLocation": "./.yarn/cache/@types-cors-npm-2.8.13-4b8ac1068f-7ef197ea19.zip/node_modules/@types/cors/",\ + "packageDependencies": [\ + ["@types/cors", "npm:2.8.13"],\ + ["@types/node", "npm:18.11.9"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@types/eslint", [\ ["npm:8.4.10", {\ "packageLocation": "./.yarn/cache/@types-eslint-npm-8.4.10-9df5f4bc78-21e009ed9e.zip/node_modules/@types/eslint/",\ @@ -5466,6 +5530,17 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["cors", [\ + ["npm:2.8.5", {\ + "packageLocation": "./.yarn/cache/cors-npm-2.8.5-c9935a2d12-ced838404c.zip/node_modules/cors/",\ + "packageDependencies": [\ + ["cors", "npm:2.8.5"],\ + ["object-assign", "npm:4.1.1"],\ + ["vary", "npm:1.1.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["cosmiconfig", [\ ["npm:7.1.0", {\ "packageLocation": "./.yarn/cache/cosmiconfig-npm-7.1.0-13a5090bcd-c53bf7befc.zip/node_modules/cosmiconfig/",\ @@ -5480,6 +5555,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["countup.js", [\ + ["npm:2.3.2", {\ + "packageLocation": "./.yarn/cache/countup.js-npm-2.3.2-fce559ea32-77bb509cd1.zip/node_modules/countup.js/",\ + "packageDependencies": [\ + ["countup.js", "npm:2.3.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["create-hash", [\ ["npm:1.2.0", {\ "packageLocation": "./.yarn/cache/create-hash-npm-1.2.0-afd048e1ce-02a6ae3bb9.zip/node_modules/create-hash/",\ @@ -7291,6 +7375,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@next/eslint-plugin-next", "npm:13.0.5"],\ ["@sentry/nextjs", "virtual:4b77e00d446246df1ed27001550885fbf1b51be18c660c1b5c357d3d763078ecef2a676194291a120f149b87573081e5af0621dc83cf1f83383639f39ac133c7#npm:7.27.0"],\ ["@svgr/webpack", "npm:6.5.1"],\ + ["@types/cors", "npm:2.8.13"],\ ["@types/eslint", "npm:8.4.10"],\ ["@types/node", "npm:18.11.9"],\ ["@types/react", "npm:18.0.25"],\ @@ -7302,6 +7387,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@typescript-eslint/parser", "virtual:4b77e00d446246df1ed27001550885fbf1b51be18c660c1b5c357d3d763078ecef2a676194291a120f149b87573081e5af0621dc83cf1f83383639f39ac133c7#npm:5.45.0"],\ ["axios", "npm:0.27.2"],\ ["buffer", "npm:6.0.3"],\ + ["cors", "npm:2.8.5"],\ ["crypto", "npm:1.0.1"],\ ["eslint", "npm:8.28.0"],\ ["eslint-config-next", "virtual:4b77e00d446246df1ed27001550885fbf1b51be18c660c1b5c357d3d763078ecef2a676194291a120f149b87573081e5af0621dc83cf1f83383639f39ac133c7#npm:13.0.5"],\ @@ -7317,6 +7403,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["next", "virtual:4b77e00d446246df1ed27001550885fbf1b51be18c660c1b5c357d3d763078ecef2a676194291a120f149b87573081e5af0621dc83cf1f83383639f39ac133c7#npm:13.0.5"],\ ["prettier", "npm:2.8.0"],\ ["react", "npm:18.2.0"],\ + ["react-countup", "virtual:4b77e00d446246df1ed27001550885fbf1b51be18c660c1b5c357d3d763078ecef2a676194291a120f149b87573081e5af0621dc83cf1f83383639f39ac133c7#npm:6.4.0"],\ ["react-dom", "virtual:4b77e00d446246df1ed27001550885fbf1b51be18c660c1b5c357d3d763078ecef2a676194291a120f149b87573081e5af0621dc83cf1f83383639f39ac133c7#npm:18.2.0"],\ ["react-is", "npm:18.2.0"],\ ["react-modal", "virtual:4b77e00d446246df1ed27001550885fbf1b51be18c660c1b5c357d3d763078ecef2a676194291a120f149b87573081e5af0621dc83cf1f83383639f39ac133c7#npm:3.16.1"],\ @@ -9155,6 +9242,30 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["react-countup", [\ + ["npm:6.4.0", {\ + "packageLocation": "./.yarn/cache/react-countup-npm-6.4.0-d1c6fe7973-259277fa70.zip/node_modules/react-countup/",\ + "packageDependencies": [\ + ["react-countup", "npm:6.4.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:4b77e00d446246df1ed27001550885fbf1b51be18c660c1b5c357d3d763078ecef2a676194291a120f149b87573081e5af0621dc83cf1f83383639f39ac133c7#npm:6.4.0", {\ + "packageLocation": "./.yarn/__virtual__/react-countup-virtual-9555373101/0/cache/react-countup-npm-6.4.0-d1c6fe7973-259277fa70.zip/node_modules/react-countup/",\ + "packageDependencies": [\ + ["react-countup", "virtual:4b77e00d446246df1ed27001550885fbf1b51be18c660c1b5c357d3d763078ecef2a676194291a120f149b87573081e5af0621dc83cf1f83383639f39ac133c7#npm:6.4.0"],\ + ["@rollup/plugin-babel", "virtual:9555373101f58738ea803ff9e79b0d8b52a66e88c21dac99d127fd080df7e60c5efb4c82f30a042556261bfb95e0c5292626cc000800b004d622753bbf9e02e5#npm:6.0.3"],\ + ["@types/react", "npm:18.0.25"],\ + ["countup.js", "npm:2.3.2"],\ + ["react", "npm:18.2.0"]\ + ],\ + "packagePeers": [\ + "@types/react",\ + "react"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["react-dom", [\ ["npm:18.2.0", {\ "packageLocation": "./.yarn/cache/react-dom-npm-18.2.0-dd675bca1c-7d323310be.zip/node_modules/react-dom/",\ @@ -10550,6 +10661,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD"\ }]\ ]],\ + ["vary", [\ + ["npm:1.1.2", {\ + "packageLocation": "./.yarn/cache/vary-npm-1.1.2-b49f70ae63-ae0123222c.zip/node_modules/vary/",\ + "packageDependencies": [\ + ["vary", "npm:1.1.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["warning", [\ ["npm:4.0.3", {\ "packageLocation": "./.yarn/cache/warning-npm-4.0.3-291e921d6d-4f2cb6a957.zip/node_modules/warning/",\ diff --git a/.yarn/cache/@rollup-plugin-babel-npm-6.0.3-1259d28dd2-412c1c3bb5.zip b/.yarn/cache/@rollup-plugin-babel-npm-6.0.3-1259d28dd2-412c1c3bb5.zip new file mode 100644 index 0000000..b4c5fef Binary files /dev/null and b/.yarn/cache/@rollup-plugin-babel-npm-6.0.3-1259d28dd2-412c1c3bb5.zip differ diff --git a/.yarn/cache/@rollup-pluginutils-npm-5.0.2-6aa9d0ddd4-edea15e543.zip b/.yarn/cache/@rollup-pluginutils-npm-5.0.2-6aa9d0ddd4-edea15e543.zip new file mode 100644 index 0000000..d898c50 Binary files /dev/null and b/.yarn/cache/@rollup-pluginutils-npm-5.0.2-6aa9d0ddd4-edea15e543.zip differ diff --git a/.yarn/cache/@types-cors-npm-2.8.13-4b8ac1068f-7ef197ea19.zip b/.yarn/cache/@types-cors-npm-2.8.13-4b8ac1068f-7ef197ea19.zip new file mode 100644 index 0000000..8c75a92 Binary files /dev/null and b/.yarn/cache/@types-cors-npm-2.8.13-4b8ac1068f-7ef197ea19.zip differ diff --git a/.yarn/cache/cors-npm-2.8.5-c9935a2d12-ced838404c.zip b/.yarn/cache/cors-npm-2.8.5-c9935a2d12-ced838404c.zip new file mode 100644 index 0000000..b7ab2c5 Binary files /dev/null and b/.yarn/cache/cors-npm-2.8.5-c9935a2d12-ced838404c.zip differ diff --git a/.yarn/cache/countup.js-npm-2.3.2-fce559ea32-77bb509cd1.zip b/.yarn/cache/countup.js-npm-2.3.2-fce559ea32-77bb509cd1.zip new file mode 100644 index 0000000..10a1c5c Binary files /dev/null and b/.yarn/cache/countup.js-npm-2.3.2-fce559ea32-77bb509cd1.zip differ diff --git a/.yarn/cache/react-countup-npm-6.4.0-d1c6fe7973-259277fa70.zip b/.yarn/cache/react-countup-npm-6.4.0-d1c6fe7973-259277fa70.zip new file mode 100644 index 0000000..180d69a Binary files /dev/null and b/.yarn/cache/react-countup-npm-6.4.0-d1c6fe7973-259277fa70.zip differ diff --git a/.yarn/cache/vary-npm-1.1.2-b49f70ae63-ae0123222c.zip b/.yarn/cache/vary-npm-1.1.2-b49f70ae63-ae0123222c.zip new file mode 100644 index 0000000..6ef0831 Binary files /dev/null and b/.yarn/cache/vary-npm-1.1.2-b49f70ae63-ae0123222c.zip differ diff --git a/components/primary-button/index.tsx b/components/primary-button/index.tsx index cb6dd22..adac418 100644 --- a/components/primary-button/index.tsx +++ b/components/primary-button/index.tsx @@ -75,7 +75,7 @@ const StyledPrimaryButton = styled.button` } `; -const SpinnerWrapper = styled.div` +export const SpinnerWrapper = styled.div` display: flex; position: relative; @@ -92,7 +92,7 @@ const spinAnimation = keyframes` } `; -const Spinner = styled.div<{ animationDelay?: string }>` +export const Spinner = styled.div<{ animationDelay?: string }>` display: block; position: absolute; top: 0; diff --git a/components/twitter-profile/index.tsx b/components/twitter-profile/index.tsx index 72a8598..00d14bf 100644 --- a/components/twitter-profile/index.tsx +++ b/components/twitter-profile/index.tsx @@ -1,18 +1,80 @@ import color from "../../styles/color"; import styled from "styled-components"; import { TwitterAuthInfoResponse } from "../../types"; -import { FunctionComponent } from "react"; +import { FunctionComponent, useEffect, useState } from "react"; import Image from "next/image"; +import ICNSIcon from "../../public/images/svg/icns-logo.svg"; + interface Props { + isOwner?: boolean; + registeredTwitterName?: string; twitterProfileInformation?: TwitterAuthInfoResponse | null; } export const TwitterProfile: FunctionComponent = (props) => { - const { twitterProfileInformation } = props; + const { isOwner, registeredTwitterName, twitterProfileInformation } = props; + const [isCopied, setIsCopied] = useState(false); + + const onClickInviteLink = async () => { + await navigator.clipboard.writeText( + `https://app.icns.xyz?referral=${registeredTwitterName}`, + ); + + setIsCopied(true); + + setTimeout(() => { + setIsCopied(false); + }, 1000); + }; return ( + {registeredTwitterName ? ( + isCopied ? ( + + copied + + + + + ) : ( + + copy invite link + + + + + + ) + ) : null} = (props) => { - {twitterProfileInformation?.name} + {twitterProfileInformation?.name} + + {isOwner ? ( + + + + ) : null} @{twitterProfileInformation?.username} @@ -58,6 +126,8 @@ export const ProfileContainer = styled.div` display: flex; flex-direction: row; + position: relative; + width: 100%; padding: 1.5rem 2rem; @@ -65,6 +135,45 @@ export const ProfileContainer = styled.div` background-color: ${(props) => props.color}; `; +const CopyIcon = styled.svg` + stroke: ${color.grey["100"]}; +`; + +const CopiedIcon = styled.svg` + stroke: ${color.grey["100"]}; +`; + +export const InviteLinkContainer = styled.div` + display: flex; + flex-direction: row; + align-items: center; + gap: 0.2rem; + + position: absolute; + + top: 1.75rem; + right: 1.5rem; + + font-family: "Inter", serif; + font-style: normal; + font-weight: 600; + font-size: 0.875rem; + line-height: 0.875rem; + text-transform: uppercase; + + color: ${color.grey["100"]}; + + cursor: pointer; + + &:hover { + color: ${color.grey["200"]}; + + ${CopyIcon} { + stroke: ${color.grey["200"]}; + } + } +`; + export const ProfileContentContainer = styled.div` display: flex; flex-direction: column; @@ -87,6 +196,12 @@ export const ProfileImageContainer = styled.div` `; export const ProfileNameContainer = styled.div` + display: flex; + flex-direction: row; + align-items: center; +`; + +export const ProfileName = styled.div` font-weight: 600; font-size: 1.2rem; line-height: 1.5rem; @@ -94,6 +209,15 @@ export const ProfileNameContainer = styled.div` color: ${color.white}; `; +export const IsOwnerIcon = styled.div` + height: 1px; + background-color: red; + margin-top: 0.1rem; + + display: flex; + align-items: center; +`; + export const ProfileUserNameContainer = styled.div` font-weight: 500; font-size: 0.8rem; diff --git a/constants/icns.ts b/constants/icns.ts index 805d0f9..719a6d8 100644 --- a/constants/icns.ts +++ b/constants/icns.ts @@ -20,6 +20,9 @@ export const RESOLVER_ADDRESS = process.env.NEXT_PUBLIC_ICNS_RESOLVER_CONTRACT_ADDRESS ?? "osmo1002awr7frr9wk44lc3vfzt0d2w6vz5z03ql6fszjsjy8vdcvk0sskruz3c"; +export const CLAIM_URL = + "https://lcd-osmosis.keplr.app/cosmwasm/wasm/v1/contract/osmo1mypljhatv0prfr9cjzzvamxdf2ctg34xkt50sudxads9zhqnyneqjuvy26/smart/eyJudW1fdG9rZW5zIjp7fX0="; + export const CHAIN_ALLOWLIST = process.env.NEXT_PUBLIC_CHAIN_ALLOWLIST || [ diff --git a/hooks/use-interval.tsx b/hooks/use-interval.tsx new file mode 100644 index 0000000..d30b06b --- /dev/null +++ b/hooks/use-interval.tsx @@ -0,0 +1,26 @@ +import { useEffect, useRef } from "react"; +import useIsomorphicLayoutEffect from "./use-isomorphic-layout-effect"; + +function useInterval(callback: () => void, delay: number | null) { + const savedCallback = useRef(callback); + + // Remember the latest callback if it changes. + useIsomorphicLayoutEffect(() => { + savedCallback.current = callback; + }, [callback]); + + // Set up the interval. + useEffect(() => { + // Don't schedule if no delay is specified. + // Note: 0 is a valid value for delay. + if (!delay && delay !== 0) { + return; + } + + const id = setInterval(() => savedCallback.current(), delay); + + return () => clearInterval(id); + }, [delay]); +} + +export default useInterval; diff --git a/hooks/use-isomorphic-layout-effect.tsx b/hooks/use-isomorphic-layout-effect.tsx new file mode 100644 index 0000000..d67ecc3 --- /dev/null +++ b/hooks/use-isomorphic-layout-effect.tsx @@ -0,0 +1,6 @@ +import { useEffect, useLayoutEffect } from "react"; + +const useIsomorphicLayoutEffect = + typeof window !== "undefined" ? useLayoutEffect : useEffect; + +export default useIsomorphicLayoutEffect; diff --git a/package.json b/package.json index 01ae06a..cd9f545 100644 --- a/package.json +++ b/package.json @@ -18,10 +18,12 @@ "@sentry/nextjs": "^7.27.0", "axios": "^0.27.2", "buffer": "^6.0.3", + "cors": "^2.8.5", "crypto": "^1.0.1", "iron-session": "^6.3.1", "next": "13.0.5", "react": "18.2.0", + "react-countup": "^6.4.0", "react-dom": "18.2.0", "react-is": "^18.2.0", "react-modal": "^3.16.1", @@ -33,6 +35,7 @@ "devDependencies": { "@next/eslint-plugin-next": "^13.0.5", "@svgr/webpack": "^6.5.1", + "@types/cors": "^2", "@types/eslint": "^8.4.10", "@types/node": "18.11.9", "@types/react": "18.0.25", diff --git a/pages/_app.tsx b/pages/_app.tsx index 8cc5efd..3002524 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -58,100 +58,6 @@ export default function App({ Component, pageProps }: AppProps) { Interchain Name Service - - - - - - - - - - - - {/* generated favicons */} - - - - - - - - - - - - - - - - - diff --git a/pages/_document.tsx b/pages/_document.tsx index 9472144..2f59cd8 100644 --- a/pages/_document.tsx +++ b/pages/_document.tsx @@ -54,6 +54,109 @@ class MyDocument extends Document { href="https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap" rel="stylesheet" /> + + + + + + + + + + + + {/* generated favicons */} + + + + + + + + + + + + + + + + +
diff --git a/pages/api/allowlist.ts b/pages/api/allowlist.ts new file mode 100644 index 0000000..f211b2c --- /dev/null +++ b/pages/api/allowlist.ts @@ -0,0 +1,23 @@ +import type { NextApiRequest, NextApiResponse } from "next"; +import { CHAIN_ALLOWLIST } from "../../constants/icns"; +import Cors from "cors"; + +const cors = Cors({ + methods: ["GET"], +}); + +export default async function (req: NextApiRequest, res: NextApiResponse) { + await new Promise((resolve, reject) => { + cors(req, res, (result: any) => { + if (result instanceof Error) { + return reject(result); + } + + return resolve(result); + }); + }); + + res.status(200).json({ + chains: CHAIN_ALLOWLIST, + }); +} diff --git a/pages/complete/index.tsx b/pages/complete/index.tsx index 24171f0..3e1029e 100644 --- a/pages/complete/index.tsx +++ b/pages/complete/index.tsx @@ -77,7 +77,7 @@ export default function CompletePage() { const width = 500; const height = 700; window.open( - `${SHARE_URL}?url=https://app.icns.xyz?referral=${twitterUsername}&text=${shareMessage}`, + `${SHARE_URL}?url=https://app.icns.xyz/?referral=${twitterUsername}&text=${shareMessage}`, "Share Twitter", `top=${(window.screen.height - height) / 2}, left=${ (window.screen.width - width) / 2 diff --git a/pages/index.tsx b/pages/index.tsx index ccd3717..9d9e115 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -6,17 +6,23 @@ import color from "../styles/color"; // Components import { ConnectWalletModal } from "../components/connect-wallet-modal"; -import { PrimaryButton } from "../components/primary-button"; +import { + PrimaryButton, + Spinner, + SpinnerWrapper, +} from "../components/primary-button"; // Image Assets import { useEffect, useState } from "react"; import { Logo } from "../components/logo"; -import { REFERRAL_KEY } from "../constants/icns"; +import { CLAIM_URL, REFERRAL_KEY } from "../constants/icns"; import { SELECTED_WALLET_KEY } from "../constants/wallet"; import StarIcon from "../public/images/svg/bg-asset-3.svg"; import CheckIcon from "../public/images/svg/check-icon.svg"; import MainLogo from "../public/images/svg/main-logo.svg"; import MainTitle from "../public/images/svg/main-title.svg"; +import CountUp from "react-countup"; +import useInterval from "../hooks/use-interval"; export default function Home() { const [currentReferral, setCurrentReferral] = useState(""); @@ -24,6 +30,8 @@ export default function Home() { const [isConnectWalletModalOpen, setIsConnectWalletModalOpen] = useState(false); + const [count, setCount] = useState<{ start: number; end: number }>(); + const onClickConnectWalletButton = async () => { amplitude.track("click connect wallet button"); @@ -46,10 +54,46 @@ export default function Home() { localStorage.removeItem(SELECTED_WALLET_KEY); }, []); + useEffect(() => { + setTimeout(() => { + countUpCallback(); + }, 1000); + }, []); + + useInterval(async () => { + await countUpCallback(); + }, 10000); + + const countUpCallback = async () => { + const response: { data: { count: number } } = await ( + await fetch(CLAIM_URL) + ).json(); + + setCount({ + start: (count?.end ?? 100) - 100, + end: response.data.count, + }); + }; + return ( + + {count ? ( + + + + ) : ( + + + + + + + )} + ICNS names claimed so far + @@ -150,6 +194,45 @@ const MainContainer = styled.div` } `; +const CountUpContainer = styled.div` + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + gap: 1.25rem; + + width: calc(25rem - 2px); + height: calc(5rem - 2px); + + position: absolute; + + margin-top: calc(10rem + 2px); + margin-left: calc(55rem + 2px); + + background-color: ${color.black}; +`; + +const CountUpText = styled.div` + font-family: "Inter", serif; + font-style: normal; + font-weight: 600; + font-size: 1rem; + line-height: 1.2rem; + letter-spacing: 0.46rem; + + color: ${color.white}; +`; + +const CountUpDescription = styled.div` + font-family: "Inter", serif; + font-style: normal; + font-weight: 500; + font-size: 0.875rem; + line-height: 1.1rem; + + color: ${color.grey["400"]}; +`; + const MainTitleContainer = styled.div` display: flex; flex-direction: column; diff --git a/pages/verification/index.tsx b/pages/verification/index.tsx index 25c608c..776b87e 100644 --- a/pages/verification/index.tsx +++ b/pages/verification/index.tsx @@ -106,6 +106,8 @@ export default function VerificationPage() { const [searchValue, setSearchValue] = useState(""); const [nftOwnerAddress, setNFTOwnerAddress] = useState(""); + // Handle the token id which actually registered. + const [registeredTwitterName, setRegisteredTwitterName] = useState(""); const [isOwner, setIsOwner] = useState(false); const [isModalOpen, setModalOpen] = useState(false); @@ -209,6 +211,13 @@ export default function VerificationPage() { isRegistered: "data" in registeredQueryResponse, }); + if ( + "data" in registeredQueryResponse && + registeredQueryResponse.data?.name + ) { + setRegisteredTwitterName(registeredQueryResponse.data.name); + } + if ("data" in registeredQueryResponse) { const ownerOfQueryResponse = await queryOwnerOfTwitterName( registeredQueryResponse.data.name, @@ -465,7 +474,7 @@ export default function VerificationPage() { pathname: "complete", query: { txHash: Buffer.from(txHash).toString("hex"), - twitterUsername: twitterInfo.username, + twitterUsername: registeredTwitterName || twitterInfo.username, }, }); } @@ -554,7 +563,11 @@ export default function VerificationPage() { ) : ( - + Chain List + + + + + + + + + + + + diff --git a/yarn.lock b/yarn.lock index 2efc204..d3579c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2090,6 +2090,25 @@ __metadata: languageName: node linkType: hard +"@rollup/plugin-babel@npm:^6.0.2": + version: 6.0.3 + resolution: "@rollup/plugin-babel@npm:6.0.3" + dependencies: + "@babel/helper-module-imports": ^7.18.6 + "@rollup/pluginutils": ^5.0.1 + peerDependencies: + "@babel/core": ^7.0.0 + "@types/babel__core": ^7.1.9 + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + "@types/babel__core": + optional: true + rollup: + optional: true + checksum: 412c1c3bb5dd029cbf0b37315ad54b51ef378b8d2fd91d1ec44d73cade723cec8718b5affa2ce8a8b06660710d11765056fac4068521f18737ce26142506a8b1 + languageName: node + linkType: hard + "@rollup/plugin-sucrase@npm:4.0.4": version: 4.0.4 resolution: "@rollup/plugin-sucrase@npm:4.0.4" @@ -2124,6 +2143,22 @@ __metadata: languageName: node linkType: hard +"@rollup/pluginutils@npm:^5.0.1": + version: 5.0.2 + resolution: "@rollup/pluginutils@npm:5.0.2" + dependencies: + "@types/estree": ^1.0.0 + estree-walker: ^2.0.2 + picomatch: ^2.3.1 + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: edea15e543bebc7dcac3b0ac8bc7b8e8e6dbd46e2864dbe5dd28072de1fbd5b0e10d545a610c0edaa178e8a7ac432e2a2a52e547ece1308471412caba47db8ce + languageName: node + linkType: hard + "@rushstack/eslint-patch@npm:^1.1.3": version: 1.2.0 resolution: "@rushstack/eslint-patch@npm:1.2.0" @@ -2527,6 +2562,15 @@ __metadata: languageName: node linkType: hard +"@types/cors@npm:^2": + version: 2.8.13 + resolution: "@types/cors@npm:2.8.13" + dependencies: + "@types/node": "*" + checksum: 7ef197ea19d2e5bf1313b8416baa6f3fd6dd887fd70191da1f804f557395357dafd8bc8bed0ac60686923406489262a7c8a525b55748f7b2b8afa686700de907 + languageName: node + linkType: hard + "@types/eslint@npm:^8.4.10": version: 8.4.10 resolution: "@types/eslint@npm:8.4.10" @@ -2537,7 +2581,7 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:*": +"@types/estree@npm:*, @types/estree@npm:^1.0.0": version: 1.0.0 resolution: "@types/estree@npm:1.0.0" checksum: 910d97fb7092c6738d30a7430ae4786a38542023c6302b95d46f49420b797f21619cdde11fa92b338366268795884111c2eb10356e4bd2c8ad5b92941e9e6443 @@ -3741,6 +3785,16 @@ __metadata: languageName: node linkType: hard +"cors@npm:^2.8.5": + version: 2.8.5 + resolution: "cors@npm:2.8.5" + dependencies: + object-assign: ^4 + vary: ^1 + checksum: ced838404ccd184f61ab4fdc5847035b681c90db7ac17e428f3d81d69e2989d2b680cc254da0e2554f5ed4f8a341820a1ce3d1c16b499f6e2f47a1b9b07b5006 + languageName: node + linkType: hard + "cosmiconfig@npm:^7.0.1": version: 7.1.0 resolution: "cosmiconfig@npm:7.1.0" @@ -3754,6 +3808,13 @@ __metadata: languageName: node linkType: hard +"countup.js@npm:^2.3.2": + version: 2.3.2 + resolution: "countup.js@npm:2.3.2" + checksum: 77bb509cd17619568c8d841f9dbba7d75c70948d7f9acd0a1acea80e3894c4b4173e27e8896268c1f53415ebee465229f1e623da5ad759083a618484ac4f9b60 + languageName: node + linkType: hard + "create-hash@npm:^1.1.0, create-hash@npm:^1.1.2, create-hash@npm:^1.2.0": version: 1.2.0 resolution: "create-hash@npm:1.2.0" @@ -4581,7 +4642,7 @@ __metadata: languageName: node linkType: hard -"estree-walker@npm:^2.0.1": +"estree-walker@npm:^2.0.1, estree-walker@npm:^2.0.2": version: 2.0.2 resolution: "estree-walker@npm:2.0.2" checksum: 6151e6f9828abe2259e57f5fd3761335bb0d2ebd76dc1a01048ccee22fabcfef3c0859300f6d83ff0d1927849368775ec5a6d265dde2f6de5a1be1721cd94efc @@ -5196,6 +5257,7 @@ __metadata: "@next/eslint-plugin-next": ^13.0.5 "@sentry/nextjs": ^7.27.0 "@svgr/webpack": ^6.5.1 + "@types/cors": ^2 "@types/eslint": ^8.4.10 "@types/node": 18.11.9 "@types/react": 18.0.25 @@ -5207,6 +5269,7 @@ __metadata: "@typescript-eslint/parser": ^5.45.0 axios: ^0.27.2 buffer: ^6.0.3 + cors: ^2.8.5 crypto: ^1.0.1 eslint: 8.28.0 eslint-config-next: 13.0.5 @@ -5222,6 +5285,7 @@ __metadata: next: 13.0.5 prettier: ^2.8.0 react: 18.2.0 + react-countup: ^6.4.0 react-dom: 18.2.0 react-is: ^18.2.0 react-modal: ^3.16.1 @@ -6411,7 +6475,7 @@ __metadata: languageName: node linkType: hard -"object-assign@npm:^4.0.1, object-assign@npm:^4.1.0, object-assign@npm:^4.1.1": +"object-assign@npm:^4, object-assign@npm:^4.0.1, object-assign@npm:^4.1.0, object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f @@ -6841,6 +6905,18 @@ __metadata: languageName: node linkType: hard +"react-countup@npm:^6.4.0": + version: 6.4.0 + resolution: "react-countup@npm:6.4.0" + dependencies: + "@rollup/plugin-babel": ^6.0.2 + countup.js: ^2.3.2 + peerDependencies: + react: ">= 16.3.0" + checksum: 259277fa70fc778fa3d67b375f5c44fdc3c8e5c9cc73225605f456adff31406966ff00379cb23ec771cb624a70c91c46d8216583c9dfc3fedb69071d31cb3208 + languageName: node + linkType: hard + "react-dom@npm:18.2.0": version: 18.2.0 resolution: "react-dom@npm:18.2.0" @@ -8047,6 +8123,13 @@ __metadata: languageName: node linkType: hard +"vary@npm:^1": + version: 1.1.2 + resolution: "vary@npm:1.1.2" + checksum: ae0123222c6df65b437669d63dfa8c36cee20a504101b2fcd97b8bf76f91259c17f9f2b4d70a1e3c6bbcee7f51b28392833adb6b2770b23b01abec84e369660b + languageName: node + linkType: hard + "warning@npm:^4.0.3": version: 4.0.3 resolution: "warning@npm:4.0.3"