Parcourir la source

Sollet extension support (#64)

* stash

* version bump

* fixes

* sollet fixes

* nextjs formatting
Jordan Sexton il y a 4 ans
Parent
commit
a9bf996475

+ 1 - 0
.prettierignore

@@ -1,3 +1,4 @@
 docs
 build
 lib
+.next

+ 5 - 5
packages/ant-design/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-ant-design",
-    "version": "0.4.3",
+    "version": "0.4.4",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -22,8 +22,8 @@
     "peerDependencies": {
         "@ant-design/icons": "^4.6.3",
         "@solana/wallet-adapter-base": "^0.5.2",
-        "@solana/wallet-adapter-react": "^0.9.2",
-        "@solana/wallet-adapter-wallets": "^0.7.6",
+        "@solana/wallet-adapter-react": "^0.9.3",
+        "@solana/wallet-adapter-wallets": "^0.7.7",
         "@solana/web3.js": "^1.20.0",
         "antd": "^4.16.11",
         "react": "^17.0.2",
@@ -35,8 +35,8 @@
     "devDependencies": {
         "@ant-design/icons": "^4.6.3",
         "@solana/wallet-adapter-base": "^0.5.2",
-        "@solana/wallet-adapter-react": "^0.9.2",
-        "@solana/wallet-adapter-wallets": "^0.7.6",
+        "@solana/wallet-adapter-react": "^0.9.3",
+        "@solana/wallet-adapter-wallets": "^0.7.7",
         "@solana/web3.js": "^1.20.0",
         "antd": "^4.16.11",
         "react": "^17.0.2",

+ 4 - 0
packages/base/src/errors.ts

@@ -60,6 +60,10 @@ export class WalletSignTransactionError extends WalletError {
     name = 'WalletSignTransactionError';
 }
 
+export class WalletTimeoutError extends WalletError {
+    name = 'WalletTimeoutError';
+}
+
 export class WalletWindowBlockedError extends WalletError {
     name = 'WalletWindowBlockedError';
 }

+ 6 - 6
packages/example/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-example",
-    "version": "0.9.4",
+    "version": "0.9.5",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -27,12 +27,12 @@
         "@craco/craco": "^6.2.0",
         "@material-ui/core": "^4.12.3",
         "@material-ui/icons": "^4.11.2",
-        "@solana/wallet-adapter-ant-design": "^0.4.3",
+        "@solana/wallet-adapter-ant-design": "^0.4.4",
         "@solana/wallet-adapter-base": "^0.5.2",
-        "@solana/wallet-adapter-material-ui": "^0.9.3",
-        "@solana/wallet-adapter-react": "^0.9.2",
-        "@solana/wallet-adapter-react-ui": "^0.1.2",
-        "@solana/wallet-adapter-wallets": "^0.7.6",
+        "@solana/wallet-adapter-material-ui": "^0.9.4",
+        "@solana/wallet-adapter-react": "^0.9.3",
+        "@solana/wallet-adapter-react-ui": "^0.1.3",
+        "@solana/wallet-adapter-wallets": "^0.7.7",
         "@solana/web3.js": "^1.22.0",
         "@testing-library/jest-dom": "^5.11.4",
         "@testing-library/react": "^11.1.0",

+ 5 - 1
packages/example/src/Demo.tsx

@@ -32,7 +32,9 @@ import {
     getSafePalWallet,
     getSlopeWallet,
     getSolflareWallet,
+    getSolflareWebWallet,
     getSolletWallet,
+    getSolletWebWallet,
     getSolongWallet,
     getTorusWallet,
 } from '@solana/wallet-adapter-wallets';
@@ -60,13 +62,15 @@ export const Demo: FC = () => {
                 },
             }),
             getLedgerWallet(),
+            getBloctoWallet({ network }),
             getSolletWallet({ network }),
             getBitpieWallet(),
-            getBloctoWallet({ network }),
             getCoin98Wallet(),
             getMathWallet(),
             getSafePalWallet(),
             getSolongWallet(),
+            getSolflareWebWallet(),
+            getSolletWebWallet({ network }),
         ],
         [network]
     );

