Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: manage dapp disconnection with mobile connector #15

Merged
merged 6 commits into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/connectors/argentMobile/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
} from "../../errors"
import { resetWalletConnect } from "../../helpers/resetWalletConnect"
import { Connector } from "../connector"
import type { StarknetAdapter } from "./modal/starknet/adapter"
import { removeStarknetLastConnectedWallet } from "../../helpers/lastConnected"

export interface ArgentMobileConnectorOptions {
dappName?: string
Expand Down Expand Up @@ -67,7 +69,6 @@ export class ArgentMobileConnector extends Connector {
}

get wallet(): StarknetWindowObject {
this.ensureWallet()
if (!this._wallet) {
throw new ConnectorNotConnectedError()
}
Expand All @@ -85,6 +86,8 @@ export class ArgentMobileConnector extends Connector {
}

async disconnect(): Promise<void> {
// wallet connect rpc enable
await (this._wallet as StarknetAdapter).disable()
resetWalletConnect()

if (!this.available() && !this._wallet) {
Expand Down Expand Up @@ -162,5 +165,18 @@ export class ArgentMobileConnector extends Connector {

const _wallet = await getStarknetWindowObject(options)
this._wallet = _wallet

// wallet connect rpc enable
const snProvider = this._wallet as StarknetAdapter
await snProvider.enable()
snProvider.client.on("session_delete", () => {
// Session was deleted -> reset the dapp state, clean up from user session, etc.
// not calling disconnect(), because .disable() is already done by the mobile app
resetWalletConnect()
this._wallet = null
removeStarknetLastConnectedWallet()
// dapp should listen to this event and update the UI accordingly
document.dispatchEvent(new Event("wallet_disconnected"))
})
}
}
20 changes: 13 additions & 7 deletions src/connectors/argentMobile/modal/argentModal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,12 @@ class ArgentModal {

public showConnectionModal(wcUri: string) {
const wcParam = encodeURIComponent(wcUri)
const href = encodeURIComponent(window.location.href)

this.showModal({
desktop: `${this.bridgeUrl}?wc=${wcParam}`,
ios: `${this.mobileUrl}app/wc?uri=${wcParam}`,
android: `${this.mobileUrl}app/wc?uri=${wcParam}`,
desktop: `${this.bridgeUrl}?wc=${wcParam}&device=desktop`,
ios: `${this.mobileUrl}app/wc?uri=${wcParam}&href=${href}&device=mobile`,
android: `${this.mobileUrl}app/wc?uri=${wcParam}&href=${href}&device=mobile`,
})
}

Expand All @@ -94,9 +96,9 @@ class ArgentModal {
this should be ignored and not considered valid as it's only used for automatically redirecting the users to approve or reject a signing request.
*/
this.showModal({
desktop: `${this.bridgeUrl}?action=sign`,
ios: `${this.mobileUrl}app/wc?uri=${href}`,
android: `${this.mobileUrl}app/wc?uri=${href}`,
desktop: `${this.bridgeUrl}?action=sign&device=desktop`,
ios: `${this.mobileUrl}app/wc?uri=${href}&device=mobile`,
bluecco marked this conversation as resolved.
Show resolved Hide resolved
android: `${this.mobileUrl}app/wc?uri=${href}&device=mobile`,
})
}

Expand All @@ -119,7 +121,11 @@ class ArgentModal {
}

if (device === "android" || device === "ios") {
window.open(urls[device])
const toMobileApp = document.createElement("a")
janek26 marked this conversation as resolved.
Show resolved Hide resolved
toMobileApp.setAttribute("href", urls[device])
toMobileApp.setAttribute("target", "_blank")
toMobileApp.click()

return
}
if (this.type === "window") {
Expand Down
3 changes: 0 additions & 3 deletions src/connectors/injected/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,23 +102,20 @@ export class InjectedConnector extends Connector {
}

get name(): string {
this.ensureWallet()
if (!this._wallet) {
throw new ConnectorNotConnectedError()
}
return this._wallet.name
}

get icon(): string {
this.ensureWallet()
if (!this._wallet) {
throw new ConnectorNotConnectedError()
}
return this._wallet.icon
}

get wallet(): StarknetWindowObject {
this.ensureWallet()
if (!this._wallet) {
throw new ConnectorNotConnectedError()
}
Expand Down
1 change: 0 additions & 1 deletion src/connectors/webwallet/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ export class WebWalletConnector extends Connector {
}

get wallet(): StarknetWindowObject {
this.ensureWallet()
if (!this._wallet) {
throw new ConnectorNotConnectedError()
}
Expand Down
38 changes: 30 additions & 8 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
import type { DisconnectOptions, StarknetWindowObject } from "get-starknet-core"
import type {
ConnectedStarknetWindowObject,
DisconnectOptions,
DisconnectedStarknetWindowObject,
StarknetWindowObject,
} from "get-starknet-core"
import sn from "get-starknet-core"

import { getStoreVersionFromBrowser } from "./helpers/getStoreVersionFromBrowser"

import { DEFAULT_WEBWALLET_URL } from "./connectors/webwallet/constants"
import { defaultConnectors } from "./helpers/defaultConnectors"
import { mapModalWallets } from "./helpers/mapModalWallets"
import { resetWalletConnect } from "./helpers/resetWalletConnect"
import Modal from "./modal/Modal.svelte"
import type { ConnectOptions, ModalWallet } from "./types/modal"
import {
removeStarknetLastConnectedWallet,
setStarknetLastConnectedWallet,
} from "./helpers/lastConnected"
import { mapModalWallets } from "./helpers/mapModalWallets"
import Modal from "./modal/Modal.svelte"
import type { ConnectOptions, ModalWallet } from "./types/modal"

import { ArgentMobileConnector, Connector } from "./connectors"
import css from "./theme.css?inline"

let selectedConnector: Connector | null = null

export const connect = async ({
modalMode = "canAsk",
storeVersion = getStoreVersionFromBrowser(),
Expand All @@ -26,6 +33,8 @@ export const connect = async ({
connectors = [],
...restOptions
}: ConnectOptions = {}): Promise<StarknetWindowObject | null> => {
// force null in case it was disconnected from mobile app
selectedConnector = null
const availableConnectors =
!connectors || connectors.length === 0
? defaultConnectors({
Expand All @@ -38,7 +47,8 @@ export const connect = async ({
if (modalMode === "neverAsk") {
const connector = availableConnectors.find((c) => c.id === lastWalletId)
await connector?.connect()
return connector?.wallet || null
selectedConnector = connector ?? null
return connector?.wallet ?? null
}

const installedWallets = await sn.getAvailableWallets(restOptions)
Expand All @@ -58,6 +68,7 @@ export const connect = async ({
if (wallet) {
const connector = availableConnectors.find((c) => c.id === lastWalletId)
await connector?.connect()
selectedConnector = connector
return wallet
} // otherwise fallback to modal
}
Expand Down Expand Up @@ -85,6 +96,8 @@ export const connect = async ({
if (value.id !== "argentWebWallet") {
setStarknetLastConnectedWallet(value.id)
}
selectedConnector =
availableConnectors.find((c) => c.id === value.id) ?? null
resolve(value)
} finally {
setTimeout(() => modal.$destroy())
Expand All @@ -97,8 +110,17 @@ export const connect = async ({
})
}

export function disconnect(options: DisconnectOptions = {}): Promise<void> {
resetWalletConnect()
export const disconnect = async (options: DisconnectOptions = {}) => {
removeStarknetLastConnectedWallet()
await selectedConnector.disconnect()
selectedConnector = null

return sn.disconnect(options)
janek26 marked this conversation as resolved.
Show resolved Hide resolved
}

export type {
ConnectedStarknetWindowObject,
DisconnectOptions,
DisconnectedStarknetWindowObject,
StarknetWindowObject,
}