فهرست منبع

Merge pull request #214 from steveluscher/wallet-detection-metadata

Add wallet detection metadata & implementation
Jordan Sexton 3 سال پیش
والد
کامیت
469edb5dd4
100فایلهای تغییر یافته به همراه641 افزوده شده و 588 حذف شده
  1. 0 15
      FAQ.md
  2. 14 14
      README.md
  3. 2 0
      package.json
  4. 1 1
      packages/core/base/package.json
  5. 54 7
      packages/core/base/src/adapter.ts
  6. 1 1
      packages/core/base/src/index.ts
  7. 10 0
      packages/core/base/src/types.ts
  8. 0 15
      packages/core/base/src/wallet.ts
  9. 2 2
      packages/core/base/tsconfig.json
  10. 3 3
      packages/core/react/package.json
  11. 77 74
      packages/core/react/src/WalletProvider.tsx
  12. 53 58
      packages/core/react/src/__tests__/WalletProvider-test.tsx
  13. 0 15
      packages/core/react/src/useInitialState.ts
  14. 4 3
      packages/core/react/src/useLocalStorage.ts
  15. 19 10
      packages/core/react/src/useWallet.ts
  16. 3 3
      packages/core/react/tsconfig.json
  17. 3 1
      packages/core/react/tsconfig.test.json
  18. 2 2
      packages/core/svelte/tsconfig.json
  19. 2 2
      packages/core/vue/tsconfig.json
  20. 14 15
      packages/starter/example/components/ContextProvider.tsx
  21. 7 7
      packages/starter/example/package.json
  22. 3 3
      packages/starter/example/tsconfig.json
  23. 5 5
      packages/starter/material-ui-starter/package.json
  24. 14 14
      packages/starter/material-ui-starter/src/Wallet.tsx
  25. 2 2
      packages/starter/material-ui-starter/tsconfig.json
  26. 14 14
      packages/starter/nextjs-starter/components/WalletConnectionProvider.tsx
  27. 5 5
      packages/starter/nextjs-starter/package.json
  28. 3 3
      packages/starter/nextjs-starter/tsconfig.json
  29. 5 5
      packages/starter/react-ui-starter/package.json
  30. 14 14
      packages/starter/react-ui-starter/src/Wallet.tsx
  31. 2 2
      packages/starter/react-ui-starter/tsconfig.json
  32. 5 5
      packages/ui/ant-design/package.json
  33. 11 2
      packages/ui/ant-design/src/WalletIcon.tsx
  34. 2 2
      packages/ui/ant-design/src/WalletMenuItem.tsx
  35. 4 4
      packages/ui/ant-design/src/WalletModal.tsx
  36. 1 1
      packages/ui/ant-design/src/WalletMultiButton.tsx
  37. 2 2
      packages/ui/ant-design/tsconfig.json
  38. 5 5
      packages/ui/material-ui/package.json
  39. 9 9
      packages/ui/material-ui/src/WalletDialog.tsx
  40. 2 2
      packages/ui/material-ui/src/WalletIcon.tsx
  41. 2 2
      packages/ui/material-ui/src/WalletListItem.tsx
  42. 1 1
      packages/ui/material-ui/src/WalletMultiButton.tsx
  43. 2 2
      packages/ui/material-ui/tsconfig.json
  44. 5 5
      packages/ui/react-ui/package.json
  45. 2 2
      packages/ui/react-ui/src/WalletIcon.tsx
  46. 4 2
      packages/ui/react-ui/src/WalletListItem.tsx
  47. 22 10
      packages/ui/react-ui/src/WalletModal.tsx
  48. 2 2
      packages/ui/react-ui/tsconfig.json
  49. 2 2
      packages/ui/vue-ui/tsconfig.json
  50. 3 3
      packages/wallets/bitkeep/package.json
  51. 9 0
      packages/wallets/bitkeep/src/adapter.ts
  52. 0 1
      packages/wallets/bitkeep/src/index.ts
  53. 0 8
      packages/wallets/bitkeep/src/wallet.ts
  54. 2 2
      packages/wallets/bitkeep/tsconfig.json
  55. 3 3
      packages/wallets/bitpie/package.json
  56. 8 0
      packages/wallets/bitpie/src/adapter.ts
  57. 0 1
      packages/wallets/bitpie/src/index.ts
  58. 0 8
      packages/wallets/bitpie/src/wallet.ts
  59. 2 2
      packages/wallets/bitpie/tsconfig.json
  60. 3 3
      packages/wallets/blocto/package.json
  61. 17 5
      packages/wallets/blocto/src/adapter.ts
  62. 0 1
      packages/wallets/blocto/src/index.ts
  63. 0 11
      packages/wallets/blocto/src/wallet.ts
  64. 2 2
      packages/wallets/blocto/tsconfig.json
  65. 3 3
      packages/wallets/clover/package.json
  66. 30 16
      packages/wallets/clover/src/adapter.ts
  67. 0 1
      packages/wallets/clover/src/index.ts
  68. 0 11
      packages/wallets/clover/src/wallet.ts
  69. 2 2
      packages/wallets/clover/tsconfig.json
  70. 3 3
      packages/wallets/coin98/package.json
  71. 9 0
      packages/wallets/coin98/src/adapter.ts
  72. 0 1
      packages/wallets/coin98/src/index.ts
  73. 0 8
      packages/wallets/coin98/src/wallet.ts
  74. 2 2
      packages/wallets/coin98/tsconfig.json
  75. 3 3
      packages/wallets/coinhub/package.json
  76. 9 0
      packages/wallets/coinhub/src/adapter.ts
  77. 0 1
      packages/wallets/coinhub/src/index.ts
  78. 0 8
      packages/wallets/coinhub/src/wallet.ts
  79. 2 2
      packages/wallets/coinhub/tsconfig.json
  80. 3 3
      packages/wallets/ledger/package.json
  81. 17 5
      packages/wallets/ledger/src/adapter.ts
  82. 0 1
      packages/wallets/ledger/src/index.ts
  83. 2 0
      packages/wallets/ledger/src/util.ts
  84. 0 11
      packages/wallets/ledger/src/wallet.ts
  85. 2 2
      packages/wallets/ledger/tsconfig.json
  86. 3 3
      packages/wallets/mathwallet/package.json
  87. 9 0
      packages/wallets/mathwallet/src/adapter.ts
  88. 0 1
      packages/wallets/mathwallet/src/index.ts
  89. 0 8
      packages/wallets/mathwallet/src/wallet.ts
  90. 2 2
      packages/wallets/mathwallet/tsconfig.json
  91. 3 3
      packages/wallets/phantom/package.json
  92. 30 16
      packages/wallets/phantom/src/adapter.ts
  93. 0 1
      packages/wallets/phantom/src/index.ts
  94. 0 11
      packages/wallets/phantom/src/wallet.ts
  95. 2 2
      packages/wallets/phantom/tsconfig.json
  96. 3 3
      packages/wallets/safepal/package.json
  97. 30 16
      packages/wallets/safepal/src/adapter.ts
  98. 0 1
      packages/wallets/safepal/src/index.ts
  99. 0 11
      packages/wallets/safepal/src/wallet.ts
  100. 2 2
      packages/wallets/safepal/tsconfig.json

+ 0 - 15
FAQ.md

