Skip to content

Commit ec2545d

Browse files
authored
[magic-v2.0.1] - Add userEmail init option to handle logged in session and add configurable z-index (#935)
* Increase magic modal z-index and expose as variable * Add userEmail init option, validation and update readme and demo * Update email validation and allow null for localstorage passing, fix spelling errors in readmes * Bump common package in Magic deps * Prettier-ify validation * Add email validation to login modal * Update Magic version in demo
1 parent e855c05 commit ec2545d

File tree

12 files changed

+90
-28
lines changed

12 files changed

+90
-28
lines changed

packages/core/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ const { unsubscribe } = state.subscribe(update =>
355355
// unsubscribe()
356356
```
357357

358-
Specific top level slices of state can be subcribed to. For example you may want to just subscribe to receive updates to the `wallets` array only:
358+
Specific top level slices of state can be subscribed to. For example you may want to just subscribe to receive updates to the `wallets` array only:
359359

360360
```javascript
361361
const wallets = onboard.state.select('wallets')
@@ -522,7 +522,7 @@ Many of the wallet modules require dependencies that are not normally included i
522522

523523
### Webpack 4
524524

525-
Everything should just work since the node builtins are automatically bundled in v4
525+
Everything should just work since the node built-ins are automatically bundled in v4
526526

527527
### Webpack 5
528528

packages/demo/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222
"webpack-dev-server": "4.7.4"
2323
},
2424
"dependencies": {
25-
"@web3-onboard/core": "^2.0.4",
25+
"@web3-onboard/core": "^2.2.1",
2626
"@web3-onboard/fortmatic": "^2.0.0",
2727
"@web3-onboard/gnosis": "^2.0.0",
28-
"@web3-onboard/injected-wallets": "^2.0.3",
28+
"@web3-onboard/injected-wallets": "^2.0.5",
2929
"@web3-onboard/keepkey": "^2.0.0",
3030
"@web3-onboard/keystone": "^2.0.0",
3131
"@web3-onboard/ledger": "^2.0.0",
@@ -34,7 +34,7 @@
3434
"@web3-onboard/trezor": "^2.0.0",
3535
"@web3-onboard/walletconnect": "^2.0.0",
3636
"@web3-onboard/coinbase": "^2.0.0",
37-
"@web3-onboard/magic": "^2.0.0",
37+
"@web3-onboard/magic": "^2.0.1",
3838
"vconsole": "^3.9.5"
3939
},
4040
"license": "MIT",

packages/demo/src/App.svelte

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,10 @@
8181
const trezor = trezorModule(trezorOptions)
8282
8383
const magic = magicModule({
84-
apiKey: 'pk_live_02207D744E81C2BA'
84+
apiKey: 'pk_live_02207D744E81C2BA',
85+
// userEmail: 'test@test.com'
86+
// userEmail is optional - if user has already logged in and/or session is still active a login modal will not appear
87+
// for more info see the @web3-onboard/magic docs
8588
})
8689
8790
const onboard = Onboard({

packages/magic/README.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@ in the same fashion that all other web3-onboard UI components are
1212

1313
`npm i @web3-onboard/magic`
1414

15-
Head over to https://magic.link/ and signup to get an API key
15+
Head over to https://magic.link/ and sign up to get an API key
1616

1717
## Options
1818

1919
```typescript
20-
type magicOptions = {
20+
type MagicInitOptions = {
2121
apiKey: string
22+
userEmail?: string // optional - if user has already logged in and/or session is still active a login modal will not appear
2223
}
2324
```
2425
@@ -28,7 +29,7 @@ type magicOptions = {
2829
import Onboard from '@web3-onboard/core'
2930
import magicModule from '@web3-onboard/magic'
3031

31-
const magic = magicModule({ apiKey: 'API_KEY' })
32+
const magic = magicModule({ apiKey: 'API_KEY', userEmail: localStorage.getItem('magicUserEmail') })
3233

3334
const onboard = Onboard({
3435
// ... other Onboard options
@@ -43,13 +44,17 @@ console.log(connectedWallets)
4344
```
4445

4546
### Accessing the Magic Wallet Internals
46-
When a Magic wallet is connect the Magic instance is exposed.
47+
When a Magic wallet is connected the Magic instance is exposed.
4748
This can be used to get information such as user MetaData, update a user's email address or handle the user's token.
49+
The user's email can be set in local storage and passed through the `MagicInitOptions` to avoid a user having to login again if they are returning to the DApp within the set user session time.
50+
Magic has a default time of 7 days and this can be configured through your Magic API Key settings.
4851
```typescript
4952
const [magicWallet] = await onboard.connectWallet()
5053

5154
try {
5255
const { email, publicAddress } = await magicWallet.instance.user.getMetadata();
56+
localStorage.setItem('magicUserEmail', email)
57+
// This email can then be passed through the MagicInitOptions to continue the users session and avoid having to login again
5358
} catch {
5459
// Handle errors if required!
5560
}

packages/magic/package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@web3-onboard/magic",
3-
"version": "2.0.0",
3+
"version": "2.0.1",
44
"description": "Magic module for Onboard.js",
55
"scripts": {
66
"build": "rollup -c",
@@ -42,8 +42,9 @@
4242
"typescript": "^4.5.5"
4343
},
4444
"dependencies": {
45-
"@web3-onboard/common": "^2.0.3",
45+
"@web3-onboard/common": "^2.0.5",
4646
"magic-sdk": "^8.1.0",
47-
"rxjs": "^7.5.2"
47+
"rxjs": "^7.5.2",
48+
"joi": "^17.4.2"
4849
}
4950
}

packages/magic/rollup.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,5 @@ export default {
3535
inlineSources: !production
3636
})
3737
],
38-
external: ['rxjs', 'magic-sdk', '@web3-onboard/common']
38+
external: ['joi', 'rxjs', 'magic-sdk', '@web3-onboard/common']
3939
}

packages/magic/src/index.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
1-
import type { WalletInit, APIKey, EIP1193Provider } from '@web3-onboard/common'
1+
import type { WalletInit, EIP1193Provider } from '@web3-onboard/common'
2+
import type { MagicInitOptions } from './types'
3+
import { validateMagicInitOptions } from './validation'
24

3-
function magic(options: APIKey): WalletInit {
4-
const { apiKey } = options
5+
function magic(options: MagicInitOptions): WalletInit {
6+
if (options) {
7+
const error = validateMagicInitOptions(options)
8+
9+
if (error) {
10+
throw error
11+
}
12+
}
13+
const { apiKey, userEmail } = options
514
const walletName = 'Magic Wallet'
615

716
return () => {
@@ -12,7 +21,6 @@ function magic(options: APIKey): WalletInit {
1221
const { Magic, RPCErrorCode } = await import('magic-sdk')
1322
const loginModal = (await import('./login-modal.js')).default
1423
const brandingHTML = (await import('./branding.js')).default
15-
let loggedIn: boolean = false
1624

1725
const {
1826
createEIP1193Provider,
@@ -24,7 +32,7 @@ function magic(options: APIKey): WalletInit {
2432

2533
if (!chains.length)
2634
throw new Error(
27-
'Atleast one Chain must be passed to onboard in order to connect'
35+
'At least one Chain must be passed to onboard in order to connect'
2836
)
2937

3038
let currentChain = chains[0]
@@ -38,6 +46,8 @@ function magic(options: APIKey): WalletInit {
3846
network: customNodeOptions
3947
})
4048

49+
let loggedIn: boolean
50+
4151
const loginWithEmail = async (emailAddress: string) => {
4252
try {
4353
await magicInstance.auth.loginWithMagicLink({ email: emailAddress })
@@ -49,6 +59,8 @@ function magic(options: APIKey): WalletInit {
4959
}
5060
}
5161

62+
if (userEmail) loggedIn = await loginWithEmail(userEmail)
63+
5264
const handleLogin = async () => {
5365
loggedIn = await loginModal({
5466
walletName: walletName,

packages/magic/src/login-modal.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ const mountLoginModal = (
8383
/* SPACING */
8484
--margin-4: 1rem;
8585
--margin-5: 0.5rem;
86+
87+
/* MODAL POSITIONING */
88+
--z-index: 25;
8689
}
8790
8891
</style>

packages/magic/src/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,9 @@ export type LoginOptions = {
44
emailLoginFunction: EmailLoginFunction
55
}
66

7+
export type MagicInitOptions = {
8+
apiKey: string,
9+
userEmail?: string,
10+
}
11+
712
export type EmailLoginFunction = (emailAddress: string) => Promise<boolean>

packages/magic/src/validation.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import Joi from 'joi'
2+
import type { MagicInitOptions } from './types'
3+
4+
const userEmail = Joi.string()
5+
.email({ tlds: { allow: false } })
6+
.allow(null)
7+
8+
const magicOptions = Joi.object({
9+
apiKey: Joi.string().required(),
10+
userEmail: userEmail
11+
})
12+
13+
type ValidateReturn = Joi.ValidationResult | null
14+
15+
const validate = (validator: Joi.Schema, data: unknown): ValidateReturn => {
16+
const result = validator.validate(data)
17+
return result.error ? result : null
18+
}
19+
20+
export const validateMagicInitOptions = (
21+
data: MagicInitOptions
22+
): ValidateReturn => {
23+
return validate(magicOptions, data)
24+
}
25+
26+
export const validateUserEmail = (email: string): ValidateReturn => {
27+
return validate(userEmail, email)
28+
}

packages/magic/src/view/LoginModal.svelte

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { fade } from 'svelte/transition'
33
import type { Subject } from 'rxjs'
44
5+
import { validateUserEmail } from '../validation'
56
import CloseButton from '../elements/CloseButton.svelte'
67
import Spinner from '../elements/Spinner.svelte'
78
import type { LoginOptions } from '../types'
@@ -19,16 +20,13 @@
1920
errorInEmail = false
2021
}
2122
22-
const emailRegex =
23-
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
24-
2523
const validateEmail = (value: string) => {
26-
return emailRegex.test(value)
24+
return validateUserEmail(value)
2725
}
2826
2927
const login = async () => {
3028
loading = true
31-
if (!validateEmail(credentials)) {
29+
if (validateEmail(credentials)) {
3230
errorInEmail = true
3331
loading = false
3432
return
@@ -42,6 +40,12 @@
4240
loggedIn$.next(false)
4341
loading = false
4442
}
43+
44+
const submitOnEnter = (e: KeyboardEvent) => {
45+
if (e.key === 'Enter') {
46+
login();
47+
}
48+
}
4549
</script>
4650

4751
<style>
@@ -120,7 +124,7 @@
120124
position: absolute;
121125
top: 0;
122126
right: 0;
123-
z-index: 20;
127+
z-index: var(--login-modal-z-index, var(--z-index));
124128
display: flex;
125129
align-items: center;
126130
justify-content: center;
@@ -130,7 +134,7 @@
130134
background-color: rgba(0, 0, 0, 0.2);
131135
}
132136
133-
.login-modal {
137+
.onboard-magic-login-modal {
134138
min-width: 36rem;
135139
max-height: 51.75rem;
136140
display: table;
@@ -166,7 +170,7 @@
166170
</style>
167171

168172
<div class="container">
169-
<div class="login-modal" transition:fade>
173+
<div class="onboard-magic-login-modal" transition:fade>
170174
<div class="close-action-container close" on:click={dismiss}>
171175
<CloseButton />
172176
</div>
@@ -178,6 +182,7 @@
178182
placeholder="Email address"
179183
bind:value={credentials}
180184
on:input={() => setErrorInEmail()}
185+
on:keydown={submitOnEnter}
181186
/>
182187
{#if errorInEmail}
183188
<span class="error-msg">Please enter a valid email address</span>

packages/react/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ type UseConnectWallet = (): [
164164
]
165165

166166
type ConnectOptions = {
167-
autoSelect?: string // wallet name to autoselect for user
167+
autoSelect?: string // wallet name to auto-select for user
168168
}
169169

170170
type DisconnectOptions = {

0 commit comments

Comments
 (0)