From bb55469aeeb4cb2d6405a2090cee4c3d4d39d24b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ti=E1=BA=BFn=20Nguy=E1=BB=85n=20Kh=E1=BA=AFc?= Date: Mon, 17 Jun 2024 15:37:06 +1200 Subject: [PATCH] refactor: split connection process of deep link wallets into 2 steps So that application can decide to role their own solution if they don't like the default modal --- packages/core/src/wallets/deep-link.ts | 18 +++++++++ .../core/src/wallets/wallet-connect/index.ts | 39 ++++++++++++++++--- 2 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 packages/core/src/wallets/deep-link.ts diff --git a/packages/core/src/wallets/deep-link.ts b/packages/core/src/wallets/deep-link.ts new file mode 100644 index 00000000..54433901 --- /dev/null +++ b/packages/core/src/wallets/deep-link.ts @@ -0,0 +1,18 @@ +import Wallet from "./wallet.js"; + +type ConnectionHandshake = { + uri: string; + wait: () => Promise; +}; + +export default abstract class DeepLinkWallet< + THandshakeResponse, +> extends Wallet { + abstract readonly initiateConnectionHandshake: () => + | ConnectionHandshake + | Promise>; + + abstract readonly completeConnectionHandshake: ( + response: THandshakeResponse, + ) => void | Promise; +} diff --git a/packages/core/src/wallets/wallet-connect/index.ts b/packages/core/src/wallets/wallet-connect/index.ts index ad60e46e..d5a01cf6 100644 --- a/packages/core/src/wallets/wallet-connect/index.ts +++ b/packages/core/src/wallets/wallet-connect/index.ts @@ -1,5 +1,5 @@ import { ReDotError } from "../../errors.js"; -import Wallet from "../wallet.js"; +import DeepLinkWallet from "../deep-link.js"; import { getPolkadotSignerFromPjs } from "./from-pjs-account.js"; import "@polkadot-api/pjs-signer"; import { AccountId } from "@polkadot-api/substrate-bindings"; @@ -16,7 +16,7 @@ import { InjectedPolkadotAccount } from "polkadot-api/pjs-signer"; import { BehaviorSubject, lastValueFrom } from "rxjs"; import { map } from "rxjs/operators"; -export default class WalletConnect extends Wallet { +export default class WalletConnect extends DeepLinkWallet { readonly #providerOptions: UniversalProviderOpts; #provider: IUniversalProvider | undefined; @@ -76,7 +76,7 @@ export default class WalletConnect extends Wallet { map((session) => session !== undefined), ); - override readonly connect = async () => { + override readonly initiateConnectionHandshake = async () => { await this.initialize(); if (this.#provider?.client === undefined) { @@ -107,14 +107,43 @@ export default class WalletConnect extends Wallet { await this.#provider.client.connect(connectOptions); if (uri === undefined) { - throw new ReDotError("Client connection doesn't return any URI"); + throw new ReDotError("No URI provided by connection"); } + return { + uri, + wait: approval, + }; + }; + + override completeConnectionHandshake = (response: SessionTypes.Struct) => + this.#session.next(response); + + override readonly connect = async () => { + const { uri, wait } = await this.initiateConnectionHandshake(); + const modal = await this.#getModal(); await modal.openModal({ uri }); - this.#session.next(await approval()); + const modalClosePromise = new Promise((resolve) => { + const unsubscribe = modal.subscribeModal((modalState) => { + if (!modalState.open) { + resolve(); + unsubscribe(); + } + }); + }); + + const sessionPromise = wait(); + + const session = await Promise.race([sessionPromise, modalClosePromise]); + + if (session === undefined) { + throw new ReDotError("Modal was closed"); + } + + this.completeConnectionHandshake(session); modal.closeModal(); };