diff --git a/.changeset/moody-beds-invite.md b/.changeset/moody-beds-invite.md new file mode 100644 index 0000000..0fa286b --- /dev/null +++ b/.changeset/moody-beds-invite.md @@ -0,0 +1,9 @@ +--- +"with-next-auth": major +"frontend-only": major +"@farcaster/auth-kit": major +"@farcaster/auth-client": minor +"@farcaster/auth-relay": patch +--- + +Moves `auth-kit` to `react-query`, forcing users to wrap it with `QueryClientProvider` and introduces API changes within hooks and components, to provide options to queries and mutations. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d9b55b..d2b5bd7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,28 +17,42 @@ jobs: timeout-minutes: 10 runs-on: ubuntu-latest + strategy: + matrix: + node-version: [20] + pnpm-version: [8.6.2] + steps: - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: pnpm/action-setup@v2.2.4 with: - node-version: "20" + version: ${{ matrix.pnpm-version }} - - name: Restore cached dependencies for Node modules. - id: module-cache + - name: Set up Node ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + cache: 'pnpm' + node-version: ${{ matrix.node-version }} + env: + # https://github.com/actions/setup-node/issues/772 + FORCE_COLOR: 0 + + - name: Cache pnpm uses: actions/cache@v3 with: - path: ${{ github.workspace }}/node_modules - key: ${{ runner.os }}--node--${{ hashFiles('**/yarn.lock') }} + path: ~/.pnpm-store + key: ${{ runner.os }}--node--${{ hashFiles('pnpm-lock.yaml') }} + restore-keys: pnpm- - name: Install dependencies - run: yarn install + run: pnpm install - name: Run build - run: yarn build + run: pnpm build - name: Run linter - run: yarn lint:ci + run: pnpm lint:ci test: timeout-minutes: 10 @@ -46,27 +60,32 @@ jobs: strategy: matrix: - node_version: [18, 20] + pnpm-version: [8.6.2] + node-version: [18, 20] steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: ${{ matrix.node_version }} + node-version: ${{ matrix.node-version }} + cache: 'pnpm' + env: + # https://github.com/actions/setup-node/issues/772 + FORCE_COLOR: 0 - name: Restore cached dependencies for Node modules. id: module-cache uses: actions/cache@v3 with: path: ${{ github.workspace }}/node_modules - key: ${{ runner.os }}--node--${{ matrix.node_version}}--${{ hashFiles('**/yarn.lock') }} + key: ${{ runner.os }}--node--${{ matrix.node-version}}--${{ hashFiles('**/pnpm-lock.yaml') }} - name: Install dependencies - run: yarn install + run: pnpm install - name: Run build - run: yarn build + run: pnpm build - name: Log in to Docker Hub to avoid rate limiting uses: docker/login-action@v2 @@ -79,7 +98,7 @@ jobs: run: docker compose -f ./apps/relay/docker-compose.yml up --build --detach redis - name: Run tests - run: yarn test:ci + run: pnpm test:ci - name: Upload coverage results uses: codecov/codecov-action@v3 diff --git a/.gitignore b/.gitignore index d3aa2b9..bcc37e9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # Logs -yarn-debug.log* -yarn-error.log* +pnpm-debug.log* +pnpm-error.log* .DS_Store **/.DS_Store diff --git a/.husky/pre-commit b/.husky/pre-commit index d2ae35e..fab6428 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,4 @@ #!/bin/sh . "$(dirname "$0")/_/husky.sh" -yarn lint-staged +pnpm lint-staged diff --git a/.yarnrc b/.yarnrc deleted file mode 100644 index 19bac4f..0000000 --- a/.yarnrc +++ /dev/null @@ -1 +0,0 @@ -registry: https://registry.npmjs.org/ diff --git a/Dockerfile.relay b/Dockerfile.relay index cd69a6b..1d4257e 100644 --- a/Dockerfile.relay +++ b/Dockerfile.relay @@ -15,9 +15,9 @@ WORKDIR /home/node/app # Run turbo prune to create a pruned version of monorepo COPY --chown=node:node ./package.json ./package.json -RUN yarn global add turbo@$(node -e "console.log(require('./package.json').devDependencies.turbo)") +RUN pnpm global add turbo@$(node -e "console.log(require('./package.json').devDependencies.turbo)") COPY --chown=node:node . . -RUN /home/node/.yarn/bin/turbo prune --scope=@farcaster/auth-relay --docker +RUN pnpm turbo prune --scope=@farcaster/auth-relay --docker ############################################################################### ############## Stage 2: Build the code using a full node image ################ @@ -41,9 +41,9 @@ ENV RUSTFLAGS="-C target-feature=-crt-static" # Copy dependency information and install all dependencies COPY --chown=node:node --from=prune /home/node/app/out/json/ . -COPY --chown=node:node --from=prune /home/node/app/out/yarn.lock ./yarn.lock +COPY --chown=node:node --from=prune /home/node/app/out/pnpm-lock.yaml ./pnpm-lock.yaml -RUN yarn install --frozen-lockfile --network-timeout 1800000 +RUN pnpm install --frozen-lockfile --network-timeout 1800000 # Copy source code (and all other relevant files) COPY --chown=node:node --from=prune /home/node/app/out/full/ . @@ -51,10 +51,10 @@ COPY --chown=node:node --from=prune /home/node/app/out/full/ . COPY --chown=node:node tsconfig.json tsconfig.json # Build code -RUN yarn build +RUN pnpm build # Purge dev dependencies and only install production dependencies -RUN rm -rf node_modules && yarn install --production --ignore-scripts --prefer-offline --force --frozen-lockfile +RUN rm -rf node_modules && pnpm install --production --ignore-scripts --prefer-offline --force --frozen-lockfile ############################################################################### ########## Stage 3: Copy over the built code to a leaner alpine image ######### diff --git a/apps/relay/.env.development b/apps/relay/.env.development new file mode 100644 index 0000000..000557f --- /dev/null +++ b/apps/relay/.env.development @@ -0,0 +1,4 @@ +CORS_ORIGIN="*" +REDIS_URL=redis://127.0.0.1:6379 +CHANNEL_TTL=3600 +AUTH_KEY=super_dev_key diff --git a/apps/relay/.env.test b/apps/relay/.env.test index ea1a6a5..7c23202 100644 --- a/apps/relay/.env.test +++ b/apps/relay/.env.test @@ -1,2 +1 @@ AUTH_KEY="some-shared-secret" -LOG_LEVEL="error" diff --git a/apps/relay/.gitignore b/apps/relay/.gitignore deleted file mode 100644 index 4c49bd7..0000000 --- a/apps/relay/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.env diff --git a/apps/relay/CHANGELOG.md b/apps/relay/CHANGELOG.md index 3023935..0628ab7 100644 --- a/apps/relay/CHANGELOG.md +++ b/apps/relay/CHANGELOG.md @@ -1,4 +1,4 @@ -# @farcaster/auth-relay +# @farcaster/relay ## 0.0.10 diff --git a/apps/relay/README.md b/apps/relay/README.md index a2f2aa3..a2b41fa 100644 --- a/apps/relay/README.md +++ b/apps/relay/README.md @@ -1,4 +1,4 @@ -# `@farcaster/auth-relay` +# `@farcaster/relay` Farcaster Auth HTTP relay server. @@ -7,7 +7,7 @@ Farcaster Auth HTTP relay server. Install dependencies: ```sh -yarn install +pnpm install ``` Start a Redis container: @@ -19,7 +19,7 @@ docker compose up Run the server: ```sh -yarn start +pnpm start ``` ## About diff --git a/apps/relay/biome.json b/apps/relay/biome.json deleted file mode 100644 index 2e5466e..0000000 --- a/apps/relay/biome.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "../../node_modules/@biomejs/biome/configuration_schema.json", - "organizeImports": { - "enabled": false - }, - "formatter": { - "enabled": true, - "indentSize": 2, - "indentStyle": "space", - "lineWidth": 120 - }, - "linter": { - "enabled": true, - "rules": { - "recommended": true, - "complexity": { - "useLiteralKeys": "off" - } - } - } -} diff --git a/apps/relay/fastify.d.ts b/apps/relay/fastify.d.ts deleted file mode 100644 index f173b53..0000000 --- a/apps/relay/fastify.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { FastifyRequest as DefaultFastifyRequest } from "fastify"; -import { RelaySession } from "./src/handlers"; -import { ChannelStore } from "./src/channels"; -import { AddressService } from "./src/addresses"; - -declare module "fastify" { - export interface FastifyRequest extends DefaultFastifyRequest { - channelToken: string; - channels: ChannelStore; - addresses: AddressService; - } -} diff --git a/apps/relay/package.json b/apps/relay/package.json index 3f278a4..33bac91 100644 --- a/apps/relay/package.json +++ b/apps/relay/package.json @@ -1,17 +1,29 @@ { - "name": "@farcaster/auth-relay", - "version": "0.0.10", + "name": "@farcaster/relay", "description": "Farcaster Auth relay server", - "private": true, - "type": "commonjs", + "version": "0.0.9", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/farcasterxyz/auth-monorepo.git", + "directory": "apps/relay" + }, "scripts": { - "build": "tsc --project ./tsconfig.json", - "lint": "biome format src/ --write && biome check src/ --apply", - "lint:ci": "biome ci src/", - "test": "yarn build && DOTENV_CONFIG_PATH=.env.test jest", - "test:ci": "yarn build && ENVIRONMENT=test NODE_OPTIONS=\"--max-old-space-size=4096\" DOTENV_CONFIG_PATH=.env.test jest --ci --forceExit --coverage", - "start": "yarn build && node build/app.js start" + "dev": "dotenv -e .env -c development tsx watch src/index.ts", + "build": "pnpm run clean && pnpm run build:esm+types", + "build:esm+types": "tsc --project tsconfig.build.json --outDir ./dist/esm --declaration --declarationMap --declarationDir ./dist/types", + "clean": "rimraf dist tsconfig.tsbuildinfo actions clients contracts errors utils", + "test": "pnpm build && dotenv -e .env -c test jest", + "typecheck": "tsc --noEmit", + "test:build": "publint --strict", + "test:ci": "pnpm build && ENVIRONMENT=test NODE_OPTIONS=\"--max-old-space-size=4096\" DOTENV_CONFIG_PATH=.env.test jest --ci --forceExit --coverage", + "start": "pnpm build && node build/app.js start" }, + "sideEffects": false, + "type": "module", + "main": "./dist/esm/exports/index.js", + "types": "./dist/types/exports/index.d.ts", + "typings": "./dist/types/exports/index.d.ts", "engines": { "node": ">=18" }, @@ -24,11 +36,16 @@ "ethers": "^6.0.8", "fastify": "^4.24.3", "ioredis": "^5.3.2", - "neverthrow": "^6.1.0", "siwe": "^2.1.4", - "viem": "^2.5.0" + "undici": "^6.13.0", + "viem": "^2.9.0", + "zod": "^3.22.4", + "zod-validation-error": "^3.0.3" }, "devDependencies": { - "jest": "^29.7.0" - } + "dotenv-cli": "^7.4.1", + "jest": "^29.7.0", + "tsx": "^4.7.1" + }, + "keywords": ["farcaster", "sign-in", "sign-in with farcaster", "siwe", "auth-client"] } diff --git a/apps/relay/src/addresses.ts b/apps/relay/src/addresses.ts deleted file mode 100644 index 9906244..0000000 --- a/apps/relay/src/addresses.ts +++ /dev/null @@ -1,103 +0,0 @@ -import axios, { AxiosInstance } from "axios"; -import { ResultAsync, err, ok } from "neverthrow"; -import { createPublicClient, http } from "viem"; -import type { PublicClient, HttpTransport, Hex } from "viem"; -import { optimism } from "viem/chains"; -import { ID_REGISTRY_ADDRESS, idRegistryABI } from "@farcaster/core"; - -import { RelayAsyncResult, RelayError } from "./errors"; -import { HUB_URL, HUB_FALLBACK_URL, OPTIMISM_RPC_URL } from "./env"; - -interface VerificationAddAddressBody { - address: Hex; -} - -interface ArbitraryVerificationMessageData { - verificationAddEthAddressBody: never; - verificationAddAddressBody: VerificationAddAddressBody; -} - -interface EthVerificationMessageData { - verificationAddEthAddressBody: VerificationAddAddressBody; - verificationAddAddressBody: never; -} - -type VerificationMessageData = ArbitraryVerificationMessageData | EthVerificationMessageData; - -interface VerificationMessage { - data: VerificationMessageData; -} - -interface VerificationsAPIResponse { - messages: VerificationMessage[]; -} - -export class AddressService { - private http: AxiosInstance; - private publicClient: PublicClient; - - constructor() { - this.http = axios.create(); - this.publicClient = createPublicClient({ - chain: optimism, - transport: http(OPTIMISM_RPC_URL), - }); - } - - async getAddresses(fid?: number): RelayAsyncResult<{ custody: Hex; verifications: Hex[] }> { - const custody = await this.custody(fid); - if (custody.isErr()) { - return err(custody.error); - } - const verifications = await this.verifications(fid); - if (verifications.isErr()) { - return err(verifications.error); - } - return ok({ - custody: custody.value, - verifications: verifications.value, - }); - } - - async custody(fid?: number): RelayAsyncResult { - return ResultAsync.fromPromise( - this.publicClient.readContract({ - address: ID_REGISTRY_ADDRESS, - abi: idRegistryABI, - functionName: "custodyOf", - args: [BigInt(fid ?? 0)], - }), - (error) => { - return new RelayError("unknown", error as Error); - }, - ); - } - - async verifications(fid?: number): RelayAsyncResult { - const url = `${HUB_URL}/v1/verificationsByFid?fid=${fid}`; - const fallbackUrl = `${HUB_FALLBACK_URL}/v1/verificationsByFid?fid=${fid}`; - - return ResultAsync.fromPromise(this.http.get(url, { timeout: 1500 }), (error) => { - return new RelayError("unknown", error as Error); - }) - .orElse(() => { - return ResultAsync.fromPromise( - this.http.get(fallbackUrl, { - timeout: 3500, - }), - (error) => { - return new RelayError("unknown", error as Error); - }, - ); - }) - .andThen((res) => { - return ok( - res.data.messages.map((message) => { - return ( - message.data?.verificationAddAddressBody?.address || message.data?.verificationAddEthAddressBody?.address - ); - }), - ); - }); - } -} diff --git a/apps/relay/src/app.ts b/apps/relay/src/app.ts deleted file mode 100644 index 0d1c079..0000000 --- a/apps/relay/src/app.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { RelayServer } from "./server"; -import { CHANNEL_TTL, REDIS_URL, RELAY_SERVER_HOST, RELAY_SERVER_PORT } from "./env"; - -new RelayServer({ - redisUrl: REDIS_URL, - ttl: CHANNEL_TTL, - corsOrigin: "*", -}).start(RELAY_SERVER_HOST, RELAY_SERVER_PORT); diff --git a/apps/relay/src/channel.ts b/apps/relay/src/channel.ts new file mode 100644 index 0000000..bb60a5f --- /dev/null +++ b/apps/relay/src/channel.ts @@ -0,0 +1,139 @@ +import { randomUUID } from "crypto"; +import { Hono } from "hono"; +import { rateLimiter } from "hono-rate-limiter"; +import { z } from "zod"; +import { generateNonce } from "siwe"; +import { fromZodError } from "zod-validation-error"; +import { auth } from "./middlewares/auth.js"; +import { channel as channelMiddleware } from "./middlewares/channel.js"; +import { getAddresses } from "./utils/getAddresses.js"; +import { getConfig } from "./utils/getConfig.js"; +import { RelayError } from "./utils/errors.js"; +import { channelCreateSchema } from "./schemas/channelCreate.js"; +import { channelAuthenticateSchema } from "./schemas/channelAuthenticate.js"; +import type { ChannelAuthenticateReturnType, ChannelCreateReturnType, ChannelGetReturnType } from "./types/actions.js"; + +const { baseUrl, authKey } = getConfig(); + +export const channel = new Hono().use( + rateLimiter({ + limit: 1000, + }), + channelMiddleware, +); + +function constructUrl( + parameters: { channelToken: string; nonce: string } & z.infer, +): string { + const query = new URLSearchParams(parameters); + return `${baseUrl}?${query.toString()}`; +} + +channel.on("POST", ["/channel", "/connect"], async (c) => { + const parseResult = channelCreateSchema.safeParse(c.req.json()); + if (!parseResult.success) { + c.status(400); + return c.json({ error: "Validation error", message: fromZodError(parseResult.error) }); + } + const body = parseResult.data; + + const channelToken = randomUUID(); + try { + await c.var.channel.create(channelToken); + + const nonce = body.nonce ?? generateNonce(); + const url = constructUrl({ channelToken, nonce, ...body }); + + const pendingChannel = { + state: "pending", + nonce, + url, + channelToken, + } as const satisfies ChannelCreateReturnType; + + await c.var.channel.update(channelToken, pendingChannel); + c.status(201); + return c.json(pendingChannel); + } catch (e) { + if (!(e instanceof RelayError)) throw new Error("Unexpected error"); + + c.status(500); + return c.json({ error: e.message }); + } +}); + +channel.post("/(connect|channel)/authenticate", auth, async (c) => { + const reqAuthKey = c.req.header("x-farcaster-auth-relay-key") ?? c.req.header("x-farcaster-connect-auth-key"); + if (reqAuthKey !== authKey) { + c.status(401); + return c.json({ error: "Unauthorized" }); + } + + try { + const parseResult = channelAuthenticateSchema.safeParse(c.req.json()); + if (!parseResult.success) { + c.status(400); + return c.json({ error: "Validation error", message: fromZodError(parseResult.error) }); + } + const { message, signature, fid, username, displayName, bio, pfpUrl } = parseResult.data; + + const addresses = await getAddresses(fid); + + const channel = await c.var.channel.get(c.var.channelToken); + + const result = { + ...channel, + state: "completed", + message, + signature, + fid, + username, + displayName, + bio, + pfpUrl, + ...addresses, + } satisfies ChannelAuthenticateReturnType; + c.status(201); + return c.json(result); + } catch (e) { + c.status(500); + + if (e instanceof RelayError) { + if (e.errCode === "not_found") { + c.status(401); + return c.json({ error: "Unauthorized" }); + } + return c.json({ error: e.message }); + } + + return c.json({ error: new RelayError("unavailable", e as Error).message }); + } +}); + +channel.get("/(connect|channel)/status", auth, async (c) => { + try { + const channel = (await c.var.channel.get(c.var.channelToken)) satisfies ChannelGetReturnType; + if (channel.state === "completed") { + try { + await c.var.channel.delete(c.var.channelToken); + } catch (e) { + if (!(e instanceof RelayError)) throw new Error("Unexpected error"); + c.status(500); + return c.json({ error: e.message }); + } + return c.json(channel); + } + c.status(202); + return c.json(channel); + } catch (e) { + if (!(e instanceof RelayError)) throw new Error("Unexpected error"); + + if (e.errCode === "not_found") { + c.status(401); + return c.json({ error: "Unauthorized" }); + } + + c.status(500); + return c.json({ error: e.message }); + } +}); diff --git a/apps/relay/src/channels.test.ts b/apps/relay/src/channels.test.ts deleted file mode 100644 index fcbc3eb..0000000 --- a/apps/relay/src/channels.test.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { ChannelStore } from "./channels"; -import { jest } from "@jest/globals"; - -interface TestSession { - foo: string; - baz?: string; -} - -let channels: ChannelStore; - -beforeAll(async () => { - channels = new ChannelStore({ - redisUrl: "redis://localhost:6379", - }); -}); - -afterAll(async () => { - await channels.stop(); -}); - -afterEach(async () => { - await channels.clear(); - jest.restoreAllMocks(); -}); - -describe("channel store", () => { - describe("open", () => { - test("opens a channel and returns the token", async () => { - const channel = await channels.open(); - expect(channel._unsafeUnwrap()).toMatch(/[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}/); - }); - }); - - describe("update", () => { - test("updates an existing channel", async () => { - const channel = await channels.open(); - const channelToken = channel._unsafeUnwrap(); - const update = await channels.update(channelToken, { foo: "bar" }); - const returnedState = update._unsafeUnwrap(); - expect(returnedState).toStrictEqual({ foo: "bar" }); - - const read = await channels.read(channelToken); - const storedState = read._unsafeUnwrap(); - expect(storedState).toStrictEqual(returnedState); - }); - - test("multiple updates", async () => { - const channel = await channels.open(); - const channelToken = channel._unsafeUnwrap(); - await channels.update(channelToken, { foo: "bar" }); - const update = await channels.update(channelToken, { - foo: "bar", - baz: "qux", - }); - const returnedState = update._unsafeUnwrap(); - expect(returnedState).toStrictEqual({ foo: "bar", baz: "qux" }); - - const read = await channels.read(channelToken); - const storedState = read._unsafeUnwrap(); - expect(storedState).toStrictEqual(returnedState); - }); - }); - - describe("read", () => { - test("reads value of an existing channel", async () => { - const channel = await channels.open(); - const channelToken = channel._unsafeUnwrap(); - await channels.update(channelToken, { foo: "bar" }); - - const read = await channels.read(channelToken); - const storedState = read._unsafeUnwrap(); - expect(storedState).toStrictEqual({ foo: "bar" }); - }); - - test("returns not_found error for missing key", async () => { - const read = await channels.read("some-invalid-key"); - expect(read.isErr()).toBe(true); - expect(read._unsafeUnwrapErr().errCode).toBe("not_found"); - }); - }); - - describe("close", () => { - test("closes a channel", async () => { - const channel = await channels.open(); - const channelToken = channel._unsafeUnwrap(); - - const close = await channels.close(channelToken); - expect(close.isOk()).toBe(true); - - const read = await channels.read(channelToken); - expect(read.isErr()).toBe(true); - expect(read._unsafeUnwrapErr().errCode).toBe("not_found"); - }); - }); -}); diff --git a/apps/relay/src/channels.ts b/apps/relay/src/channels.ts deleted file mode 100644 index 708543b..0000000 --- a/apps/relay/src/channels.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Redis } from "ioredis"; -import { ResultAsync, err, ok } from "neverthrow"; -import { randomUUID } from "crypto"; -import { RelayAsyncResult, RelayError } from "./errors"; - -interface ChannelStoreOpts { - redisUrl: string; - ttl?: number; -} - -export class ChannelStore { - private redis: Redis; - private ttl: number; - - constructor({ redisUrl, ttl }: ChannelStoreOpts) { - this.redis = new Redis(redisUrl); - this.ttl = ttl ?? 3600; - } - - async open(state?: T): RelayAsyncResult { - const channelToken = randomUUID(); - return ResultAsync.fromPromise( - this.redis.set(channelToken, JSON.stringify(state ?? {}), "EX", this.ttl), - (err) => new RelayError("unavailable", err as Error), - ).andThen(() => ok(channelToken)); - } - - async update(channelToken: string, state: T): RelayAsyncResult { - return ResultAsync.fromPromise( - this.redis.set(channelToken, JSON.stringify(state), "KEEPTTL"), - (err) => new RelayError("unavailable", err as Error), - ).andThen(() => ok(state)); - } - - async read(channelToken: string): RelayAsyncResult { - return ResultAsync.fromPromise( - this.redis.get(channelToken), - (err) => new RelayError("unavailable", err as Error), - ).andThen((channel) => { - if (channel) { - return ok(JSON.parse(channel)); - } else { - return err(new RelayError("not_found", "Channel not found")); - } - }); - } - - async close(channelToken: string) { - return ResultAsync.fromPromise(this.redis.del(channelToken), (err) => new RelayError("unknown", err as Error)); - } - - async clear() { - return this.redis.flushall(); - } - - async stop() { - return this.redis.quit(); - } -} diff --git a/apps/relay/src/env.ts b/apps/relay/src/env.ts deleted file mode 100644 index 58100cc..0000000 --- a/apps/relay/src/env.ts +++ /dev/null @@ -1,20 +0,0 @@ -import "dotenv/config"; - -export const LOG_LEVEL = process.env["LOG_LEVEL"] || "warn"; - -export const CHANNEL_TTL = Number(process.env["CHANNEL_TTL"] || "3600"); - -export const REDIS_URL = process.env["REDIS_URL"] || "redis://localhost:6379"; - -export const RELAY_SERVER_PORT = Number(process.env["RELAY_SERVER_PORT"] || "8000"); -export const RELAY_SERVER_HOST = process.env["RELAY_SERVER_HOST"] || "localhost"; - -export const URL_BASE = - process.env["URL_BASE"] || process.env["CONNECT_URI_BASE"] || "https://warpcast.com/~/sign-in-with-farcaster"; - -export const HUB_URL = process.env["HUB_URL"] || "https://nemes.farcaster.xyz:2281"; -export const HUB_FALLBACK_URL = process.env["HUB_FALLBACK_URL"] || "https://hoyt.farcaster.xyz:2281"; - -export const OPTIMISM_RPC_URL = process.env["OPTIMISM_RPC_URL"] || "https://mainnet.optimism.io"; - -export const AUTH_KEY = process.env["AUTH_KEY"]; diff --git a/apps/relay/src/exports/index.ts b/apps/relay/src/exports/index.ts new file mode 100644 index 0000000..5cf9c47 --- /dev/null +++ b/apps/relay/src/exports/index.ts @@ -0,0 +1,2 @@ +export * from "../types/actions.js"; +export * from "../types/channel.js"; diff --git a/apps/relay/src/handlers.ts b/apps/relay/src/handlers.ts deleted file mode 100644 index 2a9c6ba..0000000 --- a/apps/relay/src/handlers.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { FastifyError, FastifyReply, FastifyRequest } from "fastify"; -import type { Hex } from "viem"; -import { AUTH_KEY, URL_BASE } from "./env"; -import { generateNonce } from "siwe"; - -export type CreateChannelRequest = { - siweUri: string; - domain: string; - nonce?: string; - notBefore?: string; - expirationTime?: string; - requestId?: string; - redirectUrl?: string; -}; - -export type AuthenticateRequest = { - message: string; - signature: string; - fid: number; - username: string; - bio: string; - displayName: string; - pfpUrl: string; -}; - -export type RelaySession = { - state: "pending" | "completed"; - nonce: string; - url: string; - connectUri: string; - message?: string; - signature?: string; - fid?: number; - username?: string; - bio?: string; - displayName?: string; - pfpUrl?: string; - verifications?: Hex[]; - custody?: Hex; -}; - -const constructUrl = (channelToken: string, nonce: string, extraParams: CreateChannelRequest): string => { - const params = { channelToken, nonce, ...extraParams }; - const query = new URLSearchParams(params); - return `${URL_BASE}?${query.toString()}`; -}; - -export async function createChannel(request: FastifyRequest<{ Body: CreateChannelRequest }>, reply: FastifyReply) { - const channel = await request.channels.open(); - if (channel.isOk()) { - const channelToken = channel.value; - const nonce = request.body.nonce ?? generateNonce(); - const url = constructUrl(channelToken, nonce, request.body); - - const update = await request.channels.update(channelToken, { - state: "pending", - nonce, - url, - connectUri: url, - }); - if (update.isOk()) { - return reply.code(201).send({ channelToken, url, connectUri: url, nonce }); - } else { - return reply.code(500).send({ error: update.error.message }); - } - } else { - return reply.code(500).send({ error: channel.error.message }); - } -} - -export async function authenticate(request: FastifyRequest<{ Body: AuthenticateRequest }>, reply: FastifyReply) { - const authKey = request.headers["x-farcaster-auth-relay-key"] || request.headers["x-farcaster-connect-auth-key"]; - if (authKey !== AUTH_KEY) { - return reply.code(401).send({ error: "Unauthorized" }); - } - - const channelToken = request.channelToken; - const { message, signature, fid, username, displayName, bio, pfpUrl } = request.body; - - const addrs = await request.addresses.getAddresses(fid); - if (addrs.isOk()) { - const channel = await request.channels.read(channelToken); - if (channel.isOk()) { - const update = await request.channels.update(channelToken, { - ...channel.value, - state: "completed", - message, - signature, - fid, - username, - displayName, - bio, - pfpUrl, - ...addrs.value, - }); - if (update.isOk()) { - return reply.code(201).send(update.value); - } else { - return reply.code(500).send({ error: update.error.message }); - } - } else { - if (channel.error.errCode === "not_found") { - return reply.code(401).send({ error: "Unauthorized " }); - } - return reply.code(500).send({ error: channel.error.message }); - } - } else { - return reply.code(500).send({ error: addrs.error.message }); - } -} - -export async function status(request: FastifyRequest, reply: FastifyReply) { - const channel = await request.channels.read(request.channelToken); - if (channel.isOk()) { - const { url, connectUri, ...res } = channel.value; - if (res.state === "completed") { - const close = await request.channels.close(request.channelToken); - if (close.isErr()) { - return reply.code(500).send({ error: close.error.message }); - } - return reply.code(200).send(res); - } else { - return reply.code(202).send(res); - } - } else { - if (channel.error.errCode === "not_found") { - return reply.code(401).send({ error: "Unauthorized" }); - } - return reply.code(500).send({ error: channel.error.message }); - } -} - -export async function handleError(error: FastifyError, request: FastifyRequest, reply: FastifyReply) { - const { validation, statusCode } = error; - if (validation) { - return reply.status(400).send({ error: "Validation error", message: error.message }); - } else if (statusCode) { - reply.code(statusCode); - if (statusCode < 500) reply.send({ error: error.message }); - } else { - request.log.error({ err: error, errMsg: error.message, request }, "Error in http request"); - return reply.code(500).send({ error: error.message }); - } -} diff --git a/apps/relay/src/healthcheck.ts b/apps/relay/src/healthcheck.ts new file mode 100644 index 0000000..a786a18 --- /dev/null +++ b/apps/relay/src/healthcheck.ts @@ -0,0 +1,7 @@ +import { Hono } from "hono"; + +export const healthcheck = new Hono(); + +healthcheck.get("/", (c) => { + return c.json({ status: "OK" }); +}); diff --git a/apps/relay/src/index.ts b/apps/relay/src/index.ts new file mode 100644 index 0000000..0dafff6 --- /dev/null +++ b/apps/relay/src/index.ts @@ -0,0 +1,14 @@ +import { Hono } from "hono"; +import { cors } from "hono/cors"; +import { channel } from "./channel.js"; +import { healthcheck } from "./healthcheck.js"; +import { getConfig } from "./utils/getConfig.js"; + +const config = getConfig(); + +export const app = new Hono().basePath("/v2"); + +app.use(cors({ origin: config.corsOrigin })); + +app.route("/healthcheck", healthcheck); +app.route("/channel", channel); diff --git a/apps/relay/src/logger.ts b/apps/relay/src/logger.ts deleted file mode 100644 index 8d1a9e7..0000000 --- a/apps/relay/src/logger.ts +++ /dev/null @@ -1,10 +0,0 @@ -export const logger = { - level: "info", - redact: [ - "req.headers.authorization", - 'req.headers["x-farcaster-auth-relay-key"]', - 'req.headers["x-farcaster-connect-auth-key"]', - ], -}; - -export default logger; diff --git a/apps/relay/src/middlewares/auth.ts b/apps/relay/src/middlewares/auth.ts new file mode 100644 index 0000000..d54e318 --- /dev/null +++ b/apps/relay/src/middlewares/auth.ts @@ -0,0 +1,17 @@ +import { createMiddleware } from "hono/factory"; + +export type AuthVariables = { + channelToken: string; +}; + +export const auth = createMiddleware<{ Variables: AuthVariables }>(async (c, next) => { + const auth = c.req.header("authorization"); + + const channelToken = auth?.split(" ")[1]; + if (!channelToken) { + c.status(401); + return c.json({ error: "Unauthorized" }); + } + c.set("channelToken", channelToken); + return next(); +}); diff --git a/apps/relay/src/middlewares/channel.ts b/apps/relay/src/middlewares/channel.ts new file mode 100644 index 0000000..c1f35ee --- /dev/null +++ b/apps/relay/src/middlewares/channel.ts @@ -0,0 +1,58 @@ +import { createMiddleware } from "hono/factory"; +import { Redis } from "ioredis"; +import { getConfig } from "../utils/getConfig.js"; +import { RelayError } from "../utils/errors.js"; +import { type Channel } from "../types/channel.js"; + +const config = getConfig(); + +export type ChannelVariables = { + channel: { + get: (token: string) => Promise; + update: (token: string, channels: Channel) => Promise; + create: (token: string) => Promise; + delete: (token: string) => Promise; + }; +}; + +const { channelTtl } = getConfig(); + +export const channel = createMiddleware<{ Variables: ChannelVariables }>(async (c, next) => { + const redis = new Redis(config.redisUrl); + + c.set("channel", { + get: async (token) => { + try { + const serializedChannel = await redis.get(token); + if (!serializedChannel) throw new RelayError("not_found", "Channel not found"); + return JSON.parse(serializedChannel); + } catch (e) { + if (e instanceof RelayError) throw e; + + throw new RelayError("unknown", e as Error); + } + }, + create: async (token) => { + try { + await redis.set(token, JSON.stringify({}), "EX", channelTtl); + } catch (e) { + throw new RelayError("unknown", e as Error); + } + }, + update: async (token, channels) => { + try { + await redis.set(token, JSON.stringify(channels), "EX", channelTtl); + } catch (e) { + throw new RelayError("unknown", e as Error); + } + }, + delete: async (token) => { + try { + await redis.del(token); + } catch (e) { + throw new RelayError("unknown", e as Error); + } + }, + }); + await next(); +}); diff --git a/apps/relay/src/schemas.ts b/apps/relay/src/schemas.ts deleted file mode 100644 index cfff3cb..0000000 --- a/apps/relay/src/schemas.ts +++ /dev/null @@ -1,66 +0,0 @@ -export const createChannelRequestSchema = { - $id: "createChannelRequestSchema", - type: "object", - properties: { - siweUri: { - type: "string", - format: "uri", - }, - domain: { - type: "string", - pattern: "^[a-zA-Z0-9.-]+(:[0-9]+)?$", - }, - nonce: { - type: "string", - }, - notBefore: { - type: "string", - format: "date-time", - }, - expirationTime: { - type: "string", - format: "date-time", - }, - requestId: { - type: "string", - }, - redirectUrl: { - type: "string", - }, - }, - required: ["siweUri", "domain"], - additionalProperties: false, -}; - -export const authenticateRequestSchema = { - $id: "authenticateRequestSchema", - type: "object", - properties: { - message: { - type: "string", - }, - signature: { - type: "string", - pattern: "^0x[a-fA-F0-9]{130}$", - }, - fid: { - type: "integer", - }, - username: { - type: "string", - pattern: "^[a-z0-9][a-z0-9-]{0,15}$|^[a-z0-9][a-z0-9-]{0,15}\\.eth$", - }, - bio: { - type: "string", - }, - displayName: { - type: "string", - }, - pfpUrl: { - type: "string", - format: "uri", - }, - }, - required: ["message", "signature", "fid"], - additionalProperties: false, -}; diff --git a/apps/relay/src/schemas/channelAuthenticate.ts b/apps/relay/src/schemas/channelAuthenticate.ts new file mode 100644 index 0000000..12aa3f9 --- /dev/null +++ b/apps/relay/src/schemas/channelAuthenticate.ts @@ -0,0 +1,13 @@ +import type { Hex } from "viem"; +import { z } from "zod"; + +export const channelAuthenticateSchema = z.object({ + message: z.string() /*.url()?*/, + signature: z.custom((val) => /^0x[a-fA-F0-9]{130}$/.test(val as string)), + fid: z.number(), + username: z.string().regex(/^[a-z0-9][a-z0-9-]{0,15}$|^[a-z0-9][a-z0-9-]{0,15}\\.eth$/), + bio: z.string(), + displayName: z.string(), + pfpUrl: z.string().url(), +}); +export type ChannelAuthenticateParameters = z.infer; diff --git a/apps/relay/src/schemas/channelCreate.ts b/apps/relay/src/schemas/channelCreate.ts new file mode 100644 index 0000000..4d4829b --- /dev/null +++ b/apps/relay/src/schemas/channelCreate.ts @@ -0,0 +1,13 @@ +import { z } from "zod"; + +export const channelCreateSchema = z.object({ + siweUri: z.string().url(), + domain: z.string(), + nonce: z.string().optional(), + notBefore: z.string().optional(), + expirationTime: z.string().optional(), + requestId: z.string().optional(), + redirectUrl: z.string().optional(), +}); + +export type ChannelCreateParameters = z.infer; diff --git a/apps/relay/src/server.test.ts b/apps/relay/src/server.test.ts deleted file mode 100644 index 1b58e04..0000000 --- a/apps/relay/src/server.test.ts +++ /dev/null @@ -1,451 +0,0 @@ -import { RelayServer } from "./server"; -import axios from "axios"; -import { jest } from "@jest/globals"; - -let httpServer: RelayServer; -let httpServerAddress: string; - -const http = axios.create({ - validateStatus: () => true, -}); - -function getFullUrl(path: string) { - return `${httpServerAddress}${path}`; -} - -beforeAll(async () => { - httpServer = new RelayServer({ - redisUrl: "redis://localhost:6379", - ttl: 3600, - corsOrigin: "*", - }); - httpServerAddress = (await httpServer.start())._unsafeUnwrap(); -}); - -afterAll(async () => { - await httpServer.stop(); -}); - -afterEach(async () => { - await httpServer.channels.clear(); - jest.restoreAllMocks(); -}); - -describe("relay server", () => { - const channelParams = { - siweUri: "https://example.com", - domain: "example.com", - }; - - const authenticateParams = { - message: "example.com wants you to sign in with your Ethereum account: [...]", - signature: - "0x9335c30585854d1bd7040dccfbb18bfecc9eba6ee18c55a3996ef0aca783fba832b13b05dc09beec99fc6477804113fd293c68c84ea350a11794cdc121c71fd51b", - fid: 1, - username: "alice", - bio: "I'm a little teapot who didn't fill out my bio", - displayName: "Alice Teapot", - pfpUrl: "https://example.com/alice.png", - }; - - describe("cors", () => { - test("allows cross-origin requests", async () => { - const response = await http.get(getFullUrl("/healthcheck"), { - headers: { Origin: "http://example.com" }, - }); - - expect(response.status).toBe(200); - expect(response.headers["access-control-allow-origin"]).toBe("*"); - }); - }); - - describe("/healthcheck", () => { - test("GET returns status", async () => { - const response = await http.get(getFullUrl("/healthcheck")); - - expect(response.status).toBe(200); - expect(response.data).toStrictEqual({ status: "OK" }); - }); - }); - - describe("/v1/channel", () => { - test("POST creates a channel", async () => { - const response = await http.post(getFullUrl("/v1/channel"), channelParams); - - expect(response.status).toBe(201); - const { channelToken, url, connectUri, nonce, ...rest } = response.data; - expect(channelToken).toMatch(/[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}/); - expect(url).toMatch("https://warpcast.com/~/sign-in-with-farcaster"); - expect(url).toBe(connectUri); - expect(rest).toStrictEqual({}); - }); - - test("creates a channel with extra SIWE parameters", async () => { - const customNonce = "some-custom-nonce"; - const notBefore = "2023-01-01T00:00:00Z"; - const expirationTime = "2023-12-31T00:00:00Z"; - const requestId = "some-request-id"; - const redirectUrl = "http://some-redirect-url"; - const response = await http.post(getFullUrl("/v1/channel"), { - ...channelParams, - nonce: customNonce, - notBefore, - expirationTime, - requestId, - redirectUrl, - }); - - expect(response.status).toBe(201); - const { channelToken, url, connectUri, nonce, ...rest } = response.data; - // parse query params from URI - const params = new URLSearchParams(url.split("?")[1]); - expect(params.get("siweUri")).toBe(channelParams.siweUri); - expect(params.get("domain")).toBe(channelParams.domain); - expect(params.get("nonce")).toBe(customNonce); - expect(params.get("notBefore")).toBe(notBefore); - expect(params.get("expirationTime")).toBe(expirationTime); - expect(params.get("requestId")).toBe(requestId); - expect(params.get("redirectUrl")).toBe(redirectUrl); - expect(channelToken).toMatch(/[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}/); - expect(nonce).toBe(customNonce); - expect(url).toBe(connectUri); - expect(rest).toStrictEqual({}); - }); - - test("validates extra SIWE parameters", async () => { - const notBefore = "not a datetime"; - const response = await http.post(getFullUrl("/v1/channel"), { - ...channelParams, - notBefore, - }); - - expect(response.status).toBe(400); - expect(response.data).toStrictEqual({ - error: "Validation error", - message: 'body/notBefore must match format "date-time"', - }); - }); - - test("missing siweUri", async () => { - const { siweUri, ...missingUri } = channelParams; - const response = await http.post(getFullUrl("/v1/channel"), missingUri); - - expect(response.status).toBe(400); - expect(response.data).toStrictEqual({ - error: "Validation error", - message: "body must have required property 'siweUri'", - }); - }); - - test("invalid siweUri", async () => { - const response = await http.post(getFullUrl("/v1/channel"), { - ...channelParams, - siweUri: "not-a-uri", - }); - - expect(response.status).toBe(400); - expect(response.data).toStrictEqual({ - error: "Validation error", - message: 'body/siweUri must match format "uri"', - }); - }); - - test("missing domain", async () => { - const { domain, ...missingDomain } = channelParams; - const response = await http.post(getFullUrl("/v1/channel"), missingDomain); - - expect(response.status).toBe(400); - expect(response.data).toStrictEqual({ - error: "Validation error", - message: "body must have required property 'domain'", - }); - }); - - test("invalid domain", async () => { - const response = await http.post(getFullUrl("/v1/channel"), { - ...channelParams, - domain: "not a domain", - }); - - expect(response.status).toBe(400); - expect(response.data).toStrictEqual({ - error: "Validation error", - message: 'body/domain must match pattern "^[a-zA-Z0-9.-]+(:[0-9]+)?$"', - }); - }); - - test("domain with port", async () => { - const response = await http.post(getFullUrl("/v1/channel"), { - ...channelParams, - domain: "localhost:3000", - }); - - expect(response.status).toBe(201); - }); - - test("open channel error", async () => { - jest.spyOn(httpServer.channels, "open").mockImplementation(() => { - throw new Error("open error"); - }); - const response = await http.post(getFullUrl("/v1/channel"), channelParams); - - expect(response.status).toBe(500); - expect(response.data).toStrictEqual({ error: "open error" }); - }); - - test("update channel error", async () => { - jest.spyOn(httpServer.channels, "update").mockImplementation(() => { - throw new Error("update error"); - }); - const response = await http.post(getFullUrl("/v1/channel"), channelParams); - - expect(response.status).toBe(500); - expect(response.data).toStrictEqual({ error: "update error" }); - }); - }); - - describe("/v1/channel/authenticate", () => { - let channelToken: string; - - beforeEach(async () => { - const response = await http.post(getFullUrl("/v1/channel"), channelParams); - channelToken = response.data.channelToken; - }); - - test("POST with no token", async () => { - const response = await http.post(getFullUrl("/v1/channel/authenticate"), authenticateParams); - expect(response.status).toBe(401); - }); - - test("POST with valid token", async () => { - const response = await http.post(getFullUrl("/v1/channel/authenticate"), authenticateParams, { - headers: { - Authorization: `Bearer ${channelToken}`, - "X-Farcaster-Auth-Relay-Key": "some-shared-secret", - }, - }); - expect(response.status).toBe(201); - }); - - test("POST with invalid token", async () => { - let response = await http.post(getFullUrl("/v1/channel/authenticate"), authenticateParams, { - headers: { - Authorization: "Bearer abc-123-def", - "X-Farcaster-Auth-Relay-Key": "some-shared-secret", - }, - }); - expect(response.status).toBe(401); - response = await http.get(getFullUrl("/v1/channel/status"), { - headers: { Authorization: `Bearer ${channelToken}` }, - }); - expect(response.data.state).toBe("pending"); - }); - - test("POST with invalid key", async () => { - const response = await http.post(getFullUrl("/v1/channel/authenticate"), authenticateParams, { - headers: { - Authorization: "Bearer abc-123-def", - "X-Farcaster-Auth-Relay-Key": "invalid-shared-secret", - }, - }); - expect(response.status).toBe(401); - }); - - test("missing body param", async () => { - const { fid, ...missingFid } = authenticateParams; - const response = await http.post(getFullUrl("/v1/channel/authenticate"), missingFid, { - headers: { Authorization: `Bearer ${channelToken}` }, - }); - expect(response.status).toBe(400); - expect(response.data).toStrictEqual({ - error: "Validation error", - message: "body must have required property 'fid'", - }); - }); - - test("optional body param", async () => { - const { username, ...missingUsername } = authenticateParams; - const response = await http.post(getFullUrl("/v1/channel/authenticate"), missingUsername, { - headers: { - Authorization: `Bearer ${channelToken}`, - "X-Farcaster-Auth-Relay-Key": "some-shared-secret", - }, - }); - expect(response.status).toBe(201); - }); - - test("invalid username", async () => { - const response = await http.post( - getFullUrl("/v1/channel/authenticate"), - { ...authenticateParams, username: "not a username" }, - { headers: { Authorization: `Bearer ${channelToken}` } }, - ); - expect(response.status).toBe(400); - expect(response.data).toStrictEqual({ - error: "Validation error", - message: 'body/username must match pattern "^[a-z0-9][a-z0-9-]{0,15}$|^[a-z0-9][a-z0-9-]{0,15}\\.eth$"', - }); - }); - - test("invalid signature", async () => { - const response = await http.post( - getFullUrl("/v1/channel/authenticate"), - { ...authenticateParams, signature: "0x123" }, - { headers: { Authorization: `Bearer ${channelToken}` } }, - ); - expect(response.status).toBe(400); - expect(response.data).toStrictEqual({ - error: "Validation error", - message: 'body/signature must match pattern "^0x[a-fA-F0-9]{130}$"', - }); - }); - - test("invalid pfpUrl", async () => { - const response = await http.post( - getFullUrl("/v1/channel/authenticate"), - { ...authenticateParams, pfpUrl: "not a URL" }, - { headers: { Authorization: `Bearer ${channelToken}` } }, - ); - expect(response.status).toBe(400); - expect(response.data).toStrictEqual({ - error: "Validation error", - message: 'body/pfpUrl must match format "uri"', - }); - }); - - test("read channel error", async () => { - jest.spyOn(httpServer.channels, "read").mockImplementation(() => { - throw new Error("read error"); - }); - const response = await http.post(getFullUrl("/v1/channel/authenticate"), authenticateParams, { - headers: { - Authorization: `Bearer ${channelToken}`, - "X-Farcaster-Auth-Relay-Key": "some-shared-secret", - }, - }); - expect(response.status).toBe(500); - expect(response.data).toStrictEqual({ error: "read error" }); - }); - - test("update channel error", async () => { - jest.spyOn(httpServer.channels, "update").mockImplementation(() => { - throw new Error("update error"); - }); - const response = await http.post(getFullUrl("/v1/channel/authenticate"), authenticateParams, { - headers: { - Authorization: `Bearer ${channelToken}`, - "X-Farcaster-Auth-Relay-Key": "some-shared-secret", - }, - }); - expect(response.status).toBe(500); - expect(response.data).toStrictEqual({ error: "update error" }); - }); - - test("expired channel", async () => { - await httpServer.channels.close(channelToken); - const response = await http.post(getFullUrl("/v1/channel/authenticate"), authenticateParams, { - headers: { Authorization: `Bearer ${channelToken}` }, - }); - expect(response.status).toBe(401); - }); - }); - - describe("/v1/channel/status", () => { - let channelToken: string; - - beforeEach(async () => { - const response = await http.post(getFullUrl("/v1/channel"), channelParams); - channelToken = response.data.channelToken; - }); - - test("GET with no token", async () => { - const response = await http.get(getFullUrl("/v1/channel/status")); - expect(response.status).toBe(401); - }); - - test("GET with valid token", async () => { - const response = await http.get(getFullUrl("/v1/channel/status"), { - headers: { Authorization: `Bearer ${channelToken}` }, - }); - expect(response.status).toBe(202); - - const { state, nonce, ...rest } = response.data; - expect(state).toBe("pending"); - expect(nonce).toMatch(/[a-zA-Z0-9]{16}/); - expect(rest).toStrictEqual({}); - }); - - test("GET with invalid token", async () => { - const response = await http.get(getFullUrl("/v1/channel/status"), { - headers: { Authorization: "Bearer abc-123-def" }, - }); - expect(response.status).toBe(401); - }); - - test("read channel error", async () => { - jest.spyOn(httpServer.channels, "read").mockImplementation(() => { - throw new Error("read error"); - }); - const response = await http.get(getFullUrl("/v1/channel/status"), { - headers: { Authorization: `Bearer ${channelToken}` }, - }); - expect(response.status).toBe(500); - expect(response.data).toStrictEqual({ error: "read error" }); - }); - - test("close channel error", async () => { - jest.spyOn(httpServer.channels, "close").mockImplementation(() => { - throw new Error("close error"); - }); - await http.post(getFullUrl("/v1/channel/authenticate"), authenticateParams, { - headers: { - Authorization: `Bearer ${channelToken}`, - "X-Farcaster-Auth-Relay-Key": "some-shared-secret", - }, - }); - const response = await http.get(getFullUrl("/v1/channel/status"), { - headers: { Authorization: `Bearer ${channelToken}` }, - }); - expect(response.status).toBe(500); - expect(response.data).toStrictEqual({ error: "close error" }); - }); - }); - - describe("e2e", () => { - test("end to end channel flow", async () => { - const nonce = "some-custom-nonce"; - let response = await http.post(getFullUrl("/v1/channel"), { - ...channelParams, - nonce, - }); - expect(response.status).toBe(201); - - const channelToken = response.data.channelToken; - const authHeaders = { - headers: { Authorization: `Bearer ${channelToken}` }, - }; - - response = await http.get(getFullUrl("/v1/channel/status"), authHeaders); - expect(response.status).toBe(202); - expect(response.data.state).toBe("pending"); - - response = await http.post(getFullUrl("/v1/channel/authenticate"), authenticateParams, { - headers: { - Authorization: `Bearer ${channelToken}`, - "X-Farcaster-Auth-Relay-Key": "some-shared-secret", - }, - }); - expect(response.status).toBe(201); - - response = await http.get(getFullUrl("/v1/channel/status"), authHeaders); - expect(response.status).toBe(200); - expect(response.data.state).toBe("completed"); - expect(response.data.message).toBe(authenticateParams.message); - expect(response.data.signature).toBe(authenticateParams.signature); - expect(response.data.nonce).toBe(nonce); - - response = await http.get(getFullUrl("/v1/channel/status"), authHeaders); - expect(response.status).toBe(401); - }); - }); -}); diff --git a/apps/relay/src/server.ts b/apps/relay/src/server.ts deleted file mode 100644 index efa6c4c..0000000 --- a/apps/relay/src/server.ts +++ /dev/null @@ -1,126 +0,0 @@ -import fastify from "fastify"; -import cors from "@fastify/cors"; -import rateLimit from "@fastify/rate-limit"; -import { err, ok } from "neverthrow"; -import { createChannelRequestSchema, authenticateRequestSchema } from "./schemas"; -import { ChannelStore } from "./channels"; -import { AddressService } from "./addresses"; -import { - AuthenticateRequest, - CreateChannelRequest, - RelaySession, - authenticate, - createChannel, - handleError, - status, -} from "./handlers"; -import { RelayError, RelayAsyncResult } from "./errors"; -import logger from "./logger"; - -interface RelayServerConfig { - redisUrl: string; - ttl: number; - corsOrigin: string; -} - -export class RelayServer { - app = fastify({ logger }); - channels: ChannelStore; - addresses: AddressService; - - constructor({ redisUrl, ttl, corsOrigin }: RelayServerConfig) { - this.channels = new ChannelStore({ - redisUrl, - ttl, - }); - this.addresses = new AddressService(); - this.app.setErrorHandler(handleError); - - this.app.register(cors, { origin: [corsOrigin] }); - this.app.decorateRequest("channels"); - this.app.decorateRequest("addresses"); - this.app.addHook("onRequest", async (request) => { - request.channels = this.channels; - request.addresses = this.addresses; - }); - this.app.get("/healthcheck", async (_request, reply) => reply.send({ status: "OK" })); - this.app.addSchema(createChannelRequestSchema); - this.app.addSchema(authenticateRequestSchema); - this.initHandlers(); - } - - initHandlers() { - this.app.register( - (v1, _opts, next) => { - v1.register(async (publicRoutes, _opts, next) => { - await publicRoutes.register(rateLimit); - publicRoutes.post<{ Body: CreateChannelRequest }>( - "/channel", - { schema: { body: createChannelRequestSchema } }, - createChannel, - ); - next(); - }); - - v1.register(async (publicRoutes, _opts, next) => { - await publicRoutes.register(rateLimit); - publicRoutes.post<{ Body: CreateChannelRequest }>( - "/connect", - { schema: { body: createChannelRequestSchema } }, - createChannel, - ); - next(); - }); - - v1.register((protectedRoutes, _opts, next) => { - protectedRoutes.decorateRequest("channelToken", ""); - protectedRoutes.addHook("preHandler", async (request, reply) => { - const auth = request.headers.authorization; - const channelToken = auth?.split(" ")[1]; - if (channelToken) { - request.channelToken = channelToken; - } else { - return reply.code(401).send({ error: "Unauthorized " }); - } - }); - - protectedRoutes.post<{ - Body: AuthenticateRequest; - }>("/connect/authenticate", { schema: { body: authenticateRequestSchema } }, authenticate); - - protectedRoutes.get("/connect/status", status); - - protectedRoutes.post<{ - Body: AuthenticateRequest; - }>("/channel/authenticate", { schema: { body: authenticateRequestSchema } }, authenticate); - - protectedRoutes.get("/channel/status", status); - - next(); - }); - next(); - }, - { prefix: "/v1" }, - ); - } - - async start(ip = "0.0.0.0", port = 0): RelayAsyncResult { - return new Promise((resolve) => { - this.app.listen({ host: ip, port }, (e, address) => { - if (e) { - this.app.log.error({ err: e, errMsg: e.message }, "Failed to start http server"); - resolve(err(new RelayError("unavailable", `Failed to start http server: ${e.message}`))); - } - - this.app.log.info({ address }, "Started relay server"); - resolve(ok(address)); - }); - }); - } - - async stop() { - await this.app.close(); - await this.channels.stop(); - this.app.log.info("Stopped relay server"); - } -} diff --git a/apps/relay/src/types/actions.ts b/apps/relay/src/types/actions.ts new file mode 100644 index 0000000..faa55f9 --- /dev/null +++ b/apps/relay/src/types/actions.ts @@ -0,0 +1,12 @@ +import type { z } from "zod"; +import type { CompletedChannel, PendingChannel, Channel } from "./channel.js"; +import type { channelCreateSchema } from "../schemas/channelCreate.js"; +import type { channelAuthenticateSchema } from "../schemas/channelAuthenticate.js"; + +export type ChannelCreateParameters = z.infer; +export type ChannelCreateReturnType = PendingChannel & { channelToken: string }; + +export type ChannelAuthenticateParameters = z.infer; +export type ChannelAuthenticateReturnType = CompletedChannel; + +export type ChannelGetReturnType = Channel; diff --git a/apps/relay/src/types/channel.ts b/apps/relay/src/types/channel.ts new file mode 100644 index 0000000..a195350 --- /dev/null +++ b/apps/relay/src/types/channel.ts @@ -0,0 +1,19 @@ +import { type Hex } from "viem"; + +export type PendingChannel = { state: "pending"; nonce: string; url: string }; +export type CompletedChannel = { + state: "completed"; + message: string; + signature: `0x${string}`; + fid: number; + username: string; + bio: string; + displayName: string; + pfpUrl: string; + verifications: Hex[]; + custody: Hex; + nonce: string; + url: string; +}; + +export type Channel = PendingChannel | CompletedChannel; diff --git a/apps/relay/src/types/verifications.ts b/apps/relay/src/types/verifications.ts new file mode 100644 index 0000000..84c91ec --- /dev/null +++ b/apps/relay/src/types/verifications.ts @@ -0,0 +1,25 @@ +import { type Hex } from "viem"; + +export type VerificationAddAddressBody = { + address: Hex; +}; + +export type ArbitraryVerificationMessageData = { + verificationAddEthAddressBody: never; + verificationAddAddressBody: VerificationAddAddressBody; +}; + +export type EthVerificationMessageData = { + verificationAddEthAddressBody: VerificationAddAddressBody; + verificationAddAddressBody: never; +}; + +export type VerificationMessageData = ArbitraryVerificationMessageData | EthVerificationMessageData; + +export type VerificationMessage = { + data: VerificationMessageData; +}; + +export type VerificationsAPIResponse = { + messages: VerificationMessage[]; +}; diff --git a/apps/relay/src/errors.ts b/apps/relay/src/utils/errors.ts similarity index 88% rename from apps/relay/src/errors.ts rename to apps/relay/src/utils/errors.ts index 73fbca0..df6436a 100644 --- a/apps/relay/src/errors.ts +++ b/apps/relay/src/utils/errors.ts @@ -1,5 +1,3 @@ -import { Result } from "neverthrow"; - interface RelayErrorOpts { message: string; cause: Error | RelayError; @@ -12,6 +10,8 @@ export class RelayError extends Error { /* Indicates if error message can be presented to the user */ public readonly presentable: boolean = false; + public override readonly cause: RelayErrorOpts["cause"] | undefined; + /** * @param errCode - the ConnectError code for this message * @param context - a message, another Error, or a ConnectErrorOpts @@ -31,8 +31,9 @@ export class RelayError extends Error { parsedContext.message = parsedContext.cause?.message || ""; } - super(parsedContext.message, { cause: parsedContext.cause }); + super(parsedContext.message); + this.cause = parsedContext.cause; this.name = "ConnectError"; this.errCode = errCode; } @@ -61,7 +62,3 @@ export type RelayErrorCode = | "unavailable" /* An unknown error was encountered */ | "unknown"; - -/** Type alias for shorthand when handling errors */ -export type RelayResult = Result; -export type RelayAsyncResult = Promise>; diff --git a/apps/relay/src/utils/getAddresses.ts b/apps/relay/src/utils/getAddresses.ts new file mode 100644 index 0000000..56957f6 --- /dev/null +++ b/apps/relay/src/utils/getAddresses.ts @@ -0,0 +1,7 @@ +import { getCustodyAddress } from "./getCustodyAddress.js"; +import { getVerifiedAddresses } from "./getVerifiedAddresses.js"; + +export async function getAddresses(fid: number) { + const [custody, verifications] = await Promise.all([getCustodyAddress(fid), getVerifiedAddresses(fid)]); + return { custody, verifications }; +} diff --git a/apps/relay/src/utils/getConfig.ts b/apps/relay/src/utils/getConfig.ts new file mode 100644 index 0000000..a139a12 --- /dev/null +++ b/apps/relay/src/utils/getConfig.ts @@ -0,0 +1,44 @@ +import { createPublicClient, http } from "viem"; +import { optimism } from "viem/chains"; +import { z } from "zod"; +import { fromZodError } from "zod-validation-error"; + +const schema = z.object({ + corsOrigin: z.string(), + redisUrl: z.string().url(), + channelTtl: z.coerce.number(), + port: z.number().optional().default(8000), + host: z.string().optional().default("localhost"), + baseUrl: z.string().url().optional().default("https://warpcast.com/~/sign-in-with-farcaster"), + hubUrl: z.string().url().optional().default("https://nemes.farcaster.xyz:2281"), + hubFallbackUrl: z.string().url().optional().default("https://hoyt.farcaster.xyz:2281"), + optimismRpcUrl: z.string().url().optional().default("https://mainnet.optimism.io"), + authKey: z.string(), +}); + +export function getConfig() { + const parseResult = schema.safeParse({ + corsOrigin: process.env.CORS_ORIGIN, + redisUrl: process.env.REDIS_URL, + channelTtl: process.env.CHANNEL_TTL, + port: process.env.PORT, + host: process.env.HOST, + baseUrl: process.env.BASE_URL, + hubUrl: process.env.HUB_URL, + hubFallbackUrl: process.env.HUB_FALLBACK_URL, + optimismRpcUrl: process.env.OPTIMISM_RPC_URL, + authKey: process.env.AUTH_KEY, + }); + + if (!parseResult.success) { + throw fromZodError(parseResult.error); + } + const env = parseResult.data; + + const publicClient = createPublicClient({ + chain: optimism, + transport: http(env.optimismRpcUrl), + }); + + return { ...env, publicClient }; +} diff --git a/apps/relay/src/utils/getCustodyAddress.ts b/apps/relay/src/utils/getCustodyAddress.ts new file mode 100644 index 0000000..ac5bc75 --- /dev/null +++ b/apps/relay/src/utils/getCustodyAddress.ts @@ -0,0 +1,13 @@ +import { getConfig } from "./getConfig.js"; +import { ID_REGISTRY_ADDRESS, idRegistryABI } from "@farcaster/core"; + +const { publicClient } = getConfig(); + +export async function getCustodyAddress(fid: number) { + return publicClient.readContract({ + address: ID_REGISTRY_ADDRESS, + abi: idRegistryABI, + functionName: "custodyOf", + args: [BigInt(fid ?? 0)], + }); +} diff --git a/apps/relay/src/utils/getVerifiedAddresses.ts b/apps/relay/src/utils/getVerifiedAddresses.ts new file mode 100644 index 0000000..a60b039 --- /dev/null +++ b/apps/relay/src/utils/getVerifiedAddresses.ts @@ -0,0 +1,24 @@ +import { type VerificationsAPIResponse } from "../types/verifications.js"; +import { getConfig } from "./getConfig.js"; +import { fetch, Agent } from "undici"; + +const { hubUrl, hubFallbackUrl } = getConfig(); + +export async function getVerifiedAddresses(fid: number) { + const mainUrl = `${hubUrl}/v1/verificationsByFid?fid=${fid}`; + const fallbackUrl = `${hubFallbackUrl}/v1/verificationsByFid?fid=${fid}`; + const verifications = await fetch(mainUrl, { + dispatcher: new Agent({ connectTimeout: 1500 }), + }) + // TODO: don't do type cast and do zod schema validation instead + .then(async (r) => (await r.json()) as VerificationsAPIResponse) + .catch(async () => { + return fetch(fallbackUrl, { + dispatcher: new Agent({ connectTimeout: 3500 }), + }).then(async (r) => (await r.json()) as VerificationsAPIResponse); + }); + + return verifications.messages.map((message) => { + return message.data?.verificationAddAddressBody?.address || message.data?.verificationAddEthAddressBody?.address; + }); +} diff --git a/apps/relay/tsconfig.build.json b/apps/relay/tsconfig.build.json new file mode 100644 index 0000000..58de5cd --- /dev/null +++ b/apps/relay/tsconfig.build.json @@ -0,0 +1,5 @@ +{ + "extends": "../../tsconfig.base.json", + "include": ["src/**/*.ts"], + "exclude": ["src/**/*.test.ts", "src/**/*.test-d.ts"] +} diff --git a/apps/relay/tsconfig.json b/apps/relay/tsconfig.json index bac590b..bacbc92 100644 --- a/apps/relay/tsconfig.json +++ b/apps/relay/tsconfig.json @@ -1,15 +1,5 @@ { - "extends": "../../tsconfig.json", - "compilerOptions": { - "resolveJsonModule": true, - "moduleResolution": "node", - // BullMQ doesn't support ESM - // https://github.com/taskforcesh/bullmq/issues/1534 - "module": "commonjs", - "baseUrl": "./src", - "outDir": "build", - "rootDir": "src" - }, - "typeRoots": ["./@types"], - "exclude": ["node_modules", "jest.config.ts"] + "extends": "./tsconfig.build.json", + "include": ["src/**/*.ts", "test/**/*.ts"], + "exclude": [] } diff --git a/biome.json b/biome.json index 1e602cb..9fffeb7 100644 --- a/biome.json +++ b/biome.json @@ -16,6 +16,9 @@ "recommended": true, "complexity": { "useLiteralKeys": "off" + }, + "suspicious": { + "noExplicitAny": "off" } }, "ignore": ["examples"] diff --git a/examples/authkit-expo-demo/metro.config.js b/examples/authkit-expo-demo/metro.config.js index a3c82b5..e50eb26 100644 --- a/examples/authkit-expo-demo/metro.config.js +++ b/examples/authkit-expo-demo/metro.config.js @@ -17,4 +17,3 @@ config.resolver.nodeModulesPaths = [ ]; module.exports = config; - diff --git a/examples/authkit-expo-demo/package.json b/examples/authkit-expo-demo/package.json index b40072b..eab451b 100644 --- a/examples/authkit-expo-demo/package.json +++ b/examples/authkit-expo-demo/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "@expo/metro-runtime": "~3.1.3", - "@farcaster/auth-kit": "*", + "@farcaster/auth-kit": "workspace:*", "expo": "~50.0.14", "expo-status-bar": "~1.11.1", "fastestsmallesttextencoderdecoder": "^1.0.22", diff --git a/examples/frontend-only/.eslintrc.cjs b/examples/frontend-only/.eslintrc.cjs index d6c9537..78174f6 100644 --- a/examples/frontend-only/.eslintrc.cjs +++ b/examples/frontend-only/.eslintrc.cjs @@ -1,18 +1,11 @@ module.exports = { root: true, env: { browser: true, es2020: true }, - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:react-hooks/recommended', - ], - ignorePatterns: ['dist', '.eslintrc.cjs'], - parser: '@typescript-eslint/parser', - plugins: ['react-refresh'], + extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:react-hooks/recommended"], + ignorePatterns: ["dist", ".eslintrc.cjs"], + parser: "@typescript-eslint/parser", + plugins: ["react-refresh"], rules: { - 'react-refresh/only-export-components': [ - 'warn', - { allowConstantExport: true }, - ], + "react-refresh/only-export-components": ["warn", { allowConstantExport: true }], }, -} +}; diff --git a/examples/frontend-only/.gitignore b/examples/frontend-only/.gitignore index a547bf3..f542e80 100644 --- a/examples/frontend-only/.gitignore +++ b/examples/frontend-only/.gitignore @@ -2,8 +2,8 @@ logs *.log npm-debug.log* -yarn-debug.log* -yarn-error.log* +pnpm-debug.log* +pnpm-error.log* pnpm-debug.log* lerna-debug.log* diff --git a/examples/frontend-only/README.md b/examples/frontend-only/README.md index 4da3969..303d206 100644 --- a/examples/frontend-only/README.md +++ b/examples/frontend-only/README.md @@ -6,6 +6,6 @@ This example app shows how to use Sign In With Farcaster in a frontend app witho ```sh $ git clone https://github.com/farcasterxyz/auth-monorepo.git && cd auth-monorepo/examples/frontend-only -$ yarn install -$ yarn dev +$ pnpm install +$ pnpm dev ``` diff --git a/examples/frontend-only/index.html b/examples/frontend-only/index.html index 63697b2..715b3bd 100644 --- a/examples/frontend-only/index.html +++ b/examples/frontend-only/index.html @@ -3,6 +3,8 @@ + + Farcaster AuthKit + Vite Demo diff --git a/examples/frontend-only/package.json b/examples/frontend-only/package.json index 0bed068..0d83a4c 100644 --- a/examples/frontend-only/package.json +++ b/examples/frontend-only/package.json @@ -10,23 +10,24 @@ "preview": "vite preview" }, "dependencies": { - "@farcaster/auth-kit": "*", - "ethers": "5", + "@farcaster/auth-kit": "workspace:*", + "ethers": "6", + "@tanstack/react-query": "^5.28.8", "react": "^18.2.0", "react-dom": "^18.2.0", - "viem": "^2.0.3", + "viem": "^2.9.0", "vite-plugin-node-polyfills": "^0.21.0" }, "devDependencies": { - "@types/react": "^18.2.43", - "@types/react-dom": "^18.2.17", - "@typescript-eslint/eslint-plugin": "^6.14.0", - "@typescript-eslint/parser": "^6.14.0", + "@types/react": "^18.2.70", + "@types/react-dom": "^18.2.22", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", "@vitejs/plugin-react": "^4.2.1", - "eslint": "^8.55.0", + "eslint": "^8.57.0", "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.5", - "typescript": "^5.2.2", - "vite": "^5.0.12" + "eslint-plugin-react-refresh": "^0.4.6", + "typescript": "^5.4.3", + "vite": "^5.2.6" } } diff --git a/examples/frontend-only/src/App.tsx b/examples/frontend-only/src/App.tsx index 892067f..e80ba70 100644 --- a/examples/frontend-only/src/App.tsx +++ b/examples/frontend-only/src/App.tsx @@ -1,94 +1,88 @@ +import { JsonRpcProvider } from "ethers"; import "@farcaster/auth-kit/styles.css"; -import { providers } from "ethers"; -import { AuthKitProvider, SignInButton, useProfile } from "@farcaster/auth-kit"; +import { AuthKitProvider, createConfig, SignInButton, useProfile } from "@farcaster/auth-kit"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -const config = { +const queryClient = new QueryClient(); + +const config = createConfig({ // For a production app, replace this with an Optimism Mainnet // RPC URL from a provider like Alchemy or Infura. relay: "https://relay.farcaster.xyz", rpcUrl: "https://mainnet.optimism.io", domain: "example.com", siweUri: "https://example.com/login", - provider: new providers.JsonRpcProvider(undefined, 10) -}; + provider: new JsonRpcProvider(undefined, 10) +}); function App() { return (
- {/* @ts-expect-error ethers version type incompat */} - -
- -
-
-

