From ece541288d5f9eadd3e4910b21364cb950252b6e Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sat, 13 Apr 2024 13:26:43 +0100 Subject: [PATCH] chore: build ready --- README.md | 2 +- app/components/grid.tsx | 4 +-- .../account-abstraction/auth0_config.ts | 4 +++ .../smart-account-client.ts | 2 +- app/scripts/rewards/constants.ts | 4 +-- .../read-claim-data-from-url.ts | 4 +++ .../render-transaction/render-token-symbol.ts | 2 +- .../render-transaction/render-transaction.ts | 2 +- app/scripts/rewards/web3/connect-wallet.ts | 12 +++++--- app/scripts/rewards/web3/erc721-permit.ts | 29 ++++++++++++++----- .../rewards/web3/not-on-correct-network.ts | 4 +-- app/scripts/rewards/web3/switch-network.ts | 8 +++-- .../rewards/web3/verify-current-network.ts | 24 +++++++++++---- build/esbuild-build.ts | 4 +-- next.config.mjs | 2 ++ package.json | 2 +- 16 files changed, 76 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 5d1c3307..3b05e647 100644 --- a/README.md +++ b/README.md @@ -109,4 +109,4 @@ mask: 72057594037927936 Notice that this examples uses gnosis chain for nonce invalidation. If you need to invalidate nonce on some other chain then: 1. Set `RPC_PROVIDER_URL` on step 1 to the desired RPC chain provider -2. On step 3 open UI for the desired chain \ No newline at end of file +2. On step 3 open UI for the desired chain diff --git a/app/components/grid.tsx b/app/components/grid.tsx index d4464a62..76644640 100644 --- a/app/components/grid.tsx +++ b/app/components/grid.tsx @@ -175,8 +175,8 @@ export function GridBackground() { function render( canvas: HTMLCanvasElement, gl: WebGLRenderingContext, - timeUniformLocation: WebGLUniformLocation, - resolutionUniformLocation: WebGLUniformLocation + timeUniformLocation: WebGLUniformLocation | null, + resolutionUniformLocation: WebGLUniformLocation | null ) { if (!canvas) return; if (!gl) return; diff --git a/app/scripts/rewards/account-abstraction/auth0_config.ts b/app/scripts/rewards/account-abstraction/auth0_config.ts index 4b639a18..24eac798 100644 --- a/app/scripts/rewards/account-abstraction/auth0_config.ts +++ b/app/scripts/rewards/account-abstraction/auth0_config.ts @@ -1,6 +1,10 @@ const AUTH0_CLIENT_ID = process.env.AUTH0_CLIENT_ID; const AUTH0_DOMAIN = process.env.AUTH0_DOMAIN; +if (!AUTH0_CLIENT_ID || !AUTH0_DOMAIN) { + throw new Error("AUTH0_CLIENT_ID and AUTH0_DOMAIN must be set in the environment"); +} + const AUTH0_CLIENT = { clientId: AUTH0_CLIENT_ID, domain: AUTH0_DOMAIN, diff --git a/app/scripts/rewards/account-abstraction/smart-account-client.ts b/app/scripts/rewards/account-abstraction/smart-account-client.ts index f1f151fb..f44e1269 100644 --- a/app/scripts/rewards/account-abstraction/smart-account-client.ts +++ b/app/scripts/rewards/account-abstraction/smart-account-client.ts @@ -20,7 +20,7 @@ export async function createAAClient(app: AppState) { transport: rpcTransport, chain, signer, - factoryAddress: "", // @TODO: doesn't exist on Gnosis so will need to deploy our own for multi-owner + factoryAddress: "0x", // @TODO: doesn't exist on Gnosis so will need to deploy our own for multi-owner entryPoint: { version: "0.6.0", address: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789", diff --git a/app/scripts/rewards/constants.ts b/app/scripts/rewards/constants.ts index 217efb72..90318003 100644 --- a/app/scripts/rewards/constants.ts +++ b/app/scripts/rewards/constants.ts @@ -3,8 +3,8 @@ import extraRpcList from "../../../lib/chainlist/constants/extraRpcs"; const extraRpcs: Record = {}; Object.keys(extraRpcList).forEach((networkId) => { - const officialUrls = extraRpcList[networkId].rpcs.filter((rpc) => typeof rpc === "string"); - const extraUrls: string[] = extraRpcList[networkId].rpcs.filter((rpc) => rpc.url !== undefined).map((rpc) => rpc.url); + const officialUrls = extraRpcList[networkId].rpcs.filter((rpc: unknown) => typeof rpc === "string"); + const extraUrls: string[] = extraRpcList[networkId].rpcs.filter((rpc: { url: string }) => rpc.url !== undefined).map((rpc: { url: string }) => rpc.url); extraRpcs[networkId] = [...officialUrls, ...extraUrls]; }); diff --git a/app/scripts/rewards/render-transaction/read-claim-data-from-url.ts b/app/scripts/rewards/render-transaction/read-claim-data-from-url.ts index 914b332f..89a1be0d 100644 --- a/app/scripts/rewards/render-transaction/read-claim-data-from-url.ts +++ b/app/scripts/rewards/render-transaction/read-claim-data-from-url.ts @@ -16,6 +16,10 @@ import { RewardPermit, claimTxT } from "./tx-type"; const SUPABASE_URL = process.env.NEXT_PUBLIC_SUPABASE_URL; const SUPABASE_ANON_KEY = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY; +if (!SUPABASE_URL || !SUPABASE_ANON_KEY) { + throw new Error("SUPABASE_URL and SUPABASE_ANON_KEY must be set in the environment"); +} + export const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY); export async function readClaimDataFromUrl(app: AppState) { diff --git a/app/scripts/rewards/render-transaction/render-token-symbol.ts b/app/scripts/rewards/render-transaction/render-token-symbol.ts index 894a5112..0e308351 100644 --- a/app/scripts/rewards/render-transaction/render-token-symbol.ts +++ b/app/scripts/rewards/render-transaction/render-token-symbol.ts @@ -87,7 +87,7 @@ export async function renderNftSymbol({ symbol = storedSymbol; } else { // If the token info is not in localStorage, fetch it from the blockchain - symbol = await contract.read.symbol(); + symbol = (await contract.read.symbol()) as string; // Store the token info in localStorage for future use localStorage.setItem(tokenAddress, JSON.stringify({ symbol })); diff --git a/app/scripts/rewards/render-transaction/render-transaction.ts b/app/scripts/rewards/render-transaction/render-transaction.ts index e3047252..5e8755c3 100644 --- a/app/scripts/rewards/render-transaction/render-transaction.ts +++ b/app/scripts/rewards/render-transaction/render-transaction.ts @@ -29,7 +29,7 @@ export async function renderTransaction(): Promise { return false; } - verifyCurrentNetwork(app.reward.networkId).catch(console.error); + verifyCurrentNetwork(app).catch(console.error); if (permitCheck(app.reward)) { const treasury = await fetchTreasury(app.reward); diff --git a/app/scripts/rewards/web3/connect-wallet.ts b/app/scripts/rewards/web3/connect-wallet.ts index f87d4d02..8b31d28e 100644 --- a/app/scripts/rewards/web3/connect-wallet.ts +++ b/app/scripts/rewards/web3/connect-wallet.ts @@ -2,7 +2,7 @@ import { getButtonController, toaster } from "../toaster"; import { AppState } from "../app-state"; import { verifyCurrentNetwork } from "./verify-current-network"; import { accountAbstractionHandler } from "../account-abstraction/handler"; -import { WalletClient, createWalletClient, custom } from "viem"; +import { CustomTransport, WalletClient, createWalletClient, custom } from "viem"; import { chains } from "@alchemy/aa-core"; export async function connectWallet(app: AppState): Promise { @@ -10,17 +10,21 @@ export async function connectWallet(app: AppState): Promise // take the wallet provider from the window const [account] = await window.ethereum.request({ method: "eth_requestAccounts" }); + const transport: CustomTransport = custom({ + ...window.ethereum, + request: window.ethereum.request.bind(window.ethereum), + }); + const wallet = createWalletClient({ chain: app.networkId === 31337 ? chains.anvil : app.networkId === 1 ? chains.mainnet : chains.gnosis, - transport: custom(window.ethereum), + transport, account, // pinning it so we don't need to re-attach on every write }); // the rewards are populated before the provider is so this is safe - const rewardNetworkId = app.reward.networkId; // verify we are on the correct network immediately - await verifyCurrentNetwork(rewardNetworkId); + await verifyCurrentNetwork(app); // get account access from the wallet provider i.e metamask const accounts = await wallet.requestAddresses(); diff --git a/app/scripts/rewards/web3/erc721-permit.ts b/app/scripts/rewards/web3/erc721-permit.ts index 8aeb7f8e..9a7bde3c 100644 --- a/app/scripts/rewards/web3/erc721-permit.ts +++ b/app/scripts/rewards/web3/erc721-permit.ts @@ -1,10 +1,9 @@ -import { JsonRpcProvider, TransactionResponse } from "@ethersproject/providers"; -import { ethers } from "ethers"; import { nftRewardAbi } from "../abis/nft-reward-abi"; import { app } from "../app-state"; import { Erc721Permit } from "../render-transaction/tx-type"; import { getButtonController, getMakeClaimButton, toaster } from "../toaster"; import { connectWallet } from "./connect-wallet"; +import { PublicClient, WalletClient, getContract } from "viem"; export function claimErc721PermitHandler(reward: Erc721Permit) { return async function claimHandler() { @@ -33,11 +32,15 @@ export function claimErc721PermitHandler(reward: Erc721Permit) { getButtonController().showLoader(); try { - const nftContract = new ethers.Contract(reward.permit.permitted.token, nftRewardAbi, signer); + const nftContract = getContract({ + address: reward.permit.permitted.token as `0x${string}`, + abi: nftRewardAbi, + client: { public: app.provider, wallet: signer as WalletClient }, + }); - const tx: TransactionResponse = await nftContract.safeMint(reward.request, reward.signature); + const tx = await nftContract.write.safeMint([reward.request, reward.signature]); toaster.create("info", `Transaction sent. Waiting for confirmation...`); - const receipt = await tx.wait(); + const receipt = await app.provider.waitForTransactionReceipt({ hash: tx }); getButtonController().hideLoader(); toaster.create("success", `Claim Complete.`); getButtonController().showViewClaim(); @@ -64,7 +67,17 @@ export function claimErc721PermitHandler(reward: Erc721Permit) { }; } -async function isNonceRedeemed(reward: Erc721Permit, provider: JsonRpcProvider): Promise { - const nftContract = new ethers.Contract(reward.permit.permitted.token, nftRewardAbi, provider); - return nftContract.nonceRedeemed(reward.request.nonce); +async function isNonceRedeemed(reward: Erc721Permit, provider: PublicClient | null): Promise { + if (!provider) { + throw new Error("Provider not found"); + } + + const nftContract = getContract({ + address: reward.permit.permitted.token as `0x${string}`, + abi: nftRewardAbi, + client: { public: provider }, + }); + + const data = (await nftContract.read.nonceRedeemed([reward.request.nonce])) as boolean[]; + return data[0]; } diff --git a/app/scripts/rewards/web3/not-on-correct-network.ts b/app/scripts/rewards/web3/not-on-correct-network.ts index dccccc5f..7598ea3a 100644 --- a/app/scripts/rewards/web3/not-on-correct-network.ts +++ b/app/scripts/rewards/web3/not-on-correct-network.ts @@ -1,9 +1,9 @@ -import { ethers } from "ethers"; import { getNetworkName } from "../constants"; import { getButtonController, toaster } from "../toaster"; import { switchNetwork } from "./switch-network"; +import { WalletClient } from "viem"; -export function notOnCorrectNetwork(currentNetworkId: number, desiredNetworkId: number, web3provider: ethers.providers.Web3Provider) { +export function notOnCorrectNetwork(currentNetworkId: number, desiredNetworkId: number, web3provider: WalletClient) { if (currentNetworkId !== desiredNetworkId) { const networkName = getNetworkName(desiredNetworkId); if (!networkName) { diff --git a/app/scripts/rewards/web3/switch-network.ts b/app/scripts/rewards/web3/switch-network.ts index b2f25453..1468fd57 100644 --- a/app/scripts/rewards/web3/switch-network.ts +++ b/app/scripts/rewards/web3/switch-network.ts @@ -1,10 +1,12 @@ -import { ethers } from "ethers"; import { addNetwork } from "./add-network"; import { getButtonController } from "../toaster"; +import { WalletClient } from "viem"; -export async function switchNetwork(provider: ethers.providers.Web3Provider, networkId: number): Promise { +export async function switchNetwork(provider: WalletClient, networkId: number): Promise { try { - await provider.send("wallet_switchEthereumChain", [{ chainId: "0x" + networkId.toString(16) }]); + await provider.switchChain({ + id: networkId, + }); getButtonController().showMakeClaim(); return true; } catch (error: unknown) { diff --git a/app/scripts/rewards/web3/verify-current-network.ts b/app/scripts/rewards/web3/verify-current-network.ts index 1a23f7d6..4c2aab6a 100644 --- a/app/scripts/rewards/web3/verify-current-network.ts +++ b/app/scripts/rewards/web3/verify-current-network.ts @@ -1,21 +1,35 @@ "use client"; -import { ethers } from "ethers"; +import { chains } from "@alchemy/aa-core"; +import { AppState } from "../app-state"; import { getButtonController } from "../toaster"; import { handleIfOnCorrectNetwork } from "./handle-if-on-correct-network"; import { notOnCorrectNetwork } from "./not-on-correct-network"; +import { CustomTransport, createWalletClient, custom } from "viem"; // verifyCurrentNetwork checks if the user is on the correct network and displays an error if not -export async function verifyCurrentNetwork(desiredNetworkId: number) { +export async function verifyCurrentNetwork(app: AppState) { if (!window.ethereum) { getButtonController().hideAll(); return; } - const web3provider = new ethers.providers.Web3Provider(window.ethereum); + const [account] = await window.ethereum.request({ method: "eth_requestAccounts" }); - const network = await web3provider.getNetwork(); - const currentNetworkId = network.chainId; + const transport: CustomTransport = custom({ + ...window.ethereum, + request: window.ethereum.request.bind(window.ethereum), + }); + + const web3provider = createWalletClient({ + chain: app.networkId === 31337 ? chains.anvil : app.networkId === 1 ? chains.mainnet : chains.gnosis, + transport, + account, // pinning it so we don't need to re-attach on every write + }); + + const desiredNetworkId = app.reward.networkId; + + const currentNetworkId = await web3provider.getChainId(); // watch for network changes window.ethereum.on("chainChanged", (newNetworkId: T | string) => handleIfOnCorrectNetwork(parseInt(newNetworkId as string, 16), desiredNetworkId)); diff --git a/build/esbuild-build.ts b/build/esbuild-build.ts index 3b2e734c..c2aa6597 100644 --- a/build/esbuild-build.ts +++ b/build/esbuild-build.ts @@ -9,8 +9,8 @@ const allNetworkUrls: Record = {}; // this flattens all the rpcs into a single object, with key names that match the networkIds. The arrays are just of URLs per network ID. Object.keys(extraRpcs).forEach((networkId) => { - const officialUrls = extraRpcs[networkId].rpcs.filter((rpc) => typeof rpc === "string"); - const extraUrls: string[] = extraRpcs[networkId].rpcs.filter((rpc) => rpc.url !== undefined).map((rpc) => rpc.url); + const officialUrls = extraRpcs[networkId].rpcs.filter((rpc: string) => typeof rpc === "string"); + const extraUrls: string[] = extraRpcs[networkId].rpcs.filter((rpc: { url: string }) => rpc.url !== undefined).map((rpc: { url: string }) => rpc.url); allNetworkUrls[networkId] = [...officialUrls, ...extraUrls]; }); diff --git a/next.config.mjs b/next.config.mjs index 8f5f6c0c..762a815a 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -6,6 +6,8 @@ const nextConfig = { env: { COMMIT_HASH: commitHash, WEB3_AUTH_CLIENT_ID: process.env.WEB3_AUTH_CLIENT_ID, + AUTH0_DOMAIN: process.env.AUTH0_DOMAIN, + AUTH0_CLIENT_ID: process.env.AUTH0_CLIENT_ID, }, }; diff --git a/package.json b/package.json index 78fbc5b1..b541a893 100644 --- a/package.json +++ b/package.json @@ -101,4 +101,4 @@ "@commitlint/config-conventional" ] } -} \ No newline at end of file +}