diff --git a/package.json b/package.json index 90024b7..35d85fe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "starknetkit", - "version": "1.0.9", + "version": "1.0.10", "repository": "github:argentlabs/starknetkit", "private": false, "browser": { diff --git a/src/connectors/argentMobile/index.ts b/src/connectors/argentMobile/index.ts index d21edfc..94f9b10 100644 --- a/src/connectors/argentMobile/index.ts +++ b/src/connectors/argentMobile/index.ts @@ -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 @@ -67,7 +69,6 @@ export class ArgentMobileConnector extends Connector { } get wallet(): StarknetWindowObject { - this.ensureWallet() if (!this._wallet) { throw new ConnectorNotConnectedError() } @@ -85,6 +86,8 @@ export class ArgentMobileConnector extends Connector { } async disconnect(): Promise { + // wallet connect rpc enable + await (this._wallet as StarknetAdapter).disable() resetWalletConnect() if (!this.available() && !this._wallet) { @@ -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")) + }) } } diff --git a/src/connectors/argentMobile/modal/argentModal.ts b/src/connectors/argentMobile/modal/argentModal.ts index cb7a309..9721d31 100644 --- a/src/connectors/argentMobile/modal/argentModal.ts +++ b/src/connectors/argentMobile/modal/argentModal.ts @@ -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`, }) } @@ -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`, }) } @@ -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") { diff --git a/src/connectors/injected/index.ts b/src/connectors/injected/index.ts index 36a9921..1709049 100644 --- a/src/connectors/injected/index.ts +++ b/src/connectors/injected/index.ts @@ -102,7 +102,6 @@ export class InjectedConnector extends Connector { } get name(): string { - this.ensureWallet() if (!this._wallet) { throw new ConnectorNotConnectedError() } @@ -110,7 +109,6 @@ export class InjectedConnector extends Connector { } get icon(): string { - this.ensureWallet() if (!this._wallet) { throw new ConnectorNotConnectedError() } @@ -118,7 +116,6 @@ export class InjectedConnector extends Connector { } get wallet(): StarknetWindowObject { - this.ensureWallet() if (!this._wallet) { throw new ConnectorNotConnectedError() } diff --git a/src/connectors/webwallet/index.ts b/src/connectors/webwallet/index.ts index 3aa293e..1c990c8 100644 --- a/src/connectors/webwallet/index.ts +++ b/src/connectors/webwallet/index.ts @@ -72,7 +72,6 @@ export class WebWalletConnector extends Connector { } get wallet(): StarknetWindowObject { - this.ensureWallet() if (!this._wallet) { throw new ConnectorNotConnectedError() } diff --git a/src/main.ts b/src/main.ts index e966625..5799138 100644 --- a/src/main.ts +++ b/src/main.ts @@ -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(), @@ -26,6 +33,8 @@ export const connect = async ({ connectors = [], ...restOptions }: ConnectOptions = {}): Promise => { + // force null in case it was disconnected from mobile app + selectedConnector = null const availableConnectors = !connectors || connectors.length === 0 ? defaultConnectors({ @@ -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) @@ -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 } @@ -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()) @@ -97,8 +110,17 @@ export const connect = async ({ }) } -export function disconnect(options: DisconnectOptions = {}): Promise { - resetWalletConnect() +export const disconnect = async (options: DisconnectOptions = {}) => { removeStarknetLastConnectedWallet() + await selectedConnector.disconnect() + selectedConnector = null + return sn.disconnect(options) } + +export type { + ConnectedStarknetWindowObject, + DisconnectOptions, + DisconnectedStarknetWindowObject, + StarknetWindowObject, +}