+ 4 - 4
packages/material-ui-starter/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-material-ui-starter",
-    "version": "0.6.3",
+    "version": "0.6.4",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -28,9 +28,9 @@
         "@material-ui/core": "^4.12.3",
         "@material-ui/icons": "^4.11.2",
         "@solana/wallet-adapter-base": "^0.5.2",
-        "@solana/wallet-adapter-material-ui": "^0.9.3",
-        "@solana/wallet-adapter-react": "^0.9.2",
-        "@solana/wallet-adapter-wallets": "^0.7.6",
+        "@solana/wallet-adapter-material-ui": "^0.9.4",
+        "@solana/wallet-adapter-react": "^0.9.3",
+        "@solana/wallet-adapter-wallets": "^0.7.7",
         "@solana/web3.js": "^1.22.0",
         "@testing-library/jest-dom": "^5.11.4",
         "@testing-library/react": "^11.1.0",

+ 5 - 5
packages/material-ui/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-material-ui",
-    "version": "0.9.3",
+    "version": "0.9.4",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -23,8 +23,8 @@
         "@material-ui/core": "^4.12.1",
         "@material-ui/icons": "^4.11.2",
         "@solana/wallet-adapter-base": "^0.5.2",
-        "@solana/wallet-adapter-react": "^0.9.2",
-        "@solana/wallet-adapter-wallets": "^0.7.6",
+        "@solana/wallet-adapter-react": "^0.9.3",
+        "@solana/wallet-adapter-wallets": "^0.7.7",
         "@solana/web3.js": "^1.20.0",
         "react": "^17.0.2",
         "react-dom": "^17.0.2"
@@ -36,8 +36,8 @@
         "@material-ui/core": "^4.12.1",
         "@material-ui/icons": "^4.11.2",
         "@solana/wallet-adapter-base": "^0.5.2",
-        "@solana/wallet-adapter-react": "^0.9.2",
-        "@solana/wallet-adapter-wallets": "^0.7.6",
+        "@solana/wallet-adapter-react": "^0.9.3",
+        "@solana/wallet-adapter-wallets": "^0.7.7",
         "@solana/web3.js": "^1.20.0",
         "react": "^17.0.2",
         "react-dom": "^17.0.2"

+ 1 - 1
packages/nextjs-starter/.eslintrc.json

@@ -1,3 +1,3 @@
 {
-  "extends": "next/core-web-vitals"
+    "extends": "next/core-web-vitals"
 }

+ 3 - 3
packages/nextjs-starter/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-nextjs-starter",
-    "version": "0.1.0",
+    "version": "0.1.1",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -28,8 +28,8 @@
     },
     "dependencies": {
         "@solana/wallet-adapter-base": "^0.5.2",
-        "@solana/wallet-adapter-react": "^0.9.2",
-        "@solana/wallet-adapter-wallets": "^0.7.6",
+        "@solana/wallet-adapter-react": "^0.9.3",
+        "@solana/wallet-adapter-wallets": "^0.7.7",
         "@solana/web3.js": "^1.24.2",
         "next": "11.1.2",
         "react": "17.0.2",

+ 5 - 8
packages/nextjs-starter/pages/api/hello.ts

@@ -1,13 +1,10 @@
 // Next.js API route support: https://nextjs.org/docs/api-routes/introduction
-import type { NextApiRequest, NextApiResponse } from 'next'
+import type { NextApiRequest, NextApiResponse } from 'next';
 
 type Data = {
-  name: string
-}
+    name: string;
+};
 
