From c3937be98d11f143ca04fbdf38138642e3325287 Mon Sep 17 00:00:00 2001 From: Guru Date: Thu, 12 Dec 2024 10:26:19 +0530 Subject: [PATCH 1/6] feat: tailiwnd configs for colors --- demo/redirect-flow-example/tailwind.config.ts | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/demo/redirect-flow-example/tailwind.config.ts b/demo/redirect-flow-example/tailwind.config.ts index 519bbce..c456ee7 100644 --- a/demo/redirect-flow-example/tailwind.config.ts +++ b/demo/redirect-flow-example/tailwind.config.ts @@ -54,6 +54,18 @@ export default { 100: "var(--app-blue-100)", 50: "var(--app-blue-50)", }, + red: { + 900: "var(--app-red-900)", + 800: "var(--app-red-800)", + 700: "var(--app-red-700)", + 600: "var(--app-red-600)", + 500: "var(--app-red-500)", + 400: "var(--app-red-400)", + 300: "var(--app-red-300)", + 200: "var(--app-red-200)", + 100: "var(--app-red-100)", + 50: "var(--app-red-50)", + }, light: { "surface-main": "var(--app-gray-100)", surface1: "var(--app-white)", @@ -169,6 +181,18 @@ export default { 100: "#e1effe", 50: "#ebf5ff", }, + red: { + 900: "#7f1d1d", + 800: "#991b1b", + 700: "#b91c1c", + 600: "#dc2626", + 500: "#ef4444", + 400: "#f87171", + 300: "#fca5a5", + 200: "#fecaca", + 100: "#fee2e2", + 50: "#fef2f2", + }, success: "#30cca4", warning: "#fbc94a", error: "#fb4a61", @@ -188,4 +212,4 @@ export default { containerQueries, ], darkMode: "class", -} as Config; +} as Config; \ No newline at end of file From 322ff86f73979f314be8187a867ccd896464c9e9 Mon Sep 17 00:00:00 2001 From: Guru Date: Thu, 12 Dec 2024 10:27:00 +0530 Subject: [PATCH 2/6] feat: service worker --- .../public/serviceworker/sw.js | 315 ++++++++++++++++++ demo/redirect-flow-example/src/index.tsx | 8 +- .../src/service-worker.js | 47 +++ .../src/service-worker.ts | 80 +++++ 4 files changed, 449 insertions(+), 1 deletion(-) create mode 100644 demo/redirect-flow-example/public/serviceworker/sw.js create mode 100644 demo/redirect-flow-example/src/service-worker.js create mode 100644 demo/redirect-flow-example/src/service-worker.ts diff --git a/demo/redirect-flow-example/public/serviceworker/sw.js b/demo/redirect-flow-example/public/serviceworker/sw.js new file mode 100644 index 0000000..de1d088 --- /dev/null +++ b/demo/redirect-flow-example/public/serviceworker/sw.js @@ -0,0 +1,315 @@ +/* eslint-disable */ +function getScope() { + return self.registration.scope; +} + +self.addEventListener("message", function (event) { + if (event.data && event.data.type === "SKIP_WAITING") { + self.skipWaiting(); + } +}); + +self.addEventListener("fetch", function (event) { + try { + const url = new URL(event.request.url); + if (url.pathname.includes("redirect") && url.href.includes(getScope())) { + event.respondWith( + new Response( + new Blob( + [ + ` + + + + + + + Redirect + + + + +
+
+
+
+
+
+

You can close this window now

+
+ + + + + +${""} + `, + ], + { type: "text/html" } + ) + ) + ); + } + } catch (error) { + console.error(error); + } +}); diff --git a/demo/redirect-flow-example/src/index.tsx b/demo/redirect-flow-example/src/index.tsx index 99c60be..8edb1b4 100644 --- a/demo/redirect-flow-example/src/index.tsx +++ b/demo/redirect-flow-example/src/index.tsx @@ -2,6 +2,7 @@ import "./index.css"; import "../global.css"; import ReactDOM from "react-dom/client"; +import * as serviceWorkerRegistration from './serviceWorkerRegistration'; import App from "./App"; import React from "react"; @@ -21,7 +22,6 @@ root.render(
} /> - } /> } /> } /> } /> @@ -31,3 +31,9 @@ root.render( ); + + +// If you want your app to work offline and load faster, you can change +// unregister() to register() below. Note this comes with some pitfalls. +// Learn more about service workers: https://cra.link/PWA +serviceWorkerRegistration.register(); diff --git a/demo/redirect-flow-example/src/service-worker.js b/demo/redirect-flow-example/src/service-worker.js new file mode 100644 index 0000000..eb7f4a2 --- /dev/null +++ b/demo/redirect-flow-example/src/service-worker.js @@ -0,0 +1,47 @@ +const CACHE_NAME = 'my-app-cache-v1'; +const urlsToCache = [ + '/', + '/index.html', + '/styles.css', + '/script.js', + // Add other assets you want to cache +]; + +self.addEventListener('install', event => { + event.waitUntil( + caches.open(CACHE_NAME) + .then(cache => { + console.log('Opened cache'); + return cache.addAll(urlsToCache); + }) + ); +}); + +self.addEventListener('fetch', event => { + event.respondWith( + caches.match(event.request) + .then(response => { + // Cache hit - return response + if (response) { + return response; + } + return fetch(event.request); + } + ) + ); +}); + +self.addEventListener('activate', event => { + const cacheWhitelist = [CACHE_NAME]; + event.waitUntil( + caches.keys().then(cacheNames => { + return Promise.all( + cacheNames.map(cacheName => { + if (cacheWhitelist.indexOf(cacheName) === -1) { + return caches.delete(cacheName); + } + }) + ); + }) + ); +}); \ No newline at end of file diff --git a/demo/redirect-flow-example/src/service-worker.ts b/demo/redirect-flow-example/src/service-worker.ts new file mode 100644 index 0000000..cb296d1 --- /dev/null +++ b/demo/redirect-flow-example/src/service-worker.ts @@ -0,0 +1,80 @@ +/// +/* eslint-disable no-restricted-globals */ + +// This service worker can be customized! +// See https://developers.google.com/web/tools/workbox/modules +// for the list of available Workbox modules, or add any other +// code you'd like. +// You can also remove this file if you'd prefer not to use a +// service worker, and the Workbox build step will be skipped. + +import { clientsClaim } from 'workbox-core'; +import { ExpirationPlugin } from 'workbox-expiration'; +import { precacheAndRoute, createHandlerBoundToURL } from 'workbox-precaching'; +import { registerRoute } from 'workbox-routing'; +import { StaleWhileRevalidate } from 'workbox-strategies'; + +declare const self: ServiceWorkerGlobalScope; + +clientsClaim(); + +// Precache all of the assets generated by your build process. +// Their URLs are injected into the manifest variable below. +// This variable must be present somewhere in your service worker file, +// even if you decide not to use precaching. See https://cra.link/PWA +precacheAndRoute(self.__WB_MANIFEST); + +// Set up App Shell-style routing, so that all navigation requests +// are fulfilled with your index.html shell. Learn more at +// https://developers.google.com/web/fundamentals/architecture/app-shell +const fileExtensionRegexp = new RegExp('/[^/?]+\\.[^/]+$'); +registerRoute( + // Return false to exempt requests from being fulfilled by index.html. + ({ request, url }: { request: Request; url: URL }) => { + // If this isn't a navigation, skip. + if (request.mode !== 'navigate') { + return false; + } + + // If this is a URL that starts with /_, skip. + if (url.pathname.startsWith('/_')) { + return false; + } + + // If this looks like a URL for a resource, because it contains + // a file extension, skip. + if (url.pathname.match(fileExtensionRegexp)) { + return false; + } + + // Return true to signal that we want to use the handler. + return true; + }, + createHandlerBoundToURL(process.env.PUBLIC_URL + '/index.html') +); + +// An example runtime caching route for requests that aren't handled by the +// precache, in this case same-origin .png requests like those from in public/ +registerRoute( + // Add in any other file extensions or routing criteria as needed. + ({ url }) => url.origin === self.location.origin && url.pathname.endsWith('.png'), + // Customize this strategy as needed, e.g., by changing to CacheFirst. + new StaleWhileRevalidate({ + cacheName: 'images', + plugins: [ + // Ensure that once this runtime cache reaches a maximum size the + // least-recently used images are removed. + new ExpirationPlugin({ maxEntries: 50 }), + ], + }) +); + +// This allows the web app to trigger skipWaiting via +// registration.waiting.postMessage({type: 'SKIP_WAITING'}) +self.addEventListener('message', (event) => { + if (event.data && event.data.type === 'SKIP_WAITING') { + self.skipWaiting(); + } +}); + +// Any other custom service worker logic can go here. \ No newline at end of file From b9fcdff7e16f62738fa03956a549a96d6a5b418b Mon Sep 17 00:00:00 2001 From: Guru Date: Thu, 12 Dec 2024 10:27:56 +0530 Subject: [PATCH 3/6] feat: popup --- demo/redirect-flow-example/src/App.tsx | 81 ++++++---- .../src/serviceWorkerRegistration.ts | 142 ++++++++++++++++++ 2 files changed, 193 insertions(+), 30 deletions(-) create mode 100644 demo/redirect-flow-example/src/serviceWorkerRegistration.ts diff --git a/demo/redirect-flow-example/src/App.tsx b/demo/redirect-flow-example/src/App.tsx index 7f22f97..1a3381d 100644 --- a/demo/redirect-flow-example/src/App.tsx +++ b/demo/redirect-flow-example/src/App.tsx @@ -2,7 +2,6 @@ import { useEffect, useState } from "react"; import { Web3AuthMPCCoreKit, WEB3AUTH_NETWORK, - SubVerifierDetailsParams, COREKIT_STATUS, makeEthereumSigner, AggregateVerifierLoginParams, @@ -117,9 +116,9 @@ export const DEFAULT_CHAIN_CONFIG: CustomChainConfig = { }; function App() { - const { coreKitInstance, passkeyPlugin, setCoreKitInstance, coreKitStatus, setCoreKitStatus, provider, setProvider, setWeb3 } = useCoreKit(); + const { coreKitInstance, passkeyPlugin, setCoreKitInstance, coreKitStatus, setCoreKitStatus, provider, setProvider, setWeb3, setUserInfo, globalLoading, getShareDescriptions } = useCoreKit(); - const [isLoading, setIsLoading] = useState(false); + const [isLoading, setIsLoading] = useState(true); const navigate = useNavigate(); const [selectedTssLib, setSelectedTssLib] = useState(tssLibDkls); @@ -136,16 +135,17 @@ function App() { // decide whether to rehydrate session const init = async () => { // Example config to handle redirect result manually + setIsLoading(true); if (coreKitInstance.status === COREKIT_STATUS.NOT_INITIALIZED) { - await coreKitInstance.init({ rehydrate: true, handleRedirectResult: true }); + await coreKitInstance.init({ rehydrate: true, handleRedirectResult: false }); setCoreKitInstance(coreKitInstance); await passkeyPlugin.initWithMpcCoreKit(coreKitInstance); - if (window.location.hash.includes("state")) { - // await coreKitInstance.handleRedirectResult(); - } + setIsLoading(false); } if (coreKitInstance.status === COREKIT_STATUS.LOGGED_IN) { await setupProvider(); + setUserInformation(); + setIsLoading(false); } if (coreKitInstance.status === COREKIT_STATUS.REQUIRED_SHARE) { @@ -154,16 +154,31 @@ function App() { "required more shares, please enter your backup/ device factor key, or reset account unrecoverable once reset, please use it with caution]" ); } - console.log("coreKitInstance.status", coreKitInstance.status); setCoreKitStatus(coreKitInstance.status); }; + useEffect(() => { + const checkForRecoveryInitiation = async () => { + if (coreKitInstance.status === COREKIT_STATUS.REQUIRED_SHARE) { + navigate("/recovery"); + uiConsole( + "required more shares, please enter your backup/ device factor key, or reset account unrecoverable once reset, please use it with caution]" + ); + } + } + checkForRecoveryInitiation(); + }, [coreKitStatus]) + + useEffect(() => { + setIsLoading(globalLoading || false); + }, [globalLoading]); + useEffect(() => { const instance = new Web3AuthMPCCoreKit({ web3AuthClientId: "BPi5PB_UiIZ-cPz1GtV5i1I2iOSOHuimiXBI0e-Oe_u6X3oVAbCiAZOTEBtTXw4tsluTITPqA8zMsfxIKMjiqNQ", web3AuthNetwork: selectedNetwork, - uxMode: "redirect", + uxMode: "popup", manualSync: false, storage: window.localStorage, tssLib: selectedTssLib, @@ -190,32 +205,30 @@ function App() { if (!coreKitInstance) { throw new Error("initiated to login"); } - const verifierConfig = { - aggregateVerifierIdentifier: "web-aggregate-core-kit", - subVerifierDetailsArray: [ - { - typeOfLogin: "google", - verifier: "web3-aggreate-google", - clientId: "759944447575-6rm643ia1i9ngmnme3eq5viiep5rp6s0.apps.googleusercontent.com", - jwtParams: { - verifierIdField: "email", - }, - }, - ], - }; + const verifierConfig = { + subVerifierDetails: { + typeOfLogin: "google", + verifier: "w3a-google-demo", + clientId: "519228911939-cri01h55lsjbsia1k7ll6qpalrus75ps.apps.googleusercontent.com", + }, + }; // const verifierConfig = { - // subVerifierDetails: { - // typeOfLogin: "google", - // verifier: "w3-google-temp", - // clientId: "759944447575-6rm643ia1i9ngmnme3eq5viiep5rp6s0.apps.googleusercontent.com", - // }, - // } as SubVerifierDetailsParams; + // aggregateVerifierIdentifier: "web-aggregate-core-kit", + // subVerifierDetails: [ + // { + // typeOfLogin: "google", + // verifier: "web3-aggreate-google", + // clientId: "759944447575-6rm643ia1i9ngmnme3eq5viiep5rp6s0.apps.googleusercontent.com", + // }, + // ], + // }; await coreKitInstance.loginWithOAuth(verifierConfig as any); if (coreKitInstance.status === COREKIT_STATUS.LOGGED_IN) { await coreKitInstance.commitChanges(); // Needed for new accounts } setCoreKitStatus(coreKitInstance.status); + setUserInformation(); } catch (error: unknown) { console.error(error); } finally { @@ -249,10 +262,11 @@ function App() { await coreKitInstance.loginWithOAuth(verifierConfig); // IMP END - Login - setCoreKitStatus(coreKitInstance.status); if (coreKitInstance.status === COREKIT_STATUS.LOGGED_IN) { await coreKitInstance.commitChanges(); // Needed for new accounts } + setCoreKitStatus(coreKitInstance.status); + setUserInformation(); } catch (error: unknown) { uiConsole(error); } finally { @@ -260,6 +274,11 @@ function App() { } }; + const setUserInformation = () => { + const userInfo = coreKitInstance.getUserInfo(); + setUserInfo(userInfo); + getShareDescriptions(); + } return (
{isLoading ? ( @@ -274,7 +293,9 @@ function App() { coreKitStatus === COREKIT_STATUS.LOGGED_IN ? ( ) : ( - + <> + + ) } diff --git a/demo/redirect-flow-example/src/serviceWorkerRegistration.ts b/demo/redirect-flow-example/src/serviceWorkerRegistration.ts new file mode 100644 index 0000000..4025027 --- /dev/null +++ b/demo/redirect-flow-example/src/serviceWorkerRegistration.ts @@ -0,0 +1,142 @@ +// This optional code is used to register a service worker. +// register() is not called by default. + +// This lets the app load faster on subsequent visits in production, and gives +// it offline capabilities. However, it also means that developers (and users) +// will only see deployed updates on subsequent visits to a page, after all the +// existing tabs open on the page have been closed, since previously cached +// resources are updated in the background. + +// To learn more about the benefits of this model and instructions on how to +// opt-in, read https://cra.link/PWA + +const isLocalhost = Boolean( + window.location.hostname === 'localhost' || + // [::1] is the IPv6 localhost address. + window.location.hostname === '[::1]' || + // 127.0.0.0/8 are considered localhost for IPv4. + window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/) +); + +type Config = { + onSuccess?: (registration: ServiceWorkerRegistration) => void; + onUpdate?: (registration: ServiceWorkerRegistration) => void; +}; + +export function register(config?: Config) { + if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { + // The URL constructor is available in all browsers that support SW. + const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); + if (publicUrl.origin !== window.location.origin) { + // Our service worker won't work if PUBLIC_URL is on a different origin + // from what our page is served on. This might happen if a CDN is used to + // serve assets; see https://github.com/facebook/create-react-app/issues/2374 + return; + } + + window.addEventListener('load', () => { + const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; + + if (isLocalhost) { + // This is running on localhost. Let's check if a service worker still exists or not. + checkValidServiceWorker(swUrl, config); + + // Add some additional logging to localhost, pointing developers to the + // service worker/PWA documentation. + navigator.serviceWorker.ready.then(() => { + console.log( + 'This web app is being served cache-first by a service ' + + 'worker. To learn more, visit https://cra.link/PWA' + ); + }); + } else { + // Is not localhost. Just register service worker + registerValidSW(swUrl, config); + } + }); + } +} + +function registerValidSW(swUrl: string, config?: Config) { + navigator.serviceWorker + .register(swUrl) + .then((registration) => { + registration.onupdatefound = () => { + const installingWorker = registration.installing; + if (installingWorker == null) { + return; + } + installingWorker.onstatechange = () => { + if (installingWorker.state === 'installed') { + if (navigator.serviceWorker.controller) { + // At this point, the updated precached content has been fetched, + // but the previous service worker will still serve the older + // content until all client tabs are closed. + console.log( + 'New content is available and will be used when all ' + + 'tabs for this page are closed. See https://cra.link/PWA.' + ); + + // Execute callback + if (config && config.onUpdate) { + config.onUpdate(registration); + } + } else { + // At this point, everything has been precached. + // It's the perfect time to display a + // "Content is cached for offline use." message. + console.log('Content is cached for offline use.'); + + // Execute callback + if (config && config.onSuccess) { + config.onSuccess(registration); + } + } + } + }; + }; + }) + .catch((error) => { + console.error('Error during service worker registration:', error); + }); +} + +function checkValidServiceWorker(swUrl: string, config?: Config) { + // Check if the service worker can be found. If it can't reload the page. + fetch(swUrl, { + headers: { 'Service-Worker': 'script' }, + }) + .then((response) => { + // Ensure service worker exists, and that we really are getting a JS file. + const contentType = response.headers.get('content-type'); + if ( + response.status === 404 || + (contentType != null && contentType.indexOf('javascript') === -1) + ) { + // No service worker found. Probably a different app. Reload the page. + navigator.serviceWorker.ready.then((registration) => { + registration.unregister().then(() => { + window.location.reload(); + }); + }); + } else { + // Service worker found. Proceed as normal. + registerValidSW(swUrl, config); + } + }) + .catch(() => { + console.log('No internet connection found. App is running in offline mode.'); + }); +} + +export function unregister() { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.ready + .then((registration) => { + registration.unregister(); + }) + .catch((error) => { + console.error(error.message); + }); + } +} \ No newline at end of file From 9390e9dddacd8278315188f6df82863beb3d2880 Mon Sep 17 00:00:00 2001 From: Guru Date: Thu, 12 Dec 2024 10:31:13 +0530 Subject: [PATCH 4/6] feat: ui comments --- .../authenticator/AuthenticatorScan.tsx | 11 +++-- .../authenticator/AuthenticatorVerify.tsx | 16 ++++---- .../mfa-cards/mnemonic/CreateMnemonic.tsx | 11 +++-- .../mfa-cards/mnemonic/VerifyMnemonic.tsx | 6 ++- .../mfa-cards/password/ConfirmPassword.tsx | 34 ++++++++++++++-- .../mfa-cards/password/CreatePassword.tsx | 40 +++++++++++++++---- .../components/transactions/SignMessage.tsx | 4 +- .../transactions/TransactionCard.tsx | 2 +- .../src/components/types.ts | 9 ++++- 9 files changed, 103 insertions(+), 30 deletions(-) diff --git a/demo/redirect-flow-example/src/components/mfa-cards/authenticator/AuthenticatorScan.tsx b/demo/redirect-flow-example/src/components/mfa-cards/authenticator/AuthenticatorScan.tsx index 20d0630..c2cd1ff 100644 --- a/demo/redirect-flow-example/src/components/mfa-cards/authenticator/AuthenticatorScan.tsx +++ b/demo/redirect-flow-example/src/components/mfa-cards/authenticator/AuthenticatorScan.tsx @@ -15,7 +15,7 @@ import { getEcCrypto } from "../../../App"; import { keccak256 } from "ethereum-cryptography/keccak"; const AuthenticatorQRCodeCard: React.FC = () => { - const { coreKitInstance, setDrawerHeading, setDrawerInfo } = useCoreKit(); + const { coreKitInstance, setDrawerHeading, setDrawerInfo, setAddShareType } = useCoreKit(); const [imageUrl, setImageUrl] = React.useState(""); const [currentStep, setCurrentStep] = React.useState("register"); const [secretKey, setSecretKey] = React.useState(""); @@ -213,18 +213,21 @@ const AuthenticatorQRCodeCard: React.FC = () => { await coreKitInstance.enableMFA({ factorKey: factorKey?.private, additionalMetadata: { shareType: TssShareType.RECOVERY.toString() }, - shareDescription: FactorKeyTypeShareDescription.Other, + shareDescription: "Authenticator" as FactorKeyTypeShareDescription, }); } else { await coreKitInstance.createFactor({ shareType: TssShareType.DEVICE, factorKey: factorKey?.private, + additionalMetadata: { shareType: "Authenticator" }, + shareDescription: "Authenticator" as FactorKeyTypeShareDescription, }); } if (coreKitInstance.status === COREKIT_STATUS.LOGGED_IN) { await coreKitInstance.commitChanges(); } + setAddShareType("") // await inputBackupFactorKey(mnemonic); }; @@ -248,7 +251,9 @@ const AuthenticatorQRCodeCard: React.FC = () => {

Verify Authenticator Code

- setCode(e.target.value)} label="6 Digit Code" placeholder="Enter code" className="mb-4" /> + setCode(e.target.value)} placeholder="Enter code" className="mb-4" classes={{ + container: "flex flex-col justify-center items-center", + }}/> diff --git a/demo/redirect-flow-example/src/components/mfa-cards/authenticator/AuthenticatorVerify.tsx b/demo/redirect-flow-example/src/components/mfa-cards/authenticator/AuthenticatorVerify.tsx index ba275dc..a5d6487 100644 --- a/demo/redirect-flow-example/src/components/mfa-cards/authenticator/AuthenticatorVerify.tsx +++ b/demo/redirect-flow-example/src/components/mfa-cards/authenticator/AuthenticatorVerify.tsx @@ -14,30 +14,29 @@ const VerifyAuthenticatorCodeCard: React.FC = () => { const { coreKitInstance, inputBackupFactorKey } = useCoreKit(); const navigate = useNavigate(); const [isLoading, setIsLoading] = React.useState(false); + const [error, setError] = React.useState(""); const verifyExistingAuthenticator = async () => { setIsLoading(true); + setError(""); try { if (!coreKitInstance || !code) { throw new Error("coreKitInstance is not set"); } - - // const pubKey = getEcCrypto().keyFromPublic(coreKitInstance.getPubKey()).getPublic(); const pubKey = coreKitInstance.tKey.getTSSPub().toSEC1(coreKitInstance.tKey.tssCurve, false); - const pubKey2 = getEcCrypto().keyFromPublic(pubKey).getPublic(); + const pubKeypoint = getEcCrypto().keyFromPublic(pubKey).getPublic(); const { data: { data: dataFactor }, } = await axios.post(`${authenticatorVerifierUrl}/api/v1/verify`, { - address: `${pubKey2.getX()?.toString("hex") ?? ""}${pubKey2.getY()?.toString("hex") ?? ""}`, - // address: `${coreKitInstance.tKey.metadata.pubKey.x?.toString("hex") ?? ""}${coreKitInstance.tKey.metadata.pubKey.y?.toString("hex") ?? ""}`, + address: `${pubKeypoint.getX()?.toString("hex") ?? ""}${pubKeypoint.getY()?.toString("hex") ?? ""}`, code, }); - console.log(dataFactor.factorKey); await inputBackupFactorKey(dataFactor.factorKey); navigate("/"); } catch (error: any) { console.error(error); + setError((error as Error).message || "An error occurred while verifying the authenticator code."); if (error.response && error.response.data && error.response.data.code) throw new Error("Generic error"); throw error; } finally { @@ -57,7 +56,10 @@ const VerifyAuthenticatorCodeCard: React.FC = () => {

Verify Authenticator Code

- setCode(e.target.value)} label="6 Digit Code" placeholder="Enter code" className="mb-4" /> + setCode(e.target.value)} placeholder="Enter code" className="mb-4" classes={{ + container: "flex flex-col justify-center items-center", + }} /> + {error &&

{error}

} diff --git a/demo/redirect-flow-example/src/components/mfa-cards/mnemonic/CreateMnemonic.tsx b/demo/redirect-flow-example/src/components/mfa-cards/mnemonic/CreateMnemonic.tsx index 7e1bbf1..294f31e 100644 --- a/demo/redirect-flow-example/src/components/mfa-cards/mnemonic/CreateMnemonic.tsx +++ b/demo/redirect-flow-example/src/components/mfa-cards/mnemonic/CreateMnemonic.tsx @@ -6,7 +6,7 @@ import { COREKIT_STATUS, FactorKeyTypeShareDescription, generateFactorKey, keyTo import BN from "bn.js"; const CreateMnemonicPhraseCard: React.FC = () => { - const { coreKitInstance, setDrawerHeading, setDrawerInfo } = useCoreKit(); + const { coreKitInstance, setDrawerHeading, setDrawerInfo, setAddShareType } = useCoreKit(); const [mnemonic, setMnemonic] = React.useState(""); const [factorKey, setFactorKey] = React.useState(null); const [isLoading, setIsLoading] = React.useState(false); @@ -28,13 +28,15 @@ const CreateMnemonicPhraseCard: React.FC = () => { if (coreKitInstance.getTssFactorPub().length === 1) { await coreKitInstance.enableMFA({ factorKey: factorKey, - additionalMetadata: { shareType: TssShareType.RECOVERY.toString() }, + additionalMetadata: { shareType: "SeedPhrase" }, shareDescription: FactorKeyTypeShareDescription.SeedPhrase, }); } else { await coreKitInstance.createFactor({ shareType: TssShareType.RECOVERY, factorKey: factorKey, + additionalMetadata: { shareType: "SeedPhrase" }, + shareDescription: FactorKeyTypeShareDescription.SeedPhrase, }); } @@ -46,6 +48,7 @@ const CreateMnemonicPhraseCard: React.FC = () => { } setDrawerHeading("Seed Phrase"); setDrawerInfo("Seed phrase has been set successfully"); + setAddShareType(""); } catch (error) { console.error(error); } finally { @@ -58,12 +61,12 @@ const CreateMnemonicPhraseCard: React.FC = () => {
-

Enter Mnemonic Phrase

+

Your Mnemonic Phrase