Skip to content
Closed
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 contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"@types/chai": "^4.2.0",
"@types/mocha": "^10.0.0",
"@types/node": "^16.0.0",
"@wagmi/cli": "^1.5.2",
"@wagmi/cli": "^2.0.3",
"abitype": "^0.10.3",
"chai": "^4.2.0",
"dotenv": "^16.3.1",
Expand Down
8 changes: 0 additions & 8 deletions web/.parcelrc

This file was deleted.

3 changes: 0 additions & 3 deletions web/netlify.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,3 @@ YARN_ENABLE_GLOBAL_CACHE = "true"

[functions]
directory = "web/netlify/functions/"

[dev]
framework = "parcel"
13 changes: 9 additions & 4 deletions web/netlify/functions/authUser.ts
Original file line number Diff line number Diff line change
@@ -1,11 +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 { DEFAULT_CHAIN } from "consts/chains";
import { ETH_SIGNATURE_REGEX } from "consts/index";
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 @@ -79,9 +79,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
4 changes: 2 additions & 2 deletions web/netlify/functions/getNonce.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import middy from "@middy/core";
import { createClient } from "@supabase/supabase-js";
import { generateNonce } from "siwe";

import { ETH_ADDRESS_REGEX } from "src/consts";
import { ETH_ADDRESS_REGEX } from "src/consts/processEnvConsts";

import { Database } from "../../src/types/supabase-notification";
import { Database } from "src/types/supabase-notification";

import config from "../config";

Expand Down
6 changes: 4 additions & 2 deletions web/netlify/functions/update-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import middy from "@middy/core";
import jsonBodyParser from "@middy/http-json-body-parser";
import { createClient } from "@supabase/supabase-js";

import { EMAIL_REGEX, TELEGRAM_REGEX, ETH_ADDRESS_REGEX } from "../../src/consts/index";
import { Database } from "../../src/types/supabase-notification";
import { EMAIL_REGEX, TELEGRAM_REGEX, ETH_ADDRESS_REGEX } from "consts/processEnvConsts";

import { Database } from "src/types/supabase-notification";

import { authMiddleware } from "../middleware/authMiddleware";

import config from "../config";
Expand Down
37 changes: 18 additions & 19 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"repository": "",
"author": "",
"license": "MIT",
"type": "module",
"alias": {
"src": "./src",
"utils": "./src/utils",
Expand All @@ -25,16 +26,15 @@
"node": "20.11.0"
},
"scripts": {
"clear": "rm -fr ../.parcel-cache dist/bundle.js",
"start": "yarn start-devnet",
"start-local": "scripts/runEnv.sh local 'yarn generate && parcel'",
"start-devnet": "scripts/runEnv.sh devnet 'yarn generate && parcel'",
"start-testnet": "scripts/runEnv.sh testnet 'yarn generate && parcel'",
"start-local": "scripts/runEnv.sh local 'yarn generate && vite'",
"start-devnet": "scripts/runEnv.sh devnet 'yarn generate && vite'",
"start-testnet": "scripts/runEnv.sh testnet 'yarn generate && vite'",
"build": "yarn build-devnet",
"build-local": "scripts/runEnv.sh local 'yarn generate && parcel build'",
"build-devnet": "scripts/runEnv.sh devnet 'yarn generate && parcel build'",
"build-testnet": "scripts/runEnv.sh testnet 'yarn generate && parcel build'",
"build-netlify": "scripts/runEnv.sh devnet 'scripts/generateBuildInfo.sh && yarn generate && parcel build'",
"build-local": "scripts/runEnv.sh local 'yarn generate && vite build'",
"build-devnet": "scripts/runEnv.sh devnet 'yarn generate && vite build'",
"build-testnet": "scripts/runEnv.sh testnet 'yarn generate && vite build'",
"build-netlify": "scripts/runEnv.sh devnet 'scripts/generateBuildInfo.sh && yarn generate && vite build'",
"check-style": "eslint 'src/**/*.{js,jsx,ts,tsx}'",
"check-types": "tsc --noEmit",
"generate": "yarn generate:gql && yarn generate:hooks",
Expand All @@ -47,8 +47,6 @@
"@graphql-codegen/cli": "^4.0.1",
"@graphql-codegen/client-preset": "^4.1.0",
"@netlify/functions": "^1.6.0",
"@parcel/transformer-svg-react": "2.11.0",
"@parcel/watcher": "~2.2.0",
"@types/amqplib": "^0.10.4",
"@types/busboy": "^1.5.3",
"@types/react": "18.2.0",
Expand All @@ -58,16 +56,17 @@
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"@typescript-eslint/utils": "^5.62.0",
"@wagmi/cli": "^1.5.2",
"@wagmi/cli": "^2.0.3",
"eslint": "^8.56.0",
"eslint-config-prettier": "^8.10.0",
"eslint-import-resolver-parcel": "^1.10.6",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"lru-cache": "^7.18.3",
"parcel": "2.11.0",
"supabase": "^1.133.3",
"typescript": "^5.3.3"
"typescript": "^5.3.3",
"vite-plugin-node-polyfills": "^0.21.0",
"vite-plugin-svgr": "^4.2.0",
"vite-tsconfig-paths": "^4.3.2"
},
"dependencies": {
"@cyntler/react-doc-viewer": "^1.16.3",
Expand All @@ -78,9 +77,8 @@
"@sentry/react": "^7.93.0",
"@sentry/tracing": "^7.93.0",
"@supabase/supabase-js": "^2.39.3",
"@tanstack/react-query": "^4.28.0",
"@web3modal/ethereum": "^2.7.1",
"@web3modal/react": "^2.2.2",
"@tanstack/react-query": "^5.40.1",
"@web3modal/wagmi": "^4.1.10",
"@yornaath/batshit": "^0.9.0",
"alchemy-sdk": "^3.3.1",
"amqplib": "^0.10.4",
Expand Down Expand Up @@ -109,7 +107,8 @@
"react-use": "^17.4.3",
"siwe": "^2.3.2",
"styled-components": "^5.3.11",
"viem": "^1.21.4",
"wagmi": "^1.4.13"
"viem": "^2.1.0",
"vite": "^5.2.10",
"wagmi": "^2.2.1"
}
}
9 changes: 5 additions & 4 deletions web/scripts/gitInfo.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/* eslint-disable max-len */
const fs = require("fs");
const path = require("path");
const { execSync } = require("child_process");
const packageJson = require("../package.json");
import fs from "fs";
import path from "path";
import { execSync } from "child_process";