-export default function handler(
-  req: NextApiRequest,
-  res: NextApiResponse<Data>
-) {
-  res.status(200).json({ name: 'John Doe' })
+export default function handler(req: NextApiRequest, res: NextApiResponse<Data>) {
+    res.status(200).json({ name: 'John Doe' });
 }

+ 56 - 62
packages/nextjs-starter/pages/index.tsx

@@ -1,72 +1,66 @@
-import type { NextPage } from 'next'
-import Head from 'next/head'
-import Image from 'next/image'
-import styles from '../styles/Home.module.css'
+import type { NextPage } from 'next';
+import Head from 'next/head';
+import Image from 'next/image';
+import styles from '../styles/Home.module.css';
 
 const Home: NextPage = () => {
-  return (
-    <div className={styles.container}>
-      <Head>
-        <title>Create Next App</title>
-        <meta name="description" content="Generated by create next app" />
-        <link rel="icon" href="/favicon.ico" />
-      </Head>
+    return (
+        <div className={styles.container}>
+            <Head>
+                <title>Create Next App</title>
+                <meta name="description" content="Generated by create next app" />
+                <link rel="icon" href="/favicon.ico" />
+            </Head>
 
-      <main className={styles.main}>
-        <h1 className={styles.title}>
-          Welcome to <a href="https://nextjs.org">Next.js!</a>
-        </h1>
+            <main className={styles.main}>
+                <h1 className={styles.title}>
+                    Welcome to <a href="https://nextjs.org">Next.js!</a>
+                </h1>
 
-        <p className={styles.description}>
-          Get started by editing{' '}
-          <code className={styles.code}>pages/index.js</code>
-        </p>
+                <p className={styles.description}>
+                    Get started by editing <code className={styles.code}>pages/index.js</code>
+                </p>
 
-        <div className={styles.grid}>
-          <a href="https://nextjs.org/docs" className={styles.card}>
-            <h2>Documentation &rarr;</h2>
-            <p>Find in-depth information about Next.js features and API.</p>
-          </a>
+                <div className={styles.grid}>
+                    <a href="https://nextjs.org/docs" className={styles.card}>
+                        <h2>Documentation &rarr;</h2>
+                        <p>Find in-depth information about Next.js features and API.</p>
+                    </a>
 
-          <a href="https://nextjs.org/learn" className={styles.card}>
-            <h2>Learn &rarr;</h2>
-            <p>Learn about Next.js in an interactive course with quizzes!</p>
-          </a>
+                    <a href="https://nextjs.org/learn" className={styles.card}>
+                        <h2>Learn &rarr;</h2>
+                        <p>Learn about Next.js in an interactive course with quizzes!</p>
+                    </a>
 
-          <a
-            href="https://github.com/vercel/next.js/tree/master/examples"
-            className={styles.card}
-          >
-            <h2>Examples &rarr;</h2>
-            <p>Discover and deploy boilerplate example Next.js projects.</p>
-          </a>
+                    <a href="https://github.com/vercel/next.js/tree/master/examples" className={styles.card}>
+                        <h2>Examples &rarr;</h2>
+                        <p>Discover and deploy boilerplate example Next.js projects.</p>
+                    </a>
 
-          <a
-            href="https://vercel.com/new?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
-            className={styles.card}
-          >
-            <h2>Deploy &rarr;</h2>
-            <p>
-              Instantly deploy your Next.js site to a public URL with Vercel.
-            </p>
-          </a>
-        </div>
-      </main>
+                    <a
+                        href="https://vercel.com/new?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
+                        className={styles.card}
+                    >
+                        <h2>Deploy &rarr;</h2>
+                        <p>Instantly deploy your Next.js site to a public URL with Vercel.</p>
+                    </a>
+                </div>
+            </main>
 
-      <footer className={styles.footer}>
-        <a
-          href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
-          target="_blank"
-          rel="noopener noreferrer"
-        >
-          Powered by{' '}
-          <span className={styles.logo}>
-            <Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
-          </span>
-        </a>
-      </footer>
-    </div>
-  )
-}
+            <footer className={styles.footer}>
+                <a
+                    href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
+                    target="_blank"
+                    rel="noopener noreferrer"
+                >
+                    Powered by{' '}
+                    <span className={styles.logo}>
+                        <Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
+                    </span>
+                </a>
+            </footer>
+        </div>
+    );
+};
 
-export default Home
+export default Home;

+ 17 - 17
packages/nextjs-starter/tsconfig.json

