Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "scroll.io",
"version": "5.1.0",
"version": "5.1.1",
"private": false,
"license": "MIT",
"scripts": {
Expand Down
7 changes: 4 additions & 3 deletions src/pages/canvas/mint/flow/MintStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import useCheckViewport from "@/hooks/useCheckViewport"
import useSnackbar from "@/hooks/useSnackbar"
// import { testAsyncFunc } from "@/services/canvasService"
import useCanvasStore from "@/stores/canvasStore"
import { isUserRejected, requireEnv, sentryDebug, trimErrorMessage } from "@/utils"
import { isUserRejected, recognizeError, requireEnv, sentryDebug, trimErrorMessage } from "@/utils"

import InsufficientDialog from "./InsufficientDialog"
import StepWrapper from "./StepWrapper"
Expand Down Expand Up @@ -99,8 +99,9 @@ const MintStep = props => {
}
} catch (error) {
if (!isUserRejected(error)) {
alertWarning(trimErrorMessage(error.message))
sentryDebug(`mint canvas:${walletCurrentAddress}-${error.message}`)
const message = recognizeError(error)
alertWarning(trimErrorMessage(message))
sentryDebug(`mint canvas:${walletCurrentAddress}-${message}`)
}
} finally {
changeIsProfileMinting(false)
Expand Down
12 changes: 7 additions & 5 deletions src/services/canvasService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import AttestProxyABI from "@/assets/abis/CanvasAttestProxy.json"
import BadgeABI from "@/assets/abis/CanvasBadge.json"
import ProfileABI from "@/assets/abis/CanvasProfile.json"
import ProfileRegistryABI from "@/assets/abis/CanvasProfileRegistry.json"
import { checkDelegatedAttestation, decodeBadgePayload, isUserRejected, requireEnv, sentryDebug, trimErrorMessage } from "@/utils"
import { checkDelegatedAttestation, decodeBadgePayload, isUserRejected, recognizeError, requireEnv, sentryDebug, trimErrorMessage } from "@/utils"

const EAS_GRAPHQL_URL = requireEnv("REACT_APP_EAS_GRAPHQL_URL")
const BADGE_SCHEMA = requireEnv("REACT_APP_BADGE_SCHEMA")
Expand Down Expand Up @@ -373,8 +373,9 @@ const mintBadge = async (provider, walletCurrentAddress, badge) => {
if (isUserRejected(error)) {
return false
} else {
sentryDebug(`mint badge:${walletCurrentAddress}-${badge.badgeContract}-${error.message}`)
throw new Error(trimErrorMessage(error.message))
const message = recognizeError(error)
sentryDebug(`mint badge:${walletCurrentAddress}-${badge.badgeContract}-${message}`)
throw new Error(trimErrorMessage(message))
}
}
}
Expand All @@ -397,8 +398,9 @@ const upgradeBadge = async (provider, badge) => {
if (isUserRejected(error)) {
return false
} else {
sentryDebug(`upgrade badge:${badge.id}-${error.message}`)
throw new Error(trimErrorMessage(error.message))
const message = recognizeError(error)
sentryDebug(`upgrade badge:${badge.id}-${message}`)
throw new Error(trimErrorMessage(message))
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from "./nft"
export * from "./dom"
export * from "./blog"
export * from "./canvas"
export * from "./txError"
82 changes: 82 additions & 0 deletions src/utils/txError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { Interface } from "ethers"

const abi = [
"error Unauthorized()",
"error CannotUpgrade(bytes32 uid)",

// attestation errors
"error BadgeNotAllowed(address badge)",
"error BadgeNotFound(address badge)",
"error ExpirationDisabled()",
"error MissingPayload()",
"error ResolverPaymentsDisabled()",
"error RevocationDisabled()",
"error SingletonBadge()",
"error UnknownSchema()",

// query errors
"error AttestationBadgeMismatch(bytes32 uid)",
"error AttestationExpired(bytes32 uid)",
"error AttestationNotFound(bytes32 uid)",
"error AttestationOwnerMismatch(bytes32 uid)",
"error AttestationRevoked(bytes32 uid)",
"error AttestationSchemaMismatch(bytes32 uid)",

// profile errors
"error BadgeCountReached()",
"error LengthMismatch()",
"error TokenNotOwnedByUser(address token, uint256 tokenId)",

// profile registry errors
"error CallerIsNotUserProfile()",
"error DuplicatedUsername()",
"error ExpiredSignature()",
"error ImplementationNotContract()",
"error InvalidReferrer()",
"error InvalidSignature()",
"error InvalidUsername()",
"error MsgValueMismatchWithMintFee()",
"error ProfileAlreadyMinted()",

"error AccessDenied()",

// EAS error
"error DeadlineExpired()",
"error InvalidEAS()",
"error InvalidLength()",
"error NotFound()",
]

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.",
}

export const decodeErrorData = errSelector => {
const contract = new Interface(abi)
const parsedError = contract.parseError(errSelector)
return parsedError?.name
}

export const recognizeError = error => {
if (error.code === "INSUFFICIENT_FUNDS") {
return "Transaction failed due to insufficient funds. Please ensure your account has enough balance."
}
if (error.code === "CALL_EXCEPTION") {
const unrecognized = "Transaction failed due to an unknown error. 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
}
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.message
}