From e8b7934e7428879f20c60174d8b0df3a54060cf3 Mon Sep 17 00:00:00 2001 From: holybasil Date: Mon, 29 Jul 2024 15:33:40 +0800 Subject: [PATCH 1/3] fix: add "Issue Badges" menu --- src/assets/svgs/bridge/external-link.svg | 13 ---- src/assets/svgs/common/external-link.svg | 4 +- src/constants/canvas.ts | 3 + src/pages/bridge/FAQ/link.tsx | 2 +- .../canvas/Dashboard/ActionBox/index.tsx | 68 +++++++++++++++++-- 5 files changed, 71 insertions(+), 19 deletions(-) delete mode 100644 src/assets/svgs/bridge/external-link.svg diff --git a/src/assets/svgs/bridge/external-link.svg b/src/assets/svgs/bridge/external-link.svg deleted file mode 100644 index 24c874b42..000000000 --- a/src/assets/svgs/bridge/external-link.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/assets/svgs/common/external-link.svg b/src/assets/svgs/common/external-link.svg index 59a8d71cf..a4a1e4333 100644 --- a/src/assets/svgs/common/external-link.svg +++ b/src/assets/svgs/common/external-link.svg @@ -1,6 +1,6 @@ - + @@ -8,3 +8,5 @@ + + diff --git a/src/constants/canvas.ts b/src/constants/canvas.ts index a9abd1a59..c7bdbc362 100644 --- a/src/constants/canvas.ts +++ b/src/constants/canvas.ts @@ -2,3 +2,6 @@ export enum BADGES_VISIBLE_TYPE { VISIBLE = "Displayed", INVISIBLE = "Not displayed", } + +export const BADGE_INTEGRATION_GUIDE = + "https://scrollzkp.notion.site/Introducing-Scroll-Canvas-Badge-Integration-Guide-8656463ab63b42e8baf924763ed8c9d5" diff --git a/src/pages/bridge/FAQ/link.tsx b/src/pages/bridge/FAQ/link.tsx index bb6034c8d..7876da537 100644 --- a/src/pages/bridge/FAQ/link.tsx +++ b/src/pages/bridge/FAQ/link.tsx @@ -3,7 +3,7 @@ import { Link } from "react-router-dom" import { Stack, SvgIcon } from "@mui/material" import { styled } from "@mui/system" -import { ReactComponent as LinkSvg } from "@/assets/svgs/bridge/external-link.svg" +import { ReactComponent as LinkSvg } from "@/assets/svgs/common/external-link.svg" import { isMainnet } from "@/utils" const FAQsLink = styled(Link)(({ theme }) => ({ diff --git a/src/pages/canvas/Dashboard/ActionBox/index.tsx b/src/pages/canvas/Dashboard/ActionBox/index.tsx index 9273788e2..c9d9ccfbc 100644 --- a/src/pages/canvas/Dashboard/ActionBox/index.tsx +++ b/src/pages/canvas/Dashboard/ActionBox/index.tsx @@ -1,4 +1,5 @@ import copy from "copy-to-clipboard" +import { motion } from "framer-motion" import { Fragment, useCallback, useMemo, useState } from "react" import { useNavigate, useParams } from "react-router-dom" @@ -10,13 +11,17 @@ import { ReactComponent as CopySuccessSvg } from "@/assets/svgs/canvas/copy-succ import { ReactComponent as EditSvg } from "@/assets/svgs/canvas/edit.svg" import { ReactComponent as EthSvg } from "@/assets/svgs/canvas/eth.svg" import { ReactComponent as ShareSvg } from "@/assets/svgs/canvas/share.svg" +import { ReactComponent as ExternalLinkSvg } from "@/assets/svgs/common/external-link.svg" import { ReactComponent as TwitterSvg } from "@/assets/svgs/nft/twitter.svg" +import { BADGE_INTEGRATION_GUIDE } from "@/constants" import { useRainbowContext } from "@/contexts/RainbowProvider" import useCheckViewport from "@/hooks/useCheckViewport" import Button from "@/pages/canvas/components/Button" import useCanvasStore, { BadgesDialogType } from "@/stores/canvasStore" import { generateShareTwitterURL, requireEnv } from "@/utils" +const AnimatedMenuItem = motion(MenuItem) + interface Action { label: string | (() => React.ReactNode) icon: React.ComponentType @@ -29,8 +34,10 @@ interface Action { open: boolean onClose: () => void items: Array<{ + key: string label: string | (() => React.ReactNode) extra?: React.ReactNode + external?: boolean onClick: () => void }> } @@ -91,9 +98,11 @@ const CustomMenu = styled(Menu, { shouldForwardProp: prop => prop !== "drop }, })) -const CustomiseItem = styled(MenuItem)(({ theme }) => ({ +const CustomiseItem = styled(AnimatedMenuItem)(({ theme, external }) => ({ + position: "relative", display: "flex", - justifyContent: "space-between", + justifyContent: external ? "flex-start" : "space-between", + gap: "0.8rem", padding: "0.8rem", backgroundColor: "#FFFFFF", color: "#000000", @@ -101,6 +110,7 @@ const CustomiseItem = styled(MenuItem)(({ theme }) => ({ fontWeight: 600, "&:hover": { backgroundColor: "#FFFFFF", + color: theme.palette.primary.main, }, })) @@ -168,6 +178,8 @@ const ActionBox = () => { } const [badgesAnchorEl, setBadgesAnchorEl] = useState(null) + const [isHovering, setIsHovering] = useState("") + const badgesOpen = Boolean(badgesAnchorEl) const handleCloseMenu = () => { @@ -207,6 +219,7 @@ const ActionBox = () => { onClose: handleCloseMenu, items: [ { + key: "customize", label: "Customize display", onClick: () => { handleCloseMenu() @@ -214,6 +227,7 @@ const ActionBox = () => { }, }, { + key: "mint", label: "Mint eligible badges", extra: mintableBadges.length ? {mintableBadges.length > 99 ? "99+" : mintableBadges.length} : null, onClick: () => { @@ -224,6 +238,7 @@ const ActionBox = () => { ...(upgradableBadges.length ? [ { + key: "upgrade", label: "Upgrade badges", extra: upgradableBadges.length ? {upgradableBadges.length > 99 ? "99+" : upgradableBadges.length} : null, onClick: () => { @@ -234,11 +249,20 @@ const ActionBox = () => { ] : []), { + key: "explore", label: "Explore badges", onClick: () => { navigate("/ecosystem#badges") }, }, + { + key: "issue", + label: "Issue badges", + external: true, + onClick: () => { + window.open(BADGE_INTEGRATION_GUIDE) + }, + }, ], }, }, @@ -267,6 +291,7 @@ const ActionBox = () => { onClose: handleCloseShare, items: [ { + key: "twitter", label: () => ( <>Share to @@ -279,10 +304,11 @@ const ActionBox = () => { }, }, { + key: "link", label: () => ( <> {copied ? "Link copied" : "Copy link"} - {copied && }{" "} + {copied && } ), onClick: handleCopyLink, @@ -306,6 +332,17 @@ const ActionBox = () => { pickUpgradableBadgesLoading, ]) + const handleMouseEnter = item => { + if (item.external) { + console.log(item, "???") + setIsHovering(item.key) + } + } + + const handleMouseLeave = () => { + setIsHovering("") + } + const renderActionIcon = action => { if (action.withBadge) { return ( @@ -350,9 +387,32 @@ const ActionBox = () => { onClose={action.menu.onClose} > {action.menu.items.map((item, index) => ( - + handleMouseEnter(item)} + onHoverEnd={handleMouseLeave} + animate={isHovering === item.key ? "active" : "inactive"} + > {typeof item.label === "function" ? item.label() : item.label} {item.extra} + {item.external && ( + + + + )} ))} From 97e4a7b09fde9d0fa28da5d9d39371bde904568c Mon Sep 17 00:00:00 2001 From: holybasil Date: Mon, 29 Jul 2024 16:07:37 +0800 Subject: [PATCH 2/3] fix: update error message --- .../canvas/Dashboard/ActionBox/index.tsx | 2 +- .../canvas/Dashboard/BadgesDialog/index.tsx | 9 +++--- src/services/canvasService.ts | 4 +-- src/utils/txError.ts | 29 ++++++++++++------- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/pages/canvas/Dashboard/ActionBox/index.tsx b/src/pages/canvas/Dashboard/ActionBox/index.tsx index c9d9ccfbc..8413cfb48 100644 --- a/src/pages/canvas/Dashboard/ActionBox/index.tsx +++ b/src/pages/canvas/Dashboard/ActionBox/index.tsx @@ -98,7 +98,7 @@ const CustomMenu = styled(Menu, { shouldForwardProp: prop => prop !== "drop }, })) -const CustomiseItem = styled(AnimatedMenuItem)(({ theme, external }) => ({ +const CustomiseItem = styled(AnimatedMenuItem, { shouldForwardProp: prop => prop !== "external" })(({ theme, external }) => ({ position: "relative", display: "flex", justifyContent: external ? "flex-start" : "space-between", diff --git a/src/pages/canvas/Dashboard/BadgesDialog/index.tsx b/src/pages/canvas/Dashboard/BadgesDialog/index.tsx index efb56a7e6..fe19ccb79 100644 --- a/src/pages/canvas/Dashboard/BadgesDialog/index.tsx +++ b/src/pages/canvas/Dashboard/BadgesDialog/index.tsx @@ -1,4 +1,4 @@ -import { useMemo } from "react" +import { Fragment, useMemo } from "react" import Img from "react-cool-img" import { List } from "@mui/material" @@ -121,12 +121,11 @@ const BadgesDialog = props => { {badges.map((badge, index) => ( - <> + {badgesDialogVisible === BadgesDialogType.MINT ? ( - handleViewBadge(badge)} /> + handleViewBadge(badge)} /> ) : ( { } /> )} - + ))} diff --git a/src/services/canvasService.ts b/src/services/canvasService.ts index 7dd971616..d5484bd1f 100644 --- a/src/services/canvasService.ts +++ b/src/services/canvasService.ts @@ -373,7 +373,7 @@ const mintBadge = async (provider, walletCurrentAddress, badge) => { if (isUserRejected(error)) { return false } else { - const message = recognizeError(error) + const message = recognizeError(error, badge.issuer.name) sentryDebug(`mint badge:${walletCurrentAddress}-${badge.badgeContract}-${message}`) throw new Error(trimErrorMessage(message)) } @@ -398,7 +398,7 @@ const upgradeBadge = async (provider, badge) => { if (isUserRejected(error)) { return false } else { - const message = recognizeError(error) + const message = recognizeError(error, badge.issuer.name) sentryDebug(`upgrade badge:${badge.id}-${message}`) throw new Error(trimErrorMessage(message)) } diff --git a/src/utils/txError.ts b/src/utils/txError.ts index 650d8c2f8..6d2cbf6fa 100644 --- a/src/utils/txError.ts +++ b/src/utils/txError.ts @@ -48,12 +48,12 @@ const abi = [ ] const IDENTIFIED_ERROR_MAP = { - AccessDenied: "Access Denied. Please contact the badge issuer for assistance", - SingletonBadge: "You have minted this badge before. Please wait for EAS to sync the data", - ExpiredSignature: "Invitation code signature has expired. Please refresh the page and try again", - InvalidSignature: "Invalid signature. Please contact the badge issuer for assistance", - DeadlineExpired: "The signature has expired. Please try again", - ProfileAlreadyMinted: "You have minted Canvas before. Please refresh the page to sync the latest data.", + AccessDenied: issuer => `Failed to mint the badge. Please reach out to ${issuer}’ community for help`, + SingletonBadge: "You have already minted this badge. Please wait for a while for Canvas to be updated", + ExpiredSignature: "Something went wrong. Please try again later", + InvalidSignature: issuer => `Failed to mint the badge. Please reach out to ${issuer}’ community for help`, + DeadlineExpired: "Something went wrong. Please try again later", + ProfileAlreadyMinted: "You have already minted your Canvas. Please wait for a while for Canvas to be updated", } export const decodeErrorData = errSelector => { @@ -62,21 +62,28 @@ export const decodeErrorData = errSelector => { return parsedError?.name } -export const recognizeError = error => { +// AccessDenied / InvalidSignature only for minting a badge +export const recognizeError = (error, issuerName?) => { if (error.code === "INSUFFICIENT_FUNDS") { - return "Transaction failed due to insufficient funds. Please ensure your account has enough balance." + return "Transaction failed due to insufficient funds. Please ensure your wallet has enough ETH" } if (error.code === "CALL_EXCEPTION") { - const unrecognized = "Transaction failed due to an unknown error. Please try again later." + const unrecognized = "Something went wrong. Please try again later" // execution reverted if (error.data) { const type = decodeErrorData(error.data) - return type ? `${IDENTIFIED_ERROR_MAP[type] ? IDENTIFIED_ERROR_MAP[type] : "Execution reverted due to " + type}` : unrecognized + if (type) { + if (IDENTIFIED_ERROR_MAP[type]) { + return typeof IDENTIFIED_ERROR_MAP[type] === "function" ? IDENTIFIED_ERROR_MAP[type](issuerName) : IDENTIFIED_ERROR_MAP[type] + } + return "Execution reverted due to " + type + } + return unrecognized } return unrecognized } if (error.code === "UNKNOWN_ERROR" && error.message.startsWith("could not coalesce error")) { - return error.error?.message || error.error?.data?.error?.message || "The PRC is busy, please try again later." + return error.error?.message || error.error?.data?.error?.message || "RPC service is busy. Please try again later" } return error.message } From 0d188ba5ca82e4c17e498d281863e5e1992f1173 Mon Sep 17 00:00:00 2001 From: holybasil Date: Mon, 29 Jul 2024 19:51:03 +0800 Subject: [PATCH 3/3] fix: update tip --- src/utils/txError.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/txError.ts b/src/utils/txError.ts index 6d2cbf6fa..1e275890e 100644 --- a/src/utils/txError.ts +++ b/src/utils/txError.ts @@ -48,10 +48,10 @@ const abi = [ ] const IDENTIFIED_ERROR_MAP = { - AccessDenied: issuer => `Failed to mint the badge. Please reach out to ${issuer}’ community for help`, + AccessDenied: issuer => `Minting failed. Please reach out to ${issuer}’s community channels for help`, SingletonBadge: "You have already minted this badge. Please wait for a while for Canvas to be updated", ExpiredSignature: "Something went wrong. Please try again later", - InvalidSignature: issuer => `Failed to mint the badge. Please reach out to ${issuer}’ community for help`, + InvalidSignature: issuer => `Minting failed. Please reach out to ${issuer}’s community channels for help`, DeadlineExpired: "Something went wrong. Please try again later", ProfileAlreadyMinted: "You have already minted your Canvas. Please wait for a while for Canvas to be updated", }