@@ -1,19 +1,19 @@
 {
-  "compilerOptions": {
-    "target": "es5",
-    "lib": ["dom", "dom.iterable", "esnext"],
-    "allowJs": true,
-    "skipLibCheck": true,
-    "strict": true,
-    "forceConsistentCasingInFileNames": true,
-    "noEmit": true,
-    "esModuleInterop": true,
-    "module": "esnext",
-    "moduleResolution": "node",
-    "resolveJsonModule": true,
-    "isolatedModules": true,
-    "jsx": "preserve"
-  },
-  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
-  "exclude": ["node_modules"]
+    "compilerOptions": {
+        "target": "es5",
+        "lib": ["dom", "dom.iterable", "esnext"],
+        "allowJs": true,
+        "skipLibCheck": true,
+        "strict": true,
+        "forceConsistentCasingInFileNames": true,
+        "noEmit": true,
+        "esModuleInterop": true,
+        "module": "esnext",
+        "moduleResolution": "node",
+        "resolveJsonModule": true,
+        "isolatedModules": true,
+        "jsx": "preserve"
+    },
+    "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
+    "exclude": ["node_modules"]
 }

+ 5 - 3
packages/phantom/src/adapter.ts

@@ -6,6 +6,7 @@ import {
     WalletConnectionError,
     WalletDisconnectedError,
     WalletDisconnectionError,
+    WalletError,
     WalletNotConnectedError,
     WalletNotFoundError,
     WalletNotInstalledError,
@@ -89,7 +90,7 @@ export class PhantomWalletAdapter extends BaseMessageSignerWalletAdapter {
 
             if (!wallet.isConnected) {
                 // HACK: Phantom doesn't reject or emit an event if the popup is closed
-                const disconnect = wallet._handleDisconnect;
+                const handleDisconnect = wallet._handleDisconnect;
                 try {
                     await new Promise<void>((resolve, reject) => {
                         const connect = () => {
@@ -100,7 +101,7 @@ export class PhantomWalletAdapter extends BaseMessageSignerWalletAdapter {
                         wallet._handleDisconnect = (...args: unknown[]) => {
                             wallet.off('connect', connect);
                             reject(new WalletWindowClosedError());
-                            return disconnect.apply(wallet, args);
+                            return handleDisconnect.apply(wallet, args);
                         };
 
                         wallet.on('connect', connect);
@@ -111,9 +112,10 @@ export class PhantomWalletAdapter extends BaseMessageSignerWalletAdapter {
                         });
                     });
                 } catch (error: any) {
+                    if (error instanceof WalletError) throw error;
                     throw new WalletConnectionError(error?.message, error);
                 } finally {
-                    wallet._handleDisconnect = disconnect;
+                    wallet._handleDisconnect = handleDisconnect;
                 }
             }
 

+ 4 - 4
packages/react-ui-starter/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-react-ui-starter",
-    "version": "0.1.2",
+    "version": "0.1.3",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -25,9 +25,9 @@
     },
     "dependencies": {
         "@solana/wallet-adapter-base": "^0.5.2",
-        "@solana/wallet-adapter-react": "^0.9.2",
-        "@solana/wallet-adapter-react-ui": "^0.1.2",
-        "@solana/wallet-adapter-wallets": "^0.7.6",
+        "@solana/wallet-adapter-react": "^0.9.3",
+        "@solana/wallet-adapter-react-ui": "^0.1.3",
+        "@solana/wallet-adapter-wallets": "^0.7.7",
         "@solana/web3.js": "^1.22.0",
         "react": "^17.0.2",
         "react-dom": "^17.0.2",

+ 5 - 5
packages/react-ui/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-react-ui",
-    "version": "0.1.2",
+    "version": "0.1.3",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -21,8 +21,8 @@
     },
     "peerDependencies": {
         "@solana/wallet-adapter-base": "^0.5.2",
-        "@solana/wallet-adapter-react": "^0.9.2",
-        "@solana/wallet-adapter-wallets": "^0.7.6",
+        "@solana/wallet-adapter-react": "^0.9.3",
+        "@solana/wallet-adapter-wallets": "^0.7.7",
         "@solana/web3.js": "^1.20.0",
         "react": "^17.0.2",
         "react-dom": "^17.0.2"
@@ -32,8 +32,8 @@
     },
     "devDependencies": {
         "@solana/wallet-adapter-base": "^0.5.2",
-        "@solana/wallet-adapter-react": "^0.9.2",
-        "@solana/wallet-adapter-wallets": "^0.7.6",
+        "@solana/wallet-adapter-react": "^0.9.3",
+        "@solana/wallet-adapter-wallets": "^0.7.7",
         "@solana/web3.js": "^1.20.0",
         "react": "^17.0.2",
         "react-dom": "^17.0.2"

+ 3 - 3
packages/react/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-react",
-    "version": "0.9.2",
+    "version": "0.9.3",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -21,7 +21,7 @@
     },
     "peerDependencies": {
         "@solana/wallet-adapter-base": "^0.5.2",
-        "@solana/wallet-adapter-wallets": "^0.7.6",
+        "@solana/wallet-adapter-wallets": "^0.7.7",
         "@solana/web3.js": "^1.20.0",
         "react": "^17.0.2"
     },
@@ -30,7 +30,7 @@
     },
     "devDependencies": {
         "@solana/wallet-adapter-base": "^0.5.2",
-        "@solana/wallet-adapter-wallets": "^0.7.6",
+        "@solana/wallet-adapter-wallets": "^0.7.7",
         "@solana/web3.js": "^1.20.0",
         "react": "^17.0.2"
     }

+ 1 - 8
packages/react/src/WalletProvider.tsx

@@ -84,13 +84,6 @@ export const WalletProvider: FC<WalletProviderProps> = ({
         }
     }, [autoConnect, adapter, ready, connecting, connected, setConnecting, setName]);
 