import packageJson from "../package.json" with { type: "json" };

const execSyncWrapper = (command) => {
let stdout = null;
Expand Down
14 changes: 6 additions & 8 deletions web/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import Web3Provider from "context/Web3Provider";
import IsListProvider from "context/IsListProvider";
import QueryClientProvider from "context/QueryClientProvider";
import StyledComponentsProvider from "context/StyledComponentsProvider";
import RefetchOnBlock from "context/RefetchOnBlock";
import GraphqlBatcherProvider from "context/GraphqlBatcher";
import Layout from "layout/index";
import NewTransaction from "./pages/NewTransaction";
Expand All @@ -18,10 +17,9 @@ import AttachmentDisplay from "./pages/AttachmentDisplay";
const App: React.FC = () => {
return (
<StyledComponentsProvider>
<QueryClientProvider>
<RefetchOnBlock />
<GraphqlBatcherProvider>
<Web3Provider>
<Web3Provider>
<QueryClientProvider>
<GraphqlBatcherProvider>
<IsListProvider>
<NewTransactionProvider>
<SentryRoutes>
Expand All @@ -35,9 +33,9 @@ const App: React.FC = () => {
</SentryRoutes>
</NewTransactionProvider>
</IsListProvider>
</Web3Provider>
</GraphqlBatcherProvider>
</QueryClientProvider>
</GraphqlBatcherProvider>
</QueryClientProvider>
</Web3Provider>
</StyledComponentsProvider>
);
};
Expand Down
2 changes: 1 addition & 1 deletion web/src/assets/svgs/icons/book.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 12 additions & 5 deletions web/src/components/ConnectWallet/AccountDisplay.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import React from "react";
import styled, { css } from "styled-components";
import { landscapeStyle } from "styles/landscapeStyle";
import { useAccount, useNetwork, useEnsAvatar, useEnsName } from "wagmi";

import Identicon from "react-identicons";
import { isAddress } from "viem";
import { normalize } from "viem/ens";
import { useAccount, useChainId, useEnsAvatar, useEnsName } from "wagmi";

import { getChain } from "consts/chains";
import { shortenAddress } from "utils/shortenAddress";

import { landscapeStyle } from "styles/landscapeStyle";

const Container = styled.div`
display: flex;
flex-direction: column;
Expand Down Expand Up @@ -110,7 +116,7 @@ export const IdenticonOrAvatar: React.FC<IIdenticonOrAvatar> = ({ size = "16", a
chainId: 1,
});
const { data: avatar } = useEnsAvatar({
name,
name: normalize(name ?? ""),
chainId: 1,
});

Expand All @@ -134,11 +140,12 @@ export const AddressOrName: React.FC<IAddressOrName> = ({ address: propAddress }
chainId: 1,
});

return <label>{data ?? (address && shortenAddress(address))}</label>;
return <label>{data ?? (isAddress(address!) ? shortenAddress(address) : address)}</label>;
};

export const ChainDisplay: React.FC = () => {
const { chain } = useNetwork();
const chainId = useChainId();
const chain = getChain(chainId);
return <label>{chain?.name}</label>;
};

Expand Down
49 changes: 30 additions & 19 deletions web/src/components/ConnectWallet/index.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,57 @@
import React from "react";
import { useAccount, useNetwork, useSwitchNetwork } from "wagmi";
import { useWeb3Modal } from "@web3modal/react";
import React, { useCallback } from "react";
import { useAccount, useChainId, useSwitchChain } from "wagmi";
import { useWeb3Modal, useWeb3ModalState } from "@web3modal/wagmi/react";
import { Button } from "@kleros/ui-components-library";
import { SUPPORTED_CHAINS, DEFAULT_CHAIN } from "consts/chains";
import AccountDisplay from "./AccountDisplay";

export const SwitchChainButton: React.FC = () => {
const { switchNetwork, isLoading } = useSwitchNetwork();
const handleSwitch = () => {
if (!switchNetwork) {
export const SwitchChainButton: React.FC<{ className?: string }> = ({ className }) => {
const { switchChain, isPending } = useSwitchChain();
const handleSwitch = useCallback(() => {
if (!switchChain) {
console.error("Cannot switch network. Please do it manually.");
return;
}
try {
switchNetwork(DEFAULT_CHAIN);
switchChain({ chainId: DEFAULT_CHAIN });
} catch (err) {
console.error(err);
}
};
}, [switchChain]);
return (
<Button
isLoading={isLoading}
disabled={isLoading}
{...{ className }}
isLoading={isPending}
disabled={isPending}
text={`Switch to ${SUPPORTED_CHAINS[DEFAULT_CHAIN].name}`}
onClick={handleSwitch}
/>
);
};

const ConnectButton: React.FC = () => {
const { open, isOpen } = useWeb3Modal();
return <Button disabled={isOpen} small text={"Connect"} onClick={async () => open({ route: "ConnectWallet" })} />;

const ConnectButton: React.FC<{ className?: string }> = ({ className }) => {
const { open } = useWeb3Modal();
const { open: isOpen } = useWeb3ModalState();
return (
<Button
{...{ className }}
disabled={isOpen}
small
text={"Connect"}
onClick={async () => open({ view: "Connect" })}
/>
);
};

const ConnectWallet: React.FC = () => {
const { chain } = useNetwork();
const ConnectWallet: React.FC<{ className?: string }> = ({ className }) => {
const chainId = useChainId();
const { isConnected } = useAccount();
if (isConnected) {
if (chain && chain.id !== DEFAULT_CHAIN) {
return <SwitchChainButton />;
if (chainId !== DEFAULT_CHAIN) {
return <SwitchChainButton {...{ className }} />;
} else return <AccountDisplay />;
} else return <ConnectButton />;
} else return <ConnectButton {...{ className }} />;
};

export default ConnectWallet;
7 changes: 4 additions & 3 deletions web/src/components/EnsureAuth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import React, { useMemo, useState } from "react";

import * as jwt from "jose";
import { SiweMessage } from "siwe";
import { useAccount, useNetwork, useSignMessage } from "wagmi";
import { useAccount, useChainId, useSignMessage } from "wagmi";

import { Button } from "@kleros/ui-components-library";

import { DEFAULT_CHAIN } from "consts/chains";
import { useSessionStorage } from "hooks/useSessionStorage";
import { authoriseUser, getNonce } from "utils/authoriseUser";

import styled from "styled-components";

const Container = styled.div`
Expand Down Expand Up @@ -37,7 +38,7 @@ export const EnsureAuth: React.FC<IEnsureAuth> = ({ children, message, buttonTex

const [authToken, setAuthToken] = useSessionStorage<string | null>("auth-token", localToken);
const { address } = useAccount();
const { chain } = useNetwork();
const chainId = useChainId();

const { signMessageAsync } = useSignMessage();

Expand All @@ -57,7 +58,7 @@ export const EnsureAuth: React.FC<IEnsureAuth> = ({ children, message, buttonTex
setIsLoading(true);
if (!address) return;

const message = await createSiweMessage(address, "Sign In to Kleros with Ethereum.", chain?.id);
const message = await createSiweMessage(address, "Sign In to Kleros with Ethereum.", chainId);

const signature = await signMessageAsync({ message });

Expand Down
6 changes: 3 additions & 3 deletions web/src/components/EnsureChain.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React from "react";
import { DEFAULT_CHAIN } from "consts/chains";
import { useNetwork } from "wagmi";
import { useAccount } from "wagmi";
import ConnectWallet from "components/ConnectWallet";

interface IEnsureChain {
children: React.ReactElement;
}

export const EnsureChain: React.FC<IEnsureChain> = ({ children }) => {
const { chain } = useNetwork();
const { chainId } = useAccount();

return chain && chain.id === DEFAULT_CHAIN ? children : <ConnectWallet />;
return chainId === DEFAULT_CHAIN ? children : <ConnectWallet />;
};
Loading