Files
FrenoCorp/node_modules/@solana/wallet-standard-wallet-adapter-react/src/useStandardWalletAdapters.ts
Michael Freno 7c684a42cc FRE-600: Fix code review blockers
- 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>
2026-04-25 00:08:01 -04:00

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 }));
}