-    // Reset the state
-    const reset = useCallback(() => {
-        setConnecting(false);
-        setDisconnecting(false);
-        setState(initialState);
-    }, [setConnecting, setDisconnecting, setState]);
-
     // Select a wallet by name
     const select = useCallback(
         async (newName: WalletName | null) => {
@@ -119,7 +112,7 @@ export const WalletProvider: FC<WalletProviderProps> = ({
     }, [adapter, setState]);
 
     // Handle the adapter's disconnect event
-    const onDisconnect = useCallback(() => reset(), [reset]);
+    const onDisconnect = useCallback(() => setState(initialState), [setState]);
 
     // Connect the adapter to the wallet
     const connect = useCallback(async () => {

+ 1 - 1
packages/sollet/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-sollet",
-    "version": "0.5.2",
+    "version": "0.5.3",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",

+ 106 - 31
packages/sollet/src/adapter.ts

@@ -1,36 +1,52 @@
 import Wallet from '@project-serum/sol-wallet-adapter';
 import {
     BaseSignerWalletAdapter,
+    pollUntilReady,
     WalletAdapterNetwork,
     WalletConnectionError,
     WalletDisconnectedError,
     WalletDisconnectionError,
+    WalletError,
     WalletNotConnectedError,
+    WalletNotFoundError,
     WalletSignTransactionError,
+    WalletTimeoutError,
     WalletWindowBlockedError,
     WalletWindowClosedError,
 } from '@solana/wallet-adapter-base';
 import { PublicKey, Transaction } from '@solana/web3.js';
 
-type SolletProvider = string | { postMessage(...args: unknown[]): unknown };
+interface SolletWallet {
+    postMessage(...args: unknown[]): unknown;
+}
+
+interface SolletWindow extends Window {
+    sollet?: SolletWallet;
+}
+
+declare const window: SolletWindow;
 
 export interface SolletWalletAdapterConfig {
-    provider?: SolletProvider;
+    provider?: string | SolletWallet;
     network?: WalletAdapterNetwork;
+    pollInterval?: number;
+    pollCount?: number;
 }
 
 export class SolletWalletAdapter extends BaseSignerWalletAdapter {
-    private _provider: SolletProvider;
+    private _provider: string | SolletWallet | undefined;
     private _network: WalletAdapterNetwork;
     private _connecting: boolean;
     private _wallet: Wallet | null;
 
     constructor(config: SolletWalletAdapterConfig = {}) {
         super();
-        this._provider = config.provider || 'https://www.sollet.io';
+        this._provider = config.provider || window.sollet;
         this._network = config.network || WalletAdapterNetwork.Mainnet;
         this._connecting = false;
         this._wallet = null;
+
+        if (!this.ready) pollUntilReady(this, config.pollInterval || 1000, config.pollCount || 3);
     }
 
     get publicKey(): PublicKey | null {
@@ -38,8 +54,10 @@ export class SolletWalletAdapter extends BaseSignerWalletAdapter {
     }
 
     get ready(): boolean {
-        // @FIXME
-        return typeof window !== 'undefined';
+        return (
+            typeof window !== 'undefined' &&
+            (typeof this._provider === 'string' || typeof window.sollet?.postMessage === 'function')
+        );
     }
 
     get connecting(): boolean {
@@ -59,34 +77,63 @@ export class SolletWalletAdapter extends BaseSignerWalletAdapter {
             if (this.connected || this.connecting) return;
             this._connecting = true;
 
+            const provider = this._provider || window.sollet;
+            if (!provider) throw new WalletNotFoundError();
+
             let wallet: Wallet;
-            let interval: NodeJS.Timer | undefined;
             try {
-                wallet = new Wallet(this._provider, this._network);
-
-                // HACK: sol-wallet-adapter doesn't reject or emit an event if the popup is closed or blocked
-                await new Promise<void>((resolve, reject) => {
-                    wallet.connect().then(resolve, reject);
-
-                    if (typeof this._provider === 'string') {
-                        let count = 0;
-
-                        interval = setInterval(() => {
-                            const popup = (wallet as any)._popup;
-                            if (popup) {
-                                if (popup.closed) reject(new WalletWindowClosedError());
-                            } else {
-                                if (count > 50) reject(new WalletWindowBlockedError());
-                            }
-
-                            count++;
-                        }, 100);
-                    }
-                });
+                wallet = new Wallet(provider, this._network);
+
+                // HACK: sol-wallet-adapter doesn't reject or emit an event if the popup or extension is closed or blocked
+                const handleDisconnect: (...args: unknown[]) => unknown = (wallet as any).handleDisconnect;
+                let timeout: NodeJS.Timer | undefined;
+                let interval: NodeJS.Timer | undefined;
+                try {
+                    await new Promise<void>((resolve, reject) => {
+                        const connect = () => {
+                            if (timeout) clearTimeout(timeout);
+                            wallet.off('connect', connect);
+                            resolve();
+                        };
+
+                        (wallet as any).handleDisconnect = (...args: unknown[]): unknown => {
+                            wallet.off('connect', connect);
+                            reject(new WalletWindowClosedError());
+                            return handleDisconnect.apply(wallet, args);
+                        };
+
+                        wallet.on('connect', connect);
+
+                        wallet.connect().catch((reason: any) => {
+                            wallet.off('connect', connect);
+                            reject(reason);
+                        });
+
+                        if (typeof provider === 'string') {
+                            let count = 0;
+
+                            interval = setInterval(() => {
+                                const popup = (wallet as any)._popup;
+                                if (popup) {
+                                    if (popup.closed) reject(new WalletWindowClosedError());
+                                } else {
+                                    if (count > 50) reject(new WalletWindowBlockedError());
+                                }
+
+                                count++;
+                            }, 100);
+                        } else {
+                            // HACK: sol-wallet-adapter doesn't reject or emit an event if the extension is closed or ignored
+                            timeout = setTimeout(() => reject(new WalletTimeoutError()), 10000);
+                        }
+                    });
+                } finally {
+                    (wallet as any).handleDisconnect = handleDisconnect;
+                    if (interval) clearInterval(interval);
+                }
             } catch (error: any) {
+                if (error instanceof WalletError) throw error;
                 throw new WalletConnectionError(error?.message, error);
-            } finally {
-                if (interval) clearInterval(interval);
             }
 
             wallet.on('disconnect', this._disconnected);
@@ -109,10 +156,38 @@ export class SolletWalletAdapter extends BaseSignerWalletAdapter {
 
             this._wallet = null;
 
+            // HACK: sol-wallet-adapter doesn't reliably fulfill its promise or emit an event on disconnect
+            const handleDisconnect: (...args: unknown[]) => unknown = (wallet as any).handleDisconnect;
             try {
-                await wallet.disconnect();
+                await new Promise<void>((resolve, reject) => {
+                    const timeout = setTimeout(() => resolve(), 250);
+
+                    (wallet as any).handleDisconnect = (...args: unknown[]): unknown => {
+                        clearTimeout(timeout);
+                        resolve();
+                        return handleDisconnect.apply(wallet, args);
+                    };
+
+                    wallet.disconnect().then(
+                        () => {
+                            clearTimeout(timeout);
+                            resolve();
+                        },
+                        (error) => {
+                            clearTimeout(timeout);
+                            // HACK: sol-wallet-adapter rejects with an error on disconnect
+                            if (error.message === 'Wallet disconnected') {
+                                resolve();
+                            } else {
+                                reject(error);
+                            }
+                        }
+                    );
+                });
             } catch (error: any) {
                 this.emit('error', new WalletDisconnectionError(error?.message, error));
+            } finally {
+                (wallet as any).handleDisconnect = handleDisconnect;
             }
 
             this.emit('disconnect');

+ 2 - 0
packages/torus/src/adapter.ts

@@ -2,6 +2,7 @@ import {
     BaseSignerWalletAdapter,
     WalletConnectionError,
     WalletDisconnectionError,
+    WalletError,
     WalletKeypairError,
     WalletNotConnectedError,
     WalletSignTransactionError,
@@ -93,6 +94,7 @@ export class TorusWalletAdapter extends BaseSignerWalletAdapter {
                     }
                 }
             } catch (error: any) {
+                if (error instanceof WalletError) throw error;
                 throw new WalletConnectionError(error?.message, error);
             }
 

+ 2 - 0
packages/walletconnect/src/adapter.ts

@@ -4,6 +4,7 @@ import {
     WalletConnectionError,
     WalletDisconnectedError,
     WalletDisconnectionError,
+    WalletError,
     WalletNotConnectedError,
     WalletPublicKeyError,
     WalletSignTransactionError,
@@ -112,6 +113,7 @@ export class WalletConnectWalletAdapter extends BaseSignerWalletAdapter {
                     }
                 });
             } catch (error: any) {
+                if (error instanceof WalletError) throw error;
                 throw new WalletConnectionError(error?.message, error);
             }
 

+ 2 - 2
packages/wallets/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-wallets",
-    "version": "0.7.6",
+    "version": "0.7.7",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -32,7 +32,7 @@
         "@solana/wallet-adapter-safepal": "^0.1.0",
         "@solana/wallet-adapter-slope": "^0.1.1",
         "@solana/wallet-adapter-solflare": "^0.2.2",
-        "@solana/wallet-adapter-sollet": "^0.5.2",
+        "@solana/wallet-adapter-sollet": "^0.5.3",
         "@solana/wallet-adapter-solong": "^0.5.2",
         "@solana/wallet-adapter-torus": "^0.6.2"
     },

+ 21 - 14
packages/wallets/src/wallets.ts

@@ -24,6 +24,7 @@ export enum WalletName {
     Solflare = 'Solflare',
     SolflareWeb = 'Solflare (Web)',
     Sollet = 'Sollet',
+    SolletWeb = 'Sollet (Web)',
     Solong = 'Solong',
     Torus = 'Torus',
 }
@@ -37,85 +38,91 @@ export interface Wallet {
 
 export const ICONS_URL = 'https://raw.githubusercontent.com/solana-labs/wallet-adapter/master/packages/wallets/icons';
 
-export const getBitpieWallet = (config?: BitpieWalletAdapterConfig): Wallet => ({
+export const getBitpieWallet = (config: BitpieWalletAdapterConfig = {}): Wallet => ({
     name: WalletName.Bitpie,
     url: 'https://bitpiecn.com',
     icon: `${ICONS_URL}/bitpie.svg`,
     adapter: () => new BitpieWalletAdapter(config),
 });
 
-export const getBloctoWallet = (config?: BloctoWalletAdapterConfig): Wallet => ({
+export const getBloctoWallet = (config: BloctoWalletAdapterConfig = {}): Wallet => ({
     name: WalletName.Blocto,
     url: 'https://wallet.blocto.app',
     icon: `${ICONS_URL}/blocto.svg`,
     adapter: () => new BloctoWalletAdapter(config),
 });
 
-export const getCoin98Wallet = (config?: Coin98WalletAdapterConfig): Wallet => ({
+export const getCoin98Wallet = (config: Coin98WalletAdapterConfig = {}): Wallet => ({
     name: WalletName.Coin98,
     url: 'https://coin98.com',
     icon: `${ICONS_URL}/coin98.svg`,
     adapter: () => new Coin98WalletAdapter(config),
 });
 
-export const getLedgerWallet = (config?: LedgerWalletAdapterConfig): Wallet => ({
+export const getLedgerWallet = (config: LedgerWalletAdapterConfig = {}): Wallet => ({
     name: WalletName.Ledger,
     url: 'https://www.ledger.com',
     icon: `${ICONS_URL}/ledger.svg`,
     adapter: () => new LedgerWalletAdapter(config),
 });
 
-export const getMathWallet = (config?: MathWalletWalletAdapterConfig): Wallet => ({
+export const getMathWallet = (config: MathWalletWalletAdapterConfig = {}): Wallet => ({
     name: WalletName.MathWallet,
     url: 'https://mathwallet.org',
     icon: `${ICONS_URL}/mathwallet.svg`,
     adapter: () => new MathWalletWalletAdapter(config),
 });
 
-export const getPhantomWallet = (config?: PhantomWalletAdapterConfig): Wallet => ({
+export const getPhantomWallet = (config: PhantomWalletAdapterConfig = {}): Wallet => ({
     name: WalletName.Phantom,
     url: 'https://www.phantom.app',
     icon: `${ICONS_URL}/phantom.svg`,
     adapter: () => new PhantomWalletAdapter(config),
 });
 
-export const getSafePalWallet = (config?: SafePalWalletAdapterConfig): Wallet => ({
+export const getSafePalWallet = (config: SafePalWalletAdapterConfig = {}): Wallet => ({
     name: WalletName.SafePalWallet,
     url: 'https://www.safepal.io',
     icon: `${ICONS_URL}/safepal.svg`,
     adapter: () => new SafePalWalletAdapter(config),
 });
 
-export const getSlopeWallet = (config?: SlopeWalletAdapterConfig): Wallet => ({
+export const getSlopeWallet = (config: SlopeWalletAdapterConfig = {}): Wallet => ({
     name: WalletName.Slope,
     url: 'https://www.slope.finance/#/wallet',
     icon: `${ICONS_URL}/slope.svg`,
     adapter: () => new SlopeWalletAdapter(config),
 });
 
-export const getSolflareWallet = (config?: SolflareWalletAdapterConfig): Wallet => ({
+export const getSolflareWallet = (config: SolflareWalletAdapterConfig = {}): Wallet => ({
     name: WalletName.Solflare,
     url: 'https://solflare.com',
     icon: `${ICONS_URL}/solflare.svg`,
     adapter: () => new SolflareWalletAdapter(config),
 });
 
-export const getSolflareWebWallet = (config?: SolletWalletAdapterConfig): Wallet => ({
+export const getSolflareWebWallet = ({ provider, ...config }: SolletWalletAdapterConfig = {}): Wallet => ({
     name: WalletName.SolflareWeb,
     url: 'https://solflare.com',
     icon: `${ICONS_URL}/solflare.svg`,
-    adapter: () =>
-        new SolletWalletAdapter({ ...config, provider: config?.provider || 'https://solflare.com/access-wallet' }),
+    adapter: () => new SolletWalletAdapter({ provider: 'https://solflare.com/access-wallet', ...config }),
 });
 
-export const getSolletWallet = (config?: SolletWalletAdapterConfig): Wallet => ({
+export const getSolletWallet = ({ provider, ...config }: SolletWalletAdapterConfig = {}): Wallet => ({
     name: WalletName.Sollet,
     url: 'https://www.sollet.io',
     icon: `${ICONS_URL}/sollet.svg`,
     adapter: () => new SolletWalletAdapter(config),
 });
 
-export const getSolongWallet = (config?: SolongWalletAdapterConfig): Wallet => ({
+export const getSolletWebWallet = ({ provider, ...config }: SolletWalletAdapterConfig = {}): Wallet => ({
+    name: WalletName.SolletWeb,
+    url: 'https://www.sollet.io',
+    icon: `${ICONS_URL}/sollet.svg`,
+    adapter: () => new SolletWalletAdapter({ provider: 'https://www.sollet.io', ...config }),
+});
+
+export const getSolongWallet = (config: SolongWalletAdapterConfig = {}): Wallet => ({
     name: WalletName.Solong,
     url: 'https://solongwallet.com',
     icon: `${ICONS_URL}/solong.png`,