How to Authenticate With The Mirror World Smart SDK
By MirrorWorld
In this tutorial, we shall be covering how to authenticate your users with the Mirror World SDK. This specific tutorial will be focusing on JavaScript for the front end.
We shall be creating more tutorials for back end authentication soon! If you are looking for other frameworks, please see the integration guides for Android, Unity, iOS and Rust.
Getting Started
Create a Mirror World Project
The first step to building with the Mirror World SDK is to create a project and get it's API Key. Please follow the guide on creating your first Mirror World Project.
If you have an API Key, you can skip the step.
Install dependencies
# with pnpmpnpm add @mirrorworld/web3.js# or with NPMnpm install @mirrorworld/web3.js# or with Yarnyarn add @mirrorworld/web3.js
See Android Installation Guide and Unity Installation Guide for Android and Unity respectively
Project Setup
Create a Next JS app by running this command in your terminal
yarn create next-app mirrorworld-js# ornpx create-next-app@latest mirrorworld-js
Install the Mirror World Smart SDK
Next, let's make sure we have the Mirror World Smart SDK installed in our project. This will enable us to run the following command in your project's root directory, in the terminal:
yarn add @mirrorworld/web3.js
Implementing Login
Let's implement login functionality into our app using the Mirror World Smart SDK. To use the SDK, we'll need to create a new instance of the SDK.
Edit your index.tsx file to look like this
📁 pages/index.tsx
import { MirrorWorld, Solana } from "@mirrorworld/web3.js"import styles from "../styles/Home.module.css"export default function Home() { const mirrorworld = new MirrorWorld({ apiKey: "YOUR_SECRET_API_KEY", // Replace this with the API Key for your project chainConfig: Solana("mainnet-beta"), }) return <div className={styles.container}></div>}
Next, we're going to create a function that logs the user in, and a button to trigger that function.
Update your index.tsx file to look like this
import { useState } from "react"import { MirrorWorld, Solana } from "@mirrorworld/web3.js"import styles from "../styles/Home.module.css"export default function Home() { const [user, setUser] = useState() const mirrorworld = new MirrorWorld({ apiKey: "YOUR_SECRET_API_KEY", // Replace this with the API Key for your project chainConfig: Solana("mainnet-beta"), }) async function login() { const { user } = await mirrorworld.login() setUser(user) } return ( <div className={styles.container}> <main className={styles.main}> <button onClick={login}>Login to Mirror World</button> </main> </div> )}
As you can see, we've bound the login method to the button. When you click on the button a popup appears giving you multiple options to login to mirror world.
We also include a user state using the useState
hook from React so that we can
set the user object and use it in our app as we'll see shortly.
Let's go ahead and display the user information in our app with this piece of code:
return ( <div className={styles.container}> <main className={styles.main}> <button onClick={login}>Login to Mirror World</button> {user ? ( <div className="user-info"> <ul> <li>Username: {user.username} </li> <li>Email: {user.email}</li> <li>ETH Address: {user.wallet.eth_address}</li> <li>SOL Address: {user.wallet.sol_address}</li> </ul> </div> ) : ( <p>No User available</p> )} </main> </div> );}
Try to log in again and you should see your user details displayed like this:
Extract Login Logic to a React Hook for
Great! With the current setup, the user can now login at the click of a button, however, we would like to refresh the user's login state everytime the visit the app so that they don't have to keep logging in every time they come to your app.
Create useMirrorWorld
hook
Let's create a new hook called useMirrorWorld
that will provide our SDK
instance and automatically fetch user's state each time the app loads.
Create a new file called useMirrorWorld.tsx
with the following code.
// In your useMirrorWorld.tsx fileimport { ReactNode, createContext, useContext, useState, useEffect, useRef,} from "react"import { Solana, IUser, MirrorWorld } from "@mirrorworld/web3.js"export interface IMirrorWorldContext { user?: IUser mirrorworld: MirrorWorld login(): Promise<void>}/** * Create a MirrorWorld context object */const MirrorWorldContext = createContext<IMirrorWorldContext>( {} as IMirrorWorldContext,)/** * Export the `useMirrorWorld` hook to consume the state from our provider */export function useMirrorWorld() { return useContext(MirrorWorldContext)}// Create a storage key that the provider component will use// to store the user's refresh_token in the client-side.const storageKey = `authentication_demo_refresh_token`/** * Create a `MirrorWorldProvider` component to provide the user's * authentication logic and our SDK instance to the client */export const MirrorWorldProvider = ({ children }: { children: ReactNode }) => { const [mirrorworld, setMirrorworld] = useState<MirrorWorld>() const [user, setUser] = useState<IUser>() const isInitialized = useRef(false) /** * Logs in the user and updates the provider state * when the user successfullly logs in */ async function login() { if (!mirrorworld) throw new Error("Mirror World SDK is not initialized") const result = await mirrorworld.login() if (result.user) { setUser(result.user) localStorage.setItem(storageKey, result.refreshToken) } } /** * Helper function to initialize the SDK * PS: Remember to replace the `apiKey` with your * project's API key from the first step. */ function initialize() { const refreshToken = localStorage.getItem(storageKey) const instance = new MirrorWorld({ apiKey: "mw_YOUR_SUPER_SECRET_API_KEY", chainConfig: Solana("mainnet-beta"), ...(refreshToken && { autoLoginCredentials: refreshToken }), }) /** * This event is fired every time the user logs * in with the SDK in the browser. You can also listen * to this event somewhere else on the app. * * A full list of events can be found in the API reference: * https://docs.mirrorworld.fun/api-reference/js#events--js */ instance.on("auth:refreshToken", async (refreshToken) => { if (refreshToken) { localStorage.setItem(storageKey, refreshToken) const user = await instance.fetchUser() setUser(user) } }) // Set the Mirror World SDK instance setMirrorworld(instance) } useEffect(() => { if (!isInitialized.current) { initialize() } return () => { isInitialized.current = true } }, []) // Finally return the provider with the authentication // logic! return ( <MirrorWorldContext.Provider value={{ mirrorworld: mirrorworld as MirrorWorld, user, login, }} > {children} </MirrorWorldContext.Provider> )}
Great! now you have a created a helper hook to clean up your index.tsx
page.
Wrap app.tsx
with the MirrorWorldProvider
component
Wrap your _app.tsx
with the MirrorWorldProvider
component we just created in
our useMirrorWorld.tsx
file 👇🏽
// In your pages/_app.tsx fileimport type { AppProps } from "next/app"import { MirrorWorldProvider } from "../path/to/useMirrorWorld.tsx"export default function App({ Component, pageProps }: AppProps) { return ( <MirrorWorldProvider> <Component {...pageProps} /> </MirrorWorldProvider> )}
Refactor pages/index.tsx
to use the useMirrorWorld
hook.
Phew! We can now clean up our pages/index.tsx
page as shown below.
// Your new `pages/index.tsx` fileimport { useState } from "react"import styles from "../styles/Home.module.css"import { useMirrorWorld } from "../path/to/useMirrorWorld.tsx" // [tl! ++]export default function Home() { // Simplified home page code! const { user, login } = useMirrorWorld() return ( <div className={styles.container}> <main className={styles.main}> <button onClick={login}>Login to Mirror World</button> {user ? ( <div className="user-info"> <ul> <li>Username: {user.username} </li> <li>Email: {user.email}</li> <li>ETH Address: {user.wallet.eth_address}</li> <li>SOL Address: {user.wallet.sol_address}</li> </ul> </div> ) : ( <p>No User available</p> )} </main> </div> )}
Congrats! Now your user's will automatically be logged in whenever they visit your app!
Going Further
Great! At this point you're pretty much ready to start doing building with the JavaScript SDK for Mirror World. There are a few things you can do to proceed from here:
- Explore the Full JavaScript API Reference to learn more.
- Looking for inspiration? Take a look at our Guides or see what builders are building in the Showcase.
- Join the Mirror World Developer community! We're a vibrant community of builders!
Getting Support
If you're stuck or just looking for support, you may also schedule a support call with our team.
Happy Hacking!
Edit this page on GitHub