/** * SolanaWalletStandardRegistry * * Which Solana wallets exist, and whether each is connected. The Solana * analogue of `EvmProviderRegistry` + EIP-6963. * * Compatible wallets (Phantom, Solflare, Backpack, ...) announce themselves * through the Wallet Standard's window-event handshake. Solana Kit, * wallet-adapter, and framework-kit use these registered wallets. Observing * the handshake covers those wallets without coupling Formo to the host * library: the registry announces `wallet-standard:app-ready`, listens for * `wallet-standard:register-wallet`, and subscribes to each wallet's * `standard:events` `change` event. * * What it reports: * - `detect` when a wallet registers (session-deduped by the SDK on rdns). * - `connect` when a wallet's Solana accounts go from none to some, or the * first account changes; `disconnect` when they go from some to none. * - `chain` when the configured cluster changes while a wallet is connected. * * What it does not do: wrap any wallet method, issue any request to a * wallet, or depend on `@wallet-standard/*` (the handshake is a few lines, * and the SDK's dependency policy is two runtime dependencies, forever). * * Cluster: the Wallet Standard lists every cluster a wallet SUPPORTS, not * the one the app is using, so the cluster is `options.solana.cluster` when * given, else mainnet-beta when the wallet supports it, else the first * Solana cluster it lists. A framework-kit app gets the cluster from its * store instead, through `SolanaStoreHandler`. * * @see https://github.com/wallet-standard/wallet-standard */ import { SolanaCaptureDeps, SolanaCluster, UnsubscribeFn } from "./types"; /** What the registry needs from the SDK that owns it. */ export interface SolanaWalletStandardRegistryDeps extends SolanaCaptureDeps { willTrackEvent(chainId: number): boolean; detect(params: { providerName: string; rdns: string; }): Promise; /** * Record wallet and chain state centrally WITHOUT emitting an event. * * Observing a wallet is not the same as reporting one: the exclusion gate * keys off the central chain, so a connection or a cluster switch has to * land there even when the matching autocapture event is off or the chain * is excluded. Without an address, the chain's state is cleared. The EVM * tracker separates the two the same way. * @see FormoAnalytics.syncWalletState */ syncWalletState(params: { chainId: number; address?: string; }): void; /** The wallet the SDK currently treats as active, across namespaces. */ currentAddress(): string | undefined; /** * Whether THIS registry reports connections. * * A framework-kit app connects through the very same Wallet Standard * wallet, so its store and this registry both see every connection. The * store is the better witness there (it knows the cluster and connector), * so once it has observed or adopted a connection the registry keeps * discovering wallets and emitting `detect`, but leaves connect and * disconnect to the store. Exactly one connect per connection, either way. */ ownsWalletEvents(): boolean; } export interface SolanaWalletStandardRegistryOptions { /** The cluster the app uses. Overrides what is derived from the wallet. */ cluster?: SolanaCluster; } type SolanaConnection = { address: string; chainId: number; }; export declare class SolanaWalletStandardRegistry { private readonly deps; private wallets; private connectSeq; /** * Connections observed before this sequence number predate a `reset()`. * They stay tracked and their disconnect is still reported, but they are * not put back into central state until observed again: reset() promised * a clean slate. */ private restorableFrom; private cluster?; private removeWindowListener?; /** Set by cleanup(); a torn-down registry refuses late registrations. */ private isCleanedUp; /** * Handed to every wallet. Wallets keep it and may call `register` long * after the handshake, which is why `register` checks `isCleanedUp`. */ private readonly api; constructor(deps: SolanaWalletStandardRegistryDeps, options?: SolanaWalletStandardRegistryOptions); /** * The Wallet Standard handshake, both directions. * * A wallet injected before us hears `app-ready` and registers at once; a * wallet injected after us dispatches `register-wallet`, which we answer. * Neither is optional: an extension's content script and the app's bundle * race, and which one wins differs per page load. */ private listen; /** * Add wallets once. Returns an unregister function, as the standard asks. * * Public so an integration that already holds a wallet object (its own * `getWallets()` call, say) can hand it over without the window handshake. */ register(...wallets: unknown[]): UnsubscribeFn; private track; private untrack; private onChange; /** * Compare what the wallet now authorizes with what was last reported. * * none → some is a connect, some → none a disconnect, and a different * first account is a disconnect followed by a connect, matching what the * framework-kit store handler reports for the same transitions. */ private reconcile; private reportConnect; private reportDisconnect; /** * The chain id to report for a wallet. * * The Wallet Standard cannot say which cluster the app is on, only which * ones the wallet supports, so an explicit cluster wins, then mainnet-beta * if supported (nearly every wallet lists every cluster, and production * traffic is mainnet), then the first cluster listed. */ private chainIdFor; /** * Set the cluster the app uses. A connected wallet's chain id follows, * with a `chain` event, the same as the store handler on a cluster switch. */ setCluster(cluster: SolanaCluster): void; /** Names of every wallet discovered so far, for the debug helpers. */ get walletNames(): string[]; /** The newest restorable connection, if any, other than `except`. */ newestConnection(except?: string): SolanaConnection | undefined; /** The restorable connection on `address`, if any. */ private connectionOf; private newestTracked; private trackedOn; /** Live, attributed, and observed since the last reset(). */ private isRestorable; /** @see restorableFrom */ onReset(): void; /** * The rdns this registry reported a still-live connect for `address` * under, if any. Lets a failed store adoption name both identities. */ reportedConnectionRdns(address: string): string | undefined; /** * Transfer a connect already emitted by this registry to a store handler. * The state remains connected, but the same transition must not be emitted * a second time when framework-kit's store catches up. */ takeReportedConnection(address: string, rdns: string): { address: string; chainId: number; } | undefined; cleanup(): void; } export {}; //# sourceMappingURL=SolanaWalletStandardRegistry.d.ts.map