Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge sepolia into mainnet #1214

Merged
merged 4 commits into from
Jul 30, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions src/assets/svgs/bridge/external-link.svg

This file was deleted.

4 changes: 3 additions & 1 deletion src/assets/svgs/common/external-link.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/constants/canvas.ts
Original file line number Diff line number Diff line change
@@ -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"
2 changes: 1 addition & 1 deletion src/pages/bridge/FAQ/link.tsx
Original file line number Diff line number Diff line change
@@ -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 }) => ({
68 changes: 64 additions & 4 deletions src/pages/canvas/Dashboard/ActionBox/index.tsx
Original file line number Diff line number Diff line change
@@ -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,16 +98,19 @@ const CustomMenu = styled<any>(Menu, { shouldForwardProp: prop => prop !== "drop
},
}))

const CustomiseItem = styled(MenuItem)(({ theme }) => ({
const CustomiseItem = styled<any>(AnimatedMenuItem, { shouldForwardProp: prop => prop !== "external" })(({ 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",
fontSize: "1.6rem",
fontWeight: 600,
"&:hover": {
backgroundColor: "#FFFFFF",
color: theme.palette.primary.main,
},
}))

@@ -168,6 +178,8 @@ const ActionBox = () => {
}

const [badgesAnchorEl, setBadgesAnchorEl] = useState<null | HTMLElement>(null)
const [isHovering, setIsHovering] = useState("")

const badgesOpen = Boolean(badgesAnchorEl)

const handleCloseMenu = () => {
@@ -207,13 +219,15 @@ const ActionBox = () => {
onClose: handleCloseMenu,
items: [
{
key: "customize",
label: "Customize display",
onClick: () => {
handleCloseMenu()
changeCustomizeDisplayDialogVisible(true)
},
},
{
key: "mint",
label: "Mint eligible badges",
extra: mintableBadges.length ? <BadgeCount>{mintableBadges.length > 99 ? "99+" : mintableBadges.length}</BadgeCount> : null,
onClick: () => {
@@ -224,6 +238,7 @@ const ActionBox = () => {
...(upgradableBadges.length
? [
{
key: "upgrade",
label: "Upgrade badges",
extra: upgradableBadges.length ? <BadgeCount>{upgradableBadges.length > 99 ? "99+" : upgradableBadges.length}</BadgeCount> : 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: () => (
<Stack direction="row" gap="0.6rem" alignItems="center">
<>Share to</>
@@ -279,10 +304,11 @@ const ActionBox = () => {
},
},
{
key: "link",
label: () => (
<>
{copied ? "Link copied" : "Copy link"}
{copied && <SvgIcon sx={{ ml: "0.6rem" }} component={CopySuccessSvg} inheritViewBox></SvgIcon>}{" "}
{copied && <SvgIcon sx={{ ml: "0.6rem" }} component={CopySuccessSvg} inheritViewBox></SvgIcon>}
</>
),
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) => (
<CustomiseItem key={index} onClick={item.onClick}>
<CustomiseItem
key={index}
onClick={item.onClick}
external={item.external}
onHoverStart={() => handleMouseEnter(item)}
onHoverEnd={handleMouseLeave}
animate={isHovering === item.key ? "active" : "inactive"}
>
{typeof item.label === "function" ? item.label() : item.label}
{item.extra}
{item.external && (
<motion.div
variants={{
active: {
x: 0,
opacity: 1,
},
inactive: {
x: -8,
opacity: 0,
},
}}
>
<SvgIcon component={ExternalLinkSvg} sx={{ fontSize: "1.2rem", color: "primary.main" }}></SvgIcon>
</motion.div>
)}
</CustomiseItem>
))}
</CustomMenu>
9 changes: 4 additions & 5 deletions src/pages/canvas/Dashboard/BadgesDialog/index.tsx
Original file line number Diff line number Diff line change
@@ -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 => {
<Dialog title={dialogTitle} open={!!badgesDialogVisible} onClose={handleClose}>
<StyledList>
{badges.map((badge, index) => (
<>
<Fragment key={index}>
{badgesDialogVisible === BadgesDialogType.MINT ? (
<BadgeItem key={index} badge={badge} onClick={() => handleViewBadge(badge)} />
<BadgeItem badge={badge} onClick={() => handleViewBadge(badge)} />
) : (
<BadgeItem
key={index}
badge={badge}
action={
<Button
@@ -141,7 +140,7 @@ const BadgesDialog = props => {
}
/>
)}
</>
</Fragment>
))}
</StyledList>
</Dialog>
4 changes: 2 additions & 2 deletions src/services/canvasService.ts
Original file line number Diff line number Diff line change
@@ -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))
}
29 changes: 18 additions & 11 deletions src/utils/txError.ts
Original file line number Diff line number Diff line change
@@ -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 => `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 => `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",
}

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
}