Skip to content

Commit

Permalink
Merge pull request #15 from argentlabs/fix/mobile-connected-dapps
Browse files Browse the repository at this point in the history
fix: manage dapp disconnection with mobile connector
  • Loading branch information
bluecco authored Oct 20, 2023
2 parents c5fcbea + 4c31f02 commit 0ee8fbb
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 20 deletions.
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/request?href=${href}&device=mobile`,
android: `${this.mobileUrl}app/wc/request?href=${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")
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)
}

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

0 comments on commit 0ee8fbb

Please sign in to comment.