Verify your email address!
-
- Click the link in the email we sent to {email} to sign in.
+
+ We've just sent an email to {email}.
+
+
+ Please verify that the phrase in the email matches the following words:
+
+
+
+ If it does, please click "Verify email address" to sign in.
Cancel
diff --git a/packages/keyring-core/src/index.ts b/packages/keyring-core/src/index.ts
index ba33db3e..9ee176af 100644
--- a/packages/keyring-core/src/index.ts
+++ b/packages/keyring-core/src/index.ts
@@ -89,6 +89,10 @@ export interface KeyringContextState {
agent?: Signer
}
+export interface RegisterSpaceOptions {
+ onPhrase: (phrase: string) => void
+}
+
export interface KeyringContextActions {
/**
* Load the user agent and all stored data from secure storage.
@@ -117,7 +121,7 @@ export interface KeyringContextActions {
* storage. Use cancelRegisterSpace to abort. Automatically sets the
* newly registered space as the current space.
*/
- registerSpace: (email: string) => Promise
+ registerSpace: (email: string, options?: RegisterSpaceOptions) => Promise
/**
* Abort an ongoing account registration.
*/
diff --git a/packages/react-keyring/src/Authenticator.tsx b/packages/react-keyring/src/Authenticator.tsx
index fcad710e..2520cb29 100644
--- a/packages/react-keyring/src/Authenticator.tsx
+++ b/packages/react-keyring/src/Authenticator.tsx
@@ -30,7 +30,13 @@ export type AuthenticatorContextState = KeyringContextState & {
* A callback that can be passed to an `onSubmit` handler to
* register a new space or log in using `email`
*/
- handleRegisterSubmit?: (e: React.FormEvent) => Promise
+ handleRegisterSubmit?: (e: React.FormEvent) => Promise,
+ /**
+ * A short phrase generated by the access API that should be presented to
+ * the user on the email verification wait screen. Users should be instructed
+ * to verify that the phrase in their email matches this phrase.
+ */
+ spaceRegistrationPhrase?: string
}
export type AuthenticatorContextActions = KeyringContextActions & {
@@ -103,6 +109,7 @@ export const AuthenticatorRoot: Component =
const { createSpace, registerSpace } = actions
const [email, setEmail] = useState('')
const [submitted, setSubmitted] = useState(false)
+ const [spaceRegistrationPhrase, setSpaceRegistrationPhrase] = useState('')
const handleRegisterSubmit = useCallback(
async (e: React.FormEvent) => {
@@ -110,7 +117,7 @@ export const AuthenticatorRoot: Component =
setSubmitted(true)
try {
await createSpace()
- await registerSpace(email)
+ await registerSpace(email, { onPhrase: (phrase) => { setSpaceRegistrationPhrase(phrase) } })
} catch (error: any) {
throw new Error('failed to register', { cause: error })
} finally {
@@ -122,10 +129,10 @@ export const AuthenticatorRoot: Component =
const value = useMemo(
() => [
- { ...state, email, submitted, handleRegisterSubmit },
+ { ...state, email, submitted, handleRegisterSubmit, spaceRegistrationPhrase },
{ ...actions, setEmail }
],
- [state, actions, email, submitted, handleRegisterSubmit]
+ [state, actions, email, submitted, handleRegisterSubmit, spaceRegistrationPhrase]
)
return (
@@ -194,6 +201,16 @@ export const CancelButton: Component = createComponent(
}
)
+export type SpaceRegistrationPhraseOptions = Options
+export type SpaceRegistrationPhraseProps = Props>
+
+export const SpaceRegistrationPhrase: Component = createComponent(
+ (props) => {
+ const [{spaceRegistrationPhrase}] = useAuthenticator()
+ return createElement('span', {...props, children: <>{spaceRegistrationPhrase}>})
+ }
+)
+
/**
* Use the scoped authenticator context state from a parent `Authenticator`.
*/
diff --git a/packages/react-keyring/src/providers/Keyring.tsx b/packages/react-keyring/src/providers/Keyring.tsx
index 80e8bfd4..76f13ad3 100644
--- a/packages/react-keyring/src/providers/Keyring.tsx
+++ b/packages/react-keyring/src/providers/Keyring.tsx
@@ -9,7 +9,8 @@ import {
import type {
KeyringContextState,
KeyringContextActions,
- ServiceConfig
+ ServiceConfig,
+ RegisterSpaceOptions
} from '@w3ui/keyring-core'
import type { Agent } from '@web3-storage/access'
import type { Abilities } from '@web3-storage/access/types'
@@ -102,13 +103,13 @@ export function KeyringProvider ({
return did
}
- const registerSpace = async (email: string): Promise => {
+ const registerSpace = async (email: string, opts?: RegisterSpaceOptions): Promise => {
const agent = await getAgent()
const controller = new AbortController()
setRegisterAbortController(controller)
try {
- await agent.registerSpace(email, { signal: controller.signal })
+ await agent.registerSpace(email, {...opts, signal: controller.signal })
setSpace(getCurrentSpace(agent))
setSpaces(getSpaces(agent))
} catch (error) {