@farcaster/auth-kit + Vite

-

- This example app shows how to use{" "} - - Farcaster AuthKit - {" "} - and{" "} - - Vite - - . -

- -
-

Run this demo:

-
- git clone https://github.com/farcasterxyz/auth-monorepo.git && -
- cd auth-monorepo/examples/frontend-only && -
- yarn install && -
- yarn dev + + +
+ +
+
+

@farcaster/auth-kit + Vite

+

+ This example app shows how to use{" "} + + Farcaster AuthKit + {" "} + and{" "} + + Vite + + . +

+ +
+

Run this demo:

+
+ git clone https://github.com/farcasterxyz/auth-monorepo.git && +
+ cd auth-monorepo/examples/frontend-only && +
+ pnpm install && +
+ pnpm dev +
-
- + +
); } function Profile() { const profile = useProfile(); - const { - isAuthenticated, - profile: { fid, displayName, custody }, - } = profile; return ( <> - {isAuthenticated ? ( + {profile?.isAuthenticated ? (

- Hello, {displayName}! Your FID is {fid}. + Hello, {profile.displayName}! Your FID is {profile.fid}.

- Your custody address is:

{custody}
+ Your custody address is:
{profile.custody}

) : ( -

- Click the "Sign in with Farcaster" button above, then scan the QR code - to sign in. -

+

Click the "Sign in with Farcaster" button above, then scan the QR code to sign in.

)} ); diff --git a/examples/frontend-only/src/main.tsx b/examples/frontend-only/src/main.tsx index 1926863..3646e29 100644 --- a/examples/frontend-only/src/main.tsx +++ b/examples/frontend-only/src/main.tsx @@ -1,7 +1,6 @@ import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App.tsx"; - const root = document.getElementById("root"); if (root) { diff --git a/examples/frontend-only/tsconfig.node.json b/examples/frontend-only/tsconfig.node.json index 42872c5..61c424b 100644 --- a/examples/frontend-only/tsconfig.node.json +++ b/examples/frontend-only/tsconfig.node.json @@ -5,6 +5,5 @@ "module": "ESNext", "moduleResolution": "bundler", "allowSyntheticDefaultImports": true - }, - "include": ["vite.config.ts"] + } } diff --git a/examples/frontend-only/turbo.json b/examples/frontend-only/turbo.json new file mode 100644 index 0000000..7a21b8c --- /dev/null +++ b/examples/frontend-only/turbo.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://turbo.build/schema.json", + "extends": ["//"], + "pipeline": { + "build": { + "dependsOn": ["@farcaster/auth-client#build"], + "inputs": ["src/**", "vite.config.ts", "tsconfig.json", "tsconfig.node.json"], + "outputs": ["dist/**"] + } + } +} diff --git a/examples/frontend-only/yarn.lock b/examples/frontend-only/yarn.lock deleted file mode 100644 index 6af842a..0000000 --- a/examples/frontend-only/yarn.lock +++ /dev/null @@ -1,2973 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@aashutoshrathi/word-wrap@^1.2.3": - version "1.2.6" - resolved "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" - integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== - -"@adraffy/ens-normalize@1.10.0": - version "1.10.0" - resolved "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" - integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== - -"@ampproject/remapping@^2.2.0": - version "2.2.1" - resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" - integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== - dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" - -"@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5": - version "7.23.5" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" - integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== - dependencies: - "@babel/highlight" "^7.23.4" - chalk "^2.4.2" - -"@babel/compat-data@^7.23.5": - version "7.23.5" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" - integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== - -"@babel/core@^7.23.5": - version "7.23.7" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz#4d8016e06a14b5f92530a13ed0561730b5c6483f" - integrity sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helpers" "^7.23.7" - "@babel/parser" "^7.23.6" - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.7" - "@babel/types" "^7.23.6" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - -"@babel/generator@^7.23.6": - version "7.23.6" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" - integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== - dependencies: - "@babel/types" "^7.23.6" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" - -"@babel/helper-compilation-targets@^7.23.6": - version "7.23.6" - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" - integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== - dependencies: - "@babel/compat-data" "^7.23.5" - "@babel/helper-validator-option" "^7.23.5" - browserslist "^4.22.2" - lru-cache "^5.1.1" - semver "^6.3.1" - -"@babel/helper-environment-visitor@^7.22.20": - version "7.22.20" - resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" - integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== - -"@babel/helper-function-name@^7.23.0": - version "7.23.0" - resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" - integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== - dependencies: - "@babel/template" "^7.22.15" - "@babel/types" "^7.23.0" - -"@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-module-imports@^7.22.15": - version "7.22.15" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" - integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== - dependencies: - "@babel/types" "^7.22.15" - -"@babel/helper-module-transforms@^7.23.3": - version "7.23.3" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" - integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-simple-access" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/helper-validator-identifier" "^7.22.20" - -"@babel/helper-plugin-utils@^7.22.5": - version "7.22.5" - resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" - integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== - -"@babel/helper-simple-access@^7.22.5": - version "7.22.5" - resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" - integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-split-export-declaration@^7.22.6": - version "7.22.6" - resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" - integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-string-parser@^7.23.4": - version "7.23.4" - resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" - integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== - -"@babel/helper-validator-identifier@^7.22.20": - version "7.22.20" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" - integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== - -"@babel/helper-validator-option@^7.23.5": - version "7.23.5" - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" - integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== - -"@babel/helpers@^7.23.7": - version "7.23.7" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.7.tgz#eb543c36f81da2873e47b76ee032343ac83bba60" - integrity sha512-6AMnjCoC8wjqBzDHkuqpa7jAKwvMo4dC+lr/TFBz+ucfulO1XMpDnwWPGBNwClOKZ8h6xn5N81W/R5OrcKtCbQ== - dependencies: - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.7" - "@babel/types" "^7.23.6" - -"@babel/highlight@^7.23.4": - version "7.23.4" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" - integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== - dependencies: - "@babel/helper-validator-identifier" "^7.22.20" - chalk "^2.4.2" - js-tokens "^4.0.0" - -"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.23.6": - version "7.23.6" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" - integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== - -"@babel/plugin-transform-react-jsx-self@^7.23.3": - version "7.23.3" - resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.23.3.tgz#ed3e7dadde046cce761a8e3cf003a13d1a7972d9" - integrity sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-transform-react-jsx-source@^7.23.3": - version "7.23.3" - resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.23.3.tgz#03527006bdc8775247a78643c51d4e715fe39a3e" - integrity sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/runtime@^7.12.5": - version "7.23.7" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.7.tgz#dd7c88deeb218a0f8bd34d5db1aa242e0f203193" - integrity sha512-w06OXVOFso7LcbzMiDGt+3X7Rh7Ho8MmgPoWU3rarH+8upf+wSU/grlGbWzQyr3DkdN6ZeuMFjpdwW0Q+HxobA== - dependencies: - regenerator-runtime "^0.14.0" - -"@babel/template@^7.22.15": - version "7.22.15" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" - integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== - dependencies: - "@babel/code-frame" "^7.22.13" - "@babel/parser" "^7.22.15" - "@babel/types" "^7.22.15" - -"@babel/traverse@^7.23.7": - version "7.23.7" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz#9a7bf285c928cb99b5ead19c3b1ce5b310c9c305" - integrity sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.23.6" - "@babel/types" "^7.23.6" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6": - version "7.23.6" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd" - integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg== - dependencies: - "@babel/helper-string-parser" "^7.23.4" - "@babel/helper-validator-identifier" "^7.22.20" - to-fast-properties "^2.0.0" - -"@emotion/hash@^0.9.0": - version "0.9.1" - resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43" - integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ== - -"@esbuild/aix-ppc64@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.11.tgz#2acd20be6d4f0458bc8c784103495ff24f13b1d3" - integrity sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g== - -"@esbuild/android-arm64@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.11.tgz#b45d000017385c9051a4f03e17078abb935be220" - integrity sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q== - -"@esbuild/android-arm@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.11.tgz#f46f55414e1c3614ac682b29977792131238164c" - integrity sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw== - -"@esbuild/android-x64@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.11.tgz#bfc01e91740b82011ef503c48f548950824922b2" - integrity sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg== - -"@esbuild/darwin-arm64@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.11.tgz#533fb7f5a08c37121d82c66198263dcc1bed29bf" - integrity sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ== - -"@esbuild/darwin-x64@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.11.tgz#62f3819eff7e4ddc656b7c6815a31cf9a1e7d98e" - integrity sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g== - -"@esbuild/freebsd-arm64@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.11.tgz#d478b4195aa3ca44160272dab85ef8baf4175b4a" - integrity sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA== - -"@esbuild/freebsd-x64@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.11.tgz#7bdcc1917409178257ca6a1a27fe06e797ec18a2" - integrity sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw== - -"@esbuild/linux-arm64@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.11.tgz#58ad4ff11685fcc735d7ff4ca759ab18fcfe4545" - integrity sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg== - -"@esbuild/linux-arm@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.11.tgz#ce82246d873b5534d34de1e5c1b33026f35e60e3" - integrity sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q== - -"@esbuild/linux-ia32@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.11.tgz#cbae1f313209affc74b80f4390c4c35c6ab83fa4" - integrity sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA== - -"@esbuild/linux-loong64@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.11.tgz#5f32aead1c3ec8f4cccdb7ed08b166224d4e9121" - integrity sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg== - -"@esbuild/linux-mips64el@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.11.tgz#38eecf1cbb8c36a616261de858b3c10d03419af9" - integrity sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg== - -"@esbuild/linux-ppc64@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.11.tgz#9c5725a94e6ec15b93195e5a6afb821628afd912" - integrity sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA== - -"@esbuild/linux-riscv64@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.11.tgz#2dc4486d474a2a62bbe5870522a9a600e2acb916" - integrity sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ== - -"@esbuild/linux-s390x@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.11.tgz#4ad8567df48f7dd4c71ec5b1753b6f37561a65a8" - integrity sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q== - -"@esbuild/linux-x64@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.11.tgz#b7390c4d5184f203ebe7ddaedf073df82a658766" - integrity sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA== - -"@esbuild/netbsd-x64@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.11.tgz#d633c09492a1721377f3bccedb2d821b911e813d" - integrity sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ== - -"@esbuild/openbsd-x64@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.11.tgz#17388c76e2f01125bf831a68c03a7ffccb65d1a2" - integrity sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw== - -"@esbuild/sunos-x64@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.11.tgz#e320636f00bb9f4fdf3a80e548cb743370d41767" - integrity sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ== - -"@esbuild/win32-arm64@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.11.tgz#c778b45a496e90b6fc373e2a2bb072f1441fe0ee" - integrity sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ== - -"@esbuild/win32-ia32@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.11.tgz#481a65fee2e5cce74ec44823e6b09ecedcc5194c" - integrity sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg== - -"@esbuild/win32-x64@0.19.11": - version "0.19.11" - resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz#a5d300008960bb39677c46bf16f53ec70d8dee04" - integrity sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw== - -"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": - version "4.4.0" - resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" - integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== - dependencies: - eslint-visitor-keys "^3.3.0" - -"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": - version "4.10.0" - resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" - integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== - -"@eslint/eslintrc@^2.1.4": - version "2.1.4" - resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.6.0" - globals "^13.19.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@eslint/js@8.56.0": - version "8.56.0" - resolved "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz#ef20350fec605a7f7035a01764731b2de0f3782b" - integrity sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A== - -"@farcaster/auth-client@^0.1.0": - version "0.1.0" - resolved "https://registry.npmjs.org/@farcaster/auth-client/-/auth-client-0.1.0.tgz#3f1608ee8398bc71e8da23a898aa721b36ce78d3" - integrity sha512-hWeUDwpyNNswclL82K5wt6sA0x0UjELGhLKSZK6JYvGAE6wNR6V8o1IBhZYIGASWHHxOGoJLZ1L1xRcvS3GbUQ== - dependencies: - ethers "^6.9.2" - neverthrow "^6.1.0" - siwe "^2.1.4" - -"@farcaster/auth-kit@^0.1.4": - version "0.1.4" - resolved "https://registry.npmjs.org/@farcaster/auth-kit/-/auth-kit-0.1.4.tgz#1b76195d018f3c8a3d01e45244e06e5527313f94" - integrity sha512-+SUdbme/NEcl4E2/ktwhvJMNgU5NHmaHUeCpgtvg8OIu52VvYEL6oChERjNJfVVlzvSub006E9KMC7Iao51tsQ== - dependencies: - "@farcaster/auth-client" "^0.1.0" - "@vanilla-extract/css" "^1.14.0" - qrcode "^1.5.3" - react-remove-scroll "^2.5.7" - -"@humanwhocodes/config-array@^0.11.13": - version "0.11.13" - resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz#075dc9684f40a531d9b26b0822153c1e832ee297" - integrity sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ== - dependencies: - "@humanwhocodes/object-schema" "^2.0.1" - debug "^4.1.1" - minimatch "^3.0.5" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^2.0.1": - version "2.0.1" - resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz#e5211452df060fa8522b55c7b3c0c4d1981cb044" - integrity sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw== - -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - version "0.3.3" - resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" - integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== - dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.1" - resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" - integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== - -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15": - version "1.4.15" - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.20" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" - integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@noble/curves@1.2.0", "@noble/curves@~1.2.0": - version "1.2.0" - resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" - integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== - dependencies: - "@noble/hashes" "1.3.2" - -"@noble/hashes@1.3.2": - version "1.3.2" - resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" - integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== - -"@noble/hashes@^1.1.2", "@noble/hashes@~1.3.0", "@noble/hashes@~1.3.2": - version "1.3.3" - resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" - integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": - version "1.2.8" - resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@rollup/plugin-inject@^5.0.5": - version "5.0.5" - resolved "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-5.0.5.tgz#616f3a73fe075765f91c5bec90176608bed277a3" - integrity sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg== - dependencies: - "@rollup/pluginutils" "^5.0.1" - estree-walker "^2.0.2" - magic-string "^0.30.3" - -"@rollup/pluginutils@^5.0.1": - version "5.1.0" - resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz#7e53eddc8c7f483a4ad0b94afb1f7f5fd3c771e0" - integrity sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g== - dependencies: - "@types/estree" "^1.0.0" - estree-walker "^2.0.2" - picomatch "^2.3.1" - -"@rollup/rollup-android-arm-eabi@4.9.4": - version "4.9.4" - resolved "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.4.tgz#b1094962742c1a0349587040bc06185e2a667c9b" - integrity sha512-ub/SN3yWqIv5CWiAZPHVS1DloyZsJbtXmX4HxUTIpS0BHm9pW5iYBo2mIZi+hE3AeiTzHz33blwSnhdUo+9NpA== - -"@rollup/rollup-android-arm64@4.9.4": - version "4.9.4" - resolved "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.4.tgz#96eb86fb549e05b187f2ad06f51d191a23cb385a" - integrity sha512-ehcBrOR5XTl0W0t2WxfTyHCR/3Cq2jfb+I4W+Ch8Y9b5G+vbAecVv0Fx/J1QKktOrgUYsIKxWAKgIpvw56IFNA== - -"@rollup/rollup-darwin-arm64@4.9.4": - version "4.9.4" - resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.4.tgz#2456630c007cc5905cb368acb9ff9fc04b2d37be" - integrity sha512-1fzh1lWExwSTWy8vJPnNbNM02WZDS8AW3McEOb7wW+nPChLKf3WG2aG7fhaUmfX5FKw9zhsF5+MBwArGyNM7NA== - -"@rollup/rollup-darwin-x64@4.9.4": - version "4.9.4" - resolved "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.4.tgz#97742214fc7dfd47a0f74efba6f5ae264e29c70c" - integrity sha512-Gc6cukkF38RcYQ6uPdiXi70JB0f29CwcQ7+r4QpfNpQFVHXRd0DfWFidoGxjSx1DwOETM97JPz1RXL5ISSB0pA== - -"@rollup/rollup-linux-arm-gnueabihf@4.9.4": - version "4.9.4" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.4.tgz#cd933e61d6f689c9cdefde424beafbd92cfe58e2" - integrity sha512-g21RTeFzoTl8GxosHbnQZ0/JkuFIB13C3T7Y0HtKzOXmoHhewLbVTFBQZu+z5m9STH6FZ7L/oPgU4Nm5ErN2fw== - -"@rollup/rollup-linux-arm64-gnu@4.9.4": - version "4.9.4" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.4.tgz#33b09bf462f1837afc1e02a1b352af6b510c78a6" - integrity sha512-TVYVWD/SYwWzGGnbfTkrNpdE4HON46orgMNHCivlXmlsSGQOx/OHHYiQcMIOx38/GWgwr/po2LBn7wypkWw/Mg== - -"@rollup/rollup-linux-arm64-musl@4.9.4": - version "4.9.4" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.4.tgz#50257fb248832c2308064e3764a16273b6ee4615" - integrity sha512-XcKvuendwizYYhFxpvQ3xVpzje2HHImzg33wL9zvxtj77HvPStbSGI9czrdbfrf8DGMcNNReH9pVZv8qejAQ5A== - -"@rollup/rollup-linux-riscv64-gnu@4.9.4": - version "4.9.4" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.4.tgz#09589e4e1a073cf56f6249b77eb6c9a8e9b613a8" - integrity sha512-LFHS/8Q+I9YA0yVETyjonMJ3UA+DczeBd/MqNEzsGSTdNvSJa1OJZcSH8GiXLvcizgp9AlHs2walqRcqzjOi3A== - -"@rollup/rollup-linux-x64-gnu@4.9.4": - version "4.9.4" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.4.tgz#bd312bb5b5f02e54d15488605d15cfd3f90dda7c" - integrity sha512-dIYgo+j1+yfy81i0YVU5KnQrIJZE8ERomx17ReU4GREjGtDW4X+nvkBak2xAUpyqLs4eleDSj3RrV72fQos7zw== - -"@rollup/rollup-linux-x64-musl@4.9.4": - version "4.9.4" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.4.tgz#25b3bede85d86438ce28cc642842d10d867d40e9" - integrity sha512-RoaYxjdHQ5TPjaPrLsfKqR3pakMr3JGqZ+jZM0zP2IkDtsGa4CqYaWSfQmZVgFUCgLrTnzX+cnHS3nfl+kB6ZQ== - -"@rollup/rollup-win32-arm64-msvc@4.9.4": - version "4.9.4" - resolved "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.4.tgz#95957067eb107f571da1d81939f017d37b4958d3" - integrity sha512-T8Q3XHV+Jjf5e49B4EAaLKV74BbX7/qYBRQ8Wop/+TyyU0k+vSjiLVSHNWdVd1goMjZcbhDmYZUYW5RFqkBNHQ== - -"@rollup/rollup-win32-ia32-msvc@4.9.4": - version "4.9.4" - resolved "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.4.tgz#71b6facad976db527863f698692c6964c0b6e10e" - integrity sha512-z+JQ7JirDUHAsMecVydnBPWLwJjbppU+7LZjffGf+Jvrxq+dVjIE7By163Sc9DKc3ADSU50qPVw0KonBS+a+HQ== - -"@rollup/rollup-win32-x64-msvc@4.9.4": - version "4.9.4" - resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.4.tgz#16295ccae354707c9bc6842906bdeaad4f3ba7a5" - integrity sha512-LfdGXCV9rdEify1oxlN9eamvDSjv9md9ZVMAbNHA87xqIfFCxImxan9qZ8+Un54iK2nnqPlbnSi4R54ONtbWBw== - -"@scure/base@~1.1.0", "@scure/base@~1.1.2": - version "1.1.5" - resolved "https://registry.npmjs.org/@scure/base/-/base-1.1.5.tgz#1d85d17269fe97694b9c592552dd9e5e33552157" - integrity sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ== - -"@scure/bip32@1.3.2": - version "1.3.2" - resolved "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.2.tgz#90e78c027d5e30f0b22c1f8d50ff12f3fb7559f8" - integrity sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA== - dependencies: - "@noble/curves" "~1.2.0" - "@noble/hashes" "~1.3.2" - "@scure/base" "~1.1.2" - -"@scure/bip39@1.2.1": - version "1.2.1" - resolved "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" - integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== - dependencies: - "@noble/hashes" "~1.3.0" - "@scure/base" "~1.1.0" - -"@spruceid/siwe-parser@*": - version "2.0.2" - resolved "https://registry.npmjs.org/@spruceid/siwe-parser/-/siwe-parser-2.0.2.tgz#964dbe9e5611fe95d39e21aa96e67407f610374f" - integrity sha512-9WuA0ios2537cWYu39MMeH0O2KdrMKgKlOBUTWRTXQjCYu5B+mHCA0JkCbFaJ/0EjxoVIcYCXIW/DoPEpw+PqA== - dependencies: - "@noble/hashes" "^1.1.2" - apg-js "^4.1.1" - uri-js "^4.4.1" - valid-url "^1.0.9" - -"@stablelib/binary@^1.0.1": - version "1.0.1" - resolved "https://registry.npmjs.org/@stablelib/binary/-/binary-1.0.1.tgz#c5900b94368baf00f811da5bdb1610963dfddf7f" - integrity sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q== - dependencies: - "@stablelib/int" "^1.0.1" - -"@stablelib/int@^1.0.1": - version "1.0.1" - resolved "https://registry.npmjs.org/@stablelib/int/-/int-1.0.1.tgz#75928cc25d59d73d75ae361f02128588c15fd008" - integrity sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w== - -"@stablelib/random@^1.0.1": - version "1.0.2" - resolved "https://registry.npmjs.org/@stablelib/random/-/random-1.0.2.tgz#2dece393636489bf7e19c51229dd7900eddf742c" - integrity sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w== - dependencies: - "@stablelib/binary" "^1.0.1" - "@stablelib/wipe" "^1.0.1" - -"@stablelib/wipe@^1.0.1": - version "1.0.1" - resolved "https://registry.npmjs.org/@stablelib/wipe/-/wipe-1.0.1.tgz#d21401f1d59ade56a62e139462a97f104ed19a36" - integrity sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg== - -"@types/babel__core@^7.20.5": - version "7.20.5" - resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" - integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== - dependencies: - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__generator@*": - version "7.6.8" - resolved "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" - integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__template@*": - version "7.4.4" - resolved "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" - integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - -"@types/babel__traverse@*": - version "7.20.5" - resolved "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz#7b7502be0aa80cc4ef22978846b983edaafcd4dd" - integrity sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ== - dependencies: - "@babel/types" "^7.20.7" - -"@types/estree@1.0.5", "@types/estree@^1.0.0": - version "1.0.5" - resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" - integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== - -"@types/json-schema@^7.0.12": - version "7.0.15" - resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - -"@types/node@18.15.13": - version "18.15.13" - resolved "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" - integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== - -"@types/prop-types@*": - version "15.7.11" - resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563" - integrity sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng== - -"@types/react-dom@^18.2.17": - version "18.2.18" - resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz#16946e6cd43971256d874bc3d0a72074bb8571dd" - integrity sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw== - dependencies: - "@types/react" "*" - -"@types/react@*", "@types/react@^18.2.43": - version "18.2.47" - resolved "https://registry.npmjs.org/@types/react/-/react-18.2.47.tgz#85074b27ab563df01fbc3f68dc64bf7050b0af40" - integrity sha512-xquNkkOirwyCgoClNk85BjP+aqnIS+ckAJ8i37gAbDs14jfW/J23f2GItAf33oiUPQnqNMALiFeoM9Y5mbjpVQ== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - -"@types/scheduler@*": - version "0.16.8" - resolved "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff" - integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A== - -"@types/semver@^7.5.0": - version "7.5.6" - resolved "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz#c65b2bfce1bec346582c07724e3f8c1017a20339" - integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A== - -"@typescript-eslint/eslint-plugin@^6.14.0": - version "6.18.0" - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.0.tgz#94b86f3c25b468c714a04bd490017ecec2fd3746" - integrity sha512-3lqEvQUdCozi6d1mddWqd+kf8KxmGq2Plzx36BlkjuQe3rSTm/O98cLf0A4uDO+a5N1KD2SeEEl6fW97YHY+6w== - dependencies: - "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "6.18.0" - "@typescript-eslint/type-utils" "6.18.0" - "@typescript-eslint/utils" "6.18.0" - "@typescript-eslint/visitor-keys" "6.18.0" - debug "^4.3.4" - graphemer "^1.4.0" - ignore "^5.2.4" - natural-compare "^1.4.0" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/parser@^6.14.0": - version "6.18.0" - resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.18.0.tgz#d494161d64832e869f0a6acc6000a2cdff858383" - integrity sha512-v6uR68SFvqhNQT41frCMCQpsP+5vySy6IdgjlzUWoo7ALCnpaWYcz/Ij2k4L8cEsL0wkvOviCMpjmtRtHNOKzA== - dependencies: - "@typescript-eslint/scope-manager" "6.18.0" - "@typescript-eslint/types" "6.18.0" - "@typescript-eslint/typescript-estree" "6.18.0" - "@typescript-eslint/visitor-keys" "6.18.0" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@6.18.0": - version "6.18.0" - resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz#24ca6fc1f4a2afa71122dcfca9282878687d9997" - integrity sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA== - dependencies: - "@typescript-eslint/types" "6.18.0" - "@typescript-eslint/visitor-keys" "6.18.0" - -"@typescript-eslint/type-utils@6.18.0": - version "6.18.0" - resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.18.0.tgz#a492da599da5c38c70aa9ff9bfb473961b8ae663" - integrity sha512-ZeMtrXnGmTcHciJN1+u2CigWEEXgy1ufoxtWcHORt5kGvpjjIlK9MUhzHm4RM8iVy6dqSaZA/6PVkX6+r+ChjQ== - dependencies: - "@typescript-eslint/typescript-estree" "6.18.0" - "@typescript-eslint/utils" "6.18.0" - debug "^4.3.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/types@6.18.0": - version "6.18.0" - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz#ffce610a1540c17cf7d8ecf2bb34b8b0e2e77101" - integrity sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA== - -"@typescript-eslint/typescript-estree@6.18.0": - version "6.18.0" - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz#1c357c3ca435c3cfa2af6b9daf45ca0bc2bb059a" - integrity sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg== - dependencies: - "@typescript-eslint/types" "6.18.0" - "@typescript-eslint/visitor-keys" "6.18.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - minimatch "9.0.3" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/utils@6.18.0": - version "6.18.0" - resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz#4d07c9c08f84b9939a1aca7aef98c8f378936142" - integrity sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA== - dependencies: - "@eslint-community/eslint-utils" "^4.4.0" - "@types/json-schema" "^7.0.12" - "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "6.18.0" - "@typescript-eslint/types" "6.18.0" - "@typescript-eslint/typescript-estree" "6.18.0" - semver "^7.5.4" - -"@typescript-eslint/visitor-keys@6.18.0": - version "6.18.0" - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz#3c8733737786fa6c78a347b4fa306ae7155b560f" - integrity sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA== - dependencies: - "@typescript-eslint/types" "6.18.0" - eslint-visitor-keys "^3.4.1" - -"@ungap/structured-clone@^1.2.0": - version "1.2.0" - resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== - -"@vanilla-extract/css@^1.14.0": - version "1.14.0" - resolved "https://registry.npmjs.org/@vanilla-extract/css/-/css-1.14.0.tgz#45fab9c04d893e3e363cf2cde7559d21233b7f63" - integrity sha512-rYfm7JciWZ8PFzBM/HDiE2GLnKI3xJ6/vdmVJ5BSgcCZ5CxRlM9Cjqclni9lGzF3eMOijnUhCd/KV8TOzyzbMA== - dependencies: - "@emotion/hash" "^0.9.0" - "@vanilla-extract/private" "^1.0.3" - chalk "^4.1.1" - css-what "^6.1.0" - cssesc "^3.0.0" - csstype "^3.0.7" - deep-object-diff "^1.1.9" - deepmerge "^4.2.2" - media-query-parser "^2.0.2" - modern-ahocorasick "^1.0.0" - outdent "^0.8.0" - -"@vanilla-extract/private@^1.0.3": - version "1.0.3" - resolved "https://registry.npmjs.org/@vanilla-extract/private/-/private-1.0.3.tgz#7ec72bc2ff6fe51f9d650f962e8d1989b073690f" - integrity sha512-17kVyLq3ePTKOkveHxXuIJZtGYs+cSoev7BlP+Lf4916qfDhk/HBjvlYDe8egrea7LNPHKwSZJK/bzZC+Q6AwQ== - -"@vitejs/plugin-react@^4.2.1": - version "4.2.1" - resolved "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz#744d8e4fcb120fc3dbaa471dadd3483f5a304bb9" - integrity sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ== - dependencies: - "@babel/core" "^7.23.5" - "@babel/plugin-transform-react-jsx-self" "^7.23.3" - "@babel/plugin-transform-react-jsx-source" "^7.23.3" - "@types/babel__core" "^7.20.5" - react-refresh "^0.14.0" - -abitype@0.10.0: - version "0.10.0" - resolved "https://registry.npmjs.org/abitype/-/abitype-0.10.0.tgz#d3504747cc81df2acaa6c460250ef7bc9219a77c" - integrity sha512-QvMHEUzgI9nPj9TWtUGnS2scas80/qaL5PBxGdwWhhvzqXfOph+IEiiiWrzuisu3U3JgDQVruW9oLbJoQ3oZ3A== - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn@^8.9.0: - version "8.11.3" - resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== - -aes-js@4.0.0-beta.5: - version "4.0.0-beta.5" - resolved "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" - integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== - -ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -apg-js@^4.1.1: - version "4.3.0" - resolved "https://registry.npmjs.org/apg-js/-/apg-js-4.3.0.tgz#2c55d3f1aa6b90be5d3c6539f346cf2c726702c3" - integrity sha512-8U8MULS+JocCnm11bfrVS4zxtAcE3uOiCAI21SnjDrV9LNhMSGwTGGeko3QfyK1JLWwT7KebFqJMB2puzfdFMQ== - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -asn1.js@^5.2.0: - version "5.4.1" - resolved "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" - -assert@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz#6d92a238d05dc02e7427c881fb8be81c8448b2dd" - integrity sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw== - dependencies: - call-bind "^1.0.2" - is-nan "^1.3.2" - object-is "^1.1.5" - object.assign "^4.1.4" - util "^0.12.5" - -available-typed-arrays@^1.0.6: - version "1.0.6" - resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz#ac812d8ce5a6b976d738e1c45f08d0b00bc7d725" - integrity sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg== - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: - version "4.12.0" - resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== - -bn.js@^5.0.0, bn.js@^5.2.1: - version "5.2.1" - resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" - integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -brorand@^1.0.1, brorand@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== - -browser-resolve@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz#99b7304cb392f8d73dba741bb2d7da28c6d7842b" - integrity sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ== - dependencies: - resolve "^1.17.0" - -browserify-aes@^1.0.0, browserify-aes@^1.0.4: - version "1.2.0" - resolved "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" - integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== - dependencies: - bn.js "^5.0.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.2.2" - resolved "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz#e78d4b69816d6e3dd1c747e64e9947f9ad79bc7e" - integrity sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg== - dependencies: - bn.js "^5.2.1" - browserify-rsa "^4.1.0" - create-hash "^1.2.0" - create-hmac "^1.1.7" - elliptic "^6.5.4" - inherits "^2.0.4" - parse-asn1 "^5.1.6" - readable-stream "^3.6.2" - safe-buffer "^5.2.1" - -browserify-zlib@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== - dependencies: - pako "~1.0.5" - -browserslist@^4.22.2: - version "4.22.2" - resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" - integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A== - dependencies: - caniuse-lite "^1.0.30001565" - electron-to-chromium "^1.4.601" - node-releases "^2.0.14" - update-browserslist-db "^1.0.13" - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== - -buffer@^5.7.1: - version "5.7.1" - resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ== - -call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6: - version "1.0.7" - resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - set-function-length "^1.2.1" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^5.0.0: - version "5.3.1" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -caniuse-lite@^1.0.30001565: - version "1.0.30001576" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001576.tgz#893be772cf8ee6056d6c1e2d07df365b9ec0a5c4" - integrity sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg== - -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.0.0, chalk@^4.1.1: - version "4.1.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -cliui@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" - integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^6.2.0" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -console-browserify@^1.1.0: - version "1.2.0" - resolved "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" - integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== - -constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ== - -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - -create-ecdh@^4.0.0: - version "4.0.4" - resolved "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" - integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== - dependencies: - bn.js "^4.1.0" - elliptic "^6.5.3" - -create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: - version "1.1.7" - resolved "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -create-require@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - -cross-spawn@^7.0.2: - version "7.0.3" - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -crypto-browserify@^3.11.0: - version "3.12.0" - resolved "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -css-what@^6.1.0: - version "6.1.0" - resolved "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" - integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== - -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - -csstype@^3.0.2, csstype@^3.0.7: - version "3.1.3" - resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" - integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== - -debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -deep-object-diff@^1.1.9: - version "1.1.9" - resolved "https://registry.npmjs.org/deep-object-diff/-/deep-object-diff-1.1.9.tgz#6df7ef035ad6a0caa44479c536ed7b02570f4595" - integrity sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA== - -deepmerge@^4.2.2: - version "4.3.1" - resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" - integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== - -define-data-property@^1.0.1, define-data-property@^1.1.2: - version "1.1.4" - resolved "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - gopd "^1.0.1" - -define-properties@^1.1.3, define-properties@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" - integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== - dependencies: - define-data-property "^1.0.1" - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -des.js@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz#1d37f5766f3bbff4ee9638e871a8768c173b81da" - integrity sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg== - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -detect-node-es@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" - integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== - -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - -dijkstrajs@^1.0.1: - version "1.0.3" - resolved "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz#4c8dbdea1f0f6478bff94d9c49c784d623e4fc23" - integrity sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -domain-browser@^4.22.0: - version "4.23.0" - resolved "https://registry.npmjs.org/domain-browser/-/domain-browser-4.23.0.tgz#427ebb91efcb070f05cffdfb8a4e9a6c25f8c94b" - integrity sha512-ArzcM/II1wCCujdCNyQjXrAFwS4mrLh4C7DZWlaI8mdh7h3BfKdNd3bKXITfl2PT9FtfQqaGvhi1vPRQPimjGA== - -electron-to-chromium@^1.4.601: - version "1.4.623" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.623.tgz#0f7400114ac3425500e9244d2b0e9c3107c331cb" - integrity sha512-lKoz10iCYlP1WtRYdh5MvocQPWVRoI7ysp6qf18bmeBgR8abE6+I2CsfyNKztRDZvhdWc+krKT6wS7Neg8sw3A== - -elliptic@^6.5.3, elliptic@^6.5.4: - version "6.5.4" - resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -encode-utf8@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" - integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== - -es-define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" - integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== - dependencies: - get-intrinsic "^1.2.4" - -es-errors@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== - -esbuild@^0.19.3: - version "0.19.11" - resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.19.11.tgz#4a02dca031e768b5556606e1b468fe72e3325d96" - integrity sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA== - optionalDependencies: - "@esbuild/aix-ppc64" "0.19.11" - "@esbuild/android-arm" "0.19.11" - "@esbuild/android-arm64" "0.19.11" - "@esbuild/android-x64" "0.19.11" - "@esbuild/darwin-arm64" "0.19.11" - "@esbuild/darwin-x64" "0.19.11" - "@esbuild/freebsd-arm64" "0.19.11" - "@esbuild/freebsd-x64" "0.19.11" - "@esbuild/linux-arm" "0.19.11" - "@esbuild/linux-arm64" "0.19.11" - "@esbuild/linux-ia32" "0.19.11" - "@esbuild/linux-loong64" "0.19.11" - "@esbuild/linux-mips64el" "0.19.11" - "@esbuild/linux-ppc64" "0.19.11" - "@esbuild/linux-riscv64" "0.19.11" - "@esbuild/linux-s390x" "0.19.11" - "@esbuild/linux-x64" "0.19.11" - "@esbuild/netbsd-x64" "0.19.11" - "@esbuild/openbsd-x64" "0.19.11" - "@esbuild/sunos-x64" "0.19.11" - "@esbuild/win32-arm64" "0.19.11" - "@esbuild/win32-ia32" "0.19.11" - "@esbuild/win32-x64" "0.19.11" - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-plugin-react-hooks@^4.6.0: - version "4.6.0" - resolved "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" - integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== - -eslint-plugin-react-refresh@^0.4.5: - version "0.4.5" - resolved "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.5.tgz#6b9b307bad3feba2244ef64a1a15485ac70a2d0f" - integrity sha512-D53FYKJa+fDmZMtriODxvhwrO+IOqrxoEo21gMA0sjHdU6dPVH4OhyFip9ypl8HOF5RV5KdTo+rBQLvnY2cO8w== - -eslint-scope@^7.2.2: - version "7.2.2" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: - version "3.4.3" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" - integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== - -eslint@^8.55.0: - version "8.56.0" - resolved "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz#4957ce8da409dc0809f99ab07a1b94832ab74b15" - integrity sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.56.0" - "@humanwhocodes/config-array" "^0.11.13" - "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - "@ungap/structured-clone" "^1.2.0" - ajv "^6.12.4" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.3" - espree "^9.6.1" - esquery "^1.4.2" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.2" - globals "^13.19.0" - graphemer "^1.4.0" - ignore "^5.2.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" - -espree@^9.6.0, espree@^9.6.1: - version "9.6.1" - resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== - dependencies: - acorn "^8.9.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" - -esquery@^1.4.2: - version "1.5.0" - resolved "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -estree-walker@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" - integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -ethers@^6.9.2: - version "6.9.2" - resolved "https://registry.npmjs.org/ethers/-/ethers-6.9.2.tgz#6f4632f62e2350fa8354ff28624027a175ef85a4" - integrity sha512-YpkrtILnMQz5jSEsJQRTpduaGT/CXuLnUIuOYzHA0v/7c8IX91m2J48wSKjzGL5L9J/Us3tLoUdb+OwE3U+FFQ== - dependencies: - "@adraffy/ens-normalize" "1.10.0" - "@noble/curves" "1.2.0" - "@noble/hashes" "1.3.2" - "@types/node" "18.15.13" - aes-js "4.0.0-beta.5" - tslib "2.4.0" - ws "8.5.0" - -events@^3.0.0: - version "3.3.0" - resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.2.9: - version "3.3.2" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" - integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fastq@^1.6.0: - version "1.16.0" - resolved "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz#83b9a9375692db77a822df081edb6a9cf6839320" - integrity sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA== - dependencies: - reusify "^1.0.4" - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flat-cache@^3.0.4: - version "3.2.0" - resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" - integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== - dependencies: - flatted "^3.2.9" - keyv "^4.5.3" - rimraf "^3.0.2" - -flatted@^3.2.9: - version "3.2.9" - resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" - integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== - -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@~2.3.2, fsevents@~2.3.3: - version "2.3.3" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-caller-file@^2.0.1: - version "2.0.5" - resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-intrinsic@^1.1.3, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: - version "1.2.4" - resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== - dependencies: - es-errors "^1.3.0" - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - -get-nonce@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" - integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== - -glob-parent@^5.1.2: - version "5.1.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob@^7.1.3: - version "7.2.3" - resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^13.19.0: - version "13.24.0" - resolved "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" - integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== - dependencies: - type-fest "^0.20.2" - -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -graphemer@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" - integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.1: - version "1.0.2" - resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== - dependencies: - es-define-property "^1.0.0" - -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== - -has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0, has-tostringtag@^1.0.1: - version "1.0.2" - resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" - integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== - dependencies: - has-symbols "^1.0.3" - -hash-base@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" - integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== - dependencies: - inherits "^2.0.4" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.7" - resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - -hasown@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz#26f48f039de2c0f8d3356c223fb8d50253519faa" - integrity sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA== - dependencies: - function-bind "^1.1.2" - -hmac-drbg@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - -https-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg== - -ieee754@^1.1.13: - version "1.2.1" - resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -ignore@^5.2.0, ignore@^5.2.4: - version "5.3.0" - resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" - integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== - -import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.4: - version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-callable@^1.1.3: - version "1.2.7" - resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-core-module@^2.13.0: - version "2.13.1" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== - dependencies: - hasown "^2.0.0" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-function@^1.0.7: - version "1.0.10" - resolved "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: - version "4.0.3" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-nan@^1.3.2: - version "1.3.2" - resolved "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" - integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-typed-array@^1.1.3: - version "1.1.13" - resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" - integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== - dependencies: - which-typed-array "^1.1.14" - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -isomorphic-timers-promises@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/isomorphic-timers-promises/-/isomorphic-timers-promises-1.0.1.tgz#e4137c24dbc54892de8abae3a4b5c1ffff381598" - integrity sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ== - -isows@1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/isows/-/isows-1.0.3.tgz#93c1cf0575daf56e7120bab5c8c448b0809d0d74" - integrity sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg== - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -json5@^2.2.3: - version "2.2.3" - resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - -keyv@^4.5.3: - version "4.5.4" - resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" - integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== - dependencies: - json-buffer "3.0.1" - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -loose-envify@^1.0.0, loose-envify@^1.1.0: - version "1.4.0" - resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -magic-string@^0.30.3: - version "0.30.7" - resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz#0cecd0527d473298679da95a2d7aeb8c64048505" - integrity sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA== - dependencies: - "@jridgewell/sourcemap-codec" "^1.4.15" - -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -media-query-parser@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/media-query-parser/-/media-query-parser-2.0.2.tgz#ff79e56cee92615a304a1c2fa4f2bd056c0a1d29" - integrity sha512-1N4qp+jE0pL5Xv4uEcwVUhIkwdUO3S/9gML90nqKA7v7FcOS5vUtatfzok9S9U1EJU8dHWlcv95WLnKmmxZI9w== - dependencies: - "@babel/runtime" "^7.12.5" - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== - -minimatch@9.0.3: - version "9.0.3" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -modern-ahocorasick@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/modern-ahocorasick/-/modern-ahocorasick-1.0.1.tgz#dec373444f51b5458ac05216a8ec376e126dd283" - integrity sha512-yoe+JbhTClckZ67b2itRtistFKf8yPYelHLc7e5xAwtNAXxM6wJTUx2C7QeVSJFDzKT7bCIFyBVybPMKvmB9AA== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -nanoid@^3.3.7: - version "3.3.7" - resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" - integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - -neverthrow@^6.1.0: - version "6.1.0" - resolved "https://registry.npmjs.org/neverthrow/-/neverthrow-6.1.0.tgz#51a6e9ce2e06600045b3c1b37aecc536d267bf95" - integrity sha512-xNbNjp/6M5vUV+mststgneJN9eJeJCDSYSBTaf3vxgvcKooP+8L0ATFpM8DGfmH7UWKJeoa24Qi33tBP9Ya3zA== - -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== - -node-stdlib-browser@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/node-stdlib-browser/-/node-stdlib-browser-1.2.0.tgz#5ddcfdf4063b88fb282979a1aa6ddab9728d5e4c" - integrity sha512-VSjFxUhRhkyed8AtLwSCkMrJRfQ3e2lGtG3sP6FEgaLKBBbxM/dLfjRe1+iLhjvyLFW3tBQ8+c0pcOtXGbAZJg== - dependencies: - assert "^2.0.0" - browser-resolve "^2.0.0" - browserify-zlib "^0.2.0" - buffer "^5.7.1" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - create-require "^1.1.1" - crypto-browserify "^3.11.0" - domain-browser "^4.22.0" - events "^3.0.0" - https-browserify "^1.0.0" - isomorphic-timers-promises "^1.0.1" - os-browserify "^0.3.0" - path-browserify "^1.0.1" - pkg-dir "^5.0.0" - process "^0.11.10" - punycode "^1.4.1" - querystring-es3 "^0.2.1" - readable-stream "^3.6.0" - stream-browserify "^3.0.0" - stream-http "^3.2.0" - string_decoder "^1.0.0" - timers-browserify "^2.0.4" - tty-browserify "0.0.1" - url "^0.11.0" - util "^0.12.4" - vm-browserify "^1.0.1" - -object-inspect@^1.13.1: - version "1.13.1" - resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== - -object-is@^1.1.5: - version "1.1.5" - resolved "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.4: - version "4.1.5" - resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" - integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== - dependencies: - call-bind "^1.0.5" - define-properties "^1.2.1" - has-symbols "^1.0.3" - object-keys "^1.1.1" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -optionator@^0.9.3: - version "0.9.3" - resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" - integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== - dependencies: - "@aashutoshrathi/word-wrap" "^1.2.3" - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - -os-browserify@^0.3.0: - version "0.3.0" - resolved "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A== - -outdent@^0.8.0: - version "0.8.0" - resolved "https://registry.npmjs.org/outdent/-/outdent-0.8.0.tgz#2ebc3e77bf49912543f1008100ff8e7f44428eb0" - integrity sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A== - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -pako@~1.0.5: - version "1.0.11" - resolved "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" - integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-asn1@^5.0.0, parse-asn1@^5.1.6: - version "5.1.6" - resolved "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" - integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== - dependencies: - asn1.js "^5.2.0" - browserify-aes "^1.0.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - -path-browserify@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" - integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -pbkdf2@^3.0.3: - version "3.1.2" - resolved "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" - integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pkg-dir@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz#a02d6aebe6ba133a928f74aec20bafdfe6b8e760" - integrity sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA== - dependencies: - find-up "^5.0.0" - -pngjs@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb" - integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw== - -postcss@^8.4.35: - version "8.4.35" - resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz#60997775689ce09011edf083a549cea44aabe2f7" - integrity sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA== - dependencies: - nanoid "^3.3.7" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== - -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== - -punycode@^2.1.0: - version "2.3.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - -qrcode@^1.5.3: - version "1.5.3" - resolved "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz#03afa80912c0dccf12bc93f615a535aad1066170" - integrity sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg== - dependencies: - dijkstrajs "^1.0.1" - encode-utf8 "^1.0.3" - pngjs "^5.0.0" - yargs "^15.3.1" - -qs@^6.11.2: - version "6.11.2" - resolved "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" - integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== - dependencies: - side-channel "^1.0.4" - -querystring-es3@^0.2.1: - version "0.2.1" - resolved "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA== - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: - version "2.1.0" - resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - -react-dom@^18.2.0: - version "18.2.0" - resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" - integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== - dependencies: - loose-envify "^1.1.0" - scheduler "^0.23.0" - -react-refresh@^0.14.0: - version "0.14.0" - resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e" - integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ== - -react-remove-scroll-bar@^2.3.4: - version "2.3.4" - resolved "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.4.tgz#53e272d7a5cb8242990c7f144c44d8bd8ab5afd9" - integrity sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A== - dependencies: - react-style-singleton "^2.2.1" - tslib "^2.0.0" - -react-remove-scroll@^2.5.7: - version "2.5.7" - resolved "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz#15a1fd038e8497f65a695bf26a4a57970cac1ccb" - integrity sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA== - dependencies: - react-remove-scroll-bar "^2.3.4" - react-style-singleton "^2.2.1" - tslib "^2.1.0" - use-callback-ref "^1.3.0" - use-sidecar "^1.1.2" - -react-style-singleton@^2.2.1: - version "2.2.1" - resolved "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz#f99e420492b2d8f34d38308ff660b60d0b1205b4" - integrity sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g== - dependencies: - get-nonce "^1.0.0" - invariant "^2.2.4" - tslib "^2.0.0" - -react@^18.2.0: - version "18.2.0" - resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" - integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== - dependencies: - loose-envify "^1.1.0" - -readable-stream@^3.5.0, readable-stream@^3.6.0, readable-stream@^3.6.2: - version "3.6.2" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -regenerator-runtime@^0.14.0: - version "0.14.1" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" - integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve@^1.17.0: - version "1.22.8" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -rollup@^4.2.0: - version "4.9.4" - resolved "https://registry.npmjs.org/rollup/-/rollup-4.9.4.tgz#37bc0c09ae6b4538a9c974f4d045bb64b2e7c27c" - integrity sha512-2ztU7pY/lrQyXSCnnoU4ICjT/tCG9cdH3/G25ERqE3Lst6vl2BCM5hL2Nw+sslAvAf+ccKsAq1SkKQALyqhR7g== - dependencies: - "@types/estree" "1.0.5" - optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.9.4" - "@rollup/rollup-android-arm64" "4.9.4" - "@rollup/rollup-darwin-arm64" "4.9.4" - "@rollup/rollup-darwin-x64" "4.9.4" - "@rollup/rollup-linux-arm-gnueabihf" "4.9.4" - "@rollup/rollup-linux-arm64-gnu" "4.9.4" - "@rollup/rollup-linux-arm64-musl" "4.9.4" - "@rollup/rollup-linux-riscv64-gnu" "4.9.4" - "@rollup/rollup-linux-x64-gnu" "4.9.4" - "@rollup/rollup-linux-x64-musl" "4.9.4" - "@rollup/rollup-win32-arm64-msvc" "4.9.4" - "@rollup/rollup-win32-ia32-msvc" "4.9.4" - "@rollup/rollup-win32-x64-msvc" "4.9.4" - fsevents "~2.3.2" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safer-buffer@^2.1.0: - version "2.1.2" - resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -scheduler@^0.23.0: - version "0.23.0" - resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" - integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== - dependencies: - loose-envify "^1.1.0" - -semver@^6.3.1: - version "6.3.1" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.5.4: - version "7.5.4" - resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== - dependencies: - lru-cache "^6.0.0" - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== - -set-function-length@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz#47cc5945f2c771e2cf261c6737cf9684a2a5e425" - integrity sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g== - dependencies: - define-data-property "^1.1.2" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.3" - gopd "^1.0.1" - has-property-descriptors "^1.0.1" - -setimmediate@^1.0.4: - version "1.0.5" - resolved "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== - -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -side-channel@^1.0.4: - version "1.0.5" - resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz#9a84546599b48909fb6af1211708d23b1946221b" - integrity sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - object-inspect "^1.13.1" - -siwe@^2.1.4: - version "2.1.4" - resolved "https://registry.npmjs.org/siwe/-/siwe-2.1.4.tgz#005a8be3e61224a86bd3457f60fdaab626f2d1d4" - integrity sha512-Dke1Qqa3mgiLm3vjqw/+SQ7dl8WV/Pfk3AlQBF94cBFydTYhztngqYrikzE3X5UTsJ6565dfVbQptszsuYZNYg== - dependencies: - "@spruceid/siwe-parser" "*" - "@stablelib/random" "^1.0.1" - uri-js "^4.4.1" - valid-url "^1.0.9" - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - -stream-browserify@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f" - integrity sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA== - dependencies: - inherits "~2.0.4" - readable-stream "^3.5.0" - -stream-http@^3.2.0: - version "3.2.0" - resolved "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz#1872dfcf24cb15752677e40e5c3f9cc1926028b5" - integrity sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A== - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.4" - readable-stream "^3.6.0" - xtend "^4.0.2" - -string-width@^4.1.0, string-width@^4.2.0: - version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string_decoder@^1.0.0, string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - -timers-browserify@^2.0.4: - version "2.0.12" - resolved "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" - integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== - dependencies: - setimmediate "^1.0.4" - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -ts-api-utils@^1.0.1: - version "1.0.3" - resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" - integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg== - -tslib@2.4.0: - version "2.4.0" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== - -tslib@^2.0.0, tslib@^2.1.0: - version "2.6.2" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" - integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== - -tty-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" - integrity sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw== - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -typescript@^5.2.2: - version "5.3.3" - resolved "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" - integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== - -update-browserslist-db@^1.0.13: - version "1.0.13" - resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" - integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - -uri-js@^4.2.2, uri-js@^4.4.1: - version "4.4.1" - resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -url@^0.11.0: - version "0.11.3" - resolved "https://registry.npmjs.org/url/-/url-0.11.3.tgz#6f495f4b935de40ce4a0a52faee8954244f3d3ad" - integrity sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw== - dependencies: - punycode "^1.4.1" - qs "^6.11.2" - -use-callback-ref@^1.3.0: - version "1.3.1" - resolved "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.1.tgz#9be64c3902cbd72b07fe55e56408ae3a26036fd0" - integrity sha512-Lg4Vx1XZQauB42Hw3kK7JM6yjVjgFmFC5/Ab797s79aARomD2nEErc4mCgM8EZrARLmmbWpi5DGCadmK50DcAQ== - dependencies: - tslib "^2.0.0" - -use-sidecar@^1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz#2f43126ba2d7d7e117aa5855e5d8f0276dfe73c2" - integrity sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw== - dependencies: - detect-node-es "^1.1.0" - tslib "^2.0.0" - -util-deprecate@^1.0.1: - version "1.0.2" - resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -util@^0.12.4, util@^0.12.5: - version "0.12.5" - resolved "https://registry.npmjs.org/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" - integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - which-typed-array "^1.1.2" - -valid-url@^1.0.9: - version "1.0.9" - resolved "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" - integrity sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA== - -viem@^2.0.3: - version "2.0.3" - resolved "https://registry.npmjs.org/viem/-/viem-2.0.3.tgz#c913048b95fb392d596e187bc3dfb2edd4446c77" - integrity sha512-9r+CMEA0zf8QCvCobTUX4vhP9x0t7wRjHbadfHDHw8ULjnzwoQc1Yc1pK99GtqK4hv5hKacDe78dibg80p/a+A== - dependencies: - "@adraffy/ens-normalize" "1.10.0" - "@noble/curves" "1.2.0" - "@noble/hashes" "1.3.2" - "@scure/bip32" "1.3.2" - "@scure/bip39" "1.2.1" - abitype "0.10.0" - isows "1.0.3" - ws "8.13.0" - -vite-plugin-node-polyfills@^0.21.0: - version "0.21.0" - resolved "https://registry.npmjs.org/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.21.0.tgz#5566b3a725d4bbc75f4f794b0467e4047c14a58c" - integrity sha512-Sk4DiKnmxN8E0vhgEhzLudfJQfaT8k4/gJ25xvUPG54KjLJ6HAmDKbr4rzDD/QWEY+Lwg80KE85fGYBQihEPQA== - dependencies: - "@rollup/plugin-inject" "^5.0.5" - node-stdlib-browser "^1.2.0" - -vite@^5.0.12: - version "5.1.2" - resolved "https://registry.npmjs.org/vite/-/vite-5.1.2.tgz#34e04d38db27ceebe6f0c9d053ea14d6496753d1" - integrity sha512-uwiFebQbTWRIGbCaTEBVAfKqgqKNKMJ2uPXsXeLIZxM8MVMjoS3j0cG8NrPxdDIadaWnPSjrkLWffLSC+uiP3Q== - dependencies: - esbuild "^0.19.3" - postcss "^8.4.35" - rollup "^4.2.0" - optionalDependencies: - fsevents "~2.3.3" - -vm-browserify@^1.0.1: - version "1.1.2" - resolved "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" - integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== - -which-module@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" - integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== - -which-typed-array@^1.1.14, which-typed-array@^1.1.2: - version "1.1.14" - resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz#1f78a111aee1e131ca66164d8bdc3ab062c95a06" - integrity sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg== - dependencies: - available-typed-arrays "^1.0.6" - call-bind "^1.0.5" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.1" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -ws@8.13.0: - version "8.13.0" - resolved "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" - integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== - -ws@8.5.0: - version "8.5.0" - resolved "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" - integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== - -xtend@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -y18n@^4.0.0: - version "4.0.3" - resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" - integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yargs-parser@^18.1.2: - version "18.1.3" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" - integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs@^15.3.1: - version "15.4.1" - resolved "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" - integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== - dependencies: - cliui "^6.0.0" - decamelize "^1.2.0" - find-up "^4.1.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^4.2.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^18.1.2" - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/examples/with-next-auth/.gitignore b/examples/with-next-auth/.gitignore index fd3dbb5..814c118 100644 --- a/examples/with-next-auth/.gitignore +++ b/examples/with-next-auth/.gitignore @@ -4,7 +4,7 @@ /node_modules /.pnp .pnp.js -.yarn/install-state.gz +.pnpm/install-state.gz # testing /coverage @@ -22,8 +22,8 @@ # debug npm-debug.log* -yarn-debug.log* -yarn-error.log* +pnpm-debug.log* +pnpm-error.log* # local env files .env*.local diff --git a/examples/with-next-auth/README.md b/examples/with-next-auth/README.md index 8c194aa..e6266d9 100644 --- a/examples/with-next-auth/README.md +++ b/examples/with-next-auth/README.md @@ -6,6 +6,6 @@ This example app shows how to use Sign In With Farcaster in a Next.js app with a ```sh $ git clone https://github.com/farcasterxyz/auth-monorepo.git && cd auth-monorepo/examples/with-next-auth -$ yarn install -$ yarn dev +$ pnpm install +$ pnpm dev ``` diff --git a/examples/with-next-auth/next.config.js b/examples/with-next-auth/next.config.js index a843cbe..91ef62f 100644 --- a/examples/with-next-auth/next.config.js +++ b/examples/with-next-auth/next.config.js @@ -1,6 +1,6 @@ /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, -} +}; -module.exports = nextConfig +module.exports = nextConfig; diff --git a/examples/with-next-auth/package.json b/examples/with-next-auth/package.json index 40bd6da..7e2ce98 100644 --- a/examples/with-next-auth/package.json +++ b/examples/with-next-auth/package.json @@ -9,19 +9,20 @@ "lint": "next lint" }, "dependencies": { - "@farcaster/auth-kit": "*", + "@farcaster/auth-kit": "workspace:*", "ethers": "^6.12.0", + "@tanstack/react-query": "^5.28.8", "next": "14.0.4", - "next-auth": "^4.24.5", + "next-auth": "^4.24.7", "react": "^18.2.0", "react-dom": "^18.2.0", - "viem": "^2.0.3" + "viem": "^2.9.0" }, "devDependencies": { - "@types/node": "^20", - "@types/react": "^18", - "@types/react-dom": "^18", - "eslint-config-next": "14.2.1", - "typescript": "^5" + "@types/node": "^20.11.30", + "@types/react": "^18.2.70", + "@types/react-dom": "^18.2.22", + "eslint-config-next": "14.1.0", + "typescript": "^5.4.3" } } diff --git a/examples/with-next-auth/pages/_document.tsx b/examples/with-next-auth/pages/_document.tsx index 54e8bf3..b2fff8b 100644 --- a/examples/with-next-auth/pages/_document.tsx +++ b/examples/with-next-auth/pages/_document.tsx @@ -1,4 +1,4 @@ -import { Html, Head, Main, NextScript } from 'next/document' +import { Html, Head, Main, NextScript } from "next/document"; export default function Document() { return ( @@ -9,5 +9,5 @@ export default function Document() { - ) + ); } diff --git a/examples/with-next-auth/pages/api/auth/[...nextauth].ts b/examples/with-next-auth/pages/api/auth/[...nextauth].ts index 0830d8c..0a8aefa 100644 --- a/examples/with-next-auth/pages/api/auth/[...nextauth].ts +++ b/examples/with-next-auth/pages/api/auth/[...nextauth].ts @@ -43,7 +43,7 @@ export default (req: NextApiRequest, res: NextApiResponse) => ethereum: viemConnector(), }); - const verifyResponse = await appClient.verifySignInMessage({ + const verifyResponse = await appClient.verifySiweMessage({ message: credentials?.message as string, signature: credentials?.signature as `0x${string}`, domain: "example.com", diff --git a/examples/with-next-auth/pages/index.tsx b/examples/with-next-auth/pages/index.tsx index bd3fa08..2f33362 100644 --- a/examples/with-next-auth/pages/index.tsx +++ b/examples/with-next-auth/pages/index.tsx @@ -2,20 +2,18 @@ import "@farcaster/auth-kit/styles.css"; import Head from "next/head"; import { useSession, signIn, signOut, getCsrfToken } from "next-auth/react"; -import { - SignInButton, - AuthKitProvider, - StatusAPIResponse, -} from "@farcaster/auth-kit"; +import { SignInButton, AuthKitProvider, createConfig, SignInReturnType } from "@farcaster/auth-kit"; import { useCallback, useState } from "react"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -const config = { +const config = createConfig({ relay: "https://relay.farcaster.xyz", rpcUrl: "https://mainnet.optimism.io", - siweUri: "http://example.com/login", - domain: "example.com", -}; + domain: 'example.com', + siweUri: 'https://example.com/login' +}); +const queryClient = new QueryClient(); export default function Home() { return ( <> @@ -23,9 +21,11 @@ export default function Home() { Farcaster AuthKit + NextAuth Demo
- - - + + + + +
); @@ -40,26 +40,23 @@ function Content() { return nonce; }, []); - const handleSuccess = useCallback( - (res: StatusAPIResponse) => { - signIn("credentials", { - message: res.message, - signature: res.signature, - name: res.username, - pfp: res.pfpUrl, - redirect: false, - }); - }, - [] - ); + const handleSuccess = useCallback((res: SignInReturnType) => { + signIn("credentials", { + message: res.message, + signature: res.signature, + name: res.username, + pfp: res.pfpUrl, + redirect: false, + }); + }, [signIn]); return (
setError(true)} + onSignIn={handleSuccess} + onSignInError={() => setError(true)} onSignOut={() => signOut()} /> {error &&
Unable to sign in at this time.
} @@ -68,10 +65,7 @@ function Content() {

@farcaster/auth-kit + NextAuth

This example app shows how to use{" "} - + Farcaster AuthKit {" "} and{" "} @@ -99,9 +93,9 @@ function Content() {
cd auth-monorepo/examples/with-next-auth &&
- yarn install && + pnpm install &&
- yarn dev + pnpm dev

@@ -116,19 +110,12 @@ function Profile() {

Signed in as {session.user?.name}

-

) : ( -

- Click the "Sign in with Farcaster"e; button above, then scan the QR code to - sign in. -

+

Click the "Sign in with Farcaster" button above, then scan the QR code to sign in.

); } diff --git a/examples/with-next-auth/turbo.json b/examples/with-next-auth/turbo.json new file mode 100644 index 0000000..a13eb18 --- /dev/null +++ b/examples/with-next-auth/turbo.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://turbo.build/schema.json", + "extends": ["//"], + "pipeline": { + "build": { + "dependsOn": ["@farcaster/auth-client#build"], + "inputs": ["src/**", "vite.config.ts", "tsconfig.json", "tsconfig.node.json", "next.config.js"], + "outputs": ["dist/**"] + } + } +} diff --git a/examples/with-next-auth/yarn.lock b/examples/with-next-auth/yarn.lock deleted file mode 100644 index 9f0b5ff..0000000 --- a/examples/with-next-auth/yarn.lock +++ /dev/null @@ -1,881 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@adraffy/ens-normalize@1.10.0": - version "1.10.0" - resolved "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" - integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== - -"@babel/runtime@^7.12.5", "@babel/runtime@^7.20.13": - version "7.23.7" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.7.tgz#dd7c88deeb218a0f8bd34d5db1aa242e0f203193" - integrity sha512-w06OXVOFso7LcbzMiDGt+3X7Rh7Ho8MmgPoWU3rarH+8upf+wSU/grlGbWzQyr3DkdN6ZeuMFjpdwW0Q+HxobA== - dependencies: - regenerator-runtime "^0.14.0" - -"@emotion/hash@^0.9.0": - version "0.9.1" - resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43" - integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ== - -"@farcaster/auth-client@^0.1.0": - version "0.1.0" - resolved "https://registry.npmjs.org/@farcaster/auth-client/-/auth-client-0.1.0.tgz#3f1608ee8398bc71e8da23a898aa721b36ce78d3" - integrity sha512-hWeUDwpyNNswclL82K5wt6sA0x0UjELGhLKSZK6JYvGAE6wNR6V8o1IBhZYIGASWHHxOGoJLZ1L1xRcvS3GbUQ== - dependencies: - ethers "^6.9.2" - neverthrow "^6.1.0" - siwe "^2.1.4" - -"@farcaster/auth-kit@^0.1.4": - version "0.1.4" - resolved "https://registry.npmjs.org/@farcaster/auth-kit/-/auth-kit-0.1.4.tgz#1b76195d018f3c8a3d01e45244e06e5527313f94" - integrity sha512-+SUdbme/NEcl4E2/ktwhvJMNgU5NHmaHUeCpgtvg8OIu52VvYEL6oChERjNJfVVlzvSub006E9KMC7Iao51tsQ== - dependencies: - "@farcaster/auth-client" "^0.1.0" - "@vanilla-extract/css" "^1.14.0" - qrcode "^1.5.3" - react-remove-scroll "^2.5.7" - -"@next/env@14.0.4": - version "14.0.4" - resolved "https://registry.npmjs.org/@next/env/-/env-14.0.4.tgz#d5cda0c4a862d70ae760e58c0cd96a8899a2e49a" - integrity sha512-irQnbMLbUNQpP1wcE5NstJtbuA/69kRfzBrpAD7Gsn8zm/CY6YQYc3HQBz8QPxwISG26tIm5afvvVbu508oBeQ== - -"@next/swc-darwin-arm64@14.0.4": - version "14.0.4" - resolved "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.4.tgz#27b1854c2cd04eb1d5e75081a1a792ad91526618" - integrity sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg== - -"@next/swc-darwin-x64@14.0.4": - version "14.0.4" - resolved "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.4.tgz#9940c449e757d0ee50bb9e792d2600cc08a3eb3b" - integrity sha512-IZQ3C7Bx0k2rYtrZZxKKiusMTM9WWcK5ajyhOZkYYTCc8xytmwSzR1skU7qLgVT/EY9xtXDG0WhY6fyujnI3rw== - -"@next/swc-linux-arm64-gnu@14.0.4": - version "14.0.4" - resolved "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.4.tgz#0eafd27c8587f68ace7b4fa80695711a8434de21" - integrity sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w== - -"@next/swc-linux-arm64-musl@14.0.4": - version "14.0.4" - resolved "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.4.tgz#2b0072adb213f36dada5394ea67d6e82069ae7dd" - integrity sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ== - -"@next/swc-linux-x64-gnu@14.0.4": - version "14.0.4" - resolved "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.4.tgz#68c67d20ebc8e3f6ced6ff23a4ba2a679dbcec32" - integrity sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A== - -"@next/swc-linux-x64-musl@14.0.4": - version "14.0.4" - resolved "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.4.tgz#67cd81b42fb2caf313f7992fcf6d978af55a1247" - integrity sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw== - -"@next/swc-win32-arm64-msvc@14.0.4": - version "14.0.4" - resolved "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.4.tgz#be06585906b195d755ceda28f33c633e1443f1a3" - integrity sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w== - -"@next/swc-win32-ia32-msvc@14.0.4": - version "14.0.4" - resolved "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.4.tgz#e76cabefa9f2d891599c3d85928475bd8d3f6600" - integrity sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg== - -"@next/swc-win32-x64-msvc@14.0.4": - version "14.0.4" - resolved "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.4.tgz#e74892f1a9ccf41d3bf5979ad6d3d77c07b9cba1" - integrity sha512-yEh2+R8qDlDCjxVpzOTEpBLQTEFAcP2A8fUFLaWNap9GitYKkKv1//y2S6XY6zsR4rCOPRpU7plYDR+az2n30A== - -"@noble/curves@1.2.0", "@noble/curves@~1.2.0": - version "1.2.0" - resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" - integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== - dependencies: - "@noble/hashes" "1.3.2" - -"@noble/hashes@1.3.2": - version "1.3.2" - resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" - integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== - -"@noble/hashes@^1.1.2", "@noble/hashes@~1.3.0", "@noble/hashes@~1.3.2": - version "1.3.3" - resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" - integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== - -"@panva/hkdf@^1.0.2": - version "1.1.1" - resolved "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.1.1.tgz#ab9cd8755d1976e72fc77a00f7655a64efe6cd5d" - integrity sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA== - -"@scure/base@~1.1.0", "@scure/base@~1.1.2": - version "1.1.5" - resolved "https://registry.npmjs.org/@scure/base/-/base-1.1.5.tgz#1d85d17269fe97694b9c592552dd9e5e33552157" - integrity sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ== - -"@scure/bip32@1.3.2": - version "1.3.2" - resolved "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.2.tgz#90e78c027d5e30f0b22c1f8d50ff12f3fb7559f8" - integrity sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA== - dependencies: - "@noble/curves" "~1.2.0" - "@noble/hashes" "~1.3.2" - "@scure/base" "~1.1.2" - -"@scure/bip39@1.2.1": - version "1.2.1" - resolved "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" - integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== - dependencies: - "@noble/hashes" "~1.3.0" - "@scure/base" "~1.1.0" - -"@spruceid/siwe-parser@*": - version "2.0.2" - resolved "https://registry.npmjs.org/@spruceid/siwe-parser/-/siwe-parser-2.0.2.tgz#964dbe9e5611fe95d39e21aa96e67407f610374f" - integrity sha512-9WuA0ios2537cWYu39MMeH0O2KdrMKgKlOBUTWRTXQjCYu5B+mHCA0JkCbFaJ/0EjxoVIcYCXIW/DoPEpw+PqA== - dependencies: - "@noble/hashes" "^1.1.2" - apg-js "^4.1.1" - uri-js "^4.4.1" - valid-url "^1.0.9" - -"@stablelib/binary@^1.0.1": - version "1.0.1" - resolved "https://registry.npmjs.org/@stablelib/binary/-/binary-1.0.1.tgz#c5900b94368baf00f811da5bdb1610963dfddf7f" - integrity sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q== - dependencies: - "@stablelib/int" "^1.0.1" - -"@stablelib/int@^1.0.1": - version "1.0.1" - resolved "https://registry.npmjs.org/@stablelib/int/-/int-1.0.1.tgz#75928cc25d59d73d75ae361f02128588c15fd008" - integrity sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w== - -"@stablelib/random@^1.0.1": - version "1.0.2" - resolved "https://registry.npmjs.org/@stablelib/random/-/random-1.0.2.tgz#2dece393636489bf7e19c51229dd7900eddf742c" - integrity sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w== - dependencies: - "@stablelib/binary" "^1.0.1" - "@stablelib/wipe" "^1.0.1" - -"@stablelib/wipe@^1.0.1": - version "1.0.1" - resolved "https://registry.npmjs.org/@stablelib/wipe/-/wipe-1.0.1.tgz#d21401f1d59ade56a62e139462a97f104ed19a36" - integrity sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg== - -"@swc/helpers@0.5.2": - version "0.5.2" - resolved "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz#85ea0c76450b61ad7d10a37050289eded783c27d" - integrity sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw== - dependencies: - tslib "^2.4.0" - -"@types/node@18.15.13": - version "18.15.13" - resolved "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" - integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== - -"@types/node@^20": - version "20.10.6" - resolved "https://registry.npmjs.org/@types/node/-/node-20.10.6.tgz#a3ec84c22965802bf763da55b2394424f22bfbb5" - integrity sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw== - dependencies: - undici-types "~5.26.4" - -"@types/prop-types@*": - version "15.7.11" - resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563" - integrity sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng== - -"@types/react-dom@^18": - version "18.2.18" - resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz#16946e6cd43971256d874bc3d0a72074bb8571dd" - integrity sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw== - dependencies: - "@types/react" "*" - -"@types/react@*", "@types/react@^18": - version "18.2.46" - resolved "https://registry.npmjs.org/@types/react/-/react-18.2.46.tgz#f04d6c528f8f136ea66333bc66abcae46e2680df" - integrity sha512-nNCvVBcZlvX4NU1nRRNV/mFl1nNRuTuslAJglQsq+8ldXe5Xv0Wd2f7WTE3jOxhLH2BFfiZGC6GCp+kHQbgG+w== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - -"@types/scheduler@*": - version "0.16.8" - resolved "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff" - integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A== - -"@vanilla-extract/css@^1.14.0": - version "1.14.0" - resolved "https://registry.npmjs.org/@vanilla-extract/css/-/css-1.14.0.tgz#45fab9c04d893e3e363cf2cde7559d21233b7f63" - integrity sha512-rYfm7JciWZ8PFzBM/HDiE2GLnKI3xJ6/vdmVJ5BSgcCZ5CxRlM9Cjqclni9lGzF3eMOijnUhCd/KV8TOzyzbMA== - dependencies: - "@emotion/hash" "^0.9.0" - "@vanilla-extract/private" "^1.0.3" - chalk "^4.1.1" - css-what "^6.1.0" - cssesc "^3.0.0" - csstype "^3.0.7" - deep-object-diff "^1.1.9" - deepmerge "^4.2.2" - media-query-parser "^2.0.2" - modern-ahocorasick "^1.0.0" - outdent "^0.8.0" - -"@vanilla-extract/private@^1.0.3": - version "1.0.3" - resolved "https://registry.npmjs.org/@vanilla-extract/private/-/private-1.0.3.tgz#7ec72bc2ff6fe51f9d650f962e8d1989b073690f" - integrity sha512-17kVyLq3ePTKOkveHxXuIJZtGYs+cSoev7BlP+Lf4916qfDhk/HBjvlYDe8egrea7LNPHKwSZJK/bzZC+Q6AwQ== - -abitype@0.10.0: - version "0.10.0" - resolved "https://registry.npmjs.org/abitype/-/abitype-0.10.0.tgz#d3504747cc81df2acaa6c460250ef7bc9219a77c" - integrity sha512-QvMHEUzgI9nPj9TWtUGnS2scas80/qaL5PBxGdwWhhvzqXfOph+IEiiiWrzuisu3U3JgDQVruW9oLbJoQ3oZ3A== - -aes-js@4.0.0-beta.5: - version "4.0.0-beta.5" - resolved "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" - integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -apg-js@^4.1.1: - version "4.3.0" - resolved "https://registry.npmjs.org/apg-js/-/apg-js-4.3.0.tgz#2c55d3f1aa6b90be5d3c6539f346cf2c726702c3" - integrity sha512-8U8MULS+JocCnm11bfrVS4zxtAcE3uOiCAI21SnjDrV9LNhMSGwTGGeko3QfyK1JLWwT7KebFqJMB2puzfdFMQ== - -busboy@1.6.0: - version "1.6.0" - resolved "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" - integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== - dependencies: - streamsearch "^1.1.0" - -camelcase@^5.0.0: - version "5.3.1" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -caniuse-lite@^1.0.30001406: - version "1.0.30001572" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001572.tgz#1ccf7dc92d2ee2f92ed3a54e11b7b4a3041acfa0" - integrity sha512-1Pbh5FLmn5y4+QhNyJE9j3/7dK44dGB83/ZMjv/qJk86TvDbjk0LosiZo0i0WB0Vx607qMX9jYrn1VLHCkN4rw== - -chalk@^4.1.1: - version "4.1.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -client-only@0.0.1: - version "0.0.1" - resolved "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" - integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== - -cliui@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" - integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^6.2.0" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -cookie@^0.5.0: - version "0.5.0" - resolved "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" - integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== - -css-what@^6.1.0: - version "6.1.0" - resolved "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" - integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== - -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - -csstype@^3.0.2, csstype@^3.0.7: - version "3.1.3" - resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" - integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== - -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== - -deep-object-diff@^1.1.9: - version "1.1.9" - resolved "https://registry.npmjs.org/deep-object-diff/-/deep-object-diff-1.1.9.tgz#6df7ef035ad6a0caa44479c536ed7b02570f4595" - integrity sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA== - -deepmerge@^4.2.2: - version "4.3.1" - resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" - integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== - -detect-node-es@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" - integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== - -dijkstrajs@^1.0.1: - version "1.0.3" - resolved "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz#4c8dbdea1f0f6478bff94d9c49c784d623e4fc23" - integrity sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -encode-utf8@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" - integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== - -ethers@^6.9.2: - version "6.9.2" - resolved "https://registry.npmjs.org/ethers/-/ethers-6.9.2.tgz#6f4632f62e2350fa8354ff28624027a175ef85a4" - integrity sha512-YpkrtILnMQz5jSEsJQRTpduaGT/CXuLnUIuOYzHA0v/7c8IX91m2J48wSKjzGL5L9J/Us3tLoUdb+OwE3U+FFQ== - dependencies: - "@adraffy/ens-normalize" "1.10.0" - "@noble/curves" "1.2.0" - "@noble/hashes" "1.3.2" - "@types/node" "18.15.13" - aes-js "4.0.0-beta.5" - tslib "2.4.0" - ws "8.5.0" - -find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -get-caller-file@^2.0.1: - version "2.0.5" - resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-nonce@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" - integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== - -glob-to-regexp@^0.4.1: - version "0.4.1" - resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" - integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== - -graceful-fs@^4.1.2, graceful-fs@^4.2.11: - version "4.2.11" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -isows@1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/isows/-/isows-1.0.3.tgz#93c1cf0575daf56e7120bab5c8c448b0809d0d74" - integrity sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg== - -jose@^4.11.4, jose@^4.15.4: - version "4.15.5" - resolved "https://registry.npmjs.org/jose/-/jose-4.15.5.tgz#6475d0f467ecd3c630a1b5dadd2735a7288df706" - integrity sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg== - -"js-tokens@^3.0.0 || ^4.0.0": - version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -loose-envify@^1.0.0, loose-envify@^1.1.0: - version "1.4.0" - resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -media-query-parser@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/media-query-parser/-/media-query-parser-2.0.2.tgz#ff79e56cee92615a304a1c2fa4f2bd056c0a1d29" - integrity sha512-1N4qp+jE0pL5Xv4uEcwVUhIkwdUO3S/9gML90nqKA7v7FcOS5vUtatfzok9S9U1EJU8dHWlcv95WLnKmmxZI9w== - dependencies: - "@babel/runtime" "^7.12.5" - -modern-ahocorasick@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/modern-ahocorasick/-/modern-ahocorasick-1.0.1.tgz#dec373444f51b5458ac05216a8ec376e126dd283" - integrity sha512-yoe+JbhTClckZ67b2itRtistFKf8yPYelHLc7e5xAwtNAXxM6wJTUx2C7QeVSJFDzKT7bCIFyBVybPMKvmB9AA== - -nanoid@^3.3.6: - version "3.3.7" - resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" - integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== - -neverthrow@^6.1.0: - version "6.1.0" - resolved "https://registry.npmjs.org/neverthrow/-/neverthrow-6.1.0.tgz#51a6e9ce2e06600045b3c1b37aecc536d267bf95" - integrity sha512-xNbNjp/6M5vUV+mststgneJN9eJeJCDSYSBTaf3vxgvcKooP+8L0ATFpM8DGfmH7UWKJeoa24Qi33tBP9Ya3zA== - -next-auth@^4.24.5: - version "4.24.5" - resolved "https://registry.npmjs.org/next-auth/-/next-auth-4.24.5.tgz#1fd1bfc0603c61fd2ba6fd81b976af690edbf07e" - integrity sha512-3RafV3XbfIKk6rF6GlLE4/KxjTcuMCifqrmD+98ejFq73SRoj2rmzoca8u764977lH/Q7jo6Xu6yM+Re1Mz/Og== - dependencies: - "@babel/runtime" "^7.20.13" - "@panva/hkdf" "^1.0.2" - cookie "^0.5.0" - jose "^4.11.4" - oauth "^0.9.15" - openid-client "^5.4.0" - preact "^10.6.3" - preact-render-to-string "^5.1.19" - uuid "^8.3.2" - -next@14.0.4: - version "14.0.4" - resolved "https://registry.npmjs.org/next/-/next-14.0.4.tgz#bf00b6f835b20d10a5057838fa2dfced1d0d84dc" - integrity sha512-qbwypnM7327SadwFtxXnQdGiKpkuhaRLE2uq62/nRul9cj9KhQ5LhHmlziTNqUidZotw/Q1I9OjirBROdUJNgA== - dependencies: - "@next/env" "14.0.4" - "@swc/helpers" "0.5.2" - busboy "1.6.0" - caniuse-lite "^1.0.30001406" - graceful-fs "^4.2.11" - postcss "8.4.31" - styled-jsx "5.1.1" - watchpack "2.4.0" - optionalDependencies: - "@next/swc-darwin-arm64" "14.0.4" - "@next/swc-darwin-x64" "14.0.4" - "@next/swc-linux-arm64-gnu" "14.0.4" - "@next/swc-linux-arm64-musl" "14.0.4" - "@next/swc-linux-x64-gnu" "14.0.4" - "@next/swc-linux-x64-musl" "14.0.4" - "@next/swc-win32-arm64-msvc" "14.0.4" - "@next/swc-win32-ia32-msvc" "14.0.4" - "@next/swc-win32-x64-msvc" "14.0.4" - -oauth@^0.9.15: - version "0.9.15" - resolved "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" - integrity sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA== - -object-hash@^2.2.0: - version "2.2.0" - resolved "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5" - integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== - -oidc-token-hash@^5.0.3: - version "5.0.3" - resolved "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz#9a229f0a1ce9d4fc89bcaee5478c97a889e7b7b6" - integrity sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw== - -openid-client@^5.4.0: - version "5.6.2" - resolved "https://registry.npmjs.org/openid-client/-/openid-client-5.6.2.tgz#ec6a9135d7eadfd4692d43c4f2fa0b1be3a0badf" - integrity sha512-TIVimoK/fAvpiISLcoGZyNJx2TOfd5AE6TXn58FFj6Y8qbU/jqky54Aws7sYKuCph1bLPWSRUa1r/Rd6K21bhg== - dependencies: - jose "^4.15.4" - lru-cache "^6.0.0" - object-hash "^2.2.0" - oidc-token-hash "^5.0.3" - -outdent@^0.8.0: - version "0.8.0" - resolved "https://registry.npmjs.org/outdent/-/outdent-0.8.0.tgz#2ebc3e77bf49912543f1008100ff8e7f44428eb0" - integrity sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A== - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -pngjs@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb" - integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw== - -postcss@8.4.31: - version "8.4.31" - resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" - integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== - dependencies: - nanoid "^3.3.6" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -preact-render-to-string@^5.1.19: - version "5.2.6" - resolved "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz#0ff0c86cd118d30affb825193f18e92bd59d0604" - integrity sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw== - dependencies: - pretty-format "^3.8.0" - -preact@^10.6.3: - version "10.19.3" - resolved "https://registry.npmjs.org/preact/-/preact-10.19.3.tgz#7a7107ed2598a60676c943709ea3efb8aaafa899" - integrity sha512-nHHTeFVBTHRGxJXKkKu5hT8C/YWBkPso4/Gad6xuj5dbptt9iF9NZr9pHbPhBrnT2klheu7mHTxTZ/LjwJiEiQ== - -pretty-format@^3.8.0: - version "3.8.0" - resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz#bfbed56d5e9a776645f4b1ff7aa1a3ac4fa3c385" - integrity sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew== - -punycode@^2.1.0: - version "2.3.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - -qrcode@^1.5.3: - version "1.5.3" - resolved "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz#03afa80912c0dccf12bc93f615a535aad1066170" - integrity sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg== - dependencies: - dijkstrajs "^1.0.1" - encode-utf8 "^1.0.3" - pngjs "^5.0.0" - yargs "^15.3.1" - -react-dom@^18.2.0: - version "18.2.0" - resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" - integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== - dependencies: - loose-envify "^1.1.0" - scheduler "^0.23.0" - -react-remove-scroll-bar@^2.3.4: - version "2.3.4" - resolved "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.4.tgz#53e272d7a5cb8242990c7f144c44d8bd8ab5afd9" - integrity sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A== - dependencies: - react-style-singleton "^2.2.1" - tslib "^2.0.0" - -react-remove-scroll@^2.5.7: - version "2.5.7" - resolved "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz#15a1fd038e8497f65a695bf26a4a57970cac1ccb" - integrity sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA== - dependencies: - react-remove-scroll-bar "^2.3.4" - react-style-singleton "^2.2.1" - tslib "^2.1.0" - use-callback-ref "^1.3.0" - use-sidecar "^1.1.2" - -react-style-singleton@^2.2.1: - version "2.2.1" - resolved "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz#f99e420492b2d8f34d38308ff660b60d0b1205b4" - integrity sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g== - dependencies: - get-nonce "^1.0.0" - invariant "^2.2.4" - tslib "^2.0.0" - -react@^18.2.0: - version "18.2.0" - resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" - integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== - dependencies: - loose-envify "^1.1.0" - -regenerator-runtime@^0.14.0: - version "0.14.1" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" - integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -scheduler@^0.23.0: - version "0.23.0" - resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" - integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== - dependencies: - loose-envify "^1.1.0" - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== - -siwe@^2.1.4: - version "2.1.4" - resolved "https://registry.npmjs.org/siwe/-/siwe-2.1.4.tgz#005a8be3e61224a86bd3457f60fdaab626f2d1d4" - integrity sha512-Dke1Qqa3mgiLm3vjqw/+SQ7dl8WV/Pfk3AlQBF94cBFydTYhztngqYrikzE3X5UTsJ6565dfVbQptszsuYZNYg== - dependencies: - "@spruceid/siwe-parser" "*" - "@stablelib/random" "^1.0.1" - uri-js "^4.4.1" - valid-url "^1.0.9" - -source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - -streamsearch@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" - integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== - -string-width@^4.1.0, string-width@^4.2.0: - version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -styled-jsx@5.1.1: - version "5.1.1" - resolved "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f" - integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw== - dependencies: - client-only "0.0.1" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -tslib@2.4.0: - version "2.4.0" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== - -tslib@^2.0.0, tslib@^2.1.0, tslib@^2.4.0: - version "2.6.2" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" - integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== - -typescript@^5: - version "5.3.3" - resolved "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" - integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -uri-js@^4.4.1: - version "4.4.1" - resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -use-callback-ref@^1.3.0: - version "1.3.1" - resolved "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.1.tgz#9be64c3902cbd72b07fe55e56408ae3a26036fd0" - integrity sha512-Lg4Vx1XZQauB42Hw3kK7JM6yjVjgFmFC5/Ab797s79aARomD2nEErc4mCgM8EZrARLmmbWpi5DGCadmK50DcAQ== - dependencies: - tslib "^2.0.0" - -use-sidecar@^1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz#2f43126ba2d7d7e117aa5855e5d8f0276dfe73c2" - integrity sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw== - dependencies: - detect-node-es "^1.1.0" - tslib "^2.0.0" - -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -valid-url@^1.0.9: - version "1.0.9" - resolved "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" - integrity sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA== - -viem@^2.0.3: - version "2.0.3" - resolved "https://registry.npmjs.org/viem/-/viem-2.0.3.tgz#c913048b95fb392d596e187bc3dfb2edd4446c77" - integrity sha512-9r+CMEA0zf8QCvCobTUX4vhP9x0t7wRjHbadfHDHw8ULjnzwoQc1Yc1pK99GtqK4hv5hKacDe78dibg80p/a+A== - dependencies: - "@adraffy/ens-normalize" "1.10.0" - "@noble/curves" "1.2.0" - "@noble/hashes" "1.3.2" - "@scure/bip32" "1.3.2" - "@scure/bip39" "1.2.1" - abitype "0.10.0" - isows "1.0.3" - ws "8.13.0" - -watchpack@2.4.0: - version "2.4.0" - resolved "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" - integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== - dependencies: - glob-to-regexp "^0.4.1" - graceful-fs "^4.1.2" - -which-module@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" - integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== - -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -ws@8.13.0: - version "8.13.0" - resolved "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" - integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== - -ws@8.5.0: - version "8.5.0" - resolved "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" - integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== - -y18n@^4.0.0: - version "4.0.3" - resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" - integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yargs-parser@^18.1.2: - version "18.1.3" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" - integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs@^15.3.1: - version "15.4.1" - resolved "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" - integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== - dependencies: - cliui "^6.0.0" - decamelize "^1.2.0" - find-up "^4.1.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^4.2.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^18.1.2" diff --git a/package.json b/package.json index 5d5a47f..1627670 100644 --- a/package.json +++ b/package.json @@ -3,52 +3,45 @@ "description": "A monorepo for Farcaster Auth", "version": "0.0.0", "private": true, - "packageManager": "yarn@1.22.19", - "workspaces": [ - "apps/*", - "examples/*", - "packages/*", - "test/*" - ], + "packageManager": "pnpm@8.10.5", "scripts": { - "build": "./node_modules/.bin/turbo run build", - "clean": "./node_modules/.bin/turbo run clean", - "dev": "./node_modules/.bin/turbo run dev --parallel", - "test": "./node_modules/.bin/turbo run test", - "test:ci": "./node_modules/.bin/turbo run test:ci -- --passWithNoTests", - "lint": "./node_modules/.bin/turbo run lint --parallel", - "lint:ci": "./node_modules/.bin/turbo run lint:ci --parallel", + "build": "turbo run build", + "clean": "turbo run clean", + "dev": "turbo run dev --parallel", + "test": "turbo run test", + "test:ci": "turbo run test:ci -- --passWithNoTests", + "lint": "turbo run lint --parallel", + "lint:ci": "turbo run lint:ci --parallel", "prepare": "husky install", "version-packages": "changeset version", - "release-packages": "yarn build && changeset publish", - "release-all": "yarn build && changeset publish && changeset tag" + "release-packages": "pnpm build && changeset publish", + "release-all": "pnpm build && changeset publish && changeset tag" }, "engines": { "npm": ">=8.0.0", "node": ">=18.7" }, "lint-staged": { - "*.ts": [ - "biome check" - ] + "*.ts": ["biome check"] }, "devDependencies": { - "@biomejs/biome": "~1.1.0", + "@biomejs/biome": "~1.1.2", "@changesets/changelog-git": "^0.2.0", "@changesets/cli": "^2.27.1", - "@swc/cli": "^0.1.63", - "@swc/core": "^1.3.100", - "@swc/jest": "^0.2.29", - "@types/jest": "^29.5.11", - "@types/node": "^20.10.3", + "@swc/cli": "^0.1.65", + "@swc/core": "^1.4.8", + "@swc/jest": "^0.2.36", + "@types/jest": "^29.5.12", + "@types/node": "^20.11.30", "husky": "^8.0.3", "jest": "^29.7.0", - "lint-staged": "^15.2.0", + "lint-staged": "^15.2.2", + "publint": "^0.2.7", "rimraf": "^5.0.5", - "semver": "^7.5.4", - "ts-node": "^10.9.1", - "tsup": "^8.0.1", - "turbo": "^1.11.0", - "typescript": "^5.3.3" + "semver": "^7.6.0", + "ts-node": "^10.9.2", + "tsup": "^8.0.2", + "turbo": "^1.13.0", + "typescript": "^5.4.3" } } diff --git a/packages/auth-client/biome.json b/packages/auth-client/biome.json deleted file mode 100644 index 2e5466e..0000000 --- a/packages/auth-client/biome.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "../../node_modules/@biomejs/biome/configuration_schema.json", - "organizeImports": { - "enabled": false - }, - "formatter": { - "enabled": true, - "indentSize": 2, - "indentStyle": "space", - "lineWidth": 120 - }, - "linter": { - "enabled": true, - "rules": { - "recommended": true, - "complexity": { - "useLiteralKeys": "off" - } - } - } -} diff --git a/packages/auth-client/package.json b/packages/auth-client/package.json deleted file mode 100644 index d844a21..0000000 --- a/packages/auth-client/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "@farcaster/auth-client", - "version": "0.1.1", - "main": "./dist/index.js", - "module": "./dist/index.mjs", - "types": "./dist/index.d.ts", - "exports": { - ".": { - "require": "./dist/index.js", - "import": "./dist/index.mjs", - "types": "./dist/index.d.ts" - } - }, - "files": [ - "dist" - ], - "license": "MIT", - "scripts": { - "build": "tsup --config tsup.config.ts", - "clean": "rimraf ./dist", - "lint": "biome format src/ scripts/ --write && biome check src/ scripts/ --apply", - "lint:ci": "biome ci src/ scripts/", - "test": "jest", - "test:ci": "ENVIRONMENT=test jest --ci --forceExit --coverage", - "console": "yarn ts-node ./scripts/console.ts", - "prepublishOnly": "yarn run build" - }, - "dependencies": { - "neverthrow": "^6.1.0", - "siwe": "^2.1.4" - }, - "peerDependencies": { - "ethers": "5.x || 6.x", - "viem": "1.x || 2.x" - }, - "devDependencies": { - "ethers": "^6.12.0", - "viem": "^1.19.11" - } -} diff --git a/packages/auth-client/src/actions/app/createChannel.ts b/packages/auth-client/src/actions/app/createChannel.ts deleted file mode 100644 index 5f02626..0000000 --- a/packages/auth-client/src/actions/app/createChannel.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { AsyncUnwrapped, unwrap } from "../../errors"; -import { Client } from "../../clients/createClient"; -import { HttpResponse, post } from "../../clients/transports/http"; - -export type CreateChannelArgs = CreateChannelRequest; -export type CreateChannelResponse = AsyncUnwrapped>; - -interface CreateChannelRequest { - siweUri: string; - domain: string; - nonce?: string; - notBefore?: string; - expirationTime?: string; - requestId?: string; - redirectUrl?: string; -} - -export interface CreateChannelAPIResponse { - channelToken: string; - url: string; - nonce: string; -} - -const path = "channel"; - -export const createChannel = async (client: Client, { ...request }: CreateChannelArgs): CreateChannelResponse => { - const response = await post(client, path, request); - return unwrap(response); -}; diff --git a/packages/auth-client/src/actions/app/index.ts b/packages/auth-client/src/actions/app/index.ts deleted file mode 100644 index d2a341b..0000000 --- a/packages/auth-client/src/actions/app/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./createChannel"; -export * from "./status"; -export * from "./verifySignInMessage"; -export * from "./watchStatus"; diff --git a/packages/auth-client/src/actions/app/status.ts b/packages/auth-client/src/actions/app/status.ts deleted file mode 100644 index af387a9..0000000 --- a/packages/auth-client/src/actions/app/status.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { AsyncUnwrapped, unwrap } from "../../errors"; -import { Client } from "../../clients/createClient"; -import { get, HttpResponse } from "../../clients/transports/http"; -import type { Hex } from "viem"; - -export interface StatusArgs { - channelToken: string; -} - -export type StatusResponse = AsyncUnwrapped>; - -export interface StatusAPIResponse { - state: "pending" | "completed"; - nonce: string; - url: string; - message?: string; - signature?: `0x${string}`; - fid?: number; - username?: string; - bio?: string; - displayName?: string; - pfpUrl?: string; - verifications?: Hex[]; - custody?: Hex; -} - -const path = "channel/status"; - -export const status = async (client: Client, { channelToken }: StatusArgs): StatusResponse => { - const response = await get(client, path, { - authToken: channelToken, - }); - return unwrap(response); -}; diff --git a/packages/auth-client/src/actions/app/verifySignInMessage.ts b/packages/auth-client/src/actions/app/verifySignInMessage.ts deleted file mode 100644 index 165474c..0000000 --- a/packages/auth-client/src/actions/app/verifySignInMessage.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { SiweMessage } from "siwe"; -import { Client } from "../../clients/createClient"; -import { VerifyResponse, verify } from "../../messages/verify"; -import { Unwrapped, unwrap } from "../../errors"; -import type { Provider } from "ethers"; - -export interface VerifySignInMessageArgs { - nonce: string; - domain: string; - message: string | Partial; - signature: `0x${string}`; -} - -export type VerifySignInMessageResponse = Promise>; - -export const verifySignInMessage = async ( - client: Client, - { nonce, domain, message, signature }: VerifySignInMessageArgs, - provider?: Provider, -): VerifySignInMessageResponse => { - const result = await verify(nonce, domain, message, signature, { - getFid: client.ethereum.getFid, - provider, - }); - return unwrap(result); -}; diff --git a/packages/auth-client/src/actions/app/watchStatus.ts b/packages/auth-client/src/actions/app/watchStatus.ts deleted file mode 100644 index 2f54b07..0000000 --- a/packages/auth-client/src/actions/app/watchStatus.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { AsyncUnwrapped, unwrap } from "../../errors"; -import { Client } from "../../clients/createClient"; -import { poll, HttpResponse } from "../../clients/transports/http"; -import { StatusAPIResponse } from "./status"; - -export interface WatchStatusArgs { - channelToken: string; - timeout?: number; - interval?: number; - onResponse?: (response: HttpResponse) => void; -} - -export type WatchStatusResponse = AsyncUnwrapped>; - -const path = "channel/status"; - -const voidCallback = () => {}; - -export const watchStatus = async (client: Client, args: WatchStatusArgs): WatchStatusResponse => { - const result = await poll( - client, - path, - { - timeout: args?.timeout ?? 300_000, - interval: args?.interval ?? 1000, - onResponse: args?.onResponse ?? voidCallback, - }, - { authToken: args.channelToken }, - ); - return unwrap(result); -}; diff --git a/packages/auth-client/src/actions/auth/authenticate.ts b/packages/auth-client/src/actions/auth/authenticate.ts deleted file mode 100644 index 5ccfcf5..0000000 --- a/packages/auth-client/src/actions/auth/authenticate.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { StatusAPIResponse } from "../app/status"; -import { post, HttpResponse } from "../../clients/transports/http"; -import { Client } from "../../clients/createClient"; -import { AsyncUnwrapped, unwrap } from "../../errors"; - -export interface AuthenticateArgs extends AuthenticateRequest { - authKey: string; - channelToken: string; -} - -export type AuthenticateResponse = AsyncUnwrapped>; - -interface AuthenticateRequest { - message: string; - signature: `0x${string}`; - fid: number; - username?: string; - bio?: string; - displayName?: string; - pfpUrl?: string; -} - -export type AuthenticateAPIResponse = StatusAPIResponse; - -const path = "channel/authenticate"; - -export const authenticate = async ( - client: Client, - { channelToken, authKey, ...request }: AuthenticateArgs, -): AuthenticateResponse => { - const result = await post(client, path, request, { - authToken: channelToken, - headers: { - "X-Farcaster-Auth-Relay-Key": authKey, - }, - }); - return unwrap(result); -}; diff --git a/packages/auth-client/src/actions/auth/buildSignInMessage.test.ts b/packages/auth-client/src/actions/auth/buildSignInMessage.test.ts deleted file mode 100644 index 47a7da7..0000000 --- a/packages/auth-client/src/actions/auth/buildSignInMessage.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { createWalletClient } from "../../clients/createWalletClient"; -import { viemConnector } from "../../clients/ethereum/viemConnector"; - -describe("buildSignInMessage", () => { - const client = createWalletClient({ - relay: "https://relay.farcaster.xyz", - ethereum: viemConnector(), - }); - - test("builds Siwe message from provided parameters", async () => { - const { siweMessage, message } = client.buildSignInMessage({ - address: "0x63C378DDC446DFf1d831B9B96F7d338FE6bd4231", - uri: "https://example.com/login", - domain: "example.com", - nonce: "12345678", - fid: 1, - resources: ["https://example.com/resource"], - }); - - expect(siweMessage).toMatchObject({ - address: "0x63C378DDC446DFf1d831B9B96F7d338FE6bd4231", - statement: "Farcaster Auth", - chainId: 10, - uri: "https://example.com/login", - domain: "example.com", - version: "1", - nonce: "12345678", - resources: ["farcaster://fid/1", "https://example.com/resource"], - }); - expect(message).toBe(siweMessage.toMessage()); - }); -}); diff --git a/packages/auth-client/src/actions/auth/buildSignInMessage.ts b/packages/auth-client/src/actions/auth/buildSignInMessage.ts deleted file mode 100644 index 97550b1..0000000 --- a/packages/auth-client/src/actions/auth/buildSignInMessage.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Client } from "clients/createClient"; -import { build, BuildResponse, SignInMessageParams } from "../../messages/build"; -import { Unwrapped, unwrap } from "../../errors"; - -export type BuildSignInMessageArgs = SignInMessageParams; -export type BuildSignInMessageResponse = Unwrapped; - -export const buildSignInMessage = (_client: Client, args: BuildSignInMessageArgs): BuildSignInMessageResponse => { - return unwrap(build(args)); -}; diff --git a/packages/auth-client/src/actions/auth/index.ts b/packages/auth-client/src/actions/auth/index.ts deleted file mode 100644 index 257c859..0000000 --- a/packages/auth-client/src/actions/auth/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./authenticate"; -export * from "./buildSignInMessage"; -export * from "./parseSignInURI"; diff --git a/packages/auth-client/src/actions/auth/parseSignInURI.ts b/packages/auth-client/src/actions/auth/parseSignInURI.ts deleted file mode 100644 index 9aecf9c..0000000 --- a/packages/auth-client/src/actions/auth/parseSignInURI.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Unwrapped, unwrap } from "../../errors"; -import { Client } from "../../clients/createClient"; -import { parseSignInURI as parse, ParsedSignInURI } from "../../messages/parseSignInURI"; - -export interface ParseSignInURIArgs { - uri: string; -} -export type ParseSignInURIResponse = Unwrapped; - -export const parseSignInURI = (_client: Client, { uri }: ParseSignInURIArgs): ParseSignInURIResponse => { - return unwrap(parse(uri)); -}; diff --git a/packages/auth-client/src/actions/index.ts b/packages/auth-client/src/actions/index.ts deleted file mode 100644 index 2002587..0000000 --- a/packages/auth-client/src/actions/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./app"; -export * from "./auth"; diff --git a/packages/auth-client/src/clients/createAppClient.ts b/packages/auth-client/src/clients/createAppClient.ts deleted file mode 100644 index 2f16e74..0000000 --- a/packages/auth-client/src/clients/createAppClient.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { createChannel, CreateChannelArgs, CreateChannelResponse } from "../actions/app/createChannel"; -import { status, StatusArgs, StatusResponse } from "../actions/app/status"; -import { watchStatus, WatchStatusArgs, WatchStatusResponse } from "../actions/app/watchStatus"; -import { - verifySignInMessage, - VerifySignInMessageArgs, - VerifySignInMessageResponse, -} from "../actions/app/verifySignInMessage"; -import { Client, CreateClientArgs, createClient } from "./createClient"; -import type { Provider } from "ethers"; - -export { Provider }; - -export interface AppClient extends Client { - createChannel: (args: CreateChannelArgs) => CreateChannelResponse; - status: (args: StatusArgs) => StatusResponse; - watchStatus: (args: WatchStatusArgs) => WatchStatusResponse; - verifySignInMessage: (args: VerifySignInMessageArgs) => VerifySignInMessageResponse; -} - -export const createAppClient = (config: CreateClientArgs, provider?: Provider): AppClient => { - const client = createClient(config); - return { - ...client, - createChannel: (args: CreateChannelArgs) => createChannel(client, args), - status: (args: StatusArgs) => status(client, args), - watchStatus: (args: WatchStatusArgs) => watchStatus(client, args), - verifySignInMessage: (args: VerifySignInMessageArgs) => verifySignInMessage(client, args, provider), - }; -}; diff --git a/packages/auth-client/src/clients/createWalletClient.ts b/packages/auth-client/src/clients/createWalletClient.ts deleted file mode 100644 index f480c7a..0000000 --- a/packages/auth-client/src/clients/createWalletClient.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { authenticate, AuthenticateArgs, AuthenticateResponse } from "../actions/auth/authenticate"; -import { parseSignInURI, ParseSignInURIArgs, ParseSignInURIResponse } from "../actions/auth/parseSignInURI"; -import { - buildSignInMessage, - BuildSignInMessageArgs, - BuildSignInMessageResponse, -} from "../actions/auth/buildSignInMessage"; -import { Client, CreateClientArgs, createClient } from "./createClient"; - -export interface WalletClient extends Client { - authenticate: (args: AuthenticateArgs) => AuthenticateResponse; - buildSignInMessage: (args: BuildSignInMessageArgs) => BuildSignInMessageResponse; - parseSignInURI: (args: ParseSignInURIArgs) => ParseSignInURIResponse; -} - -export const createWalletClient = (config: CreateClientArgs): WalletClient => { - const client = createClient(config); - return { - ...client, - authenticate: (args: AuthenticateArgs) => authenticate(client, args), - buildSignInMessage: (args: BuildSignInMessageArgs) => buildSignInMessage(client, args), - parseSignInURI: (args: ParseSignInURIArgs) => parseSignInURI(client, args), - }; -}; diff --git a/packages/auth-client/src/clients/ethereum/connector.ts b/packages/auth-client/src/clients/ethereum/connector.ts deleted file mode 100644 index 7cea4fe..0000000 --- a/packages/auth-client/src/clients/ethereum/connector.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Hex } from "viem"; - -export interface EthereumConnector { - getFid: (custody: Hex) => Promise; -} diff --git a/packages/auth-client/src/clients/ethereum/index.ts b/packages/auth-client/src/clients/ethereum/index.ts deleted file mode 100644 index 8570783..0000000 --- a/packages/auth-client/src/clients/ethereum/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./viemConnector"; diff --git a/packages/auth-client/src/clients/index.ts b/packages/auth-client/src/clients/index.ts deleted file mode 100644 index 4e683ad..0000000 --- a/packages/auth-client/src/clients/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from "./createAppClient"; -export * from "./createWalletClient"; -export * from "./createClient"; -export * from "./ethereum"; -export * from "./transports"; diff --git a/packages/auth-client/src/clients/transports/http.ts b/packages/auth-client/src/clients/transports/http.ts deleted file mode 100644 index 3d78f77..0000000 --- a/packages/auth-client/src/clients/transports/http.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { ResultAsync, ok, err } from "neverthrow"; -import { Client } from "../createClient"; -import { AuthClientError, AuthClientAsyncResult } from "../../errors"; - -export interface HttpOpts { - authToken?: string; - headers?: Record; -} - -export interface PollOpts { - interval?: number; - timeout?: number; - successCode?: number; - onResponse?: (response: HttpResponse) => void; -} - -export interface HttpResponse { - response: Response; - data: ResponseDataType; -} - -export type AsyncHttpResponse = Promise>; - -const defaultPollOpts = { - interval: 1000, - timeout: 10000, - successCode: 200, - onResponse: () => {}, -}; - -export const get = async ( - client: Client, - path: string, - opts?: HttpOpts, -): AuthClientAsyncResult> => { - return ResultAsync.fromPromise( - fetch(getURI(client, path), { - headers: getHeaders(opts), - }), - (e) => { - return new AuthClientError("unknown", e as Error); - }, - ).andThen((response) => { - return ResultAsync.fromPromise(response.json(), (e) => { - return new AuthClientError("unknown", e as Error); - }).andThen((data) => { - return ok({ response, data }); - }); - }); -}; - -export const post = async ( - client: Client, - path: string, - json: BodyType, - opts?: HttpOpts, -): AuthClientAsyncResult> => { - return ResultAsync.fromPromise( - fetch(getURI(client, path), { - method: "POST", - body: JSON.stringify(json), - headers: getHeaders(opts), - }), - (e) => { - return new AuthClientError("unknown", e as Error); - }, - ).andThen((response) => { - return ResultAsync.fromPromise(response.json(), (e) => { - return new AuthClientError("unknown", e as Error); - }).andThen((data) => { - return ok({ response, data }); - }); - }); -}; - -export const poll = async ( - client: Client, - path: string, - pollOpts?: PollOpts, - opts?: HttpOpts, -): AuthClientAsyncResult> => { - const { timeout, interval, successCode, onResponse } = { - ...defaultPollOpts, - ...pollOpts, - }; - - const deadline = Date.now() + timeout; - - while (Date.now() < deadline) { - const res = await get(client, path, opts); - if (res.isOk()) { - const { response } = res.value; - if (response.status === successCode) { - return ok(res.value); - } - onResponse(res.value); - await new Promise((resolve) => setTimeout(resolve, interval)); - } else { - return err(res.error); - } - } - return err(new AuthClientError("unavailable", `Polling timed out after ${timeout}ms`)); -}; - -const getURI = (client: Client, path: string) => { - return `${client.config.relay}/${client.config.version}/${path}`; -}; - -const getHeaders = (opts?: HttpOpts) => { - const headers = { - ...opts?.headers, - }; - if (opts?.authToken) { - headers["Authorization"] = `Bearer ${opts.authToken}`; - } - return { ...headers, "Content-Type": "application/json" }; -}; diff --git a/packages/auth-client/src/clients/transports/index.ts b/packages/auth-client/src/clients/transports/index.ts deleted file mode 100644 index b4f0c19..0000000 --- a/packages/auth-client/src/clients/transports/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./http"; diff --git a/packages/auth-client/src/index.ts b/packages/auth-client/src/index.ts deleted file mode 100644 index 9e5c41b..0000000 --- a/packages/auth-client/src/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { generateNonce } from "siwe"; - -export * from "./errors"; -export * from "./actions"; -export * from "./clients"; diff --git a/packages/auth-client/src/messages/build.test.ts b/packages/auth-client/src/messages/build.test.ts deleted file mode 100644 index 64fff19..0000000 --- a/packages/auth-client/src/messages/build.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { build } from "./build"; - -const siweParams = { - domain: "example.com", - address: "0x63C378DDC446DFf1d831B9B96F7d338FE6bd4231", - uri: "https://example.com/login", - version: "1", - nonce: "12345678", - issuedAt: "2023-10-01T00:00:00.000Z", -}; - -describe("build", () => { - test("adds auth-specific parameters", () => { - const result = build({ - ...siweParams, - fid: 5678, - }); - expect(result.isOk()).toBe(true); - const { siweMessage, message } = result._unsafeUnwrap(); - expect(siweMessage).toMatchObject({ - ...siweParams, - statement: "Farcaster Auth", - chainId: 10, - resources: ["farcaster://fid/5678"], - }); - expect(message).toEqual(siweMessage.toMessage()); - }); - - test("handles additional resources", () => { - const result = build({ - ...siweParams, - fid: 5678, - resources: ["https://example.com/resource"], - }); - expect(result.isOk()).toBe(true); - const { siweMessage } = result._unsafeUnwrap(); - expect(siweMessage).toMatchObject({ - ...siweParams, - statement: "Farcaster Auth", - chainId: 10, - resources: ["farcaster://fid/5678", "https://example.com/resource"], - }); - }); -}); diff --git a/packages/auth-client/src/messages/build.ts b/packages/auth-client/src/messages/build.ts deleted file mode 100644 index 67b65e8..0000000 --- a/packages/auth-client/src/messages/build.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { SiweMessage } from "siwe"; -import { err, ok } from "neverthrow"; -import { AuthClientResult } from "../errors"; -import { validate } from "./validate"; -import { parseSignInURI } from "./parseSignInURI"; -import { STATEMENT, CHAIN_ID } from "./constants"; - -export type FarcasterResourceParams = { - fid: number; -}; -export type SignInMessageParams = Partial & FarcasterResourceParams; -export interface BuildResponse { - siweMessage: SiweMessage; - message: string; -} - -export const build = (params: SignInMessageParams): AuthClientResult => { - const { fid, ...siweParams } = params; - const resources = siweParams.resources ?? []; - siweParams.version = "1"; - siweParams.statement = STATEMENT; - siweParams.chainId = CHAIN_ID; - siweParams.resources = [buildFidResource(fid), ...resources]; - const valid = validate(siweParams); - if (valid.isErr()) return err(valid.error); - else { - const siweMessage = valid.value; - return ok({ siweMessage, message: siweMessage.toMessage() }); - } -}; - -export const buildFromSignInURI = (signInUri: string, fid: number): AuthClientResult => { - return parseSignInURI(signInUri).andThen(({ params }) => build({ ...params, fid })); -}; - -const buildFidResource = (fid: number): string => { - return `farcaster://fid/${fid}`; -}; diff --git a/packages/auth-client/src/messages/index.ts b/packages/auth-client/src/messages/index.ts deleted file mode 100644 index a8e3f37..0000000 --- a/packages/auth-client/src/messages/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from "./build"; -export * from "./constants"; -export * from "./parseSignInURI"; -export * from "./validate"; -export * from "./verify"; diff --git a/packages/auth-client/src/messages/parseSignInURI.test.ts b/packages/auth-client/src/messages/parseSignInURI.test.ts deleted file mode 100644 index 0482cb9..0000000 --- a/packages/auth-client/src/messages/parseSignInURI.test.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { parseSignInURI } from "./parseSignInURI"; - -describe("parseSignInUri", () => { - test("parses Sign in With Farcaster URI into message params", () => { - const signInUri = - "https://warpcast.com/~/sign-in-with-farcaster?channelToken=76be6229-bdf7-4ad2-930a-540fb2de1e08&nonce=ESsxs6MaFio7OvqWb&siweUri=https%3A%2F%2Fexample.com%2Flogin&domain=example.com&redirectUrl=https%3A%2F%2Fexample.com"; - const result = parseSignInURI(signInUri); - expect(result._unsafeUnwrap()).toStrictEqual({ - channelToken: "76be6229-bdf7-4ad2-930a-540fb2de1e08", - params: { - domain: "example.com", - uri: "https://example.com/login", - nonce: "ESsxs6MaFio7OvqWb", - redirectUrl: "https://example.com", - }, - }); - }); -}); diff --git a/packages/auth-client/src/messages/parseSignInURI.ts b/packages/auth-client/src/messages/parseSignInURI.ts deleted file mode 100644 index 25b4426..0000000 --- a/packages/auth-client/src/messages/parseSignInURI.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { err, ok } from "neverthrow"; -import { AuthClientError, AuthClientResult } from "../errors"; -import { SignInMessageParams } from "./build"; - -export interface ParsedSignInURI { - channelToken: string; - params: Partial & { redirectUrl?: string }; -} - -export const parseSignInURI = (signInUri: string): AuthClientResult => { - const url = new URL(signInUri); - const searchParams = Object.fromEntries(url.searchParams.entries()); - const { channelToken, ...params } = searchParams; - if (!channelToken) { - return err(validationFail("No channel token provided")); - } - if (!params["nonce"]) { - return err(validationFail("No nonce provided")); - } - if (!params["siweUri"]) { - return err(validationFail("No SIWE URI provided")); - } - if (!params["domain"]) { - return err(validationFail("No domain provided")); - } - const { siweUri, ...siweParams } = params; - return ok({ channelToken, params: { uri: siweUri, ...siweParams } }); -}; - -const validationFail = (message: string): AuthClientError => { - return new AuthClientError("bad_request.validation_failure", message); -}; diff --git a/packages/auth-client/src/messages/validate.test.ts b/packages/auth-client/src/messages/validate.test.ts deleted file mode 100644 index 20f4081..0000000 --- a/packages/auth-client/src/messages/validate.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { validate } from "./validate"; -import { AuthClientError } from "../errors"; - -const siweParams = { - domain: "example.com", - address: "0x63C378DDC446DFf1d831B9B96F7d338FE6bd4231", - uri: "https://example.com/login", - version: "1", - nonce: "12345678", - issuedAt: "2023-10-01T00:00:00.000Z", -}; - -const authParams = { - ...siweParams, - statement: "Farcaster Auth", - chainId: 10, - resources: ["farcaster://fid/1234"], -}; - -describe("validate", () => { - test("default parameters are valid", () => { - const result = validate(authParams); - expect(result.isOk()).toBe(true); - }); - - test("propagates SIWE message errors", () => { - const result = validate({ - ...authParams, - address: "Invalid address", - }); - expect(result.isErr()).toBe(true); - expect(result._unsafeUnwrapErr().errCode).toEqual("bad_request.validation_failure"); - expect(result._unsafeUnwrapErr().message).toMatch("invalid address"); - }); - - test("message must contain 'Farcaster Auth'", () => { - const result = validate({ - ...authParams, - statement: "Invalid statement", - }); - expect(result.isErr()).toBe(true); - expect(result._unsafeUnwrapErr()).toEqual( - new AuthClientError("bad_request.validation_failure", "Statement must be 'Farcaster Auth'"), - ); - }); - - test("statement allows 'Farcaster Connect'", () => { - const result = validate({ - ...authParams, - statement: "Farcaster Connect", - }); - expect(result.isOk()).toBe(true); - }); - - test("message must include chainId 10", () => { - const result = validate({ - ...authParams, - chainId: 1, - }); - expect(result.isErr()).toBe(true); - expect(result._unsafeUnwrapErr()).toEqual( - new AuthClientError("bad_request.validation_failure", "Chain ID must be 10"), - ); - }); - - test("message must include FID resource", () => { - const result = validate({ - ...authParams, - resources: [], - }); - expect(result.isErr()).toBe(true); - expect(result._unsafeUnwrapErr()).toEqual( - new AuthClientError("bad_request.validation_failure", "No fid resource provided"), - ); - }); - - test("message must only include one FID resource", () => { - const result = validate({ - ...authParams, - resources: ["farcaster://fid/1", "farcaster://fid/2"], - }); - expect(result.isErr()).toBe(true); - expect(result._unsafeUnwrapErr()).toEqual( - new AuthClientError("bad_request.validation_failure", "Multiple fid resources provided"), - ); - }); -}); diff --git a/packages/auth-client/src/messages/validate.ts b/packages/auth-client/src/messages/validate.ts deleted file mode 100644 index 7ada641..0000000 --- a/packages/auth-client/src/messages/validate.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { SiweMessage } from "siwe"; -import { Result, err, ok } from "neverthrow"; -import { AuthClientResult, AuthClientError } from "../errors"; -import { STATEMENT, CHAIN_ID } from "./constants"; -import { FarcasterResourceParams } from "./build"; - -const FID_URI_REGEX = /^farcaster:\/\/fid\/([1-9]\d*)\/?$/; - -export const validate = (params: string | Partial): AuthClientResult => { - return Result.fromThrowable( - // SiweMessage validates itself when constructed - () => new SiweMessage(params), - // If construction time validation fails, propagate the error - (e) => new AuthClientError("bad_request.validation_failure", e as Error), - )() - .andThen(validateStatement) - .andThen(validateChainId) - .andThen(validateResources); -}; - -export const parseResources = (message: SiweMessage): AuthClientResult => { - const fid = parseFid(message); - if (fid.isErr()) return err(fid.error); - return ok({ fid: fid.value }); -}; - -export const parseFid = (message: SiweMessage): AuthClientResult => { - const resource = (message.resources ?? []).find((resource) => { - return FID_URI_REGEX.test(resource); - }); - if (!resource) { - return err(new AuthClientError("bad_request.validation_failure", "No fid resource provided")); - } - const fid = parseInt(resource.match(FID_URI_REGEX)?.[1] ?? ""); - if (isNaN(fid)) { - return err(new AuthClientError("bad_request.validation_failure", "Invalid fid")); - } - return ok(fid); -}; - -export const validateStatement = (message: SiweMessage): AuthClientResult => { - const validStatement = message.statement === STATEMENT || message.statement === "Farcaster Connect"; - if (!validStatement) { - return err(new AuthClientError("bad_request.validation_failure", `Statement must be '${STATEMENT}'`)); - } - return ok(message); -}; - -export const validateChainId = (message: SiweMessage): AuthClientResult => { - if (message.chainId !== CHAIN_ID) { - return err(new AuthClientError("bad_request.validation_failure", `Chain ID must be ${CHAIN_ID}`)); - } - return ok(message); -}; - -export const validateResources = (message: SiweMessage): AuthClientResult => { - const fidResources = (message.resources ?? []).filter((resource) => { - return FID_URI_REGEX.test(resource); - }); - if (fidResources.length === 0) { - return err(new AuthClientError("bad_request.validation_failure", "No fid resource provided")); - } else if (fidResources.length > 1) { - return err(new AuthClientError("bad_request.validation_failure", "Multiple fid resources provided")); - } else { - return ok(message); - } -}; diff --git a/packages/auth-client/src/messages/verify.test.ts b/packages/auth-client/src/messages/verify.test.ts deleted file mode 100644 index 5edc3e5..0000000 --- a/packages/auth-client/src/messages/verify.test.ts +++ /dev/null @@ -1,202 +0,0 @@ -import { build } from "./build"; -import { verify } from "./verify"; -import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; -import { Hex, zeroAddress } from "viem"; -import { getDefaultProvider, providers } from "ethers"; - -const account = privateKeyToAccount(generatePrivateKey()); - -const siweParams = { - domain: "example.com", - address: "0x63C378DDC446DFf1d831B9B96F7d338FE6bd4231", - uri: "https://example.com/login", - version: "1", - nonce: "12345678", - issuedAt: "2023-10-01T00:00:00.000Z", -}; -const { nonce, domain } = siweParams; - -describe("verify", () => { - test("verifies valid EOA signatures", async () => { - const getFid = (_custody: Hex) => Promise.resolve(1234n); - - const res = build({ - ...siweParams, - address: account.address, - fid: 1234, - }); - const { siweMessage, message } = res._unsafeUnwrap(); - const sig = await account.signMessage({ message }); - const result = await verify(nonce, domain, message, sig, { getFid }); - expect(result.isOk()).toBe(true); - expect(result._unsafeUnwrap()).toEqual({ - data: siweMessage, - success: true, - fid: 1234, - }); - }); - - test("adds parsed resources to response", async () => { - const getFid = (_custody: Hex) => Promise.resolve(1234n); - - const res = build({ - ...siweParams, - address: account.address, - fid: 1234, - }); - const { siweMessage, message } = res._unsafeUnwrap(); - const sig = await account.signMessage({ message }); - const result = await verify(nonce, domain, message, sig, { getFid }); - expect(result.isOk()).toBe(true); - expect(result._unsafeUnwrap()).toEqual({ - data: siweMessage, - success: true, - fid: 1234, - }); - }); - - test("verifies valid 1271 signatures", async () => { - const getFid = (_custody: Hex) => Promise.resolve(1234n); - const provider = getDefaultProvider("https://mainnet.optimism.io"); - - const res = build({ - ...siweParams, - address: "0xC89858205c6AdDAD842E1F58eD6c42452671885A", - fid: 1234, - }); - const { siweMessage, message } = res._unsafeUnwrap(); - const sig = await account.signMessage({ message }); - const result = await verify(nonce, domain, message, sig, { getFid, provider }); - expect(result.isOk()).toBe(true); - expect(result._unsafeUnwrap()).toEqual({ - data: siweMessage, - success: true, - fid: 1234, - }); - }); - - test("1271 signatures fail without provider", async () => { - const getFid = (_custody: Hex) => Promise.resolve(1234n); - - const res = build({ - ...siweParams, - address: "0xC89858205c6AdDAD842E1F58eD6c42452671885A", - fid: 1234, - }); - const { message } = res._unsafeUnwrap(); - const sig = await account.signMessage({ message }); - const result = await verify(nonce, domain, message, sig, { getFid }); - expect(result.isOk()).toBe(false); - const err = result._unsafeUnwrapErr(); - expect(err.errCode).toBe("unauthorized"); - expect(err.message).toBe("Signature does not match address of the message."); - }); - - test("invalid SIWE message", async () => { - const getFid = (_custody: Hex) => Promise.resolve(1234n); - - const res = build({ - ...siweParams, - address: zeroAddress, - fid: 1234, - }); - const { message } = res._unsafeUnwrap(); - const sig = await account.signMessage({ - message, - }); - const result = await verify(nonce, domain, message, sig, { getFid }); - expect(result.isOk()).toBe(false); - const err = result._unsafeUnwrapErr(); - expect(err.errCode).toBe("unauthorized"); - expect(err.message).toBe("Signature does not match address of the message."); - }); - - test("invalid fid owner", async () => { - const getFid = (_custody: Hex) => Promise.resolve(5678n); - - const res = build({ - ...siweParams, - address: account.address, - fid: 1234, - }); - const { message } = res._unsafeUnwrap(); - const sig = await account.signMessage({ - message, - }); - const result = await verify(nonce, domain, message, sig, { getFid }); - expect(result.isOk()).toBe(false); - const err = result._unsafeUnwrapErr(); - expect(err.errCode).toBe("unauthorized"); - expect(err.message).toBe(`Invalid resource: signer ${account.address} does not own fid 1234.`); - }); - - test("client error", async () => { - const getFid = (_custody: Hex) => Promise.reject(new Error("client error")); - - const res = build({ - ...siweParams, - address: account.address, - fid: 1234, - }); - const { message } = res._unsafeUnwrap(); - const sig = await account.signMessage({ - message, - }); - const result = await verify(nonce, domain, message, sig, { getFid }); - expect(result.isOk()).toBe(false); - const err = result._unsafeUnwrapErr(); - expect(err.errCode).toBe("unavailable"); - expect(err.message).toBe("client error"); - }); - - test("missing verifier", async () => { - const res = build({ - ...siweParams, - address: account.address, - fid: 1234, - }); - const { message } = res._unsafeUnwrap(); - const sig = await account.signMessage({ - message, - }); - const result = await verify(nonce, domain, message, sig); - expect(result.isOk()).toBe(false); - const err = result._unsafeUnwrapErr(); - expect(err.errCode).toBe("unavailable"); - expect(err.message).toBe("Not implemented: Must provide an fid verifier"); - }); - - test("mismatched nonce", async () => { - const res = build({ - ...siweParams, - address: account.address, - fid: 1234, - }); - const { message } = res._unsafeUnwrap(); - const sig = await account.signMessage({ - message, - }); - const result = await verify("mismatched-nonce", domain, message, sig); - expect(result.isOk()).toBe(false); - const err = result._unsafeUnwrapErr(); - expect(err.errCode).toBe("unauthorized"); - expect(err.message).toBe("Invalid nonce"); - }); - - test("mismatched domain", async () => { - const res = build({ - ...siweParams, - address: account.address, - fid: 1234, - }); - const { message } = res._unsafeUnwrap(); - const sig = await account.signMessage({ - message, - }); - const result = await verify(nonce, "mismatched-domain", message, sig); - expect(result.isOk()).toBe(false); - const err = result._unsafeUnwrapErr(); - expect(err.errCode).toBe("unauthorized"); - expect(err.message).toBe("Invalid domain"); - }); -}); diff --git a/packages/auth-client/src/messages/verify.ts b/packages/auth-client/src/messages/verify.ts deleted file mode 100644 index 39d7458..0000000 --- a/packages/auth-client/src/messages/verify.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { SiweMessage, SiweResponse, SiweError } from "siwe"; -import { ResultAsync, err, ok } from "neverthrow"; -import { AuthClientAsyncResult, AuthClientResult, AuthClientError } from "../errors"; - -import { validate, parseResources } from "./validate"; -import { FarcasterResourceParams } from "./build"; -import type { Provider } from "ethers"; - -type Hex = `0x${string}`; -type SignInOpts = { - getFid: (custody: Hex) => Promise; - provider?: Provider | undefined; -}; -export type VerifyResponse = Omit & FarcasterResourceParams; - -const voidVerifyFid = (_custody: Hex) => Promise.reject(new Error("Not implemented: Must provide an fid verifier")); - -/** - * Verify signature of a Sign In With Farcaster message. Returns an error if the - * message is invalid or the signature is invalid. - */ -export const verify = async ( - nonce: string, - domain: string, - message: string | Partial, - signature: string, - options: SignInOpts = { - getFid: voidVerifyFid, - }, -): AuthClientAsyncResult => { - const { getFid, provider } = options; - const valid = validate(message) - .andThen((message) => validateNonce(message, nonce)) - .andThen((message) => validateDomain(message, domain)); - if (valid.isErr()) return err(valid.error); - - const siwe = (await verifySiweMessage(valid.value, signature, provider)).andThen(mergeResources); - if (siwe.isErr()) return err(siwe.error); - if (!siwe.value.success) { - const errMessage = siwe.value.error?.type ?? "Failed to verify SIWE message"; - return err(new AuthClientError("unauthorized", errMessage)); - } - - const fid = await verifyFidOwner(siwe.value, getFid); - if (fid.isErr()) return err(fid.error); - if (!fid.value.success) { - const errMessage = siwe.value.error?.type ?? "Failed to validate fid owner"; - return err(new AuthClientError("unauthorized", errMessage)); - } - const { error, ...response } = fid.value; - return ok(response); -}; - -const validateNonce = (message: SiweMessage, nonce: string): AuthClientResult => { - if (message.nonce !== nonce) { - return err(new AuthClientError("unauthorized", "Invalid nonce")); - } else { - return ok(message); - } -}; - -const validateDomain = (message: SiweMessage, domain: string): AuthClientResult => { - if (message.domain !== domain) { - return err(new AuthClientError("unauthorized", "Invalid domain")); - } else { - return ok(message); - } -}; - -const verifySiweMessage = async ( - message: SiweMessage, - signature: string, - provider?: Provider, -): AuthClientAsyncResult => { - return ResultAsync.fromPromise(message.verify({ signature }, { provider, suppressExceptions: true }), (e) => { - return new AuthClientError("unauthorized", e as Error); - }); -}; - -const verifyFidOwner = async ( - response: SiweResponse & FarcasterResourceParams, - fidVerifier: (custody: Hex) => Promise, -): AuthClientAsyncResult => { - const signer = response.data.address as Hex; - return ResultAsync.fromPromise(fidVerifier(signer), (e) => { - return new AuthClientError("unavailable", e as Error); - }).andThen((fid) => { - if (fid !== BigInt(response.fid)) { - response.success = false; - response.error = new SiweError( - `Invalid resource: signer ${signer} does not own fid ${response.fid}.`, - response.fid.toString(), - fid.toString(), - ); - } - return ok(response); - }); -}; - -const mergeResources = (response: SiweResponse): AuthClientResult => { - return parseResources(response.data).andThen((resources) => { - return ok({ ...resources, ...response }); - }); -}; diff --git a/packages/auth-client/tsconfig.json b/packages/auth-client/tsconfig.json deleted file mode 100644 index c0bc7fa..0000000 --- a/packages/auth-client/tsconfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "declaration": true, - "baseUrl": "./src", - "outDir": "build", - "rootDir": "src", - "isolatedModules": true - }, - "include": ["src/index.ts"], - "exclude": ["build", "node_modules", "jest.config.ts"], - "ts-node": { - "compilerOptions": { - "module": "commonjs" - } - } -} diff --git a/packages/auth-client/tsup.config.ts b/packages/auth-client/tsup.config.ts deleted file mode 100644 index 51e1f86..0000000 --- a/packages/auth-client/tsup.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from "tsup"; - -export default defineConfig({ - target: ["es2020"], - entryPoints: ["src/index.ts"], - format: ["esm", "cjs"], - dts: true, - clean: true, - shims: true, -}); diff --git a/packages/auth-kit/.eslintrc.cjs b/packages/auth-kit/.eslintrc.cjs deleted file mode 100644 index 6e8698b..0000000 --- a/packages/auth-kit/.eslintrc.cjs +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = { - root: true, - env: { browser: true, es2020: true }, - extends: [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:react-hooks/recommended", - ], - ignorePatterns: ["dist", ".eslintrc.cjs"], - parser: "@typescript-eslint/parser", - plugins: ["react-refresh"], - rules: { - "react-refresh/only-export-components": [ - "warn", - { allowConstantExport: true }, - ], - }, -}; diff --git a/packages/auth-kit/package.json b/packages/auth-kit/package.json deleted file mode 100644 index 539ac4f..0000000 --- a/packages/auth-kit/package.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "@farcaster/auth-kit", - "version": "0.2.2", - "type": "module", - "main": "./dist/auth-kit.js", - "types": "./dist/auth-kit.d.ts", - "exports": { - ".": "./dist/auth-kit.js", - "./styles.css": "./dist/style.css" - }, - "files": [ - "dist" - ], - "license": "MIT", - "scripts": { - "dev": "vite", - "build": "tsc && vite build", - "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0" - }, - "dependencies": { - "@farcaster/auth-client": "^0.1.1", - "@vanilla-extract/css": "^1.14.0", - "ethers": "^6.12.0", - "qrcode": "^1.5.3", - "react-remove-scroll": "^2.5.7" - }, - "devDependencies": { - "@types/qrcode": "^1.5.5", - "@types/react": "^18.2.43", - "@types/react-dom": "^18.2.17", - "@typescript-eslint/eslint-plugin": "^6.14.0", - "@typescript-eslint/parser": "^6.14.0", - "@vanilla-extract/vite-plugin": "^3.9.3", - "@vitejs/plugin-react": "^4.2.1", - "eslint": "^8.55.0", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.5", - "ethers": "5", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "typescript": "^5.2.2", - "viem": "^1.19.11", - "vite": "^5.0.12", - "vite-plugin-dts": "^3.7.0", - "vite-plugin-node-polyfills": "^0.19.0" - }, - "peerDependencies": { - "react": ">= 17", - "react-dom": ">= 17" - } -} diff --git a/packages/auth-kit/src/components/ActionButton/index.ts b/packages/auth-kit/src/components/ActionButton/index.ts deleted file mode 100644 index 4b6341e..0000000 --- a/packages/auth-kit/src/components/ActionButton/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./ActionButton"; diff --git a/packages/auth-kit/src/components/AuthKitProvider/AuthKitProvider.tsx b/packages/auth-kit/src/components/AuthKitProvider/AuthKitProvider.tsx deleted file mode 100644 index b5d8c7b..0000000 --- a/packages/auth-kit/src/components/AuthKitProvider/AuthKitProvider.tsx +++ /dev/null @@ -1,116 +0,0 @@ -import { createContext, ReactNode, useCallback, useEffect, useState } from "react"; -import { AppClient, createAppClient, viemConnector, Provider } from "@farcaster/auth-client"; -import { UseSignInData } from "../../hooks/useSignIn"; - -export interface AuthKitConfig { - relay?: string; - domain?: string; - siweUri?: string; - rpcUrl?: string; - redirectUrl?: string; - version?: string; - provider?: Provider; -} - -export interface Profile { - fid?: number; - pfpUrl?: string; - username?: string; - displayName?: string; - bio?: string; - custody?: `0x${string}`; - verifications?: `0x${string}`[]; -} - -export interface SignInMessage { - message?: string; - signature?: string; -} - -export interface AuthKitContextValues { - isAuthenticated: boolean; - config: AuthKitConfig; - profile: Profile; - signInMessage: SignInMessage; - appClient?: AppClient; - onSignIn: (signInData: UseSignInData) => void; - onSignOut: () => void; -} - -const domainDefaults = (typeof window !== 'undefined' && window?.location) ? { - domain: window.location.host, - siweUri: window.location.href -} : {}; - -const configDefaults = { - relay: "https://relay.farcaster.xyz", - version: "v1", - ...domainDefaults -}; - -export const AuthKitContext = createContext({ - isAuthenticated: false, - config: configDefaults, - profile: {}, - signInMessage: {}, - onSignIn: () => { }, - onSignOut: () => { }, -}); - -export function AuthKitProvider({ - config, - children, -}: { - config: AuthKitConfig; - children: ReactNode; -}) { - const [appClient, setAppClient] = useState(); - const [isAuthenticated, setIsAuthenticated] = useState(false); - const [profile, setProfile] = useState({}); - const [signInMessage, setSignInMessage] = useState({}); - - const authKitConfig = { - ...configDefaults, - ...config, - }; - const { relay, rpcUrl, version, provider } = authKitConfig; - - useEffect(() => { - const ethereum = rpcUrl ? viemConnector({ rpcUrl }) : viemConnector(); - const client = createAppClient({ - relay, - ethereum, - version, - }, provider); - setAppClient(client); - }, [relay, rpcUrl, version, provider]); - - const onSignIn = useCallback((signInData: UseSignInData) => { - const { message, signature, fid, username, bio, displayName, pfpUrl, custody, verifications } = signInData; - setIsAuthenticated(true); - setProfile({ fid, username, bio, displayName, pfpUrl, custody, verifications }); - setSignInMessage({ message, signature }); - }, []); - - const onSignOut = () => { - setIsAuthenticated(false); - setProfile({}); - setSignInMessage({}); - } - - return ( - - {children} - - ); -} diff --git a/packages/auth-kit/src/components/AuthKitProvider/index.ts b/packages/auth-kit/src/components/AuthKitProvider/index.ts deleted file mode 100644 index 9eafe45..0000000 --- a/packages/auth-kit/src/components/AuthKitProvider/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { AuthKitProvider } from "./AuthKitProvider"; diff --git a/packages/auth-kit/src/components/Demo/Demo.tsx b/packages/auth-kit/src/components/Demo/Demo.tsx deleted file mode 100644 index 92214fc..0000000 --- a/packages/auth-kit/src/components/Demo/Demo.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import useProfile from "../../hooks/useProfile"; -import { SignInButton } from "../SignInButton"; -import { AuthKitProvider } from "../AuthKitProvider"; - -export function Demo() { - const config = { - rpcUrl: "https://mainnet.optimism.io", - }; - - return ( - -
- console.error("error callback:", error)} - onSuccess={(data) => console.log("success callback:", data)} - onStatusResponse={(res) => console.log("status callback:", res)} - onSignOut={() => console.log("sign out callback")} - debug - /> -
- -
- ); -} - -function UserProfile() { - const { - isAuthenticated, - profile: { fid, bio, displayName, custody }, - } = useProfile(); - - return ( -
- {isAuthenticated && ( -
- {fid && ( -

- FID: {fid} -

- )} - {displayName && ( -

- Display name: {displayName} -

- )} - {bio && ( -

- Bio: {bio} -

- )} - {custody && ( -

- Custody address: {custody} -

- )} -
- )} -
- ); -} diff --git a/packages/auth-kit/src/components/Demo/index.ts b/packages/auth-kit/src/components/Demo/index.ts deleted file mode 100644 index f9847d3..0000000 --- a/packages/auth-kit/src/components/Demo/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./Demo"; diff --git a/packages/auth-kit/src/components/Dialog/index.ts b/packages/auth-kit/src/components/Dialog/index.ts deleted file mode 100644 index 24cc75a..0000000 --- a/packages/auth-kit/src/components/Dialog/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./Dialog"; diff --git a/packages/auth-kit/src/components/ProfileButton/index.ts b/packages/auth-kit/src/components/ProfileButton/index.ts deleted file mode 100644 index ae74779..0000000 --- a/packages/auth-kit/src/components/ProfileButton/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./ProfileButton"; diff --git a/packages/auth-kit/src/components/QRCodeDialog/index.tsx b/packages/auth-kit/src/components/QRCodeDialog/index.tsx deleted file mode 100644 index 90358ee..0000000 --- a/packages/auth-kit/src/components/QRCodeDialog/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { QRCodeDialog } from "./QRCodeDialog"; diff --git a/packages/auth-kit/src/components/SignInButton/SignInButton.tsx b/packages/auth-kit/src/components/SignInButton/SignInButton.tsx deleted file mode 100644 index fb62de0..0000000 --- a/packages/auth-kit/src/components/SignInButton/SignInButton.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import { useCallback, useEffect, useState } from "react"; -import useSignIn, { UseSignInArgs } from "../../hooks/useSignIn.ts"; -import { ActionButton } from "../ActionButton/index.ts"; -import { ProfileButton } from "../ProfileButton/index.ts"; -import { QRCodeDialog } from "../QRCodeDialog/index.tsx"; -import { isMobile } from "../../utils.ts"; -import { AuthClientError, StatusAPIResponse } from "@farcaster/auth-client"; -import { debugPanel } from "./SignInButton.css.ts"; - -type SignInButtonProps = UseSignInArgs & { - onSignOut?: () => void; - debug?: boolean; - hideSignOut?: boolean; -}; - -export function SignInButton({ - debug, - hideSignOut, - onSignOut, - ...signInArgs -}: SignInButtonProps) { - const { onSuccess, onStatusResponse, onError } = signInArgs; - - const onSuccessCallback = useCallback( - (res: StatusAPIResponse) => { - onSuccess?.(res); - }, - [onSuccess] - ); - - const onStatusCallback = useCallback( - (res: StatusAPIResponse) => { - onStatusResponse?.(res); - }, - [onStatusResponse] - ); - - const onErrorCallback = useCallback( - (error?: AuthClientError) => { - onError?.(error); - }, - [onError] - ); - - const onSignOutCallback = useCallback(() => { - onSignOut?.(); - }, [onSignOut]); - - const signInState = useSignIn({ - ...signInArgs, - onSuccess: onSuccessCallback, - onStatusResponse: onStatusCallback, - onError: onErrorCallback, - }); - const { - signIn, - signOut, - connect, - reconnect, - isSuccess, - isError, - error, - channelToken, - url, - data, - validSignature, - } = signInState; - - const handleSignOut = useCallback(() => { - setShowDialog(false); - signOut(); - onSignOutCallback(); - }, [signOut, onSignOutCallback]); - - const [showDialog, setShowDialog] = useState(false); - - const onClick = useCallback(() => { - if (isError) { - reconnect(); - } - setShowDialog(true); - signIn(); - if (url && isMobile()) { - window.location.href = url; - } - }, [isError, reconnect, signIn, url]); - - const authenticated = isSuccess && validSignature; - - useEffect(() => { - if (!channelToken) { - connect(); - } - }, [channelToken, connect]); - - return ( -
- {authenticated ? ( - - ) : ( - <> - - {url && ( - setShowDialog(false)} - url={url} - isError={isError} - error={error} - /> - )} - - )} - {debug && ( -
-
{JSON.stringify(signInState, null, 2)}
-
- )} -
- ); -} diff --git a/packages/auth-kit/src/components/SignInButton/index.ts b/packages/auth-kit/src/components/SignInButton/index.ts deleted file mode 100644 index b89da15..0000000 --- a/packages/auth-kit/src/components/SignInButton/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./SignInButton"; diff --git a/packages/auth-kit/src/components/SignOutButton/index.ts b/packages/auth-kit/src/components/SignOutButton/index.ts deleted file mode 100644 index 7e1dee0..0000000 --- a/packages/auth-kit/src/components/SignOutButton/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./SignOutButton"; diff --git a/packages/auth-kit/src/components/index.ts b/packages/auth-kit/src/components/index.ts deleted file mode 100644 index 442f51c..0000000 --- a/packages/auth-kit/src/components/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./SignInButton"; -export * from "./AuthKitProvider"; -export * from "./Demo"; -export * from "./QRCode"; diff --git a/packages/auth-kit/src/demo.tsx b/packages/auth-kit/src/demo.tsx deleted file mode 100644 index 8897aaf..0000000 --- a/packages/auth-kit/src/demo.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { createRoot } from "react-dom/client"; -import { Demo } from "./index"; - -const domNode = document.getElementById("root"); -const root = createRoot(domNode!); -root.render(); diff --git a/packages/auth-kit/src/hooks/index.ts b/packages/auth-kit/src/hooks/index.ts deleted file mode 100644 index b54d8e3..0000000 --- a/packages/auth-kit/src/hooks/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from "./useAppClient"; -export * from "./useCreateChannel"; -export * from "./useSignIn"; -export * from "./useSignInMessage"; -export * from "./useProfile"; -export * from "./useVerifySignInMessage"; -export * from "./useWatchStatus"; diff --git a/packages/auth-kit/src/hooks/useAppClient.ts b/packages/auth-kit/src/hooks/useAppClient.ts deleted file mode 100644 index 0f0c6a0..0000000 --- a/packages/auth-kit/src/hooks/useAppClient.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { useAuthKitContext } from "./useAuthKitContext"; - -export function useAppClient() { - const { appClient } = useAuthKitContext(); - return appClient; -} - -export default useAppClient; diff --git a/packages/auth-kit/src/hooks/useAuthKitContext.ts b/packages/auth-kit/src/hooks/useAuthKitContext.ts deleted file mode 100644 index bb2729e..0000000 --- a/packages/auth-kit/src/hooks/useAuthKitContext.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { useContext } from "react"; - -import { AuthKitContext } from "../components/AuthKitProvider/AuthKitProvider"; - -export function useAuthKitContext() { - return useContext(AuthKitContext); -} - -export default useAuthKitContext; diff --git a/packages/auth-kit/src/hooks/useCreateChannel.ts b/packages/auth-kit/src/hooks/useCreateChannel.ts deleted file mode 100644 index 8a559a1..0000000 --- a/packages/auth-kit/src/hooks/useCreateChannel.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { AuthClientError } from "@farcaster/auth-client"; -import { useCallback, useEffect, useState } from "react"; - -import { useAppClient } from "./useAppClient"; -import useAuthKitContext from "./useAuthKitContext"; - -export interface UseCreateChannelArgs { - nonce?: string | (() => Promise); - notBefore?: string; - expirationTime?: string; - requestId?: string; - redirectUrl?: string; - onSuccess?: (createChannelData: UseCreateChannelData) => void; - onError?: (error?: AuthClientError) => void; -} - -export interface UseCreateChannelData { - channelToken?: string; - url?: string; - nonce?: string; -} - -export function useCreateChannel({ - nonce: customNonce, - notBefore, - expirationTime, - requestId, - onSuccess, - onError, - redirectUrl, -}: UseCreateChannelArgs) { - const { config } = useAuthKitContext(); - const { siweUri, domain } = config; - const appClient = useAppClient(); - - const [connected, setConnected] = useState(false); - const [channelToken, setChannelToken] = useState(); - const [url, setUrl] = useState(); - const [nonce, setNonce] = useState(); - const [isSuccess, setIsSuccess] = useState(false); - const [isError, setIsError] = useState(false); - const [error, setError] = useState(); - - const createChannel = useCallback(async () => { - if (connected && appClient && siweUri && domain && !channelToken) { - const nonceVal = typeof customNonce === "function" ? await customNonce() : customNonce; - const { - data, - isError: isCreateChannelError, - error: createChannelError, - } = await appClient.createChannel({ - nonce: nonceVal, - siweUri, - domain, - notBefore, - expirationTime, - requestId, - redirectUrl, - }); - if (isCreateChannelError) { - setIsError(true); - setError(createChannelError); - onError?.(createChannelError); - } else { - const { channelToken, url, nonce } = data; - setChannelToken(channelToken); - setUrl(url); - setNonce(nonce); - - setIsSuccess(true); - onSuccess?.({ channelToken, url, nonce }); - } - } - }, [ - connected, - appClient, - siweUri, - domain, - channelToken, - customNonce, - notBefore, - expirationTime, - requestId, - onError, - onSuccess, - redirectUrl, - ]); - - useEffect(() => { - createChannel(); - }, [createChannel]); - - const connect = useCallback(async () => { - setConnected(true); - }, [setConnected]); - - const reset = useCallback(() => { - setChannelToken(undefined); - setUrl(undefined); - setIsSuccess(false); - setIsError(false); - setError(undefined); - }, [setChannelToken, setUrl, setIsSuccess, setIsError, setError]); - - const reconnect = useCallback(() => { - reset(); - connect(); - }, [connect, reset]); - - return { - connect, - reconnect, - reset, - isSuccess, - isError, - error, - data: { channelToken, url, nonce }, - }; -} - -export default useCreateChannel; diff --git a/packages/auth-kit/src/hooks/useProfile.ts b/packages/auth-kit/src/hooks/useProfile.ts deleted file mode 100644 index 51822ab..0000000 --- a/packages/auth-kit/src/hooks/useProfile.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { useAuthKitContext } from "./useAuthKitContext"; - -export function useProfile() { - const { isAuthenticated, profile } = useAuthKitContext(); - return { isAuthenticated, profile }; -} - -export default useProfile; diff --git a/packages/auth-kit/src/hooks/useSignIn.ts b/packages/auth-kit/src/hooks/useSignIn.ts deleted file mode 100644 index 61ac509..0000000 --- a/packages/auth-kit/src/hooks/useSignIn.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { AuthClientError, StatusAPIResponse } from "@farcaster/auth-client"; -import { useCallback, useEffect } from "react"; - -import useAppClient from "./useAppClient"; -import useCreateChannel, { UseCreateChannelArgs } from "./useCreateChannel"; -import useAuthKitContext from "./useAuthKitContext"; -import useVerifySignInMessage from "./useVerifySignInMessage"; -import useWatchStatus, { UseWatchStatusData } from "./useWatchStatus"; - -export type UseSignInArgs = Omit & { - timeout?: number; - interval?: number; - onSuccess?: (res: UseSignInData) => void; - onStatusResponse?: (statusData: UseWatchStatusData) => void; - onError?: (error?: AuthClientError) => void; -}; - -export type UseSignInData = StatusAPIResponse; - -const defaults = { - timeout: 300_000, - interval: 1_500, -}; - -export function useSignIn(args: UseSignInArgs) { - const appClient = useAppClient(); - const { - onSignIn, - onSignOut, - config: { domain, redirectUrl }, - } = useAuthKitContext(); - const { timeout, interval, onSuccess, onStatusResponse, onError, ...createChannelArgs } = { - ...defaults, - ...args, - }; - - const { - connect, - reconnect, - reset, - data: { channelToken, url, nonce }, - isSuccess: isConnected, - isError: isCreateChannelError, - error: createChannelError, - } = useCreateChannel({ ...createChannelArgs, redirectUrl, onError }); - - const { - watch, - isPolling, - data: statusData, - isError: isWatchStatusError, - error: watchStatusError, - } = useWatchStatus({ - channelToken, - timeout, - interval, - onError, - onResponse: onStatusResponse, - }); - - const { - isSuccess, - data: { validSignature }, - isError: isVerifyError, - error: verifyError, - } = useVerifySignInMessage({ - nonce, - domain, - message: statusData?.message, - signature: statusData?.signature, - onError, - }); - - const isError = isCreateChannelError || isWatchStatusError || isVerifyError; - const error = createChannelError || watchStatusError || verifyError; - - const signIn = useCallback(() => { - watch(); - }, [watch]); - - const signOut = useCallback(() => { - onSignOut(); - reset(); - }, [onSignOut, reset]); - - useEffect(() => { - if (isSuccess && statusData && validSignature) { - onSignIn(statusData); - onSuccess?.(statusData); - } - }, [isSuccess, statusData, validSignature, onSignIn, onSuccess]); - - return { - signIn, - signOut, - connect, - reconnect, - isConnected, - isSuccess, - isPolling, - isError, - error, - channelToken, - url, - appClient, - data: statusData, - validSignature, - }; -} - -export default useSignIn; diff --git a/packages/auth-kit/src/hooks/useSignInMessage.ts b/packages/auth-kit/src/hooks/useSignInMessage.ts deleted file mode 100644 index 5880ad2..0000000 --- a/packages/auth-kit/src/hooks/useSignInMessage.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { useAuthKitContext } from "./useAuthKitContext"; - -export function useSignInMessage() { - const { signInMessage } = useAuthKitContext(); - return signInMessage; -} - -export default useSignInMessage; diff --git a/packages/auth-kit/src/hooks/useVerifySignInMessage.ts b/packages/auth-kit/src/hooks/useVerifySignInMessage.ts deleted file mode 100644 index 90ac89d..0000000 --- a/packages/auth-kit/src/hooks/useVerifySignInMessage.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { useCallback, useEffect, useState } from "react"; -import { AuthClientError } from "@farcaster/auth-client"; -import useAppClient from "./useAppClient"; - -export interface UseVerifySignInMessageArgs { - nonce?: string; - domain?: string; - message?: string; - signature?: `0x${string}`; - onSuccess?: (statusData: UseVerifySignInMessageData) => void; - onError?: (error?: AuthClientError) => void; -} - -export interface UseVerifySignInMessageData { - message?: string; - signature?: `0x${string}`; - validSignature: boolean; -} - -export function useVerifySignInMessage({ - nonce, - domain, - message, - signature, - onSuccess, - onError, -}: UseVerifySignInMessageArgs) { - const appClient = useAppClient(); - - const [validSignature, setValidSignature] = useState(false); - const [isSuccess, setIsSuccess] = useState(false); - const [isError, setIsError] = useState(false); - const [error, setError] = useState(); - - const resetState = async () => { - setIsError(false); - setIsSuccess(false); - setValidSignature(false); - setError(undefined); - }; - - const verifySignInMessage = useCallback(async () => { - if (appClient && nonce && domain && message && signature) { - const { - success, - isError: isVerifyError, - error: verifyError, - } = await appClient.verifySignInMessage({ - nonce, - domain, - message, - signature, - }); - if (isVerifyError) { - setIsError(true); - setError(verifyError); - onError?.(verifyError); - } else { - setValidSignature(success); - setIsSuccess(true); - onSuccess?.({ message, signature, validSignature: success }); - } - } - }, [appClient, nonce, domain, message, signature, onSuccess, onError]); - - useEffect(() => { - resetState(); - if (nonce && domain && message && signature) { - verifySignInMessage(); - } - }, [nonce, domain, message, signature, verifySignInMessage]); - - return { - isSuccess, - isError, - error, - data: { message, signature, validSignature }, - }; -} - -export default useVerifySignInMessage; diff --git a/packages/auth-kit/src/hooks/useWatchStatus.ts b/packages/auth-kit/src/hooks/useWatchStatus.ts deleted file mode 100644 index 52b63bd..0000000 --- a/packages/auth-kit/src/hooks/useWatchStatus.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { useCallback, useEffect, useState } from "react"; -import { AuthClientError, StatusAPIResponse } from "@farcaster/auth-client"; -import useAppClient from "./useAppClient"; - -export interface UseWatchStatusArgs { - channelToken?: string; - timeout?: number; - interval?: number; - onSuccess?: (statusData: UseWatchStatusData) => void; - onError?: (error?: AuthClientError) => void; - onResponse?: (statusData: UseWatchStatusData) => void; -} - -export type UseWatchStatusData = StatusAPIResponse; - -const defaults = { - timeout: 300_000, - interval: 1_500, -}; - -export function useWatchStatus(args: UseWatchStatusArgs) { - const appClient = useAppClient(); - const { channelToken, timeout, interval, onSuccess, onError, onResponse } = { - ...defaults, - ...args, - }; - - const [statusData, setStatusData] = useState(); - const [isEnabled, setIsEnabled] = useState(false); - const [isSuccess, setIsSuccess] = useState(false); - const [isPolling, setIsPolling] = useState(false); - const [isError, setIsError] = useState(false); - const [error, setError] = useState(); - - const resetState = () => { - setStatusData(undefined); - setIsEnabled(false); - setIsError(false); - setIsSuccess(false); - setError(undefined); - }; - - const watch = () => { - setIsEnabled(true); - }; - - const watchStatus = useCallback(async () => { - if (isEnabled && appClient && channelToken) { - setIsPolling(true); - const { - data, - isError: isWatchStatusError, - error: watchStatusError, - } = await appClient.watchStatus({ - channelToken, - timeout, - interval, - onResponse: ({ data }: { data: StatusAPIResponse }) => { - setStatusData(data); - onResponse?.(data); - }, - }); - if (isWatchStatusError) { - setIsError(true); - setIsPolling(false); - setError(watchStatusError); - onError?.(watchStatusError); - } else { - setIsSuccess(true); - setIsPolling(false); - setStatusData(data); - onSuccess?.(data); - } - } - }, [isEnabled, appClient, channelToken, timeout, interval, onSuccess, onError, onResponse]); - - useEffect(() => { - resetState(); - if (channelToken) { - watchStatus(); - } - }, [channelToken, watchStatus]); - - return { - watch, - isSuccess, - isPolling, - isError, - error, - data: statusData, - }; -} - -export default useWatchStatus; diff --git a/packages/auth-kit/src/index.ts b/packages/auth-kit/src/index.ts deleted file mode 100644 index 6404779..0000000 --- a/packages/auth-kit/src/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "@farcaster/auth-client"; - -export * from "./components"; -export * from "./hooks"; diff --git a/packages/auth-kit/tsconfig.json b/packages/auth-kit/tsconfig.json deleted file mode 100644 index a7fc6fb..0000000 --- a/packages/auth-kit/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src"], - "references": [{ "path": "./tsconfig.node.json" }] -} diff --git a/packages/auth-kit/tsconfig.node.json b/packages/auth-kit/tsconfig.node.json deleted file mode 100644 index 6749b86..0000000 --- a/packages/auth-kit/tsconfig.node.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "skipLibCheck": true, - "module": "ESNext", - "moduleResolution": "bundler", - "allowSyntheticDefaultImports": true, - "jsx": "react-jsx" - }, - "include": ["vite.config.ts"] -} diff --git a/packages/auth-kit/vite.config.ts b/packages/auth-kit/vite.config.ts deleted file mode 100644 index 65f6327..0000000 --- a/packages/auth-kit/vite.config.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { resolve } from "path"; -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react"; -import { vanillaExtractPlugin } from "@vanilla-extract/vite-plugin"; -import dts from "vite-plugin-dts"; -import { nodePolyfills } from "vite-plugin-node-polyfills"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [ - react(), - vanillaExtractPlugin(), - dts({ rollupTypes: true }), - nodePolyfills({ include: ["buffer"] }), - ], - build: { - lib: { - formats: ["es"], - entry: resolve(__dirname, "src/index.ts"), - fileName: "auth-kit", - }, - rollupOptions: { - external: [ - "react", - "react/jsx-runtime", - "react-dom", - "@farcaster/auth-client", - ], - }, - }, -}); diff --git a/packages/auth-client/CHANGELOG.md b/packages/core/CHANGELOG.md similarity index 100% rename from packages/auth-client/CHANGELOG.md rename to packages/core/CHANGELOG.md diff --git a/packages/auth-client/README.md b/packages/core/README.md similarity index 100% rename from packages/auth-client/README.md rename to packages/core/README.md diff --git a/packages/auth-client/jest.config.ts b/packages/core/jest.config.ts similarity index 100% rename from packages/auth-client/jest.config.ts rename to packages/core/jest.config.ts diff --git a/packages/core/package.json b/packages/core/package.json new file mode 100644 index 0000000..b7f2412 --- /dev/null +++ b/packages/core/package.json @@ -0,0 +1,87 @@ +{ + "name": "@farcaster/auth-client", + "description": "A framework agnostic client library for Farcaster Auth.", + "version": "0.1.0", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/farcasterxyz/auth-monorepo.git", + "directory": "packages/core" + }, + "scripts": { + "build": "pnpm run clean && pnpm run build:esm+types", + "build:esm+types": "tsc --project tsconfig.build.json --outDir ./dist/esm --declaration --declarationMap --declarationDir ./dist/types", + "clean": "rimraf dist tsconfig.tsbuildinfo actions clients contracts errors utils", + "test:build": "publint --strict", + "typecheck": "tsc --noEmit", + "test:ci": "ENVIRONMENT=test jest --ci --forceExit --coverage", + "console": "pnpm ts-node ./scripts/console.ts", + "prepublishOnly": "pnpm run build" + }, + "files": [ + "dist/**", + "!dist/**/*.tsbuildinfo", + "src/**/*.ts", + "!src/**/*.test.ts", + "!src/**/*.test-d.ts", + "/actions", + "/clients", + "/contracts", + "/errors", + "/utils" + ], + "sideEffects": false, + "type": "module", + "main": "./dist/esm/exports/index.js", + "types": "./dist/types/exports/index.d.ts", + "typings": "./dist/types/exports/index.d.ts", + "exports": { + ".": { + "types": "./dist/types/exports/index.d.ts", + "default": "./dist/esm/exports/index.js" + }, + "./actions": { + "types": "./dist/types/exports/actions.d.ts", + "default": "./dist/esm/exports/actions.js" + }, + "./clients": { + "types": "./dist/types/exports/clients.d.ts", + "default": "./dist/esm/exports/clients.js" + }, + "./contracts": { + "types": "./dist/types/exports/contracts.d.ts", + "default": "./dist/esm/exports/contracts.js" + }, + "./errors": { + "types": "./dist/types/exports/errors.d.ts", + "default": "./dist/esm/exports/errors.js" + }, + "./utils": { + "types": "./dist/types/exports/utils.d.ts", + "default": "./dist/esm/exports/utils.js" + }, + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "actions": ["./dist/types/exports/actions.d.ts"], + "clients": ["./dist/types/exports/clients.d.ts"], + "contracts": ["./dist/types/exports/contracts.d.ts"], + "errors": ["./dist/types/exports/errors.d.ts"], + "utils": ["./dist/types/exports/utils.d.ts"] + } + }, + "dependencies": { + "@farcaster/relay": "workspace:*", + "ethers": "^6.11.1", + "neverthrow": "^6.1.0", + "siwe": "^2.1.4" + }, + "peerDependencies": { + "viem": "1.x || 2.x" + }, + "devDependencies": { + "viem": "^1.21.4" + }, + "keywords": ["farcaster", "sign-in", "sign-in with farcaster", "siwe", "auth-client"] +} diff --git a/packages/auth-client/scripts/console.ts b/packages/core/scripts/console.ts similarity index 100% rename from packages/auth-client/scripts/console.ts rename to packages/core/scripts/console.ts diff --git a/packages/auth-client/src/actions/app/status.test.ts b/packages/core/src/actions/app/channel.test.ts similarity index 56% rename from packages/auth-client/src/actions/app/status.test.ts rename to packages/core/src/actions/app/channel.test.ts index f16e9b6..51b6c4a 100644 --- a/packages/auth-client/src/actions/app/status.test.ts +++ b/packages/core/src/actions/app/channel.test.ts @@ -1,9 +1,9 @@ -import { createAppClient } from "../../clients/createAppClient"; +import { createAppClient } from "../../clients/createAppClient.js"; import { jest } from "@jest/globals"; -import { viemConnector } from "../../clients/ethereum/viemConnector"; -import { StatusAPIResponse } from "./status"; +import { viemConnector } from "../../clients/ethereum/viemConnector.js"; +import { type ChannelReturnType } from "./channel.js"; -describe("status", () => { +describe("channel", () => { const client = createAppClient({ ethereum: viemConnector(), }); @@ -12,23 +12,22 @@ describe("status", () => { jest.restoreAllMocks(); }); - const statusResponseDataStub: StatusAPIResponse = { + const channelResponseDataStub: ChannelReturnType = { state: "pending", nonce: "abcd1234", url: "https://warpcast.com/~/sign-in-with-farcaster?nonce=abcd1234[...]", }; - test("constructs API request", async () => { - const response = new Response(JSON.stringify(statusResponseDataStub)); - const spy = jest.spyOn(global, "fetch").mockResolvedValue(response); + test("constructs request", async () => { + const spy = jest.spyOn(global, "fetch").mockResolvedValue(new Response(JSON.stringify(channelResponseDataStub))); - const res = await client.status({ + const res = await client.channel({ channelToken: "some-channel-token", }); - expect(res.response).toEqual(response); + expect(res).toEqual(channelResponseDataStub); expect(spy).toHaveBeenCalledTimes(1); - expect(spy).toHaveBeenCalledWith("https://relay.farcaster.xyz/v1/channel/status", { + expect(spy).toHaveBeenCalledWith("https://relay.farcaster.xyz/v1/channel/channel", { headers: { "Content-Type": "application/json", Authorization: "Bearer some-channel-token", diff --git a/packages/core/src/actions/app/channel.ts b/packages/core/src/actions/app/channel.ts new file mode 100644 index 0000000..8776d03 --- /dev/null +++ b/packages/core/src/actions/app/channel.ts @@ -0,0 +1,17 @@ +import { type Client } from "../../clients/createClient.js"; +import { get } from "../../clients/transports/http.js"; +import { type ChannelGetReturnType } from "@farcaster/relay"; + +export type ChannelParameters = { + channelToken: string; +}; + +export type ChannelReturnType = ChannelGetReturnType; + +const path = "channel/status"; + +export const channel = (client: Client, { channelToken }: ChannelParameters): Promise => { + return get(client, path, { + channelToken: channelToken, + }); +}; diff --git a/packages/auth-client/src/actions/app/createChannel.test.ts b/packages/core/src/actions/app/createChannel.test.ts similarity index 55% rename from packages/auth-client/src/actions/app/createChannel.test.ts rename to packages/core/src/actions/app/createChannel.test.ts index f03a420..d259f9d 100644 --- a/packages/auth-client/src/actions/app/createChannel.test.ts +++ b/packages/core/src/actions/app/createChannel.test.ts @@ -1,8 +1,8 @@ -import { createAppClient } from "../../clients/createAppClient"; +import { createAppClient } from "../../clients/createAppClient.js"; import { jest } from "@jest/globals"; -import { viemConnector } from "../../clients/ethereum/viemConnector"; -import { AuthClientError } from "../../errors"; -import { CreateChannelAPIResponse } from "./createChannel"; +import { viemConnector } from "../../clients/ethereum/viemConnector.js"; +import { AuthClientError } from "../../errors.js"; +import { type CreateChannelReturnType } from "./createChannel.js"; describe("createChannel", () => { const client = createAppClient({ @@ -17,15 +17,16 @@ describe("createChannel", () => { const domain = "example.com"; const nonce = "abcd1234"; - const createChannelResponseDataStub: CreateChannelAPIResponse = { - channelToken: "some-channel-token", - url: "completed", + const createChannelResponseDataStub: CreateChannelReturnType = { + url: "https://some-url", + state: "pending", nonce, }; test("constructs API request", async () => { - const response = new Response(JSON.stringify(createChannelResponseDataStub)); - const spy = jest.spyOn(global, "fetch").mockResolvedValue(response); + const spy = jest + .spyOn(global, "fetch") + .mockResolvedValue(new Response(JSON.stringify(createChannelResponseDataStub))); const res = await client.createChannel({ siweUri, @@ -33,7 +34,7 @@ describe("createChannel", () => { nonce, }); - expect(res.response).toEqual(response); + expect(res).toEqual(createChannelResponseDataStub); expect(spy).toHaveBeenCalledTimes(1); expect(spy).toHaveBeenCalledWith("https://relay.farcaster.xyz/v1/channel", { method: "POST", @@ -51,14 +52,16 @@ describe("createChannel", () => { test("handles errors", async () => { const spy = jest.spyOn(global, "fetch").mockRejectedValue(new Error("some error")); - const res = await client.createChannel({ - siweUri, - domain, - nonce, - }); - - expect(spy).toHaveBeenCalledTimes(1); - expect(res.isError).toBe(true); - expect(res.error).toEqual(new AuthClientError("unknown", "some error")); + try { + await client.createChannel({ + siweUri, + domain, + nonce, + }); + expect(true).toBe(false); + } catch (e) { + expect(spy).toHaveBeenCalledTimes(1); + expect(e).toEqual(new AuthClientError("unknown", "some error")); + } }); }); diff --git a/packages/core/src/actions/app/createChannel.ts b/packages/core/src/actions/app/createChannel.ts new file mode 100644 index 0000000..fb53a8f --- /dev/null +++ b/packages/core/src/actions/app/createChannel.ts @@ -0,0 +1,16 @@ +import { type ChannelCreateParameters, type ChannelCreateReturnType } from "@farcaster/relay"; +import { type Client } from "../../clients/createClient.js"; +import { post } from "../../clients/transports/http.js"; + +export type CreateChannelParameters = ChannelCreateParameters; + +export type CreateChannelReturnType = ChannelCreateReturnType; + +const path = "channel"; + +export const createChannel = ( + client: Client, + parameters: CreateChannelParameters, +): Promise => { + return post(client, path, parameters); +}; diff --git a/packages/core/src/actions/app/index.ts b/packages/core/src/actions/app/index.ts new file mode 100644 index 0000000..6c5eb76 --- /dev/null +++ b/packages/core/src/actions/app/index.ts @@ -0,0 +1,4 @@ +export * from "./createChannel.js"; +export * from "./channel.js"; +export * from "./verifySiweMessage.js"; +export * from "./pollChannelTillCompleted.js"; diff --git a/packages/auth-client/src/actions/app/watchStatus.test.ts b/packages/core/src/actions/app/pollChannelTillCompleted.test.ts similarity index 66% rename from packages/auth-client/src/actions/app/watchStatus.test.ts rename to packages/core/src/actions/app/pollChannelTillCompleted.test.ts index 1b79eab..b96775b 100644 --- a/packages/auth-client/src/actions/app/watchStatus.test.ts +++ b/packages/core/src/actions/app/pollChannelTillCompleted.test.ts @@ -1,8 +1,8 @@ -import { createAppClient } from "../../clients/createAppClient"; +import { createAppClient } from "../../clients/createAppClient.js"; import { jest } from "@jest/globals"; -import { viemConnector } from "../../clients/ethereum/viemConnector"; +import { viemConnector } from "../../clients/ethereum/viemConnector.js"; -describe("status", () => { +describe("channel", () => { const client = createAppClient({ ethereum: viemConnector(), }); @@ -11,7 +11,7 @@ describe("status", () => { jest.restoreAllMocks(); }); - test("polls for status changes", async () => { + test("polls for channel changes", async () => { const pending1 = new Response(JSON.stringify({ state: "pending" }), { status: 202, }); @@ -25,16 +25,11 @@ describe("status", () => { .mockResolvedValueOnce(pending2) .mockResolvedValueOnce(completed); - const callbackSpy = jest.fn(); - - const res = await client.watchStatus({ + const res = await client.pollChannelTillCompleted({ channelToken: "some-channel-token", - onResponse: callbackSpy, }); - expect(res.response.status).toEqual(200); - expect(res.data).toEqual({ state: "completed" }); + expect(res).toEqual({ state: "completed" }); expect(fetchSpy).toHaveBeenCalledTimes(3); - expect(callbackSpy).toHaveBeenCalledTimes(2); }); }); diff --git a/packages/core/src/actions/app/pollChannelTillCompleted.ts b/packages/core/src/actions/app/pollChannelTillCompleted.ts new file mode 100644 index 0000000..98cb9b2 --- /dev/null +++ b/packages/core/src/actions/app/pollChannelTillCompleted.ts @@ -0,0 +1,38 @@ +import { AuthClientError } from "../../errors.js"; +import { type Client } from "../../clients/createClient.js"; +import { poll } from "../../clients/transports/http.js"; +import { type ChannelReturnType } from "./channel.js"; +import type { CompletedChannel } from "@farcaster/relay"; + +export type PollChannelTillCompletedParameters = { + channelToken: string; + timeout?: number; + interval?: number; +}; + +export type PollChannelTillCompletedReturnType = CompletedChannel; + +const path = "channel/status"; + +export const pollChannelTillCompleted = async ( + client: Client, + args: PollChannelTillCompletedParameters, +): Promise => { + for await (const polledData of poll( + client, + path, + { + timeout: args?.timeout ?? 300_000, + interval: args?.interval ?? 1000, + }, + { channelToken: args.channelToken }, + )) { + if (polledData.state === "completed") { + // type coercing to completed as if the response status is 200 + // it is expected to have a completed status. + return polledData; + } + } + // This error should not be thrown, as the `poll` function will throw an error on timeout + throw new AuthClientError("unknown", "unexpected error in `pollChannelTillCompleted`"); +}; diff --git a/packages/auth-client/src/actions/app/verifySignInMessage.test.ts b/packages/core/src/actions/app/verifySiweMessage.test.ts similarity index 60% rename from packages/auth-client/src/actions/app/verifySignInMessage.test.ts rename to packages/core/src/actions/app/verifySiweMessage.test.ts index 9fbe8c2..399fe27 100644 --- a/packages/auth-client/src/actions/app/verifySignInMessage.test.ts +++ b/packages/core/src/actions/app/verifySiweMessage.test.ts @@ -1,11 +1,11 @@ -import { createAppClient } from "../../clients/createAppClient"; -import { createWalletClient } from "../../clients/createWalletClient"; -import { viemConnector } from "../../clients/ethereum/viemConnector"; +import { createAppClient } from "../../clients/createAppClient.js"; +import { viemConnector } from "../../clients/ethereum/viemConnector.js"; import { privateKeyToAccount, generatePrivateKey } from "viem/accounts"; -import { AuthClientError } from "../../errors"; +import { AuthClientError } from "../../errors.js"; +import { createSiweMessage } from "../../utils/createSiweMessage.js"; import { JsonRpcProvider } from "ethers"; -describe("verifySignInMessage", () => { +describe("verifySiweMessage", () => { const client = createAppClient( { ethereum: viemConnector(), @@ -13,10 +13,6 @@ describe("verifySignInMessage", () => { new JsonRpcProvider("https://mainnet.optimism.io/", 10), ); - const walletClient = createWalletClient({ - ethereum: viemConnector(), - }); - const account = privateKeyToAccount(generatePrivateKey()); const siweParams = { @@ -29,49 +25,56 @@ describe("verifySignInMessage", () => { const { nonce, domain } = siweParams; test("verifies sign in message", async () => { - const { message } = walletClient.buildSignInMessage({ + const siweMessage = createSiweMessage({ ...siweParams, address: account.address, fid: 1234, }); const signature = await account.signMessage({ - message, + message: siweMessage.toMessage(), }); const errMsg = `Invalid resource: signer ${account.address} does not own fid 1234.`; const err = new AuthClientError("unauthorized", errMsg); - const { isError, error } = await client.verifySignInMessage({ - nonce, - domain, - message, - signature, - }); - expect(isError).toBe(true); - expect(error).toStrictEqual(err); + try { + await client.verifySiweMessage({ + nonce, + domain, + message: siweMessage.toMessage(), + signature, + }); + expect(true).toBe(false); + } catch (e) { + expect(e).toStrictEqual(err); + } }); test("verifies 1271 sign in message", async () => { const LGTM = "0xC89858205c6AdDAD842E1F58eD6c42452671885A"; - const { message } = walletClient.buildSignInMessage({ + const siweMessage = createSiweMessage({ ...siweParams, address: LGTM, fid: 1234, }); const signature = await account.signMessage({ - message, + message: siweMessage.toMessage(), }); const errMsg = `Invalid resource: signer ${LGTM} does not own fid 1234.`; const err = new AuthClientError("unauthorized", errMsg); - const { isError, error } = await client.verifySignInMessage({ - nonce, - domain, - message, - signature, - }); - expect(isError).toBe(true); - expect(error).toStrictEqual(err); + + try { + await client.verifySiweMessage({ + nonce, + domain, + message: siweMessage, + signature, + }); + expect(true).toBe(false); + } catch (e) { + expect(e).toStrictEqual(err); + } }); }); diff --git a/packages/core/src/actions/app/verifySiweMessage.ts b/packages/core/src/actions/app/verifySiweMessage.ts new file mode 100644 index 0000000..a639ccc --- /dev/null +++ b/packages/core/src/actions/app/verifySiweMessage.ts @@ -0,0 +1,29 @@ +import { type Client } from "../../clients/createClient.js"; +import { + type VerifySiweMessageWithVerifierReturnType, + type VerifySiweMessageWithVerifierParameters, + verifySiweMessageWithVerifier as util_verifySiweMessage, +} from "../../utils/verifySiweMessageWithVerifier.js"; +import type { Omit } from "../../types/utils.js"; +import type { Provider } from "ethers"; + +export type VerifySiweMessageParameters = Omit; + +export type VerifySiweMessageReturnType = VerifySiweMessageWithVerifierReturnType; + +export const verifySiweMessage = ( + client: Client, + { nonce, domain, message, signature }: VerifySiweMessageParameters, + provider?: Provider, +): Promise => { + return util_verifySiweMessage({ + nonce, + domain, + message, + signature, + verifier: { + getFid: client.ethereum.getFid, + provider: provider, + }, + }); +}; diff --git a/packages/auth-client/src/actions/auth/authenticate.test.ts b/packages/core/src/actions/auth/authenticate.test.ts similarity index 80% rename from packages/auth-client/src/actions/auth/authenticate.test.ts rename to packages/core/src/actions/auth/authenticate.test.ts index 3f217f8..98cc08f 100644 --- a/packages/auth-client/src/actions/auth/authenticate.test.ts +++ b/packages/core/src/actions/auth/authenticate.test.ts @@ -1,7 +1,7 @@ -import { createWalletClient } from "../../clients/createWalletClient"; +import { createWalletClient } from "../../clients/createWalletClient.js"; import { jest } from "@jest/globals"; -import { viemConnector } from "../../clients/ethereum/viemConnector"; -import { AuthenticateAPIResponse } from "./authenticate"; +import { viemConnector } from "../../clients/ethereum/viemConnector.js"; +import { type AuthenticateReturnType } from "./authenticate.js"; describe("authenticate", () => { const client = createWalletClient({ @@ -21,8 +21,8 @@ describe("authenticate", () => { const displayName = "Alice Teapot"; const pfpUrl = "https://example.com/alice.png"; - const statusResponseDataStub: AuthenticateAPIResponse = { - state: "completed", + const statusResponseDataStub: AuthenticateReturnType = { + status: "completed", nonce: "abcd1234", url: "https://warpcast.com/~/sign-in-with-farcaster?nonce=abcd1234[...]", message, @@ -32,11 +32,12 @@ describe("authenticate", () => { bio, displayName, pfpUrl, + verifications: [], + custody: "0x0000000000000000000000000000000000000000", }; test("constructs API request", async () => { - const response = new Response(JSON.stringify(statusResponseDataStub)); - const spy = jest.spyOn(global, "fetch").mockResolvedValue(response); + const spy = jest.spyOn(global, "fetch").mockResolvedValue(new Response(JSON.stringify(statusResponseDataStub))); const res = await client.authenticate({ authKey: "some-auth-key", @@ -50,7 +51,7 @@ describe("authenticate", () => { pfpUrl, }); - expect(res.response).toEqual(response); + expect(res).toEqual(statusResponseDataStub); expect(spy).toHaveBeenCalledTimes(1); expect(spy).toHaveBeenCalledWith("https://relay.farcaster.xyz/v1/channel/authenticate", { method: "POST", diff --git a/packages/core/src/actions/auth/authenticate.ts b/packages/core/src/actions/auth/authenticate.ts new file mode 100644 index 0000000..4039289 --- /dev/null +++ b/packages/core/src/actions/auth/authenticate.ts @@ -0,0 +1,21 @@ +import { type ChannelAuthenticateParameters, type ChannelAuthenticateReturnType } from "@farcaster/relay"; +import { post } from "../../clients/transports/http.js"; +import { type Client } from "../../clients/createClient.js"; + +export type AuthenticateParameters = ChannelAuthenticateParameters & { channelToken: string; authKey: string }; + +export type AuthenticateReturnType = ChannelAuthenticateReturnType; + +const path = "channel/authenticate"; + +export const authenticate = async ( + client: Client, + { channelToken, authKey, ...request }: AuthenticateParameters, +): Promise => { + return post, AuthenticateReturnType>(client, path, request, { + channelToken, + headers: { + "X-Farcaster-Auth-Relay-Key": authKey, + }, + }); +}; diff --git a/packages/auth-client/src/clients/createAppClient.test.ts b/packages/core/src/clients/createAppClient.test.ts similarity index 84% rename from packages/auth-client/src/clients/createAppClient.test.ts rename to packages/core/src/clients/createAppClient.test.ts index bc3ee29..da5b089 100644 --- a/packages/auth-client/src/clients/createAppClient.test.ts +++ b/packages/core/src/clients/createAppClient.test.ts @@ -1,5 +1,5 @@ -import { createAppClient, AppClient } from "./createAppClient"; -import { viemConnector } from "./ethereum/viemConnector"; +import { createAppClient, type AppClient } from "./createAppClient.js"; +import { viemConnector } from "./ethereum/viemConnector.js"; describe("createAppClient", () => { const config = { diff --git a/packages/core/src/clients/createAppClient.ts b/packages/core/src/clients/createAppClient.ts new file mode 100644 index 0000000..b6bf3fc --- /dev/null +++ b/packages/core/src/clients/createAppClient.ts @@ -0,0 +1,36 @@ +import { + createChannel, + type CreateChannelParameters, + type CreateChannelReturnType, +} from "../actions/app/createChannel.js"; +import { channel, type ChannelParameters, type ChannelReturnType } from "../actions/app/channel.js"; +import { + pollChannelTillCompleted, + type PollChannelTillCompletedParameters, + type PollChannelTillCompletedReturnType, +} from "../actions/app/pollChannelTillCompleted.js"; +import { + verifySiweMessage, + type VerifySiweMessageParameters, + type VerifySiweMessageReturnType, +} from "../actions/app/verifySiweMessage.js"; +import { type Client, type CreateClientParameters, createClient } from "./createClient.js"; +import { type Provider } from "ethers"; + +export interface AppClient extends Client { + createChannel: (args: CreateChannelParameters) => Promise; + channel: (args: ChannelParameters) => Promise; + pollChannelTillCompleted: (args: PollChannelTillCompletedParameters) => Promise; + verifySiweMessage: (args: VerifySiweMessageParameters) => Promise; +} + +export const createAppClient = (config: CreateClientParameters, provider?: Provider): AppClient => { + const client = createClient(config); + return { + ...client, + createChannel: (args: CreateChannelParameters) => createChannel(client, args), + channel: (args: ChannelParameters) => channel(client, args), + pollChannelTillCompleted: (args: PollChannelTillCompletedParameters) => pollChannelTillCompleted(client, args), + verifySiweMessage: (args: VerifySiweMessageParameters) => verifySiweMessage(client, args, provider), + }; +}; diff --git a/packages/auth-client/src/clients/createClient.test.ts b/packages/core/src/clients/createClient.test.ts similarity index 89% rename from packages/auth-client/src/clients/createClient.test.ts rename to packages/core/src/clients/createClient.test.ts index 07d673c..eae6633 100644 --- a/packages/auth-client/src/clients/createClient.test.ts +++ b/packages/core/src/clients/createClient.test.ts @@ -1,5 +1,5 @@ -import { createClient, Client } from "./createClient"; -import { viemConnector } from "./ethereum/viemConnector"; +import { createClient, type Client } from "./createClient.js"; +import { viemConnector } from "./ethereum/viemConnector.js"; describe("createClient", () => { const ethereum = viemConnector(); diff --git a/packages/auth-client/src/clients/createClient.ts b/packages/core/src/clients/createClient.ts similarity index 75% rename from packages/auth-client/src/clients/createClient.ts rename to packages/core/src/clients/createClient.ts index 167c4c4..132d4db 100644 --- a/packages/auth-client/src/clients/createClient.ts +++ b/packages/core/src/clients/createClient.ts @@ -1,7 +1,6 @@ -import { EthereumConnector } from "./ethereum/connector"; -import type { Provider } from "ethers"; +import { type EthereumConnector } from "./ethereum/connector.js"; -export interface CreateClientArgs { +export interface CreateClientParameters { relay?: string; version?: string; ethereum: EthereumConnector; @@ -22,7 +21,7 @@ const configDefaults = { version: "v1", }; -export const createClient = ({ ethereum, ...config }: CreateClientArgs) => { +export const createClient = ({ ethereum, ...config }: CreateClientParameters) => { return { config: { ...configDefaults, ...config }, ethereum, diff --git a/packages/auth-client/src/clients/createWalletClient.test.ts b/packages/core/src/clients/createWalletClient.test.ts similarity index 83% rename from packages/auth-client/src/clients/createWalletClient.test.ts rename to packages/core/src/clients/createWalletClient.test.ts index 00d7845..2d186b5 100644 --- a/packages/auth-client/src/clients/createWalletClient.test.ts +++ b/packages/core/src/clients/createWalletClient.test.ts @@ -1,5 +1,5 @@ -import { createWalletClient, WalletClient } from "./createWalletClient"; -import { viemConnector } from "./ethereum/viemConnector"; +import { createWalletClient, type WalletClient } from "./createWalletClient.js"; +import { viemConnector } from "./ethereum/viemConnector.js"; describe("createWalletClient", () => { const config = { diff --git a/packages/core/src/clients/createWalletClient.ts b/packages/core/src/clients/createWalletClient.ts new file mode 100644 index 0000000..2c66460 --- /dev/null +++ b/packages/core/src/clients/createWalletClient.ts @@ -0,0 +1,18 @@ +import { + authenticate, + type AuthenticateParameters, + type AuthenticateReturnType, +} from "../actions/auth/authenticate.js"; +import { type Client, type CreateClientParameters, createClient } from "./createClient.js"; + +export interface WalletClient extends Client { + authenticate: (args: AuthenticateParameters) => Promise; +} + +export const createWalletClient = (config: CreateClientParameters): WalletClient => { + const client = createClient(config); + return { + ...client, + authenticate: (args: AuthenticateParameters) => authenticate(client, args), + }; +}; diff --git a/packages/core/src/clients/ethereum/connector.ts b/packages/core/src/clients/ethereum/connector.ts new file mode 100644 index 0000000..2b0da79 --- /dev/null +++ b/packages/core/src/clients/ethereum/connector.ts @@ -0,0 +1,5 @@ +import { type Hex } from "viem"; + +export interface EthereumConnector { + getFid: (custody: Hex) => Promise; +} diff --git a/packages/core/src/clients/ethereum/index.ts b/packages/core/src/clients/ethereum/index.ts new file mode 100644 index 0000000..fbe1e47 --- /dev/null +++ b/packages/core/src/clients/ethereum/index.ts @@ -0,0 +1 @@ +export * from "./viemConnector.js"; diff --git a/packages/auth-client/src/clients/ethereum/viemConnector.ts b/packages/core/src/clients/ethereum/viemConnector.ts similarity index 73% rename from packages/auth-client/src/clients/ethereum/viemConnector.ts rename to packages/core/src/clients/ethereum/viemConnector.ts index c13a629..dededc7 100644 --- a/packages/auth-client/src/clients/ethereum/viemConnector.ts +++ b/packages/core/src/clients/ethereum/viemConnector.ts @@ -1,7 +1,7 @@ -import { Hex, createPublicClient, http } from "viem"; +import { type Hex, createPublicClient, http } from "viem"; import { optimism } from "viem/chains"; -import { ID_REGISTRY_ADDRESS, idRegistryABI } from "../../contracts/idRegistry"; -import { EthereumConnector } from "./connector"; +import { ID_REGISTRY_ADDRESS, idRegistryABI } from "../../contracts/idRegistry.js"; +import { type EthereumConnector } from "./connector.js"; interface ViemConfigArgs { rpcUrl?: string; @@ -13,7 +13,7 @@ export const viemConnector = (args?: ViemConfigArgs): EthereumConnector => { transport: http(args?.rpcUrl), }); - const getFid = async (custody: Hex): Promise => { + const getFid = async (custody: Hex): Promise => { return publicClient.readContract({ address: ID_REGISTRY_ADDRESS, abi: idRegistryABI, diff --git a/packages/core/src/clients/index.ts b/packages/core/src/clients/index.ts new file mode 100644 index 0000000..2aeea97 --- /dev/null +++ b/packages/core/src/clients/index.ts @@ -0,0 +1,5 @@ +export * from "./createAppClient.js"; +export * from "./createWalletClient.js"; +export * from "./createClient.js"; +export * from "./ethereum/index.js"; +export * from "./transports/index.js"; diff --git a/packages/auth-client/src/clients/transports/http.test.ts b/packages/core/src/clients/transports/http.test.ts similarity index 65% rename from packages/auth-client/src/clients/transports/http.test.ts rename to packages/core/src/clients/transports/http.test.ts index 6ef0196..12f95af 100644 --- a/packages/auth-client/src/clients/transports/http.test.ts +++ b/packages/core/src/clients/transports/http.test.ts @@ -1,6 +1,6 @@ -import { createClient } from "../createClient"; -import { viemConnector } from "../ethereum/viemConnector"; -import { get, poll, post } from "./http"; +import { createClient } from "../createClient.js"; +import { viemConnector } from "../ethereum/viemConnector.js"; +import { get, poll, post } from "./http.js"; import { jest } from "@jest/globals"; describe("http", () => { @@ -23,20 +23,10 @@ describe("http", () => { }); describe("get", () => { - test("returns fetch response", async () => { - jest.spyOn(global, "fetch").mockResolvedValue(httpResponse); - - const res = await get(client, "path"); - const { response } = res._unsafeUnwrap(); - - expect(response).toEqual(httpResponse); - }); - test("returns parsed body data", async () => { jest.spyOn(global, "fetch").mockResolvedValue(httpResponse); - const res = await get(client, "path"); - const { data } = res._unsafeUnwrap(); + const data = await get(client, "path"); expect(data).toEqual(bodyData); }); @@ -76,20 +66,18 @@ describe("http", () => { jest.spyOn(global, "fetch").mockResolvedValue(httpResponse); const requestData = { data: "request stub" }; - const res = await post(client, "path", requestData); + const data = await post(client, "path", requestData); - const { response } = res._unsafeUnwrap(); - expect(response).toEqual(httpResponse); + expect(data).toEqual(bodyData); }); test("returns parsed body data", async () => { jest.spyOn(global, "fetch").mockResolvedValue(httpResponse); const requestData = { data: "request stub" }; - const res = await post(client, "path", requestData); + const data = await post(client, "path", requestData); - const { data } = res._unsafeUnwrap(); - expect(data).toEqual(data); + expect(data).toEqual(bodyData); }); test("constructs fetch request", async () => { @@ -116,28 +104,30 @@ describe("http", () => { describe("poll", () => { test("polls for success response", async () => { - const accepted1 = new Response(JSON.stringify({ state: "pending" }), { - status: 202, - }); - const accepted2 = new Response(JSON.stringify({ state: "pending" }), { - status: 202, + let i = 0; + const spy = jest.spyOn(global, "fetch").mockImplementation(async () => { + if (i === 2) + return new Response(JSON.stringify({ state: "completed" }), { + status: 200, + }); + i++; + return new Response(JSON.stringify({ state: "pending" }), { + status: 202, + }); }); - const ok = new Response(JSON.stringify({ state: "completed" }), { - status: 200, - }); - - const spy = jest - .spyOn(global, "fetch") - .mockResolvedValueOnce(accepted1) - .mockResolvedValueOnce(accepted2) - .mockResolvedValueOnce(ok); - - const res = await poll(client, "path"); + // .mockResolvedValueOnce(accepted1) + // .mockResolvedValueOnce(accepted2) + // .mockResolvedValueOnce(ok); + + let data: { state: string } = { + state: "error", + }; + for await (const generatorResponse of poll(client, "path", { interval: 100 })) { + data = generatorResponse; + if (generatorResponse.state === "completed") break; + } expect(spy).toHaveBeenCalledTimes(3); - expect(res.isOk()).toBe(true); - const { response, data } = res._unsafeUnwrap(); - expect(response.status).toBe(200); expect(data).toEqual({ state: "completed" }); }); @@ -148,9 +138,14 @@ describe("http", () => { jest.spyOn(global, "fetch").mockResolvedValue(accepted); - const res = await poll(client, "path", { timeout: 1, interval: 1 }); - expect(res.isErr()).toBe(true); - expect(res._unsafeUnwrapErr().message).toBe("Polling timed out after 1ms"); + let i = 0; + try { + for await (const _generatorResponse of poll(client, "path", { timeout: 1, interval: 1 })) { + if (i++ === 1) expect(true).toBe(false); + } + } catch (e: unknown) { + expect((e as Error).message).toBe("Polling timed out after 1ms"); + } }); }); }); diff --git a/packages/core/src/clients/transports/http.ts b/packages/core/src/clients/transports/http.ts new file mode 100644 index 0000000..8ccd613 --- /dev/null +++ b/packages/core/src/clients/transports/http.ts @@ -0,0 +1,104 @@ +import { type Client } from "../createClient.js"; +import { AuthClientError } from "../../errors.js"; + +export interface HttpOpts { + channelToken?: string; + headers?: Record; +} + +export interface PollOpts { + interval?: number; + timeout?: number; + conditionToReturn?: (data: BodyType) => boolean; +} + +export interface HttpResponse { + response: Response; + data: ResponseDataType; +} + +export type AsyncHttpResponse = Promise>; + +const defaultPollOpts = { + interval: 1000, + timeout: 10000, +}; + +export const get = async ( + client: Client, + path: string, + opts?: HttpOpts, +): Promise => { + try { + const response = await fetch(getURI(client, path), { + headers: getHeaders(opts), + }); + + if (!response.ok) { + throw new AuthClientError("unknown", new Error(response.statusText)); + } + + return await response.json(); + } catch (error) { + throw new AuthClientError("unknown", error as Error); + } +}; + +export const post = async ( + client: Client, + path: string, + parameters: BodyType, + opts?: HttpOpts, +): Promise => { + try { + const response = await fetch(getURI(client, path), { + method: "POST", + body: JSON.stringify(parameters), + headers: getHeaders(opts), + }); + + if (!response.ok) { + throw new AuthClientError("unknown", new Error(response.statusText)); + } + + return await response.json(); + } catch (error) { + throw new AuthClientError("unknown", error as Error); + } +}; + +export async function* poll( + client: Client, + path: string, + pollOpts?: PollOpts, + opts?: HttpOpts, +): AsyncGenerator { + const { timeout, interval } = { + ...defaultPollOpts, + ...pollOpts, + }; + + const deadline = Date.now() + timeout; + + while (Date.now() < deadline) { + const data = await get(client, path, opts); + if (pollOpts?.conditionToReturn?.(data)) return data; + yield data; + await new Promise((resolve) => setTimeout(resolve, interval)); + } + throw new AuthClientError("unavailable", `Polling timed out after ${timeout}ms`); +} + +const getURI = (client: Client, path: string) => { + return `${client.config.relay}/${client.config.version}/${path}`; +}; + +const getHeaders = (opts?: HttpOpts) => { + const headers = { + ...opts?.headers, + }; + if (opts?.channelToken) { + headers["Authorization"] = `Bearer ${opts.channelToken}`; + } + return { ...headers, "Content-Type": "application/json" }; +}; diff --git a/packages/core/src/clients/transports/index.ts b/packages/core/src/clients/transports/index.ts new file mode 100644 index 0000000..080c36c --- /dev/null +++ b/packages/core/src/clients/transports/index.ts @@ -0,0 +1 @@ +export * from "./http.js"; diff --git a/packages/auth-client/src/contracts/idRegistry.ts b/packages/core/src/contracts/idRegistry.ts similarity index 100% rename from packages/auth-client/src/contracts/idRegistry.ts rename to packages/core/src/contracts/idRegistry.ts diff --git a/packages/auth-client/src/errors.ts b/packages/core/src/errors.ts similarity index 74% rename from packages/auth-client/src/errors.ts rename to packages/core/src/errors.ts index 781e12c..d8b5c31 100644 --- a/packages/auth-client/src/errors.ts +++ b/packages/core/src/errors.ts @@ -1,5 +1,3 @@ -import { Result } from "neverthrow"; - interface AuthClientErrorOpts { message: string; cause: Error | AuthClientError; @@ -61,28 +59,3 @@ export type AuthClientErrorCode = | "unavailable" /* An unknown error was encountered */ | "unknown"; - -/** Type alias for shorthand when handling errors */ -export type AuthClientResult = Result; -export type AuthClientAsyncResult = Promise>; -export type NoneOf = { - [K in keyof T]: never; -}; -export type Unwrapped = - | (T & { - isError: false; - error?: never; - }) - | (NoneOf & { - isError: true; - error?: AuthClientError; - }); -export type AsyncUnwrapped = Promise>; - -export const unwrap = (result: AuthClientResult): Unwrapped => { - if (result.isErr()) { - return { error: result.error, isError: true }; - } else { - return { ...result.value, isError: false }; - } -}; diff --git a/packages/core/src/exports/actions.ts b/packages/core/src/exports/actions.ts new file mode 100644 index 0000000..449ecfa --- /dev/null +++ b/packages/core/src/exports/actions.ts @@ -0,0 +1,5 @@ +export * from "../actions/app/createChannel.js"; +export * from "../actions/app/pollChannelTillCompleted.js"; +export * from "../actions/app/channel.js"; +export * from "../actions/app/verifySiweMessage.js"; +export * from "../actions/auth/authenticate.js"; diff --git a/packages/core/src/exports/clients.ts b/packages/core/src/exports/clients.ts new file mode 100644 index 0000000..cf60f65 --- /dev/null +++ b/packages/core/src/exports/clients.ts @@ -0,0 +1 @@ +export * from "../clients/index.js"; diff --git a/packages/core/src/exports/contracts.ts b/packages/core/src/exports/contracts.ts new file mode 100644 index 0000000..1cd506e --- /dev/null +++ b/packages/core/src/exports/contracts.ts @@ -0,0 +1 @@ +export * from "../contracts/idRegistry.js"; diff --git a/packages/core/src/exports/errors.ts b/packages/core/src/exports/errors.ts new file mode 100644 index 0000000..2b2c82d --- /dev/null +++ b/packages/core/src/exports/errors.ts @@ -0,0 +1 @@ +export * from "../errors.js"; diff --git a/packages/core/src/exports/index.ts b/packages/core/src/exports/index.ts new file mode 100644 index 0000000..40c05a4 --- /dev/null +++ b/packages/core/src/exports/index.ts @@ -0,0 +1,5 @@ +export * from "./actions.js"; +export * from "./clients.js"; +export * from "./contracts.js"; +export * from "./errors.js"; +export * from "./utils.js"; diff --git a/packages/core/src/exports/utils.ts b/packages/core/src/exports/utils.ts new file mode 100644 index 0000000..78d3638 --- /dev/null +++ b/packages/core/src/exports/utils.ts @@ -0,0 +1,11 @@ +export * from "../utils/constants.js"; +export * from "../utils/createSiweMessage.js"; +export * from "../utils/createSiweMessageFromSignInURI.js"; +export * from "../utils/getFidFromSiweMessage.js"; +export * from "../utils/getResourcesFromSiweMessage.js"; +export * from "../utils/getSiweMessage.js"; +export * from "../utils/getSiweMessageFromSignInURI.js"; +export * from "../utils/validateSiweMessageChainId.js"; +export * from "../utils/validateSiweMessageResources.js"; +export * from "../utils/validateSiweMessageStatement.js"; +export * from "../utils/verifySiweMessageWithVerifier.js"; diff --git a/packages/core/src/types/address.ts b/packages/core/src/types/address.ts new file mode 100644 index 0000000..f64ddbb --- /dev/null +++ b/packages/core/src/types/address.ts @@ -0,0 +1 @@ +export type Address = `0x${string}`; diff --git a/packages/core/src/types/utils.ts b/packages/core/src/types/utils.ts new file mode 100644 index 0000000..05c4c6c --- /dev/null +++ b/packages/core/src/types/utils.ts @@ -0,0 +1,16 @@ +// Copied from https://github.com/wevm/wagmi/blob/main/packages/core/src/types/utils.ts +/** Combines members of an intersection into a readable type. */ +// https://twitter.com/mattpocockuk/status/1622730173446557697?s=20&t=NdpAcmEFXY01xkqU3KO0Mg +export type Evaluate = { [key in keyof type]: type[key] } & unknown; + +/** + * Makes all properties of an object optional. + * + * Compatible with [`exactOptionalPropertyTypes`](https://www.typescriptlang.org/tsconfig#exactOptionalPropertyTypes). + */ +export type ExactPartial = { + [key in keyof type]?: type[key] | undefined; +}; + +/** Strict version of built-in Omit type */ +export type Omit = Pick>; diff --git a/packages/auth-client/src/messages/constants.ts b/packages/core/src/utils/constants.ts similarity index 51% rename from packages/auth-client/src/messages/constants.ts rename to packages/core/src/utils/constants.ts index a56f9b7..0e36174 100644 --- a/packages/auth-client/src/messages/constants.ts +++ b/packages/core/src/utils/constants.ts @@ -1,2 +1,3 @@ export const STATEMENT = "Farcaster Auth"; export const CHAIN_ID = 10; +export const FID_URI_REGEX = /^farcaster:\/\/fid\/([1-9]\d*)\/?$/; diff --git a/packages/core/src/utils/createSiweMessage.ts b/packages/core/src/utils/createSiweMessage.ts new file mode 100644 index 0000000..d530b99 --- /dev/null +++ b/packages/core/src/utils/createSiweMessage.ts @@ -0,0 +1,25 @@ +import { SiweMessage } from "siwe"; +import { AuthClientError } from "../errors.js"; +import { STATEMENT, CHAIN_ID } from "./constants.js"; +import { getSiweMessage } from "./getSiweMessage.js"; + +export type FarcasterResourceParameters = { fid: number }; +export type CreateSiweMessageParameters = Partial & FarcasterResourceParameters; + +export const createSiweMessage = (parameters: CreateSiweMessageParameters): SiweMessage => { + try { + const { fid, ...siweParameters } = parameters; + const resources = siweParameters.resources ?? []; + siweParameters.version = "1"; + siweParameters.statement = STATEMENT; + siweParameters.chainId = CHAIN_ID; + siweParameters.resources = [createFidResource(fid), ...resources]; + return getSiweMessage({ message: siweParameters }); + } catch (e) { + throw new AuthClientError("bad_request.validation_failure", e as Error); + } +}; + +const createFidResource = (fid: number): string => { + return `farcaster://fid/${fid}`; +}; diff --git a/packages/core/src/utils/createSiweMessageFromSignInURI.ts b/packages/core/src/utils/createSiweMessageFromSignInURI.ts new file mode 100644 index 0000000..e553284 --- /dev/null +++ b/packages/core/src/utils/createSiweMessageFromSignInURI.ts @@ -0,0 +1,10 @@ +import { SiweMessage } from "siwe"; +import { createSiweMessage } from "./createSiweMessage.js"; +import { getSiweMessageFromSignInURI } from "./getSiweMessageFromSignInURI.js"; + +export type CreateSiweMessageFromSignInURIParameters = { uri: string; fid: number }; + +export const createSiweMessageFromSignInURI = ({ uri, fid }: CreateSiweMessageFromSignInURIParameters): SiweMessage => { + const parsedSignInURI = getSiweMessageFromSignInURI({ uri }); + return createSiweMessage({ ...parsedSignInURI.params, fid }); +}; diff --git a/packages/core/src/utils/getFidFromSiweMessage.ts b/packages/core/src/utils/getFidFromSiweMessage.ts new file mode 100644 index 0000000..2ad9abd --- /dev/null +++ b/packages/core/src/utils/getFidFromSiweMessage.ts @@ -0,0 +1,18 @@ +import { SiweMessage } from "siwe"; +import { AuthClientError } from "../errors.js"; +import { FID_URI_REGEX } from "./constants.js"; + +export type GetFidFromSiweMessageParameters = { message: SiweMessage }; +export const getFidFromSiweMessage = ({ message }: GetFidFromSiweMessageParameters): number => { + const resource = (message.resources ?? []).find((resource) => { + return FID_URI_REGEX.test(resource); + }); + if (!resource) { + throw new AuthClientError("bad_request.validation_failure", "No fid resource provided"); + } + const fid = parseInt(resource.match(FID_URI_REGEX)?.[1] ?? ""); + if (Number.isNaN(fid)) { + throw new AuthClientError("bad_request.validation_failure", "Invalid fid"); + } + return fid; +}; diff --git a/packages/core/src/utils/getResourcesFromSiweMessage.ts b/packages/core/src/utils/getResourcesFromSiweMessage.ts new file mode 100644 index 0000000..9961d83 --- /dev/null +++ b/packages/core/src/utils/getResourcesFromSiweMessage.ts @@ -0,0 +1,10 @@ +import { SiweMessage } from "siwe"; +import { type FarcasterResourceParameters } from "./createSiweMessage.js"; +import { getFidFromSiweMessage } from "./getFidFromSiweMessage.js"; + +export type GetResourcesFromSiweMessageParameters = { message: SiweMessage }; +export const getResourcesFromSiweMessage = ({ + message, +}: GetResourcesFromSiweMessageParameters): FarcasterResourceParameters => { + return { fid: getFidFromSiweMessage({ message }) }; +}; diff --git a/packages/core/src/utils/getSiweMessage.test.ts b/packages/core/src/utils/getSiweMessage.test.ts new file mode 100644 index 0000000..02d1528 --- /dev/null +++ b/packages/core/src/utils/getSiweMessage.test.ts @@ -0,0 +1,121 @@ +import { getSiweMessage } from "./getSiweMessage.js"; +import { AuthClientError } from "../errors.js"; + +const siweParams = { + domain: "example.com", + address: "0x63C378DDC446DFf1d831B9B96F7d338FE6bd4231", + uri: "https://example.com/login", + version: "1", + nonce: "12345678", + issuedAt: "2023-10-01T00:00:00.000Z", +}; + +const authParams = { + ...siweParams, + statement: "Farcaster Auth", + chainId: 10, + resources: ["farcaster://fid/1234"], +}; + +describe("getSiweMessage", () => { + test("default parameters are valid", () => { + expect(() => getSiweMessage({ message: authParams })).not.toThrow(); + }); + + test("propagates SIWE message errors", () => { + try { + getSiweMessage({ + message: { + ...authParams, + address: "Invalid address", + }, + }); + expect(true).toBe(false); + } catch (e) { + expect(e).toBeInstanceOf(AuthClientError); + if (!(e instanceof AuthClientError)) throw new Error("unexpected"); + + expect(e.errCode).toEqual("bad_request.validation_failure"); + expect(e.message).toMatch("invalid address"); + } + }); + + test("message must contain 'Farcaster Auth'", () => { + try { + getSiweMessage({ + message: { + ...authParams, + statement: "Invalid statement", + }, + }); + expect(true).toBe(false); + } catch (e) { + expect(e).toBeInstanceOf(AuthClientError); + if (!(e instanceof AuthClientError)) throw new Error("unexpected"); + + expect(e).toEqual(new AuthClientError("bad_request.validation_failure", "Statement must be 'Farcaster Auth'")); + } + }); + + test("statement allows 'Farcaster Connect'", () => { + expect(() => + getSiweMessage({ + message: { + ...authParams, + statement: "Farcaster Connect", + }, + }), + ).not.toThrow(); + }); + + test("message must include chainId 10", () => { + try { + getSiweMessage({ + message: { + ...authParams, + chainId: 1, + }, + }); + expect(true).toBe(false); + } catch (e) { + expect(e).toBeInstanceOf(AuthClientError); + if (!(e instanceof AuthClientError)) throw new Error("unexpected"); + + expect(e).toEqual(new AuthClientError("bad_request.validation_failure", "Chain ID must be 10")); + } + }); + + test("message must include FID resource", () => { + try { + getSiweMessage({ + message: { + ...authParams, + resources: [], + }, + }); + expect(true).toBe(false); + } catch (e) { + expect(e).toBeInstanceOf(AuthClientError); + if (!(e instanceof AuthClientError)) throw new Error("unexpected"); + + expect(e).toEqual(new AuthClientError("bad_request.validation_failure", "No fid resource provided")); + } + }); + + test("message must only include one FID resource", () => { + try { + getSiweMessage({ + message: { + ...authParams, + resources: ["farcaster://fid/1", "farcaster://fid/2"], + }, + }); + expect(true).toBe(false); + } catch (e) { + expect(e).toBeInstanceOf(AuthClientError); + if (!(e instanceof AuthClientError)) throw new Error("unexpected"); + + expect(e).toEqual(new AuthClientError("bad_request.validation_failure", "Multiple fid resources provided")); + } + }); +}); diff --git a/packages/core/src/utils/getSiweMessage.ts b/packages/core/src/utils/getSiweMessage.ts new file mode 100644 index 0000000..0424ded --- /dev/null +++ b/packages/core/src/utils/getSiweMessage.ts @@ -0,0 +1,18 @@ +import { SiweMessage } from "siwe"; +import { AuthClientError } from "../errors.js"; +import { validateSiweMessageChainId } from "./validateSiweMessageChainId.js"; +import { validateSiweMessageResources } from "./validateSiweMessageResources.js"; +import { validateSiweMessageStatement } from "./validateSiweMessageStatement.js"; + +export type GetSiweMessageParameters = { message: string | Partial }; +export const getSiweMessage = (parameters: GetSiweMessageParameters): SiweMessage => { + try { + const message = new SiweMessage(parameters.message); + validateSiweMessageStatement({ message }); + validateSiweMessageChainId({ message }); + validateSiweMessageResources({ message }); + return message; + } catch (e) { + throw new AuthClientError("bad_request.validation_failure", e as Error); + } +}; diff --git a/packages/auth-client/src/actions/auth/parseSignInURI.test.ts b/packages/core/src/utils/getSiweMessageFromSignInURI.test.ts similarity index 58% rename from packages/auth-client/src/actions/auth/parseSignInURI.test.ts rename to packages/core/src/utils/getSiweMessageFromSignInURI.test.ts index 7a0f787..7b10746 100644 --- a/packages/auth-client/src/actions/auth/parseSignInURI.test.ts +++ b/packages/core/src/utils/getSiweMessageFromSignInURI.test.ts @@ -1,14 +1,8 @@ -import { createWalletClient } from "../../clients/createWalletClient"; -import { viemConnector } from "../../clients/ethereum/viemConnector"; - -describe("parseSignInURI", () => { - const client = createWalletClient({ - relay: "https://relay.farcaster.xyz", - ethereum: viemConnector(), - }); +import { getSiweMessageFromSignInURI } from "./getSiweMessageFromSignInURI.js"; +describe("getSiweMessageFromSignInURI", () => { test("parses sign in params from protocol URI", async () => { - const { channelToken, params } = client.parseSignInURI({ + const { channelToken, params } = getSiweMessageFromSignInURI({ uri: "https://warpcast.com/~/sign-in-with-farcaster?channelToken=76be6229-bdf7-4ad2-930a-540fb2de1e08&nonce=ESsxs6MaFio7OvqWb&siweUri=https%3A%2F%2Fexample.com%2Flogin&domain=example.com", }); diff --git a/packages/core/src/utils/getSiweMessageFromSignInURI.ts b/packages/core/src/utils/getSiweMessageFromSignInURI.ts new file mode 100644 index 0000000..d32f58e --- /dev/null +++ b/packages/core/src/utils/getSiweMessageFromSignInURI.ts @@ -0,0 +1,35 @@ +import { AuthClientError } from "../errors.js"; +import { type CreateSiweMessageParameters } from "./createSiweMessage.js"; + +export type GetSiweMessageFromSignInURIParameters = { uri: string }; + +export type GetSiweMessageFromSignInURIReturnType = { + channelToken: string; + params: Partial; +}; + +export const getSiweMessageFromSignInURI = ({ + uri, +}: GetSiweMessageFromSignInURIParameters): GetSiweMessageFromSignInURIReturnType => { + const url = new URL(uri); + const searchParams = Object.fromEntries(url.searchParams.entries()); + const { channelToken, ...params } = searchParams; + if (!channelToken) { + throw validationFail("No channel token provided"); + } + if (!params["nonce"]) { + throw validationFail("No nonce provided"); + } + if (!params["siweUri"]) { + throw validationFail("No SIWE URI provided"); + } + if (!params["domain"]) { + throw validationFail("No domain provided"); + } + const { siweUri, ...siweParameters } = params; + return { channelToken, params: { uri: siweUri, ...siweParameters } }; +}; + +const validationFail = (message: string): AuthClientError => { + return new AuthClientError("bad_request.validation_failure", message); +}; diff --git a/packages/core/src/utils/validateSiweMessageChainId.ts b/packages/core/src/utils/validateSiweMessageChainId.ts new file mode 100644 index 0000000..51ed96b --- /dev/null +++ b/packages/core/src/utils/validateSiweMessageChainId.ts @@ -0,0 +1,10 @@ +import { SiweMessage } from "siwe"; +import { AuthClientError } from "../errors.js"; +import { CHAIN_ID } from "./constants.js"; + +type ValidateSiweMessageChainIdParameters = { message: SiweMessage }; +export const validateSiweMessageChainId = ({ message }: ValidateSiweMessageChainIdParameters): void => { + if (message.chainId !== CHAIN_ID) { + throw new AuthClientError("bad_request.validation_failure", `Chain ID must be ${CHAIN_ID}`); + } +}; diff --git a/packages/core/src/utils/validateSiweMessageResources.ts b/packages/core/src/utils/validateSiweMessageResources.ts new file mode 100644 index 0000000..e26d22c --- /dev/null +++ b/packages/core/src/utils/validateSiweMessageResources.ts @@ -0,0 +1,16 @@ +import { SiweMessage } from "siwe"; +import { AuthClientError } from "../errors.js"; +import { FID_URI_REGEX } from "./constants.js"; + +type ValidateSiweMessageResourcesParameters = { message: SiweMessage }; +export const validateSiweMessageResources = ({ message }: ValidateSiweMessageResourcesParameters): void => { + const fidResources = (message.resources ?? []).filter((resource) => { + return FID_URI_REGEX.test(resource); + }); + if (fidResources.length === 0) { + throw new AuthClientError("bad_request.validation_failure", "No fid resource provided"); + } + if (fidResources.length > 1) { + throw new AuthClientError("bad_request.validation_failure", "Multiple fid resources provided"); + } +}; diff --git a/packages/core/src/utils/validateSiweMessageStatement.ts b/packages/core/src/utils/validateSiweMessageStatement.ts new file mode 100644 index 0000000..18d215d --- /dev/null +++ b/packages/core/src/utils/validateSiweMessageStatement.ts @@ -0,0 +1,12 @@ +import { SiweMessage } from "siwe"; +import { AuthClientError } from "../errors.js"; +import { STATEMENT } from "./constants.js"; + +export type ValidateSiweMessageStatementParameters = { message: SiweMessage }; + +export const validateSiweMessageStatement = ({ message }: ValidateSiweMessageStatementParameters): void => { + const validStatement = message.statement === STATEMENT || message.statement === "Farcaster Connect"; + if (!validStatement) { + throw new AuthClientError("bad_request.validation_failure", `Statement must be '${STATEMENT}'`); + } +}; diff --git a/packages/core/src/utils/verifySiweMessageWithVerifier.test.ts b/packages/core/src/utils/verifySiweMessageWithVerifier.test.ts new file mode 100644 index 0000000..20d54c4 --- /dev/null +++ b/packages/core/src/utils/verifySiweMessageWithVerifier.test.ts @@ -0,0 +1,242 @@ +import { verifySiweMessageWithVerifier } from "./verifySiweMessageWithVerifier.js"; +import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; +import { type Hex, zeroAddress } from "viem"; +import { getDefaultProvider } from "ethers"; +import { AuthClientError } from "../errors.js"; +import { createSiweMessage } from "./createSiweMessage.js"; + +const account = privateKeyToAccount(generatePrivateKey()); + +const siweParams = { + domain: "example.com", + address: "0x63C378DDC446DFf1d831B9B96F7d338FE6bd4231", + uri: "https://example.com/login", + version: "1", + nonce: "12345678", + issuedAt: "2023-10-01T00:00:00.000Z", +}; +const { nonce, domain } = siweParams; + +describe("verify", () => { + test("verifies valid EOA signatures", async () => { + const getFid = (_custody: Hex) => Promise.resolve(1234n); + + const res = createSiweMessage({ + ...siweParams, + address: account.address, + fid: 1234, + }); + const siweMessage = res; + const message = siweMessage.toMessage(); + const signature = await account.signMessage({ message }); + const result = await verifySiweMessageWithVerifier({ nonce, domain, message, signature, verifier: { getFid } }); + expect(result).toEqual({ + data: siweMessage, + success: true, + fid: 1234, + }); + }); + + test("adds parsed resources to response", async () => { + const getFid = (_custody: Hex) => Promise.resolve(1234n); + + const res = createSiweMessage({ + ...siweParams, + address: account.address, + fid: 1234, + }); + const siweMessage = res; + const message = siweMessage.toMessage(); + const signature = await account.signMessage({ message }); + const result = await verifySiweMessageWithVerifier({ nonce, domain, message, signature, verifier: { getFid } }); + expect(result).toEqual({ + data: siweMessage, + success: true, + fid: 1234, + }); + }); + + test("verifies valid 1271 signatures", async () => { + const getFid = (_custody: Hex) => Promise.resolve(1234n); + const provider = getDefaultProvider("https://mainnet.optimism.io"); + + const res = createSiweMessage({ + ...siweParams, + address: "0xC89858205c6AdDAD842E1F58eD6c42452671885A", + fid: 1234, + }); + const siweMessage = res; + const message = siweMessage.toMessage(); + const signature = await account.signMessage({ message }); + const result = await verifySiweMessageWithVerifier({ + nonce, + domain, + message, + signature, + verifier: { getFid, provider }, + }); + expect(result).toEqual({ + data: siweMessage, + success: true, + fid: 1234, + }); + }); + + test("1271 signatures fail without provider", async () => { + const getFid = (_custody: Hex) => Promise.resolve(1234n); + + const res = createSiweMessage({ + ...siweParams, + address: "0xC89858205c6AdDAD842E1F58eD6c42452671885A", + fid: 1234, + }); + const siweMessage = res; + const message = siweMessage.toMessage(); + const signature = await account.signMessage({ message }); + try { + await verifySiweMessageWithVerifier({ nonce, domain, message, signature, verifier: { getFid } }); + expect(true).toBe(false); + } catch (e) { + expect(e).toBeInstanceOf(AuthClientError); + if (!(e instanceof AuthClientError)) throw new Error("unexpected"); + + expect(e.errCode).toBe("unauthorized"); + expect(e.message).toBe("Signature does not match address of the message."); + } + }); + + test("invalid SIWE message", async () => { + const getFid = (_custody: Hex) => Promise.resolve(1234n); + + const res = createSiweMessage({ + ...siweParams, + address: zeroAddress, + fid: 1234, + }); + const siweMessage = res; + const message = siweMessage.toMessage(); + const signature = await account.signMessage({ + message, + }); + try { + await verifySiweMessageWithVerifier({ nonce, domain, message, signature, verifier: { getFid } }); + expect(true).toBe(false); + } catch (e) { + expect(e).toBeInstanceOf(AuthClientError); + if (!(e instanceof AuthClientError)) throw new Error("unexpected"); + + expect(e.errCode).toBe("unauthorized"); + expect(e.message).toBe("Signature does not match address of the message."); + } + }); + + test("invalid fid owner", async () => { + const getFid = (_custody: Hex) => Promise.resolve(5678n); + + const res = createSiweMessage({ + ...siweParams, + address: account.address, + fid: 1234, + }); + const siweMessage = res; + const message = siweMessage.toMessage(); + const signature = await account.signMessage({ + message, + }); + try { + await verifySiweMessageWithVerifier({ nonce, domain, message, signature, verifier: { getFid } }); + expect(true).toBe(false); + } catch (e) { + expect(e).toBeInstanceOf(AuthClientError); + if (!(e instanceof AuthClientError)) throw new Error("unexpected"); + + expect(e.errCode).toBe("unauthorized"); + expect(e.message).toBe(`Invalid resource: signer ${account.address} does not own fid 1234.`); + } + }); + + test("client error", async () => { + const getFid = (_custody: Hex) => Promise.reject(new Error("client error")); + + const res = createSiweMessage({ + ...siweParams, + address: account.address, + fid: 1234, + }); + const siweMessage = res; + const message = siweMessage.toMessage(); + const signature = await account.signMessage({ + message, + }); + try { + await verifySiweMessageWithVerifier({ nonce, domain, message, signature, verifier: { getFid } }); + expect(true).toBe(false); + } catch (e) { + expect(e).toBeInstanceOf(AuthClientError); + if (!(e instanceof AuthClientError)) throw new Error("unexpected"); + + expect(e.errCode).toBe("unavailable"); + expect(e.message).toBe("client error"); + } + }); + + test("mismatched nonce", async () => { + const res = createSiweMessage({ + ...siweParams, + address: account.address, + fid: 1234, + }); + const siweMessage = res; + const message = siweMessage.toMessage(); + const signature = await account.signMessage({ + message, + }); + const getFid = (_custody: Hex) => Promise.resolve(1234n); + try { + await verifySiweMessageWithVerifier({ + nonce: "mismatched-nonce", + domain, + message, + signature, + verifier: { getFid }, + }); + expect(true).toBe(false); + } catch (e) { + expect(e).toBeInstanceOf(AuthClientError); + if (!(e instanceof AuthClientError)) throw new Error("unexpected"); + + expect(e.errCode).toBe("unauthorized"); + expect(e.message).toBe("Invalid nonce"); + } + }); + + test("mismatched domain", async () => { + const res = createSiweMessage({ + ...siweParams, + address: account.address, + fid: 1234, + }); + const siweMessage = res; + const message = siweMessage.toMessage(); + const signature = await account.signMessage({ + message, + }); + const getFid = (_custody: Hex) => Promise.resolve(1234n); + try { + await verifySiweMessageWithVerifier({ + nonce, + domain: "mismatched-domain", + message, + signature, + verifier: { getFid }, + }); + expect(true).toBe(false); + } catch (e) { + expect(e).toBeInstanceOf(AuthClientError); + if (!(e instanceof AuthClientError)) throw new Error("unexpected"); + + expect(e.errCode).toBe("unauthorized"); + expect(e.message).toBe("Invalid domain"); + } + }); +}); diff --git a/packages/core/src/utils/verifySiweMessageWithVerifier.ts b/packages/core/src/utils/verifySiweMessageWithVerifier.ts new file mode 100644 index 0000000..08723a7 --- /dev/null +++ b/packages/core/src/utils/verifySiweMessageWithVerifier.ts @@ -0,0 +1,107 @@ +import { SiweMessage, type SiweResponse, SiweError } from "siwe"; +import { AuthClientError } from "../errors.js"; + +import { type FarcasterResourceParameters } from "./createSiweMessage.js"; +import type { Provider } from "ethers"; +import { getSiweMessage } from "./getSiweMessage.js"; +import { getResourcesFromSiweMessage } from "./getResourcesFromSiweMessage.js"; +import type { Address } from "../types/address.js"; + +export type VerifySiweMessageWithVerifierParameters = { + nonce: string; + domain: string; + message: string | Partial; + signature: string; + verifier: { + getFid: (custody: Address) => Promise; + provider?: Provider; + }; +}; +export type VerifySiweMessageWithVerifierReturnType = Omit & FarcasterResourceParameters; + +const voidVerifyFid = (_custody: Address) => Promise.reject(new Error("Not implemented: Must provide an fid verifier")); + +/** + * Verify signature of a Sign In With Farcaster message. Returns an error if the + * message is invalid or the signature is invalid. + */ +export const verifySiweMessageWithVerifier = async ( + parameters: VerifySiweMessageWithVerifierParameters, +): Promise => { + const { + nonce, + domain, + message, + signature, + verifier = { + getFid: voidVerifyFid, + }, + } = parameters; + + const { getFid, provider } = verifier; + const validatedMessage = getSiweMessage({ message }); + verifyNonce(validatedMessage, nonce); + verifyDomain(validatedMessage, domain); + + const siweResponse = await verifySignature(validatedMessage, signature, provider); + const siweResponseWithResources = mergeResources(siweResponse); + + if (!siweResponseWithResources.success) { + const errMessage = siweResponseWithResources.error?.type ?? "Failed to verify SIWE message"; + throw new AuthClientError("unauthorized", errMessage); + } + + const siweResponseWithResourcesAndValidatedFid = await verifyFidOwner(siweResponseWithResources, getFid); + if (!siweResponseWithResourcesAndValidatedFid.success) { + const errMessage = siweResponseWithResourcesAndValidatedFid.error?.type ?? "Failed to validate fid owner"; + throw new AuthClientError("unauthorized", errMessage); + } + const { error, ...response } = siweResponseWithResourcesAndValidatedFid; + return response; +}; + +const verifySignature = async (message: SiweMessage, signature: string, provider?: Provider): Promise => { + try { + return await message.verify({ signature }, { provider, suppressExceptions: true }); + } catch (e) { + throw new AuthClientError("unauthorized", e as Error); + } +}; + +const verifyFidOwner = async ( + response: SiweResponse & FarcasterResourceParameters, + fidVerifier: (custody: Address) => Promise, +): Promise => { + const signer = response.data.address as Address; + try { + const fid = await fidVerifier(signer); + if (fid !== BigInt(response.fid)) { + response.success = false; + response.error = new SiweError( + `Invalid resource: signer ${signer} does not own fid ${response.fid}.`, + response.fid.toString(), + fid.toString(), + ); + } + return response; + } catch (e) { + throw new AuthClientError("unavailable", e as Error); + } +}; + +const mergeResources = (response: SiweResponse): SiweResponse & FarcasterResourceParameters => { + const resources = getResourcesFromSiweMessage({ message: response.data }); + return { ...response, ...resources }; +}; + +export const verifyNonce = (message: SiweMessage, nonce: string): void => { + if (message.nonce !== nonce) { + throw new AuthClientError("unauthorized", "Invalid nonce"); + } +}; + +export const verifyDomain = (message: SiweMessage, domain: string): void => { + if (message.domain !== domain) { + throw new AuthClientError("unauthorized", "Invalid domain"); + } +}; diff --git a/packages/core/tsconfig.build.json b/packages/core/tsconfig.build.json new file mode 100644 index 0000000..fbed2b1 --- /dev/null +++ b/packages/core/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "include": ["src/**/*.ts"], + "exclude": ["src/**/*.test.ts", "src/**/*.test-d.ts"], + "compilerOptions": { + "sourceMap": true + } +} diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json new file mode 100644 index 0000000..bacbc92 --- /dev/null +++ b/packages/core/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "./tsconfig.build.json", + "include": ["src/**/*.ts", "test/**/*.ts"], + "exclude": [] +} diff --git a/packages/react/.eslintrc.cjs b/packages/react/.eslintrc.cjs new file mode 100644 index 0000000..78174f6 --- /dev/null +++ b/packages/react/.eslintrc.cjs @@ -0,0 +1,11 @@ +module.exports = { + root: true, + env: { browser: true, es2020: true }, + extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:react-hooks/recommended"], + ignorePatterns: ["dist", ".eslintrc.cjs"], + parser: "@typescript-eslint/parser", + plugins: ["react-refresh"], + rules: { + "react-refresh/only-export-components": ["warn", { allowConstantExport: true }], + }, +}; diff --git a/packages/auth-kit/.gitignore b/packages/react/.gitignore similarity index 84% rename from packages/auth-kit/.gitignore rename to packages/react/.gitignore index 2f79067..a6c06f0 100644 --- a/packages/auth-kit/.gitignore +++ b/packages/react/.gitignore @@ -1,8 +1,8 @@ # Logs logs *.log -yarn-debug.log* -yarn-error.log* +pnpm-debug.log* +pnpm-error.log* node_modules dist diff --git a/packages/auth-kit/CHANGELOG.md b/packages/react/CHANGELOG.md similarity index 100% rename from packages/auth-kit/CHANGELOG.md rename to packages/react/CHANGELOG.md diff --git a/packages/auth-kit/README.md b/packages/react/README.md similarity index 100% rename from packages/auth-kit/README.md rename to packages/react/README.md diff --git a/packages/auth-kit/index.html b/packages/react/index.html similarity index 100% rename from packages/auth-kit/index.html rename to packages/react/index.html diff --git a/packages/react/package.json b/packages/react/package.json new file mode 100644 index 0000000..bedcc20 --- /dev/null +++ b/packages/react/package.json @@ -0,0 +1,86 @@ +{ + "name": "@farcaster/auth-kit", + "description": "A React library that makes it easy to add Sign In With Farcaster to your application.", + "version": "0.2.1", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/farcasterxyz/auth-monorepo.git", + "directory": "packages/react" + }, + "scripts": { + "build": "pnpm run clean && pnpm vite build", + "build:esm+types": "tsc --project tsconfig.build.json --outDir ./dist/esm --declaration --declarationMap --declarationDir ./dist/types", + "clean": "rimraf dist tsconfig.tsbuildinfo actions clients contracts errors utils", + "test:build": "publint --strict", + "typecheck": "tsc --noEmit", + "dev": "vite" + }, + "files": [ + "dist/**", + "!dist/**/*.tsbuildinfo", + "src/**/*.ts", + "!src/**/*.test.ts", + "!src/**/*.test-d.ts", + "/actions", + "/components", + "/hooks" + ], + "type": "module", + "main": "./dist/exports/index.js", + "types": "./dist/exports/index.d.ts", + "exports": { + ".": { + "types": "./dist/exports/index.d.ts", + "default": "./dist/exports/index.js" + }, + "./actions": { + "types": "./dist/exports/actions.d.ts", + "default": "./dist/exports/actions.js" + }, + "./components": { + "types": "./dist/exports/components.d.ts", + "default": "./dist/exports/components.js" + }, + "./hooks": { + "types": "./dist/exports/hooks.d.ts", + "default": "./dist/exports/hooks.js" + }, + "./styles.css": "./dist/style.css" + }, + "dependencies": { + "@farcaster/auth-client": "workspace:*", + "@vanilla-extract/css": "^1.14.1", + "qrcode": "^1.5.3", + "react-remove-scroll": "^2.5.9", + "zustand": "^4.5.2" + }, + "devDependencies": { + "@tanstack/query-core": "^5.28.8", + "@tanstack/react-query": "^5.28.8", + "@types/qrcode": "^1.5.5", + "@types/react": "^18.2.70", + "@types/react-dom": "^18.2.22", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", + "@vanilla-extract/vite-plugin": "^3.9.5", + "@vitejs/plugin-react": "^4.2.1", + "eslint": "^8.57.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.6", + "ethers": "^6.12.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "typescript": "^5.4.3", + "viem": "^1.21.4", + "vite": "^5.2.6", + "vite-plugin-dts": "^3.7.3", + "vite-plugin-node-polyfills": "^0.19.0" + }, + "peerDependencies": { + "@tanstack/react-query": ">=5.0.0", + "ethers": "5.x || 6.x", + "react": ">= 17", + "react-dom": ">= 17" + } +} diff --git a/packages/react/src/actions/createChannel.ts b/packages/react/src/actions/createChannel.ts new file mode 100644 index 0000000..5eda68f --- /dev/null +++ b/packages/react/src/actions/createChannel.ts @@ -0,0 +1,31 @@ +import { + AuthClientError, + type CreateChannelParameters as client_CreateChannelParameters, + type CreateChannelReturnType as client_CreateChannelReturnType, +} from "@farcaster/auth-client"; +import { type Config } from "../types/config.js"; +import type { Omit } from "../types/utils.js"; + +export type CreateChannelParameters = Omit & { + nonce?: string | (() => Promise); +}; + +export type CreateChannelReturnType = client_CreateChannelReturnType; +export type CreateChannelErrorType = AuthClientError; + +export async function createChannel( + config: Config, + parameters: CreateChannelParameters, +): Promise { + const { nonce, expirationTime, notBefore, requestId, siweUri = config.siweUri, domain = config.domain } = parameters; + + const nonceVal = typeof nonce === "function" ? await nonce() : nonce; + return await config.appClient.createChannel({ + nonce: nonceVal, + siweUri, + domain, + notBefore, + expirationTime, + requestId, + }); +} diff --git a/packages/react/src/actions/pollChannelTillCompleted.ts b/packages/react/src/actions/pollChannelTillCompleted.ts new file mode 100644 index 0000000..3e0dce7 --- /dev/null +++ b/packages/react/src/actions/pollChannelTillCompleted.ts @@ -0,0 +1,28 @@ +import { + AuthClientError, + type PollChannelTillCompletedParameters as client_PollChannelTilCompletedParameters, + type PollChannelTillCompletedReturnType as client_PollChannelTilCompletedReturnType, +} from "@farcaster/auth-client"; +import { type Config } from "../types/config.js"; + +export type PollChannelTillCompletedParameters = client_PollChannelTilCompletedParameters; + +export type PollChannelTillCompletedReturnType = client_PollChannelTilCompletedReturnType; +export type PollChannelTillCompletedErrorType = AuthClientError; + +const defaults = { + timeout: 300_000, + interval: 1_500, +}; + +export async function pollChannelTillCompleted( + config: Config, + parameters: PollChannelTillCompletedParameters, +): Promise { + const { channelToken, timeout = defaults.timeout, interval = defaults.interval } = parameters; + return await config.appClient.pollChannelTillCompleted({ + channelToken, + timeout, + interval, + }); +} diff --git a/packages/react/src/actions/signIn.ts b/packages/react/src/actions/signIn.ts new file mode 100644 index 0000000..561d4e6 --- /dev/null +++ b/packages/react/src/actions/signIn.ts @@ -0,0 +1,38 @@ +import { + AuthClientError, + type PollChannelTillCompletedReturnType, + type PollChannelTillCompletedParameters, +} from "@farcaster/auth-client"; +import { type Config } from "../types/config.js"; +import { type Omit } from "../types/utils.js"; + +export type SignInErrorType = AuthClientError; + +export type SignInParameters = Omit & { + channelToken: string; +}; + +export type SignInReturnType = PollChannelTillCompletedReturnType & { isAuthenticated: boolean }; + +const defaults = { + timeout: 300_000, + interval: 1_500, +}; + +export async function signIn(config: Config, parameters: SignInParameters): Promise { + if (!config.domain) throw new Error("domain is not defined"); + const pollChannelTillCompletedResponse = await config.appClient.pollChannelTillCompleted({ + channelToken: parameters?.channelToken, + timeout: parameters?.timeout ?? defaults.timeout, + interval: parameters?.interval ?? defaults.interval, + }); + + const { success: isAuthenticated } = await config.appClient.verifySiweMessage({ + nonce: pollChannelTillCompletedResponse.nonce, + domain: config.domain, + message: pollChannelTillCompletedResponse.message, + signature: pollChannelTillCompletedResponse.signature, + }); + + return { isAuthenticated, ...pollChannelTillCompletedResponse }; +} diff --git a/packages/react/src/actions/verifySiweMessage.ts b/packages/react/src/actions/verifySiweMessage.ts new file mode 100644 index 0000000..1b7f88e --- /dev/null +++ b/packages/react/src/actions/verifySiweMessage.ts @@ -0,0 +1,25 @@ +import { + AuthClientError, + type VerifySiweMessageParameters as client_VerifySiweMessageParameters, + type VerifySiweMessageReturnType as client_VerifySiweMessageReturnType, +} from "@farcaster/auth-client"; +import { type Config } from "../types/config.js"; + +export type VerifySiweMessageParameters = client_VerifySiweMessageParameters; + +export type VerifySiweMessageReturnType = client_VerifySiweMessageReturnType; +export type VerifySiweMessageErrorType = AuthClientError; + +export async function verifySiweMessage( + config: Config, + parameters: VerifySiweMessageParameters, +): Promise { + const { nonce, domain, message, signature } = parameters; + + return await config.appClient.verifySiweMessage({ + nonce, + domain, + message, + signature, + }); +} diff --git a/packages/auth-kit/src/components/ActionButton/ActionButton.tsx b/packages/react/src/components/ActionButton/ActionButton.tsx similarity index 53% rename from packages/auth-kit/src/components/ActionButton/ActionButton.tsx rename to packages/react/src/components/ActionButton/ActionButton.tsx index e706978..dee61d2 100644 --- a/packages/auth-kit/src/components/ActionButton/ActionButton.tsx +++ b/packages/react/src/components/ActionButton/ActionButton.tsx @@ -1,15 +1,19 @@ -import { FarcasterLogo } from "../FarcasterLogo.tsx"; -import { Button } from "../Button.tsx"; +"use client"; + +import { FarcasterLogo } from "../FarcasterLogo.js"; +import { Button } from "../Button.js"; export function ActionButton({ label, + disabled, onClick, }: { label: string; + disabled?: boolean; onClick: () => void; }) { return ( - diff --git a/packages/react/src/components/ActionButton/index.ts b/packages/react/src/components/ActionButton/index.ts new file mode 100644 index 0000000..7f49e38 --- /dev/null +++ b/packages/react/src/components/ActionButton/index.ts @@ -0,0 +1 @@ +export * from "./ActionButton.js"; diff --git a/packages/react/src/components/AuthKitProvider/AuthKitProvider.tsx b/packages/react/src/components/AuthKitProvider/AuthKitProvider.tsx new file mode 100644 index 0000000..218a7ba --- /dev/null +++ b/packages/react/src/components/AuthKitProvider/AuthKitProvider.tsx @@ -0,0 +1,28 @@ +"use client"; + +import { createContext, type ReactNode } from "react"; +import { type Config } from "../../types/config.js"; + +export interface AuthKitConfigContextValues { + config: Config; +} + +export const AuthKitContext = createContext(null); + +export function AuthKitProvider({ + config, + children, +}: { + config: Config; + children: ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/packages/react/src/components/AuthKitProvider/config.ts b/packages/react/src/components/AuthKitProvider/config.ts new file mode 100644 index 0000000..c63e89e --- /dev/null +++ b/packages/react/src/components/AuthKitProvider/config.ts @@ -0,0 +1,36 @@ +import { createAppClient, viemConnector } from "@farcaster/auth-client"; +import { type Config } from "../../types/config.js"; + +const domainDefaults = + typeof window !== "undefined" && window?.location + ? { + domain: window.location.host, + siweUri: window.location.href, + } + : {}; + +const configDefaults = { + relay: "https://relay.farcaster.xyz", + version: "v1", + ...domainDefaults, +}; + +export function createConfig(config: Omit): Config { + const authKitConfig = { + ...configDefaults, + ...config, + }; + + const { relay, rpcUrl, version, provider } = authKitConfig; + + const ethereum = viemConnector(rpcUrl ? { rpcUrl } : undefined); + const appClient = createAppClient( + { + relay, + ethereum, + version, + }, + provider, + ); + return { ...authKitConfig, appClient }; +} diff --git a/packages/react/src/components/AuthKitProvider/index.ts b/packages/react/src/components/AuthKitProvider/index.ts new file mode 100644 index 0000000..e9f2b90 --- /dev/null +++ b/packages/react/src/components/AuthKitProvider/index.ts @@ -0,0 +1,2 @@ +export { AuthKitProvider } from "./AuthKitProvider.js"; +export { createConfig } from "./config.js"; diff --git a/packages/auth-kit/src/components/Button.tsx b/packages/react/src/components/Button.tsx similarity index 86% rename from packages/auth-kit/src/components/Button.tsx rename to packages/react/src/components/Button.tsx index 6a9f9d6..5ed4565 100644 --- a/packages/auth-kit/src/components/Button.tsx +++ b/packages/react/src/components/Button.tsx @@ -1,5 +1,5 @@ -import { ButtonHTMLAttributes } from "react"; -import { primaryButton, secondaryButton, tertiaryButton, resetButton } from "./styles.css"; +import { type ButtonHTMLAttributes } from "react"; +import { primaryButton, secondaryButton, tertiaryButton, resetButton } from "./styles.css.js"; export type Props = ButtonHTMLAttributes & { kind?: "primary" | "secondary" | "tertiary" | "reset"; diff --git a/packages/react/src/components/Demo/Demo.tsx b/packages/react/src/components/Demo/Demo.tsx new file mode 100644 index 0000000..f78e7ed --- /dev/null +++ b/packages/react/src/components/Demo/Demo.tsx @@ -0,0 +1,62 @@ +"use client"; + +import useProfile from "../../hooks/useProfile.js"; +import { SignInButton } from "../SignInButton/index.js"; +import { AuthKitProvider, createConfig } from "../AuthKitProvider/index.js"; + +export function Demo() { + const config = createConfig({ + rpcUrl: "https://mainnet.optimism.io", + siweUri: "https://example.com/login", + domain: "example.com", + }); + + return ( + +
+ console.error("error callback:", error)} + onSignIn={(data) => console.log("success callback:", data)} + onSignOut={() => console.log("sign out callback")} + /> +
+ +
+ ); +} + +function UserProfile() { + const profile = useProfile(); + + return ( +
+ {profile?.isAuthenticated && ( +
+ {profile.fid && ( +

+ FID: {profile.fid} +

+ )} + {profile.displayName && ( +

+ Display name: {profile.displayName} +

+ )} + {profile.bio && ( +

+ Bio: {profile.bio} +

+ )} + {profile.custody && ( +

+ Custody address: {profile.custody} +

+ )} +
+ )} +
+ ); +} diff --git a/packages/react/src/components/Demo/index.ts b/packages/react/src/components/Demo/index.ts new file mode 100644 index 0000000..8ee4c6a --- /dev/null +++ b/packages/react/src/components/Demo/index.ts @@ -0,0 +1 @@ +export * from "./Demo.js"; diff --git a/packages/auth-kit/src/components/Dialog/Dialog.css.ts b/packages/react/src/components/Dialog/Dialog.css.ts similarity index 100% rename from packages/auth-kit/src/components/Dialog/Dialog.css.ts rename to packages/react/src/components/Dialog/Dialog.css.ts diff --git a/packages/auth-kit/src/components/Dialog/Dialog.tsx b/packages/react/src/components/Dialog/Dialog.tsx similarity index 64% rename from packages/auth-kit/src/components/Dialog/Dialog.tsx rename to packages/react/src/components/Dialog/Dialog.tsx index 9d5d140..282df1b 100644 --- a/packages/auth-kit/src/components/Dialog/Dialog.tsx +++ b/packages/react/src/components/Dialog/Dialog.tsx @@ -1,18 +1,13 @@ -import { - MouseEventHandler, - ReactNode, - useCallback, - useEffect, - useState, -} from "react"; +"use client"; + +import { type MouseEventHandler, type ReactNode, useCallback, useEffect, useState } from "react"; import { createPortal } from "react-dom"; import { RemoveScroll } from "react-remove-scroll"; -import * as styles from "./Dialog.css"; -import { FocusTrap } from "./FocusTrap"; -import { isMobile } from "../../utils"; +import * as styles from "./Dialog.css.js"; +import { FocusTrap } from "./FocusTrap.js"; +import { isMobile } from "../../utils.js"; -const stopPropagation: MouseEventHandler = (event) => - event.stopPropagation(); +const stopPropagation: MouseEventHandler = (event) => event.stopPropagation(); interface DialogProps { open: boolean; @@ -24,8 +19,7 @@ interface DialogProps { export function Dialog({ children, onClose, open, titleId }: DialogProps) { useEffect(() => { - const handleEscape = (event: KeyboardEvent) => - open && event.key === "Escape" && onClose(); + const handleEscape = (event: KeyboardEvent) => open && event.key === "Escape" && onClose(); document.addEventListener("keydown", handleEscape); @@ -34,9 +28,7 @@ export function Dialog({ children, onClose, open, titleId }: DialogProps) { const [bodyScrollable, setBodyScrollable] = useState(true); useEffect(() => { - setBodyScrollable( - getComputedStyle(window.document.body).overflow !== "hidden" - ); + setBodyScrollable(getComputedStyle(window.document.body).overflow !== "hidden"); }, []); const handleBackdropClick = useCallback(() => onClose(), [onClose]); @@ -57,16 +49,12 @@ export function Dialog({ children, onClose, open, titleId }: DialogProps) { onClick={handleBackdropClick} role="dialog" > - + {children} , - document.body + document.body, ) : null} diff --git a/packages/auth-kit/src/components/Dialog/FocusTrap.tsx b/packages/react/src/components/Dialog/FocusTrap.tsx similarity index 97% rename from packages/auth-kit/src/components/Dialog/FocusTrap.tsx rename to packages/react/src/components/Dialog/FocusTrap.tsx index 8203bb8..fb139fc 100644 --- a/packages/auth-kit/src/components/Dialog/FocusTrap.tsx +++ b/packages/react/src/components/Dialog/FocusTrap.tsx @@ -1,3 +1,5 @@ +"use client"; + import { useCallback, useEffect, useRef } from "react"; const moveFocusWithin = (element: HTMLElement, position: "start" | "end") => { @@ -7,7 +9,7 @@ const moveFocusWithin = (element: HTMLElement, position: "start" | "end") => { if (focusableElements.length === 0) return; - focusableElements[position === "end" ? focusableElements.length - 1 : 0].focus(); + focusableElements[position === "end" ? focusableElements.length - 1 : 0]?.focus(); }; export function FocusTrap(props: JSX.IntrinsicElements["div"]) { diff --git a/packages/react/src/components/Dialog/index.ts b/packages/react/src/components/Dialog/index.ts new file mode 100644 index 0000000..659fd15 --- /dev/null +++ b/packages/react/src/components/Dialog/index.ts @@ -0,0 +1 @@ +export * from "./Dialog.js"; diff --git a/packages/auth-kit/src/components/FarcasterLogo.tsx b/packages/react/src/components/FarcasterLogo.tsx similarity index 96% rename from packages/auth-kit/src/components/FarcasterLogo.tsx rename to packages/react/src/components/FarcasterLogo.tsx index 650305f..4d5ad2f 100644 --- a/packages/auth-kit/src/components/FarcasterLogo.tsx +++ b/packages/react/src/components/FarcasterLogo.tsx @@ -8,12 +8,7 @@ export function FarcasterLogo({ const width = height * 1.1; return ( - + Farcaster logo diff --git a/packages/auth-kit/src/components/ProfileButton/ProfileButton.css.ts b/packages/react/src/components/ProfileButton/ProfileButton.css.ts similarity index 100% rename from packages/auth-kit/src/components/ProfileButton/ProfileButton.css.ts rename to packages/react/src/components/ProfileButton/ProfileButton.css.ts diff --git a/packages/auth-kit/src/components/ProfileButton/ProfileButton.tsx b/packages/react/src/components/ProfileButton/ProfileButton.tsx similarity index 76% rename from packages/auth-kit/src/components/ProfileButton/ProfileButton.tsx rename to packages/react/src/components/ProfileButton/ProfileButton.tsx index dfde077..0067c60 100644 --- a/packages/auth-kit/src/components/ProfileButton/ProfileButton.tsx +++ b/packages/react/src/components/ProfileButton/ProfileButton.tsx @@ -1,12 +1,10 @@ +"use client"; + import { useRef, useState } from "react"; -import { secondaryButton } from "../styles.css.ts"; -import useDetectClickOutside from "../../hooks/useDetectClickOutside.ts"; -import { - profileButtonContainer, - profileImage, - profileName, -} from "./ProfileButton.css.ts"; -import { SignOutButton } from "../SignOutButton"; +import { secondaryButton } from "../styles.css.js"; +import useDetectClickOutside from "../../hooks/useDetectClickOutside.js"; +import { profileButtonContainer, profileImage, profileName } from "./ProfileButton.css.js"; +import { SignOutButton } from "../SignOutButton/index.js"; interface UserDataProps { fid?: number; @@ -33,10 +31,7 @@ export function ProfileButton({ const showSignOut = showSignOutButton && !hideSignOut; return ( -
+
-