@lukso/up-connector 0.6.0 → 0.7.0-dev.360c7b1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/account-modal.cjs +3 -3
- package/dist/account-modal.js +2 -2
- package/dist/auto-setup.cjs +3 -3
- package/dist/auto-setup.js +2 -2
- package/dist/{avatar-CmUCtW_w.d.cts → avatar-CQkubMTK.d.cts} +0 -1
- package/dist/{avatar-CmUCtW_w.d.ts → avatar-CQkubMTK.d.ts} +0 -1
- package/dist/avatar.cjs +2 -2
- package/dist/avatar.d.cts +1 -1
- package/dist/avatar.d.ts +1 -1
- package/dist/avatar.js +1 -1
- package/dist/backup-modal.cjs +3 -3
- package/dist/backup-modal.js +2 -2
- package/dist/{chunk-W7QI6BTA.cjs → chunk-4YK3Q32C.cjs} +3 -3
- package/dist/chunk-4YK3Q32C.cjs.map +1 -0
- package/dist/{chunk-ORJK2YGG.cjs → chunk-7LQ5EB2X.cjs} +22 -24
- package/dist/chunk-7LQ5EB2X.cjs.map +1 -0
- package/dist/{chunk-KMCCANMJ.js → chunk-DI4MT7EC.js} +2 -2
- package/dist/chunk-DI4MT7EC.js.map +1 -0
- package/dist/{chunk-IAKQFHFD.cjs → chunk-E34NRQRA.cjs} +8 -12
- package/dist/chunk-E34NRQRA.cjs.map +1 -0
- package/dist/{chunk-6N35TCFT.js → chunk-GKAVIDXP.js} +21 -23
- package/dist/chunk-GKAVIDXP.js.map +1 -0
- package/dist/{chunk-NWCNJSG3.js → chunk-I5I6SZZ5.js} +8 -4
- package/dist/chunk-I5I6SZZ5.js.map +1 -0
- package/dist/{chunk-YIWSPI4I.js → chunk-LIHQISFN.js} +2 -2
- package/dist/{chunk-GFVUWAG4.cjs → chunk-MEEN5QJZ.cjs} +3 -3
- package/dist/{chunk-GFVUWAG4.cjs.map → chunk-MEEN5QJZ.cjs.map} +1 -1
- package/dist/{chunk-SAQWNAQ6.js → chunk-NIMT2B6H.js} +51 -80
- package/dist/{chunk-SAQWNAQ6.js.map → chunk-NIMT2B6H.js.map} +1 -1
- package/dist/{chunk-GCYDV7FB.cjs → chunk-QIKRPHWT.cjs} +47 -76
- package/dist/chunk-QIKRPHWT.cjs.map +1 -0
- package/dist/{chunk-3SGSPHOZ.js → chunk-RCCGJ3DC.js} +7 -11
- package/dist/chunk-RCCGJ3DC.js.map +1 -0
- package/dist/{chunk-XGIT7YUY.js → chunk-UPWE4L5Z.js} +2 -2
- package/dist/{chunk-XGIT7YUY.js.map → chunk-UPWE4L5Z.js.map} +1 -1
- package/dist/{chunk-7ETKG6KR.cjs → chunk-UQZN2AKN.cjs} +9 -5
- package/dist/chunk-UQZN2AKN.cjs.map +1 -0
- package/dist/{chunk-XOKG3KIL.cjs → chunk-ZWXGWUXQ.cjs} +2 -2
- package/dist/{chunk-XOKG3KIL.cjs.map → chunk-ZWXGWUXQ.cjs.map} +1 -1
- package/dist/connect-modal/index.cjs +2 -2
- package/dist/connect-modal/index.d.cts +1 -1
- package/dist/connect-modal/index.d.ts +1 -1
- package/dist/connect-modal/index.js +1 -1
- package/dist/index.cjs +23 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +13 -14
- package/dist/index.js.map +1 -1
- package/dist/restore-modal.cjs +3 -3
- package/dist/restore-modal.d.cts +2 -2
- package/dist/restore-modal.d.ts +2 -2
- package/dist/restore-modal.js +2 -2
- package/dist/{wagmi-DgjkdmGk.d.cts → wagmi-84MPgN9w.d.cts} +0 -15
- package/dist/{wagmi-DgjkdmGk.d.ts → wagmi-84MPgN9w.d.ts} +0 -15
- package/package.json +7 -7
- package/src/auto-setup.ts +0 -1
- package/src/avatar.ts +20 -23
- package/src/backup-modal.ts +6 -2
- package/src/connect-modal/components/connection-view.ts +16 -9
- package/src/connect-modal/components/eoa-connection-view.ts +9 -5
- package/src/connect-modal/components/qr-code-view.ts +4 -4
- package/src/connect-modal/connect-modal.templates.ts +7 -6
- package/src/connect-modal/connect-modal.ts +17 -60
- package/src/connect-modal/styles/styles.css +1 -1
- package/src/connector.ts +4 -8
- package/src/popup-instance.ts +3 -4
- package/src/restore-modal.ts +5 -3
- package/src/styles/styles.css +1 -1
- package/dist/chunk-3SGSPHOZ.js.map +0 -1
- package/dist/chunk-6N35TCFT.js.map +0 -1
- package/dist/chunk-7ETKG6KR.cjs.map +0 -1
- package/dist/chunk-GCYDV7FB.cjs.map +0 -1
- package/dist/chunk-IAKQFHFD.cjs.map +0 -1
- package/dist/chunk-KMCCANMJ.js.map +0 -1
- package/dist/chunk-NWCNJSG3.js.map +0 -1
- package/dist/chunk-ORJK2YGG.cjs.map +0 -1
- package/dist/chunk-W7QI6BTA.cjs.map +0 -1
- /package/dist/{chunk-YIWSPI4I.js.map → chunk-LIHQISFN.js.map} +0 -0
|
@@ -4,7 +4,11 @@
|
|
|
4
4
|
* Main connection view displaying primary Lukso connectors and option to show EOA connectors.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
withDeviceService,
|
|
9
|
+
withIntlService,
|
|
10
|
+
withTheme,
|
|
11
|
+
} from '@lukso/core/mixins'
|
|
8
12
|
import { html, type TemplateResult } from 'lit'
|
|
9
13
|
import { property } from 'lit/decorators.js'
|
|
10
14
|
|
|
@@ -25,8 +29,8 @@ import { walletConnectDeepLinkUrl } from '../utils/walletConnectDeepLinkUrl'
|
|
|
25
29
|
|
|
26
30
|
const logInfo = debug('connect-modal:info')
|
|
27
31
|
|
|
28
|
-
export class ConnectionView extends
|
|
29
|
-
withDeviceService(ConnectModalBase)
|
|
32
|
+
export class ConnectionView extends withTheme(
|
|
33
|
+
withIntlService(withDeviceService(ConnectModalBase))
|
|
30
34
|
) {
|
|
31
35
|
@property({ type: Boolean }) isConnecting = false
|
|
32
36
|
@property({ type: String }) connectingRdns: string | undefined = undefined
|
|
@@ -272,6 +276,7 @@ export class ConnectionView extends withIntlService(
|
|
|
272
276
|
return html`
|
|
273
277
|
<lukso-button
|
|
274
278
|
variant="secondary"
|
|
279
|
+
.theme=${this.theme}
|
|
275
280
|
size=${this.device?.isMobile ? 'medium' : 'large'}
|
|
276
281
|
is-full-width
|
|
277
282
|
?disabled=${isDisabled}
|
|
@@ -283,7 +288,7 @@ export class ConnectionView extends withIntlService(
|
|
|
283
288
|
name=${iconName}
|
|
284
289
|
size=${this.device?.isMobile ? 'small' : 'medium'}
|
|
285
290
|
class="mr-2"
|
|
286
|
-
secondary-color="neutral-100"
|
|
291
|
+
secondary-color="${this.theme === 'dark' ? 'neutral-20' : 'neutral-100'}"
|
|
287
292
|
></lukso-icon>
|
|
288
293
|
${label}
|
|
289
294
|
</lukso-button>
|
|
@@ -344,12 +349,12 @@ export class ConnectionView extends withIntlService(
|
|
|
344
349
|
private renderDivider(): TemplateResult<1> {
|
|
345
350
|
return html`
|
|
346
351
|
<div class="relative w-full my-2">
|
|
347
|
-
<div class="paragraph-inter-12-regular relative z-[1] bg-neutral-98 dark:bg-neutral-
|
|
352
|
+
<div class="paragraph-inter-12-regular relative z-[1] bg-neutral-98 dark:bg-neutral-10 px-4 text-neutral-40 dark:text-neutral-95 inline-block">
|
|
348
353
|
${this.formatMessage('connect_modal_or')}
|
|
349
354
|
</div>
|
|
350
|
-
<div class="absolute top-[13px] left-0 right-0 h-px bg-neutral-80 dark:bg-neutral-
|
|
355
|
+
<div class="absolute top-[13px] left-0 right-0 h-px bg-neutral-80 dark:bg-neutral-80" />
|
|
351
356
|
</div>
|
|
352
|
-
<div class="paragraph-inter-16-regular py-4">
|
|
357
|
+
<div class="paragraph-inter-16-regular py-4 text-neutral-20 dark:text-neutral-100">
|
|
353
358
|
${this.formatMessage('connect_modal_or_info')}
|
|
354
359
|
</div>
|
|
355
360
|
`
|
|
@@ -361,13 +366,13 @@ export class ConnectionView extends withIntlService(
|
|
|
361
366
|
<button
|
|
362
367
|
@click=${this.handleClose}
|
|
363
368
|
>
|
|
364
|
-
${renderCloseButton()}
|
|
369
|
+
${renderCloseButton(this.theme)}
|
|
365
370
|
</button>
|
|
366
371
|
</div>
|
|
367
372
|
<div class="flex flex-col items-center text-center">
|
|
368
373
|
${renderLogo()}
|
|
369
374
|
${renderTitle(this.formatMessage('connect_modal_title'))}
|
|
370
|
-
<p class="mb-6 paragraph-inter-16-regular">
|
|
375
|
+
<p class="mb-6 paragraph-inter-16-regular text-neutral-20 dark:text-neutral-100">
|
|
371
376
|
${this.formatMessage('connect_modal_description')}
|
|
372
377
|
</p>
|
|
373
378
|
<div class="${cn('flex w-full gap-2 mb-4', this.device?.isMobile ? 'flex-col-reverse' : 'flex-col')}">
|
|
@@ -378,6 +383,7 @@ export class ConnectionView extends withIntlService(
|
|
|
378
383
|
variant="secondary"
|
|
379
384
|
size=${this.device?.isMobile ? 'medium' : 'large'}
|
|
380
385
|
is-full-width
|
|
386
|
+
.theme=${this.theme}
|
|
381
387
|
?disabled=${this.isConnecting}
|
|
382
388
|
@click=${this.handleShowEoaConnections}
|
|
383
389
|
>
|
|
@@ -385,6 +391,7 @@ export class ConnectionView extends withIntlService(
|
|
|
385
391
|
name="wallet-outline"
|
|
386
392
|
size=${this.device?.isMobile ? 'small' : 'medium'}
|
|
387
393
|
class="mr-2"
|
|
394
|
+
color="${this.theme === 'dark' ? 'neutral-100' : 'neutral-20'}"
|
|
388
395
|
></lukso-icon>
|
|
389
396
|
${this.formatMessage('connect_modal_other_connectors')}
|
|
390
397
|
</lukso-button>
|
|
@@ -5,7 +5,11 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { Task } from '@lit/task'
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
withDeviceService,
|
|
10
|
+
withIntlService,
|
|
11
|
+
withTheme,
|
|
12
|
+
} from '@lukso/core/mixins'
|
|
9
13
|
import debug from 'debug'
|
|
10
14
|
import { html, nothing, type TemplateResult } from 'lit'
|
|
11
15
|
import { property, state } from 'lit/decorators.js'
|
|
@@ -40,8 +44,8 @@ import { getWagmiSetup } from '../services/wagmi'
|
|
|
40
44
|
|
|
41
45
|
const logInfo = debug('connect-modal:info')
|
|
42
46
|
|
|
43
|
-
export class EoaConnectionView extends
|
|
44
|
-
withDeviceService(ConnectModalBase)
|
|
47
|
+
export class EoaConnectionView extends withTheme(
|
|
48
|
+
withIntlService(withDeviceService(ConnectModalBase))
|
|
45
49
|
) {
|
|
46
50
|
@property({ type: Array }) connectors: WalletConnector[] = []
|
|
47
51
|
|
|
@@ -382,13 +386,13 @@ export class EoaConnectionView extends withIntlService(
|
|
|
382
386
|
<button
|
|
383
387
|
@click=${this.handleBack}
|
|
384
388
|
>
|
|
385
|
-
${renderBackButton()}
|
|
389
|
+
${renderBackButton(this.theme)}
|
|
386
390
|
</button>
|
|
387
391
|
|
|
388
392
|
<button
|
|
389
393
|
@click=${this.handleClose}
|
|
390
394
|
>
|
|
391
|
-
${renderCloseButton()}
|
|
395
|
+
${renderCloseButton(this.theme)}
|
|
392
396
|
</button>
|
|
393
397
|
</div>
|
|
394
398
|
<div class="flex flex-col items-center text-center">
|
|
@@ -10,12 +10,12 @@ import { ConnectModalBase } from '../connect-modal.base'
|
|
|
10
10
|
|
|
11
11
|
// Import lukso web components
|
|
12
12
|
import '@lukso/web-components/dist/components/lukso-qr-code'
|
|
13
|
-
import { withIntlService } from '@lukso/core/mixins'
|
|
13
|
+
import { withIntlService, withTheme } from '@lukso/core/mixins'
|
|
14
14
|
import { property } from 'lit/decorators.js'
|
|
15
15
|
import { renderBackButton, renderCloseButton } from '../connect-modal.templates'
|
|
16
16
|
import cubeGlassImage from '../images/up-cube-glass.png'
|
|
17
17
|
|
|
18
|
-
export class QrCodeView extends withIntlService(ConnectModalBase) {
|
|
18
|
+
export class QrCodeView extends withTheme(withIntlService(ConnectModalBase)) {
|
|
19
19
|
@property({ type: String }) data: string | undefined = undefined
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -41,13 +41,13 @@ export class QrCodeView extends withIntlService(ConnectModalBase) {
|
|
|
41
41
|
<button
|
|
42
42
|
@click=${this.handleBack}
|
|
43
43
|
>
|
|
44
|
-
${renderBackButton()}
|
|
44
|
+
${renderBackButton(this.theme)}
|
|
45
45
|
</button>
|
|
46
46
|
|
|
47
47
|
<button
|
|
48
48
|
@click=${this.handleClose}
|
|
49
49
|
>
|
|
50
|
-
${renderCloseButton()}
|
|
50
|
+
${renderCloseButton(this.theme)}
|
|
51
51
|
</button>
|
|
52
52
|
</div>
|
|
53
53
|
<div class="flex flex-col items-center text-center">
|
|
@@ -1,21 +1,22 @@
|
|
|
1
|
+
import type { Theme } from '@lukso/core'
|
|
1
2
|
import { cn } from '@lukso/web-components/tools'
|
|
2
3
|
import { html } from 'lit'
|
|
3
4
|
import cubeGlassImage from './images/up-cube-glass.png'
|
|
4
5
|
|
|
5
|
-
export const renderCloseButton = () =>
|
|
6
|
+
export const renderCloseButton = (theme: Theme) =>
|
|
6
7
|
html`<lukso-icon name="close-lg"
|
|
7
|
-
class="cursor-pointer transition-opacity hover:opacity-60"></lukso-icon>`
|
|
8
|
+
class="cursor-pointer transition-opacity hover:opacity-60" color="${theme === 'dark' ? 'neutral-100' : 'neutral-20'}"></lukso-icon>`
|
|
8
9
|
|
|
9
|
-
export const renderBackButton = () =>
|
|
10
|
-
html`<lukso-icon name="arrow-left-lg" class="cursor-pointer transition-opacity hover:opacity-60"></lukso-icon>`
|
|
10
|
+
export const renderBackButton = (theme: Theme) =>
|
|
11
|
+
html`<lukso-icon name="arrow-left-lg" class="cursor-pointer transition-opacity hover:opacity-60" color="${theme === 'dark' ? 'neutral-100' : 'neutral-20'}"></lukso-icon>`
|
|
11
12
|
|
|
12
13
|
export const renderLogo = () =>
|
|
13
14
|
html`<img src="${cubeGlassImage}" alt="" class="mb-5 w-14 animate-bounce2" />`
|
|
14
15
|
|
|
15
16
|
export const renderTitle = (title: string) =>
|
|
16
|
-
html`<h2 class="m-0 mb-4 text-neutral-20 dark:text-
|
|
17
|
+
html`<h2 class="m-0 mb-4 text-neutral-20 dark:text-neutral-100 heading-inter-21-semi-bold">
|
|
17
18
|
${title}
|
|
18
19
|
</h2>`
|
|
19
20
|
|
|
20
21
|
export const renderPlaceholder = (style: string) =>
|
|
21
|
-
html`<div class="${cn('bg-neutral-90 dark:bg-neutral-
|
|
22
|
+
html`<div class="${cn('bg-neutral-90 dark:bg-neutral-20 rounded-4 animate-pulse', style)}"></div>`
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Framework-agnostic connection modal for wallet/profile connections.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { withDeviceService } from '@lukso/core/mixins'
|
|
7
|
+
import { withDeviceService, withTheme } from '@lukso/core/mixins'
|
|
8
8
|
import debug from 'debug'
|
|
9
9
|
import { html, type TemplateResult } from 'lit'
|
|
10
10
|
import { property, state } from 'lit/decorators.js'
|
|
@@ -12,7 +12,6 @@ import { property, state } from 'lit/decorators.js'
|
|
|
12
12
|
import { ConnectModalBase } from './connect-modal.base.js'
|
|
13
13
|
import type {
|
|
14
14
|
ConnectionModalView,
|
|
15
|
-
ConnectModalTheme,
|
|
16
15
|
WalletConnector,
|
|
17
16
|
} from './connect-modal.types'
|
|
18
17
|
import { fromWagmiConnectors, getWagmiSetup } from './services/wagmi'
|
|
@@ -24,64 +23,26 @@ import './components/qr-code-view'
|
|
|
24
23
|
|
|
25
24
|
const logInfo = debug('connect-modal:info')
|
|
26
25
|
|
|
27
|
-
export class ConnectModal extends
|
|
26
|
+
export class ConnectModal extends withTheme(
|
|
27
|
+
withDeviceService(ConnectModalBase)
|
|
28
|
+
) {
|
|
28
29
|
// Public properties
|
|
29
30
|
@property({ type: Boolean, reflect: true }) open = false
|
|
30
|
-
@property({ type: String, reflect: true }) theme: ConnectModalTheme = 'light'
|
|
31
31
|
|
|
32
32
|
// Private state
|
|
33
33
|
@state() private connectors: WalletConnector[] = []
|
|
34
|
-
|
|
34
|
+
// isDark state is provided by withTheme mixin
|
|
35
35
|
@state() private modalView: ConnectionModalView = 'up_connection'
|
|
36
36
|
@state() private qrCodeData: string | undefined = undefined
|
|
37
37
|
|
|
38
|
-
private mediaQueryList: MediaQueryList | null = null
|
|
39
|
-
|
|
40
38
|
updated(changedProperties: Map<string, any>): void {
|
|
39
|
+
super.updated(changedProperties)
|
|
40
|
+
|
|
41
41
|
// Reset view and load connectors when modal opens
|
|
42
42
|
if (changedProperties.has('open') && this.open) {
|
|
43
43
|
this.modalView = 'up_connection' // Reset to main view when modal opens
|
|
44
44
|
this.loadConnectors()
|
|
45
45
|
}
|
|
46
|
-
|
|
47
|
-
// Handle theme changes
|
|
48
|
-
if (changedProperties.has('theme')) {
|
|
49
|
-
this.updateTheme()
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
connectedCallback(): void {
|
|
54
|
-
super.connectedCallback()
|
|
55
|
-
this.updateTheme()
|
|
56
|
-
|
|
57
|
-
// Listen for system theme changes when in 'auto' mode
|
|
58
|
-
if (this.theme === 'auto') {
|
|
59
|
-
this.mediaQueryList = window.matchMedia('(prefers-color-scheme: dark)')
|
|
60
|
-
this.mediaQueryList.addEventListener(
|
|
61
|
-
'change',
|
|
62
|
-
this.handleMediaQueryChange
|
|
63
|
-
)
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
disconnectedCallback(): void {
|
|
68
|
-
super.disconnectedCallback()
|
|
69
|
-
|
|
70
|
-
if (this.mediaQueryList) {
|
|
71
|
-
this.mediaQueryList.removeEventListener(
|
|
72
|
-
'change',
|
|
73
|
-
this.handleMediaQueryChange
|
|
74
|
-
)
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Handle system theme changes
|
|
80
|
-
*
|
|
81
|
-
* @param event
|
|
82
|
-
*/
|
|
83
|
-
private handleMediaQueryChange = (event: MediaQueryListEvent): void => {
|
|
84
|
-
this.isDark = event.matches
|
|
85
46
|
}
|
|
86
47
|
|
|
87
48
|
/**
|
|
@@ -95,17 +56,6 @@ export class ConnectModal extends withDeviceService(ConnectModalBase) {
|
|
|
95
56
|
)
|
|
96
57
|
}
|
|
97
58
|
|
|
98
|
-
/**
|
|
99
|
-
* Update isDark state based on theme property
|
|
100
|
-
*/
|
|
101
|
-
private updateTheme(): void {
|
|
102
|
-
if (this.theme === 'auto') {
|
|
103
|
-
this.isDark = window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
104
|
-
} else {
|
|
105
|
-
this.isDark = this.theme === 'dark'
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
59
|
private async loadConnectors(): Promise<void> {
|
|
110
60
|
const globalWagmiSetup = getWagmiSetup()
|
|
111
61
|
logInfo('Global wagmi setup:', globalWagmiSetup)
|
|
@@ -217,12 +167,17 @@ export class ConnectModal extends withDeviceService(ConnectModalBase) {
|
|
|
217
167
|
private renderModalContent(): TemplateResult<1> {
|
|
218
168
|
switch (this.modalView) {
|
|
219
169
|
case 'qr_code':
|
|
220
|
-
return html`<qr-code-view
|
|
221
|
-
|
|
170
|
+
return html`<qr-code-view
|
|
171
|
+
.data=${this.qrCodeData}
|
|
172
|
+
.theme=${this.theme}
|
|
173
|
+
@on-back=${this.handleBackToConnectionView}
|
|
174
|
+
@on-close=${this.handleClose}
|
|
175
|
+
></qr-code-view>`
|
|
222
176
|
case 'eoa_connection':
|
|
223
177
|
return html`
|
|
224
178
|
<eoa-connection-view
|
|
225
179
|
.connectors=${this.connectors}
|
|
180
|
+
.theme=${this.theme}
|
|
226
181
|
@on-back=${this.handleBackToConnectionView}
|
|
227
182
|
@on-close=${this.handleClose}
|
|
228
183
|
@on-connect=${this.handleOnConnectSuccess}
|
|
@@ -233,6 +188,7 @@ export class ConnectModal extends withDeviceService(ConnectModalBase) {
|
|
|
233
188
|
return html`
|
|
234
189
|
<connection-view
|
|
235
190
|
.connectors=${this.connectors}
|
|
191
|
+
.theme=${this.theme}
|
|
236
192
|
@on-back=${this.handleBackToConnectionView}
|
|
237
193
|
@on-close=${this.handleClose}
|
|
238
194
|
@on-connect=${this.handleOnConnectSuccess}
|
|
@@ -250,9 +206,10 @@ export class ConnectModal extends withDeviceService(ConnectModalBase) {
|
|
|
250
206
|
?is-open=${this.open}
|
|
251
207
|
?has-bottom-padding=${!!(this.device?.isIOS && this.device?.isSafari)}
|
|
252
208
|
size="auto"
|
|
209
|
+
.theme=${this.theme}
|
|
253
210
|
@on-backdrop-click=${this.handleClose}
|
|
254
211
|
>
|
|
255
|
-
<div class="p-6
|
|
212
|
+
<div class="p-6 w-full sm:w-[372px]">
|
|
256
213
|
${this.renderModalContent()}
|
|
257
214
|
</div>
|
|
258
215
|
</lukso-modal>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@import "@lukso/web-components/
|
|
1
|
+
@import "@lukso/web-components/tools/styles/main.css";
|
package/src/connector.ts
CHANGED
|
@@ -31,11 +31,7 @@ import {
|
|
|
31
31
|
getConnection,
|
|
32
32
|
watchConnection,
|
|
33
33
|
} from './connect-modal/index.js'
|
|
34
|
-
import type {
|
|
35
|
-
ConnectionState,
|
|
36
|
-
ConnectorConfig,
|
|
37
|
-
WalletProvider,
|
|
38
|
-
} from './types.js'
|
|
34
|
+
import type { ConnectionState, ConnectorConfig } from './types.js'
|
|
39
35
|
|
|
40
36
|
const DEFAULT_CONFIG: Required<
|
|
41
37
|
Omit<ConnectorConfig, 'avatar' | 'modal' | 'onConnectionChange'>
|
|
@@ -52,12 +48,12 @@ export class UPConnector {
|
|
|
52
48
|
private avatar?: DraggableAvatar
|
|
53
49
|
private connectModal?: ConnectModal
|
|
54
50
|
private accountModal?: AccountModal
|
|
55
|
-
private connectors: WalletConnector[] = []
|
|
56
51
|
private connectionState: ConnectionState = 'disconnected'
|
|
57
52
|
private connectedAddress?: string
|
|
58
53
|
private connectedProvider?: any
|
|
59
54
|
private connectedChainId?: number
|
|
60
55
|
private wagmiUnsubscribe?: (() => void) | null
|
|
56
|
+
connectors: WalletConnector[] = []
|
|
61
57
|
|
|
62
58
|
constructor(config: ConnectorConfig = {}) {
|
|
63
59
|
this.config = { ...DEFAULT_CONFIG, ...config }
|
|
@@ -194,7 +190,7 @@ export class UPConnector {
|
|
|
194
190
|
// TODO: Replace with Lit-based account management modal
|
|
195
191
|
// Legacy createModal() method removed - was using deprecated ConnectorModal
|
|
196
192
|
|
|
197
|
-
private handleAvatarClick(
|
|
193
|
+
private handleAvatarClick(_event: MouseEvent): void {
|
|
198
194
|
if (this.connectionState === 'connected') {
|
|
199
195
|
// Show account management modal
|
|
200
196
|
this.showAccountModal()
|
|
@@ -221,7 +217,7 @@ export class UPConnector {
|
|
|
221
217
|
|
|
222
218
|
// Handle connect event
|
|
223
219
|
this.connectModal.addEventListener('connect', ((e: CustomEvent) => {
|
|
224
|
-
const
|
|
220
|
+
const _connector = e.detail.connector as WalletConnector
|
|
225
221
|
// TODO: Handle actual connection logic
|
|
226
222
|
// For now, this will be extended when wagmi/viem integration is added
|
|
227
223
|
}) as EventListener)
|
package/src/popup-instance.ts
CHANGED
|
@@ -53,7 +53,7 @@ class PopupEventEmitter {
|
|
|
53
53
|
if (!this.handlers.has(event)) {
|
|
54
54
|
this.handlers.set(event, new Set())
|
|
55
55
|
}
|
|
56
|
-
this.handlers.get(event)
|
|
56
|
+
this.handlers.get(event)?.add(handler)
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
off(event: string, handler: (...args: any[]) => void): void {
|
|
@@ -197,7 +197,7 @@ export class ModalPopupInstance extends BasePopupInstance {
|
|
|
197
197
|
|
|
198
198
|
// Remove from DOM after animation
|
|
199
199
|
setTimeout(() => {
|
|
200
|
-
if (this.modalElement
|
|
200
|
+
if (this.modalElement?.parentNode) {
|
|
201
201
|
this.modalElement.parentNode.removeChild(this.modalElement)
|
|
202
202
|
}
|
|
203
203
|
}, 300)
|
|
@@ -212,7 +212,7 @@ export class ModalPopupInstance extends BasePopupInstance {
|
|
|
212
212
|
if (this.modalElement) {
|
|
213
213
|
this.modalElement.classList.remove('visible')
|
|
214
214
|
setTimeout(() => {
|
|
215
|
-
if (this.modalElement
|
|
215
|
+
if (this.modalElement?.parentNode) {
|
|
216
216
|
this.modalElement.parentNode.removeChild(this.modalElement)
|
|
217
217
|
}
|
|
218
218
|
}, 300)
|
|
@@ -525,7 +525,6 @@ export class WindowPopupInstance extends BasePopupInstance {
|
|
|
525
525
|
left = screenLeft + windowWidth - width - 20
|
|
526
526
|
top = screenTop + 20
|
|
527
527
|
break
|
|
528
|
-
case 'center':
|
|
529
528
|
default:
|
|
530
529
|
left = screenLeft + (windowWidth - width) / 2
|
|
531
530
|
top = screenTop + (windowHeight - height) / 2
|
package/src/restore-modal.ts
CHANGED
|
@@ -43,14 +43,14 @@ export class RestoreModal extends CoreLitElement {
|
|
|
43
43
|
@state() private password = ''
|
|
44
44
|
@state() private passwordErrors: string[] = []
|
|
45
45
|
@state() private isRestoring = false
|
|
46
|
-
@state() private walletData: WalletData | null = null
|
|
47
46
|
@state() private validationWarnings: string[] = []
|
|
48
|
-
@state() private validationInfo: string[] = []
|
|
49
47
|
@state() private controllers: Array<{
|
|
50
48
|
address: string
|
|
51
49
|
status: 'new' | 'existing'
|
|
52
50
|
}> = []
|
|
53
51
|
@state() private restoredAddresses: string[] = []
|
|
52
|
+
validationInfo: string[] = []
|
|
53
|
+
walletData: WalletData | null = null
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Public method for parent to set preview result
|
|
@@ -208,7 +208,9 @@ export class RestoreModal extends CoreLitElement {
|
|
|
208
208
|
label="Password"
|
|
209
209
|
placeholder="Enter decryption password"
|
|
210
210
|
.value=${this.password}
|
|
211
|
-
@on-input=${(e: CustomEvent) =>
|
|
211
|
+
@on-input=${(e: CustomEvent) => {
|
|
212
|
+
this.password = e.detail.value
|
|
213
|
+
}}
|
|
212
214
|
@keyup=${(e: KeyboardEvent) => e.key === 'Enter' && canProceed && this.previewRestore()}
|
|
213
215
|
is-full-width
|
|
214
216
|
autofocus
|
package/src/styles/styles.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@import "@lukso/web-components/
|
|
1
|
+
@import "@lukso/web-components/tools/styles/main.css";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/restore-modal.ts"],"sourcesContent":["/**\n * Restore Modal - Lit Component\n *\n * Framework-agnostic restore modal for wallet data import.\n * Uses lukso-modal from @lukso/web-components for consistent UI.\n */\n\nimport type {\n BackupFile,\n PasskeyAuthProvider,\n WalletData,\n} from '@lukso/passkey-auth'\nimport { readBackupFile } from '@lukso/passkey-auth'\nimport { html, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { CoreLitElement } from './styles'\n\n// Import lukso web components\nimport '@lukso/web-components/dist/components/lukso-modal'\nimport '@lukso/web-components/dist/components/lukso-button'\nimport '@lukso/web-components/dist/components/lukso-input'\n\nenum Step {\n UPLOAD = 1,\n PASSWORD = 2,\n PREVIEW = 3,\n SUCCESS = 4,\n}\n\n@customElement('restore-modal')\nexport class RestoreModal extends CoreLitElement {\n // Public properties\n @property({ type: Boolean, reflect: true }) isOpen = false\n @property({ type: String }) theme: 'light' | 'dark' | 'auto' = 'auto'\n @property({ type: Object }) keyGenerator: PasskeyAuthProvider | null = null\n\n // Private state\n @state() private currentStep: Step = Step.UPLOAD\n @state() private selectedFile: File | null = null\n @state() private backupData: BackupFile | null = null\n @state() private fileError: string | null = null\n @state() private isDragging = false\n @state() private password = ''\n @state() private passwordErrors: string[] = []\n @state() private isRestoring = false\n @state() private walletData: WalletData | null = null\n @state() private validationWarnings: string[] = []\n @state() private validationInfo: string[] = []\n @state() private controllers: Array<{\n address: string\n status: 'new' | 'existing'\n }> = []\n @state() private restoredAddresses: string[] = []\n\n /**\n * Public method for parent to set preview result\n * Called after parent handles the 'preview' event\n */\n public setPreviewResult(options: {\n controllers: Array<{ address: string; status: 'new' | 'existing' }>\n warnings?: string[]\n }) {\n this.controllers = options.controllers\n this.validationWarnings = options.warnings || []\n }\n\n /**\n * Public method for parent to set validation result\n * Called after parent handles the 'validate' event\n */\n public setValidationResult(\n walletData: WalletData | null,\n options?: {\n error?: string\n warnings?: string[]\n info?: string[]\n }\n ) {\n this.isRestoring = false\n\n if (options?.error) {\n this.passwordErrors = [options.error]\n this.validationWarnings = []\n this.validationInfo = []\n } else if (walletData) {\n this.walletData = walletData\n this.validationWarnings = options?.warnings || []\n this.validationInfo = options?.info || []\n this.currentStep = Step.SUCCESS\n }\n }\n\n render() {\n return html`\n <lukso-modal\n ?is-open=${this.isOpen}\n size=\"medium\"\n @on-backdrop-click=${this.close}\n >\n <div class=\"p-6\">\n <!-- Header -->\n <h2 class=\"m-0 mb-6 text-neutral-20 dark:text-white heading-inter-21-semi-bold\">\n ${this.getStepTitle()}\n </h2>\n\n <!-- Step content -->\n ${this.renderStep()}\n </div>\n </lukso-modal>\n `\n }\n\n private renderStep() {\n switch (this.currentStep) {\n case Step.UPLOAD:\n return this.renderUploadStep()\n case Step.PASSWORD:\n return this.renderPasswordStep()\n case Step.PREVIEW:\n return this.renderPreviewStep()\n case Step.SUCCESS:\n return this.renderSuccessStep()\n default:\n return nothing\n }\n }\n\n private renderUploadStep() {\n return html`\n <p class=\"mb-6 text-neutral-40 dark:text-neutral-50 paragraph-inter-16-regular\">\n Select your backup file to restore your wallet data. Your backup file stays on your device and is never uploaded.\n </p>\n\n <div\n class=\"border-2 border-dashed rounded-xl p-10 text-center bg-neutral-95 dark:bg-neutral-80 transition-all cursor-pointer my-6 ${\n this.isDragging\n ? 'border-blue-60 bg-blue-95 dark:bg-blue-95/10'\n : this.fileError\n ? 'border-red-55 bg-red-95'\n : 'border-neutral-90 dark:border-neutral-70'\n }\"\n @drop=${this.handleDrop}\n @dragover=${this.handleDragOver}\n @dragleave=${this.handleDragLeave}\n @click=${this.triggerFileInput}\n >\n <div class=\"flex flex-col items-center gap-3\">\n <p class=\"m-0 text-neutral-10 dark:text-white heading-inter-16-semi-bold\">\n Drag and drop your backup file here\n </p>\n <p class=\"m-0 text-neutral-40 paragraph-inter-14-regular\">or</p>\n <lukso-button\n variant=\"primary\"\n @click=${(e: Event) => {\n e.stopPropagation()\n this.triggerFileInput()\n }}\n >\n Choose File\n </lukso-button>\n ${\n this.selectedFile\n ? html`\n <p class=\"mt-2 mb-0 text-green-54 paragraph-inter-14-semi-bold\">\n ${this.selectedFile.name}\n </p>\n `\n : nothing\n }\n ${\n this.fileError\n ? html`\n <p class=\"mt-2 mb-0 text-red-55 paragraph-inter-14-semi-bold\">\n ${this.fileError}\n </p>\n `\n : nothing\n }\n </div>\n </div>\n\n <input\n type=\"file\"\n class=\"hidden\"\n accept=\".json\"\n @change=${this.handleFileSelect}\n />\n\n <div class=\"flex justify-end mt-6\">\n <lukso-button variant=\"text\" @click=${this.close}>\n Cancel\n </lukso-button>\n </div>\n `\n }\n\n private renderPasswordStep() {\n const canProceed = this.password && this.password.length > 0\n\n return html`\n <p class=\"mb-5 text-neutral-40 dark:text-neutral-50 paragraph-inter-14-regular\">\n This backup is encrypted. Enter the password to decrypt it.\n </p>\n\n <div>\n <lukso-input\n type=\"password\"\n label=\"Password\"\n placeholder=\"Enter decryption password\"\n .value=${this.password}\n @on-input=${(e: CustomEvent) => (this.password = e.detail.value)}\n @keyup=${(e: KeyboardEvent) => e.key === 'Enter' && canProceed && this.previewRestore()}\n is-full-width\n autofocus\n ></lukso-input>\n ${this.passwordErrors.map(\n (error) => html`\n <div class=\"mt-1 text-red-55 paragraph-inter-13-regular\">${error}</div>\n `\n )}\n </div>\n\n <div class=\"flex justify-between gap-3 mt-6\">\n <div class=\"flex gap-3\">\n <lukso-button variant=\"text\" @click=${this.close}>\n Cancel\n </lukso-button>\n <lukso-button variant=\"secondary\" @click=${this.goBack}>\n Back\n </lukso-button>\n </div>\n <lukso-button\n variant=\"primary\"\n ?disabled=${!canProceed || this.isRestoring}\n ?is-loading=${this.isRestoring}\n @click=${this.previewRestore}\n >\n Continue\n </lukso-button>\n </div>\n `\n }\n\n private renderPreviewStep() {\n return html`\n <p class=\"mb-6 text-neutral-40 dark:text-neutral-50 paragraph-inter-16-regular\">\n ${\n this.controllers.length > 0\n ? `Found ${this.controllers.length} controller${this.controllers.length === 1 ? '' : 's'} in backup.`\n : 'No controllers found in backup.'\n }\n </p>\n\n ${\n this.controllers.length > 0\n ? html`\n <div class=\"mb-6\">\n <div class=\"mb-3 text-neutral-20 dark:text-neutral-90 paragraph-inter-14-semi-bold\">\n Controllers:\n </div>\n ${this.controllers.map(\n (controller) => html`\n <div class=\"bg-neutral-95 dark:bg-neutral-80 border border-neutral-90 dark:border-neutral-70 rounded-lg px-3 py-2.5 mb-2\">\n <div class=\"flex items-center justify-between\">\n <div class=\"text-neutral-40 paragraph-inter-13-regular font-mono\">\n ${this.truncateAddress(controller.address)}\n </div>\n <div\n class=\"px-2 py-0.5 rounded text-xs font-semibold ${\n controller.status === 'new'\n ? 'bg-green-95 dark:bg-green-95/10 text-green-55 border border-green-55/30'\n : 'bg-neutral-90 dark:bg-neutral-70 text-neutral-50 border border-neutral-80 dark:border-neutral-60'\n }\"\n >\n ${controller.status === 'new' ? 'NEW' : 'EXISTS'}\n </div>\n </div>\n <div class=\"text-neutral-60 paragraph-inter-12-regular mt-1\">\n ${controller.address}\n </div>\n </div>\n `\n )}\n </div>\n `\n : nothing\n }\n\n ${\n this.validationWarnings.length > 0\n ? html`\n <div class=\"mb-4\">\n ${this.validationWarnings.map(\n (warning) => html`\n <div class=\"bg-yellow-95 dark:bg-yellow-95/10 border border-yellow-55 dark:border-yellow-55/50 rounded-lg px-3 py-2.5 mb-2 flex items-start gap-2\">\n <span class=\"text-yellow-55 dark:text-yellow-55 text-lg leading-none\">⚠️</span>\n <span class=\"text-yellow-55 dark:text-yellow-55 paragraph-inter-13-regular flex-1\">${warning}</span>\n </div>\n `\n )}\n </div>\n `\n : nothing\n }\n\n <div class=\"flex justify-between gap-3 mt-6\">\n <div class=\"flex gap-3\">\n <lukso-button variant=\"text\" @click=${this.close}>\n Cancel\n </lukso-button>\n <lukso-button variant=\"secondary\" @click=${this.goBackFromPreview}>\n Back\n </lukso-button>\n </div>\n <lukso-button\n variant=\"primary\"\n @click=${this.confirmRestore}\n >\n Confirm Restore\n </lukso-button>\n </div>\n `\n }\n\n private renderSuccessStep() {\n return html`\n <!-- Success header with icon -->\n <div class=\"text-center mb-6\">\n <div class=\"w-16 h-16 mx-auto mb-4 bg-green-95 dark:bg-green-95/20 rounded-full flex items-center justify-center\">\n <span class=\"text-2xl text-green-55\">✅</span>\n </div>\n <h3 class=\"text-neutral-20 dark:text-white heading-inter-18-semi-bold mb-2\">\n Wallet Restored Successfully!\n </h3>\n <p class=\"text-neutral-40 dark:text-neutral-50 paragraph-inter-14-regular\">\n ${\n this.restoredAddresses.length > 0\n ? `Imported ${this.restoredAddresses.length} address${this.restoredAddresses.length > 1 ? 'es' : ''} to your wallet.`\n : 'Your wallet has been restored successfully.'\n }\n </p>\n </div>\n \n <!-- Restored addresses -->\n ${\n this.restoredAddresses.length > 0\n ? html`\n <div class=\"mb-6\">\n <div class=\"mb-3 text-neutral-20 dark:text-neutral-90 paragraph-inter-14-semi-bold\">\n Restored Addresses:\n </div>\n ${this.restoredAddresses.map(\n (address: string) => html`\n <div class=\"bg-green-95 dark:bg-green-95/10 border border-green-60 dark:border-green-60/50 rounded-lg px-3 py-2.5 mb-2 flex items-center gap-2\">\n <span class=\"text-green-60 dark:text-green-45 text-sm\">✓</span>\n <span class=\"text-neutral-20 dark:text-white paragraph-inter-13-regular font-mono flex-1\">${this.truncateAddress(address)}</span>\n </div>\n `\n )}\n </div>\n `\n : ''\n }\n\n <!-- Action buttons for success -->\n <div class=\"flex justify-center mt-6\">\n <lukso-button variant=\"primary\" @click=${this.close}>\n OK\n </lukso-button>\n </div>\n `\n }\n\n private getStepTitle(): string {\n switch (this.currentStep) {\n case Step.UPLOAD:\n return 'Restore Wallet'\n case Step.PASSWORD:\n return 'Enter Password'\n case Step.PREVIEW:\n return 'Review Changes'\n case Step.SUCCESS:\n return 'Restore Complete'\n default:\n return 'Restore Wallet'\n }\n }\n\n private triggerFileInput() {\n const input = this.shadowRoot?.querySelector(\n 'input[type=\"file\"]'\n ) as HTMLInputElement\n if (input) {\n input.click()\n }\n }\n\n private async handleFileSelect(e: Event) {\n const input = e.target as HTMLInputElement\n const file = input.files?.[0]\n if (file) {\n await this.handleFile(file)\n }\n }\n\n private handleDragOver(e: DragEvent) {\n e.preventDefault()\n this.isDragging = true\n }\n\n private handleDragLeave() {\n this.isDragging = false\n }\n\n private async handleDrop(e: DragEvent) {\n e.preventDefault()\n this.isDragging = false\n\n const file = e.dataTransfer?.files?.[0]\n if (file) {\n await this.handleFile(file)\n }\n }\n\n private async handleFile(file: File) {\n this.fileError = null\n\n if (!file.name.endsWith('.json')) {\n this.fileError = 'Please select a valid JSON backup file'\n return\n }\n\n try {\n // Use passkey-auth readBackupFile function\n const backup = await readBackupFile(file)\n\n this.selectedFile = file\n this.backupData = backup\n\n // Check if encrypted (handle both current and legacy formats)\n const isEncrypted = backup.encryptedSecrets // Legacy: always encrypted if encryptedSecrets exists\n ? true\n : backup.secrets?.encrypted // Current: check encrypted flag\n\n if (isEncrypted) {\n this.currentStep = Step.PASSWORD\n } else {\n // Unencrypted backup - preview directly\n await this.previewRestore()\n }\n } catch (error) {\n this.fileError =\n error instanceof Error ? error.message : 'Failed to read backup file'\n console.error('Failed to read backup file:', error)\n }\n }\n\n private async previewRestore() {\n if (!this.backupData) return\n\n this.isRestoring = true\n this.passwordErrors = []\n\n try {\n // First, we need to decrypt the backup if it's encrypted\n let decryptedBackup = this.backupData\n\n if (\n this.backupData.encryptedSecrets ||\n this.backupData.secrets?.encrypted\n ) {\n // PREVIEW ONLY: Use verify to check password and get preview data (don't actually import yet)\n if (!this.keyGenerator) {\n throw new Error('KeyGenerator not available')\n }\n\n // Use verifyBackup for preview - this validates password and returns public data only\n const verifiedBackup = await this.keyGenerator.verifyBackup(\n this.backupData,\n this.password\n )\n\n // Use the verified backup data (which has filtered public data)\n decryptedBackup = verifiedBackup\n } else {\n // Unencrypted - use data directly for preview (no import needed)\n decryptedBackup = this.backupData\n }\n\n // Extract all controller addresses from the backup\n const backupControllers = new Set<string>()\n\n // Get addresses from the secrets (the actual private keys we're restoring)\n const secretsData = (decryptedBackup.secrets?.data as any[]) || []\n for (const secret of secretsData) {\n if (secret.address) {\n backupControllers.add(secret.address.toLowerCase())\n }\n }\n\n // Also get controllers from account metadata (V2 format with networks)\n for (const account of decryptedBackup.accounts || []) {\n // V2 format: accounts have networks array with controllers\n if (account.networks) {\n for (const network of account.networks) {\n for (const controller of network.controllers || []) {\n if (controller.address) {\n backupControllers.add(controller.address.toLowerCase())\n }\n }\n }\n }\n }\n\n // Also get controllers from LSP23CrossChainDeployment if present\n const lsp23Deployments =\n (decryptedBackup as any).LSP23CrossChainDeployment || []\n for (const deployment of lsp23Deployments) {\n for (const controller of deployment.initialControllers || []) {\n if (controller.address) {\n backupControllers.add(controller.address.toLowerCase())\n }\n }\n }\n\n console.log(\n '🔍 [RestoreModal] Found controller addresses:',\n Array.from(backupControllers)\n )\n\n // Extract addresses from the decrypted backup for preview\n for (const secret of secretsData) {\n if (secret.address) {\n backupControllers.add(secret.address.toLowerCase())\n }\n }\n\n // For now, mark all addresses as 'new' - could enhance this later\n this.controllers = Array.from(backupControllers).map((address) => ({\n address,\n status: 'new' as const,\n }))\n\n this.currentStep = Step.PREVIEW\n } catch (error) {\n console.error('Failed to preview restore:', error)\n const errorMessage =\n error instanceof Error ? error.message : 'Failed to preview restore'\n\n // Check for password-specific errors\n if (errorMessage.toLowerCase().includes('password')) {\n this.passwordErrors = ['Incorrect password. Please try again.']\n } else {\n // For non-password errors, set as file error to show in upload step\n this.fileError = errorMessage\n this.currentStep = Step.UPLOAD\n // Clear the file selection so user can try again\n this.selectedFile = null\n this.backupData = null\n // Clear the file input\n const input = this.shadowRoot?.querySelector(\n 'input[type=\"file\"]'\n ) as HTMLInputElement\n if (input) {\n input.value = ''\n }\n }\n } finally {\n this.isRestoring = false\n }\n }\n\n private async confirmRestore() {\n if (!this.backupData || !this.keyGenerator) {\n console.error(\n '❌ [RestoreModal] Missing backup data or keyGenerator for restore'\n )\n this.dispatchEvent(\n new CustomEvent('error', {\n detail: { error: 'Missing backup data or keyGenerator' },\n bubbles: true,\n composed: true,\n })\n )\n return\n }\n\n try {\n this.isRestoring = true\n console.log('🔄 [RestoreModal] Starting secure restoration process...')\n\n // ✅ SECURE: Use keyGenerator.restoreFromBackup internally\n const result = await this.keyGenerator.restoreFromBackup(\n this.backupData,\n this.password\n )\n\n if (result.success) {\n console.log('✅ [RestoreModal] Restore successful:', result.addresses)\n\n // Store restored addresses for display on success screen\n this.restoredAddresses = result.addresses\n\n // Emit success event (only public addresses, no sensitive data)\n this.dispatchEvent(\n new CustomEvent('success', {\n detail: { addresses: result.addresses },\n bubbles: true,\n composed: true,\n })\n )\n\n // Move to success step\n this.currentStep = Step.SUCCESS\n } else {\n console.error('❌ [RestoreModal] Restore failed')\n this.dispatchEvent(\n new CustomEvent('error', {\n detail: {\n error:\n 'Restore failed. Please check the backup file and password.',\n },\n bubbles: true,\n composed: true,\n })\n )\n }\n } catch (error) {\n console.error('❌ [RestoreModal] Restore error:', error)\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error'\n\n this.dispatchEvent(\n new CustomEvent('error', {\n detail: { error: errorMessage },\n bubbles: true,\n composed: true,\n })\n )\n } finally {\n this.isRestoring = false\n }\n }\n\n private goBack() {\n if (this.currentStep === Step.PASSWORD) {\n this.currentStep = Step.UPLOAD\n this.password = ''\n this.passwordErrors = []\n }\n }\n\n private goBackFromPreview() {\n // Go back to password step (or upload if unencrypted)\n const isEncrypted = this.backupData?.encryptedSecrets\n ? true\n : this.backupData?.secrets?.encrypted\n\n if (isEncrypted) {\n this.currentStep = Step.PASSWORD\n } else {\n this.currentStep = Step.UPLOAD\n }\n // Clear preview data\n this.controllers = []\n this.validationWarnings = []\n }\n\n private close() {\n this.isOpen = false\n this.dispatchEvent(\n new CustomEvent('close', { bubbles: true, composed: true })\n )\n\n // Reset state after animation\n setTimeout(() => {\n this.currentStep = Step.UPLOAD\n this.selectedFile = null\n this.backupData = null\n this.fileError = null\n this.isDragging = false\n this.password = ''\n this.passwordErrors = []\n this.isRestoring = false\n this.walletData = null\n this.restoredAddresses = []\n this.controllers = []\n this.validationWarnings = []\n }, 300)\n }\n\n private truncateAddress(address: string): string {\n if (!address || address.length < 10) return address\n return `${address.slice(0, 6)}...${address.slice(-4)}`\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'restore-modal': RestoreModal\n }\n}\n"],"mappings":"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","names":[]}
|