From eb07da23fa277d77f5dd435c98ade5d2be896e76 Mon Sep 17 00:00:00 2001 From: Aries Gunawan Date: Sat, 26 Oct 2024 01:04:20 +0200 Subject: [PATCH 1/7] feat: decode metamask transaction error --- static/scripts/rewards/toaster.ts | 9 ++++++++ static/scripts/rewards/web3/erc20-permit.ts | 5 ++-- static/scripts/rewards/web3/erc721-permit.ts | 21 +++++++++++++---- static/scripts/rewards/web3/error-decoder.ts | 24 ++++++++++++++++++++ 4 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 static/scripts/rewards/web3/error-decoder.ts diff --git a/static/scripts/rewards/toaster.ts b/static/scripts/rewards/toaster.ts index 08c771b4..39ea79d4 100644 --- a/static/scripts/rewards/toaster.ts +++ b/static/scripts/rewards/toaster.ts @@ -74,4 +74,13 @@ export type MetaMaskError = { hex: "0x012c5a"; }; }; + error: { + code: string; + message: string; + data: { + code: string; + message: string; + data: string; + }; + }; }; diff --git a/static/scripts/rewards/web3/erc20-permit.ts b/static/scripts/rewards/web3/erc20-permit.ts index 8b2500f7..f6e058c9 100644 --- a/static/scripts/rewards/web3/erc20-permit.ts +++ b/static/scripts/rewards/web3/erc20-permit.ts @@ -9,6 +9,7 @@ import { buttonController, getMakeClaimButton, viewClaimButton } from "../button import { toaster, errorToast, MetaMaskError } from "../toaster"; import { connectWallet } from "./connect-wallet"; import { convertToNetworkId } from "./use-rpc-handler"; +import { decodeError } from "./error-decoder"; export async function fetchTreasury(permit: Permit): Promise<{ balance: BigNumber; allowance: BigNumber; decimals: number; symbol: string }> { let balance: BigNumber, allowance: BigNumber, decimals: number, symbol: string; @@ -89,8 +90,8 @@ export async function transferFromPermit(permit2Contract: Contract, reward: Perm buttonController.hideLoader(); buttonController.showMakeClaim(); } else { - // Handle other errors - console.error("Error in permitTransferFrom:", e); + const { errorname, message } = decodeError(permit2Contract, e); + console.error(`Error in permitTransferFrom: ${errorname} [ ${message} ]`); errorToast(e, e.reason); } } diff --git a/static/scripts/rewards/web3/erc721-permit.ts b/static/scripts/rewards/web3/erc721-permit.ts index 992a7b4c..ba115e06 100644 --- a/static/scripts/rewards/web3/erc721-permit.ts +++ b/static/scripts/rewards/web3/erc721-permit.ts @@ -3,9 +3,10 @@ import { ERC721Permit } from "@ubiquibot/permit-generation/types"; import { BigNumber, ethers } from "ethers"; import { nftRewardAbi } from "../abis/nft-reward-abi"; import { app } from "../app-state"; -import { toaster } from "../toaster"; +import { errorToast, MetaMaskError, toaster } from "../toaster"; import { buttonController, getMakeClaimButton } from "../button-controller"; import { connectWallet } from "./connect-wallet"; +import { decodeError } from "./error-decoder"; export function claimErc721PermitHandler(reward: ERC721Permit) { return async function claimHandler() { @@ -31,9 +32,11 @@ export function claimErc721PermitHandler(reward: ERC721Permit) { } buttonController.showLoader(); - try { - const nftContract = new ethers.Contract(reward.tokenAddress, nftRewardAbi, signer); + const nftContract = new ethers.Contract(reward.tokenAddress, nftRewardAbi, signer); + if (!nftContract) return; + + try { const tx: TransactionResponse = await nftContract.safeMint( { beneficiary: reward.beneficiary, @@ -62,7 +65,17 @@ export function claimErc721PermitHandler(reward: ERC721Permit) { } catch (error: unknown) { console.error(error); if (error instanceof Error) { - toaster.create("error", `Error claiming NFT: ${error.message}`); + const e = error as unknown as MetaMaskError; + if (e.code == "ACTION_REJECTED") { + // Handle the user rejection case + toaster.create("info", `Transaction was not sent because it was rejected by the user.`); + buttonController.hideLoader(); + buttonController.showMakeClaim(); + } else { + const { errorname, message } = decodeError(nftContract, e); + console.error(`Error claiming NFT: ${errorname} [ ${message} ]`); + errorToast(e, e.reason); + } } else if (typeof error === "string") { toaster.create("error", `Error claiming NFT: ${error}`); } else { diff --git a/static/scripts/rewards/web3/error-decoder.ts b/static/scripts/rewards/web3/error-decoder.ts new file mode 100644 index 00000000..2508c77e --- /dev/null +++ b/static/scripts/rewards/web3/error-decoder.ts @@ -0,0 +1,24 @@ +import { Contract } from "ethers"; +import { MetaMaskError } from "../toaster"; + +export function decodeError(contract: Contract, err: MetaMaskError) { + const errordata = err.error?.data?.data; + const iface = contract.interface; + const selecter = errordata.slice(0, 10); + const res = iface.decodeErrorResult(selecter, errordata); + const errorfragments = iface.getError(selecter); + + let message; + if (errorfragments.inputs.length > 0) { + message = errorfragments.inputs + .map((input, index) => { + return `${input.name}: ${res[index].toString()}`; + }) + .join(", "); + } + + return { + errorname: errorfragments.name, + message: message, + }; +} From 2eab98d9637fa7c5d3b0d5b4b60fbcb880a2ea2a Mon Sep 17 00:00:00 2001 From: Aries Gunawan Date: Sat, 26 Oct 2024 01:14:23 +0200 Subject: [PATCH 2/7] fix: update error formatting --- static/scripts/rewards/web3/erc20-permit.ts | 2 +- static/scripts/rewards/web3/erc721-permit.ts | 2 +- static/scripts/rewards/web3/error-decoder.ts | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/static/scripts/rewards/web3/erc20-permit.ts b/static/scripts/rewards/web3/erc20-permit.ts index f6e058c9..74ef8e9b 100644 --- a/static/scripts/rewards/web3/erc20-permit.ts +++ b/static/scripts/rewards/web3/erc20-permit.ts @@ -91,7 +91,7 @@ export async function transferFromPermit(permit2Contract: Contract, reward: Perm buttonController.showMakeClaim(); } else { const { errorname, message } = decodeError(permit2Contract, e); - console.error(`Error in permitTransferFrom: ${errorname} [ ${message} ]`); + console.error(`Error in permitTransferFrom: ${errorname} ${message}`); errorToast(e, e.reason); } } diff --git a/static/scripts/rewards/web3/erc721-permit.ts b/static/scripts/rewards/web3/erc721-permit.ts index ba115e06..a689d255 100644 --- a/static/scripts/rewards/web3/erc721-permit.ts +++ b/static/scripts/rewards/web3/erc721-permit.ts @@ -73,7 +73,7 @@ export function claimErc721PermitHandler(reward: ERC721Permit) { buttonController.showMakeClaim(); } else { const { errorname, message } = decodeError(nftContract, e); - console.error(`Error claiming NFT: ${errorname} [ ${message} ]`); + console.error(`Error claiming NFT: ${errorname} ${message}`); errorToast(e, e.reason); } } else if (typeof error === "string") { diff --git a/static/scripts/rewards/web3/error-decoder.ts b/static/scripts/rewards/web3/error-decoder.ts index 2508c77e..e0119f4c 100644 --- a/static/scripts/rewards/web3/error-decoder.ts +++ b/static/scripts/rewards/web3/error-decoder.ts @@ -8,13 +8,15 @@ export function decodeError(contract: Contract, err: MetaMaskError) { const res = iface.decodeErrorResult(selecter, errordata); const errorfragments = iface.getError(selecter); - let message; + let message = ""; if (errorfragments.inputs.length > 0) { + message += "[ "; message = errorfragments.inputs .map((input, index) => { return `${input.name}: ${res[index].toString()}`; }) .join(", "); + message += " ]"; } return { From 0b42c226991ff1111afa45d5109546ccec409bf2 Mon Sep 17 00:00:00 2001 From: Aries Gunawan Date: Sat, 26 Oct 2024 10:20:18 +0200 Subject: [PATCH 3/7] fix: use ethers-decode-error --- static/scripts/rewards/web3/erc20-permit.ts | 8 +++--- static/scripts/rewards/web3/erc721-permit.ts | 7 +++--- static/scripts/rewards/web3/error-decoder.ts | 26 -------------------- 3 files changed, 7 insertions(+), 34 deletions(-) delete mode 100644 static/scripts/rewards/web3/error-decoder.ts diff --git a/static/scripts/rewards/web3/erc20-permit.ts b/static/scripts/rewards/web3/erc20-permit.ts index 74ef8e9b..6ad632a1 100644 --- a/static/scripts/rewards/web3/erc20-permit.ts +++ b/static/scripts/rewards/web3/erc20-permit.ts @@ -9,7 +9,8 @@ import { buttonController, getMakeClaimButton, viewClaimButton } from "../button import { toaster, errorToast, MetaMaskError } from "../toaster"; import { connectWallet } from "./connect-wallet"; import { convertToNetworkId } from "./use-rpc-handler"; -import { decodeError } from "./error-decoder"; +import { decodeError } from "ethers-decode-error"; +// import { decodeError } from "./error-decoder"; export async function fetchTreasury(permit: Permit): Promise<{ balance: BigNumber; allowance: BigNumber; decimals: number; symbol: string }> { let balance: BigNumber, allowance: BigNumber, decimals: number, symbol: string; @@ -90,9 +91,8 @@ export async function transferFromPermit(permit2Contract: Contract, reward: Perm buttonController.hideLoader(); buttonController.showMakeClaim(); } else { - const { errorname, message } = decodeError(permit2Contract, e); - console.error(`Error in permitTransferFrom: ${errorname} ${message}`); - errorToast(e, e.reason); + const { error } = decodeError(e, permit2Abi); + errorToast(e, `Error in permitTransferFrom: ${error}`); } } return null; diff --git a/static/scripts/rewards/web3/erc721-permit.ts b/static/scripts/rewards/web3/erc721-permit.ts index a689d255..cd40ae59 100644 --- a/static/scripts/rewards/web3/erc721-permit.ts +++ b/static/scripts/rewards/web3/erc721-permit.ts @@ -6,7 +6,7 @@ import { app } from "../app-state"; import { errorToast, MetaMaskError, toaster } from "../toaster"; import { buttonController, getMakeClaimButton } from "../button-controller"; import { connectWallet } from "./connect-wallet"; -import { decodeError } from "./error-decoder"; +import { decodeError } from "ethers-decode-error"; export function claimErc721PermitHandler(reward: ERC721Permit) { return async function claimHandler() { @@ -72,9 +72,8 @@ export function claimErc721PermitHandler(reward: ERC721Permit) { buttonController.hideLoader(); buttonController.showMakeClaim(); } else { - const { errorname, message } = decodeError(nftContract, e); - console.error(`Error claiming NFT: ${errorname} ${message}`); - errorToast(e, e.reason); + const { error } = decodeError(e, nftRewardAbi); + errorToast(e, `Error in permitTransferFrom: ${error}`); } } else if (typeof error === "string") { toaster.create("error", `Error claiming NFT: ${error}`); diff --git a/static/scripts/rewards/web3/error-decoder.ts b/static/scripts/rewards/web3/error-decoder.ts deleted file mode 100644 index e0119f4c..00000000 --- a/static/scripts/rewards/web3/error-decoder.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Contract } from "ethers"; -import { MetaMaskError } from "../toaster"; - -export function decodeError(contract: Contract, err: MetaMaskError) { - const errordata = err.error?.data?.data; - const iface = contract.interface; - const selecter = errordata.slice(0, 10); - const res = iface.decodeErrorResult(selecter, errordata); - const errorfragments = iface.getError(selecter); - - let message = ""; - if (errorfragments.inputs.length > 0) { - message += "[ "; - message = errorfragments.inputs - .map((input, index) => { - return `${input.name}: ${res[index].toString()}`; - }) - .join(", "); - message += " ]"; - } - - return { - errorname: errorfragments.name, - message: message, - }; -} From 3fef0f565141e4d598dfa7deb787da6cbd4df692 Mon Sep 17 00:00:00 2001 From: Aries Gunawan Date: Sat, 26 Oct 2024 10:26:08 +0200 Subject: [PATCH 4/7] fix: added ethers-decode-error --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 42f7aaf0..7345c4e3 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "countries-and-timezones": "^3.6.0", "dotenv": "^16.4.4", "ethers": "^5.7.2", + "ethers-decode-error": "^1.0.0", "npm-run-all": "^4.1.5", "zod": "^3.23.8" }, From 62f9e74066ea00bdcfebdc61ed9d862d7c5f80db Mon Sep 17 00:00:00 2001 From: Aries Gunawan Date: Sat, 26 Oct 2024 11:25:44 +0200 Subject: [PATCH 5/7] fix: add forked ether-decode-error lib --- package.json | 2 +- static/scripts/rewards/web3/erc20-permit.ts | 2 +- static/scripts/rewards/web3/erc721-permit.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 7345c4e3..3f0f796d 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "countries-and-timezones": "^3.6.0", "dotenv": "^16.4.4", "ethers": "^5.7.2", - "ethers-decode-error": "^1.0.0", + "@ariesgun/ethers-decode-error": "^1.1.0", "npm-run-all": "^4.1.5", "zod": "^3.23.8" }, diff --git a/static/scripts/rewards/web3/erc20-permit.ts b/static/scripts/rewards/web3/erc20-permit.ts index 6ad632a1..90495f83 100644 --- a/static/scripts/rewards/web3/erc20-permit.ts +++ b/static/scripts/rewards/web3/erc20-permit.ts @@ -9,7 +9,7 @@ import { buttonController, getMakeClaimButton, viewClaimButton } from "../button import { toaster, errorToast, MetaMaskError } from "../toaster"; import { connectWallet } from "./connect-wallet"; import { convertToNetworkId } from "./use-rpc-handler"; -import { decodeError } from "ethers-decode-error"; +import { decodeError } from "@ariesgun/ethers-decode-error"; // import { decodeError } from "./error-decoder"; export async function fetchTreasury(permit: Permit): Promise<{ balance: BigNumber; allowance: BigNumber; decimals: number; symbol: string }> { diff --git a/static/scripts/rewards/web3/erc721-permit.ts b/static/scripts/rewards/web3/erc721-permit.ts index cd40ae59..d346c936 100644 --- a/static/scripts/rewards/web3/erc721-permit.ts +++ b/static/scripts/rewards/web3/erc721-permit.ts @@ -6,7 +6,7 @@ import { app } from "../app-state"; import { errorToast, MetaMaskError, toaster } from "../toaster"; import { buttonController, getMakeClaimButton } from "../button-controller"; import { connectWallet } from "./connect-wallet"; -import { decodeError } from "ethers-decode-error"; +import { decodeError } from "@ariesgun/ethers-decode-error"; export function claimErc721PermitHandler(reward: ERC721Permit) { return async function claimHandler() { From 980d99f1669d9522c9402cb0211041e658f2e715 Mon Sep 17 00:00:00 2001 From: Aries Gunawan Date: Sat, 26 Oct 2024 06:02:20 -0400 Subject: [PATCH 6/7] fix: cleanup --- static/scripts/rewards/web3/erc20-permit.ts | 11 ++++++----- static/scripts/rewards/web3/erc721-permit.ts | 5 +---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/static/scripts/rewards/web3/erc20-permit.ts b/static/scripts/rewards/web3/erc20-permit.ts index 90495f83..44a37a44 100644 --- a/static/scripts/rewards/web3/erc20-permit.ts +++ b/static/scripts/rewards/web3/erc20-permit.ts @@ -10,7 +10,6 @@ import { toaster, errorToast, MetaMaskError } from "../toaster"; import { connectWallet } from "./connect-wallet"; import { convertToNetworkId } from "./use-rpc-handler"; import { decodeError } from "@ariesgun/ethers-decode-error"; -// import { decodeError } from "./error-decoder"; export async function fetchTreasury(permit: Permit): Promise<{ balance: BigNumber; allowance: BigNumber; decimals: number; symbol: string }> { let balance: BigNumber, allowance: BigNumber, decimals: number, symbol: string; @@ -91,6 +90,7 @@ export async function transferFromPermit(permit2Contract: Contract, reward: Perm buttonController.hideLoader(); buttonController.showMakeClaim(); } else { + console.error(e); const { error } = decodeError(e, permit2Abi); errorToast(e, `Error in permitTransferFrom: ${error}`); } @@ -273,11 +273,12 @@ invalidateButton.addEventListener("click", async function invalidateButtonClickH if (!app.signer) return; await invalidateNonce(app.signer, app.reward.nonce); - } catch (error: unknown) { - if (error instanceof Error) { - const e = error as unknown as MetaMaskError; + } catch (err: unknown) { + if (err instanceof Error) { + const e = err as unknown as MetaMaskError; console.error(e); - errorToast(e, e.reason); + const { error } = decodeError(e, permit2Abi); + errorToast(e, `Error in invalidateNonce: ${error}`); return; } } diff --git a/static/scripts/rewards/web3/erc721-permit.ts b/static/scripts/rewards/web3/erc721-permit.ts index d346c936..adc26039 100644 --- a/static/scripts/rewards/web3/erc721-permit.ts +++ b/static/scripts/rewards/web3/erc721-permit.ts @@ -32,11 +32,8 @@ export function claimErc721PermitHandler(reward: ERC721Permit) { } buttonController.showLoader(); - - const nftContract = new ethers.Contract(reward.tokenAddress, nftRewardAbi, signer); - if (!nftContract) return; - try { + const nftContract = new ethers.Contract(reward.tokenAddress, nftRewardAbi, signer); const tx: TransactionResponse = await nftContract.safeMint( { beneficiary: reward.beneficiary, From 50809a3b304d1d8dbbb777ae35c5ab80b29ee284 Mon Sep 17 00:00:00 2001 From: Aries Thio Date: Sun, 1 Dec 2024 22:13:02 +0100 Subject: [PATCH 7/7] feat: updated package ethers-decode-error --- package.json | 2 +- static/scripts/rewards/web3/erc20-permit.ts | 2 +- static/scripts/rewards/web3/erc721-permit.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index b8ae61d3..dc7de2e6 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "countries-and-timezones": "^3.6.0", "dotenv": "^16.4.4", "ethers": "^5.7.2", - "@ariesgun/ethers-decode-error": "^1.1.0", + "@ubiquity-os/ethers-decode-error": "^1.1.0", "npm-run-all": "^4.1.5", "zod": "^3.23.8" }, diff --git a/static/scripts/rewards/web3/erc20-permit.ts b/static/scripts/rewards/web3/erc20-permit.ts index 44a37a44..bcc027de 100644 --- a/static/scripts/rewards/web3/erc20-permit.ts +++ b/static/scripts/rewards/web3/erc20-permit.ts @@ -9,7 +9,7 @@ import { buttonController, getMakeClaimButton, viewClaimButton } from "../button import { toaster, errorToast, MetaMaskError } from "../toaster"; import { connectWallet } from "./connect-wallet"; import { convertToNetworkId } from "./use-rpc-handler"; -import { decodeError } from "@ariesgun/ethers-decode-error"; +import { decodeError } from "@ubiquity-os/ethers-decode-error"; export async function fetchTreasury(permit: Permit): Promise<{ balance: BigNumber; allowance: BigNumber; decimals: number; symbol: string }> { let balance: BigNumber, allowance: BigNumber, decimals: number, symbol: string; diff --git a/static/scripts/rewards/web3/erc721-permit.ts b/static/scripts/rewards/web3/erc721-permit.ts index adc26039..5f452cdd 100644 --- a/static/scripts/rewards/web3/erc721-permit.ts +++ b/static/scripts/rewards/web3/erc721-permit.ts @@ -6,7 +6,7 @@ import { app } from "../app-state"; import { errorToast, MetaMaskError, toaster } from "../toaster"; import { buttonController, getMakeClaimButton } from "../button-controller"; import { connectWallet } from "./connect-wallet"; -import { decodeError } from "@ariesgun/ethers-decode-error"; +import { decodeError } from "@ubiquity-os/ethers-decode-error"; export function claimErc721PermitHandler(reward: ERC721Permit) { return async function claimHandler() {