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

Fix for the Alchemy URL and SIWE verification for ERC-1271 #1638

Merged
merged 2 commits into from
Jul 4, 2024
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
12 changes: 9 additions & 3 deletions web/netlify/functions/authUser.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import middy from "@middy/core";
import jsonBodyParser from "@middy/http-json-body-parser";
import { createClient } from "@supabase/supabase-js";
import { ethers } from "ethers";
import * as jwt from "jose";
import { SiweMessage } from "siwe";

import { ETH_SIGNATURE_REGEX, DEFAULT_CHAIN } from "consts/processEnvConsts";
import { ETH_SIGNATURE_REGEX, DEFAULT_CHAIN, isProductionDeployment } from "consts/processEnvConsts";

import { netlifyUri, netlifyDeployUri, netlifyDeployPrimeUri } from "src/generatedNetlifyInfo.json";
import { Database } from "src/types/supabase-notification";
Expand Down Expand Up @@ -73,9 +74,14 @@ const authUser = async (event) => {
}

try {
await siweMessage.verify({ signature, nonce: nonceData.nonce, time: new Date().toISOString() });
// If the main Alchemy API key is permissioned, it won't work in a Netlify Function so we use a dedicated API key
const alchemyApiKey = process.env.ALCHEMY_FUNCTIONS_API_KEY ?? process.env.ALCHEMY_API_KEY;
const alchemyChain = isProductionDeployment() ? "arb-mainnet" : "arb-sepolia";
const alchemyRpcURL = `https://${alchemyChain}.g.alchemy.com/v2/${alchemyApiKey}`;
const provider = new ethers.providers.JsonRpcProvider(alchemyRpcURL);
await siweMessage.verify({ signature, nonce: nonceData.nonce, time: new Date().toISOString() }, { provider });
} catch (err) {
throw new Error("Invalid signer");
throw new Error("Invalid signer: " + JSON.stringify(err));
}

const { error } = await supabase.from("user-nonce").delete().match({ address: lowerCaseAddress });
Expand Down
5 changes: 4 additions & 1 deletion web/src/consts/chains.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { extractChain } from "viem";
import { Chain, arbitrum, mainnet, arbitrumSepolia, gnosisChiado } from "viem/chains";
import { Chain, arbitrum, mainnet, arbitrumSepolia, gnosis, gnosisChiado } from "viem/chains";

import { isProductionDeployment } from "./index";

export const DEFAULT_CHAIN = isProductionDeployment() ? arbitrum.id : arbitrumSepolia.id;

// Read/Write
export const SUPPORTED_CHAINS: Record<number, Chain> = {
[isProductionDeployment() ? arbitrum.id : arbitrumSepolia.id]: isProductionDeployment() ? arbitrum : arbitrumSepolia,
};

// Read Only
export const QUERY_CHAINS: Record<number, Chain> = {
[gnosisChiado.id]: gnosisChiado,
[gnosis.id]: gnosis,
[mainnet.id]: mainnet,
};

Expand Down
59 changes: 42 additions & 17 deletions web/src/context/Web3Provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,59 @@ import React from "react";
import { createWeb3Modal } from "@web3modal/wagmi/react";
import { type Chain } from "viem";
import { createConfig, fallback, http, WagmiProvider, webSocket } from "wagmi";
import { mainnet, arbitrumSepolia, arbitrum, gnosisChiado } from "wagmi/chains";
import { mainnet, arbitrumSepolia, arbitrum, gnosisChiado, gnosis, sepolia } from "wagmi/chains";
import { walletConnect } from "wagmi/connectors";

import { ALL_CHAINS } from "consts/chains";
import { ALL_CHAINS, DEFAULT_CHAIN } from "consts/chains";
import { isProductionDeployment } from "consts/index";

import { lightTheme } from "styles/themes";

const projectId = import.meta.env.WALLETCONNECT_PROJECT_ID ?? "";
export const alchemyApiKey = import.meta.env.ALCHEMY_API_KEY ?? "";
const alchemyApiKey = import.meta.env.ALCHEMY_API_KEY ?? "";
const isProduction = isProductionDeployment();

const chains = ALL_CHAINS as [Chain, ...Chain[]];
// https://github.com/alchemyplatform/alchemy-sdk-js/blob/96b3f62/src/types/types.ts#L98-L119
const alchemyToViemChain = {
[arbitrum.id]: "arb-mainnet",
[arbitrumSepolia.id]: "arb-sepolia",
[mainnet.id]: "eth-mainnet",
[sepolia.id]: "eth-sepolia",
};

type AlchemyProtocol = "https" | "wss";
type AlchemyChain = "arb-sepolia" | "eth-mainnet" | "arb";
const alchemyURL = (protocol: AlchemyProtocol, chain: AlchemyChain) =>
`${protocol}://${chain}.g.alchemy.com/v2/${alchemyApiKey}`;
const alchemyTransport = (chain: AlchemyChain) =>
fallback([webSocket(alchemyURL("wss", chain)), http(alchemyURL("https", chain))]);

const transports = {
[isProductionDeployment() ? arbitrum.id : arbitrumSepolia.id]: isProductionDeployment()
? alchemyTransport("arb")
: alchemyTransport("arb-sepolia"),
[mainnet.id]: alchemyTransport("eth-mainnet"),
[gnosisChiado.id]: fallback([webSocket("wss://rpc.chiadochain.net/wss"), http("https://rpc.chiadochain.net")]),

// https://github.com/alchemyplatform/alchemy-sdk-js/blob/96b3f62/src/util/const.ts#L16-L18
const alchemyURL = (protocol: AlchemyProtocol, chainId: number) =>
`${protocol}://${alchemyToViemChain[chainId]}.g.alchemy.com/v2/${alchemyApiKey}`;

export const getChainRpcUrl = (protocol: AlchemyProtocol, chainId: number) => {
return alchemyURL(protocol, chainId);
};

export const getDefaultChainRpcUrl = (protocol: AlchemyProtocol) => {
return getChainRpcUrl(protocol, DEFAULT_CHAIN);
};

export const getTransports = () => {
const alchemyTransport = (chain: Chain) =>
fallback([http(alchemyURL("https", chain.id)), webSocket(alchemyURL("wss", chain.id))]);
const defaultTransport = (chain: Chain) =>
fallback([http(chain.rpcUrls.default?.http?.[0]), webSocket(chain.rpcUrls.default?.webSocket?.[0])]);

return {
[isProduction ? arbitrum.id : arbitrumSepolia.id]: isProduction
? alchemyTransport(arbitrum)
: alchemyTransport(arbitrumSepolia),
[isProduction ? gnosis.id : gnosisChiado.id]: isProduction
? defaultTransport(gnosis)
: defaultTransport(gnosisChiado),
[mainnet.id]: alchemyTransport(mainnet), // Always enabled for ENS resolution
};
};

const chains = ALL_CHAINS as [Chain, ...Chain[]];
const transports = getTransports();
const projectId = import.meta.env.WALLETCONNECT_PROJECT_ID ?? "";
const wagmiConfig = createConfig({
chains,
transports,
Expand Down
Loading