diff --git a/README.md b/README.md index 2834a357..888ad781 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # ⚡ TurboETH - Web3 App Starter Kit -Web3 App Template built using Next.js, RainbowKit, SIWE, Disco, and more! +Web3 App Template built using Next.js, RainbowKit, SIWE, SpruceKit, Disco, and more! ### Starter Kit Examples diff --git a/app/(general)/integration/sprucekit/layout.tsx b/app/(general)/integration/sprucekit/layout.tsx new file mode 100644 index 00000000..3955cbfb --- /dev/null +++ b/app/(general)/integration/sprucekit/layout.tsx @@ -0,0 +1,9 @@ +'use client' + +import { ReactNode } from 'react' + +import { SpruceKitProvider } from '@/integrations/sprucekit/spruce-kit-provider' + +export default function LayoutIntegration({ children }: { children: ReactNode }) { + return {children} +} diff --git a/app/(general)/integration/sprucekit/opengraph-image.tsx b/app/(general)/integration/sprucekit/opengraph-image.tsx new file mode 100644 index 00000000..ff981f67 --- /dev/null +++ b/app/(general)/integration/sprucekit/opengraph-image.tsx @@ -0,0 +1,9 @@ +import { IntegrationOgImage } from '@/components/ui/social/og-image-integrations' + +export const runtime = 'edge' +export const size = { + width: 1200, + height: 630, +} + +export default IntegrationOgImage('sprucekit') diff --git a/app/(general)/integration/sprucekit/page.tsx b/app/(general)/integration/sprucekit/page.tsx new file mode 100644 index 00000000..14b19da3 --- /dev/null +++ b/app/(general)/integration/sprucekit/page.tsx @@ -0,0 +1,72 @@ +'use client' +import { motion } from 'framer-motion' +import Image from 'next/image' +import Balancer from 'react-wrap-balancer' + +import { WalletConnect } from '@/components/blockchain/wallet-connect' +import { IsDarkTheme } from '@/components/shared/is-dark-theme' +import { IsLightTheme } from '@/components/shared/is-light-theme' +import { IsWalletConnected } from '@/components/shared/is-wallet-connected' +import { IsWalletDisconnected } from '@/components/shared/is-wallet-disconnected' +import { LinkComponent } from '@/components/shared/link-component' +import { FADE_DOWN_ANIMATION_VARIANTS } from '@/config/design' +import { turboIntegrations } from '@/data/turbo-integrations' +import { ButtonSpruceKitLogin } from '@/integrations/sprucekit/components/button-sprucekit-login' +import { ButtonSpruceKitLogout } from '@/integrations/sprucekit/components/button-sprucekit-logout' +import { IsSignedIn } from '@/integrations/sprucekit/components/is-signed-in' +import { IsSignedOut } from '@/integrations/sprucekit/components/is-signed-out' + +export default function PageIntegration() { + return ( +
+ + + Sign-In With Ethereum logo + + + Sign-In With Ethereum logo + + + {turboIntegrations.sprucekit.name} + + + {turboIntegrations.sprucekit.description} + + + + Documentation + + + + +
+ + + + + + + + + + + +
+
+ ) +} diff --git a/app/(general)/integration/sprucekit/twitter-image.tsx b/app/(general)/integration/sprucekit/twitter-image.tsx new file mode 100644 index 00000000..dbca541e --- /dev/null +++ b/app/(general)/integration/sprucekit/twitter-image.tsx @@ -0,0 +1,9 @@ +import Image from './opengraph-image' + +export const runtime = 'edge' +export const size = { + width: 1200, + height: 630, +} + +export default Image diff --git a/app/(general)/page.tsx b/app/(general)/page.tsx index c9b5045e..d15ccd96 100644 --- a/app/(general)/page.tsx +++ b/app/(general)/page.tsx @@ -158,6 +158,16 @@ const features = [ ), }, + { + title: 'SpruceKit', + description: turboIntegrations.sprucekit.description, + href: turboIntegrations.sprucekit.href, + demo: ( +
+ Prisma logo +
+ ), + }, { title: 'Rainbowkit', description: 'The best way to connect a wallet. Designed for everyone. Built for developers.', diff --git a/app/api/ssx/route.ts b/app/api/ssx/route.ts new file mode 100644 index 00000000..0eadaa66 --- /dev/null +++ b/app/api/ssx/route.ts @@ -0,0 +1 @@ +export { GET } from '@/integrations/sprucekit/api' diff --git a/app/api/ssx/ssx-login/route.ts b/app/api/ssx/ssx-login/route.ts new file mode 100644 index 00000000..1276c471 --- /dev/null +++ b/app/api/ssx/ssx-login/route.ts @@ -0,0 +1 @@ +export { POST } from '@/integrations/sprucekit/api/login' diff --git a/app/api/ssx/ssx-logout/route.ts b/app/api/ssx/ssx-logout/route.ts new file mode 100644 index 00000000..4cacfce4 --- /dev/null +++ b/app/api/ssx/ssx-logout/route.ts @@ -0,0 +1 @@ +export { GET } from '@/integrations/sprucekit/api/logout' diff --git a/app/api/ssx/ssx-nonce/route.ts b/app/api/ssx/ssx-nonce/route.ts new file mode 100644 index 00000000..7efbac85 --- /dev/null +++ b/app/api/ssx/ssx-nonce/route.ts @@ -0,0 +1 @@ +export { GET } from '@/integrations/sprucekit/api/nonce' diff --git a/app/api/ssx/ssx-verify/route.ts b/app/api/ssx/ssx-verify/route.ts new file mode 100644 index 00000000..64c5e984 --- /dev/null +++ b/app/api/ssx/ssx-verify/route.ts @@ -0,0 +1 @@ +export { POST } from '@/integrations/sprucekit/api/verify' diff --git a/data/turbo-integrations.ts b/data/turbo-integrations.ts index 9dc5668a..e4a5497e 100644 --- a/data/turbo-integrations.ts +++ b/data/turbo-integrations.ts @@ -7,6 +7,14 @@ export const turboIntegrations = { imgLight: '/integrations/siwe.svg', imgDark: '/integrations/siwe.svg', }, + sprucekit: { + name: 'SpruceKit', + href: '/integration/sprucekit', + url: 'https://sprucekit.dev/', + description: 'The open-source toolkit for decentralized identity.', + imgLight: '/integrations/sprucekit.svg', + imgDark: '/integrations/sprucekit.svg', + }, erc20: { name: 'ERC20', href: '/integration/erc20', diff --git a/integrations/sprucekit/README.md b/integrations/sprucekit/README.md new file mode 100644 index 00000000..ef833fb4 --- /dev/null +++ b/integrations/sprucekit/README.md @@ -0,0 +1,60 @@ +# SpruceKit - TurboETH Integration + +Welcome to the [SpruceKit](https://sprucekit.dev/) TurboETH Integration! This integration provides a secure and straightforward method for users to authenticate themselves using their Ethereum wallets. + +## Features + +- Secure user authentication via their Ethereum wallet. +- Sign-In with Ethereum (SIWE) login and logout functionality. +- Displaying user's account details post-authentication. +- React components to handle various authentication states. + +## API + +### Actions + +`spruceKitLogin()` +Initiates the SSX login process, creating and signing a SIWE message and then verifying it through a backend service. + +`spruceKitLogout()` +Finalize the SSX session and logs out the user by sending a request to the backend logout service. + +### Components + +`BranchButtonLoginOrAccount()` +Renders either a login or logout button and a link to the user's account depending on whether the user is authenticated or not. + +`IsSignedInd()` +A React component that conditionally renders its children if the user is signed in. + +`IsSignedOut()` +A React component that conditionally renders its children if the user is signed out. + +`ButtonSpruceKitLogin()` +A button that initiates the SSX login process when clicked. + +`ButtonSpruceKitLogout()` +A button that initiates the SSX logout process when clicked. + +## File Structure + +``` +integrations/sprucekit +├─ actions/ +│ ├─ spruceki-login.ts +│ ├─ sprucekit-logout.ts +├─ api/ +│ ├─ _ssx.ts +│ ├─ index.ts +│ ├─ login.ts +│ ├─ logout.ts +│ ├─ nonce.ts +│ ├─ verify.ts +├─ components/ +│ ├─ branch-button-login-or-account.tsx +│ ├─ button-sprucekit-login.tsx +│ ├─ button-sprucekit-logout.tsx +│ ├─ is-signed-in.tsx +│ ├─ is-signed-out.tsx +├─ README.md +``` diff --git a/integrations/sprucekit/actions/sprucekit-login.ts b/integrations/sprucekit/actions/sprucekit-login.ts new file mode 100644 index 00000000..d7067aec --- /dev/null +++ b/integrations/sprucekit/actions/sprucekit-login.ts @@ -0,0 +1,23 @@ +import { SiweMessage } from 'siwe' + +interface SpruceKitLoginProps { + message: string + signature: string +} + +export const spruceKitLogin = async ({ message, signature }: SpruceKitLoginProps) => { + // 1. Verify signature + const siweMessage = new SiweMessage(message) + const verifyRes = await fetch('/api/ssx/ssx-verify', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ message: siweMessage, signature }), + }) + + if (!verifyRes.ok) throw new Error('Error verifying message') + if (verifyRes.status === 200) { + dispatchEvent(new Event('verified')) + } +} diff --git a/integrations/sprucekit/actions/sprucekit-logout.ts b/integrations/sprucekit/actions/sprucekit-logout.ts new file mode 100644 index 00000000..bcd3410b --- /dev/null +++ b/integrations/sprucekit/actions/sprucekit-logout.ts @@ -0,0 +1,13 @@ +import axios, { AxiosError } from 'axios' + +export async function spruceKitLogout(): Promise { + try { + await axios.get('/api/ssx/ssx-logout') + return true + } catch (error) { + if (error instanceof AxiosError === true) { + return false + } + throw new Error(`Unexpected Error`) + } +} diff --git a/integrations/sprucekit/api/_ssx.ts b/integrations/sprucekit/api/_ssx.ts new file mode 100644 index 00000000..1b1294a0 --- /dev/null +++ b/integrations/sprucekit/api/_ssx.ts @@ -0,0 +1,9 @@ +import { SSXServer } from '@spruceid/ssx-server' + +import { env } from '@/env.mjs' + +const ssx = new SSXServer({ + signingKey: env.NEXTAUTH_SECRET, +}) + +export default ssx diff --git a/integrations/sprucekit/api/index.ts b/integrations/sprucekit/api/index.ts new file mode 100644 index 00000000..6a07d70d --- /dev/null +++ b/integrations/sprucekit/api/index.ts @@ -0,0 +1,9 @@ +import { getIronSession } from 'iron-session' + +import { SERVER_SESSION_SETTINGS } from '@/lib/session' + +export async function GET(req: Request) { + const res = new Response() + const session = await getIronSession(req, res, SERVER_SESSION_SETTINGS) + return new Response(JSON.stringify({ address: session.siwe?.address })) +} diff --git a/integrations/sprucekit/api/login.ts b/integrations/sprucekit/api/login.ts new file mode 100644 index 00000000..49e80ee8 --- /dev/null +++ b/integrations/sprucekit/api/login.ts @@ -0,0 +1,66 @@ +import { getIronSession } from 'iron-session' +import { cookies } from 'next/headers' +import type { SiweMessage } from 'siwe' +import { z } from 'zod' + +import { env } from '@/env.mjs' +import { prisma } from '@/lib/prisma' +import { SERVER_SESSION_SETTINGS } from '@/lib/session' + +import ssx from './_ssx' + +const admins = env.APP_ADMINS?.split(',') || [] + +const loginSchema = z.object({ + siwe: z.string(), + signature: z.string(), + daoLogin: z.boolean(), + resolveEns: z.boolean(), + resolveLens: z.boolean(), +}) + +interface Session { + session: { + siwe: SiweMessage + } +} + +export async function POST(req: Request) { + try { + const request = loginSchema.safeParse(await req.json()) + if (!request.success) { + return new Response(JSON.stringify({ ok: false })) + } + const cookieStore = cookies() + const nonce = cookieStore.get('nonce') + const { siwe, daoLogin, resolveEns, resolveLens, signature } = request.data + const ssxSession: Session = await ssx.login(siwe, signature, daoLogin, resolveEns, nonce?.value ?? '', resolveLens) + const res = new Response(JSON.stringify({ ok: true })) + const session = await getIronSession(req, res, SERVER_SESSION_SETTINGS) + const fields = ssxSession.session.siwe + session.siwe = fields + + if (admins.includes(fields.address)) { + session.isAdmin = true + } + await session.save() + if (env.DATABASE_URL) { + await prisma.user.upsert({ + where: { id: fields.address }, + update: { + address: fields.address, + }, + create: { + id: fields.address, + address: fields.address, + }, + }) + } + + return new Response(JSON.stringify({ ...ssxSession, ok: true })) + } catch (e) { + const errorMessage = e instanceof Error ? e.message : String(e) + console.error(errorMessage) + return new Response(JSON.stringify({ ok: false })) + } +} diff --git a/integrations/sprucekit/api/logout.ts b/integrations/sprucekit/api/logout.ts new file mode 100644 index 00000000..9e2f9eef --- /dev/null +++ b/integrations/sprucekit/api/logout.ts @@ -0,0 +1,12 @@ +import { getIronSession } from 'iron-session' + +import { SERVER_SESSION_SETTINGS } from '@/lib/session' + +import ssx from './_ssx' + +export async function GET(req: Request) { + const res = new Response(JSON.stringify({ ok: (await ssx.logout()) && true })) + const session = await getIronSession(req, res, SERVER_SESSION_SETTINGS) + session.destroy() + return res +} diff --git a/integrations/sprucekit/api/nonce.ts b/integrations/sprucekit/api/nonce.ts new file mode 100644 index 00000000..b8ff355b --- /dev/null +++ b/integrations/sprucekit/api/nonce.ts @@ -0,0 +1,21 @@ +import { getIronSession } from 'iron-session' + +import { SERVER_SESSION_SETTINGS } from '@/lib/session' + +import ssx from './_ssx' + +export async function GET(req: Request) { + const nonce = ssx.generateNonce() + const res = new Response(nonce, { + headers: { + 'Content-Type': 'text/plain', + 'Set-Cookie': `nonce=${nonce}`, + }, + }) + const session = await getIronSession(req, res, SERVER_SESSION_SETTINGS) + session.destroy() + session.nonce = nonce + await session.save() + + return res +} diff --git a/integrations/sprucekit/api/verify.ts b/integrations/sprucekit/api/verify.ts new file mode 100644 index 00000000..7c56695b --- /dev/null +++ b/integrations/sprucekit/api/verify.ts @@ -0,0 +1,58 @@ +import { getIronSession } from 'iron-session' +import { SiweMessage } from 'siwe' +import { z } from 'zod' + +import { env } from '@/env.mjs' +import { prisma } from '@/lib/prisma' +import { SERVER_SESSION_SETTINGS } from '@/lib/session' + +const admins = env.APP_ADMINS?.split(',') || [] + +const verifySchema = z.object({ + signature: z.string(), + message: z.object({ + domain: z.string(), + address: z.string(), + statement: z.string(), + uri: z.string(), + version: z.string(), + chainId: z.number(), + nonce: z.string(), + issuedAt: z.string(), + }), +}) + +export async function POST(req: Request) { + try { + const res = new Response(JSON.stringify({ ok: true })) + const session = await getIronSession(req, res, SERVER_SESSION_SETTINGS) + const { message, signature } = verifySchema.parse(await req.json()) + const siweMessage = new SiweMessage(message) + const { data: fields } = await siweMessage.verify({ signature }) + if (fields.nonce !== session.nonce) return new Response(JSON.stringify({ message: 'Invalid nonce.' }), { status: 422 }) + session.siwe = fields + + if (admins.includes(fields.address)) { + session.isAdmin = true + } + await session.save() + if (env.DATABASE_URL) { + await prisma.user.upsert({ + where: { id: fields.address }, + update: { + address: fields.address, + }, + create: { + id: fields.address, + address: fields.address, + }, + }) + } + + return res + } catch (e) { + const errorMessage = e instanceof Error ? e.message : String(e) + console.error(errorMessage) + return new Response(JSON.stringify({ ok: false })) + } +} diff --git a/integrations/sprucekit/components/branch-button-login-or-account.tsx b/integrations/sprucekit/components/branch-button-login-or-account.tsx new file mode 100644 index 00000000..fe37b9bb --- /dev/null +++ b/integrations/sprucekit/components/branch-button-login-or-account.tsx @@ -0,0 +1,33 @@ +import { IsWalletConnected } from '@/components/shared/is-wallet-connected' +import { LinkComponent } from '@/components/shared/link-component' +import { ButtonSpruceKitLogin } from '@/integrations/sprucekit/components/button-sprucekit-login' +import { ButtonSpruceKitLogout } from '@/integrations/sprucekit/components/button-sprucekit-logout' +import { cn } from '@/lib/utils' + +import { IsSignedIn } from './is-signed-in' +import { IsSignedOut } from './is-signed-out' + +interface BranchButtonLoginOrAccountProps { + classNameButtonLogin?: string + classNameButtonLogout?: string +} + +export const BranchButtonLoginOrAccount = ({ classNameButtonLogin, classNameButtonLogout }: BranchButtonLoginOrAccountProps) => { + return ( + + +
+ + + Account + +
+
+ + + +
+ ) +} + +export default BranchButtonLoginOrAccount diff --git a/integrations/sprucekit/components/button-sprucekit-login.tsx b/integrations/sprucekit/components/button-sprucekit-login.tsx new file mode 100644 index 00000000..4f5b8da2 --- /dev/null +++ b/integrations/sprucekit/components/button-sprucekit-login.tsx @@ -0,0 +1,51 @@ +'use client' + +import { HTMLAttributes, useState } from 'react' + +import { useSSX } from '@spruceid/ssx-react' +import { useAccount, useNetwork } from 'wagmi' + +import { spruceKitLogin } from '@/integrations/sprucekit/actions/sprucekit-login' +import { useUser } from '@/lib/hooks/use-user' +import { cn } from '@/lib/utils' + +interface ButtonSpruceKitLoginProps extends HTMLAttributes { + label?: string + disabled?: boolean +} +export const ButtonSpruceKitLogin = ({ className, label = 'Sign-In With Ethereum', disabled, children, ...props }: ButtonSpruceKitLoginProps) => { + const { mutateUser } = useUser() + const { address } = useAccount() + const { chain } = useNetwork() + const { ssx } = useSSX() + + const [isLoading, setIsLoading] = useState(false) + + const isInvalid = !address || !chain?.id || !ssx + + const handleCreateMessage = async () => { + setIsLoading(true) + try { + if (isInvalid) return + + const { siwe, signature } = await ssx.signIn() + + await spruceKitLogin({ message: siwe, signature }) + await mutateUser() + } catch (error) { + console.error(error) + } + setIsLoading(false) + } + const classes = cn('relative', className) + const labelClasses = cn({ + 'opacity-0': isLoading, + }) + + return ( + + ) +} diff --git a/integrations/sprucekit/components/button-sprucekit-logout.tsx b/integrations/sprucekit/components/button-sprucekit-logout.tsx new file mode 100644 index 00000000..1e691541 --- /dev/null +++ b/integrations/sprucekit/components/button-sprucekit-logout.tsx @@ -0,0 +1,31 @@ +'use client' + +import { HTMLAttributes } from 'react' + +import { useSSX } from '@spruceid/ssx-react' + +import { spruceKitLogout } from '@/integrations/sprucekit/actions/sprucekit-logout' +import { useUser } from '@/lib/hooks/use-user' + +interface ButtonSpruceKitLogoutProps extends HTMLAttributes { + label?: string +} + +export const ButtonSpruceKitLogout = ({ className, label = 'Logout', children, ...props }: ButtonSpruceKitLogoutProps) => { + const { mutateUser } = useUser() + const { ssx } = useSSX() + const handleLogout = async () => { + try { + await ssx?.signOut?.() + } catch (e) { + await spruceKitLogout() + } + await mutateUser() + } + + return ( + + ) +} diff --git a/integrations/sprucekit/components/is-signed-in.tsx b/integrations/sprucekit/components/is-signed-in.tsx new file mode 100644 index 00000000..af223c55 --- /dev/null +++ b/integrations/sprucekit/components/is-signed-in.tsx @@ -0,0 +1,17 @@ +'use client' + +import { ReactNode } from 'react' + +import { useUser } from '@/lib/hooks/use-user' + +interface IsSignedInProps { + children: ReactNode +} + +export const IsSignedIn = ({ children }: IsSignedInProps) => { + const { user } = useUser() + + if (user?.isLoggedIn) return <>{children} + + return null +} diff --git a/integrations/sprucekit/components/is-signed-out.tsx b/integrations/sprucekit/components/is-signed-out.tsx new file mode 100644 index 00000000..f20b39db --- /dev/null +++ b/integrations/sprucekit/components/is-signed-out.tsx @@ -0,0 +1,17 @@ +'use client' + +import { ReactNode } from 'react' + +import { useUser } from '@/lib/hooks/use-user' + +interface IsSignedOutProps { + children: ReactNode +} + +export const IsSignedOut = ({ children }: IsSignedOutProps) => { + const { user } = useUser() + + if (!user?.isLoggedIn) return <>{children} + + return null +} diff --git a/integrations/sprucekit/spruce-kit-provider.tsx b/integrations/sprucekit/spruce-kit-provider.tsx new file mode 100644 index 00000000..e9170d02 --- /dev/null +++ b/integrations/sprucekit/spruce-kit-provider.tsx @@ -0,0 +1,37 @@ +import type { ReactNode } from 'react' + +import { SSXProvider } from '@spruceid/ssx-react' +import { useWalletClient } from 'wagmi' + +import { siteConfig } from '@/config/site' + +const ssxConfig = { + providers: { + server: { + host: `${window.location.origin}/api/ssx`, + routes: { + logout: { + method: 'get', + }, + }, + }, + }, + siweConfig: { + statement: `Sign in with Ethereum to ${siteConfig.name}`, + uri: window.location.origin, + }, +} + +export function SpruceKitProvider({ children }: { children: ReactNode }) { + const { data: walletClient } = useWalletClient() + + const web3Provider = { + provider: walletClient, + } + + return ( + + {children} + + ) +} diff --git a/package.json b/package.json index 52313e4c..14e58365 100644 --- a/package.json +++ b/package.json @@ -37,11 +37,11 @@ }, "packageManager": "pnpm@7.1.8", "dependencies": { - "@hookform/resolvers": "^3.1.1", "@connext/nxtp-utils": "^2.0.3", "@connext/sdk": "2.0.4-alpha.2", "@gelatonetwork/automate-sdk": "^2.14.0", "@graphql-typed-document-node/core": "^3.2.0", + "@hookform/resolvers": "^3.1.1", "@lit-protocol/lit-node-client": "2.1.161", "@livepeer/react": "^2.6.0", "@prisma/client": "^4.8.1", @@ -72,6 +72,9 @@ "@radix-ui/react-toast": "^1.1.3", "@radix-ui/react-tooltip": "^1.0.3", "@rainbow-me/rainbowkit": "1.0.1", + "@spruceid/siwe-parser": "2.0.2", + "@spruceid/ssx-react": "^2.0.2", + "@spruceid/ssx-server": "^2.0.0", "@t3-oss/env-nextjs": "^0.4.0", "@tailwindcss/forms": "^0.5.3", "@tailwindcss/line-clamp": "^0.4.2", @@ -103,7 +106,7 @@ "react-responsive": "^9.0.2", "react-table": "^7.8.0", "react-wrap-balancer": "^0.3.0", - "siwe": "1.1.6", + "siwe": "2.1.4", "tailwind-merge": "^1.8.1", "tailwindcss": "^3.2.4", "usehooks-ts": "^2.9.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b4e3cdc7..10ba738b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -106,6 +106,15 @@ dependencies: '@rainbow-me/rainbowkit': specifier: 1.0.1 version: 1.0.1(@types/react@18.0.26)(react-dom@18.2.0)(react@18.2.0)(viem@1.0.0)(wagmi@1.1.0) + '@spruceid/siwe-parser': + specifier: 2.0.2 + version: 2.0.2 + '@spruceid/ssx-react': + specifier: ^2.0.2 + version: 2.0.2(wagmi@1.1.0) + '@spruceid/ssx-server': + specifier: ^2.0.0 + version: 2.0.0 '@t3-oss/env-nextjs': specifier: ^0.4.0 version: 0.4.0(typescript@5.0.4)(zod@3.21.4) @@ -200,8 +209,8 @@ dependencies: specifier: ^0.3.0 version: 0.3.0(react@18.2.0) siwe: - specifier: 1.1.6 - version: 1.1.6(ethers@5.7.2) + specifier: 2.1.4 + version: 2.1.4(ethers@5.7.2) tailwind-merge: specifier: ^1.8.1 version: 1.10.0 @@ -6676,6 +6685,11 @@ packages: - encoding dev: false + /@metamask/detect-provider@1.2.0: + resolution: {integrity: sha512-ocA76vt+8D0thgXZ7LxFPyqw3H7988qblgzddTDA6B8a/yU0uKV42QR/DhA+Jh11rJjxW0jKvwb5htA6krNZDQ==} + engines: {node: '>= 10'} + dev: false + /@metamask/eth-sig-util@4.0.1: resolution: {integrity: sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==} engines: {node: '>=12.0.0'} @@ -9111,6 +9125,101 @@ packages: apg-js: 4.1.3 dev: false + /@spruceid/siwe-parser@2.0.2: + resolution: {integrity: sha512-9WuA0ios2537cWYu39MMeH0O2KdrMKgKlOBUTWRTXQjCYu5B+mHCA0JkCbFaJ/0EjxoVIcYCXIW/DoPEpw+PqA==} + dependencies: + '@noble/hashes': 1.3.0 + apg-js: 4.1.3 + uri-js: 4.4.1 + valid-url: 1.0.9 + dev: false + + /@spruceid/ssx-core@2.0.0(ethers@5.7.2): + resolution: {integrity: sha512-c3N+KtEmi9l+8JKW6plJi+YErnKYNwpwop2B5J6Cpt4s9gmYq/rV10A9blo/HLNAukmX17rMy5yGN5MIeWFTug==} + engines: {node: '>=18.16.0'} + peerDependencies: + ethers: ^5.7.2 + dependencies: + '@spruceid/ssx-sdk-wasm': 0.3.0 + axios: 0.27.2 + ethers: 5.7.2 + events: 3.3.0 + express: 4.18.2 + express-session: 1.17.3 + siwe: 2.1.4(ethers@5.7.2) + transitivePeerDependencies: + - debug + - supports-color + dev: false + + /@spruceid/ssx-react@2.0.2(wagmi@1.1.0): + resolution: {integrity: sha512-otblNSuDmJdPwcsJKXaWbX9OMPWYiGA1RUixynQZ9vrbU0WQix5Mj5h6hJExkWn3J2MyK8FzT/uDy6vteGcUYA==} + peerDependencies: + wagmi: '>=0.5.0' + dependencies: + '@spruceid/ssx': 2.1.0 + wagmi: 1.1.0(react-dom@18.2.0)(react-native@0.72.3)(react@18.2.0)(typescript@5.0.4)(viem@1.0.0)(zod@3.21.4) + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + dev: false + + /@spruceid/ssx-sdk-wasm@0.3.0: + resolution: {integrity: sha512-uuLVoajjgMahhv+i5xPHz/v6I1TMycDW5zmIOE3F29+amDt2q+C14yjFOlr0j625Zm4qiB3O4QbxZEqWKrQ5Hg==} + dev: false + + /@spruceid/ssx-server@2.0.0: + resolution: {integrity: sha512-yJDF5IJ1wGbDXFfGTIfQ8qoWvcE6IX3p17rYPFnBc7EfNym9Ml3jlq5lo1OpDR7gunrPyQo3AHT4P3HHHRNfAg==} + hasBin: true + dependencies: + '@spruceid/ssx-core': 2.0.0(ethers@5.7.2) + axios: 0.27.2 + body-parser: 1.20.2 + cookie-parser: 1.4.6 + cors: 2.8.5 + ethers: 5.7.2 + express: 4.18.2 + express-session: 1.17.3 + rc: 1.2.8 + siwe: 2.1.4(ethers@5.7.2) + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + dev: false + + /@spruceid/ssx@2.1.0: + resolution: {integrity: sha512-r5siD/dZk6mEVNoBiVfjOL7G5QWYI5ysITB4hTagJbGqbH4MPqQ6ET13uWJRcFDxnNoxgvVYzz+KPgOVN6ppeg==} + dependencies: + '@metamask/detect-provider': 1.2.0 + '@spruceid/ssx-core': 2.0.0(ethers@5.7.2) + '@spruceid/ssx-sdk-wasm': 0.3.0 + assert: 2.0.0 + axios: 0.27.2 + browser: 0.2.6 + buffer: 6.0.3 + cross-env: 5.0.5 + ethers: 5.7.2 + events: 3.3.0 + https-browserify: 1.0.0 + lodash.merge: 4.6.2 + os-browserify: 0.3.0 + path-browserify: 1.0.1 + process: 0.11.10 + siwe: 2.1.4(ethers@5.7.2) + stream-browserify: 3.0.0 + stream-http: 3.2.0 + url: 0.11.1 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + dev: false + /@stablelib/aead@1.0.1: resolution: {integrity: sha512-q39ik6sxGHewqtO0nP4BuSe3db5G1fEJE8ukvngS2gLkBXyy6E7pLubhbYgnkDFv6V8cWaxcE4Xn0t6LWcJkyg==} @@ -11321,6 +11430,15 @@ packages: engines: {node: '>=0.8'} dev: false + /assert@2.0.0: + resolution: {integrity: sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==} + dependencies: + es6-object-assign: 1.1.0 + is-nan: 1.3.2 + object-is: 1.1.5 + util: 0.12.5 + dev: false + /assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} dev: false @@ -11421,6 +11539,15 @@ packages: - debug dev: false + /axios@0.27.2: + resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==} + dependencies: + follow-redirects: 1.15.2(debug@4.3.4) + form-data: 4.0.0 + transitivePeerDependencies: + - debug + dev: false + /axios@1.3.3: resolution: {integrity: sha512-eYq77dYIFS77AQlhzEL937yUBSepBfPIe8FcgEDN35vMNZKMrs81pgnyrQpwfy4NF4b4XWX1Zgx7yX+25w8QJA==} dependencies: @@ -11833,7 +11960,6 @@ packages: /boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - dev: true /borsh@0.7.0: resolution: {integrity: sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==} @@ -11886,6 +12012,15 @@ packages: resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} dev: false + /browser@0.2.6: + resolution: {integrity: sha512-U6FjD1MaSio5jnSbGj7nrMzdy4mHmXe6RZ4/5Oa9CWIEa6iWCwnhJPfbZXGwaOOySqRF10v8BIQ4zYJyhBg97g==} + dependencies: + cheerio: 1.0.0-rc.12 + junjo: 0.2.8 + termcolor: 0.2.0 + u2r: 0.1.3 + dev: false + /browserify-aes@1.2.0: resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} dependencies: @@ -11974,6 +12109,10 @@ packages: engines: {node: '>=8.0.0'} dev: false + /builtin-status-codes@3.0.0: + resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==} + dev: false + /bundle-name@3.0.0: resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==} engines: {node: '>=12'} @@ -12236,6 +12375,30 @@ packages: resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} dev: false + /cheerio-select@2.1.0: + resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} + dependencies: + boolbase: 1.0.0 + css-select: 5.1.0 + css-what: 6.1.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.1.0 + dev: false + + /cheerio@1.0.0-rc.12: + resolution: {integrity: sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==} + engines: {node: '>= 6'} + dependencies: + cheerio-select: 2.1.0 + dom-serializer: 2.0.0 + domhandler: 5.0.3 + domutils: 3.1.0 + htmlparser2: 8.0.2 + parse5: 7.1.2 + parse5-htmlparser2-tree-adapter: 7.0.0 + dev: false + /chokidar@3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} @@ -12598,10 +12761,23 @@ packages: /convert-source-map@1.9.0: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + /cookie-parser@1.4.6: + resolution: {integrity: sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==} + engines: {node: '>= 0.8.0'} + dependencies: + cookie: 0.4.1 + cookie-signature: 1.0.6 + dev: false + /cookie-signature@1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} dev: false + /cookie@0.4.1: + resolution: {integrity: sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==} + engines: {node: '>= 0.6'} + dev: false + /cookie@0.4.2: resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} engines: {node: '>= 0.6'} @@ -12739,6 +12915,15 @@ packages: /create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + /cross-env@5.0.5: + resolution: {integrity: sha512-pSnNZd+WdVzjhuvHoX5lF+w0fci4yLcwSBA2bF/KnS8U0PkgkAaHs8kOC07ctdLMRk7I76bOAaSnAwXViKUZNA==} + engines: {node: '>=4.0'} + hasBin: true + dependencies: + cross-spawn: 5.1.0 + is-windows: 1.0.2 + dev: false + /cross-fetch@3.1.5: resolution: {integrity: sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==} dependencies: @@ -12754,6 +12939,14 @@ packages: - encoding dev: false + /cross-spawn@5.1.0: + resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + dependencies: + lru-cache: 4.1.5 + shebang-command: 1.2.0 + which: 1.3.1 + dev: false + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -12780,6 +12973,16 @@ packages: nth-check: 2.1.1 dev: true + /css-select@5.1.0: + resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 5.0.3 + domutils: 3.1.0 + nth-check: 2.1.1 + dev: false + /css-tree@1.1.3: resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} engines: {node: '>=8.0.0'} @@ -12796,7 +12999,6 @@ packages: /css-what@6.1.0: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} - dev: true /cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} @@ -12985,6 +13187,11 @@ packages: which-typed-array: 1.1.9 dev: true + /deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + dev: false + /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true @@ -13209,13 +13416,20 @@ packages: entities: 2.2.0 dev: true + /dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.4.0 + dev: false + /dom-walk@0.1.2: resolution: {integrity: sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==} dev: false /domelementtype@2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - dev: true /domhandler@4.3.1: resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} @@ -13224,6 +13438,13 @@ packages: domelementtype: 2.3.0 dev: true + /domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + dependencies: + domelementtype: 2.3.0 + dev: false + /domutils@2.8.0: resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} dependencies: @@ -13232,6 +13453,14 @@ packages: domhandler: 4.3.1 dev: true + /domutils@3.1.0: + resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + dev: false + /dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} dependencies: @@ -13373,7 +13602,6 @@ packages: /entities@4.4.0: resolution: {integrity: sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==} engines: {node: '>=0.12'} - dev: true /env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} @@ -13509,6 +13737,10 @@ packages: es6-symbol: 3.1.3 dev: false + /es6-object-assign@1.1.0: + resolution: {integrity: sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==} + dev: false + /es6-promise@4.2.8: resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} @@ -14508,6 +14740,22 @@ packages: strip-final-newline: 3.0.0 dev: true + /express-session@1.17.3: + resolution: {integrity: sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==} + engines: {node: '>= 0.8.0'} + dependencies: + cookie: 0.4.2 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + on-headers: 1.0.2 + parseurl: 1.3.3 + safe-buffer: 5.2.1 + uid-safe: 2.1.5 + transitivePeerDependencies: + - supports-color + dev: false + /express@4.18.2: resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} engines: {node: '>= 0.10.0'} @@ -15546,6 +15794,15 @@ packages: resolution: {integrity: sha512-C++tTF1GqkGYecL+2S1wJTfoH6APGAsbb7PAWQ3iVIwgG/EFseAfEVOKFgAFq4yK3+6j1EjUD4UQ9dRJHX/sSQ==} dev: true + /htmlparser2@8.0.2: + resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.1.0 + entities: 4.4.0 + dev: false + /http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} dev: false @@ -15599,6 +15856,10 @@ packages: resolve-alpn: 1.2.1 dev: false + /https-browserify@1.0.0: + resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} + dev: false + /https-proxy-agent@5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} @@ -15754,7 +16015,6 @@ packages: /ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: true /inline-style-parser@0.1.1: resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} @@ -16172,6 +16432,14 @@ packages: resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} dev: true + /is-nan@1.3.2: + resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + dev: false + /is-negative-zero@2.0.2: resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} engines: {node: '>= 0.4'} @@ -16333,7 +16601,6 @@ packages: /is-windows@1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} - dev: true /is-wsl@1.1.0: resolution: {integrity: sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==} @@ -16873,6 +17140,10 @@ packages: setimmediate: 1.0.5 dev: false + /junjo@0.2.8: + resolution: {integrity: sha512-aekTv1Qq5BpOSXWlJWgfTsUKsu1gg/+ZluD+9aJfJcOP/BiywM+8owTX/DIZTp9O7V7YOybOXiIftz35JyjjuA==} + dev: false + /just-extend@4.2.1: resolution: {integrity: sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==} dev: false @@ -17433,6 +17704,13 @@ packages: engines: {node: 14 || >=16.14} dev: true + /lru-cache@4.1.5: + resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + dependencies: + pseudomap: 1.0.2 + yallist: 2.1.2 + dev: false + /lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} dependencies: @@ -18823,7 +19101,6 @@ packages: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} dependencies: boolbase: 1.0.0 - dev: true /nullthrows@1.1.1: resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} @@ -18865,7 +19142,6 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.2.0 - dev: true /object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} @@ -19035,6 +19311,10 @@ packages: wcwidth: 1.0.1 dev: true + /os-browserify@0.3.0: + resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} + dev: false + /os-tmpdir@1.0.2: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} @@ -19210,6 +19490,19 @@ packages: lines-and-columns: 1.2.4 dev: true + /parse5-htmlparser2-tree-adapter@7.0.0: + resolution: {integrity: sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==} + dependencies: + domhandler: 5.0.3 + parse5: 7.1.2 + dev: false + + /parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.4.0 + dev: false + /parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -19223,7 +19516,6 @@ packages: /path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} - dev: true /path-case@3.0.4: resolution: {integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==} @@ -19720,6 +20012,10 @@ packages: resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} dev: false + /pseudomap@1.0.2: + resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + dev: false + /psl@1.9.0: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} dev: false @@ -19733,7 +20029,6 @@ packages: /punycode@1.4.1: resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} - dev: true /punycode@2.1.0: resolution: {integrity: sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA==} @@ -19883,6 +20178,11 @@ packages: - supports-color dev: false + /random-bytes@1.0.0: + resolution: {integrity: sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==} + engines: {node: '>= 0.8'} + dev: false + /randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: @@ -19912,6 +20212,16 @@ packages: unpipe: 1.0.0 dev: false + /rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + dev: false + /react-copy-to-clipboard@5.1.0(react@18.2.0): resolution: {integrity: sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==} peerDependencies: @@ -20804,12 +21114,24 @@ packages: resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==} dev: false + /shebang-command@1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + dependencies: + shebang-regex: 1.0.0 + dev: false + /shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} dependencies: shebang-regex: 3.0.0 + /shebang-regex@1.0.0: + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} + engines: {node: '>=0.10.0'} + dev: false + /shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} @@ -20892,6 +21214,18 @@ packages: ethers: 5.7.2 dev: false + /siwe@2.1.4(ethers@5.7.2): + resolution: {integrity: sha512-Dke1Qqa3mgiLm3vjqw/+SQ7dl8WV/Pfk3AlQBF94cBFydTYhztngqYrikzE3X5UTsJ6565dfVbQptszsuYZNYg==} + peerDependencies: + ethers: ^5.6.8 || ^6.0.8 + dependencies: + '@spruceid/siwe-parser': 2.0.2 + '@stablelib/random': 1.0.2 + ethers: 5.7.2 + uri-js: 4.4.1 + valid-url: 1.0.9 + dev: false + /slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -21107,6 +21441,15 @@ packages: inherits: 2.0.4 readable-stream: 3.6.2 + /stream-http@3.2.0: + resolution: {integrity: sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==} + dependencies: + builtin-status-codes: 3.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + xtend: 4.0.2 + dev: false + /stream-shift@1.0.1: resolution: {integrity: sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==} @@ -21250,6 +21593,11 @@ packages: min-indent: 1.0.1 dev: true + /strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + dev: false + /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -21431,6 +21779,10 @@ packages: dependencies: rimraf: 2.6.3 + /termcolor@0.2.0: + resolution: {integrity: sha512-BJ/FFGl0cQAyYYmUurkqQUJA9RyD2PFt9YNd24nlt7HkeuZqUmHL86ELvaY6JY/TLUvmxzJY9/fHHk3jFibUSg==} + dev: false + /terser@5.19.2: resolution: {integrity: sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==} engines: {node: '>=10'} @@ -21787,6 +22139,10 @@ packages: engines: {node: '>=12.20'} hasBin: true + /u2r@0.1.3: + resolution: {integrity: sha512-OqMjkw3si8wJyuK6RzBQCuJjbDmCm7LEBoQEMrZg1hUtwXBhZxZzEnxUF/Mky3zesSPfwRud5xbvoH7lzoiS3Q==} + dev: false + /ua-parser-js@1.0.35: resolution: {integrity: sha512-fKnGuqmTBnIE+/KXSzCn4db8RTigUzw1AN0DmdU6hJovUTbYJKyqj+8Mt1c4VfRDnOVJnENmfYkIPZ946UrSAA==} dev: true @@ -21800,6 +22156,13 @@ packages: commander: 2.13.0 source-map: 0.6.1 + /uid-safe@2.1.5: + resolution: {integrity: sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==} + engines: {node: '>= 0.8'} + dependencies: + random-bytes: 1.0.0 + dev: false + /uint8arraylist@2.4.3: resolution: {integrity: sha512-oEVZr4/GrH87K0kjNce6z8pSCzLEPqHNLNR5sj8cJOySrTP8Vb/pMIbZKLJGhQKxm1TiZ31atNrpn820Pyqpow==} engines: {node: '>=16.0.0', npm: '>=7.0.0'} @@ -21985,6 +22348,13 @@ packages: resolution: {integrity: sha512-3AChu4NiXquPfeckE5R5cGdiHCMWJx1dwCWOmWIL4KHAziJNOFIYJlpGFeKDvwLPHovZRCxK3cYlwzqI9Vp+Gg==} dev: false + /url@0.11.1: + resolution: {integrity: sha512-rWS3H04/+mzzJkv0eZ7vEDGiQbgquI1fGfOad6zKvgYQi1SzMmhl7c/DdRGxhaWrVH6z0qWITo8rpnxK/RfEhA==} + dependencies: + punycode: 1.4.1 + qs: 6.11.1 + dev: false + /urlpattern-polyfill@8.0.2: resolution: {integrity: sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==} dev: true @@ -22114,6 +22484,10 @@ packages: /v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + /valid-url@1.0.9: + resolution: {integrity: sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==} + dev: false + /validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} dependencies: @@ -22643,6 +23017,13 @@ packages: has-tostringtag: 1.0.0 is-typed-array: 1.1.10 + /which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: false + /which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -22824,6 +23205,10 @@ packages: engines: {node: '>=0.10.32'} dev: false + /yallist@2.1.2: + resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + dev: false + /yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} diff --git a/public/integrations/sprucekit.svg b/public/integrations/sprucekit.svg new file mode 100644 index 00000000..a5c079dc --- /dev/null +++ b/public/integrations/sprucekit.svg @@ -0,0 +1,5 @@ + + + + +