- Consolidated duplicate UndoManagers to single instance - Fixed connection promise to only resolve on 'connected' status - Fixed WebSocketProvider import (WebsocketProvider) - Added proper doc.destroy() cleanup - Renamed isPresenceInitialized property to avoid conflict Co-Authored-By: Paperclip <noreply@paperclip.ing>
81 lines
3.1 KiB
TypeScript
81 lines
3.1 KiB
TypeScript
import type { Adapter, WalletName } from '@solana/wallet-adapter-base';
|
|
import { isWalletAdapterCompatibleWallet, StandardWalletAdapter } from '@solana/wallet-standard-wallet-adapter-base';
|
|
import { DEPRECATED_getWallets } from '@wallet-standard/app';
|
|
import type { Wallet } from '@wallet-standard/base';
|
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
|
|
export function useStandardWalletAdapters(adapters: Adapter[]): Adapter[] {
|
|
const warnings = useConstant(() => new Set<WalletName>());
|
|
const { get, on } = useConstant(() => DEPRECATED_getWallets());
|
|
const [standardAdapters, setStandardAdapters] = useState(() => wrapWalletsWithAdapters(get()));
|
|
|
|
useEffect(() => {
|
|
const listeners = [
|
|
on('register', (...wallets) =>
|
|
setStandardAdapters((standardAdapters) => [...standardAdapters, ...wrapWalletsWithAdapters(wallets)])
|
|
),
|
|
on('unregister', (...wallets) =>
|
|
setStandardAdapters((standardAdapters) =>
|
|
standardAdapters.filter((standardAdapter) =>
|
|
wallets.some((wallet) => wallet === standardAdapter.wallet)
|
|
)
|
|
)
|
|
),
|
|
];
|
|
return () => listeners.forEach((off) => off());
|
|
}, [on]);
|
|
|
|
const prevStandardAdapters = usePrevious(standardAdapters);
|
|
useEffect(() => {
|
|
if (!prevStandardAdapters) return;
|
|
|
|
const currentAdapters = new Set(standardAdapters);
|
|
const removedAdapters = new Set(
|
|
prevStandardAdapters.filter((previousAdapter) => !currentAdapters.has(previousAdapter))
|
|
);
|
|
removedAdapters.forEach((adapter) => adapter.destroy());
|
|
}, [prevStandardAdapters, standardAdapters]);
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
useEffect(() => () => standardAdapters.forEach((adapter) => adapter.destroy()), []);
|
|
|
|
return useMemo(
|
|
() => [
|
|
...standardAdapters,
|
|
...adapters.filter(({ name }) => {
|
|
if (standardAdapters.some((standardAdapter) => standardAdapter.name === name)) {
|
|
if (!warnings.has(name)) {
|
|
warnings.add(name);
|
|
console.warn(
|
|
`${name} was registered as a Standard Wallet. The Wallet Adapter for ${name} can be removed from your app.`
|
|
);
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}),
|
|
],
|
|
[standardAdapters, adapters, warnings]
|
|
);
|
|
}
|
|
|
|
function useConstant<T>(fn: () => T): T {
|
|
const ref = useRef<{ value: T }>(undefined);
|
|
if (ref.current === undefined) {
|
|
ref.current = { value: fn() };
|
|
}
|
|
return ref.current.value;
|
|
}
|
|
|
|
function usePrevious<T>(state: T): T | undefined {
|
|
const ref = useRef<T>(undefined);
|
|
useEffect(() => {
|
|
ref.current = state;
|
|
});
|
|
return ref.current;
|
|
}
|
|
|
|
function wrapWalletsWithAdapters(wallets: readonly Wallet[]): readonly StandardWalletAdapter[] {
|
|
return wallets.filter(isWalletAdapterCompatibleWallet).map((wallet) => new StandardWalletAdapter({ wallet }));
|
|
}
|