@lukso/up-connector 0.4.0-dev.a8c9315
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/LICENSE +201 -0
- package/README.md +280 -0
- package/dist/account-modal.cjs +9 -0
- package/dist/account-modal.cjs.map +1 -0
- package/dist/account-modal.d.cts +16 -0
- package/dist/account-modal.d.ts +16 -0
- package/dist/account-modal.js +9 -0
- package/dist/account-modal.js.map +1 -0
- package/dist/auto-setup.cjs +17 -0
- package/dist/auto-setup.cjs.map +1 -0
- package/dist/auto-setup.d.cts +123 -0
- package/dist/auto-setup.d.ts +123 -0
- package/dist/auto-setup.js +17 -0
- package/dist/auto-setup.js.map +1 -0
- package/dist/avatar-CmUCtW_w.d.cts +205 -0
- package/dist/avatar-CmUCtW_w.d.ts +205 -0
- package/dist/avatar.cjs +12 -0
- package/dist/avatar.cjs.map +1 -0
- package/dist/avatar.d.cts +1 -0
- package/dist/avatar.d.ts +1 -0
- package/dist/avatar.js +12 -0
- package/dist/avatar.js.map +1 -0
- package/dist/backup-modal.cjs +9 -0
- package/dist/backup-modal.cjs.map +1 -0
- package/dist/backup-modal.d.cts +41 -0
- package/dist/backup-modal.d.ts +41 -0
- package/dist/backup-modal.js +9 -0
- package/dist/backup-modal.js.map +1 -0
- package/dist/chunk-3SGSPHOZ.js +595 -0
- package/dist/chunk-3SGSPHOZ.js.map +1 -0
- package/dist/chunk-6AYZOIFY.js +181 -0
- package/dist/chunk-6AYZOIFY.js.map +1 -0
- package/dist/chunk-6N35TCFT.js +852 -0
- package/dist/chunk-6N35TCFT.js.map +1 -0
- package/dist/chunk-7ETKG6KR.cjs +387 -0
- package/dist/chunk-7ETKG6KR.cjs.map +1 -0
- package/dist/chunk-EUXUH3YW.js +15 -0
- package/dist/chunk-EUXUH3YW.js.map +1 -0
- package/dist/chunk-GFVUWAG4.cjs +158 -0
- package/dist/chunk-GFVUWAG4.cjs.map +1 -0
- package/dist/chunk-IAKQFHFD.cjs +595 -0
- package/dist/chunk-IAKQFHFD.cjs.map +1 -0
- package/dist/chunk-MH7MP7XK.cjs +181 -0
- package/dist/chunk-MH7MP7XK.cjs.map +1 -0
- package/dist/chunk-NWCNJSG3.js +387 -0
- package/dist/chunk-NWCNJSG3.js.map +1 -0
- package/dist/chunk-NXU2DQAV.js +1128 -0
- package/dist/chunk-NXU2DQAV.js.map +1 -0
- package/dist/chunk-ORJK2YGG.cjs +852 -0
- package/dist/chunk-ORJK2YGG.cjs.map +1 -0
- package/dist/chunk-RFA6SEIS.cjs +1128 -0
- package/dist/chunk-RFA6SEIS.cjs.map +1 -0
- package/dist/chunk-XGIT7YUY.js +31 -0
- package/dist/chunk-XGIT7YUY.js.map +1 -0
- package/dist/chunk-XOKG3KIL.cjs +31 -0
- package/dist/chunk-XOKG3KIL.cjs.map +1 -0
- package/dist/chunk-YIWSPI4I.js +158 -0
- package/dist/chunk-YIWSPI4I.js.map +1 -0
- package/dist/chunk-ZBDE64SD.cjs +15 -0
- package/dist/chunk-ZBDE64SD.cjs.map +1 -0
- package/dist/connect-modal/index.cjs +20 -0
- package/dist/connect-modal/index.cjs.map +1 -0
- package/dist/connect-modal/index.d.cts +9 -0
- package/dist/connect-modal/index.d.ts +9 -0
- package/dist/connect-modal/index.js +20 -0
- package/dist/connect-modal/index.js.map +1 -0
- package/dist/index-D2orHGFi.d.cts +8 -0
- package/dist/index-D2orHGFi.d.ts +8 -0
- package/dist/index.cjs +793 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +189 -0
- package/dist/index.d.ts +189 -0
- package/dist/index.js +793 -0
- package/dist/index.js.map +1 -0
- package/dist/restore-modal.cjs +9 -0
- package/dist/restore-modal.cjs.map +1 -0
- package/dist/restore-modal.d.cts +68 -0
- package/dist/restore-modal.d.ts +68 -0
- package/dist/restore-modal.js +9 -0
- package/dist/restore-modal.js.map +1 -0
- package/dist/wagmi-CVuDs_0h.d.cts +386 -0
- package/dist/wagmi-CVuDs_0h.d.ts +386 -0
- package/package.json +158 -0
- package/src/account-modal.ts +142 -0
- package/src/auto-setup.ts +362 -0
- package/src/avatar.ts +1135 -0
- package/src/backup-modal.ts +439 -0
- package/src/connect-modal/components/connection-view.ts +398 -0
- package/src/connect-modal/components/eoa-connection-view.ts +408 -0
- package/src/connect-modal/components/qr-code-view.ts +71 -0
- package/src/connect-modal/connect-modal.base.ts +18 -0
- package/src/connect-modal/connect-modal.config.ts +27 -0
- package/src/connect-modal/connect-modal.templates.ts +21 -0
- package/src/connect-modal/connect-modal.ts +270 -0
- package/src/connect-modal/connect-modal.types.ts +104 -0
- package/src/connect-modal/images/up-cube-glass.png +0 -0
- package/src/connect-modal/index.ts +23 -0
- package/src/connect-modal/services/wagmi.ts +266 -0
- package/src/connect-modal/styles/styles.css +1 -0
- package/src/connect-modal/utils/walletConnectDeepLinkUrl.ts +43 -0
- package/src/connector.ts +544 -0
- package/src/index.ts +62 -0
- package/src/popup-instance.ts +537 -0
- package/src/restore-modal.ts +702 -0
- package/src/styles/index.ts +28 -0
- package/src/styles/styles.css +1 -0
- package/src/types/css-raw.d.ts +4 -0
- package/src/types/images.d.ts +4 -0
- package/src/types.ts +168 -0
package/src/connector.ts
ADDED
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UP Connector - Main class that orchestrates avatar and modal
|
|
3
|
+
* Provides smooth avatar-to-modal animations and connection state management
|
|
4
|
+
*
|
|
5
|
+
* NOTE: This connector uses Lit-based modal components:
|
|
6
|
+
* - <connect-modal> for wallet connection (configured via setupConnectModal())
|
|
7
|
+
* - <account-modal> for account management (shows address, chain, disconnect)
|
|
8
|
+
*
|
|
9
|
+
* Current implementation status:
|
|
10
|
+
* - ✅ Avatar integration (DraggableAvatar with IconView)
|
|
11
|
+
* - ✅ Connection modal (Lit-based ConnectModal)
|
|
12
|
+
* - ✅ Account management modal (Lit-based AccountModal)
|
|
13
|
+
* - ✅ Wagmi synchronization
|
|
14
|
+
*
|
|
15
|
+
* The legacy ConnectorModal (vanilla JS) has been removed. The config.modal property
|
|
16
|
+
* is deprecated and has no effect - use setupConnectModal() instead.
|
|
17
|
+
*
|
|
18
|
+
* Users can pre-place modal components in DOM for custom positioning:
|
|
19
|
+
* - Place <connect-modal> or <account-modal> anywhere in your HTML
|
|
20
|
+
* - The connector will find and reuse existing modals instead of creating new ones
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { DraggableAvatar } from './avatar.js'
|
|
24
|
+
import './connect-modal/index.js' // Import for side-effect (registers custom element)
|
|
25
|
+
import './account-modal.js' // Import for side-effect (registers custom element)
|
|
26
|
+
import { setLuksoConfig } from '@lukso/transaction-view-headless'
|
|
27
|
+
import type { AccountModal } from './account-modal.js'
|
|
28
|
+
import type { ConnectModal, WalletConnector } from './connect-modal/index.js'
|
|
29
|
+
import {
|
|
30
|
+
disconnectWagmi,
|
|
31
|
+
getWagmiAccount,
|
|
32
|
+
watchWagmiAccount,
|
|
33
|
+
} from './connect-modal/index.js'
|
|
34
|
+
import type {
|
|
35
|
+
ConnectionState,
|
|
36
|
+
ConnectorConfig,
|
|
37
|
+
WalletProvider,
|
|
38
|
+
} from './types.js'
|
|
39
|
+
|
|
40
|
+
const DEFAULT_CONFIG: Required<
|
|
41
|
+
Omit<ConnectorConfig, 'avatar' | 'modal' | 'onConnectionChange'>
|
|
42
|
+
> = {
|
|
43
|
+
autoConnect: false,
|
|
44
|
+
persistConnection: true,
|
|
45
|
+
storageKey: 'up-connector-state',
|
|
46
|
+
chainId: 42, // LUKSO mainnet
|
|
47
|
+
rpcUrl: 'https://rpc.lukso.network',
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export class UPConnector {
|
|
51
|
+
private config: ConnectorConfig & typeof DEFAULT_CONFIG
|
|
52
|
+
private avatar?: DraggableAvatar
|
|
53
|
+
private connectModal?: ConnectModal
|
|
54
|
+
private accountModal?: AccountModal
|
|
55
|
+
private connectors: WalletConnector[] = []
|
|
56
|
+
private connectionState: ConnectionState = 'disconnected'
|
|
57
|
+
private connectedAddress?: string
|
|
58
|
+
private connectedProvider?: any
|
|
59
|
+
private connectedChainId?: number
|
|
60
|
+
private wagmiUnsubscribe?: (() => void) | null
|
|
61
|
+
|
|
62
|
+
constructor(config: ConnectorConfig = {}) {
|
|
63
|
+
this.config = { ...DEFAULT_CONFIG, ...config }
|
|
64
|
+
|
|
65
|
+
// Initialize components
|
|
66
|
+
this.init()
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private async init(): Promise<void> {
|
|
70
|
+
// Create avatar immediately
|
|
71
|
+
await this.createAvatar()
|
|
72
|
+
|
|
73
|
+
// Start watching wagmi (handles both initial state and changes)
|
|
74
|
+
// This is async but non-blocking - connector works immediately
|
|
75
|
+
this.startWagmiSync()
|
|
76
|
+
|
|
77
|
+
// Try auto-connect if enabled (for non-wagmi connections)
|
|
78
|
+
if (this.config.autoConnect && this.config.persistConnection) {
|
|
79
|
+
await this.tryAutoConnect()
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Start syncing with wagmi
|
|
85
|
+
* Checks current state and subscribes to changes
|
|
86
|
+
*/
|
|
87
|
+
/**
|
|
88
|
+
* Update global Lukso config for address resolution
|
|
89
|
+
*/
|
|
90
|
+
private updateLuksoConfig(chainId: number): void {
|
|
91
|
+
try {
|
|
92
|
+
if (chainId === 42) {
|
|
93
|
+
// LUKSO Mainnet
|
|
94
|
+
setLuksoConfig({
|
|
95
|
+
chainId: 42,
|
|
96
|
+
rpcUrl: 'https://rpc.lukso.network',
|
|
97
|
+
})
|
|
98
|
+
} else if (chainId === 4201) {
|
|
99
|
+
// LUKSO Testnet
|
|
100
|
+
setLuksoConfig({
|
|
101
|
+
chainId: 4201,
|
|
102
|
+
rpcUrl: 'https://rpc.testnet.lukso.network',
|
|
103
|
+
})
|
|
104
|
+
} else {
|
|
105
|
+
// Other networks - default to mainnet config but with custom chainId
|
|
106
|
+
setLuksoConfig({
|
|
107
|
+
chainId,
|
|
108
|
+
rpcUrl: this.config.rpcUrl,
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
} catch (error) {
|
|
112
|
+
console.warn('⚠️ [Connector] Failed to update Lukso config:', error)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private async startWagmiSync(): Promise<void> {
|
|
117
|
+
try {
|
|
118
|
+
// Check initial state first
|
|
119
|
+
const account = await getWagmiAccount()
|
|
120
|
+
|
|
121
|
+
if (!account) {
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (account.isConnected && account.address) {
|
|
126
|
+
this.handleConnection(
|
|
127
|
+
account.address,
|
|
128
|
+
account.connector,
|
|
129
|
+
account.chainId
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Subscribe to wagmi account changes
|
|
134
|
+
this.wagmiUnsubscribe = await watchWagmiAccount((account) => {
|
|
135
|
+
if (account.isConnected && account.address) {
|
|
136
|
+
// Connected
|
|
137
|
+
if (
|
|
138
|
+
this.connectedAddress !== account.address ||
|
|
139
|
+
this.connectedChainId !== account.chainId
|
|
140
|
+
) {
|
|
141
|
+
this.handleConnection(
|
|
142
|
+
account.address,
|
|
143
|
+
account.connector,
|
|
144
|
+
account.chainId
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
// Disconnected
|
|
149
|
+
if (this.connectionState === 'connected') {
|
|
150
|
+
this.handleDisconnection()
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
} catch (error) {
|
|
155
|
+
console.warn('⚠️ [Connector] Failed to sync with wagmi:', error)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
private async createAvatar(): Promise<void> {
|
|
160
|
+
this.avatar = new DraggableAvatar({
|
|
161
|
+
// Default avatar options
|
|
162
|
+
avatarSize: 'medium',
|
|
163
|
+
initialPosition: 'top-right',
|
|
164
|
+
fallbackText: '👤',
|
|
165
|
+
|
|
166
|
+
// Override with user config
|
|
167
|
+
...this.config.avatar,
|
|
168
|
+
|
|
169
|
+
// Connection-specific callbacks
|
|
170
|
+
onClick: (event, data) => {
|
|
171
|
+
// Call user-defined onClick first
|
|
172
|
+
this.config.avatar?.onClick?.(event, data)
|
|
173
|
+
|
|
174
|
+
// Then handle connection logic
|
|
175
|
+
this.handleAvatarClick(event)
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
onAddressClick: (event) => {
|
|
179
|
+
// Call user-defined callback
|
|
180
|
+
this.config.avatar?.onAddressClick?.(event)
|
|
181
|
+
},
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
// Update avatar connected state
|
|
185
|
+
this.updateAvatarState()
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// TODO: Replace with Lit-based account management modal
|
|
189
|
+
// Legacy createModal() method removed - was using deprecated ConnectorModal
|
|
190
|
+
|
|
191
|
+
private handleAvatarClick(event: MouseEvent): void {
|
|
192
|
+
if (this.connectionState === 'connected') {
|
|
193
|
+
// Show account management modal
|
|
194
|
+
this.showAccountModal()
|
|
195
|
+
} else {
|
|
196
|
+
// Show connection modal
|
|
197
|
+
this.showConnectionModal()
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
private showConnectionModal(): void {
|
|
202
|
+
// First, check if user has placed a connect-modal in the DOM
|
|
203
|
+
if (!this.connectModal) {
|
|
204
|
+
this.connectModal = document.querySelector(
|
|
205
|
+
'connect-modal'
|
|
206
|
+
) as ConnectModal
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// If still not found, create and append it
|
|
210
|
+
if (!this.connectModal) {
|
|
211
|
+
this.connectModal = document.createElement(
|
|
212
|
+
'connect-modal'
|
|
213
|
+
) as ConnectModal
|
|
214
|
+
document.body.appendChild(this.connectModal as unknown as HTMLElement)
|
|
215
|
+
|
|
216
|
+
// Handle connect event
|
|
217
|
+
this.connectModal.addEventListener('connect', ((e: CustomEvent) => {
|
|
218
|
+
const connector = e.detail.connector as WalletConnector
|
|
219
|
+
// TODO: Handle actual connection logic
|
|
220
|
+
// For now, this will be extended when wagmi/viem integration is added
|
|
221
|
+
}) as EventListener)
|
|
222
|
+
|
|
223
|
+
// Handle close event
|
|
224
|
+
this.connectModal.addEventListener('close', (() => {
|
|
225
|
+
// Modal closed
|
|
226
|
+
}) as EventListener)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Modal will load connectors automatically from global setup
|
|
230
|
+
// Open the modal
|
|
231
|
+
this.connectModal.open = true
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
private showAccountModal(): void {
|
|
235
|
+
if (!this.connectedAddress) return
|
|
236
|
+
|
|
237
|
+
// First, check if user has placed an account-modal in the DOM
|
|
238
|
+
if (!this.accountModal) {
|
|
239
|
+
this.accountModal = document.querySelector(
|
|
240
|
+
'account-modal'
|
|
241
|
+
) as AccountModal
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// If still not found, create and append it
|
|
245
|
+
if (!this.accountModal) {
|
|
246
|
+
this.accountModal = document.createElement(
|
|
247
|
+
'account-modal'
|
|
248
|
+
) as AccountModal
|
|
249
|
+
document.body.appendChild(this.accountModal)
|
|
250
|
+
|
|
251
|
+
// Handle disconnect event
|
|
252
|
+
this.accountModal.addEventListener('disconnect', () => {
|
|
253
|
+
this.handleDisconnection()
|
|
254
|
+
})
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Set properties and open
|
|
258
|
+
this.accountModal.address = this.connectedAddress
|
|
259
|
+
this.accountModal.chainId = this.connectedChainId
|
|
260
|
+
this.accountModal.connectorName = this.connectedProvider?.name || 'Unknown'
|
|
261
|
+
this.accountModal.open = true
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
private handleConnection(
|
|
265
|
+
address: string,
|
|
266
|
+
provider: any,
|
|
267
|
+
chainId?: number
|
|
268
|
+
): void {
|
|
269
|
+
this.connectedAddress = address
|
|
270
|
+
this.connectedProvider = provider
|
|
271
|
+
this.connectedChainId = chainId
|
|
272
|
+
this.setConnectionState('connected')
|
|
273
|
+
|
|
274
|
+
// Update global Lukso config for address resolution
|
|
275
|
+
if (chainId) {
|
|
276
|
+
this.updateLuksoConfig(chainId)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Update avatar with connected address and chainId
|
|
280
|
+
if (this.avatar) {
|
|
281
|
+
this.avatar.updateAddress(address, undefined, chainId)
|
|
282
|
+
this.avatar.setConnected(true)
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Persist connection if enabled
|
|
286
|
+
if (this.config.persistConnection) {
|
|
287
|
+
this.saveConnectionState()
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Hide connection modal if open
|
|
291
|
+
if (this.connectModal) {
|
|
292
|
+
this.connectModal.open = false
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
private async handleDisconnection(): Promise<void> {
|
|
297
|
+
// Disconnect from wagmi first to ensure state is clean
|
|
298
|
+
await disconnectWagmi()
|
|
299
|
+
|
|
300
|
+
this.connectedAddress = undefined
|
|
301
|
+
this.connectedProvider = undefined
|
|
302
|
+
this.connectedChainId = undefined
|
|
303
|
+
this.setConnectionState('disconnected')
|
|
304
|
+
|
|
305
|
+
// Update avatar - clear address and show disconnected state
|
|
306
|
+
if (this.avatar) {
|
|
307
|
+
this.avatar.setConnected(false)
|
|
308
|
+
// Clear the address to show fallback/disconnected state
|
|
309
|
+
this.avatar.updateAddress('')
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Clear persisted state
|
|
313
|
+
if (this.config.persistConnection) {
|
|
314
|
+
this.clearConnectionState()
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Hide connect modal if open
|
|
318
|
+
if (this.connectModal) {
|
|
319
|
+
this.connectModal.open = false
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
private setConnectionState(state: ConnectionState): void {
|
|
324
|
+
const prevState = this.connectionState
|
|
325
|
+
this.connectionState = state
|
|
326
|
+
|
|
327
|
+
// Update avatar state
|
|
328
|
+
this.updateAvatarState()
|
|
329
|
+
|
|
330
|
+
// Notify callback
|
|
331
|
+
if (prevState !== state) {
|
|
332
|
+
this.config.onConnectionChange?.(state, {
|
|
333
|
+
address: this.connectedAddress,
|
|
334
|
+
provider: this.connectedProvider,
|
|
335
|
+
chainId: this.connectedChainId,
|
|
336
|
+
})
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
private updateAvatarState(): void {
|
|
341
|
+
if (!this.avatar) return
|
|
342
|
+
|
|
343
|
+
this.avatar.setConnected(this.connectionState === 'connected')
|
|
344
|
+
|
|
345
|
+
// Update avatar address and chainId if connected
|
|
346
|
+
if (this.connectionState === 'connected' && this.connectedAddress) {
|
|
347
|
+
this.avatar.updateAddress(
|
|
348
|
+
this.connectedAddress,
|
|
349
|
+
undefined,
|
|
350
|
+
this.connectedChainId
|
|
351
|
+
)
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
private async tryAutoConnect(): Promise<void> {
|
|
356
|
+
const savedState = this.loadConnectionState()
|
|
357
|
+
if (!savedState?.address) return
|
|
358
|
+
|
|
359
|
+
this.setConnectionState('connecting')
|
|
360
|
+
|
|
361
|
+
try {
|
|
362
|
+
// Try to reconnect using saved provider info
|
|
363
|
+
// This would typically involve checking if the provider is still available
|
|
364
|
+
// and attempting to reconnect
|
|
365
|
+
|
|
366
|
+
// For now, simulate auto-connection
|
|
367
|
+
setTimeout(() => {
|
|
368
|
+
if (savedState.address) {
|
|
369
|
+
this.handleConnection(savedState.address, savedState.provider)
|
|
370
|
+
} else {
|
|
371
|
+
this.setConnectionState('disconnected')
|
|
372
|
+
}
|
|
373
|
+
}, 1000)
|
|
374
|
+
} catch (error) {
|
|
375
|
+
console.warn('Auto-connect failed:', error)
|
|
376
|
+
this.setConnectionState('disconnected')
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
private saveConnectionState(): void {
|
|
381
|
+
if (typeof localStorage === 'undefined') return
|
|
382
|
+
|
|
383
|
+
try {
|
|
384
|
+
const state = {
|
|
385
|
+
address: this.connectedAddress,
|
|
386
|
+
provider: this.connectedProvider?.constructor?.name,
|
|
387
|
+
timestamp: Date.now(),
|
|
388
|
+
}
|
|
389
|
+
localStorage.setItem(this.config.storageKey, JSON.stringify(state))
|
|
390
|
+
} catch (error) {
|
|
391
|
+
console.warn('Failed to save connection state:', error)
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
private loadConnectionState(): any {
|
|
396
|
+
if (typeof localStorage === 'undefined') return null
|
|
397
|
+
|
|
398
|
+
try {
|
|
399
|
+
const saved = localStorage.getItem(this.config.storageKey)
|
|
400
|
+
if (!saved) return null
|
|
401
|
+
|
|
402
|
+
const state = JSON.parse(saved)
|
|
403
|
+
|
|
404
|
+
// Check if state is not too old (24 hours)
|
|
405
|
+
const maxAge = 24 * 60 * 60 * 1000
|
|
406
|
+
if (Date.now() - state.timestamp > maxAge) {
|
|
407
|
+
this.clearConnectionState()
|
|
408
|
+
return null
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
return state
|
|
412
|
+
} catch (error) {
|
|
413
|
+
console.warn('Failed to load connection state:', error)
|
|
414
|
+
return null
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
private clearConnectionState(): void {
|
|
419
|
+
if (typeof localStorage === 'undefined') return
|
|
420
|
+
|
|
421
|
+
try {
|
|
422
|
+
localStorage.removeItem(this.config.storageKey)
|
|
423
|
+
} catch (error) {
|
|
424
|
+
console.warn('Failed to clear connection state:', error)
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Public API
|
|
429
|
+
public getAvatar(): DraggableAvatar | undefined {
|
|
430
|
+
return this.avatar
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* @deprecated Legacy modal removed. Use getConnectModal() or create account modal
|
|
435
|
+
*/
|
|
436
|
+
public getModal(): undefined {
|
|
437
|
+
console.warn('getModal() is deprecated - legacy ConnectorModal removed')
|
|
438
|
+
return undefined
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
public getConnectModal(): ConnectModal | undefined {
|
|
442
|
+
return this.connectModal
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* @deprecated Use setupConnectModal() instead to configure wagmi connectors globally
|
|
447
|
+
*/
|
|
448
|
+
public setConnectors(connectors: WalletConnector[]): void {
|
|
449
|
+
this.connectors = connectors
|
|
450
|
+
// Note: The ConnectModal now loads connectors automatically from global setup
|
|
451
|
+
// Use setupConnectModal() to configure wagmi integration
|
|
452
|
+
console.warn(
|
|
453
|
+
'setConnectors() is deprecated. Use setupConnectModal() instead.'
|
|
454
|
+
)
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
public async connect(providerId?: string): Promise<void> {
|
|
458
|
+
this.setConnectionState('connecting')
|
|
459
|
+
|
|
460
|
+
if (providerId) {
|
|
461
|
+
// Connect to specific provider
|
|
462
|
+
// This would be implemented based on available providers
|
|
463
|
+
} else {
|
|
464
|
+
// Show connection modal
|
|
465
|
+
this.showConnectionModal()
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
public disconnect(): void {
|
|
470
|
+
this.handleDisconnection()
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
public getConnectionState(): ConnectionState {
|
|
474
|
+
return this.connectionState
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
public getConnectedAddress(): string | undefined {
|
|
478
|
+
return this.connectedAddress
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
public getConnectedProvider(): any {
|
|
482
|
+
return this.connectedProvider
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
public isConnected(): boolean {
|
|
486
|
+
return this.connectionState === 'connected'
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
public showModal(): void {
|
|
490
|
+
if (this.isConnected()) {
|
|
491
|
+
this.showAccountModal()
|
|
492
|
+
} else {
|
|
493
|
+
this.showConnectionModal()
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
public hideModal(): void {
|
|
498
|
+
if (this.connectModal) {
|
|
499
|
+
this.connectModal.open = false
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
public updateConfig(config: Partial<ConnectorConfig>): void {
|
|
504
|
+
this.config = { ...this.config, ...config }
|
|
505
|
+
|
|
506
|
+
// Update avatar if config changed
|
|
507
|
+
if (config.avatar && this.avatar) {
|
|
508
|
+
// This would require implementing avatar config updates
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
public destroy(): void {
|
|
513
|
+
// Unsubscribe from wagmi changes
|
|
514
|
+
if (this.wagmiUnsubscribe) {
|
|
515
|
+
this.wagmiUnsubscribe()
|
|
516
|
+
this.wagmiUnsubscribe = undefined
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
this.avatar?.destroy()
|
|
520
|
+
|
|
521
|
+
// Clean up connect modal
|
|
522
|
+
if (this.connectModal) {
|
|
523
|
+
this.connectModal.open = false
|
|
524
|
+
if (this.connectModal.parentNode) {
|
|
525
|
+
this.connectModal.parentNode.removeChild(this.connectModal)
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
this.avatar = undefined
|
|
530
|
+
this.connectModal = undefined
|
|
531
|
+
this.connectedAddress = undefined
|
|
532
|
+
this.connectedProvider = undefined
|
|
533
|
+
this.connectionState = 'disconnected'
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Factory function for creating UP Connector instances
|
|
539
|
+
*/
|
|
540
|
+
export function createConnector(config: ConnectorConfig = {}): UPConnector {
|
|
541
|
+
return new UPConnector(config)
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
export default UPConnector
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @lukso/up-connector
|
|
3
|
+
* Universal Profile connector with draggable avatar and connection modal
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Backup & Restore Modals (Lit Components)
|
|
7
|
+
export { AccountModal } from './account-modal.js'
|
|
8
|
+
// Auto-setup for LUKSO products
|
|
9
|
+
export type { LuksoConnectorConfig } from './auto-setup.js'
|
|
10
|
+
export {
|
|
11
|
+
EMBEDDED_WALLET_ID,
|
|
12
|
+
EMBEDDED_WALLET_URL_DEV,
|
|
13
|
+
EMBEDDED_WALLET_URL_PROD,
|
|
14
|
+
setupLuksoConnector,
|
|
15
|
+
UP_EXTENSION_ID,
|
|
16
|
+
} from './auto-setup.js'
|
|
17
|
+
export { createAvatar, DraggableAvatar } from './avatar.js'
|
|
18
|
+
export { BackupModal } from './backup-modal.js'
|
|
19
|
+
export type { WagmiConnector } from './connect-modal'
|
|
20
|
+
export type {
|
|
21
|
+
ConnectionModalView,
|
|
22
|
+
ConnectModalSetup,
|
|
23
|
+
ConnectModalTheme,
|
|
24
|
+
WalletConnector,
|
|
25
|
+
} from './connect-modal/index.js'
|
|
26
|
+
export {
|
|
27
|
+
ConnectModal,
|
|
28
|
+
disconnectWagmi,
|
|
29
|
+
getWagmiAccount,
|
|
30
|
+
getWagmiSetup,
|
|
31
|
+
setupConnectModal,
|
|
32
|
+
watchWagmiAccount,
|
|
33
|
+
} from './connect-modal/index.js'
|
|
34
|
+
// Wagmi Adapter
|
|
35
|
+
export {
|
|
36
|
+
fromWagmiConnector,
|
|
37
|
+
fromWagmiConnectors,
|
|
38
|
+
} from './connect-modal/services/wagmi.js'
|
|
39
|
+
// Main exports
|
|
40
|
+
// Default export
|
|
41
|
+
export {
|
|
42
|
+
createConnector,
|
|
43
|
+
createConnector as default,
|
|
44
|
+
UPConnector,
|
|
45
|
+
} from './connector.js'
|
|
46
|
+
// Enhanced popup system
|
|
47
|
+
export {
|
|
48
|
+
ModalPopupInstance,
|
|
49
|
+
WindowPopupInstance,
|
|
50
|
+
} from './popup-instance.js'
|
|
51
|
+
export { RestoreModal } from './restore-modal.js'
|
|
52
|
+
// Types
|
|
53
|
+
export type {
|
|
54
|
+
AddressData,
|
|
55
|
+
AvatarOptions,
|
|
56
|
+
ConnectionState,
|
|
57
|
+
ConnectorConfig,
|
|
58
|
+
PopupInstance,
|
|
59
|
+
PopupRequest,
|
|
60
|
+
UIDelegate,
|
|
61
|
+
WalletProvider,
|
|
62
|
+
} from './types.js'
|