@@ -97,21 +97,6 @@ The other methods are optional APIs, so you have to feature-detect them before u
 
 Please see [issue #72](https://github.com/solana-labs/wallet-adapter/issues/72#issuecomment-919232595).
 
-### Torus wallet doesn't connect / `registering module Get a client ID @ https://developer.tor.us`
-
-This can happen if you're using one of the starter projects and you didn't configure Torus for your dApp.
-
-Go to https://developer.tor.us to sign up for your own unique client ID. Then use this ID in your configuration:
-```tsx
-    const wallets = useMemo(() => [
-        // ...
-        getTorusWallet({
-            options: { clientId: '<YOUR CLIENT ID>' },
-        }),
-        // ...
-    ], [network]);
-```
-
 ## How can I sign and verify messages?
 
 Some wallet adapters provide a `signMessage` method for signing arbitrary bytes:

+ 14 - 14
README.md

@@ -48,13 +48,13 @@ import React, { FC, useMemo } from 'react';
 import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react';
 import { WalletAdapterNetwork } from '@solana/wallet-adapter-base';
 import {
-    getLedgerWallet,
-    getPhantomWallet,
-    getSlopeWallet,
-    getSolflareWallet,
-    getSolletExtensionWallet,
-    getSolletWallet,
-    getTorusWallet,
+    LedgerWalletAdapter,
+    PhantomWalletAdapter,
+    SlopeWalletAdapter,
+    SolflareWalletAdapter,
+    SolletExtensionWalletAdapter,
+    SolletWalletAdapter,
+    TorusWalletAdapter,
 } from '@solana/wallet-adapter-wallets';
 import {
     WalletModalProvider,
@@ -78,13 +78,13 @@ export const Wallet: FC = () => {
     // of wallets that your users connect to will be loaded
     const wallets = useMemo(
         () => [
-            getPhantomWallet(),
-            getSlopeWallet(),
-            getSolflareWallet(),
-            getTorusWallet(),
-            getLedgerWallet(),
-            getSolletWallet({ network }),
-            getSolletExtensionWallet({ network }),
+            new PhantomWalletAdapter(),
+            new SlopeWalletAdapter(),
+            new SolflareWalletAdapter(),
+            new TorusWalletAdapter(),
+            new LedgerWalletAdapter(),
+            new SolletWalletAdapter({ network }),
+            new SolletExtensionWalletAdapter({ network }),
         ],
         [network]
     );

+ 2 - 0
package.json

@@ -10,6 +10,8 @@
             "packages/*/*"
         ],
         "nohoist": [
+            "**/@babel/preset-env",
+            "**/@babel/preset-env/**",
             "**/babel-loader",
             "**/babel-loader/**",
             "**/webpack",

+ 1 - 1
packages/core/base/package.json

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

+ 54 - 7
packages/core/base/src/adapter.ts

@@ -5,21 +5,29 @@ import { WalletError } from './errors';
 export { EventEmitter };
 
 export interface WalletAdapterEvents {
-    connect(): void;
+    connect(publicKey: PublicKey): void;
     disconnect(): void;
     error(error: WalletError): void;
+    readyStateChange(readyState: WalletReadyState): void;
 }
 
 export interface SendTransactionOptions extends SendOptions {
     signers?: Signer[];
 }
 
+// WalletName is a nominal type that wallet adapters should use, e.g. `'MyCryptoWallet' as WalletName`
+// https://medium.com/@KevinBGreene/surviving-the-typescript-ecosystem-branding-and-type-tagging-6cf6e516523d
+export type WalletName = string & { __brand__: 'WalletName' };
+
 export interface WalletAdapterProps {
+    name: WalletName;
+    url: string;
+    icon: string;
+    readyState: WalletReadyState;
     publicKey: PublicKey | null;
     connecting: boolean;
     connected: boolean;
 
-    ready(): Promise<boolean>;
     connect(): Promise<void>;
     disconnect(): Promise<void>;
     sendTransaction(
@@ -31,7 +39,40 @@ export interface WalletAdapterProps {
 
 export type WalletAdapter = WalletAdapterProps & EventEmitter<WalletAdapterEvents>;
 
+/**
+ * A wallet's readiness describes a series of states that the wallet can be in,
+ * depending on what kind of wallet it is. An installable wallet (eg. a browser
+ * extension like Phantom) might be `Installed` if we've found the Phantom API
+ * in the global scope, or `NotDetected` otherwise. A loadable, zero-install
+ * runtime (eg. Torus Wallet) might simply signal that it's `Loadable`. Use this
+ * metadata to personalize the wallet list for each user (eg. to show their
+ * installed wallets first).
+ */
+export enum WalletReadyState {
+    /**
+     * User-installable wallets can typically be detected by scanning for an API
+     * that they've injected into the global context. If such an API is present,
+     * we consider the wallet to have been installed.
+     */
+    Installed = 'Installed',
+    NotDetected = 'NotDetected',
+    /**
+     * Loadable wallets are always available to you. Since you can load them at
+     * any time, it's meaningless to say that they have been detected.
+     */
+    Loadable = 'Loadable',
+    /**
+     * If a wallet is not supported on a given platform (eg. server-rendering, or
+     * mobile) then it will stay in the `Unsupported` state.
+     */
+    Unsupported = 'Unsupported',
+}
+
 export abstract class BaseWalletAdapter extends EventEmitter<WalletAdapterEvents> implements WalletAdapter {
+    abstract name: WalletName;
+    abstract url: string;
+    abstract icon: string;
+    abstract readyState: WalletReadyState;
     abstract publicKey: PublicKey | null;
     abstract connecting: boolean;
 
@@ -39,7 +80,6 @@ export abstract class BaseWalletAdapter extends EventEmitter<WalletAdapterEvents
         return !!this.publicKey;
     }
 
-    abstract ready(): Promise<boolean>;
     abstract connect(): Promise<void>;
     abstract disconnect(): Promise<void>;
     abstract sendTransaction(
@@ -49,8 +89,15 @@ export abstract class BaseWalletAdapter extends EventEmitter<WalletAdapterEvents
     ): Promise<TransactionSignature>;
 }
 
-export enum WalletAdapterNetwork {
-    Mainnet = 'mainnet-beta',
-    Testnet = 'testnet',
-    Devnet = 'devnet',
+export function scopePollingDetectionStrategy(performDetection: () => boolean): void {
+    if (typeof window === 'undefined' || typeof document === 'undefined') return;
+    if (document.readyState === 'complete') {
+        performDetection();
+        return;
+    }
+    function listener() {
+        window.removeEventListener('load', listener);
+        performDetection();
+    }
+    window.addEventListener('load', listener);
 }

+ 1 - 1
packages/core/base/src/index.ts

@@ -1,4 +1,4 @@
 export * from './adapter';
 export * from './errors';
 export * from './signer';
-export * from './wallet';
+export * from './types';

+ 10 - 0
packages/core/base/src/types.ts

@@ -0,0 +1,10 @@
+import { WalletAdapter } from './adapter';
+import { MessageSignerWalletAdapter, SignerWalletAdapter } from './signer';
+
+export type Adapter = WalletAdapter | SignerWalletAdapter | MessageSignerWalletAdapter;
+
+export enum WalletAdapterNetwork {
+    Mainnet = 'mainnet-beta',
+    Testnet = 'testnet',
+    Devnet = 'devnet',
+}

+ 0 - 15
packages/core/base/src/wallet.ts

@@ -1,15 +0,0 @@
-import { WalletAdapter } from './adapter';
-import { MessageSignerWalletAdapter, SignerWalletAdapter } from './signer';
-
-// WalletName is a nominal type that wallet adapters should use, e.g. `'MyCryptoWallet' as WalletName`
-// https://medium.com/@KevinBGreene/surviving-the-typescript-ecosystem-branding-and-type-tagging-6cf6e516523d
-export type WalletName = string & { __brand__: 'WalletName' };
-
-export type Adapter = WalletAdapter | SignerWalletAdapter | MessageSignerWalletAdapter;
-
-export interface Wallet {
-    name: WalletName;
-    url: string;
-    icon: string;
-    adapter: Adapter;
-}

+ 2 - 2
packages/core/base/tsconfig.json

@@ -1,8 +1,8 @@
 {
     "extends": "../../../tsconfig.json",
+    "include": ["src"],
     "compilerOptions": {
         "noEmit": false,
         "outDir": "lib"
-    },
-    "include": ["src"]
+    }
 }

+ 3 - 3
packages/core/react/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-react",
-    "version": "0.14.2",
+    "version": "0.15.0",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -23,12 +23,12 @@
         "test": "jest"
     },
     "peerDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0",
         "react": "^17.0.2"
     },
     "devDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0",
         "@types/jest": "^27.0.3",
         "@types/react": "^17.0.24",

+ 77 - 74
packages/core/react/src/WalletProvider.tsx

@@ -1,106 +1,112 @@
 import {
     Adapter,
     SendTransactionOptions,
-    Wallet,
     WalletError,
     WalletName,
     WalletNotConnectedError,
     WalletNotReadyError,
+    WalletReadyState,
 } from '@solana/wallet-adapter-base';
 import { Connection, PublicKey, Transaction } from '@solana/web3.js';
 import React, { FC, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';
 import { WalletNotSelectedError } from './errors';
-import { useInitialState } from './useInitialState';
 import { useLocalStorage } from './useLocalStorage';
-import { EnhancedWallet, WalletContext } from './useWallet';
+import { Wallet, WalletContext } from './useWallet';
 
 export interface WalletProviderProps {
     children: ReactNode;
-    wallets: Wallet[];
+    wallets: Adapter[];
     autoConnect?: boolean;
     onError?: (error: WalletError) => void;
     localStorageKey?: string;
 }
 
 const initialState: {
-    wallet: EnhancedWallet | null;
+    wallet: Wallet | null;
     adapter: Adapter | null;
-    ready: boolean;
-    connected: boolean;
     publicKey: PublicKey | null;
+    connected: boolean;
 } = {
     wallet: null,
     adapter: null,
-    ready: false,
-    connected: false,
     publicKey: null,
+    connected: false,
 };
 
 export const WalletProvider: FC<WalletProviderProps> = ({
     children,
-    wallets,
+    wallets: adapters,
     autoConnect = false,
     onError,
     localStorageKey = 'walletName',
 }) => {
     const [name, setName] = useLocalStorage<WalletName | null>(localStorageKey, null);
-    const [{ wallet, adapter, ready, publicKey, connected }, setState] = useState(initialState);
+    const [{ wallet, adapter, publicKey, connected }, setState] = useState(initialState);
+    const readyState = adapter?.readyState || WalletReadyState.Unsupported;
     const [connecting, setConnecting] = useState(false);
     const [disconnecting, setDisconnecting] = useState(false);
     const isConnecting = useRef(false);
     const isDisconnecting = useRef(false);
     const isUnloading = useRef(false);
 
-    // When the wallets change, enhance them with additional properties
-    const [enhancedWallets, setEnhancedWallets] = useInitialState(
-        () => wallets.map((wallet) => ({ ...wallet, ready: false })),
-        [wallets]
+    // Wrap adapters to conform to the `Wallet` interface
+    const [wallets, setWallets] = useState(() =>
+        adapters.map((adapter) => ({
+            adapter,
+            readyState: adapter.readyState,
+        }))
     );
 
-    // When the wallets change, asynchronously update the enhanced properties
+    // When the wallets change, start to listen for changes to their `readyState`
     useEffect(() => {
-        let walletsChangedWhileWaiting = false;
-        (async () => {
-            const ready = await Promise.all(wallets.map((wallet) => wallet.adapter.ready()));
-            if (!walletsChangedWhileWaiting) {
-                setEnhancedWallets(wallets.map((wallet, index) => ({ ...wallet, ready: ready[index] })));
-            }
-        })();
+        function handleReadyStateChange(this: Adapter, readyState: WalletReadyState) {
+            setWallets((prevWallets) => {
+                const walletIndex = prevWallets.findIndex(({ adapter }) => adapter.name === this.name);
+                if (walletIndex === -1) return prevWallets;
+
+                return [
+                    ...prevWallets.slice(0, walletIndex),
+                    { ...prevWallets[walletIndex], readyState },
+                    ...prevWallets.slice(walletIndex + 1),
+                ];
+            });
+        }
+        for (const adapter of adapters) {
+            adapter.on('readyStateChange', handleReadyStateChange, adapter);
+        }
         return () => {
-            walletsChangedWhileWaiting = true;
+            for (const adapter of adapters) {
+                adapter.off('readyStateChange', handleReadyStateChange, adapter);
+            }
         };
-    }, [wallets]);
-
-    // When the enhanced wallets change, map the wallet names to the enhanced wallets
-    const enhancedWalletsByName = useMemo(
-        () =>
-            enhancedWallets.reduce<Record<WalletName, EnhancedWallet>>((enhancedWallets, enhancedWallet) => {
-                enhancedWallets[enhancedWallet.name] = enhancedWallet;
-                return enhancedWallets;
-            }, {}),
-        [enhancedWallets]
-    );
+    }, [adapters]);
 
     // When the selected wallet changes, initialize the state
     useEffect(() => {
-        const wallet = (name && enhancedWalletsByName[name]) || null;
-        const adapter = wallet && wallet.adapter;
-        if (adapter) {
+        const wallet = wallets.find(({ adapter }) => adapter.name === name);
+        if (wallet) {
             setState({
                 wallet,
-                adapter,
-                ready: enhancedWalletsByName[wallet.name].ready,
-                connected: adapter.connected,
-                publicKey: adapter.publicKey,
+                adapter: wallet.adapter,
+                connected: wallet.adapter.connected,
+                publicKey: wallet.adapter.publicKey,
             });
         } else {
             setState(initialState);
         }
-    }, [name, enhancedWalletsByName]);
+    }, [name, wallets]);
 
     // If autoConnect is enabled, try to connect when the adapter changes and is ready
     useEffect(() => {
-        if (isConnecting.current || connecting || connected || !autoConnect || !adapter || !ready) return;
+        if (
+            isConnecting.current ||
+            connecting ||
+            connected ||
+            !autoConnect ||
+            !adapter ||
+            !(readyState === WalletReadyState.Installed || readyState === WalletReadyState.Loadable)
+        )
+            return;
 
         (async function () {
             isConnecting.current = true;
@@ -116,7 +122,7 @@ export const WalletProvider: FC<WalletProviderProps> = ({
                 isConnecting.current = false;
             }
         })();
-    }, [isConnecting, connecting, connected, autoConnect, adapter, ready]);
+    }, [isConnecting, connecting, connected, autoConnect, adapter, readyState]);
 
     // If the window is closing or reloading, ignore disconnect and error events from the adapter
     useEffect(() => {
@@ -150,17 +156,38 @@ export const WalletProvider: FC<WalletProviderProps> = ({
         [isUnloading, onError]
     );
 
+    // Setup and teardown event listeners when the adapter changes
+    useEffect(() => {
+        if (adapter) {
+            adapter.on('connect', handleConnect);
+            adapter.on('disconnect', handleDisconnect);
+            adapter.on('error', handleError);
+            return () => {
+                adapter.off('connect', handleConnect);
+                adapter.off('disconnect', handleDisconnect);
+                adapter.off('error', handleError);
+            };
+        }
+    }, [adapter, handleConnect, handleDisconnect, handleError]);
+
+    // When the adapter changes, disconnect the old one
+    useEffect(() => {
+        return () => {
+            adapter?.disconnect();
+        };
+    }, [adapter]);
+
     // Connect the adapter to the wallet
     const connect = useCallback(async () => {
         if (isConnecting.current || connecting || disconnecting || connected) return;
-        if (!wallet || !adapter) throw handleError(new WalletNotSelectedError());
+        if (!adapter) throw handleError(new WalletNotSelectedError());
 
-        if (!ready) {
+        if (!(readyState === WalletReadyState.Installed || readyState === WalletReadyState.Loadable)) {
             // Clear the selected wallet
             setName(null);
 
             if (typeof window !== 'undefined') {
-                window.open(wallet.url, '_blank');
+                window.open(adapter.url, '_blank');
             }
 
             throw handleError(new WalletNotReadyError());
@@ -179,7 +206,7 @@ export const WalletProvider: FC<WalletProviderProps> = ({
             setConnecting(false);
             isConnecting.current = false;
         }
-    }, [isConnecting, connecting, disconnecting, connected, wallet, adapter, handleError, ready]);
+    }, [isConnecting, connecting, disconnecting, connected, adapter, readyState, handleError]);
 
     // Disconnect the adapter from the wallet
     const disconnect = useCallback(async () => {
@@ -247,37 +274,13 @@ export const WalletProvider: FC<WalletProviderProps> = ({
         [adapter, handleError, connected]
     );
 
-    // Setup and teardown event listeners when the adapter changes
-    useEffect(() => {
-        if (adapter) {
-            adapter.on('connect', handleConnect);
-            adapter.on('disconnect', handleDisconnect);
-            adapter.on('error', handleError);
-            return () => {
-                adapter.off('connect', handleConnect);
-                adapter.off('disconnect', handleDisconnect);
-                adapter.off('error', handleError);
-            };
-        }
-    }, [adapter, handleConnect, handleDisconnect, handleError]);
-
-    // When the adapter changes, disconnect the old one.
-    useEffect(() => {
-        return () => {
-            adapter?.disconnect();
-        };
-    }, [adapter]);
-
     return (
         <WalletContext.Provider
             value={{
-                wallets: enhancedWallets,
-                walletsByName: enhancedWalletsByName,
                 autoConnect,
+                wallets,
                 wallet,
-                adapter,
                 publicKey,
-                ready,
                 connected,
                 connecting,
                 disconnecting,

+ 53 - 58
packages/core/react/src/__tests__/WalletProvider-test.tsx

@@ -9,7 +9,14 @@ import { render, unmountComponentAtNode } from 'react-dom';
 import React, { createRef, forwardRef, useImperativeHandle } from 'react';
 import { act } from 'react-dom/test-utils';
 import { WalletProvider, WalletProviderProps } from '../WalletProvider';
-import { BaseWalletAdapter, Wallet, WalletError, WalletName, WalletNotReadyError } from '@solana/wallet-adapter-base';
+import {
+    Adapter,
+    BaseWalletAdapter,
+    WalletError,
+    WalletName,
+    WalletNotReadyError,
+    WalletReadyState,
+} from '@solana/wallet-adapter-base';
 import { PublicKey } from '@solana/web3.js';
 import { useWallet, WalletContextState } from '../useWallet';
 
@@ -37,12 +44,12 @@ describe('WalletProvider', () => {
     let fooWalletAdapter: MockWalletAdapter;
     let barWalletAdapter: MockWalletAdapter;
     let bazWalletAdapter: MockWalletAdapter;
-    let wallets: Wallet[];
+    let adapters: Adapter[];
 
-    function renderTest(props: Pick<WalletProviderProps, Exclude<keyof WalletProviderProps, 'children' | 'wallets'>>) {
+    function renderTest(props: Omit<WalletProviderProps, 'children' | 'wallets'>) {
         act(() => {
             render(
-                <WalletProvider {...props} wallets={wallets}>
+                <WalletProvider {...props} wallets={adapters}>
                     <TestComponent ref={ref} />
                 </WalletProvider>,
                 container
@@ -53,18 +60,15 @@ describe('WalletProvider', () => {
     abstract class MockWalletAdapter extends BaseWalletAdapter {
         connectionPromise: null | Promise<void> = null;
         disconnectionPromise: null | Promise<void> = null;
-        readyPromise: null | Promise<void> = null;
         connectedValue = false;
         get connected() {
             return this.connectedValue;
         }
+        readyStateValue: WalletReadyState = WalletReadyState.Installed;
+        get readyState() {
+            return this.readyStateValue;
+        }
         connecting = false;
-        ready = jest.fn(async () => {
-            if (this.readyPromise) {
-                await this.readyPromise;
-            }
-            return true;
-        });
         connect = jest.fn(async () => {
             this.connecting = true;
             if (this.connectionPromise) {
@@ -72,7 +76,7 @@ describe('WalletProvider', () => {
             }
             this.connecting = false;
             this.connectedValue = true;
-            this.emit('connect');
+            this.emit('connect', this.publicKey!);
         });
         disconnect = jest.fn(async () => {
             this.connecting = false;
@@ -85,12 +89,21 @@ describe('WalletProvider', () => {
         sendTransaction = jest.fn();
     }
     class FooWalletAdapter extends MockWalletAdapter {
+        name = 'FooWallet' as WalletName;
+        url = 'https://foowallet.com';
+        icon = 'foo.png';
         publicKey = new PublicKey('Foo11111111111111111111111111111111111111111');
     }
     class BarWalletAdapter extends MockWalletAdapter {
+        name = 'BarWallet' as WalletName;
+        url = 'https://barwallet.com';
+        icon = 'bar.png';
         publicKey = new PublicKey('Bar11111111111111111111111111111111111111111');
     }
     class BazWalletAdapter extends MockWalletAdapter {
+        name = 'BazWallet' as WalletName;
+        url = 'https://bazwallet.com';
+        icon = 'baz.png';
         publicKey = new PublicKey('Baz11111111111111111111111111111111111111111');
     }
 
@@ -103,26 +116,7 @@ describe('WalletProvider', () => {
         fooWalletAdapter = new FooWalletAdapter();
         barWalletAdapter = new BarWalletAdapter();
         bazWalletAdapter = new BazWalletAdapter();
-        wallets = [
-            {
-                adapter: fooWalletAdapter,
-                icon: 'foo.png',
-                name: 'FooWallet' as WalletName,
-                url: 'https://foowallet.com',
-            },
-            {
-                adapter: barWalletAdapter,
-                icon: 'bar.png',
-                name: 'BarWallet' as WalletName,
-                url: 'https://barwallet.com',
-            },
-            {
-                adapter: bazWalletAdapter,
-                icon: 'baz.png',
-                name: 'BazWallet' as WalletName,
-                url: 'https://bazwallet.com',
-            },
-        ];
+        adapters = [fooWalletAdapter, barWalletAdapter, bazWalletAdapter];
     });
     afterEach(() => {
         if (container) {
@@ -132,26 +126,24 @@ describe('WalletProvider', () => {
         }
     });
     describe('given a selected wallet', () => {
-        let makeReady: () => void;
         beforeEach(async () => {
-            fooWalletAdapter.readyPromise = new Promise((resolve) => {
-                makeReady = resolve;
-            });
+            fooWalletAdapter.readyStateValue = WalletReadyState.NotDetected;
             renderTest({});
             await act(async () => {
                 ref.current?.getWalletContextState().select('FooWallet' as WalletName);
                 await Promise.resolve(); // Flush all promises in effects after calling `select()`.
             });
-            expect(ref.current?.getWalletContextState().ready).toBe(false);
+            expect(ref.current?.getWalletContextState().wallet?.readyState).toBe(WalletReadyState.NotDetected);
         });
         describe('that then becomes ready', () => {
             beforeEach(() => {
                 act(() => {
-                    makeReady();
+                    fooWalletAdapter.readyStateValue = WalletReadyState.Installed;
+                    fooWalletAdapter.emit('readyStateChange', WalletReadyState.Installed);
                 });
             });
             it('sets `ready` to true', () => {
-                expect(ref.current?.getWalletContextState().ready).toBe(true);
+                expect(ref.current?.getWalletContextState().wallet?.readyState).toBe(WalletReadyState.Installed);
             });
         });
         describe('when the wallet disconnects of its own accord', () => {
@@ -165,11 +157,10 @@ describe('WalletProvider', () => {
             });
             it('updates state tracking variables appropriately', () => {
                 expect(ref.current?.getWalletContextState()).toMatchObject({
-                    adapter: null,
+                    wallet: null,
                     connected: false,
                     connecting: false,
                     publicKey: null,
-                    ready: false,
                 });
             });
         });
@@ -189,9 +180,9 @@ describe('WalletProvider', () => {
         beforeEach(() => {
             (localStorage.getItem as jest.Mock).mockReturnValue(null);
         });
-        it('loads no adapter into state', () => {
+        it('loads no wallet into state', () => {
             renderTest({});
-            expect(ref.current?.getWalletContextState().adapter).toBeNull();
+            expect(ref.current?.getWalletContextState().wallet).toBeNull();
         });
         it('loads no public key into state', () => {
             renderTest({});
@@ -204,7 +195,7 @@ describe('WalletProvider', () => {
         });
         it('loads the corresponding adapter into state', () => {
             renderTest({});
-            expect(ref.current?.getWalletContextState().adapter).toBeInstanceOf(FooWalletAdapter);
+            expect(ref.current?.getWalletContextState().wallet?.adapter).toBeInstanceOf(FooWalletAdapter);
         });
         it('loads the corresponding public key into state', () => {
             renderTest({});
@@ -232,6 +223,7 @@ describe('WalletProvider', () => {
         describe('and auto connect is enabled', () => {
             const props = { autoConnect: true };
             beforeEach(() => {
+                fooWalletAdapter.readyStateValue = WalletReadyState.NotDetected;
                 renderTest(props);
             });
             it('`autoConnect` is `true` on state', () => {
@@ -241,15 +233,17 @@ describe('WalletProvider', () => {
                 it('does not call `connect` on the adapter', () => {
                     expect(fooWalletAdapter.connect).not.toHaveBeenCalled();
                 });
-            });
-            describe('once the adapter becomes ready', () => {
-                beforeEach(() => {
-                    act(() => {
-                        fooWalletAdapter.ready();
+                describe('once the adapter becomes ready', () => {
+                    beforeEach(async () => {
+                        await act(async () => {
+                            fooWalletAdapter.readyStateValue = WalletReadyState.Installed;
+                            fooWalletAdapter.emit('readyStateChange', WalletReadyState.Installed);
+                            await Promise.resolve(); // Flush all promises in effects after calling `select()`.
+                        });
+                    });
+                    it('calls `connect` on the adapter', () => {
+                        expect(fooWalletAdapter.connect).toHaveBeenCalledTimes(1);
                     });
-                });
-                it('calls `connect` on the adapter', () => {
-                    expect(fooWalletAdapter.connect).toHaveBeenCalledTimes(1);
                 });
             });
         });
@@ -284,18 +278,19 @@ describe('WalletProvider', () => {
         describe('given a wallet that is not ready', () => {
             beforeEach(async () => {
                 window.open = jest.fn();
+                fooWalletAdapter.readyStateValue = WalletReadyState.NotDetected;
                 renderTest({});
                 act(() => {
                     ref.current?.getWalletContextState().select('FooWallet' as WalletName);
                 });
-                expect(ref.current?.getWalletContextState().ready).toBe(false);
+                expect(ref.current?.getWalletContextState().wallet?.readyState).toBe(WalletReadyState.NotDetected);
                 act(() => {
                     expect(ref.current?.getWalletContextState().connect).rejects.toThrow();
                 });
             });
             it('clears out the state', () => {
                 expect(ref.current?.getWalletContextState()).toMatchObject({
-                    adapter: null,
+                    wallet: null,
                     connected: false,
                     connecting: false,
                     publicKey: null,
@@ -385,7 +380,7 @@ describe('WalletProvider', () => {
                 });
                 it('clears out the state', () => {
                     expect(ref.current?.getWalletContextState()).toMatchObject({
-                        adapter: null,
+                        wallet: null,
                         connected: false,
                         connecting: false,
                         publicKey: null,
@@ -406,7 +401,7 @@ describe('WalletProvider', () => {
                 });
                 it('sets the state tracking variables', () => {
                     expect(ref.current?.getWalletContextState()).toMatchObject({
-                        adapter: fooWalletAdapter,
+                        wallet: { adapter: fooWalletAdapter, readyState: fooWalletAdapter.readyState },
                         connected: false,
                         connecting: false,
                         publicKey: fooWalletAdapter.publicKey,
@@ -437,7 +432,7 @@ describe('WalletProvider', () => {
                     expect(fooWalletAdapter.disconnect).toHaveBeenCalled();
                 });
                 it('the adapter of the new wallet should be set in state', () => {
-                    expect(ref.current?.getWalletContextState().adapter).toBe(barWalletAdapter);
+                    expect(ref.current?.getWalletContextState().wallet?.adapter).toBe(barWalletAdapter);
                 });
                 /**
                  * Regression test: a race condition in the wallet name setter could result in the
@@ -455,7 +450,7 @@ describe('WalletProvider', () => {
                         });
                     });
                     it('the wallet you selected last should be set in state', () => {
-                        expect(ref.current?.getWalletContextState().adapter).toBe(bazWalletAdapter);
+                        expect(ref.current?.getWalletContextState().wallet?.adapter).toBe(bazWalletAdapter);
                     });
                 });
             });

+ 0 - 15
packages/core/react/src/useInitialState.ts

@@ -1,15 +0,0 @@
-import { DependencyList, Dispatch, SetStateAction, useEffect, useMemo, useState } from 'react';
-
-/** @internal */
-export function useInitialState<S>(
-    factory: () => S,
-    deps: DependencyList | undefined
-): [S, Dispatch<SetStateAction<S>>] {
-    const initialState = useMemo(factory, deps);
-    const [state, setState] = useState(initialState);
-
-    // When the deps change, reinitialize the state
-    useEffect(() => setState(initialState), [initialState]);
-
-    return [state, setState];
-}

+ 4 - 3
packages/core/react/src/useLocalStorage.ts

@@ -11,6 +11,7 @@ export function useLocalStorage<T>(key: string, defaultState: T): [T, React.Disp
 
         return defaultState;
     });
+    const value = state[0];
 
     const isFirstRender = useRef(true);
     useEffect(() => {
@@ -19,15 +20,15 @@ export function useLocalStorage<T>(key: string, defaultState: T): [T, React.Disp
             return;
         }
         try {
-            if (state[0] === null) {
+            if (value === null) {
                 localStorage.removeItem(key);
             } else {
-                localStorage.setItem(key, JSON.stringify(state[0]));
+                localStorage.setItem(key, JSON.stringify(value));
             }
         } catch (error) {
             console.error(error);
         }
-    }, [state[0]]);
+    }, [value]);
 
     return state;
 }

+ 19 - 10
packages/core/react/src/useWallet.ts

@@ -1,27 +1,36 @@
 import {
     Adapter,
     MessageSignerWalletAdapterProps,
+    SendTransactionOptions,
     SignerWalletAdapterProps,
-    Wallet,
-    WalletAdapterProps,
     WalletName,
+    WalletReadyState,
 } from '@solana/wallet-adapter-base';
+import { Connection, PublicKey, Transaction, TransactionSignature } from '@solana/web3.js';
 import { createContext, useContext } from 'react';
 
-export interface EnhancedWallet extends Wallet {
-    ready: boolean;
+export interface Wallet {
+    adapter: Adapter;
+    readyState: WalletReadyState;
 }
 
-export interface WalletContextState extends Omit<WalletAdapterProps, 'ready'> {
-    wallets: EnhancedWallet[];
-    walletsByName: Record<WalletName, EnhancedWallet>;
+export interface WalletContextState {
     autoConnect: boolean;
-    wallet: EnhancedWallet | null;
-    adapter: Adapter | null;
-    ready: boolean;
+    wallets: Wallet[];
+    wallet: Wallet | null;
+    publicKey: PublicKey | null;
+    connecting: boolean;
+    connected: boolean;
     disconnecting: boolean;
 
     select(walletName: WalletName): void;
+    connect(): Promise<void>;
+    disconnect(): Promise<void>;
+    sendTransaction(
+        transaction: Transaction,
+        connection: Connection,
+        options?: SendTransactionOptions
+    ): Promise<TransactionSignature>;
 
     signTransaction: SignerWalletAdapterProps['signTransaction'] | undefined;
     signAllTransactions: SignerWalletAdapterProps['signAllTransactions'] | undefined;

+ 3 - 3
packages/core/react/tsconfig.json

@@ -1,9 +1,9 @@
 {
     "extends": "../../../tsconfig.json",
+    "include": ["src"],
+    "exclude": ["node_modules", "src/**/__tests__"],
     "compilerOptions": {
         "noEmit": false,
         "outDir": "lib"
-    },
-    "include": ["src"],
-    "exclude": ["node_modules", "src/**/__tests__"]
+    }
 }

+ 3 - 1
packages/core/react/tsconfig.test.json

@@ -1,6 +1,8 @@
 {
     "extends": "./tsconfig.json",
+    "exclude": ["node_modules"],
     "compilerOptions": {
+        "noEmit": true,
         "allowJs": true
-    },
+    }
 }

+ 2 - 2
packages/core/svelte/tsconfig.json

@@ -1,8 +1,8 @@
 {
     "extends": "../../../tsconfig.json",
+    "include": ["src"],
     "compilerOptions": {
         "noEmit": false,
         "outDir": "lib"
-    },
-    "include": ["src"]
+    }
 }

+ 2 - 2
packages/core/vue/tsconfig.json

@@ -1,9 +1,9 @@
 {
     "extends": "../../../tsconfig.json",
+    "include": ["src"],
     "compilerOptions": {
         "noEmit": false,
         "outDir": "lib",
         "isolatedModules": false
-    },
-    "include": ["src"]
+    }
 }

+ 14 - 15
packages/starter/example/components/ContextProvider.tsx

@@ -1,16 +1,15 @@
 import { createTheme, StyledEngineProvider, ThemeProvider } from '@mui/material';
-
 import { deepPurple, pink } from '@mui/material/colors';
 import { WalletAdapterNetwork, WalletError } from '@solana/wallet-adapter-base';
 import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react';
 import {
-    getLedgerWallet,
-    getPhantomWallet,
-    getSlopeWallet,
-    getSolflareWallet,
-    getSolletExtensionWallet,
-    getSolletWallet,
-    getTorusWallet,
+    LedgerWalletAdapter,
+    PhantomWalletAdapter,
+    SlopeWalletAdapter,
+    SolflareWalletAdapter,
+    SolletExtensionWalletAdapter,
+    SolletWalletAdapter,
+    TorusWalletAdapter,
 } from '@solana/wallet-adapter-wallets';
 import { clusterApiUrl } from '@solana/web3.js';
 import { SnackbarProvider, useSnackbar } from 'notistack';
@@ -66,13 +65,13 @@ const WalletContextProvider: FC<{ children: ReactNode }> = ({ children }) => {
     // of wallets that your users connect to will be loaded
     const wallets = useMemo(
         () => [
-            getPhantomWallet(),
-            getSlopeWallet(),
-            getSolflareWallet(),
-            getTorusWallet(),
-            getLedgerWallet(),
-            getSolletWallet({ network }),
-            getSolletExtensionWallet({ network }),
+            new PhantomWalletAdapter(),
+            new SlopeWalletAdapter(),
+            new SolflareWalletAdapter(),
+            new TorusWalletAdapter(),
+            new LedgerWalletAdapter(),
+            new SolletWalletAdapter({ network }),
+            new SolletExtensionWalletAdapter({ network }),
         ],
         [network]
     );

+ 7 - 7
packages/starter/example/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-example",
-    "version": "0.15.0",
+    "version": "0.16.0",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -30,12 +30,12 @@
         "@ant-design/icons": "^4.6.3",
         "@mui/icons-material": "^5.1.0",
         "@mui/material": "^5.1.0",
-        "@solana/wallet-adapter-ant-design": "^0.10.0",
-        "@solana/wallet-adapter-base": "^0.8.1",
-        "@solana/wallet-adapter-material-ui": "^0.15.0",
-        "@solana/wallet-adapter-react": "^0.14.0",
-        "@solana/wallet-adapter-react-ui": "^0.7.0",
-        "@solana/wallet-adapter-wallets": "^0.13.1",
+        "@solana/wallet-adapter-ant-design": "^0.11.0",
+        "@solana/wallet-adapter-base": "^0.9.0",
+        "@solana/wallet-adapter-material-ui": "^0.16.0",
+        "@solana/wallet-adapter-react": "^0.15.0",
+        "@solana/wallet-adapter-react-ui": "^0.8.0",
+        "@solana/wallet-adapter-wallets": "^0.14.0",
         "@solana/web3.js": "^1.20.0",
         "antd": "^4.16.11",
         "bs58": "^4.0.1",

+ 3 - 3
packages/starter/example/tsconfig.json

@@ -1,4 +1,6 @@
 {
+    "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
+    "exclude": ["node_modules"],
     "compilerOptions": {
         "target": "es6",
         "lib": ["dom", "dom.iterable", "esnext"],
@@ -13,7 +15,5 @@
         "resolveJsonModule": true,
         "isolatedModules": true,
         "jsx": "preserve"
-    },
-    "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
-    "exclude": ["node_modules"]
+    }
 }

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

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-material-ui-starter",
-    "version": "0.11.0",
+    "version": "0.12.0",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -29,10 +29,10 @@
         "@emotion/styled": "^11.6.0",
         "@mui/icons-material": "^5.1.0",
         "@mui/material": "^5.1.0",
-        "@solana/wallet-adapter-base": "^0.8.1",
-        "@solana/wallet-adapter-material-ui": "^0.15.0",
-        "@solana/wallet-adapter-react": "^0.14.0",
-        "@solana/wallet-adapter-wallets": "^0.13.0",
+        "@solana/wallet-adapter-base": "^0.9.0",
+        "@solana/wallet-adapter-material-ui": "^0.16.0",
+        "@solana/wallet-adapter-react": "^0.15.0",
+        "@solana/wallet-adapter-wallets": "^0.14.0",
         "@solana/web3.js": "^1.20.0",
         "notistack": "^2.0.3",
         "react": "^17.0.2",

+ 14 - 14
packages/starter/material-ui-starter/src/Wallet.tsx

@@ -2,13 +2,13 @@ import { WalletAdapterNetwork, WalletError } from '@solana/wallet-adapter-base';
 import { WalletDialogProvider } from '@solana/wallet-adapter-material-ui';
 import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react';
 import {
-    getLedgerWallet,
-    getPhantomWallet,
-    getSlopeWallet,
-    getSolflareWallet,
-    getSolletExtensionWallet,
-    getSolletWallet,
-    getTorusWallet,
+    LedgerWalletAdapter,
+    PhantomWalletAdapter,
+    SlopeWalletAdapter,
+    SolflareWalletAdapter,
+    SolletExtensionWalletAdapter,
+    SolletWalletAdapter,
+    TorusWalletAdapter,
 } from '@solana/wallet-adapter-wallets';
 import { clusterApiUrl } from '@solana/web3.js';
 import { useSnackbar } from 'notistack';
@@ -27,13 +27,13 @@ export const Wallet: FC = () => {
     // of wallets that your users connect to will be loaded
     const wallets = useMemo(
         () => [
-            getPhantomWallet(),
-            getSlopeWallet(),
-            getSolflareWallet(),
-            getTorusWallet(),
-            getLedgerWallet(),
-            getSolletWallet({ network }),
-            getSolletExtensionWallet({ network }),
+            new PhantomWalletAdapter(),
+            new SlopeWalletAdapter(),
+            new SolflareWalletAdapter(),
+            new TorusWalletAdapter(),
+            new LedgerWalletAdapter(),
+            new SolletWalletAdapter({ network }),
+            new SolletExtensionWalletAdapter({ network }),
         ],
         [network]
     );

+ 2 - 2
packages/starter/material-ui-starter/tsconfig.json

@@ -1,4 +1,5 @@
 {
+    "include": ["src"],
     "compilerOptions": {
         "target": "es6",
         "lib": ["dom", "dom.iterable", "esnext"],
@@ -15,6 +16,5 @@
         "isolatedModules": true,
         "noEmit": true,
         "jsx": "react-jsx"
-    },
-    "include": ["src"]
+    }
 }

+ 14 - 14
packages/starter/nextjs-starter/components/WalletConnectionProvider.tsx

@@ -1,13 +1,13 @@
 import { WalletAdapterNetwork } from '@solana/wallet-adapter-base';
 import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react';
 import {
-    getLedgerWallet,
-    getPhantomWallet,
-    getSlopeWallet,
-    getSolflareWallet,
-    getSolletExtensionWallet,
-    getSolletWallet,
-    getTorusWallet,
+    LedgerWalletAdapter,
+    PhantomWalletAdapter,
+    SlopeWalletAdapter,
+    SolflareWalletAdapter,
+    SolletExtensionWalletAdapter,
+    SolletWalletAdapter,
+    TorusWalletAdapter,
 } from '@solana/wallet-adapter-wallets';
 import { clusterApiUrl } from '@solana/web3.js';
 import { FC, ReactNode, useMemo } from 'react';
@@ -24,13 +24,13 @@ export const WalletConnectionProvider: FC<{ children: ReactNode }> = ({ children
     // of wallets that your users connect to will be loaded
     const wallets = useMemo(
         () => [
-            getPhantomWallet(),
-            getSlopeWallet(),
-            getSolflareWallet(),
-            getTorusWallet(),
-            getLedgerWallet(),
-            getSolletWallet({ network }),
-            getSolletExtensionWallet({ network }),
+            new PhantomWalletAdapter(),
+            new SlopeWalletAdapter(),
+            new SolflareWalletAdapter(),
+            new TorusWalletAdapter(),
+            new LedgerWalletAdapter(),
+            new SolletWalletAdapter({ network }),
+            new SolletExtensionWalletAdapter({ network }),
         ],
         [network]
     );

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

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-nextjs-starter",
-    "version": "0.5.1",
+    "version": "0.6.0",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -27,10 +27,10 @@
         "lint": "next lint"
     },
     "dependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
-        "@solana/wallet-adapter-react": "^0.14.0",
-        "@solana/wallet-adapter-react-ui": "^0.7.0",
-        "@solana/wallet-adapter-wallets": "^0.13.0",
+        "@solana/wallet-adapter-base": "^0.9.0",
+        "@solana/wallet-adapter-react": "^0.15.0",
+        "@solana/wallet-adapter-react-ui": "^0.8.0",
+        "@solana/wallet-adapter-wallets": "^0.14.0",
         "@solana/web3.js": "^1.20.0",
         "next": "^11.1.2",
         "react": "^17.0.2",

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

@@ -1,4 +1,6 @@
 {
+    "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
+    "exclude": ["node_modules"],
     "compilerOptions": {
         "target": "es6",
         "lib": ["dom", "dom.iterable", "esnext"],
@@ -13,7 +15,5 @@
         "resolveJsonModule": true,
         "isolatedModules": true,
         "jsx": "preserve"
-    },
-    "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
-    "exclude": ["node_modules"]
+    }
 }

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

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-react-ui-starter",
-    "version": "0.6.0",
+    "version": "0.7.0",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -25,10 +25,10 @@
         "analyze": "source-map-explorer 'build/static/js/*.js'"
     },
     "dependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
-        "@solana/wallet-adapter-react": "^0.14.0",
-        "@solana/wallet-adapter-react-ui": "^0.7.0",
-        "@solana/wallet-adapter-wallets": "^0.13.0",
+        "@solana/wallet-adapter-base": "^0.9.0",
+        "@solana/wallet-adapter-react": "^0.15.0",
+        "@solana/wallet-adapter-react-ui": "^0.8.0",
+        "@solana/wallet-adapter-wallets": "^0.14.0",
         "@solana/web3.js": "^1.20.0",
         "react": "^17.0.2",
         "react-dom": "^17.0.2",

+ 14 - 14
packages/starter/react-ui-starter/src/Wallet.tsx

@@ -2,13 +2,13 @@ import { WalletAdapterNetwork, WalletError } from '@solana/wallet-adapter-base';
 import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react';
 import { WalletModalProvider } from '@solana/wallet-adapter-react-ui';
 import {
-    getLedgerWallet,
-    getPhantomWallet,
-    getSlopeWallet,
-    getSolflareWallet,
-    getSolletExtensionWallet,
-    getSolletWallet,
-    getTorusWallet,
+    LedgerWalletAdapter,
+    PhantomWalletAdapter,
+    SlopeWalletAdapter,
+    SolflareWalletAdapter,
+    SolletExtensionWalletAdapter,
+    SolletWalletAdapter,
+    TorusWalletAdapter,
 } from '@solana/wallet-adapter-wallets';
 import { clusterApiUrl } from '@solana/web3.js';
 import React, { FC, useCallback, useMemo } from 'react';
@@ -28,13 +28,13 @@ export const Wallet: FC = () => {
     // of wallets that your users connect to will be loaded
     const wallets = useMemo(
         () => [
-            getPhantomWallet(),
-            getSlopeWallet(),
-            getSolflareWallet(),
-            getTorusWallet(),
-            getLedgerWallet(),
-            getSolletWallet({ network }),
-            getSolletExtensionWallet({ network }),
+            new PhantomWalletAdapter(),
+            new SlopeWalletAdapter(),
+            new SolflareWalletAdapter(),
+            new TorusWalletAdapter(),
+            new LedgerWalletAdapter(),
+            new SolletWalletAdapter({ network }),
+            new SolletExtensionWalletAdapter({ network }),
         ],
         [network]
     );

+ 2 - 2
packages/starter/react-ui-starter/tsconfig.json

@@ -1,4 +1,5 @@
 {
+    "include": ["src"],
     "compilerOptions": {
         "target": "es6",
         "lib": ["dom", "dom.iterable", "esnext"],
@@ -15,6 +16,5 @@
         "isolatedModules": true,
         "noEmit": true,
         "jsx": "react-jsx"
-    },
-    "include": ["src"]
+    }
 }

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

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-ant-design",
-    "version": "0.10.0",
+    "version": "0.11.0",
     "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.8.1",
-        "@solana/wallet-adapter-react": "^0.14.0",
+        "@solana/wallet-adapter-base": "^0.9.0",
+        "@solana/wallet-adapter-react": "^0.15.0",
         "@solana/web3.js": "^1.20.0",
         "antd": "^4.16.11",
         "react": "^17.0.2",
@@ -31,8 +31,8 @@
     },
     "devDependencies": {
         "@ant-design/icons": "^4.6.3",
-        "@solana/wallet-adapter-base": "^0.8.1",
-        "@solana/wallet-adapter-react": "^0.14.0",
+        "@solana/wallet-adapter-base": "^0.9.0",
+        "@solana/wallet-adapter-react": "^0.15.0",
         "@solana/web3.js": "^1.20.0",
         "@types/react": "^17.0.24",
         "antd": "^4.16.11",

+ 11 - 2
packages/ui/ant-design/src/WalletIcon.tsx

@@ -1,4 +1,4 @@
-import { Wallet } from '@solana/wallet-adapter-base';
+import { Wallet } from '@solana/wallet-adapter-react';
 import React, { DetailedHTMLProps, FC, ImgHTMLAttributes } from 'react';
 
 export interface WalletIconProps extends DetailedHTMLProps<ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement> {
@@ -6,5 +6,14 @@ export interface WalletIconProps extends DetailedHTMLProps<ImgHTMLAttributes<HTM
 }
 
 export const WalletIcon: FC<WalletIconProps> = ({ wallet, ...props }) => {
-    return wallet && <img src={wallet.icon} alt={`${wallet.name} icon`} className="wallet-adapter-icon" {...props} />;
+    return (
+        wallet && (
+            <img
+                src={wallet.adapter.icon}
+                alt={`${wallet.adapter.name} icon`}
+                className="wallet-adapter-icon"
+                {...props}
+            />
+        )
+    );
 };

+ 2 - 2
packages/ui/ant-design/src/WalletMenuItem.tsx

@@ -1,4 +1,4 @@
-import { Wallet } from '@solana/wallet-adapter-base';
+import { Wallet } from '@solana/wallet-adapter-react';
 import { Button, Menu, MenuItemProps } from 'antd';
 import React, { FC, MouseEventHandler } from 'react';
 import { WalletIcon } from './WalletIcon';
@@ -19,7 +19,7 @@ export const WalletMenuItem: FC<WalletMenuItemProps> = ({ onClick, wallet, ...pr
                 htmlType="button"
                 block
             >
-                {wallet.name}
+                {wallet.adapter.name}
             </Button>
         </Menu.Item>
     );

+ 4 - 4
packages/ui/ant-design/src/WalletModal.tsx

@@ -56,8 +56,8 @@ export const WalletModal: FC<WalletModalProps> = ({
             <Menu className="wallet-adapter-modal-menu" inlineIndent={0} mode="inline" onOpenChange={onOpenChange}>
                 {featured.map((wallet) => (
                     <WalletMenuItem
-                        key={wallet.name}
-                        onClick={(event) => handleWalletClick(event, wallet.name)}
+                        key={wallet.adapter.name}
+                        onClick={(event) => handleWalletClick(event, wallet.adapter.name)}
                         wallet={wallet}
                     />
                 ))}
@@ -65,8 +65,8 @@ export const WalletModal: FC<WalletModalProps> = ({
                     <Menu.SubMenu key="wallet-adapter-modal-submenu" title={`${expanded ? 'Less' : 'More'} options`}>
                         {more.map((wallet) => (
                             <WalletMenuItem
-                                key={wallet.name}
-                                onClick={(event) => handleWalletClick(event, wallet.name)}
+                                key={wallet.adapter.name}
+                                onClick={(event) => handleWalletClick(event, wallet.adapter.name)}
                                 wallet={wallet}
                             />
                         ))}

+ 1 - 1
packages/ui/ant-design/src/WalletMultiButton.tsx

@@ -57,7 +57,7 @@ export const WalletMultiButton: FC<ButtonProps> = ({
                             block
                             {...props}
                         >
-                            {wallet.name}
+                            {wallet.adapter.name}
                         </Button>
                     </Menu.Item>
                     <Menu.Item

+ 2 - 2
packages/ui/ant-design/tsconfig.json

@@ -1,8 +1,8 @@
 {
     "extends": "../../../tsconfig.json",
+    "include": ["src"],
     "compilerOptions": {
         "noEmit": false,
         "outDir": "lib"
-    },
-    "include": ["src"]
+    }
 }

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

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-material-ui",
-    "version": "0.15.0",
+    "version": "0.16.0",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -22,8 +22,8 @@
     "peerDependencies": {
         "@mui/icons-material": "^5.1.0",
         "@mui/material": "^5.1.0",
-        "@solana/wallet-adapter-base": "^0.8.1",
-        "@solana/wallet-adapter-react": "^0.14.0",
+        "@solana/wallet-adapter-base": "^0.9.0",
+        "@solana/wallet-adapter-react": "^0.15.0",
         "@solana/web3.js": "^1.20.0",
         "react": "^17.0.2",
         "react-dom": "^17.0.2"
@@ -31,8 +31,8 @@
     "devDependencies": {
         "@mui/icons-material": "^5.1.0",
         "@mui/material": "^5.1.0",
-        "@solana/wallet-adapter-base": "^0.8.1",
-        "@solana/wallet-adapter-react": "^0.14.0",
+        "@solana/wallet-adapter-base": "^0.9.0",
+        "@solana/wallet-adapter-react": "^0.15.0",
         "@solana/web3.js": "^1.20.0",
         "@types/react": "^17.0.24",
         "react": "^17.0.2",

+ 9 - 9
packages/ui/material-ui/src/WalletDialog.tsx

@@ -80,11 +80,11 @@ export interface WalletDialogProps extends Omit<DialogProps, 'title' | 'open'> {
 }
 
 export const WalletDialog: FC<WalletDialogProps> = ({
-                                                        title = 'Select your wallet',
-                                                        featuredWallets = 3,
-                                                        onClose,
-                                                        ...props
-                                                    }) => {
+    title = 'Select your wallet',
+    featuredWallets = 3,
+    onClose,
+    ...props
+}) => {
     const { wallets, select } = useWallet();
     const { open, setOpen } = useWalletDialog();
     const [expanded, setExpanded] = useState(false);
@@ -124,8 +124,8 @@ export const WalletDialog: FC<WalletDialogProps> = ({
                 <List>
                     {featured.map((wallet) => (
                         <WalletListItem
-                            key={wallet.name}
-                            onClick={(event) => handleWalletClick(event, wallet.name)}
+                            key={wallet.adapter.name}
+                            onClick={(event) => handleWalletClick(event, wallet.adapter.name)}
                             wallet={wallet}
                         />
                     ))}
@@ -135,8 +135,8 @@ export const WalletDialog: FC<WalletDialogProps> = ({
                                 <List>
                                     {more.map((wallet) => (
                                         <WalletListItem
-                                            key={wallet.name}
-                                            onClick={(event) => handleWalletClick(event, wallet.name)}
+                                            key={wallet.adapter.name}
+                                            onClick={(event) => handleWalletClick(event, wallet.adapter.name)}
                                             wallet={wallet}
                                         />
                                     ))}

+ 2 - 2
packages/ui/material-ui/src/WalletIcon.tsx

@@ -1,6 +1,6 @@
 import { Theme } from '@mui/material';
 import { styled } from '@mui/material/styles';
-import { Wallet } from '@solana/wallet-adapter-base';
+import { Wallet } from '@solana/wallet-adapter-react';
 import React, { DetailedHTMLProps, FC, ImgHTMLAttributes } from 'react';
 
 const Img = styled('img')(({ theme }: { theme: Theme }) => ({
@@ -13,5 +13,5 @@ export interface WalletIconProps extends DetailedHTMLProps<ImgHTMLAttributes<HTM
 }
 
 export const WalletIcon: FC<WalletIconProps> = ({ wallet, ...props }) => {
-    return wallet && <Img src={wallet.icon} alt={`${wallet.name} icon`} {...props} />;
+    return wallet && <Img src={wallet.adapter.icon} alt={`${wallet.adapter.name} icon`} {...props} />;
 };

+ 2 - 2
packages/ui/material-ui/src/WalletListItem.tsx

@@ -1,5 +1,5 @@
 import { Button, ListItem, ListItemProps } from '@mui/material';
-import { Wallet } from '@solana/wallet-adapter-base';
+import { Wallet } from '@solana/wallet-adapter-react';
 import React, { FC, MouseEventHandler } from 'react';
 import { WalletIcon } from './WalletIcon';
 
@@ -12,7 +12,7 @@ export const WalletListItem: FC<WalletListItemProps> = ({ onClick, wallet, ...pr
     return (
         <ListItem {...props}>
             <Button onClick={onClick} endIcon={<WalletIcon wallet={wallet} />}>
-                {wallet.name}
+                {wallet.adapter.name}
             </Button>
         </ListItem>
     );

+ 1 - 1
packages/ui/material-ui/src/WalletMultiButton.tsx

@@ -112,7 +112,7 @@ export const WalletMultiButton: FC<ButtonProps> = ({
                         fullWidth
                         {...props}
                     >
-                        {wallet.name}
+                        {wallet.adapter.name}
                     </Button>
                 </WalletMenuItem>
                 <Collapse in={!!anchor}>

+ 2 - 2
packages/ui/material-ui/tsconfig.json

@@ -1,8 +1,8 @@
 {
     "extends": "../../../tsconfig.json",
+    "include": ["src"],
     "compilerOptions": {
         "noEmit": false,
         "outDir": "lib"
-    },
-    "include": ["src"]
+    }
 }

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

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-react-ui",
-    "version": "0.7.0",
+    "version": "0.8.0",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -21,15 +21,15 @@
         "build": "yarn clean && tsc"
     },
     "peerDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
-        "@solana/wallet-adapter-react": "^0.14.0",
+        "@solana/wallet-adapter-base": "^0.9.0",
+        "@solana/wallet-adapter-react": "^0.15.0",
         "@solana/web3.js": "^1.20.0",
         "react": "^17.0.2",
         "react-dom": "^17.0.2"
     },
     "devDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
-        "@solana/wallet-adapter-react": "^0.14.0",
+        "@solana/wallet-adapter-base": "^0.9.0",
+        "@solana/wallet-adapter-react": "^0.15.0",
         "@solana/web3.js": "^1.20.0",
         "@types/react": "^17.0.24",
         "react": "^17.0.2",

+ 2 - 2
packages/ui/react-ui/src/WalletIcon.tsx

@@ -1,4 +1,4 @@
-import { Wallet } from '@solana/wallet-adapter-base';
+import { Wallet } from '@solana/wallet-adapter-react';
 import React, { DetailedHTMLProps, FC, ImgHTMLAttributes } from 'react';
 
 export interface WalletIconProps extends DetailedHTMLProps<ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement> {
@@ -6,5 +6,5 @@ export interface WalletIconProps extends DetailedHTMLProps<ImgHTMLAttributes<HTM
 }
 
 export const WalletIcon: FC<WalletIconProps> = ({ wallet, ...props }) => {
-    return wallet && <img src={wallet.icon} alt={`${wallet.name} icon`} {...props} />;
+    return wallet && <img src={wallet.adapter.icon} alt={`${wallet.adapter.name} icon`} {...props} />;
 };

+ 4 - 2
packages/ui/react-ui/src/WalletListItem.tsx

@@ -1,4 +1,5 @@
-import { Wallet } from '@solana/wallet-adapter-base';
+import { WalletReadyState } from '@solana/wallet-adapter-base';
+import { Wallet } from '@solana/wallet-adapter-react';
 import React, { FC, MouseEventHandler } from 'react';
 import { Button } from './Button';
 import { WalletIcon } from './WalletIcon';
@@ -13,7 +14,8 @@ export const WalletListItem: FC<WalletListItemProps> = ({ handleClick, tabIndex,
     return (
         <li>
             <Button onClick={handleClick} endIcon={<WalletIcon wallet={wallet} />} tabIndex={tabIndex}>
-                {wallet.name}
+                {wallet.adapter.name}
+                {wallet.readyState === WalletReadyState.Installed ? ' (detected)' : null}
             </Button>
         </li>
     );

+ 22 - 10
packages/ui/react-ui/src/WalletModal.tsx

@@ -1,5 +1,5 @@
-import { WalletName } from '@solana/wallet-adapter-base';
-import { useWallet } from '@solana/wallet-adapter-react';
+import { WalletName, WalletReadyState } from '@solana/wallet-adapter-base';
+import { useWallet, Wallet } from '@solana/wallet-adapter-react';
 import React, { FC, MouseEvent, ReactNode, useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
 import { createPortal } from 'react-dom';
 import { Button } from './Button';
@@ -27,10 +27,22 @@ export const WalletModal: FC<WalletModalProps> = ({
     const [fadeIn, setFadeIn] = useState(false);
     const [portal, setPortal] = useState<Element | null>(null);
 
-    const [featured, more] = useMemo(
-        () => [wallets.slice(0, featuredWallets), wallets.slice(featuredWallets)],
-        [wallets, featuredWallets]
-    );
+    const [featured, more] = useMemo(() => {
+        const installedWallets: Wallet[] = [];
+        const otherWallets: Wallet[] = [];
+        wallets.forEach((wallet) => {
+            if (wallet.readyState === WalletReadyState.Installed) {
+                installedWallets.push(wallet);
+            } else {
+                otherWallets.push(wallet);
+            }
+        });
+        const remainingFeaturedSpots = Math.max(0, featuredWallets - installedWallets.length);
+        return [
+            [...installedWallets, ...otherWallets.slice(0, remainingFeaturedSpots)],
+            otherWallets.slice(remainingFeaturedSpots),
+        ];
+    }, [wallets, featuredWallets]);
 
     const hideModal = useCallback(() => {
         setFadeIn(false);
@@ -145,8 +157,8 @@ export const WalletModal: FC<WalletModalProps> = ({
                         <ul className="wallet-adapter-modal-list">
                             {featured.map((wallet) => (
                                 <WalletListItem
-                                    key={wallet.name}
-                                    handleClick={(event) => handleWalletClick(event, wallet.name)}
+                                    key={wallet.adapter.name}
+                                    handleClick={(event) => handleWalletClick(event, wallet.adapter.name)}
                                     wallet={wallet}
                                 />
                             ))}
@@ -157,8 +169,8 @@ export const WalletModal: FC<WalletModalProps> = ({
                                     <ul className="wallet-adapter-modal-list">
                                         {more.map((wallet) => (
                                             <WalletListItem
-                                                key={wallet.name}
-                                                handleClick={(event) => handleWalletClick(event, wallet.name)}
+                                                key={wallet.adapter.name}
+                                                handleClick={(event) => handleWalletClick(event, wallet.adapter.name)}
                                                 tabIndex={expanded ? 0 : -1}
                                                 wallet={wallet}
                                             />

+ 2 - 2
packages/ui/react-ui/tsconfig.json

@@ -1,8 +1,8 @@
 {
     "extends": "../../../tsconfig.json",
+    "include": ["src"],
     "compilerOptions": {
         "noEmit": false,
         "outDir": "lib"
-    },
-    "include": ["src"]
+    }
 }

+ 2 - 2
packages/ui/vue-ui/tsconfig.json

@@ -1,10 +1,10 @@
 {
     "extends": "../../../tsconfig.json",
+    "include": ["src"],
     "compilerOptions": {
         "noEmit": false,
         "outDir": "lib",
         "types": ["vue"],
         "isolatedModules": false
-    },
-    "include": ["src"]
+    }
 }

+ 3 - 3
packages/wallets/bitkeep/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-bitkeep",
-    "version": "0.2.0",
+    "version": "0.3.0",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -22,11 +22,11 @@
         "build": "yarn clean && tsc"
     },
     "peerDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     },
     "devDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     }
 }

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 9 - 0
packages/wallets/bitkeep/src/adapter.ts


+ 0 - 1
packages/wallets/bitkeep/src/index.ts

@@ -1,2 +1 @@
 export * from './adapter';
-export * from './wallet';

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 8
packages/wallets/bitkeep/src/wallet.ts


+ 2 - 2
packages/wallets/bitkeep/tsconfig.json

@@ -1,8 +1,8 @@
 {
     "extends": "../../../tsconfig.json",
+    "include": ["src"],
     "compilerOptions": {
         "noEmit": false,
         "outDir": "lib"
-    },
-    "include": ["src"]
+    }
 }

+ 3 - 3
packages/wallets/bitpie/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-bitpie",
-    "version": "0.4.0",
+    "version": "0.5.0",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -22,11 +22,11 @@
         "build": "yarn clean && tsc"
     },
     "peerDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     },
     "devDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     }
 }

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 8 - 0
packages/wallets/bitpie/src/adapter.ts


+ 0 - 1
packages/wallets/bitpie/src/index.ts

@@ -1,2 +1 @@
 export * from './adapter';
-export * from './wallet';

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 8
packages/wallets/bitpie/src/wallet.ts


+ 2 - 2
packages/wallets/bitpie/tsconfig.json

@@ -1,8 +1,8 @@
 {
     "extends": "../../../tsconfig.json",
+    "include": ["src"],
     "compilerOptions": {
         "noEmit": false,
         "outDir": "lib"
-    },
-    "include": ["src"]
+    }
 }

+ 3 - 3
packages/wallets/blocto/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-blocto",
-    "version": "0.4.1",
+    "version": "0.5.0",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -22,14 +22,14 @@
         "build": "yarn clean && tsc"
     },
     "peerDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     },
     "dependencies": {
         "@blocto/sdk": "^0.2.21"
     },
     "devDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     }
 }

+ 17 - 5
packages/wallets/blocto/src/adapter.ts

@@ -1,5 +1,6 @@
 import type { SolanaProviderInterface } from '@blocto/sdk';
 import {
+    Adapter,
     BaseWalletAdapter,
     SendTransactionOptions,
     WalletAccountError,
@@ -8,9 +9,11 @@ import {
     WalletConnectionError,
     WalletDisconnectionError,
     WalletLoadError,
+    WalletName,
     WalletNotConnectedError,
     WalletNotReadyError,
     WalletPublicKeyError,
+    WalletReadyState,
     WalletSendTransactionError,
 } from '@solana/wallet-adapter-base';
 import { Connection, PublicKey, Transaction, TransactionSignature } from '@solana/web3.js';
@@ -19,11 +22,20 @@ export interface BloctoWalletAdapterConfig {
     network?: WalletAdapterNetwork;
 }
 
+export const BloctoWalletName = 'Blocto' as WalletName;
+
 export class BloctoWalletAdapter extends BaseWalletAdapter {
+    name = BloctoWalletName;
+    url = 'https://blocto.app';
+    icon =
+        'data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGwtcnVsZT0iZXZlbm9kZCI+PHBhdGggZD0ibTE5LjQ4MzggMTUuMjQ5Yy4yNzY5IDAgLjUwNDguMjA5OS41MzI1LjQ3ODhsLjAwMjIuMDQyOS0uMDA0My4xMTQyYy0uMzM1IDMuOTgzMy0zLjc5MDQgNy4xMTUxLTguMDAzNyA3LjExNTEtNC4xNzA2IDAtNy41OTg2My0zLjA2ODctNy45OTI2OS02Ljk5NDZsLS4wMTYzOC0uMTgxMS0uMDAxMDYtLjA1MzIuMDAxNzgtLjAzOThjLjAyNTk4LS4yNzA2LjI1NDg3LS40ODIzLjUzMjg5LS40ODIzeiIgZmlsbD0iI2FmZDhmNyIvPjxwYXRoIGQ9Im00LjMwMDA5IDFjMy43ODc1NSAwIDYuODI1ODEgMi45MDkxMSA2LjgyNTgxIDYuNTAyNzd2Ni4zNTM0M2MtLjAwMDQuMjkxNy0uMjM5Mi41Mjg0LS41MzQuNTI4OGwtNi4wNTc1OC4wMDMyYy0uMjk1MTEuMDAwNy0uNTM0MzItLjIzNjEtLjUzNDMyLS41Mjc4bC4wMDAzNi0xMi41NjM3NWMwLS4xNTE0OS4xMTQyNi0uMjc2MjIuMjYxOTktLjI5NDE4eiIgZmlsbD0iIzE4MmE3MSIvPjxwYXRoIGQ9Im0xOS42OTIxIDEyLjIzODMuMDM4OC4xMjgzLS4wMjg4LS4wODQ2Yy4xNjE2LjQ1MzQuMjY2Ni43NzY5LjMxNTMgMS4zNDEzLjAzMzUuMzg3OS0uMjU3LjcyODktLjY0ODUuNzYybC0uMDMwMy4wMDIyLTMuMDgwOS4wMDA3Yy0yLjEwNjMgMC0zLjgyMDQtMS40NzQxLTMuODc1Mi0zLjU0MjNsLS4wMDE0LS4xMDIxdi0zLjQ2NThjMC0uMjAxNTMuMTY5NC0uMzY5NTkuMzc0MS0uMzYwMDcgMy4zMDAzLjE1NDY2IDUuOTk3OCAyLjM0MTUxIDYuOTM2OSA1LjMyMDM3eiIgZmlsbD0iIzM0ODVjNCIvPjwvZz48L3N2Zz4=';
+
     private _connecting: boolean;
     private _wallet: SolanaProviderInterface | null;
     private _publicKey: PublicKey | null;
     private _network: string;
+    private _readyState: WalletReadyState =
+        typeof window !== 'undefined' ? WalletReadyState.Unsupported : WalletReadyState.Loadable;
 
     constructor(config: BloctoWalletAdapterConfig = {}) {
         super();
@@ -41,16 +53,16 @@ export class BloctoWalletAdapter extends BaseWalletAdapter {
         return this._connecting;
     }
 
-    async ready(): Promise<boolean> {
-        return typeof window !== 'undefined';
+    get readyState(): WalletReadyState {
+        return this._readyState;
     }
 
     async connect(): Promise<void> {
         try {
             if (this.connected || this.connecting) return;
-            this._connecting = true;
+            if (this._readyState !== WalletReadyState.Loadable) throw new WalletNotReadyError();
 
-            if (!(await this.ready())) throw new WalletNotReadyError();
+            this._connecting = true;
 
             let BloctoSDK: typeof import('@blocto/sdk');
             try {
@@ -89,7 +101,7 @@ export class BloctoWalletAdapter extends BaseWalletAdapter {
             this._wallet = wallet;
             this._publicKey = publicKey;
 
-            this.emit('connect');
+            this.emit('connect', publicKey);
         } catch (error: any) {
             this.emit('error', error);
             throw error;

+ 0 - 1
packages/wallets/blocto/src/index.ts

@@ -1,2 +1 @@
 export * from './adapter';
-export * from './wallet';

+ 0 - 11
packages/wallets/blocto/src/wallet.ts

@@ -1,11 +0,0 @@
-import { Wallet, WalletName } from '@solana/wallet-adapter-base';
-import { BloctoWalletAdapter, BloctoWalletAdapterConfig } from './adapter';
-
-export const BloctoWalletName = 'Blocto' as WalletName;
-
-export const getBloctoWallet = (config: BloctoWalletAdapterConfig = {}): Wallet => ({
-    name: BloctoWalletName,
-    url: 'https://blocto.app',
-    icon: 'data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGwtcnVsZT0iZXZlbm9kZCI+PHBhdGggZD0ibTE5LjQ4MzggMTUuMjQ5Yy4yNzY5IDAgLjUwNDguMjA5OS41MzI1LjQ3ODhsLjAwMjIuMDQyOS0uMDA0My4xMTQyYy0uMzM1IDMuOTgzMy0zLjc5MDQgNy4xMTUxLTguMDAzNyA3LjExNTEtNC4xNzA2IDAtNy41OTg2My0zLjA2ODctNy45OTI2OS02Ljk5NDZsLS4wMTYzOC0uMTgxMS0uMDAxMDYtLjA1MzIuMDAxNzgtLjAzOThjLjAyNTk4LS4yNzA2LjI1NDg3LS40ODIzLjUzMjg5LS40ODIzeiIgZmlsbD0iI2FmZDhmNyIvPjxwYXRoIGQ9Im00LjMwMDA5IDFjMy43ODc1NSAwIDYuODI1ODEgMi45MDkxMSA2LjgyNTgxIDYuNTAyNzd2Ni4zNTM0M2MtLjAwMDQuMjkxNy0uMjM5Mi41Mjg0LS41MzQuNTI4OGwtNi4wNTc1OC4wMDMyYy0uMjk1MTEuMDAwNy0uNTM0MzItLjIzNjEtLjUzNDMyLS41Mjc4bC4wMDAzNi0xMi41NjM3NWMwLS4xNTE0OS4xMTQyNi0uMjc2MjIuMjYxOTktLjI5NDE4eiIgZmlsbD0iIzE4MmE3MSIvPjxwYXRoIGQ9Im0xOS42OTIxIDEyLjIzODMuMDM4OC4xMjgzLS4wMjg4LS4wODQ2Yy4xNjE2LjQ1MzQuMjY2Ni43NzY5LjMxNTMgMS4zNDEzLjAzMzUuMzg3OS0uMjU3LjcyODktLjY0ODUuNzYybC0uMDMwMy4wMDIyLTMuMDgwOS4wMDA3Yy0yLjEwNjMgMC0zLjgyMDQtMS40NzQxLTMuODc1Mi0zLjU0MjNsLS4wMDE0LS4xMDIxdi0zLjQ2NThjMC0uMjAxNTMuMTY5NC0uMzY5NTkuMzc0MS0uMzYwMDcgMy4zMDAzLjE1NDY2IDUuOTk3OCAyLjM0MTUxIDYuOTM2OSA1LjMyMDM3eiIgZmlsbD0iIzM0ODVjNCIvPjwvZz48L3N2Zz4=',
-    adapter: new BloctoWalletAdapter(config),
-});

+ 2 - 2
packages/wallets/blocto/tsconfig.json

@@ -1,8 +1,8 @@
 {
     "extends": "../../../tsconfig.json",
+    "include": ["src"],
     "compilerOptions": {
         "noEmit": false,
         "outDir": "lib"
-    },
-    "include": ["src"]
+    }
 }

+ 3 - 3
packages/wallets/clover/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-clover",
-    "version": "0.3.0",
+    "version": "0.4.0",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -22,11 +22,11 @@
         "build": "yarn clean && tsc"
     },
     "peerDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     },
     "devDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     }
 }

+ 30 - 16
packages/wallets/clover/src/adapter.ts

@@ -1,9 +1,13 @@
 import {
+    Adapter,
     BaseSignerWalletAdapter,
+    scopePollingDetectionStrategy,
     WalletAccountError,
+    WalletName,
     WalletNotConnectedError,
     WalletNotReadyError,
     WalletPublicKeyError,
+    WalletReadyState,
     WalletSignTransactionError,
 } from '@solana/wallet-adapter-base';
 import { PublicKey, Transaction } from '@solana/web3.js';
@@ -23,16 +27,37 @@ declare const window: CloverWalletWindow;
 
 export interface CloverWalletAdapterConfig {}
 
+export const CloverWalletName = 'Clover' as WalletName;
+
 export class CloverWalletAdapter extends BaseSignerWalletAdapter {
+    name = CloverWalletName;
+    url = 'https://clover.finance';
+    icon =
+        'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzQiIGhlaWdodD0iNzQiIHZpZXdCb3g9IjAgMCA3NCA3NCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTczLjg5NDcgMTguNTc4OEM3My44OTQ3IDI4Ljc4MTUgNjUuNjIzOCAzNy4wNTI1IDU1LjQyMTEgMzcuMDUyNUM0NS4yNTczIDM3LjA1MjUgMzcuMDEwNiAyOC44NDQ2IDM2Ljk0NzcgMTguNjk1NkMzNi44ODUzIDI4LjgxMyAyOC42ODk5IDM3LjAwMTUgMTguNTY5OSAzNy4wNTI3QzI4LjcyODQgMzcuMTA0NSAzNi45NDc0IDQ1LjM1NTUgMzYuOTQ3NCA1NS41MjYyQzM2Ljk0NzQgNjUuNzI4OSAyOC42NzY0IDczLjk5OTggMTguNDczNyA3My45OTk4QzguMjcwOTUgNzMuOTk5OCAwIDY1LjcyODkgMCA1NS41MjYyQzAgNDUuMzU1MyA4LjIxOTM5IDM3LjEwNDEgMTguMzc4MiAzNy4wNTI3QzguMjE5NzIgMzcuMDAwOSAwLjAwMDcxOTU3MiAyOC43NDk5IDAuMDAwNzE5NTcyIDE4LjU3OTNDMC4wMDA3MTk1NzIgOC4zNzY1NCA4LjI3MTY3IDAuMTA1NTkxIDE4LjQ3NDQgMC4xMDU1OTFDMjguNjM4MiAwLjEwNTU5MSAzNi44ODQ5IDguMzEzNDggMzYuOTQ3NyAxOC40NjI1QzM3LjAxMDMgOC4zMTMyNiA0NS4yNTcxIDAuMTA1MTAzIDU1LjQyMTEgMC4xMDUxMDNDNjUuNjIzOCAwLjEwNTEwMyA3My44OTQ3IDguMzc2MDUgNzMuODk0NyAxOC41Nzg4Wk01NS40MjExIDM3LjA1MjVDNDUuMjE4MyAzNy4wNTI1IDM2Ljk0NzQgNDUuMzIzNCAzNi45NDc0IDU1LjUyNjJDMzYuOTQ3NCA2NS43Mjg5IDQ1LjIxODMgNzMuOTk5OCA1NS40MjExIDczLjk5OThDNjUuNjIzOCA3My45OTk4IDczLjg5NDcgNjUuNzI4OSA3My44OTQ3IDU1LjUyNjJDNzMuODk0NyA0NS4zMjM0IDY1LjYyMzggMzcuMDUyNSA1NS40MjExIDM3LjA1MjVaIiBmaWxsPSIjMjdBNTc3Ii8+PC9zdmc+Cg==';
+
     private _connecting: boolean;
     private _wallet: CloverWallet | null;
     private _publicKey: PublicKey | null;
+    private _readyState: WalletReadyState =
+        typeof window === 'undefined' || typeof document === 'undefined'
+            ? WalletReadyState.Unsupported
+            : WalletReadyState.NotDetected;
 
     constructor(config: CloverWalletAdapterConfig = {}) {
         super();
         this._connecting = false;
         this._wallet = null;
         this._publicKey = null;
+        if (this._readyState !== WalletReadyState.Unsupported) {
+            scopePollingDetectionStrategy(() => {
+                if (window.clover_solana?.isCloverWallet) {
+                    this._readyState = WalletReadyState.Installed;
+                    this.emit('readyStateChange', this._readyState);
+                    return true;
+                }
+                return false;
+            });
+        }
     }
 
     get publicKey(): PublicKey | null {
@@ -43,27 +68,16 @@ export class CloverWalletAdapter extends BaseSignerWalletAdapter {
         return this._connecting;
     }
 
-    async ready(): Promise<boolean> {
-        if (typeof window === 'undefined' || typeof document === 'undefined') return false;
-
-        if (document.readyState === 'complete') return !!window.clover_solana?.isCloverWallet;
-
-        return new Promise((resolve) => {
-            function listener() {
-                window.removeEventListener('load', listener);
-                resolve(!!window.clover_solana?.isCloverWallet);
-            }
-
-            window.addEventListener('load', listener);
-        });
+    get readyState(): WalletReadyState {
+        return this._readyState;
     }
 
     async connect(): Promise<void> {
         try {
             if (this.connected || this.connecting) return;
-            this._connecting = true;
+            if (this._readyState !== WalletReadyState.Installed) throw new WalletNotReadyError();
 
-            if (!(await this.ready())) throw new WalletNotReadyError();
+            this._connecting = true;
 
             const wallet = window!.clover_solana!;
 
@@ -84,7 +98,7 @@ export class CloverWalletAdapter extends BaseSignerWalletAdapter {
             this._wallet = wallet;
             this._publicKey = publicKey;
 
-            this.emit('connect');
+            this.emit('connect', publicKey);
         } catch (error: any) {
             this.emit('error', error);
             throw error;

+ 0 - 1
packages/wallets/clover/src/index.ts

@@ -1,2 +1 @@
 export * from './adapter';
-export * from './wallet';

+ 0 - 11
packages/wallets/clover/src/wallet.ts

@@ -1,11 +0,0 @@
-import { Wallet, WalletName } from '@solana/wallet-adapter-base';
-import { CloverWalletAdapter, CloverWalletAdapterConfig } from './adapter';
-
-export const CloverWalletName = 'Clover' as WalletName;
-
-export const getCloverWallet = (config: CloverWalletAdapterConfig = {}): Wallet => ({
-    name: CloverWalletName,
-    url: 'https://clover.finance',
-    icon: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzQiIGhlaWdodD0iNzQiIHZpZXdCb3g9IjAgMCA3NCA3NCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTczLjg5NDcgMTguNTc4OEM3My44OTQ3IDI4Ljc4MTUgNjUuNjIzOCAzNy4wNTI1IDU1LjQyMTEgMzcuMDUyNUM0NS4yNTczIDM3LjA1MjUgMzcuMDEwNiAyOC44NDQ2IDM2Ljk0NzcgMTguNjk1NkMzNi44ODUzIDI4LjgxMyAyOC42ODk5IDM3LjAwMTUgMTguNTY5OSAzNy4wNTI3QzI4LjcyODQgMzcuMTA0NSAzNi45NDc0IDQ1LjM1NTUgMzYuOTQ3NCA1NS41MjYyQzM2Ljk0NzQgNjUuNzI4OSAyOC42NzY0IDczLjk5OTggMTguNDczNyA3My45OTk4QzguMjcwOTUgNzMuOTk5OCAwIDY1LjcyODkgMCA1NS41MjYyQzAgNDUuMzU1MyA4LjIxOTM5IDM3LjEwNDEgMTguMzc4MiAzNy4wNTI3QzguMjE5NzIgMzcuMDAwOSAwLjAwMDcxOTU3MiAyOC43NDk5IDAuMDAwNzE5NTcyIDE4LjU3OTNDMC4wMDA3MTk1NzIgOC4zNzY1NCA4LjI3MTY3IDAuMTA1NTkxIDE4LjQ3NDQgMC4xMDU1OTFDMjguNjM4MiAwLjEwNTU5MSAzNi44ODQ5IDguMzEzNDggMzYuOTQ3NyAxOC40NjI1QzM3LjAxMDMgOC4zMTMyNiA0NS4yNTcxIDAuMTA1MTAzIDU1LjQyMTEgMC4xMDUxMDNDNjUuNjIzOCAwLjEwNTEwMyA3My44OTQ3IDguMzc2MDUgNzMuODk0NyAxOC41Nzg4Wk01NS40MjExIDM3LjA1MjVDNDUuMjE4MyAzNy4wNTI1IDM2Ljk0NzQgNDUuMzIzNCAzNi45NDc0IDU1LjUyNjJDMzYuOTQ3NCA2NS43Mjg5IDQ1LjIxODMgNzMuOTk5OCA1NS40MjExIDczLjk5OThDNjUuNjIzOCA3My45OTk4IDczLjg5NDcgNjUuNzI4OSA3My44OTQ3IDU1LjUyNjJDNzMuODk0NyA0NS4zMjM0IDY1LjYyMzggMzcuMDUyNSA1NS40MjExIDM3LjA1MjVaIiBmaWxsPSIjMjdBNTc3Ii8+PC9zdmc+Cg==',
-    adapter: new CloverWalletAdapter(config),
-});

+ 2 - 2
packages/wallets/clover/tsconfig.json

@@ -1,8 +1,8 @@
 {
     "extends": "../../../tsconfig.json",
+    "include": ["src"],
     "compilerOptions": {
         "noEmit": false,
         "outDir": "lib"
-    },
-    "include": ["src"]
+    }
 }

+ 3 - 3
packages/wallets/coin98/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-coin98",
-    "version": "0.4.0",
+    "version": "0.5.0",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -22,7 +22,7 @@
         "build": "yarn clean && tsc"
     },
     "peerDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     },
     "dependencies": {
@@ -30,7 +30,7 @@
         "bs58": "^4.0.1"
     },
     "devDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     }
 }

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 9 - 0
packages/wallets/coin98/src/adapter.ts


+ 0 - 1
packages/wallets/coin98/src/index.ts

@@ -1,2 +1 @@
 export * from './adapter';
-export * from './wallet';

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 8
packages/wallets/coin98/src/wallet.ts


+ 2 - 2
packages/wallets/coin98/tsconfig.json

@@ -1,8 +1,8 @@
 {
     "extends": "../../../tsconfig.json",
+    "include": ["src"],
     "compilerOptions": {
         "noEmit": false,
         "outDir": "lib"
-    },
-    "include": ["src"]
+    }
 }

+ 3 - 3
packages/wallets/coinhub/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-coinhub",
-    "version": "0.2.0",
+    "version": "0.3.0",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -22,11 +22,11 @@
         "build": "yarn clean && tsc"
     },
     "peerDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     },
     "devDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     }
 }

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 9 - 0
packages/wallets/coinhub/src/adapter.ts


+ 0 - 1
packages/wallets/coinhub/src/index.ts

@@ -1,2 +1 @@
 export * from './adapter';
-export * from './wallet';

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 8
packages/wallets/coinhub/src/wallet.ts


+ 2 - 2
packages/wallets/coinhub/tsconfig.json

@@ -1,8 +1,8 @@
 {
     "extends": "../../../tsconfig.json",
+    "include": ["src"],
     "compilerOptions": {
         "noEmit": false,
         "outDir": "lib"
-    },
-    "include": ["src"]
+    }
 }

+ 3 - 3
packages/wallets/ledger/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-ledger",
-    "version": "0.8.1",
+    "version": "0.9.0",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -22,7 +22,7 @@
         "build": "yarn clean && tsc"
     },
     "peerDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     },
     "dependencies": {
@@ -31,7 +31,7 @@
         "@types/w3c-web-hid": "^1.0.2"
     },
     "devDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     }
 }

+ 17 - 5
packages/wallets/ledger/src/adapter.ts

@@ -1,13 +1,16 @@
 import type Transport from '@ledgerhq/hw-transport';
 import {
+    Adapter,
     BaseSignerWalletAdapter,
     WalletConnectionError,
     WalletDisconnectedError,
     WalletDisconnectionError,
     WalletLoadError,
+    WalletName,
     WalletNotConnectedError,
     WalletNotReadyError,
     WalletPublicKeyError,
+    WalletReadyState,
     WalletSignTransactionError,
 } from '@solana/wallet-adapter-base';
 import { PublicKey, Transaction } from '@solana/web3.js';
@@ -17,11 +20,20 @@ export interface LedgerWalletAdapterConfig {
     derivationPath?: Buffer;
 }
 
+export const LedgerWalletName = 'Ledger' as WalletName;
+
 export class LedgerWalletAdapter extends BaseSignerWalletAdapter {
+    name = LedgerWalletName;
+    url = 'https://ledger.com';
+    icon =
+        'data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMzUgMzUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0iI2ZmZiI+PHBhdGggZD0ibTIzLjU4OCAwaC0xNnYyMS41ODNoMjEuNnYtMTZhNS41ODUgNS41ODUgMCAwIDAgLTUuNi01LjU4M3oiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDUuNzM5KSIvPjxwYXRoIGQ9Im04LjM0MiAwaC0yLjc1N2E1LjU4NSA1LjU4NSAwIDAgMCAtNS41ODUgNS41ODV2Mi43NTdoOC4zNDJ6Ii8+PHBhdGggZD0ibTAgNy41OWg4LjM0MnY4LjM0MmgtOC4zNDJ6IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwIDUuNzM5KSIvPjxwYXRoIGQ9Im0xNS4xOCAyMy40NTFoMi43NTdhNS41ODUgNS41ODUgMCAwIDAgNS41ODUtNS42di0yLjY3MWgtOC4zNDJ6IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMS40NzggMTEuNDc4KSIvPjxwYXRoIGQ9Im03LjU5IDE1LjE4aDguMzQydjguMzQyaC04LjM0MnoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDUuNzM5IDExLjQ3OCkiLz48cGF0aCBkPSJtMCAxNS4xOHYyLjc1N2E1LjU4NSA1LjU4NSAwIDAgMCA1LjU4NSA1LjU4NWgyLjc1N3YtOC4zNDJ6IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwIDExLjQ3OCkiLz48L2c+PC9zdmc+';
+
     private _derivationPath: Buffer;
     private _connecting: boolean;
     private _transport: Transport | null;
     private _publicKey: PublicKey | null;
+    private _readyState: WalletReadyState =
+        typeof navigator === 'undefined' || !navigator.hid ? WalletReadyState.Unsupported : WalletReadyState.Loadable;
 
     constructor(config: LedgerWalletAdapterConfig = {}) {
         super();
@@ -39,16 +51,16 @@ export class LedgerWalletAdapter extends BaseSignerWalletAdapter {
         return this._connecting;
     }
 
-    async ready(): Promise<boolean> {
-        return typeof navigator !== 'undefined' && !!navigator.hid;
+    get readyState(): WalletReadyState {
+        return this._readyState;
     }
 
     async connect(): Promise<void> {
         try {
             if (this.connected || this.connecting) return;
-            this._connecting = true;
+            if (this._readyState === WalletReadyState.Unsupported) throw new WalletNotReadyError();
 
-            if (!(await this.ready())) throw new WalletNotReadyError();
+            this._connecting = true;
 
             let TransportWebHID: typeof import('@ledgerhq/hw-transport-webhid');
             try {
@@ -76,7 +88,7 @@ export class LedgerWalletAdapter extends BaseSignerWalletAdapter {
             this._transport = transport;
             this._publicKey = publicKey;
 
-            this.emit('connect');
+            this.emit('connect', publicKey);
         } catch (error: any) {
             this.emit('error', error);
             throw error;

+ 0 - 1
packages/wallets/ledger/src/index.ts

@@ -1,3 +1,2 @@
 export * from './adapter';
 export { getDerivationPath } from './util';
-export * from './wallet';

+ 2 - 0
packages/wallets/ledger/src/util.ts

@@ -38,11 +38,13 @@ const MAX_PAYLOAD = 255;
 
 const LEDGER_CLA = 0xe0;
 
+/** @internal */
 export async function getPublicKey(transport: Transport, derivationPath: Buffer): Promise<PublicKey> {
     const bytes = await send(transport, INS_GET_PUBKEY, P1_NON_CONFIRM, derivationPath);
     return new PublicKey(bytes);
 }
 
+/** @internal */
 export async function signTransaction(
     transport: Transport,
     transaction: Transaction,

+ 0 - 11
packages/wallets/ledger/src/wallet.ts

@@ -1,11 +0,0 @@
-import { Wallet, WalletName } from '@solana/wallet-adapter-base';
-import { LedgerWalletAdapter, LedgerWalletAdapterConfig } from './adapter';
-
-export const LedgerWalletName = 'Ledger' as WalletName;
-
-export const getLedgerWallet = (config: LedgerWalletAdapterConfig = {}): Wallet => ({
-    name: LedgerWalletName,
-    url: 'https://ledger.com',
-    icon: 'data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMzUgMzUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0iI2ZmZiI+PHBhdGggZD0ibTIzLjU4OCAwaC0xNnYyMS41ODNoMjEuNnYtMTZhNS41ODUgNS41ODUgMCAwIDAgLTUuNi01LjU4M3oiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDUuNzM5KSIvPjxwYXRoIGQ9Im04LjM0MiAwaC0yLjc1N2E1LjU4NSA1LjU4NSAwIDAgMCAtNS41ODUgNS41ODV2Mi43NTdoOC4zNDJ6Ii8+PHBhdGggZD0ibTAgNy41OWg4LjM0MnY4LjM0MmgtOC4zNDJ6IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwIDUuNzM5KSIvPjxwYXRoIGQ9Im0xNS4xOCAyMy40NTFoMi43NTdhNS41ODUgNS41ODUgMCAwIDAgNS41ODUtNS42di0yLjY3MWgtOC4zNDJ6IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMS40NzggMTEuNDc4KSIvPjxwYXRoIGQ9Im03LjU5IDE1LjE4aDguMzQydjguMzQyaC04LjM0MnoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDUuNzM5IDExLjQ3OCkiLz48cGF0aCBkPSJtMCAxNS4xOHYyLjc1N2E1LjU4NSA1LjU4NSAwIDAgMCA1LjU4NSA1LjU4NWgyLjc1N3YtOC4zNDJ6IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwIDExLjQ3OCkiLz48L2c+PC9zdmc+',
-    adapter: new LedgerWalletAdapter(config),
-});

+ 2 - 2
packages/wallets/ledger/tsconfig.json

@@ -1,8 +1,8 @@
 {
     "extends": "../../../tsconfig.json",
+    "include": ["src"],
     "compilerOptions": {
         "noEmit": false,
         "outDir": "lib"
-    },
-    "include": ["src"]
+    }
 }

+ 3 - 3
packages/wallets/mathwallet/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-mathwallet",
-    "version": "0.8.0",
+    "version": "0.9.0",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -22,11 +22,11 @@
         "build": "yarn clean && tsc"
     },
     "peerDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     },
     "devDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     }
 }

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 9 - 0
packages/wallets/mathwallet/src/adapter.ts


+ 0 - 1
packages/wallets/mathwallet/src/index.ts

@@ -1,2 +1 @@
 export * from './adapter';
-export * from './wallet';

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 8
packages/wallets/mathwallet/src/wallet.ts


+ 2 - 2
packages/wallets/mathwallet/tsconfig.json

@@ -1,8 +1,8 @@
 {
     "extends": "../../../tsconfig.json",
+    "include": ["src"],
     "compilerOptions": {
         "noEmit": false,
         "outDir": "lib"
-    },
-    "include": ["src"]
+    }
 }

+ 3 - 3
packages/wallets/phantom/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-phantom",
-    "version": "0.8.1",
+    "version": "0.9.0",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -22,11 +22,11 @@
         "build": "yarn clean && tsc"
     },
     "peerDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     },
     "devDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     }
 }

+ 30 - 16
packages/wallets/phantom/src/adapter.ts

@@ -1,15 +1,19 @@
 import {
+    Adapter,
     BaseMessageSignerWalletAdapter,
     EventEmitter,
+    scopePollingDetectionStrategy,
     SendTransactionOptions,
     WalletAccountError,
     WalletConnectionError,
     WalletDisconnectedError,
     WalletDisconnectionError,
     WalletError,
+    WalletName,
     WalletNotConnectedError,
     WalletNotReadyError,
     WalletPublicKeyError,
+    WalletReadyState,
     WalletSignTransactionError,
     WalletWindowClosedError,
 } from '@solana/wallet-adapter-base';
@@ -44,16 +48,37 @@ declare const window: PhantomWindow;
 
 export interface PhantomWalletAdapterConfig {}
 
+export const PhantomWalletName = 'Phantom' as WalletName;
+
 export class PhantomWalletAdapter extends BaseMessageSignerWalletAdapter {
+    name = PhantomWalletName;
+    url = 'https://phantom.app';
+    icon =
+        'data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjM0IiB3aWR0aD0iMzQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iLjUiIHgyPSIuNSIgeTE9IjAiIHkyPSIxIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiM1MzRiYjEiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiM1NTFiZjkiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iYiIgeDE9Ii41IiB4Mj0iLjUiIHkxPSIwIiB5Mj0iMSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZmZmIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjZmZmIiBzdG9wLW9wYWNpdHk9Ii44MiIvPjwvbGluZWFyR3JhZGllbnQ+PGNpcmNsZSBjeD0iMTciIGN5PSIxNyIgZmlsbD0idXJsKCNhKSIgcj0iMTciLz48cGF0aCBkPSJtMjkuMTcwMiAxNy4yMDcxaC0yLjk5NjljMC02LjEwNzQtNC45NjgzLTExLjA1ODE3LTExLjA5NzUtMTEuMDU4MTctNi4wNTMyNSAwLTEwLjk3NDYzIDQuODI5NTctMTEuMDk1MDggMTAuODMyMzctLjEyNDYxIDYuMjA1IDUuNzE3NTIgMTEuNTkzMiAxMS45NDUzOCAxMS41OTMyaC43ODM0YzUuNDkwNiAwIDEyLjg0OTctNC4yODI5IDEzLjk5OTUtOS41MDEzLjIxMjMtLjk2MTktLjU1MDItMS44NjYxLTEuNTM4OC0xLjg2NjF6bS0xOC41NDc5LjI3MjFjMCAuODE2Ny0uNjcwMzggMS40ODQ3LTEuNDkwMDEgMS40ODQ3LS44MTk2NCAwLTEuNDg5OTgtLjY2ODMtMS40ODk5OC0xLjQ4NDd2LTIuNDAxOWMwLS44MTY3LjY3MDM0LTEuNDg0NyAxLjQ4OTk4LTEuNDg0Ny44MTk2MyAwIDEuNDkwMDEuNjY4IDEuNDkwMDEgMS40ODQ3em01LjE3MzggMGMwIC44MTY3LS42NzAzIDEuNDg0Ny0xLjQ4OTkgMS40ODQ3LS44MTk3IDAtMS40OS0uNjY4My0xLjQ5LTEuNDg0N3YtMi40MDE5YzAtLjgxNjcuNjcwNi0xLjQ4NDcgMS40OS0xLjQ4NDcuODE5NiAwIDEuNDg5OS42NjggMS40ODk5IDEuNDg0N3oiIGZpbGw9InVybCgjYikiLz48L3N2Zz4K';
+
     private _connecting: boolean;
     private _wallet: PhantomWallet | null;
     private _publicKey: PublicKey | null;
+    private _readyState: WalletReadyState =
+        typeof window === 'undefined' || typeof document === 'undefined'
+            ? WalletReadyState.Unsupported
+            : WalletReadyState.NotDetected;
 
     constructor(config: PhantomWalletAdapterConfig = {}) {
         super();
         this._connecting = false;
         this._wallet = null;
         this._publicKey = null;
+        if (this._readyState !== WalletReadyState.Unsupported) {
+            scopePollingDetectionStrategy(() => {
+                if (window.solana?.isPhantom) {
+                    this._readyState = WalletReadyState.Installed;
+                    this.emit('readyStateChange', this._readyState);
+                    return true;
+                }
+                return false;
+            });
+        }
     }
 
     get publicKey(): PublicKey | null {
@@ -68,27 +93,16 @@ export class PhantomWalletAdapter extends BaseMessageSignerWalletAdapter {
         return !!this._wallet?.isConnected;
     }
 
-    async ready(): Promise<boolean> {
-        if (typeof window === 'undefined' || typeof document === 'undefined') return false;
-
-        if (document.readyState === 'complete') return !!window.solana?.isPhantom;
-
-        return new Promise((resolve) => {
-            function listener() {
-                window.removeEventListener('load', listener);
-                resolve(!!window.solana?.isPhantom);
-            }
-
-            window.addEventListener('load', listener);
-        });
+    get readyState(): WalletReadyState {
+        return this._readyState;
     }
 
     async connect(): Promise<void> {
         try {
             if (this.connected || this.connecting) return;
-            this._connecting = true;
+            if (this._readyState !== WalletReadyState.Installed) throw new WalletNotReadyError();
 
-            if (!(await this.ready())) throw new WalletNotReadyError();
+            this._connecting = true;
 
             const wallet = window!.solana!;
 
@@ -137,7 +151,7 @@ export class PhantomWalletAdapter extends BaseMessageSignerWalletAdapter {
             this._wallet = wallet;
             this._publicKey = publicKey;
 
-            this.emit('connect');
+            this.emit('connect', publicKey);
         } catch (error: any) {
             this.emit('error', error);
             throw error;

+ 0 - 1
packages/wallets/phantom/src/index.ts

@@ -1,2 +1 @@
 export * from './adapter';
-export * from './wallet';

+ 0 - 11
packages/wallets/phantom/src/wallet.ts

@@ -1,11 +0,0 @@
-import { Wallet, WalletName } from '@solana/wallet-adapter-base';
-import { PhantomWalletAdapter, PhantomWalletAdapterConfig } from './adapter';
-
-export const PhantomWalletName = 'Phantom' as WalletName;
-
-export const getPhantomWallet = (config: PhantomWalletAdapterConfig = {}): Wallet => ({
-    name: PhantomWalletName,
-    url: 'https://phantom.app',
-    icon: 'data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjM0IiB3aWR0aD0iMzQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iLjUiIHgyPSIuNSIgeTE9IjAiIHkyPSIxIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiM1MzRiYjEiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiM1NTFiZjkiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iYiIgeDE9Ii41IiB4Mj0iLjUiIHkxPSIwIiB5Mj0iMSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZmZmIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjZmZmIiBzdG9wLW9wYWNpdHk9Ii44MiIvPjwvbGluZWFyR3JhZGllbnQ+PGNpcmNsZSBjeD0iMTciIGN5PSIxNyIgZmlsbD0idXJsKCNhKSIgcj0iMTciLz48cGF0aCBkPSJtMjkuMTcwMiAxNy4yMDcxaC0yLjk5NjljMC02LjEwNzQtNC45NjgzLTExLjA1ODE3LTExLjA5NzUtMTEuMDU4MTctNi4wNTMyNSAwLTEwLjk3NDYzIDQuODI5NTctMTEuMDk1MDggMTAuODMyMzctLjEyNDYxIDYuMjA1IDUuNzE3NTIgMTEuNTkzMiAxMS45NDUzOCAxMS41OTMyaC43ODM0YzUuNDkwNiAwIDEyLjg0OTctNC4yODI5IDEzLjk5OTUtOS41MDEzLjIxMjMtLjk2MTktLjU1MDItMS44NjYxLTEuNTM4OC0xLjg2NjF6bS0xOC41NDc5LjI3MjFjMCAuODE2Ny0uNjcwMzggMS40ODQ3LTEuNDkwMDEgMS40ODQ3LS44MTk2NCAwLTEuNDg5OTgtLjY2ODMtMS40ODk5OC0xLjQ4NDd2LTIuNDAxOWMwLS44MTY3LjY3MDM0LTEuNDg0NyAxLjQ4OTk4LTEuNDg0Ny44MTk2MyAwIDEuNDkwMDEuNjY4IDEuNDkwMDEgMS40ODQ3em01LjE3MzggMGMwIC44MTY3LS42NzAzIDEuNDg0Ny0xLjQ4OTkgMS40ODQ3LS44MTk3IDAtMS40OS0uNjY4My0xLjQ5LTEuNDg0N3YtMi40MDE5YzAtLjgxNjcuNjcwNi0xLjQ4NDcgMS40OS0xLjQ4NDcuODE5NiAwIDEuNDg5OS42NjggMS40ODk5IDEuNDg0N3oiIGZpbGw9InVybCgjYikiLz48L3N2Zz4K',
-    adapter: new PhantomWalletAdapter(config),
-});

+ 2 - 2
packages/wallets/phantom/tsconfig.json

@@ -1,8 +1,8 @@
 {
     "extends": "../../../tsconfig.json",
+    "include": ["src"],
     "compilerOptions": {
         "noEmit": false,
         "outDir": "lib"
-    },
-    "include": ["src"]
+    }
 }

+ 3 - 3
packages/wallets/safepal/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@solana/wallet-adapter-safepal",
-    "version": "0.4.0",
+    "version": "0.5.0",
     "author": "Solana Maintainers <maintainers@solana.foundation>",
     "repository": "https://github.com/solana-labs/wallet-adapter",
     "license": "Apache-2.0",
@@ -22,11 +22,11 @@
         "build": "yarn clean && tsc"
     },
     "peerDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     },
     "devDependencies": {
-        "@solana/wallet-adapter-base": "^0.8.1",
+        "@solana/wallet-adapter-base": "^0.9.0",
         "@solana/web3.js": "^1.20.0"
     }
 }

+ 30 - 16
packages/wallets/safepal/src/adapter.ts

@@ -1,9 +1,13 @@
 import {
+    Adapter,
     BaseSignerWalletAdapter,
+    scopePollingDetectionStrategy,
     WalletAccountError,
+    WalletName,
     WalletNotConnectedError,
     WalletNotReadyError,
     WalletPublicKeyError,
+    WalletReadyState,
     WalletSignTransactionError,
 } from '@solana/wallet-adapter-base';
 import { PublicKey, Transaction } from '@solana/web3.js';
@@ -23,16 +27,37 @@ declare const window: SafePalWalletWindow;
 
 export interface SafePalWalletAdapterConfig {}
 
+export const SafePalWalletName = 'SafePal' as WalletName;
+
 export class SafePalWalletAdapter extends BaseSignerWalletAdapter {
+    name = SafePalWalletName;
+    url = 'https://safepal.io';
+    icon =
+        'data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI1NiIgdmlld0JveD0iMCAwIDI1NiAyNTYiIHdpZHRoPSIyNTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48cGF0aCBkPSJtMjU2IDEyOGMwIDcwLjY5Mzg3My01Ny4zMDc5MzMgMTI4LTEyOCAxMjgtNzAuNjkyMDY2NyAwLTEyOC01Ny4zMDYxMjctMTI4LTEyOCAwLTcwLjY5MjA2NjcgNTcuMzA3OTMzMy0xMjggMTI4LTEyOCA3MC42OTIwNjcgMCAxMjggNTcuMzA3OTMzMyAxMjggMTI4IiBmaWxsPSIjMDAwIi8+PHBhdGggZD0ibTIwMC45OTE0OTkgMTQxLjM4NDM3OXYxMS45MzQ0MDRjMCAzMi40OTcwNzgtNDYuMjA1ODI2IDUxLjQ3NTM0Ni02MS45MzUzOTggNTYuOTg2NTMybC02LjI4OTM3MSAyLjE3NDY4NXYtMjAuNjI5NDAxbDIuNjIxOTE2LS45ODkyOGMyMi43MTQ3NDUtOC41NDg4MzYgNDUuNjMyMjgyLTIzLjI5NTQ2NSA0Ni4wODgzNjEtMzcuMTIzNzg0bC4wMDY5MjItLjQxODc1MnYtMTEuOTM0NDA0em0tNzIuODY1MTcyLTk3Ljg2NDM3OSAxOS42NjExMzUgNi4wNjMzODIydjIxLjA0ODA2N2wtMTkuNjYxMTM1LTYuMDg0Mzk2My0xLjI4NjcxMS4zOTkyNjgzdjQ3LjM1NDUxMzhoMjAuOTQ3ODQ2djE5LjUxMDgwM2gtMjAuOTQ3ODQ2djgwLjM4MDYzbC02LjM2Mjg5Mi0yLjM3NTQ2N2MtMi40NDg2MzUtLjkyODUwMi01Ljk3MzE2Ny0yLjMzOTg4Ni0xMC4yMTU4NzUtNC4yNDkxNDJsLS41NTc0NC0uMjUxODU4LTIuMzc0NTk2LTEuMDg0NjUydi0xNTQuMjkzNzU5N3ptLTI2Ljk2OTIgOC40MDA0NzU4djIwLjk1MTA3ODhsLTI2LjY0MTA1NTggOC4yNjk4NjQ5djMxLjE1OTA5MjVoMjYuNjQxMDU1OHY5MC4yNDI3MThsLTUuOTAwMTE4Mi0zLjAzNDExNWMtMTguMTc2Mjc3My05LjM1NTM5LTM5LjgxMTA4ODItMjUuMDcwMTczLTQwLjI0MTk2NjgtNDYuOTcwMjQ4bC0uMDA2NTQxMS0uNjY1NTMydi0xMC40ODkyOGgxOS41MDc1NzAzdjEwLjQ4OTI4YzAgNC40NjY3MzcgMi4yNTgyODY3IDkuMTU1OCA2LjcxODY5NjMgMTMuOTgyOTQ0bC40MTE1NTY2LjQzOTIwOXYtMzQuNDg0MTczaC0yNi42Mzc4MjMydi02NS42NDY0OTh6bTUyLjU1MjYtLjQ5OTE2NjIgNDcuMjgxNzcyIDE0LjYzMzkxMDZ2NjUuNzU2NDE3OGgtMjcuNzU4MDM3djI4LjQ3NTc1MWwtLjI4NTQ4OS4zNTQyMDZjLTEuMzU1MjUgMS42MzQ0NTUtNy41NjM1NzUgOC42MjI2NTUtMTkuMjIwNDY1IDE0LjU5NDkxNnptMTkuNTIzNzM1IDI3LjA3NzUwMzN2MzMuODAyMDIyMWg4LjI1MDQ2N3YtMzEuMjU0NDY0eiIgZmlsbD0iI2ZmZiIvPjwvZz48L3N2Zz4=';
+
     private _connecting: boolean;
     private _wallet: SafePalWallet | null;
     private _publicKey: PublicKey | null;
+    private _readyState: WalletReadyState =
+        typeof window === 'undefined' || typeof document === 'undefined'
+            ? WalletReadyState.Unsupported
+            : WalletReadyState.NotDetected;
 
     constructor(config: SafePalWalletAdapterConfig = {}) {
         super();
         this._connecting = false;
         this._wallet = null;
         this._publicKey = null;
+        if (this._readyState !== WalletReadyState.Unsupported) {
+            scopePollingDetectionStrategy(() => {
+                if (window.safepal?.isSafePalWallet) {
+                    this._readyState = WalletReadyState.Installed;
+                    this.emit('readyStateChange', this._readyState);
+                    return true;
+                }
+                return false;
+            });
+        }
     }
 
     get publicKey(): PublicKey | null {
@@ -43,27 +68,16 @@ export class SafePalWalletAdapter extends BaseSignerWalletAdapter {
         return this._connecting;
     }
 
-    async ready(): Promise<boolean> {
-        if (typeof window === 'undefined' || typeof document === 'undefined') return false;
-
-        if (document.readyState === 'complete') return !!window.safepal?.isSafePalWallet;
-
-        return new Promise((resolve) => {
-            function listener() {
-                window.removeEventListener('load', listener);
-                resolve(!!window.safepal?.isSafePalWallet);
-            }
-
-            window.addEventListener('load', listener);
-        });
+    get readyState(): WalletReadyState {
+        return this._readyState;
     }
 
     async connect(): Promise<void> {
         try {
             if (this.connected || this.connecting) return;
-            this._connecting = true;
+            if (this._readyState !== WalletReadyState.Installed) throw new WalletNotReadyError();
 
-            if (!(await this.ready())) throw new WalletNotReadyError();
+            this._connecting = true;
 
             const wallet = window!.safepal!;
 
@@ -84,7 +98,7 @@ export class SafePalWalletAdapter extends BaseSignerWalletAdapter {
             this._wallet = wallet;
             this._publicKey = publicKey;
 
-            this.emit('connect');
+            this.emit('connect', publicKey);
         } catch (error: any) {
             this.emit('error', error);
             throw error;

+ 0 - 1
packages/wallets/safepal/src/index.ts

@@ -1,2 +1 @@
 export * from './adapter';
-export * from './wallet';

+ 0 - 11
packages/wallets/safepal/src/wallet.ts

@@ -1,11 +0,0 @@
-import { Wallet, WalletName } from '@solana/wallet-adapter-base';
-import { SafePalWalletAdapter, SafePalWalletAdapterConfig } from './adapter';
-
-export const SafePalWalletName = 'SafePal' as WalletName;
-
-export const getSafePalWallet = (config: SafePalWalletAdapterConfig = {}): Wallet => ({
-    name: SafePalWalletName,
-    url: 'https://safepal.io',
-    icon: 'data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI1NiIgdmlld0JveD0iMCAwIDI1NiAyNTYiIHdpZHRoPSIyNTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48cGF0aCBkPSJtMjU2IDEyOGMwIDcwLjY5Mzg3My01Ny4zMDc5MzMgMTI4LTEyOCAxMjgtNzAuNjkyMDY2NyAwLTEyOC01Ny4zMDYxMjctMTI4LTEyOCAwLTcwLjY5MjA2NjcgNTcuMzA3OTMzMy0xMjggMTI4LTEyOCA3MC42OTIwNjcgMCAxMjggNTcuMzA3OTMzMyAxMjggMTI4IiBmaWxsPSIjMDAwIi8+PHBhdGggZD0ibTIwMC45OTE0OTkgMTQxLjM4NDM3OXYxMS45MzQ0MDRjMCAzMi40OTcwNzgtNDYuMjA1ODI2IDUxLjQ3NTM0Ni02MS45MzUzOTggNTYuOTg2NTMybC02LjI4OTM3MSAyLjE3NDY4NXYtMjAuNjI5NDAxbDIuNjIxOTE2LS45ODkyOGMyMi43MTQ3NDUtOC41NDg4MzYgNDUuNjMyMjgyLTIzLjI5NTQ2NSA0Ni4wODgzNjEtMzcuMTIzNzg0bC4wMDY5MjItLjQxODc1MnYtMTEuOTM0NDA0em0tNzIuODY1MTcyLTk3Ljg2NDM3OSAxOS42NjExMzUgNi4wNjMzODIydjIxLjA0ODA2N2wtMTkuNjYxMTM1LTYuMDg0Mzk2My0xLjI4NjcxMS4zOTkyNjgzdjQ3LjM1NDUxMzhoMjAuOTQ3ODQ2djE5LjUxMDgwM2gtMjAuOTQ3ODQ2djgwLjM4MDYzbC02LjM2Mjg5Mi0yLjM3NTQ2N2MtMi40NDg2MzUtLjkyODUwMi01Ljk3MzE2Ny0yLjMzOTg4Ni0xMC4yMTU4NzUtNC4yNDkxNDJsLS41NTc0NC0uMjUxODU4LTIuMzc0NTk2LTEuMDg0NjUydi0xNTQuMjkzNzU5N3ptLTI2Ljk2OTIgOC40MDA0NzU4djIwLjk1MTA3ODhsLTI2LjY0MTA1NTggOC4yNjk4NjQ5djMxLjE1OTA5MjVoMjYuNjQxMDU1OHY5MC4yNDI3MThsLTUuOTAwMTE4Mi0zLjAzNDExNWMtMTguMTc2Mjc3My05LjM1NTM5LTM5LjgxMTA4ODItMjUuMDcwMTczLTQwLjI0MTk2NjgtNDYuOTcwMjQ4bC0uMDA2NTQxMS0uNjY1NTMydi0xMC40ODkyOGgxOS41MDc1NzAzdjEwLjQ4OTI4YzAgNC40NjY3MzcgMi4yNTgyODY3IDkuMTU1OCA2LjcxODY5NjMgMTMuOTgyOTQ0bC40MTE1NTY2LjQzOTIwOXYtMzQuNDg0MTczaC0yNi42Mzc4MjMydi02NS42NDY0OTh6bTUyLjU1MjYtLjQ5OTE2NjIgNDcuMjgxNzcyIDE0LjYzMzkxMDZ2NjUuNzU2NDE3OGgtMjcuNzU4MDM3djI4LjQ3NTc1MWwtLjI4NTQ4OS4zNTQyMDZjLTEuMzU1MjUgMS42MzQ0NTUtNy41NjM1NzUgOC42MjI2NTUtMTkuMjIwNDY1IDE0LjU5NDkxNnptMTkuNTIzNzM1IDI3LjA3NzUwMzN2MzMuODAyMDIyMWg4LjI1MDQ2N3YtMzEuMjU0NDY0eiIgZmlsbD0iI2ZmZiIvPjwvZz48L3N2Zz4=',
-    adapter: new SafePalWalletAdapter(config),
-});

+ 2 - 2
packages/wallets/safepal/tsconfig.json

@@ -1,8 +1,8 @@
 {
     "extends": "../../../tsconfig.json",
+    "include": ["src"],
     "compilerOptions": {
         "noEmit": false,
         "outDir": "lib"
-    },
-    "include": ["src"]
+    }
 }

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است