Skip to content

Commit bb92e56

Browse files
Sessionless connection upgrade and error handling in DappClient (#902)
1 parent 5556e7e commit bb92e56

1 file changed

Lines changed: 109 additions & 0 deletions

File tree

packages/wallet/dapp-client/src/DappClient.ts

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,34 @@ export class DappClient {
403403
}
404404
this.emit('walletActionResponse', eventPayload)
405405
} else if (chainId !== undefined) {
406+
if ('error' in response && response.error && action === RequestActionType.CREATE_NEW_SESSION) {
407+
await this.sequenceStorage.setPendingRedirectRequest(false)
408+
await this.sequenceStorage.getAndClearTempSessionPk()
409+
await this.sequenceStorage.getAndClearPendingRequest()
410+
411+
if (this.hasSessionlessConnection) {
412+
const sessionlessConnection = await this.sequenceStorage.getSessionlessConnection()
413+
if (sessionlessConnection) {
414+
await this.applySessionlessConnectionState(
415+
sessionlessConnection.walletAddress,
416+
sessionlessConnection.loginMethod,
417+
sessionlessConnection.userEmail,
418+
sessionlessConnection.guard,
419+
false,
420+
)
421+
} else if (this.walletAddress) {
422+
await this.applySessionlessConnectionState(
423+
this.walletAddress,
424+
this.loginMethod,
425+
this.userEmail,
426+
this.guard,
427+
false,
428+
)
429+
}
430+
}
431+
return
432+
}
433+
406434
const chainSessionManager = this.getChainSessionManager(chainId)
407435
if (!chainSessionManager.isInitialized && this.walletAddress) {
408436
chainSessionManager.initializeWithWallet(this.walletAddress)
@@ -500,6 +528,87 @@ export class DappClient {
500528
}
501529
}
502530

531+
/**
532+
* Upgrades an existing sessionless connection by creating implicit and/or explicit sessions.
533+
* @param chainId The chain ID to target for the new sessions.
534+
* @param sessionConfig The explicit session configuration to request. {@link ExplicitSessionConfig}
535+
* @param options Connection options such as preferred login method or email for social/email logins.
536+
* @throws If no sessionless connection is available or the session upgrade fails. {@link InitializationError}
537+
* @throws If neither an implicit nor explicit session is requested. {@link InitializationError}
538+
*
539+
* @returns A promise that resolves once the session upgrade completes.
540+
*/
541+
async upgradeSessionlessConnection(
542+
chainId: number,
543+
sessionConfig?: ExplicitSessionConfig,
544+
options: {
545+
preferredLoginMethod?: LoginMethod
546+
email?: string
547+
includeImplicitSession?: boolean
548+
} = {},
549+
): Promise<void> {
550+
if (!this.isInitialized || !this.hasSessionlessConnection || !this.walletAddress) {
551+
throw new InitializationError('A sessionless connection is required before requesting new sessions.')
552+
}
553+
554+
const shouldCreateSession = !!sessionConfig || (options.includeImplicitSession ?? false)
555+
if (!shouldCreateSession) {
556+
throw new InitializationError(
557+
'Cannot upgrade a sessionless connection without requesting an implicit or explicit session.',
558+
)
559+
}
560+
561+
const sessionlessSnapshot = {
562+
walletAddress: this.walletAddress,
563+
loginMethod: this.loginMethod,
564+
userEmail: this.userEmail,
565+
guard: this.guard,
566+
}
567+
568+
try {
569+
let chainSessionManager = this.chainSessionManagers.get(chainId)
570+
if (
571+
chainSessionManager &&
572+
chainSessionManager.isInitialized &&
573+
!chainSessionManager.getImplicitSession() &&
574+
chainSessionManager.getExplicitSessions().length === 0
575+
) {
576+
this.chainSessionManagers.delete(chainId)
577+
chainSessionManager = undefined
578+
}
579+
chainSessionManager = chainSessionManager ?? this.getChainSessionManager(chainId)
580+
await chainSessionManager.createNewSession(this.origin, sessionConfig, options)
581+
582+
if (this.transport.mode === TransportMode.POPUP) {
583+
const hasImplicitSession = !!chainSessionManager.getImplicitSession()
584+
const hasExplicitSessions = chainSessionManager.getExplicitSessions().length > 0
585+
586+
if (shouldCreateSession && (hasImplicitSession || hasExplicitSessions)) {
587+
await this._loadStateFromStorage()
588+
} else {
589+
const walletAddress = chainSessionManager.getWalletAddress()
590+
if (!walletAddress) {
591+
throw new InitializationError('Wallet address missing after connect.')
592+
}
593+
await this.applySessionlessConnectionState(
594+
walletAddress,
595+
chainSessionManager.loginMethod,
596+
chainSessionManager.userEmail,
597+
chainSessionManager.getGuard(),
598+
)
599+
}
600+
}
601+
} catch (err) {
602+
await this.applySessionlessConnectionState(
603+
sessionlessSnapshot.walletAddress,
604+
sessionlessSnapshot.loginMethod,
605+
sessionlessSnapshot.userEmail,
606+
sessionlessSnapshot.guard,
607+
)
608+
throw new ConnectionError(`Connection failed: ${err}`)
609+
}
610+
}
611+
503612
/**
504613
* Adds a new explicit session for a given chain to an existing wallet.
505614
* @remarks

0 commit comments

Comments
 (0)