Move from web3modal to walletconnect v2 (#64)

Co-authored-by: Gregorio Granado Magalhaes <greg.magalhaes@gmail.com>
This commit is contained in:
Simon Bihel 2023-06-22 17:21:15 +01:00 committed by GitHub
parent 3278ff752a
commit 1c29815376
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 4650 additions and 18750 deletions

View File

@ -14,9 +14,7 @@ COPY --from=dep_planner /siwe-oidc/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json RUN cargo chef cook --release --recipe-path recipe.json
FROM node:16-alpine as node_builder FROM node:16-alpine as node_builder
ENV FORTMATIC_KEY="" ENV PROJECT_ID=""
ENV INFURA_ID=""
ENV PORTIS_ID=""
ADD --chown=node:node ./static /siwe-oidc/static ADD --chown=node:node ./static /siwe-oidc/static
ADD --chown=node:node ./js/ui /siwe-oidc/js/ui ADD --chown=node:node ./js/ui /siwe-oidc/js/ui
WORKDIR /siwe-oidc/js/ui WORKDIR /siwe-oidc/js/ui

View File

@ -6,6 +6,10 @@ Two versions are available, a stand-alone binary (using Axum and Redis) and a
Cloudflare Worker. They use the same code base and are selected at compile time Cloudflare Worker. They use the same code base and are selected at compile time
(compiling for `wasm32` will make the Worker version). (compiling for `wasm32` will make the Worker version).
> The front-end depends on WalletConnect, meaning you will need to create a
> project with them and have the environment variable `PROJECT_ID` set when you
> build the front-end.
### Cloudflare Worker ### Cloudflare Worker
You will need [`wrangler`](https://github.com/cloudflare/wrangler). You will need [`wrangler`](https://github.com/cloudflare/wrangler).
@ -52,8 +56,9 @@ siweoidc.example.com/.w*
### Stand-Alone Binary ### Stand-Alone Binary
> Note that currently the published Docker image doesn't support all wallets due > **WARNING - ** Due to the reliance on WalletConnect, and the project ID being
> to the need of bundling secrets for web3modal at compile-time. > loaded at compile-time, the current version of the Docker image won't have a
> working web app.
#### Dependencies #### Dependencies

23226
js/ui/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -33,12 +33,12 @@
"svelte": "^3.49.0", "svelte": "^3.49.0",
"svelte-check": "^2.2.11", "svelte-check": "^2.2.11",
"svelte-loader": "^3.0.0", "svelte-loader": "^3.0.0",
"svelte-preprocess": "^4.3.0", "svelte-preprocess": "^5.0.4",
"svg-url-loader": "^7.1.1", "svg-url-loader": "^7.1.1",
"tailwindcss": "^3.0.9", "tailwindcss": "^3.0.9",
"ts-loader": "^9.2.6", "ts-loader": "^9.2.6",
"tslib": "^2.0.1", "tslib": "^2.0.1",
"typescript": "^4.0.3", "typescript": "^5.1.3",
"webpack": "^5.76.0", "webpack": "^5.76.0",
"webpack-cli": "^4.4.0", "webpack-cli": "^4.4.0",
"webpack-dev-server": "^4.6.0" "webpack-dev-server": "^4.6.0"
@ -49,12 +49,12 @@
"validate": "svelte-check" "validate": "svelte-check"
}, },
"dependencies": { "dependencies": {
"@coinbase/wallet-sdk": "^3.0.5", "@wagmi/core": "^1.2.0",
"@portis/web3": "^4.0.6", "@web3modal/ethereum": "^2.4.5",
"@spruceid/siwe-web3modal": "^0.1.11", "@web3modal/html": "^2.4.5",
"@toruslabs/torus-embed": "^1.21.0", "js-cookie": "^3.0.5",
"@walletconnect/web3-provider": "^1.7.7", "siwe": "^2.1.4",
"fortmatic": "^2.2.1", "url": "^0.11.0",
"url": "^0.11.0" "viem": "^1.0.6"
} }
} }

View File

