{"id":13423820,"url":"https://github.com/random-bits-studio/use-siwe","last_synced_at":"2025-12-30T02:27:19.949Z","repository":{"id":64217160,"uuid":"538559212","full_name":"random-bits-studio/use-siwe","owner":"random-bits-studio","description":"The easiest way to add Sign-in with Ethereum to your app.","archived":false,"fork":false,"pushed_at":"2023-10-28T07:23:00.000Z","size":374,"stargazers_count":25,"open_issues_count":2,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-17T17:17:18.769Z","etag":null,"topics":["auth","authentication","ethereum","express","expressjs","ironsession","next","nextjs","react","session","siwe","wagmi","web3"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/random-bits-studio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2022-09-19T15:05:04.000Z","updated_at":"2024-09-10T09:37:18.000Z","dependencies_parsed_at":"2024-01-07T06:21:47.041Z","dependency_job_id":"59e0dc3e-2e23-45b9-aeb4-f3e9b95aa319","html_url":"https://github.com/random-bits-studio/use-siwe","commit_stats":{"total_commits":31,"total_committers":1,"mean_commits":31.0,"dds":0.0,"last_synced_commit":"74a00e4970db655e026acdf82468d8346d8910db"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/random-bits-studio%2Fuse-siwe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/random-bits-studio%2Fuse-siwe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/random-bits-studio%2Fuse-siwe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/random-bits-studio%2Fuse-siwe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/random-bits-studio","download_url":"https://codeload.github.com/random-bits-studio/use-siwe/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243767318,"owners_count":20344906,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auth","authentication","ethereum","express","expressjs","ironsession","next","nextjs","react","session","siwe","wagmi","web3"],"created_at":"2024-07-31T00:00:43.226Z","updated_at":"2025-12-30T02:27:19.875Z","avatar_url":"https://github.com/random-bits-studio.png","language":"TypeScript","readme":"# UseSIWE\n\nUseSIWE is a library that provides react hooks and API endpoints that make it\ndead simple to add Sign-In with Ethereum functionality to your react\napplication.\n\n### 🌈 Works with RainbowKit\n\nThe easiest way to use this library is with RainbowKit!\nCheck out the RainbowKit authentication adapter for UseSiwe here:\nhttps://github.com/random-bits-studio/rainbowkit-use-siwe-auth\n\n# Table of Contents\n\n- [Installation](#installation)\n- [Getting Started](#getting-started)\n  - [Configure settings for iron-session](#configure-settings-for-iron-session)\n  - [Setting up the API routes](#setting-up-the-api-routes)\n    - [Next.js](#nextjs)\n    - [Express.js](#expressjs)\n  - [Wrapping your application with SiweProvider](#wrapping-your-application-with-siweprovider)\n  - [Using the hooks](#using-the-hooks)\n    - [Checking if a user is authenticated](#checking-if-a-user-is-authenticated)\n    - [Signing In](#signing-in)\n    - [Signing Out](#signing-out)\n- [API](#api)\n  - [Types](#types)\n    - [UseSiweOptions](#usesiweoptions)\n  - [Components](#components)\n    - [SiweProvider](#siweprovider)\n  - [Hooks](#hooks)\n    - [useSession](#usesession)\n    - [useSignIn](#usesignin)\n    - [useSignOut](#usesignout)\n    - [useOptions](#useoptions)\n  - [Routes](#routes)\n    - [Next.js: SiweApi](#nextjs-siweapi)\n    - [Express.js: SiweApi](#expressjs-siweapi)\n  - [Functions](#functions)\n    - [getSession](#getsession)\n    - [createMessage](#createmessage)\n    - [getMessageBody](#getmessagebody)\n    - [verify](#verify)\n    - [signOut](#signout)\n\n# Installation\n\nTo install UseSIWE and it's dependencies run the following command:\n\n```\nnpm install @randombits/use-siwe wagmi ethers iron-session\n```\n\n# Getting Started\n\n## Configure settings for `iron-session`\n\nCopy and paste the following code into a new file in your project:\n\n```ts\n// lib/ironOptions.ts\n\nimport { IronSessionOptions } from 'iron-session';\n\nif (!process.env.IRON_SESSION_PASSWORD)\n  throw new Error('IRON_SESSION_PASSWORD must be set');\n\nconst ironOptions: IronSessionOptions = {\n  password: process.env.IRON_SESSION_PASSWORD,\n  cookieName: 'session',\n  cookieOptions: {\n    secure: process.env.NODE_ENV === \"production\",\n  },\n};\n\ndeclare module \"iron-session\" {\n  interface IronSessionData {\n    address?: string | undefined;\n    nonce?: string | undefined;\n  }\n}\n\nexport default ironOptions;\n```\n\n**Remember to set IRON_SESSION_PASSWORD** in your `.env.local` file for\ndevelopment, and in your production environment through your hosting\nprovider settings. The password must be at least 32 characters long. You can\nuse https://1password.com/password-generator/ to generate strong passwords.\n\nFor full reference of possible options see:\nhttps://github.com/vvo/iron-session#ironoptions\n\n**Typing session data**\nThe type definition of `IronSessionData` in the example above provides a type\ndefinition to the data passed to api functions in `req.session`. `address` and\n`nonce` are used and set by UseSIWE; if you plan on storing other data in the\nsession, feel free to add additional types here.\n\nFor more information see:\nhttps://github.com/vvo/iron-session#typing-session-data-with-typescript\n\n## Setting up the API routes\n\n### Next.js\n\nCopy and past the following code into `pages/api/auth/[[...route]].ts`:\n\n```ts\nimport { withIronSessionApiRoute } from \"iron-session/next\";\nimport ironOptions from \"lib/ironOptions\";\nimport { siweApi } from \"@randombits/use-siwe/next\"\n\nexport default withIronSessionApiRoute(siweApi(), ironOptions);\n```\n\n### Express.js\n\nTo add auth routes to your existing express API, add the following:\n\n```ts\nimport express from \"express\";\nimport { ironSession } from \"iron-session/express\";\nimport ironOptions from \"./ironOptions.js\";\nimport { authRouter } from \"@randombits/use-siwe/express\";\n\nconst app = express();\n\n// Add iron session middleware before all routes that will use session data\napp.use(ironSession(ironOptions));\n\n// Your existing api routes here...\n\n// Add UseSIWE auth routes\napp.use('/auth', authRouter());\n\napp.listen(3001);\n```\n\n## Wrapping your application with `SiweProvider`\n\nAny component that uses the any of the UseSIWE hooks must be wrapped with the\n`SiweProvider` component. For a Next.js application we recommend doing so in\n`pages/_app.tsx` like in the example below:\n\n```ts\n// pages/_app.tsx\n\nimport type { AppProps } from 'next/app';\nimport { configureChains, mainnet } from 'wagmi';\nimport { publicProvider } from 'wagmi/providers/public';\nimport { SiweProvider } from '@randombits/use-siwe';\n\nconst { chains, provider, webSocketProvider } = configureChains(\n  [mainnet],\n  [publicProvider()],\n);\n\nconst client = createClient({\n  autoConnect: true,\n  provider,\n  webSocketProvider,\n});\n\nexport default function MyApp({ Component, pageProps }: AppProps) {\n  return (\n    \u003cWagmiConfig client={client}\u003e\n      \u003cSiweProvider\u003e\n        \u003cComponent {...pageProps} /\u003e\n      \u003c/SiweProvider\u003e\n    \u003c/WagmiConfig\u003e\n  );\n}\n```\n\n**Important:** The `SiweProvider` must be inside a `WagmiConfig` component.\n\n## Using the hooks\n\n### Checking if a user is authenticated\n\n#### Client-side\n\nCheck to see is a user is authenticated with the `useSession` hook like in the\nexample below:\n\n```ts\nimport { useSession } from \"@randombits/use-siwe\";\n\nexport const AuthCheck = () =\u003e {\n  const { isLoading, authenticated, address } = useSession();\n\n  if (isLoading) return \u003cp\u003eLoading...\u003c/p\u003e;\n  if (!authenticated) return \u003cp\u003eNot authenticated\u003c/p\u003e;\n  return \u003cp\u003e{address} is Authenticated\u003c/p\u003e;\n};\n```\n\n#### Server-side\n\nFor API routes, wrap your API handler with `withIronSessionApiRoute` and check\nto see if `req.session.address` is set. If a user is authenticated,\n`req.session.address` will be set to their address, otherwise it will be\n`undefined`.\n\n```ts\nimport ironOptions from '@/lib/ironOptions'\nimport { withIronSessionApiRoute } from 'iron-session/next/dist'\nimport type { NextApiHandler } from 'next'\n\nconst handler: NextApiHandler = (req, res) =\u003e {\n  if (!req.session.address) return res.status(401).send(\"Unauthorized\");\n  res.status(200).send(`Hello, ${req.session.address}!`);\n}\n\nexport default withIronSessionApiRoute(handler, ironOptions);\n```\n\n### Signing In\n\nLogin the user by calling the `signIn` function returned by the `useSignIn`\nhook:\n\n```ts\nimport { useSignIn } from \"@randombits/use-siwe\";\n\nconst SignInButton = () =\u003e {\n  const { signIn, isLoading } = useSignIn();\n  return \u003cbutton onClick={() =\u003e signIn()} disabled={isLoading}\u003eSign In with Ethereum\u003c/button\u003e;\n};\n```\n\n### Signing Out\n\nLogout the user by calling the `signOut` function returned by the `useSignOut`\nhook:\n\n```ts\nimport { useSignOut } from \"@randombits/use-siwe\";\n\nconst SignOutButton = () =\u003e {\n  const { signOut, isLoading } = useSignOut();\n  return \u003cbutton onClick={() =\u003e signOut()} disabled={isLoading}\u003eSign Out\u003c/button\u003e;\n};\n```\n\n# API\n\n## Types\n\n### UseSiweOptions\n\nUseSIWE accepts an object of options. Currently this consists of one optional\nsetting:\n\n#### Usage\n\n```ts\nconst options: UseSiweOptions = {\n  baseUrl: \"/v2/api/auth\",\n};\n```\n\n#### Options\n\n- `baseUrl`, optional: The base url for the auth API endpoints that is\n  prepended to all requests. Defaults to: `/api/auth`\n\n## Components\n\n### SiweProvider\n\nContext provider component that must wrap all components that use `useSession`,\n`useSignIn`, `useSignOut`, or `useOptions` hooks.\n\n#### Usage\n\n```ts\nimport type { AppProps } from 'next/app';\nimport { SiweProvider } from '@randombits/use-siwe';\n\nexport default function MyApp({ Component, pageProps }: AppProps) {\n  return \u003cSiweProvider\u003e\n    \u003cComponent {...pageProps} /\u003e\n  \u003c/SiweProvider\u003e;\n}\n```\n\n#### Props\n\n- `options`, Optional: A `UseSiweOptions` object.\n\n## Hooks\n\n### useSession\n\nA hook that returns the the current state of the users session.\n\n#### Usage\n\n```ts\nimport { useSession } from \"@randombits/use-siwe\";\n\nexport const Component = () =\u003e {\n  const { isLoading, authenticated, address } = useSession();\n\n  if (isLoading) return \u003cdiv\u003eLoading...\u003c/div\u003e;\n  if (!authenticated) return \u003cdiv\u003eNot Signed In\u003c/div\u003e;\n  return \u003cdiv\u003eHello, {address}!\u003c/div\u003e;\n};\n```\n\n#### Return Value\n\nReturns a `UseQueryResult` ([ref](https://tanstack.com/query/latest/docs/react/reference/useQuery))\naugmented with the following:\n\n```ts\n{\n  authenticated: boolean;\n  address?: string;\n  nonce?: string;\n} \u0026 UseQueryResult\n```\n\n### useSignIn\n\nA hook that returns a `signIn` function that will initiate a SIWE flow, as well\nas the status of that signIn process.\n\n#### Usage\n\n```ts\nimport { useSignIn } from \"@randombits/use-siwe\";\n\nconst SignInButton = () =\u003e {\n  const { signIn, isLoading } = useSignIn();\n  return \u003cbutton onClick={() =\u003e signIn()} disabled={isLoading}\u003eSign In with Ethereum\u003c/button\u003e;\n};\n```\n\n#### Options\n\n```ts\n{\n  onSuccess: () =\u003e void,\n  onError: () =\u003e void,\n}\n```\n\n#### Return Value\n\nReturns a `UseMutationResult` ([ref](https://tanstack.com/query/latest/docs/react/reference/useMutation))\naugmented with the following:\n\n```ts\n{\n  signIn: () =\u003e void,\n  SignInAsync: () =\u003e Promise\u003cvoid\u003e,\n} \u0026 UseMutationResult\n```\n\n### useSignOut\n\nA hook that returns a `signOut` function that when called will sign out the\ncurrent user and disconnect their wallet.\n\n#### Usage\n\n```ts\nimport { useSignOut } from \"@randombits/use-siwe\";\n\nconst SignOutButton = () =\u003e {\n  const { signOut, isLoading } = useSignOut();\n  return \u003cbutton onClick={() =\u003e signOut()} disabled={isLoading}\u003eSign Out\u003c/button\u003e;\n};\n```\n\n#### Options\n\n```ts\n{\n  onSuccess: () =\u003e void,\n  onError: () =\u003e void,\n}\n```\n\n#### Return Value\n\nReturns a `UseMutationResult` ([ref](https://tanstack.com/query/latest/docs/react/reference/useMutation))\naugmented with the following:\n\n```ts\n{\n  signOut: () =\u003e void,\n  SignOutAsync: () =\u003e Promise\u003cvoid\u003e,\n} \u0026 UseMutationResult\n```\n\n### useOptions\n\nA hook that simply returns the options that have been set by in the\n`SiweProvider` component.\n\n#### Usage\n\n```ts\nimport { useOptions, verify } from \"@randombits/use-siwe\";\n\nconst verifyButton = (props) =\u003e {\n  const options = useOptions();\n  const handleClick = () =\u003e verify({\n    message: props.message,\n    signature: props.signature,\n  }, options);\n\n  return \u003cbutton onClick={() =\u003e handleClick()}\u003eVerify Signature\u003c/button\u003e;\n};\n```\n\n#### Return Value\n\n```ts\nuseSiweOptions\n```\n\n## Routes\n\n### Next.js: SiweApi\n\nA function that returns a `NextApiHandler` that will handle all auth API\nroutes.\n\n#### Usage\n\n```ts\nimport { withIronSessionApiRoute } from \"iron-session/next\";\nimport ironOptions from \"lib/ironOptions\";\nimport { siweApi } from \"@randombits/use-siwe/next\"\n\nexport default withIronSessionApiRoute(siweApi(), ironOptions);\n```\n\n#### Return Value\n\n```ts\nNextApiHandler\n```\n\n### Express.js: SiweApi\n\nA function that returns an express `Router` that will handle all auth API\nroutes.\n\n#### Usage\n\n```ts\nimport express from \"express\";\nimport { ironSession } from \"iron-session/express\";\nimport ironOptions from \"./ironOptions.js\";\nimport { authRouter } from \"@randombits/use-siwe/express\";\n\nconst app = express();\n\napp.use(ironSession(ironOptions));\napp.use('/auth', authRouter());\n\napp.listen(3001);\n```\n\n#### Return Value\n\n```ts\nRouter\n```\n\n## Functions\n\n### getSession\n\nA function to retrieve the session data where using a hook doesn't make sense.\n\n#### Usage\n\n```ts\nimport { getSession } from \"@randombits/use-siwe\";\n\nconst addressOrNull = async () =\u003e {\n  const { address } = await getSession();\n  if (!address) return null;\n  return address;\n};\n```\n\n#### Args\n\n- `options?: UseSiweOptions`\n\n#### Return Value\n\n```ts\n{\n  authenticated: boolean;\n  address?: string;\n  nonce?: string;\n}\n```\n\n### createMessage\n\nReturns a `SiweMessage` for the given address, chainId, and nonce.\n\n#### Usage\n\n```ts\nimport { createMessage, getMessageBody } from \"@randombits/use-siwe\";\n\nconst debugMessage = (address, chainId, nonce) =\u003e {\n  const message = createMessage({ address, chainId, nonce });\n  const messageBody = getMessageBody({ message });\n  console.log({ message, messageBody });\n};\n```\n\n#### Args\n\n- `args: MessageArgs`\n\n```ts\ntype MessageArgs = {\n  address: string,\n  chainId: number,\n  nonce: string,\n};\n```\n\n#### Return Value\n\n```ts\nSiweMessage\n```\n\n### getMessageBody\n\nReturns a message ready to be signed according with the type defined in the\nSiweMessage object.\n\n#### Usage\n\n```ts\nimport { createMessage, getMessageBody } from \"@randombits/use-siwe\";\n\nconst debugMessage = (address, chainId, nonce) =\u003e {\n  const message = createMessage({ address, chainId, nonce });\n  const messageBody = getMessageBody({ message });\n  console.log({ message, messageBody });\n};\n```\n\n#### Args\n\n- `args: { message: SiweMessage }`\n\n#### Return Value\n\n```ts\nstring\n```\n\n### verify\n\nTakes a message and a signature as arguments and attempts to verify them using\nthe auth API. A successful verification will create a session for the user.\n\n#### Usage\n\n```ts\nimport { verify } from \"@randombits/use-siwe\";\n\nconst verifyButton = (props) =\u003e {\n  const handleClick = () =\u003e {\n    const success = verify({\n      message: props.message,\n      signature: props.signature,\n    });\n\n    if (!success) return console.error(\"VERIFICATION FAILED\");\n    console.log(\"SIGNATURE VERIFIED\");\n  };\n\n  return \u003cbutton onClick={() =\u003e handleClick()}\u003eVerify Signature\u003c/button\u003e;\n};\n```\n\n#### Args\n\n- `args: VerifyArgs`\n- `options?: UseSiweOptions`\n\n```ts\ntype VerifyArgs = {\n  message: SiweMessage,\n  signature: string,\n};\n```\n\n#### Return Value\n\n```ts\nboolean\n```\n\n### signOut\n\nA function to sign out the user where using a hook doesn't make sense.\n\n#### Usage\n\n```ts\nimport { signOut } from \"@randombits/use-siwe\";\n\n// Logout a user after 1 hour\nsetTimeout(async () =\u003e {\n  await signOut();\n  window.location.href = \"/session-expired\";\n}, 60 * 60 * 1000);\n```\n\n#### Args\n\n- `options?: UseSiweOptions`\n\n#### Return Value\n\n```ts\nPromise\u003cvoid\u003e\n```\n","funding_links":[],"categories":["Extensions","Projects","Uncategorized"],"sub_categories":["Packages","Uncategorized"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frandom-bits-studio%2Fuse-siwe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frandom-bits-studio%2Fuse-siwe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frandom-bits-studio%2Fuse-siwe/lists"}