## πŸ“£ Hello Hive Community Members! --- Welcome back to my wild ReactJS learning ride 🎒 β€” and guess what? We’re already on **Day 8**! If you've missed previous episodes, don't worry. Grab some popcorn 🍿 and catch up below: --- ### πŸ“– **ReactJS Journey So Far** - [πŸ“š **Day One**](https://peakd.com/hive-139531/@sagarkothari88/integrate-aioha-with-your-react-app-from-scratch-vite--tailwind--daisyui): Fresh React app + AIOHA integration! - [🧭 **Day Two**](https://peakd.com/hive-139531/@sagarkothari88/integrating-react-router-my-routing-adventures-with-react): Routing drama & rebellious NavBar 😀 - [πŸ› οΈ **Day Three**](https://peakd.com/hive-139531/@sagarkothari88/from-navbar-mess-to-react-router-success-fixing-layouts-routing-and-aioha-in-one-go): Fixed Layouts, Routing & AIOHA πŸ’₯ - [🧠 **Day Four**](https://peakd.com/hive-139531/@sagarkothari88/day-4-reactjs-adventures--distriator-progress-usestate-useeffect-and-env-chaos): useState, useEffect, and .env headaches πŸ˜… - [🧹 **Day Five**](https://peakd.com/hive-139531/@sagarkothari88/level-up-your-imports-using-path-aliases-for-cleaner-react--typescript-projects): Path Aliases to clean up relative path spaghetti 🍝 - [πŸ“‘ **Day Six**](https://peakd.com/hive-139531/@sagarkothari88/day-6-learning-reactjs-calling-apis-and-creating-context-providers-or-distriator-feature-update): Create Context Provider & call API - [🍞 **Day Seven**](#): Show a toast message --- ## πŸš€ What’s New in Day 8? In this episode, I went full-on security ninja. πŸ₯· Here's what I implemented: - πŸ” Login API with @aioha & distriator combo - πŸ“¦ Storing user data *securely* in `localStorage` using AES encryption & base64 encoding - βœ… Upsert logic for managing multiple Hive logins --- ## 🧠 **Data Modeling Like a Boss** πŸ“ Folder: `src/types/LoginApiRequestResponse.tsx` ``` export interface LoginRequestDTO { challenge: string; proof: string; pubkey: string; username: string; } export interface LoginSuccessResponseDTO { token: string; type: string; } export interface LocalStorageUserDTO { token: string; type: string; challenge: string; proof: string; pubkey: string; username: string; } export interface LoginErrorResponseDTO { error: string; } ``` --- ## πŸ’Ύ **Encrypting User Data in LocalStorage** ![localstorage image reference](https://i.ytimg.com/vi/N7rs5F4f6FA/maxresdefault.jpg) πŸ“ File: `src/utils/LocalStorageUtils.tsx` Let’s bring in the secret scrolls of utility magic! πŸ§™ ### πŸ” Base64 Helper Spells ``` function toBase64(str: string): string { return typeof window !== "undefined" ? window.btoa(unescape(encodeURIComponent(str))) : Buffer.from(str, "utf-8").toString("base64"); } function fromBase64(b64: string): string { return typeof window !== "undefined" ? decodeURIComponent(escape(window.atob(b64))) : Buffer.from(b64, "base64").toString("utf-8"); } ``` --- ### πŸ“₯ Retrieve Users from LocalStorage (aka Decrypt Scroll) ``` export function getLoggedInUsers(): LocalStorageUserDTO[] { const apiKey = import.meta.env.VITE_LOCAL_KEY; const data = localStorage.getItem("logged-in-users") || ""; const decrypteText = CryptoJS.AES.decrypt(data, apiKey).toString( CryptoJS.enc.Utf8 ); if (!data) return []; try { const jsonStr = fromBase64(decrypteText); return JSON.parse(jsonStr); } catch (e) { console.error("Failed to decode/parse localStorage ", e); return []; } } ``` πŸ“ Steps: - Get πŸ” key from `.env` - Decrypt β†’ decode β†’ parse β†’ return! --- ### πŸ“ Store/Update New Logged-In Users (Avengers-like registry 🦸) ``` export function setLoggedInUsers(users: LocalStorageUserDTO[]): void { try { const apiKey = import.meta.env.VITE_DEKEY; const jsonStr = JSON.stringify(users); const base64Str = toBase64(jsonStr); const encryptedText = CryptoJS.AES.encrypt(base64Str, apiKey).toString(); localStorage.setItem("logged-in-users", encryptedText); } catch (e) { console.error("Failed to encode/set localStorage ", e); } } ``` --- ### πŸ”„ Save/Update User Info (like a React-powered CRM 😎) ``` export function saveOrUpdateUser(newUser: LocalStorageUserDTO): void { const users = getLoggedInUsers(); const idx = users.findIndex((user) => user.username === newUser.username); if (idx !== -1) { users[idx] = newUser; } else { users.push(newUser); } setLoggedInUsers(users); } ``` πŸ™…β€β™‚οΈ No remove logic yet β€” coming with future logout feature. Stay tuned! --- ## πŸ”Œ **Calling the Login API – FTW!** πŸ“ File: `src/api/LoginApi.tsx` Here’s how the server handshake looks: ``` export const loginApi = async (challenge, proof, pubkey, username): Promise<null | string> => { try { const rqst: LoginRequestDTO = { challenge, proof, pubkey, username }; const response = await fetch("https://beta-api.distriator.com/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(rqst), }); if (!response.ok) { const errorBody: LoginErrorResponseDTO = await response.json(); console.error("Login failed:", errorBody); return `Error - ${errorBody.error}`; } const success: LoginSuccessResponseDTO = await response.json(); const updatedUser: LocalStorageUserDTO = { ...rqst, token: success.token, type: success.type }; saveOrUpdateUser(updatedUser); return null; } catch (error) { console.error("Network error:", error); return `Network error - ${error.message}`; } }; ``` πŸ”₯ Boom! Now you're securely logged in and your data is sealed like Wakanda tech! πŸ›‘οΈ --- ## 🀝 AIOHA + Distriator Login Combo πŸ’ͺ πŸ“ File: `src/components/HiveUserAvatarButton.tsx` We've glued it all together using `@aioha/react-ui`. 🧩 ``` <AiohaModal displayed={modalDisplayed} loginOptions={{ msg: proof, keyType: KeyTypes.Posting, }} onLogin={performLogin} onClose={setModalDisplayed} /> ``` And here’s the magic `performLogin` function: ``` async function performLogin(result: LoginResult) { if (result.success) { const loginResult = await loginApi(result.result, proof, result.publicKey || "none", result.username); if (loginResult == null) { console.log("πŸŽ‰ Logged in successfully!"); } else { console.error(`Login failed: ${loginResult}`); } } else { console.error(result.error || "Something went wrong"); } } ``` --- ## 🎯 Wrapping Up This was a deep dive into login flows, secure data handling & functional integration of blockchain login workflows! 🧩 That's it for now, folks! Thank you so much for reading my post. πŸ’™ More power to the **Hive Blockchain** 🐝 More power to all our community members πŸ™Œ Until next time, Happy Coding! πŸ’»βœ¨ --- ### πŸ“ Final Note - I asked AI to help optimize this post to make it more readable and viewer-friendly. - Here is the link where you can find both original content & improvements made by AI - https://www.perplexity.ai/search/e4abc965-4e52-442b-b001-ab6942995dff --- ### πŸš€ My Contributions to ♦️ Hive Ecosystem | Contribution | To | Hive | Ecosystem | |--------------|----|------|-----------| | Hive Witness Node | Hive API Node (in progress) | 3Speak Video Encoder Node Operator (highest number of nodes) | 3Speak Mobile App Developer | | 3Speak Podcast App Developer | 3Speak Shorts App Developer | 3Speak Support & Maintenance Team | [Distriator Developer](https://distriator.com/) | | [CheckinWithXYZ](https://checkinwith.xyz/) | [Hive Inbox](https://hive-inbox.the-hive-mobile.app/) | [HiFind](https://hifind.the-hive-mobile.app/) | [Hive Donate App](https://donate.the-hive-mobile.app/) | | Contributed to HiveAuth Mobile App | Ecency ↔ 3Speak Integration | Ecency ↔ InLeo Integration | Ecency ↔ Actifit Integration | | [Hive Stats App](https://stats.the-hive-mobile.app/) | [Vote for Witness App](https://witness.the-hive-mobile.app/) | [HiveFlutterKit](https://hiveflutterkit.sagarkothari88.one/docs/intro) | [New 3Speak App](https://3speak.sagarkothari88.one/#/?tab=home) | --- ### πŸ™Œ Support Back ❀️ **Appreciate my work? Consider supporting @threespeak & @sagarkothari88!** ❀️ | Vote | For | Witness | |------|-----|---------| | [![](https://images.hive.blog/u/sagarkothari88/avatar)](https://witness.the-hive-mobile.app/#/witnesses/@sagarkothari88) | [sagarkothari88](https://witness.the-hive-mobile.app/#/witnesses/@sagarkothari88) | @sagarkothari88 | | [![](https://images.hive.blog/u/threespeak/avatar)](https://witness.the-hive-mobile.app/#/witnesses/@threespeak) | [threespeak](https://witness.the-hive-mobile.app/#/witnesses/@threespeak) | @threespeak | ---