@ -1,11 +1,12 @@
<script lang="ts"> <script lang="ts">
import Portis from '@portis/web3';
import { Client } from '@spruceid/siwe-web3modal';
import Torus from '@toruslabs/torus-embed';
import WalletConnectProvider from '@walletconnect/web3-provider';
import Fortmatic from 'fortmatic';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import CoinbaseWalletSDK from "@coinbase/wallet-sdk"; import { EthereumClient, w3mConnectors, w3mProvider } from '@web3modal/ethereum';
import { Web3Modal } from '@web3modal/html';
import { configureChains, createConfig } from '@wagmi/core';
import { arbitrum, mainnet, polygon } from '@wagmi/core/chains';
import { getAccount } from '@wagmi/core';
import { SiweMessage } from 'siwe';
import Cookies from 'js-cookie';
// TODO: REMOVE DEFAULTS: // TODO: REMOVE DEFAULTS:
// main.ts will parse the params from the server // main.ts will parse the params from the server
@ -15,57 +16,20 @@
export let state: string; export let state: string;
export let oidc_nonce: string; export let oidc_nonce: string;
export let client_id: string; export let client_id: string;
const projectId: string = process.env.PROJECT_ID;
// Could be exposed in the future.
export let useENS: boolean = true;
$: status = 'Not Logged In'; $: status = 'Not Logged In';
let client = new Client({ const chains = [arbitrum, mainnet, polygon];
session: {
domain: window.location.host, const { publicClient } = configureChains(chains, [w3mProvider({ projectId })]);
uri: window.location.origin, const wagmiConfig = createConfig({
useENS, autoConnect: true,
version: '1', connectors: w3mConnectors({ projectId, version: 1, chains }),
// TODO: Vet this as the default statement. publicClient,
statement: `You are signing-in to ${domain}.`,
resources: [redirect],
},
modal: {
theme: 'dark',
providerOptions: {
walletconnect: {
package: WalletConnectProvider,
options: {
infuraId: process.env.INFURA_ID,
pollingInterval: 100000,
},
},
torus: {
package: Torus,
},
portis: {
package: Portis,
options: {
id: process.env.PORTIS_ID,
},
},
fortmatic: {
package: Fortmatic,
options: {
key: process.env.FORTMATIC_KEY,
},
},
walletlink: {
package: CoinbaseWalletSDK,
options: {
appName: "Sign-In with Ethereum",
infuraId: process.env.INFURA_ID
}
},
},
},
}); });
const ethereumClient = new EthereumClient(wagmiConfig, chains);
const web3modal = new Web3Modal({ projectId }, ethereumClient);
let client_metadata = {}; let client_metadata = {};
onMount(async () => { onMount(async () => {
@ -75,19 +39,58 @@
console.error(e); console.error(e);
} }
}); });
web3modal.subscribeModal(async () => {
const account = getAccount();
if (account.isConnected) {
try {
const expirationTime = new Date(
new Date().getTime() + (2 * 24 * 60 * 60 * 1000) // 48h
);
const signMessage = new SiweMessage({
domain: window.location.host,
address: account.address,
chainId: await account.connector.getChainId(),
expirationTime: expirationTime.toISOString(),
uri: window.location.origin,
version: '1',
statement: `You are signing-in to ${window.location.host}.`,
nonce,
resources: [redirect],
}).prepareMessage();
const signature = await (
await account.connector.getWalletClient()
).signMessage({
account: account.address,
message: signMessage,
});
const message = new SiweMessage(signMessage);
const session = {
message,
raw: signMessage,
signature,
};
Cookies.set('siwe', JSON.stringify(session), {
expires: expirationTime,
});
window.location.replace(
`/sign_in?redirect_uri=${encodeURI(redirect)}&state=${encodeURI(state)}&client_id=${encodeURI(
client_id,
)}${encodeURI(oidc_nonce_param)}`,
);
return;
} catch (e) {
console.error(e);
}
}
});
let oidc_nonce_param = ''; let oidc_nonce_param = '';
if (oidc_nonce != null && oidc_nonce != '') { if (oidc_nonce != null && oidc_nonce != '') {
oidc_nonce_param = `&oidc_nonce=${oidc_nonce}`; oidc_nonce_param = `&oidc_nonce=${oidc_nonce}`;
} }
client.on('signIn', (result) => {
console.log(result);
window.location.replace(
`/sign_in?redirect_uri=${encodeURI(redirect)}&state=${encodeURI(state)}&client_id=${encodeURI(
client_id,
)}${encodeURI(oidc_nonce_param)}`,
);
});
</script> </script>
<div <div
@ -111,9 +114,7 @@
<button <button
class="h-12 border hover:scale-105 justify-evenly shadow-xl border-white mt-4 duration-100 ease-in-out transition-all transform flex items-center" class="h-12 border hover:scale-105 justify-evenly shadow-xl border-white mt-4 duration-100 ease-in-out transition-all transform flex items-center"
on:click={() => { on:click={() => {
client.signIn(nonce).catch((e) => { web3modal.openModal();
console.error(e);
});
}} }}
> >
<svg <svg

View File

@ -3,6 +3,7 @@
"include": ["src/**/*", "src/node_modules/**/*"], "include": ["src/**/*", "src/node_modules/**/*"],
"exclude": ["node_modules/*", "__sapper__/*", "static/*"], "exclude": ["node_modules/*", "__sapper__/*", "static/*"],
"compilerOptions": { "compilerOptions": {
"types": ["node", "svelte"] "types": ["node", "svelte"],
"ignoreDeprecations": "5.0"
} }
} }

View File

@ -8,7 +8,7 @@ const prod = mode === 'production';
module.exports = { module.exports = {
entry: { entry: {
'build/bundle': ['./src/main.ts'] 'bundle': ['./src/main.ts']
}, },
resolve: { resolve: {
alias: { alias: {
@ -31,8 +31,12 @@ module.exports = {
// util: false, // util: false,
} }
}, },
optimization: {
runtimeChunk: 'single',
},
output: { output: {
path: path.join(__dirname, '../../static'), path: path.join(__dirname, '../../static/build'),
publicPath: "/build/",
filename: '[name].js', filename: '[name].js',
chunkFilename: '[name].[id].js' chunkFilename: '[name].[id].js'
}, },
@ -96,7 +100,7 @@ module.exports = {
new MiniCssExtractPlugin({ new MiniCssExtractPlugin({
filename: '[name].css' filename: '[name].css'
}), }),
new webpack.EnvironmentPlugin(prod ? ['INFURA_ID', 'PORTIS_ID', 'FORTMATIC_KEY'] : []), new webpack.EnvironmentPlugin(prod ? ['PROJECT_ID'] : []),
], ],
devtool: prod ? false : 'source-map', devtool: prod ? false : 'source-map',
devServer: { devServer: {

View File

@ -10,6 +10,7 @@
<link rel="stylesheet" href="/build/bundle.css" /> <link rel="stylesheet" href="/build/bundle.css" />
<script defer src="/build/bundle.js"></script> <script defer src="/build/bundle.js"></script>
<script defer src="/build/runtime.js"></script>
<link <link
href="https://api.fontshare.com/css?f[]=satoshi@300,301,400,401,500,501,700,701,900,901,1,2&display=swap" href="https://api.fontshare.com/css?f[]=satoshi@300,301,400,401,500,501,700,701,900,901,1,2&display=swap"
rel="stylesheet" rel="stylesheet"