diff --git a/packages/kit-plugin-wallet/.gitignore b/packages/kit-plugin-wallet/.gitignore
new file mode 100644
index 0000000..849ddff
--- /dev/null
+++ b/packages/kit-plugin-wallet/.gitignore
@@ -0,0 +1 @@
+dist/
diff --git a/packages/kit-plugin-wallet/.prettierignore b/packages/kit-plugin-wallet/.prettierignore
new file mode 100644
index 0000000..c52dcf5
--- /dev/null
+++ b/packages/kit-plugin-wallet/.prettierignore
@@ -0,0 +1,4 @@
+dist/
+test-ledger/
+target/
+CHANGELOG.md
diff --git a/packages/kit-plugin-wallet/LICENSE b/packages/kit-plugin-wallet/LICENSE
new file mode 100644
index 0000000..f7e0a95
--- /dev/null
+++ b/packages/kit-plugin-wallet/LICENSE
@@ -0,0 +1,22 @@
+MIT License
+
+Copyright (c) 2025 Anza
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/packages/kit-plugin-wallet/README.md b/packages/kit-plugin-wallet/README.md
new file mode 100644
index 0000000..535d3a4
--- /dev/null
+++ b/packages/kit-plugin-wallet/README.md
@@ -0,0 +1,265 @@
+# Kit Plugins ➤ Wallet
+
+[![npm][npm-image]][npm-url]
+[![npm-downloads][npm-downloads-image]][npm-url]
+
+[npm-downloads-image]: https://img.shields.io/npm/dm/@solana/kit-plugin-wallet.svg?style=flat
+[npm-image]: https://img.shields.io/npm/v/@solana/kit-plugin-wallet.svg?style=flat&label=%40solana%2Fkit-plugin-wallet
+[npm-url]: https://www.npmjs.com/package/@solana/kit-plugin-wallet
+
+This package provides plugins that add browser wallet support to your Kit clients using [wallet-standard](https://github.com/wallet-standard/wallet-standard). They handle wallet discovery, connection lifecycle, account selection, and signer creation.
+
+Four plugin functions are exported — each adds a `client.wallet` namespace, but they differ in how the connected wallet's signer is exposed on the client:
+
+| Plugin | `client.payer` | `client.identity` | Use case |
+| --------------------- | -------------- | ----------------- | ------------------------------------------------------------- |
+| `walletSigner` | wallet signer | wallet signer | Most dApps — wallet pays fees and signs as the user identity. |
+| `walletPayer` | wallet signer | — | Wallet pays fees; identity is managed separately. |
+| `walletIdentity` | — | wallet signer | Backend relayer pays fees; wallet provides user identity. |
+| `walletWithoutSigner` | — | — | Wallet state only; payer and identity are managed separately. |
+
+## Installation
+
+```sh
+pnpm install @solana/kit-plugin-wallet
+```
+
+## Quick start
+
+```ts
+import { createClient } from '@solana/kit';
+import { solanaRpc } from '@solana/kit-plugin-rpc';
+import { walletSigner } from '@solana/kit-plugin-wallet';
+import { planAndSendTransactions } from '@solana/kit-plugin-instruction-plan';
+
+const client = createClient()
+ .use(walletSigner({ chain: 'solana:mainnet' }))
+ .use(solanaRpc({ rpcUrl: 'https://api.mainnet-beta.solana.com' }))
+ .use(planAndSendTransactions());
+
+// Read discovered wallets from state
+const { wallets } = client.wallet.getState();
+
+// Connect a wallet
+await client.wallet.connect(wallets[0]);
+
+// client.payer and client.identity are now the connected wallet's signer
+await client.sendTransaction([myInstruction]);
+```
+
+## `walletSigner` plugin
+
+Syncs the connected wallet's signer to both `client.payer` and `client.identity`. This is the most common choice for dApps where the user's wallet pays fees and signs as the transaction identity.
+
+```ts
+import { walletSigner } from '@solana/kit-plugin-wallet';
+
+const client = createClient()
+ .use(walletSigner({ chain: 'solana:mainnet' }))
+ .use(solanaRpc({ rpcUrl: 'https://api.mainnet-beta.solana.com' }))
+ .use(planAndSendTransactions());
+```
+
+## `walletPayer` plugin
+
+Syncs the connected wallet's signer to `client.payer` only. Use this when you need the wallet as the fee payer but don't need `client.identity`. For most dApps, prefer `walletSigner` which sets both.
+
+```ts
+import { walletPayer } from '@solana/kit-plugin-wallet';
+
+const client = createClient()
+ .use(walletPayer({ chain: 'solana:mainnet' }))
+ .use(solanaRpc({ rpcUrl: 'https://api.mainnet-beta.solana.com' }))
+ .use(planAndSendTransactions());
+```
+
+## `walletIdentity` plugin
+
+Syncs the connected wallet's signer to `client.identity` only. Use this when a separate payer (e.g. a backend relayer) pays transaction fees, but the user's wallet is needed as the identity signer.
+
+```ts
+import { payer } from '@solana/kit-plugin-signer';
+import { walletIdentity } from '@solana/kit-plugin-wallet';
+
+const client = createClient()
+ .use(payer(relayerKeypair))
+ .use(walletIdentity({ chain: 'solana:mainnet' }))
+ .use(solanaRpc({ rpcUrl: 'https://api.mainnet-beta.solana.com' }))
+ .use(planAndSendTransactions());
+
+// client.payer is always relayerKeypair
+// client.identity is the connected wallet's signer
+```
+
+## `walletWithoutSigner` plugin
+
+Adds `client.wallet` without setting `client.payer` or `client.identity`. Use this alongside separate `payer()` and/or `identity()` plugins, or when the wallet's signer is used explicitly in instructions.
+
+```ts
+import { payer } from '@solana/kit-plugin-signer';
+import { walletWithoutSigner } from '@solana/kit-plugin-wallet';
+
+const client = createClient()
+ .use(payer(backendKeypair))
+ .use(walletWithoutSigner({ chain: 'solana:mainnet' }))
+ .use(solanaRpc({ rpcUrl: 'https://api.mainnet-beta.solana.com' }))
+ .use(planAndSendTransactions());
+
+// client.payer is always backendKeypair
+// client.wallet.getState().connected?.signer for manual use
+```
+
+## State and actions
+
+All wallet state is accessed via `client.wallet.getState()`, which returns a referentially stable `WalletState` object (new reference only when something changes).
+
+- **`getState().wallets`** — All discovered wallets that support the configured chain.
+
+ ```ts
+ const { wallets } = client.wallet.getState();
+ for (const w of wallets) {
+ console.log(w.name, w.icon);
+ }
+ ```
+
+- **`getState().connected`** — The active connection (wallet, account, and signer), or `null` when disconnected.
+
+ ```ts
+ const { connected } = client.wallet.getState();
+ console.log(connected?.account.address);
+ ```
+
+- **`getState().status`** — The current connection status: `'pending'`, `'disconnected'`, `'connecting'`, `'connected'`, `'disconnecting'`, or `'reconnecting'`.
+
+- **`connect(wallet)`** — Connect to a wallet and select the first newly authorized account.
+
+ ```ts
+ const accounts = await client.wallet.connect(selectedWallet);
+ ```
+
+- **`disconnect()`** — Disconnect the active wallet.
+
+- **`selectAccount(account)`** — Switch to a different account within an already-authorized wallet without reconnecting.
+
+ ```ts
+ client.wallet.selectAccount(accounts[0]);
+ ```
+
+- **`signMessage(message)`** — Sign a raw message with the connected account.
+
+ ```ts
+ const signature = await client.wallet.signMessage(new TextEncoder().encode('Hello'));
+ ```
+
+- **`signIn(wallet, input)`** — Sign In With Solana (SIWS-as-connect). Connects the wallet, calls `solana:signIn`, and sets up full connection state. Pass `{}` for `input` if no sign-in customization is needed. To sign in with the already-connected wallet, pass `getState().connected.wallet`.
+
+ ```ts
+ const output = await client.wallet.signIn(selectedWallet, { domain: window.location.host });
+ ```
+
+## Framework integration
+
+The plugin exposes `subscribe` and `getState` for binding wallet state to any UI framework.
+
+**React** — use `useSyncExternalStore` for concurrent-mode-safe rendering:
+
+```tsx
+import { useSyncExternalStore } from 'react';
+
+function useWalletState() {
+ return useSyncExternalStore(client.wallet.subscribe, client.wallet.getState);
+}
+
+function App() {
+ const { wallets, connected, status } = useWalletState();
+
+ if (status === 'pending') return null; // avoid flashing a connect button before auto-reconnect
+
+ if (!connected) {
+ return wallets.map(w => (
+
+ ));
+ }
+
+ return
Connected: {connected.account.address}
;
+}
+```
+
+**Vue** — use a `shallowRef` composable:
+
+```ts
+import { onMounted, onUnmounted, shallowRef } from 'vue';
+
+function useWalletState() {
+ const state = shallowRef(client.wallet.getState());
+ onMounted(() => {
+ const unsub = client.wallet.subscribe(() => {
+ state.value = client.wallet.getState();
+ });
+ onUnmounted(unsub);
+ });
+ return state;
+}
+```
+
+**Svelte** — wrap in a `readable` store:
+
+```ts
+import { readable } from 'svelte/store';
+
+export const walletState = readable(client.wallet.getState(), set => {
+ return client.wallet.subscribe(() => set(client.wallet.getState()));
+});
+```
+
+## Configuration
+
+```ts
+walletSigner({
+ chain: 'solana:mainnet', // required
+ storage: sessionStorage, // default: localStorage (null to disable)
+ storageKey: 'my-app:wallet', // default: 'kit-wallet'
+ autoConnect: false, // default: true (disable silent reconnect)
+ filter: w => w.features.includes('solana:signAndSendTransaction'), // optional
+});
+```
+
+## Persistence
+
+By default the plugin uses `localStorage` to remember the last connected wallet and auto-reconnects on the next page load. Pass `storage: null` to disable, or provide a custom adapter (e.g. `sessionStorage` or an IndexedDB wrapper).
+
+## SSR / server-side rendering
+
+All four wallet plugins are safe to include in a shared client that runs on both server and browser. On the server, `status` stays `'pending'` permanently, all actions throw, and no registry listeners or storage reads are made. In the browser the plugin initializes normally.
+
+```ts
+const client = createClient()
+ .use(solanaRpc({ rpcUrl: 'https://api.mainnet-beta.solana.com' }))
+ .use(walletSigner({ chain: 'solana:mainnet' }))
+ .use(planAndSendTransactions());
+
+// Server: status === 'pending', client.payer throws
+// Browser: auto-connects, client.payer becomes the wallet signer
+```
+
+## Cleanup
+
+The plugin implements `[Symbol.dispose]`, so it integrates with the `using` declaration or explicit disposal:
+
+```ts
+{
+ using client = createClient().use(walletSigner({ chain: 'solana:mainnet' }));
+ // registry listeners and storage subscriptions are cleaned up on scope exit
+}
+```
+
+Or call `[Symbol.dispose]()` explicitly when you're done with the client:
+
+```ts
+const client = createClient().use(walletSigner({ chain: 'solana:mainnet' }));
+
+// ... later, when the client is no longer needed
+client[Symbol.dispose]();
+```
diff --git a/packages/kit-plugin-wallet/package.json b/packages/kit-plugin-wallet/package.json
new file mode 100644
index 0000000..1dbf358
--- /dev/null
+++ b/packages/kit-plugin-wallet/package.json
@@ -0,0 +1,77 @@
+{
+ "name": "@solana/kit-plugin-wallet",
+ "version": "0.1.0",
+ "description": "Wallet connection plugin for Kit clients",
+ "exports": {
+ "types": "./dist/types/index.d.ts",
+ "react-native": "./dist/index.react-native.mjs",
+ "browser": {
+ "import": "./dist/index.browser.mjs",
+ "require": "./dist/index.browser.cjs"
+ },
+ "node": {
+ "import": "./dist/index.node.mjs",
+ "require": "./dist/index.node.cjs"
+ }
+ },
+ "browser": {
+ "./dist/index.node.cjs": "./dist/index.browser.cjs",
+ "./dist/index.node.mjs": "./dist/index.browser.mjs"
+ },
+ "main": "./dist/index.node.cjs",
+ "module": "./dist/index.node.mjs",
+ "react-native": "./dist/index.react-native.mjs",
+ "types": "./dist/types/index.d.ts",
+ "type": "commonjs",
+ "files": [
+ "./dist/types",
+ "./dist/index.*",
+ "./src/"
+ ],
+ "sideEffects": false,
+ "keywords": [
+ "solana",
+ "kit",
+ "plugin",
+ "wallet",
+ "wallet-adapter",
+ "wallet-standard",
+ "signer"
+ ],
+ "scripts": {
+ "build": "rimraf dist && tsup && tsc -p ./tsconfig.declarations.json",
+ "dev": "vitest --project node",
+ "lint": "eslint . && prettier --check .",
+ "lint:fix": "eslint --fix . && prettier --write .",
+ "test": "pnpm test:types && pnpm test:treeshakability",
+ "test:treeshakability": "for file in dist/index.*.mjs; do agadoo $file; done",
+ "test:types": "tsc --noEmit"
+ },
+ "peerDependencies": {
+ "@solana/kit": "^6.6.0"
+ },
+ "dependencies": {
+ "@solana/wallet-account-signer": "^6.6.0",
+ "@solana/wallet-standard-chains": "^1.1.1",
+ "@solana/wallet-standard-features": "^1.3.0",
+ "@wallet-standard/app": "^1.1.0",
+ "@wallet-standard/base": "^1.1.0",
+ "@wallet-standard/errors": "^0.1.1",
+ "@wallet-standard/features": "^1.1.0",
+ "@wallet-standard/ui": "^1.0.1",
+ "@wallet-standard/ui-features": "^1.0.1",
+ "@wallet-standard/ui-registry": "^1.0.1"
+ },
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/anza-xyz/kit-plugins"
+ },
+ "bugs": {
+ "url": "http://github.com/anza-xyz/kit-plugins/issues"
+ },
+ "browserslist": [
+ "supports bigint and not dead",
+ "maintained node versions"
+ ]
+}
diff --git a/packages/kit-plugin-wallet/src/__typetests__/wallet-typetest.ts b/packages/kit-plugin-wallet/src/__typetests__/wallet-typetest.ts
new file mode 100644
index 0000000..6f7c60d
--- /dev/null
+++ b/packages/kit-plugin-wallet/src/__typetests__/wallet-typetest.ts
@@ -0,0 +1,95 @@
+import { type ClientWithIdentity, type ClientWithPayer, createClient, TransactionSigner } from '@solana/kit';
+
+import { ClientWithWallet } from '../types';
+import { walletIdentity, walletPayer, walletSigner, walletWithoutSigner } from '../wallet';
+
+const config = { chain: 'solana:mainnet' as const };
+
+const signer = null as unknown as TransactionSigner;
+
+// [DESCRIBE] walletSigner
+{
+ // It sets payer, identity, and wallet on the client.
+ {
+ const client = createClient().use(walletSigner(config));
+ client.payer satisfies ClientWithPayer['payer'];
+ client.identity satisfies ClientWithIdentity['identity'];
+ client.wallet satisfies ClientWithWallet['wallet'];
+ }
+}
+
+// [DESCRIBE] walletPayer
+{
+ // It sets payer and wallet on the client.
+ {
+ const client = createClient().use(walletPayer(config));
+ client.payer satisfies ClientWithPayer['payer'];
+ client.wallet satisfies ClientWithWallet['wallet'];
+ }
+ // It does not strip a previously-set identity.
+ {
+ const base = { identity: signer } as unknown as ClientWithIdentity;
+ const result = walletPayer(config)(base);
+ result.identity satisfies TransactionSigner;
+ }
+}
+
+// [DESCRIBE] walletIdentity
+{
+ // It sets identity and wallet on the client.
+ {
+ const client = createClient().use(walletIdentity(config));
+ client.identity satisfies ClientWithIdentity['identity'];
+ client.wallet satisfies ClientWithWallet['wallet'];
+ }
+ // It does not strip a previously-set payer.
+ {
+ const base = { payer: signer } as unknown as ClientWithPayer;
+ const result = walletIdentity(config)(base);
+ result.payer satisfies TransactionSigner;
+ }
+}
+
+// [DESCRIBE] walletWithoutSigner
+{
+ // It sets wallet on the client.
+ {
+ const client = createClient().use(walletWithoutSigner(config));
+ client.wallet satisfies ClientWithWallet['wallet'];
+ }
+ // It does not strip a previously-set payer.
+ {
+ const base = { payer: signer } as unknown as ClientWithPayer;
+ const result = walletWithoutSigner(config)(base);
+ result.payer satisfies TransactionSigner;
+ }
+ // It does not strip a previously-set identity.
+ {
+ const base = { identity: signer } as unknown as ClientWithIdentity;
+ const result = walletWithoutSigner(config)(base);
+ result.identity satisfies TransactionSigner;
+ }
+ // It does not strip a previously-set payer and identity.
+ {
+ const base = { identity: signer, payer: signer } as unknown as ClientWithIdentity & ClientWithPayer;
+ const result = walletWithoutSigner(config)(base);
+ result.payer satisfies TransactionSigner;
+ result.identity satisfies TransactionSigner;
+ }
+}
+
+// [DESCRIBE] Only one wallet plugin allowed
+{
+ // It fails to typecheck when a wallet plugin is used on a client that already has wallet.
+ {
+ const client = createClient().use(walletSigner(config));
+ // @ts-expect-error Cannot use a second wallet plugin.
+ walletSigner(config)(client);
+ // @ts-expect-error Cannot use a second wallet plugin.
+ walletPayer(config)(client);
+ // @ts-expect-error Cannot use a second wallet plugin.
+ walletIdentity(config)(client);
+ // @ts-expect-error Cannot use a second wallet plugin.
+ walletWithoutSigner(config)(client);
+ }
+}
diff --git a/packages/kit-plugin-wallet/src/index.ts b/packages/kit-plugin-wallet/src/index.ts
new file mode 100644
index 0000000..cf3ebe1
--- /dev/null
+++ b/packages/kit-plugin-wallet/src/index.ts
@@ -0,0 +1,2 @@
+export * from './types';
+export * from './wallet';
diff --git a/packages/kit-plugin-wallet/src/store.ts b/packages/kit-plugin-wallet/src/store.ts
new file mode 100644
index 0000000..958912d
--- /dev/null
+++ b/packages/kit-plugin-wallet/src/store.ts
@@ -0,0 +1,14 @@
+import type { WalletNamespace, WalletPluginConfig } from './types';
+
+// -- Internal types ---------------------------------------------------------
+
+export type WalletStore = WalletNamespace & {
+ [Symbol.dispose]: () => void;
+};
+
+// -- Store ------------------------------------------------------------------
+
+/** @internal */
+export function createWalletStore(_config: WalletPluginConfig): WalletStore {
+ throw new Error('not implemented');
+}
diff --git a/packages/kit-plugin-wallet/src/types.ts b/packages/kit-plugin-wallet/src/types.ts
new file mode 100644
index 0000000..290e98d
--- /dev/null
+++ b/packages/kit-plugin-wallet/src/types.ts
@@ -0,0 +1,300 @@
+import type { MessageSigner, SignatureBytes, TransactionSigner } from '@solana/kit';
+import type { SolanaChain } from '@solana/wallet-standard-chains';
+import type { SolanaSignInInput, SolanaSignInOutput } from '@solana/wallet-standard-features';
+import type { IdentifierString } from '@wallet-standard/base';
+import type { UiWallet, UiWalletAccount } from '@wallet-standard/ui';
+
+/**
+ * The signer type for a connected wallet account.
+ *
+ * Always satisfies `TransactionSigner`. Additionally implements `MessageSigner`
+ * when the wallet supports `solana:signMessage`.
+ */
+export type WalletSigner = TransactionSigner | (MessageSigner & TransactionSigner);
+
+// -- Public types -----------------------------------------------------------
+
+/**
+ * The connection status of the wallet plugin.
+ *
+ * - `pending` — not yet initialized. Initial state on both server and browser.
+ * On the server this state is permanent. In the browser it resolves to
+ * `disconnected` or `reconnecting` once the storage check completes.
+ * - `disconnected` — initialized, no wallet connected.
+ * - `connecting` — a user-initiated connection request is in progress.
+ * - `connected` — a wallet is connected.
+ * - `disconnecting` — a user-initiated disconnection request is in progress.
+ * - `reconnecting` — auto-connect in progress (connecting to persisted wallet).
+ */
+export type WalletStatus = 'connected' | 'connecting' | 'disconnected' | 'disconnecting' | 'pending' | 'reconnecting';
+
+/**
+ * A snapshot of the wallet plugin state at a point in time.
+ *
+ * Returned by {@link WalletNamespace.getState}. The same object reference
+ * is returned on successive calls as long as nothing has changed — a new
+ * object is only created when a field actually changes. This ensures
+ * `useSyncExternalStore` only triggers re-renders on meaningful state changes.
+ *
+ * @see {@link WalletNamespace.getState}
+ */
+export type WalletState = {
+ /**
+ * The active connection, or `null` when disconnected.
+ *
+ * `signer` is `null` for read-only / watch-only wallets that do not
+ * support any signing feature.
+ */
+ readonly connected: {
+ readonly account: UiWalletAccount;
+ /** The signer for the active account, or `null` for read-only wallets. */
+ readonly signer: WalletSigner | null;
+ readonly wallet: UiWallet;
+ } | null;
+ /** The current connection status. */
+ readonly status: WalletStatus;
+ /** All discovered wallets matching the configured chain and filter. */
+ readonly wallets: readonly UiWallet[];
+};
+
+/**
+ * Options accepted by each async wallet action.
+ *
+ * Currently only carries an `abortSignal`, but is kept as an object for
+ * consistency with the rest of the Kit ecosystem and to allow future
+ * additions without breaking the call-site shape.
+ *
+ * @see {@link WalletNamespace.connect}
+ * @see {@link WalletNamespace.disconnect}
+ * @see {@link WalletNamespace.signMessage}
+ * @see {@link WalletNamespace.signIn}
+ */
+export type WalletActionOptions = {
+ /**
+ * An optional `AbortSignal` used to cancel the operation.
+ *
+ * Cancellation is pre-call only: the plugin calls
+ * `abortSignal.throwIfAborted()` at the start of each action and bails
+ * out before invoking the wallet. Once the underlying wallet-standard
+ * call has been dispatched, its result is returned even if the signal
+ * is aborted mid-flight — the wallet's side effect (an approved
+ * signature, a live connection, a broadcast transaction) is the source
+ * of truth, and throwing here would discard real user work without
+ * undoing what the wallet already did.
+ */
+ abortSignal?: AbortSignal;
+};
+
+/**
+ * A pluggable storage adapter for persisting the selected wallet account.
+ *
+ * Follows the Web Storage API shape (`getItem`/`setItem`/`removeItem`).
+ * `localStorage` and `sessionStorage` satisfy this interface directly.
+ * Async backends (IndexedDB, encrypted storage) may return `Promise`s.
+ *
+ * @example
+ * ```ts
+ * // Use sessionStorage
+ * wallet({ chain: 'solana:mainnet', storage: sessionStorage });
+ *
+ * // Custom async adapter
+ * wallet({
+ * chain: 'solana:mainnet',
+ * storage: {
+ * getItem: (key) => myStore.get(key),
+ * setItem: (key, value) => myStore.set(key, value),
+ * removeItem: (key) => myStore.delete(key),
+ * },
+ * });
+ * ```
+ */
+export type WalletStorage = {
+ getItem(key: string): Promise | string | null;
+ removeItem(key: string): Promise | void;
+ setItem(key: string, value: string): Promise | void;
+};
+
+/**
+ * Configuration for the wallet plugins ({@link walletSigner},
+ * {@link walletPayer}, {@link walletIdentity}, {@link walletWithoutSigner}).
+ */
+export type WalletPluginConfig = {
+ /**
+ * Whether to attempt silent reconnection on startup using the persisted
+ * wallet account from `storage`.
+ *
+ * Has no effect if `storage` is `null`.
+ *
+ * @default true
+ */
+ autoConnect?: boolean;
+
+ /**
+ * The chain this client targets (e.g. `'solana:mainnet'`).
+ *
+ * Accepts any {@link SolanaChain} (with literal autocomplete) and, as an
+ * escape hatch, any wallet-standard {@link IdentifierString} shape
+ * (`${string}:${string}`) for custom chains or non-Solana L2s. The plugin's
+ * runtime behavior is chain-agnostic — it passes the identifier to
+ * wallet-standard discovery (`uiWallet.chains.includes(chain)`) and to
+ * `createSignerFromWalletAccount`. Wallets that don't advertise the chain
+ * are filtered out, and accounts that can't produce a signer for the chain
+ * resolve to `signer: null` (matching the read-only-wallet contract).
+ *
+ * One client = one chain. To switch networks, create a separate client
+ * with a different chain and RPC endpoint.
+ */
+ chain: SolanaChain | (IdentifierString & {});
+
+ /**
+ * Optional filter function for wallet discovery. Called for each wallet
+ * that supports the configured chain and `standard:connect`. Return `true`
+ * to include the wallet, `false` to exclude it.
+ *
+ * @example
+ * ```ts
+ * // Require signAndSendTransaction
+ * filter: (w) => w.features.includes('solana:signAndSendTransaction')
+ *
+ * // Whitelist specific wallets
+ * filter: (w) => ['SomeWallet', 'SomeOtherWallet'].includes(w.name)
+ * ```
+ */
+ filter?: (wallet: UiWallet) => boolean;
+
+ /**
+ * Storage adapter for persisting the selected wallet account across page
+ * loads. Pass `null` to disable persistence entirely.
+ *
+ * When omitted in a browser environment, `localStorage` is used by default.
+ * On the server, storage is always skipped regardless of this option.
+ *
+ * @default localStorage (in browser)
+ * @see {@link WalletStorage}
+ */
+ storage?: WalletStorage | null;
+
+ /**
+ * Storage key used for persistence.
+ *
+ * @default 'kit-wallet'
+ */
+ storageKey?: string;
+};
+
+/**
+ * The `wallet` namespace exposed on the client as `client.wallet`.
+ *
+ * All wallet state is accessed via {@link getState}. Use {@link subscribe}
+ * to be notified of changes and integrate with framework primitives such as
+ * React's `useSyncExternalStore`.
+ *
+ * @see {@link ClientWithWallet}
+ */
+export type WalletNamespace = {
+ // -- Actions --
+
+ /**
+ * Connect to a wallet. Calls `standard:connect`, then selects the first
+ * newly authorized account (or the first account if reconnecting). Creates
+ * and caches a signer for the active account.
+ *
+ * @returns All accounts from the wallet after connection.
+ * @throws The wallet's rejection error if the user declines the prompt.
+ * @throws `options.abortSignal.reason` if the signal is already aborted
+ * when the action is called. Aborts after the wallet call has been
+ * dispatched do not take effect.
+ */
+ connect: (wallet: UiWallet, options?: WalletActionOptions) => Promise;
+
+ /**
+ * Disconnect the active wallet. Calls `standard:disconnect` if supported.
+ *
+ * @throws `options.abortSignal.reason` if the signal is already aborted
+ * when the action is called. Aborts after the wallet call has been
+ * dispatched do not take effect.
+ */
+ disconnect: (options?: WalletActionOptions) => Promise;
+
+ // -- State --
+ /**
+ * Get the current wallet state. Referentially stable — a new object is
+ * only created when a field actually changes, so React's
+ * `useSyncExternalStore` skips re-renders when nothing meaningful changed.
+ *
+ * @see {@link WalletState}
+ */
+ getState: () => WalletState;
+
+ /**
+ * Switch to a different account within the connected wallet. Creates and
+ * caches a new signer for the selected account.
+ *
+ * @throws `SolanaError(SOLANA_ERROR__WALLET__NOT_CONNECTED)` if no wallet is connected.
+ */
+ selectAccount: (account: UiWalletAccount) => void;
+
+ /**
+ * Sign In With Solana (SIWS-as-connect).
+ *
+ * Connects the wallet, calls `solana:signIn`, sets the returned account as
+ * active, and creates a signer. After completion, the client is in the same
+ * state as if {@link connect} had been called.
+ *
+ * All fields on `SolanaSignInInput` are optional — pass `{}` if no sign-in
+ * customization is needed.
+ *
+ * To sign in with the already-connected wallet, pass
+ * `getState().connected.wallet`.
+ *
+ * @throws `WalletStandardError(WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_FEATURE_UNIMPLEMENTED)`
+ * if the wallet does not support `solana:signIn`.
+ * @throws `options.abortSignal.reason` if the signal is already aborted
+ * when the action is called. Aborts after the wallet call has been
+ * dispatched do not take effect.
+ */
+ signIn: (wallet: UiWallet, input: SolanaSignInInput, options?: WalletActionOptions) => Promise;
+
+ /**
+ * Sign an arbitrary message with the connected account.
+ *
+ * Calls the wallet's `solana:signMessage` feature directly (does not go
+ * through the cached signer), so message signing works even for wallets
+ * that don't support transaction signing.
+ *
+ * @throws `SolanaError(SOLANA_ERROR__WALLET__NOT_CONNECTED)` if no wallet is connected.
+ * @throws `WalletStandardError(WALLET_STANDARD_ERROR__FEATURES__WALLET_ACCOUNT_FEATURE_UNIMPLEMENTED)`
+ * if the wallet does not support `solana:signMessage`.
+ * @throws `options.abortSignal.reason` if the signal is already aborted
+ * when the action is called. Aborts after the wallet call has been
+ * dispatched do not take effect.
+ */
+ signMessage: (message: Uint8Array, options?: WalletActionOptions) => Promise;
+
+ /**
+ * Subscribe to any wallet state change. Compatible with React's
+ * `useSyncExternalStore` and similar framework primitives.
+ *
+ * @returns An unsubscribe function.
+ *
+ * @example
+ * ```ts
+ * const state = useSyncExternalStore(client.wallet.subscribe, client.wallet.getState);
+ * ```
+ */
+ subscribe: (listener: () => void) => () => void;
+};
+
+/**
+ * Properties added to the client by the wallet plugins.
+ *
+ * All wallet state and actions are namespaced under `client.wallet`.
+ *
+ * @see {@link walletSigner}
+ * @see {@link WalletNamespace}
+ */
+// TODO: would be moved to kit plugin-interfaces
+export type ClientWithWallet = {
+ /** The wallet namespace — state, actions, and framework integration. */
+ readonly wallet: WalletNamespace;
+};
diff --git a/packages/kit-plugin-wallet/src/types/global.d.ts b/packages/kit-plugin-wallet/src/types/global.d.ts
new file mode 100644
index 0000000..13de8a7
--- /dev/null
+++ b/packages/kit-plugin-wallet/src/types/global.d.ts
@@ -0,0 +1,6 @@
+declare const __BROWSER__: boolean;
+declare const __ESM__: boolean;
+declare const __NODEJS__: boolean;
+declare const __REACTNATIVE__: boolean;
+declare const __TEST__: boolean;
+declare const __VERSION__: string;
diff --git a/packages/kit-plugin-wallet/src/wallet.ts b/packages/kit-plugin-wallet/src/wallet.ts
new file mode 100644
index 0000000..817b254
--- /dev/null
+++ b/packages/kit-plugin-wallet/src/wallet.ts
@@ -0,0 +1,177 @@
+import { type ClientWithIdentity, type ClientWithPayer, extendClient, withCleanup } from '@solana/kit';
+
+import { createWalletStore } from './store';
+import type { ClientWithWallet, WalletPluginConfig } from './types';
+
+// -- Internal helpers ---------------------------------------------------------
+
+function defineSignerGetter(
+ additions: Record,
+ property: string,
+ store: ReturnType,
+): void {
+ Object.defineProperty(additions, property, {
+ configurable: true,
+ enumerable: true,
+ get() {
+ const state = store.getState();
+ if (!state.connected) {
+ // TODO: throw new SolanaError(SOLANA_ERROR__WALLET__NO_SIGNER_CONNECTED, { status: state.status });
+ throw new Error(`No signing wallet connected (status: ${state.status})`);
+ }
+ if (!state.connected.signer) {
+ // TODO: throw new SolanaError(SOLANA_ERROR__WALLET__SIGNER_NOT_AVAILABLE);
+ throw new Error('Connected wallet does not support signing');
+ }
+ return state.connected.signer;
+ },
+ });
+}
+
+function createPlugin(config: WalletPluginConfig, signerProperties: string[]) {
+ return (client: T): Disposable & Omit & TAdditions => {
+ if ('wallet' in client) {
+ throw new Error(
+ 'Only one wallet plugin can be used per client. ' +
+ 'Use walletSigner, walletPayer, walletIdentity, or walletWithoutSigner — not multiple.',
+ );
+ }
+
+ const store = createWalletStore(config);
+
+ const additions: Record = { wallet: store };
+ for (const prop of signerProperties) {
+ defineSignerGetter(additions, prop, store);
+ }
+
+ return withCleanup(extendClient(client, additions), () => store[Symbol.dispose]()) as unknown as Disposable &
+ Omit &
+ TAdditions;
+ };
+}
+
+// -- Public API ---------------------------------------------------------------
+
+/**
+ * A framework-agnostic Kit plugin that manages wallet discovery, connection
+ * lifecycle, and signer creation using wallet-standard — and syncs the
+ * connected wallet's signer to both `client.payer` and `client.identity`.
+ *
+ * This is the most common entrypoint for dApps. When a signing-capable
+ * wallet is connected, `client.payer` and `client.identity` both return the
+ * wallet signer. When disconnected or read-only, accessing either throws.
+ *
+ * **SSR-safe.** Can be included in a shared client chain that runs on both
+ * server and browser.
+ *
+ * ```ts
+ * const client = createClient()
+ * .use(rpc('https://api.mainnet-beta.solana.com'))
+ * .use(walletSigner({ chain: 'solana:mainnet' }))
+ * .use(planAndSendTransactions());
+ * ```
+ *
+ * @param config - Plugin configuration.
+ *
+ * @see {@link walletPayer}
+ * @see {@link walletIdentity}
+ * @see {@link walletWithoutSigner}
+ * @see {@link WalletPluginConfig}
+ */
+export function walletSigner(config: WalletPluginConfig) {
+ return createPlugin(config, ['payer', 'identity']);
+}
+
+/**
+ * A framework-agnostic Kit plugin that manages wallet discovery, connection
+ * lifecycle, and signer creation using wallet-standard — and syncs the
+ * connected wallet's signer to `client.identity`.
+ *
+ * Use this when `client.payer` is controlled by a separate `payer()` plugin
+ * (e.g. a backend relayer pays fees, but the user's wallet is the identity).
+ *
+ * **SSR-safe.** Can be included in a shared client chain that runs on both
+ * server and browser.
+ *
+ * ```ts
+ * const client = createClient()
+ * .use(rpc('https://api.mainnet-beta.solana.com'))
+ * .use(payer(relayerKeypair))
+ * .use(walletIdentity({ chain: 'solana:mainnet' }))
+ * .use(planAndSendTransactions());
+ * ```
+ *
+ * @param config - Plugin configuration.
+ *
+ * @see {@link walletSigner}
+ * @see {@link walletPayer}
+ * @see {@link walletWithoutSigner}
+ * @see {@link WalletPluginConfig}
+ */
+export function walletIdentity(config: WalletPluginConfig) {
+ return createPlugin(config, ['identity']);
+}
+
+/**
+ * A framework-agnostic Kit plugin that manages wallet discovery, connection
+ * lifecycle, and signer creation using wallet-standard — and syncs the
+ * connected wallet's signer to `client.payer`.
+ *
+ * Use this when you need the wallet as the fee payer but don't need
+ * `client.identity`. For most dApps, prefer {@link walletSigner} which
+ * sets both.
+ *
+ * **SSR-safe.** Can be included in a shared client chain that runs on both
+ * server and browser.
+ *
+ * ```ts
+ * const client = createClient()
+ * .use(rpc('https://api.mainnet-beta.solana.com'))
+ * .use(walletPayer({ chain: 'solana:mainnet' }))
+ * .use(planAndSendTransactions());
+ * ```
+ *
+ * @param config - Plugin configuration.
+ *
+ * @see {@link walletSigner}
+ * @see {@link walletIdentity}
+ * @see {@link walletWithoutSigner}
+ * @see {@link WalletPluginConfig}
+ */
+export function walletPayer(config: WalletPluginConfig) {
+ return createPlugin(config, ['payer']);
+}
+
+/**
+ * A framework-agnostic Kit plugin that manages wallet discovery, connection
+ * lifecycle, and signer creation using wallet-standard.
+ *
+ * Adds the `wallet` namespace to the client without setting `client.payer`
+ * or `client.identity`. Use this alongside separate `payer()` and/or
+ * `identity()` plugins, or when the wallet's signer is used explicitly in
+ * instructions. For most dApps, prefer {@link walletSigner} instead.
+ *
+ * **SSR-safe.** Can be included in a shared client chain that runs on both
+ * server and browser.
+ *
+ * ```ts
+ * const client = createClient()
+ * .use(rpc('https://api.mainnet-beta.solana.com'))
+ * .use(payer(backendKeypair))
+ * .use(walletWithoutSigner({ chain: 'solana:mainnet' }))
+ * .use(planAndSendTransactions());
+ *
+ * // client.payer is always backendKeypair
+ * // client.wallet.getState().connected?.signer for manual use
+ * ```
+ *
+ * @param config - Plugin configuration.
+ *
+ * @see {@link walletSigner}
+ * @see {@link walletPayer}
+ * @see {@link walletIdentity}
+ * @see {@link WalletPluginConfig}
+ */
+export function walletWithoutSigner(config: WalletPluginConfig) {
+ return createPlugin(config, []);
+}
diff --git a/packages/kit-plugin-wallet/tsconfig.declarations.json b/packages/kit-plugin-wallet/tsconfig.declarations.json
new file mode 100644
index 0000000..dc2d27b
--- /dev/null
+++ b/packages/kit-plugin-wallet/tsconfig.declarations.json
@@ -0,0 +1,10 @@
+{
+ "compilerOptions": {
+ "declaration": true,
+ "declarationMap": true,
+ "emitDeclarationOnly": true,
+ "outDir": "./dist/types"
+ },
+ "extends": "./tsconfig.json",
+ "include": ["src/index.ts", "src/types"]
+}
diff --git a/packages/kit-plugin-wallet/tsconfig.json b/packages/kit-plugin-wallet/tsconfig.json
new file mode 100644
index 0000000..7a4f027
--- /dev/null
+++ b/packages/kit-plugin-wallet/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "compilerOptions": { "lib": [] },
+ "display": "@solana/kit-plugin-wallet",
+ "extends": "../../tsconfig.json",
+ "include": ["src", "test"]
+}
diff --git a/packages/kit-plugin-wallet/tsup.config.ts b/packages/kit-plugin-wallet/tsup.config.ts
new file mode 100644
index 0000000..55e9945
--- /dev/null
+++ b/packages/kit-plugin-wallet/tsup.config.ts
@@ -0,0 +1,5 @@
+import { defineConfig } from 'tsup';
+
+import { getPackageBuildConfigs } from '../../tsup.config.base';
+
+export default defineConfig(getPackageBuildConfigs());
diff --git a/packages/kit-plugin-wallet/vitest.config.mts b/packages/kit-plugin-wallet/vitest.config.mts
new file mode 100644
index 0000000..8fd0137
--- /dev/null
+++ b/packages/kit-plugin-wallet/vitest.config.mts
@@ -0,0 +1,8 @@
+import { defineConfig } from 'vitest/config';
+import { getVitestConfig } from '../../vitest.config.base.mjs';
+
+export default defineConfig({
+ test: {
+ projects: [getVitestConfig('browser'), getVitestConfig('node'), getVitestConfig('react-native')],
+ },
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 7edee31..cae36ab 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -46,7 +46,7 @@ importers:
version: 6.1.3
tsup:
specifier: ^8.5.1
- version: 8.5.1(postcss@8.5.10)(typescript@5.9.3)
+ version: 8.5.1(postcss@8.5.9)(typescript@5.9.3)
turbo:
specifier: ^2.9.4
version: 2.9.6
@@ -173,6 +173,42 @@ importers:
specifier: ^6.8.0
version: 6.8.0(typescript@5.9.3)
+ packages/kit-plugin-wallet:
+ dependencies:
+ '@solana/kit':
+ specifier: ^6.8.0
+ version: 6.8.0(typescript@5.9.3)
+ '@solana/wallet-account-signer':
+ specifier: ^6.6.0
+ version: 6.6.0(typescript@5.9.3)
+ '@solana/wallet-standard-chains':
+ specifier: ^1.1.1
+ version: 1.1.1
+ '@solana/wallet-standard-features':
+ specifier: ^1.3.0
+ version: 1.3.0
+ '@wallet-standard/app':
+ specifier: ^1.1.0
+ version: 1.1.0
+ '@wallet-standard/base':
+ specifier: ^1.1.0
+ version: 1.1.0
+ '@wallet-standard/errors':
+ specifier: ^0.1.1
+ version: 0.1.1
+ '@wallet-standard/features':
+ specifier: ^1.1.0
+ version: 1.1.0
+ '@wallet-standard/ui':
+ specifier: ^1.0.1
+ version: 1.0.1
+ '@wallet-standard/ui-features':
+ specifier: ^1.0.1
+ version: 1.0.1
+ '@wallet-standard/ui-registry':
+ specifier: ^1.0.1
+ version: 1.0.1
+
packages/kit-plugins:
dependencies:
'@solana/kit':
@@ -352,8 +388,8 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
- '@babel/runtime@7.29.2':
- resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==}
+ '@babel/runtime@7.28.6':
+ resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==}
engines: {node: '>=6.9.0'}
'@babel/template@7.28.6':
@@ -432,14 +468,14 @@ packages:
'@changesets/write@0.4.0':
resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==}
- '@emnapi/core@1.10.0':
- resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==}
+ '@emnapi/core@1.9.1':
+ resolution: {integrity: sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==}
- '@emnapi/runtime@1.10.0':
- resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==}
+ '@emnapi/runtime@1.9.1':
+ resolution: {integrity: sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==}
- '@emnapi/wasi-threads@1.2.1':
- resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==}
+ '@emnapi/wasi-threads@1.2.0':
+ resolution: {integrity: sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==}
'@esbuild/aix-ppc64@0.27.2':
resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==}
@@ -447,8 +483,8 @@ packages:
cpu: [ppc64]
os: [aix]
- '@esbuild/aix-ppc64@0.27.7':
- resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==}
+ '@esbuild/aix-ppc64@0.27.5':
+ resolution: {integrity: sha512-nGsF/4C7uzUj+Nj/4J+Zt0bYQ6bz33Phz8Lb2N80Mti1HjGclTJdXZ+9APC4kLvONbjxN1zfvYNd8FEcbBK/MQ==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
@@ -459,8 +495,8 @@ packages:
cpu: [arm64]
os: [android]
- '@esbuild/android-arm64@0.27.7':
- resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==}
+ '@esbuild/android-arm64@0.27.5':
+ resolution: {integrity: sha512-Oeghq+XFgh1pUGd1YKs4DDoxzxkoUkvko+T/IVKwlghKLvvjbGFB3ek8VEDBmNvqhwuL0CQS3cExdzpmUyIrgA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
@@ -471,8 +507,8 @@ packages:
cpu: [arm]
os: [android]
- '@esbuild/android-arm@0.27.7':
- resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==}
+ '@esbuild/android-arm@0.27.5':
+ resolution: {integrity: sha512-Cv781jd0Rfj/paoNrul1/r4G0HLvuFKYh7C9uHZ2Pl8YXstzvCyyeWENTFR9qFnRzNMCjXmsulZuvosDg10Mog==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
@@ -483,8 +519,8 @@ packages:
cpu: [x64]
os: [android]
- '@esbuild/android-x64@0.27.7':
- resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==}
+ '@esbuild/android-x64@0.27.5':
+ resolution: {integrity: sha512-nQD7lspbzerlmtNOxYMFAGmhxgzn8Z7m9jgFkh6kpkjsAhZee1w8tJW3ZlW+N9iRePz0oPUDrYrXidCPSImD0Q==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
@@ -495,8 +531,8 @@ packages:
cpu: [arm64]
os: [darwin]
- '@esbuild/darwin-arm64@0.27.7':
- resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==}
+ '@esbuild/darwin-arm64@0.27.5':
+ resolution: {integrity: sha512-I+Ya/MgC6rr8oRWGRDF3BXDfP8K1BVUggHqN6VI2lUZLdDi1IM1v2cy0e3lCPbP+pVcK3Tv8cgUhHse1kaNZZw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
@@ -507,8 +543,8 @@ packages:
cpu: [x64]
os: [darwin]
- '@esbuild/darwin-x64@0.27.7':
- resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==}
+ '@esbuild/darwin-x64@0.27.5':
+ resolution: {integrity: sha512-MCjQUtC8wWJn/pIPM7vQaO69BFgwPD1jriEdqwTCKzWjGgkMbcg+M5HzrOhPhuYe1AJjXlHmD142KQf+jnYj8A==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
@@ -519,8 +555,8 @@ packages:
cpu: [arm64]
os: [freebsd]
- '@esbuild/freebsd-arm64@0.27.7':
- resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==}
+ '@esbuild/freebsd-arm64@0.27.5':
+ resolution: {integrity: sha512-X6xVS+goSH0UelYXnuf4GHLwpOdc8rgK/zai+dKzBMnncw7BTQIwquOodE7EKvY2UVUetSqyAfyZC1D+oqLQtg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
@@ -531,8 +567,8 @@ packages:
cpu: [x64]
os: [freebsd]
- '@esbuild/freebsd-x64@0.27.7':
- resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==}
+ '@esbuild/freebsd-x64@0.27.5':
+ resolution: {integrity: sha512-233X1FGo3a8x1ekLB6XT69LfZ83vqz+9z3TSEQCTYfMNY880A97nr81KbPcAMl9rmOFp11wO0dP+eB18KU/Ucg==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
@@ -543,8 +579,8 @@ packages:
cpu: [arm64]
os: [linux]
- '@esbuild/linux-arm64@0.27.7':
- resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==}
+ '@esbuild/linux-arm64@0.27.5':
+ resolution: {integrity: sha512-euKkilsNOv7x/M1NKsx5znyprbpsRFIzTV6lWziqJch7yWYayfLtZzDxDTl+LSQDJYAjd9TVb/Kt5UKIrj2e4A==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
@@ -555,8 +591,8 @@ packages:
cpu: [arm]
os: [linux]
- '@esbuild/linux-arm@0.27.7':
- resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==}
+ '@esbuild/linux-arm@0.27.5':
+ resolution: {integrity: sha512-0wkVrYHG4sdCCN/bcwQ7yYMXACkaHc3UFeaEOwSVW6e5RycMageYAFv+JS2bKLwHyeKVUvtoVH+5/RHq0fgeFw==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
@@ -567,8 +603,8 @@ packages:
cpu: [ia32]
os: [linux]
- '@esbuild/linux-ia32@0.27.7':
- resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==}
+ '@esbuild/linux-ia32@0.27.5':
+ resolution: {integrity: sha512-hVRQX4+P3MS36NxOy24v/Cdsimy/5HYePw+tmPqnNN1fxV0bPrFWR6TMqwXPwoTM2VzbkA+4lbHWUKDd5ZDA/w==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
@@ -579,8 +615,8 @@ packages:
cpu: [loong64]
os: [linux]
- '@esbuild/linux-loong64@0.27.7':
- resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==}
+ '@esbuild/linux-loong64@0.27.5':
+ resolution: {integrity: sha512-mKqqRuOPALI8nDzhOBmIS0INvZOOFGGg5n1osGIXAx8oersceEbKd4t1ACNTHM3sJBXGFAlEgqM+svzjPot+ZQ==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
@@ -591,8 +627,8 @@ packages:
cpu: [mips64el]
os: [linux]
- '@esbuild/linux-mips64el@0.27.7':
- resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==}
+ '@esbuild/linux-mips64el@0.27.5':
+ resolution: {integrity: sha512-EE/QXH9IyaAj1qeuIV5+/GZkBTipgGO782Ff7Um3vPS9cvLhJJeATy4Ggxikz2inZ46KByamMn6GqtqyVjhenA==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
@@ -603,8 +639,8 @@ packages:
cpu: [ppc64]
os: [linux]
- '@esbuild/linux-ppc64@0.27.7':
- resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==}
+ '@esbuild/linux-ppc64@0.27.5':
+ resolution: {integrity: sha512-0V2iF1RGxBf1b7/BjurA5jfkl7PtySjom1r6xOK2q9KWw/XCpAdtB6KNMO+9xx69yYfSCRR9FE0TyKfHA2eQMw==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
@@ -615,8 +651,8 @@ packages:
cpu: [riscv64]
os: [linux]
- '@esbuild/linux-riscv64@0.27.7':
- resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==}
+ '@esbuild/linux-riscv64@0.27.5':
+ resolution: {integrity: sha512-rYxThBx6G9HN6tFNuvB/vykeLi4VDsm5hE5pVwzqbAjZEARQrWu3noZSfbEnPZ/CRXP3271GyFk/49up2W190g==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
@@ -627,8 +663,8 @@ packages:
cpu: [s390x]
os: [linux]
- '@esbuild/linux-s390x@0.27.7':
- resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==}
+ '@esbuild/linux-s390x@0.27.5':
+ resolution: {integrity: sha512-uEP2q/4qgd8goEUc4QIdU/1P2NmEtZ/zX5u3OpLlCGhJIuBIv0s0wr7TB2nBrd3/A5XIdEkkS5ZLF0ULuvaaYQ==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
@@ -639,8 +675,8 @@ packages:
cpu: [x64]
os: [linux]
- '@esbuild/linux-x64@0.27.7':
- resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==}
+ '@esbuild/linux-x64@0.27.5':
+ resolution: {integrity: sha512-+Gq47Wqq6PLOOZuBzVSII2//9yyHNKZLuwfzCemqexqOQCSz0zy0O26kIzyp9EMNMK+nZ0tFHBZrCeVUuMs/ew==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
@@ -651,8 +687,8 @@ packages:
cpu: [arm64]
os: [netbsd]
- '@esbuild/netbsd-arm64@0.27.7':
- resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==}
+ '@esbuild/netbsd-arm64@0.27.5':
+ resolution: {integrity: sha512-3F/5EG8VHfN/I+W5cO1/SV2H9Q/5r7vcHabMnBqhHK2lTWOh3F8vixNzo8lqxrlmBtZVFpW8pmITHnq54+Tq4g==}
engines: {node: '>=18'}
cpu: [arm64]
os: [netbsd]
@@ -663,8 +699,8 @@ packages:
cpu: [x64]
os: [netbsd]
- '@esbuild/netbsd-x64@0.27.7':
- resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==}
+ '@esbuild/netbsd-x64@0.27.5':
+ resolution: {integrity: sha512-28t+Sj3CPN8vkMOlZotOmDgilQwVvxWZl7b8rxpn73Tt/gCnvrHxQUMng4uu3itdFvrtba/1nHejvxqz8xgEMA==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
@@ -675,8 +711,8 @@ packages:
cpu: [arm64]
os: [openbsd]
- '@esbuild/openbsd-arm64@0.27.7':
- resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==}
+ '@esbuild/openbsd-arm64@0.27.5':
+ resolution: {integrity: sha512-Doz/hKtiuVAi9hMsBMpwBANhIZc8l238U2Onko3t2xUp8xtM0ZKdDYHMnm/qPFVthY8KtxkXaocwmMh6VolzMA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
@@ -687,8 +723,8 @@ packages:
cpu: [x64]
os: [openbsd]
- '@esbuild/openbsd-x64@0.27.7':
- resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==}
+ '@esbuild/openbsd-x64@0.27.5':
+ resolution: {integrity: sha512-WfGVaa1oz5A7+ZFPkERIbIhKT4olvGl1tyzTRaB5yoZRLqC0KwaO95FeZtOdQj/oKkjW57KcVF944m62/0GYtA==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
@@ -699,8 +735,8 @@ packages:
cpu: [arm64]
os: [openharmony]
- '@esbuild/openharmony-arm64@0.27.7':
- resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==}
+ '@esbuild/openharmony-arm64@0.27.5':
+ resolution: {integrity: sha512-Xh+VRuh6OMh3uJ0JkCjI57l+DVe7VRGBYymen8rFPnTVgATBwA6nmToxM2OwTlSvrnWpPKkrQUj93+K9huYC6A==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openharmony]
@@ -711,8 +747,8 @@ packages:
cpu: [x64]
os: [sunos]
- '@esbuild/sunos-x64@0.27.7':
- resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==}
+ '@esbuild/sunos-x64@0.27.5':
+ resolution: {integrity: sha512-aC1gpJkkaUADHuAdQfuVTnqVUTLqqUNhAvEwHwVWcnVVZvNlDPGA0UveZsfXJJ9T6k9Po4eHi3c02gbdwO3g6w==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
@@ -723,8 +759,8 @@ packages:
cpu: [arm64]
os: [win32]
- '@esbuild/win32-arm64@0.27.7':
- resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==}
+ '@esbuild/win32-arm64@0.27.5':
+ resolution: {integrity: sha512-0UNx2aavV0fk6UpZcwXFLztA2r/k9jTUa7OW7SAea1VYUhkug99MW1uZeXEnPn5+cHOd0n8myQay6TlFnBR07w==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
@@ -735,8 +771,8 @@ packages:
cpu: [ia32]
os: [win32]
- '@esbuild/win32-ia32@0.27.7':
- resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==}
+ '@esbuild/win32-ia32@0.27.5':
+ resolution: {integrity: sha512-5nlJ3AeJWCTSzR7AEqVjT/faWyqKU86kCi1lLmxVqmNR+j4HrYdns+eTGjS/vmrzCIe8inGQckUadvS0+JkKdQ==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
@@ -747,8 +783,8 @@ packages:
cpu: [x64]
os: [win32]
- '@esbuild/win32-x64@0.27.7':
- resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==}
+ '@esbuild/win32-x64@0.27.5':
+ resolution: {integrity: sha512-PWypQR+d4FLfkhBIV+/kHsUELAnMpx1bRvvsn3p+/sAERbnCzFrtDRG2Xw5n+2zPxBK2+iaP+vetsRl4Ti7WgA==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
@@ -979,8 +1015,8 @@ packages:
cpu: [arm]
os: [android]
- '@rollup/rollup-android-arm-eabi@4.60.2':
- resolution: {integrity: sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==}
+ '@rollup/rollup-android-arm-eabi@4.60.1':
+ resolution: {integrity: sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==}
cpu: [arm]
os: [android]
@@ -989,8 +1025,8 @@ packages:
cpu: [arm64]
os: [android]
- '@rollup/rollup-android-arm64@4.60.2':
- resolution: {integrity: sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==}
+ '@rollup/rollup-android-arm64@4.60.1':
+ resolution: {integrity: sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==}
cpu: [arm64]
os: [android]
@@ -999,8 +1035,8 @@ packages:
cpu: [arm64]
os: [darwin]
- '@rollup/rollup-darwin-arm64@4.60.2':
- resolution: {integrity: sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==}
+ '@rollup/rollup-darwin-arm64@4.60.1':
+ resolution: {integrity: sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==}
cpu: [arm64]
os: [darwin]
@@ -1009,8 +1045,8 @@ packages:
cpu: [x64]
os: [darwin]
- '@rollup/rollup-darwin-x64@4.60.2':
- resolution: {integrity: sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==}
+ '@rollup/rollup-darwin-x64@4.60.1':
+ resolution: {integrity: sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==}
cpu: [x64]
os: [darwin]
@@ -1019,8 +1055,8 @@ packages:
cpu: [arm64]
os: [freebsd]
- '@rollup/rollup-freebsd-arm64@4.60.2':
- resolution: {integrity: sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==}
+ '@rollup/rollup-freebsd-arm64@4.60.1':
+ resolution: {integrity: sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==}
cpu: [arm64]
os: [freebsd]
@@ -1029,8 +1065,8 @@ packages:
cpu: [x64]
os: [freebsd]
- '@rollup/rollup-freebsd-x64@4.60.2':
- resolution: {integrity: sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==}
+ '@rollup/rollup-freebsd-x64@4.60.1':
+ resolution: {integrity: sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==}
cpu: [x64]
os: [freebsd]
@@ -1039,8 +1075,8 @@ packages:
cpu: [arm]
os: [linux]
- '@rollup/rollup-linux-arm-gnueabihf@4.60.2':
- resolution: {integrity: sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==}
+ '@rollup/rollup-linux-arm-gnueabihf@4.60.1':
+ resolution: {integrity: sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==}
cpu: [arm]
os: [linux]
@@ -1049,8 +1085,8 @@ packages:
cpu: [arm]
os: [linux]
- '@rollup/rollup-linux-arm-musleabihf@4.60.2':
- resolution: {integrity: sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==}
+ '@rollup/rollup-linux-arm-musleabihf@4.60.1':
+ resolution: {integrity: sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==}
cpu: [arm]
os: [linux]
@@ -1059,8 +1095,8 @@ packages:
cpu: [arm64]
os: [linux]
- '@rollup/rollup-linux-arm64-gnu@4.60.2':
- resolution: {integrity: sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==}
+ '@rollup/rollup-linux-arm64-gnu@4.60.1':
+ resolution: {integrity: sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==}
cpu: [arm64]
os: [linux]
@@ -1069,8 +1105,8 @@ packages:
cpu: [arm64]
os: [linux]
- '@rollup/rollup-linux-arm64-musl@4.60.2':
- resolution: {integrity: sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==}
+ '@rollup/rollup-linux-arm64-musl@4.60.1':
+ resolution: {integrity: sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==}
cpu: [arm64]
os: [linux]
@@ -1079,13 +1115,13 @@ packages:
cpu: [loong64]
os: [linux]
- '@rollup/rollup-linux-loong64-gnu@4.60.2':
- resolution: {integrity: sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==}
+ '@rollup/rollup-linux-loong64-gnu@4.60.1':
+ resolution: {integrity: sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==}
cpu: [loong64]
os: [linux]
- '@rollup/rollup-linux-loong64-musl@4.60.2':
- resolution: {integrity: sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==}
+ '@rollup/rollup-linux-loong64-musl@4.60.1':
+ resolution: {integrity: sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==}
cpu: [loong64]
os: [linux]
@@ -1094,13 +1130,13 @@ packages:
cpu: [ppc64]
os: [linux]
- '@rollup/rollup-linux-ppc64-gnu@4.60.2':
- resolution: {integrity: sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==}
+ '@rollup/rollup-linux-ppc64-gnu@4.60.1':
+ resolution: {integrity: sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==}
cpu: [ppc64]
os: [linux]
- '@rollup/rollup-linux-ppc64-musl@4.60.2':
- resolution: {integrity: sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==}
+ '@rollup/rollup-linux-ppc64-musl@4.60.1':
+ resolution: {integrity: sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==}
cpu: [ppc64]
os: [linux]
@@ -1109,8 +1145,8 @@ packages:
cpu: [riscv64]
os: [linux]
- '@rollup/rollup-linux-riscv64-gnu@4.60.2':
- resolution: {integrity: sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==}
+ '@rollup/rollup-linux-riscv64-gnu@4.60.1':
+ resolution: {integrity: sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==}
cpu: [riscv64]
os: [linux]
@@ -1119,8 +1155,8 @@ packages:
cpu: [riscv64]
os: [linux]
- '@rollup/rollup-linux-riscv64-musl@4.60.2':
- resolution: {integrity: sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==}
+ '@rollup/rollup-linux-riscv64-musl@4.60.1':
+ resolution: {integrity: sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==}
cpu: [riscv64]
os: [linux]
@@ -1129,8 +1165,8 @@ packages:
cpu: [s390x]
os: [linux]
- '@rollup/rollup-linux-s390x-gnu@4.60.2':
- resolution: {integrity: sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==}
+ '@rollup/rollup-linux-s390x-gnu@4.60.1':
+ resolution: {integrity: sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==}
cpu: [s390x]
os: [linux]
@@ -1139,8 +1175,8 @@ packages:
cpu: [x64]
os: [linux]
- '@rollup/rollup-linux-x64-gnu@4.60.2':
- resolution: {integrity: sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==}
+ '@rollup/rollup-linux-x64-gnu@4.60.1':
+ resolution: {integrity: sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==}
cpu: [x64]
os: [linux]
@@ -1149,13 +1185,13 @@ packages:
cpu: [x64]
os: [linux]
- '@rollup/rollup-linux-x64-musl@4.60.2':
- resolution: {integrity: sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==}
+ '@rollup/rollup-linux-x64-musl@4.60.1':
+ resolution: {integrity: sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==}
cpu: [x64]
os: [linux]
- '@rollup/rollup-openbsd-x64@4.60.2':
- resolution: {integrity: sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==}
+ '@rollup/rollup-openbsd-x64@4.60.1':
+ resolution: {integrity: sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==}
cpu: [x64]
os: [openbsd]
@@ -1164,8 +1200,8 @@ packages:
cpu: [arm64]
os: [openharmony]
- '@rollup/rollup-openharmony-arm64@4.60.2':
- resolution: {integrity: sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==}
+ '@rollup/rollup-openharmony-arm64@4.60.1':
+ resolution: {integrity: sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==}
cpu: [arm64]
os: [openharmony]
@@ -1174,8 +1210,8 @@ packages:
cpu: [arm64]
os: [win32]
- '@rollup/rollup-win32-arm64-msvc@4.60.2':
- resolution: {integrity: sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==}
+ '@rollup/rollup-win32-arm64-msvc@4.60.1':
+ resolution: {integrity: sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==}
cpu: [arm64]
os: [win32]
@@ -1184,8 +1220,8 @@ packages:
cpu: [ia32]
os: [win32]
- '@rollup/rollup-win32-ia32-msvc@4.60.2':
- resolution: {integrity: sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==}
+ '@rollup/rollup-win32-ia32-msvc@4.60.1':
+ resolution: {integrity: sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==}
cpu: [ia32]
os: [win32]
@@ -1194,8 +1230,8 @@ packages:
cpu: [x64]
os: [win32]
- '@rollup/rollup-win32-x64-gnu@4.60.2':
- resolution: {integrity: sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==}
+ '@rollup/rollup-win32-x64-gnu@4.60.1':
+ resolution: {integrity: sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==}
cpu: [x64]
os: [win32]
@@ -1204,8 +1240,8 @@ packages:
cpu: [x64]
os: [win32]
- '@rollup/rollup-win32-x64-msvc@4.60.2':
- resolution: {integrity: sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==}
+ '@rollup/rollup-win32-x64-msvc@4.60.1':
+ resolution: {integrity: sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==}
cpu: [x64]
os: [win32]
@@ -1242,6 +1278,15 @@ packages:
typescript:
optional: true
+ '@solana/addresses@6.6.0':
+ resolution: {integrity: sha512-P0sblHfk7vYfzo2aya/7JxqVDT/6gFvTON9MKS5XBKkgg7jbSUjMHTyhIxIrYPQegd483AuAqjcMp/psJBNnGA==}
+ engines: {node: '>=20.18.0'}
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@solana/addresses@6.8.0':
resolution: {integrity: sha512-xVlA0DNX1LVfTueVsbhxDDoqr1VxeXvgJEh2GcIN/vcJPhY3GE3AYtjTbJJmTDgPrzOccI0t6ElVb1gelJH/PQ==}
engines: {node: '>=20.18.0'}
@@ -1251,6 +1296,15 @@ packages:
typescript:
optional: true
+ '@solana/assertions@6.6.0':
+ resolution: {integrity: sha512-zzu3svXpssVJwPyHxzi1cWDL1xRN+iD1BhLK0EhATUgxjAdSP9HtKra0bisURRNLH4QuPp7HBzjEWaBUftc4nQ==}
+ engines: {node: '>=20.18.0'}
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@solana/assertions@6.8.0':
resolution: {integrity: sha512-OU6prCq39fSvGL8xY1C/9vhghasvAkMiRlituzJxzJpZRfpVRrwhzLd6P5NPAPoQ28qKcenA50kFdw9+ZyneJQ==}
engines: {node: '>=20.18.0'}
@@ -1260,6 +1314,15 @@ packages:
typescript:
optional: true
+ '@solana/codecs-core@6.6.0':
+ resolution: {integrity: sha512-sjVgIDnOp5ZTnrv7p1bq6UXm1uOTa8vVvm+tHdHiaBkYcCrcUx9XwAlODfpEW8GBXihdq7dYs6xwj+80jzjmeA==}
+ engines: {node: '>=20.18.0'}
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@solana/codecs-core@6.8.0':
resolution: {integrity: sha512-udFO8TrvzgROonwX3rY3E2SG675RehILNb4ZYcKlf1mL7vkDJ9bEJnBxi87AEwl8RWZFTl+MhT0MmrJnbpvdug==}
engines: {node: '>=20.18.0'}
@@ -1269,6 +1332,15 @@ packages:
typescript:
optional: true
+ '@solana/codecs-data-structures@6.6.0':
+ resolution: {integrity: sha512-EFv8HyANnvU9JaXqoXO480dxC+r+fV7FeUIbRuGJG5bUrhkfmHyMSV9w/GrMs6Jo4YgRHh8z5klrX6VR2od+xg==}
+ engines: {node: '>=20.18.0'}
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@solana/codecs-data-structures@6.8.0':
resolution: {integrity: sha512-lHr0F+nNwgm9c+tWQX398yzYh1qDi7QSCJpY9MQ2azW4FfY2IyPSo7bqzTaWNnJh9pmJx3ZI6jHfXBnLD5k/SQ==}
engines: {node: '>=20.18.0'}
@@ -1278,6 +1350,15 @@ packages:
typescript:
optional: true
+ '@solana/codecs-numbers@6.6.0':
+ resolution: {integrity: sha512-ykRsdKQgEgNL/ci4dhVIusG3KLiaQVDnjQecDmzlyTJ4EFMvCvvb9W3uCOwLKjSvCqPPj0NgSmpIIc/mahYhSQ==}
+ engines: {node: '>=20.18.0'}
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@solana/codecs-numbers@6.8.0':
resolution: {integrity: sha512-ebf4f1D19EAe0uhdUYOCEYnn5+EellsBxbJ42tM2yYEoIBVz5FoBBC0gSsq+UTNbQHFa7XagyBT3LewxXttiTQ==}
engines: {node: '>=20.18.0'}
@@ -1287,6 +1368,18 @@ packages:
typescript:
optional: true
+ '@solana/codecs-strings@6.6.0':
+ resolution: {integrity: sha512-YK1IzJyymuiKsEdYXqswt+CaZMJ8YcTwsQrUd4KfdUKUo1o1Bz3HxzTeuFfMqn0K+Yv+U5V7JVhO90gzJIMB2g==}
+ engines: {node: '>=20.18.0'}
+ peerDependencies:
+ fastestsmallesttextencoderdecoder: ^1.0.22
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ fastestsmallesttextencoderdecoder:
+ optional: true
+ typescript:
+ optional: true
+
'@solana/codecs-strings@6.8.0':
resolution: {integrity: sha512-Rpk5NVhbKYcPnE7wz3IpTp0GVNVs0IYKdmyzByiimgPTiII8eb8ay4wQiYHGHrpYh62hD14Qy3GiGDFgipRKqA==}
engines: {node: '>=20.18.0'}
@@ -1308,6 +1401,16 @@ packages:
typescript:
optional: true
+ '@solana/errors@6.6.0':
+ resolution: {integrity: sha512-8MlqxF3NWWT+nzvq08/7uPyx3u7zOGBR7ZmYvczWxM37pPcBmGEgsruWqw120Zk2Z1spzqOzXd/uTbXBxanH4Q==}
+ engines: {node: '>=20.18.0'}
+ hasBin: true
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@solana/errors@6.8.0':
resolution: {integrity: sha512-HRTrLgTn0c99GKz4v4IKgz2+6soaRY1mh2tLW4sk1Fe4Zzv85Q6ZLK1mXrVGL73z1apyHDrr9/Sd/9ZhUsUvpA==}
engines: {node: '>=20.18.0'}
@@ -1344,6 +1447,15 @@ packages:
typescript:
optional: true
+ '@solana/functional@6.6.0':
+ resolution: {integrity: sha512-Cmyr/fg3G5cbCJPQ2yB4qVJAUYghCRoQ0vjl1z88TV40S64h0xUCm8tiaMyJZeEjL2nKHzfCXhgbtnlpliRHmg==}
+ engines: {node: '>=20.18.0'}
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@solana/functional@6.8.0':
resolution: {integrity: sha512-oMSAD/8w9ujx7OplvwRWwHHFnaaxi/Xrji1XH3xAB+gzxupUpBbOmgxQ+e84x+9VN8QWk5aU3L7gmCqdTAR6OA==}
engines: {node: '>=20.18.0'}
@@ -1362,6 +1474,15 @@ packages:
typescript:
optional: true
+ '@solana/instructions@6.6.0':
+ resolution: {integrity: sha512-RMLFKlDbHXIN5RSd5j2dPv8dayHkASHiNzUVZjgd/IXdOw6MK32PfII3Uk5DYPRifEo74fUsX3VRZKK+TdTO1A==}
+ engines: {node: '>=20.18.0'}
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@solana/instructions@6.8.0':
resolution: {integrity: sha512-dTtykhS9IeN3npCfnd7wSS6KmKAh54+g90JRtLYy5/31L2Zvunf3AJz2QUk58vgsAGZ5fuoiMyhCxRJm4rHUBQ==}
engines: {node: '>=20.18.0'}
@@ -1371,6 +1492,15 @@ packages:
typescript:
optional: true
+ '@solana/keys@6.6.0':
+ resolution: {integrity: sha512-iXBnzFnuPnq6DgLIvVaEp0Y21nEkOUlcxEXPqKc+Wliqu2lOUiqfukETwlglomA/2Fo8QP3248jfFqcYWNaUeQ==}
+ engines: {node: '>=20.18.0'}
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@solana/keys@6.8.0':
resolution: {integrity: sha512-Wo8CnbrVfCP1Jbsb3ElMej/3dmMrl4ArPhI1mDcqIIz/O4j4HmxZYbn2BCWtnV9V/LPM638EMO2r1x6GzDNrPA==}
engines: {node: '>=20.18.0'}
@@ -1389,6 +1519,15 @@ packages:
typescript:
optional: true
+ '@solana/nominal-types@6.6.0':
+ resolution: {integrity: sha512-kKCOBf60iHop7qYs/cr+t4lQf6QQQ8wsko0tV42rfmAEsAHTnmGCGOeh9s8fq4Wd4NeolOi/4qVrWQo3B/cmcw==}
+ engines: {node: '>=20.18.0'}
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@solana/nominal-types@6.8.0':
resolution: {integrity: sha512-mLmHr92pM4mEfe49GUmZ5Ry0RMqtMuFQqZYnxQqhDKMcl+Wtt820ezxYgwPhqcMxRzfqaQSO3ZxpSB0RlLBa/Q==}
engines: {node: '>=20.18.0'}
@@ -1398,6 +1537,15 @@ packages:
typescript:
optional: true
+ '@solana/offchain-messages@6.6.0':
+ resolution: {integrity: sha512-g3ERmMxlJcVThJlRYSu7EtZ2JHE89LbbxwNGARPU8dRbDXzPkBJwbaka3JqbDlIBZEUnYsKiaaA6wYPvxpwQNw==}
+ engines: {node: '>=20.18.0'}
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@solana/offchain-messages@6.8.0':
resolution: {integrity: sha512-HoniTs2uoCHGicD0dTTJ3YBhLZC9URxdXXUf0CHalLFwAidF9iNuB8dsuKk16Euu68L4/ERKKGfyC0QobBvahw==}
engines: {node: '>=20.18.0'}
@@ -1457,6 +1605,15 @@ packages:
typescript:
optional: true
+ '@solana/promises@6.6.0':
+ resolution: {integrity: sha512-EVNVrHh9MiNHXAuvlloOxgTWElMJrC9IrgbfGro8T1v9epLJD953Q1Wi7kU5oT3hMRDZaJ31Gk2VUUdOjNQWgA==}
+ engines: {node: '>=20.18.0'}
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@solana/promises@6.8.0':
resolution: {integrity: sha512-kIypZG83ZbADbrAq9/LS7LuWlVxlgJSzIpic75+9IuAfC3k5/KSus8LrvggBkCzfAyIslrUh70iz4JcnzUZrOw==}
engines: {node: '>=20.18.0'}
@@ -1556,6 +1713,15 @@ packages:
typescript:
optional: true
+ '@solana/rpc-types@6.6.0':
+ resolution: {integrity: sha512-CGa9Nc9rJfLs7DgI8XdpCsabI3FnZW/XFMFM00eUOJcSQEff2PDC/IUkLvKY/5A++/xzA3EB5r3ck+b/ktPEpQ==}
+ engines: {node: '>=20.18.0'}
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@solana/rpc-types@6.8.0':
resolution: {integrity: sha512-vACMV9VR2JsZGDcgaMOFN/dwLK57CsE+erassxxtF12sSPXJooz+Vu1vyY2Yp2EkCc7mDf7BNkTKvSXajbt+Qw==}
engines: {node: '>=20.18.0'}
@@ -1574,6 +1740,15 @@ packages:
typescript:
optional: true
+ '@solana/signers@6.6.0':
+ resolution: {integrity: sha512-TL5ZscoF+y4QfN80cs3MndGLMijOFIFJKwuRRXEDtSUfd35O7w+TpK1Bmxd+YVCXZv+KYNTVKdon6QTLihP+QA==}
+ engines: {node: '>=20.18.0'}
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@solana/signers@6.8.0':
resolution: {integrity: sha512-7E1cAXBLOcz9kmHhzWdu5m3UJlJzxfwOl8irOMLJI6NnKB2EmU0B0h4I+Mlfs9w8Bfj0WQpUei21ammbNBq39g==}
engines: {node: '>=20.18.0'}
@@ -1610,6 +1785,15 @@ packages:
typescript:
optional: true
+ '@solana/transaction-messages@6.6.0':
+ resolution: {integrity: sha512-wxsS+7JKs6SzX/8ibuAp4UUNAR9/zeJmCUtD5sT7Cu9Fy3qGCmZhrxY9t265+UCMrAUZso5Lw7plIm4b2UuyUA==}
+ engines: {node: '>=20.18.0'}
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@solana/transaction-messages@6.8.0':
resolution: {integrity: sha512-jsJu9mAcN1x7onKOeC4WEvYP04UVcnkOYu/9bMe+S9jqjL+3DMy9kFZpV5FBl+TPuTNJrtOqc6Gc28hUWyyp1A==}
engines: {node: '>=20.18.0'}
@@ -1619,6 +1803,15 @@ packages:
typescript:
optional: true
+ '@solana/transactions@6.6.0':
+ resolution: {integrity: sha512-wAuqS64hcuwjc8ZIceX3+VeaM8DiO7LsmMfyJWDqolb79flUdDuLMg5yGU+bt29t3+ZBPNG4KPfIzs5y/7X2dQ==}
+ engines: {node: '>=20.18.0'}
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@solana/transactions@6.8.0':
resolution: {integrity: sha512-Q46m+o3C1yL2EIZBAP5B8ou2VZwHN9wTi+muIS6/giCKO3jwUtnTEbWcZEDMj2vxUb7P2WfwTluZb/VAWxlx7Q==}
engines: {node: '>=20.18.0'}
@@ -1628,6 +1821,23 @@ packages:
typescript:
optional: true
+ '@solana/wallet-account-signer@6.6.0':
+ resolution: {integrity: sha512-kdBSwBviUCWKtvTEaxnLMRfphu32b2SjdXPGQJvbb2ma8Sued9vRUb7JvjE81/Mka2NhtU5+C1UDh5wEHlNjQA==}
+ engines: {node: '>=20.18.0'}
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ '@solana/wallet-standard-chains@1.1.1':
+ resolution: {integrity: sha512-Us3TgL4eMVoVWhuC4UrePlYnpWN+lwteCBlhZDUhFZBJ5UMGh94mYPXno3Ho7+iHPYRtuCi/ePvPcYBqCGuBOw==}
+ engines: {node: '>=16'}
+
+ '@solana/wallet-standard-features@1.3.0':
+ resolution: {integrity: sha512-ZhpZtD+4VArf6RPitsVExvgkF+nGghd1rzPjd97GmBximpnt1rsUxMOEyoIEuH3XBxPyNB6Us7ha7RHWQR+abg==}
+ engines: {node: '>=16'}
+
'@standard-schema/spec@1.1.0':
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
@@ -1984,6 +2194,43 @@ packages:
'@vitest/utils@4.1.5':
resolution: {integrity: sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug==}
+ '@wallet-standard/app@1.1.0':
+ resolution: {integrity: sha512-3CijvrO9utx598kjr45hTbbeeykQrQfKmSnxeWOgU25TOEpvcipD/bYDQWIqUv1Oc6KK4YStokSMu/FBNecGUQ==}
+ engines: {node: '>=16'}
+
+ '@wallet-standard/base@1.1.0':
+ resolution: {integrity: sha512-DJDQhjKmSNVLKWItoKThJS+CsJQjR9AOBOirBVT1F9YpRyC9oYHE+ZnSf8y8bxUphtKqdQMPVQ2mHohYdRvDVQ==}
+ engines: {node: '>=16'}
+
+ '@wallet-standard/errors@0.1.1':
+ resolution: {integrity: sha512-V8Ju1Wvol8i/VDyQOHhjhxmMVwmKiwyxUZBnHhtiPZJTWY0U/Shb2iEWyGngYEbAkp2sGTmEeNX1tVyGR7PqNw==}
+ engines: {node: '>=16'}
+ hasBin: true
+
+ '@wallet-standard/features@1.1.0':
+ resolution: {integrity: sha512-hiEivWNztx73s+7iLxsuD1sOJ28xtRix58W7Xnz4XzzA/pF0+aicnWgjOdA10doVDEDZdUuZCIIqG96SFNlDUg==}
+ engines: {node: '>=16'}
+
+ '@wallet-standard/ui-compare@1.0.1':
+ resolution: {integrity: sha512-Qr6AjgxTgTNgjUm/HQend08jFCUJ2ugbONpbC1hSl4Ndul+theJV3CwVZ2ffKun584bHoR8OAibJ+QA4ecogEA==}
+ engines: {node: '>=16'}
+
+ '@wallet-standard/ui-core@1.0.0':
+ resolution: {integrity: sha512-pnpBfxJois0fIAI0IBJ6hopOguw81JniB6DzOs5J7C16W7/M2kC0OKHQFKrz6cgSGMq8X0bPA8nZTXFTSNbURg==}
+ engines: {node: '>=16'}
+
+ '@wallet-standard/ui-features@1.0.1':
+ resolution: {integrity: sha512-0/lZFx599bGcDEvisAWtbFMuRM/IuqP/o0vbhAeQdLWsWsaqFTUIKZtMt8JJq+fFBMQGc6tuRH6ehrgm+Y0biQ==}
+ engines: {node: '>=16'}
+
+ '@wallet-standard/ui-registry@1.0.1':
+ resolution: {integrity: sha512-+SeXEwSoyqEWv9B6JLxRioRlgN5ksSFObZMf+XKm2U+vwmc/mfm43I8zw5wvGBpubzmywbe2eejd5k/snyx+uA==}
+ engines: {node: '>=16'}
+
+ '@wallet-standard/ui@1.0.1':
+ resolution: {integrity: sha512-3b1iSfHOB3YpuBM645ZAgA0LMGZv+3Eh4y9lM3kS+NnvK4NxwnEdn1mLbFxevRhyulNjFZ50m2Cq5mpEOYs2mw==}
+ engines: {node: '>=16'}
+
acorn-jsx@5.3.2:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
@@ -2091,8 +2338,8 @@ packages:
resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
engines: {node: 18 || 20 || >=22}
- baseline-browser-mapping@2.10.20:
- resolution: {integrity: sha512-1AaXxEPfXT+GvTBJFuy4yXVHWJBXa4OdbIebGN/wX5DlsIkU0+wzGnd2lOzokSk51d5LUmqjgBLRLlypLUqInQ==}
+ baseline-browser-mapping@2.10.19:
+ resolution: {integrity: sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==}
engines: {node: '>=6.0.0'}
hasBin: true
@@ -2205,6 +2452,10 @@ packages:
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+ commander@13.1.0:
+ resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==}
+ engines: {node: '>=18'}
+
commander@14.0.3:
resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==}
engines: {node: '>=20'}
@@ -2308,8 +2559,8 @@ packages:
engines: {node: '>=18'}
hasBin: true
- esbuild@0.27.7:
- resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==}
+ esbuild@0.27.5:
+ resolution: {integrity: sha512-zdQoHBjuDqKsvV5OPaWansOwfSQ0Js+Uj9J85TBvj3bFW1JjWTSULMRwdQAc8qMeIScbClxeMK0jlrtB9linhA==}
engines: {node: '>=18'}
hasBin: true
@@ -3188,8 +3439,8 @@ packages:
yaml:
optional: true
- postcss@8.5.10:
- resolution: {integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==}
+ postcss@8.5.9:
+ resolution: {integrity: sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==}
engines: {node: ^10 || ^12 || >=14}
prelude-ls@1.2.1:
@@ -3273,8 +3524,8 @@ packages:
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
- rollup@4.60.2:
- resolution: {integrity: sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==}
+ rollup@4.60.1:
+ resolution: {integrity: sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
@@ -3876,7 +4127,7 @@ snapshots:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.28.6
- '@babel/runtime@7.29.2': {}
+ '@babel/runtime@7.28.6': {}
'@babel/template@7.28.6':
dependencies:
@@ -4061,18 +4312,18 @@ snapshots:
human-id: 4.1.3
prettier: 2.8.8
- '@emnapi/core@1.10.0':
+ '@emnapi/core@1.9.1':
dependencies:
- '@emnapi/wasi-threads': 1.2.1
+ '@emnapi/wasi-threads': 1.2.0
tslib: 2.8.1
optional: true
- '@emnapi/runtime@1.10.0':
+ '@emnapi/runtime@1.9.1':
dependencies:
tslib: 2.8.1
optional: true
- '@emnapi/wasi-threads@1.2.1':
+ '@emnapi/wasi-threads@1.2.0':
dependencies:
tslib: 2.8.1
optional: true
@@ -4080,157 +4331,157 @@ snapshots:
'@esbuild/aix-ppc64@0.27.2':
optional: true
- '@esbuild/aix-ppc64@0.27.7':
+ '@esbuild/aix-ppc64@0.27.5':
optional: true
'@esbuild/android-arm64@0.27.2':
optional: true
- '@esbuild/android-arm64@0.27.7':
+ '@esbuild/android-arm64@0.27.5':
optional: true
'@esbuild/android-arm@0.27.2':
optional: true
- '@esbuild/android-arm@0.27.7':
+ '@esbuild/android-arm@0.27.5':
optional: true
'@esbuild/android-x64@0.27.2':
optional: true
- '@esbuild/android-x64@0.27.7':
+ '@esbuild/android-x64@0.27.5':
optional: true
'@esbuild/darwin-arm64@0.27.2':
optional: true
- '@esbuild/darwin-arm64@0.27.7':
+ '@esbuild/darwin-arm64@0.27.5':
optional: true
'@esbuild/darwin-x64@0.27.2':
optional: true
- '@esbuild/darwin-x64@0.27.7':
+ '@esbuild/darwin-x64@0.27.5':
optional: true
'@esbuild/freebsd-arm64@0.27.2':
optional: true
- '@esbuild/freebsd-arm64@0.27.7':
+ '@esbuild/freebsd-arm64@0.27.5':
optional: true
'@esbuild/freebsd-x64@0.27.2':
optional: true
- '@esbuild/freebsd-x64@0.27.7':
+ '@esbuild/freebsd-x64@0.27.5':
optional: true
'@esbuild/linux-arm64@0.27.2':
optional: true
- '@esbuild/linux-arm64@0.27.7':
+ '@esbuild/linux-arm64@0.27.5':
optional: true
'@esbuild/linux-arm@0.27.2':
optional: true
- '@esbuild/linux-arm@0.27.7':
+ '@esbuild/linux-arm@0.27.5':
optional: true
'@esbuild/linux-ia32@0.27.2':
optional: true
- '@esbuild/linux-ia32@0.27.7':
+ '@esbuild/linux-ia32@0.27.5':
optional: true
'@esbuild/linux-loong64@0.27.2':
optional: true
- '@esbuild/linux-loong64@0.27.7':
+ '@esbuild/linux-loong64@0.27.5':
optional: true
'@esbuild/linux-mips64el@0.27.2':
optional: true
- '@esbuild/linux-mips64el@0.27.7':
+ '@esbuild/linux-mips64el@0.27.5':
optional: true
'@esbuild/linux-ppc64@0.27.2':
optional: true
- '@esbuild/linux-ppc64@0.27.7':
+ '@esbuild/linux-ppc64@0.27.5':
optional: true
'@esbuild/linux-riscv64@0.27.2':
optional: true
- '@esbuild/linux-riscv64@0.27.7':
+ '@esbuild/linux-riscv64@0.27.5':
optional: true
'@esbuild/linux-s390x@0.27.2':
optional: true
- '@esbuild/linux-s390x@0.27.7':
+ '@esbuild/linux-s390x@0.27.5':
optional: true
'@esbuild/linux-x64@0.27.2':
optional: true
- '@esbuild/linux-x64@0.27.7':
+ '@esbuild/linux-x64@0.27.5':
optional: true
'@esbuild/netbsd-arm64@0.27.2':
optional: true
- '@esbuild/netbsd-arm64@0.27.7':
+ '@esbuild/netbsd-arm64@0.27.5':
optional: true
'@esbuild/netbsd-x64@0.27.2':
optional: true
- '@esbuild/netbsd-x64@0.27.7':
+ '@esbuild/netbsd-x64@0.27.5':
optional: true
'@esbuild/openbsd-arm64@0.27.2':
optional: true
- '@esbuild/openbsd-arm64@0.27.7':
+ '@esbuild/openbsd-arm64@0.27.5':
optional: true
'@esbuild/openbsd-x64@0.27.2':
optional: true
- '@esbuild/openbsd-x64@0.27.7':
+ '@esbuild/openbsd-x64@0.27.5':
optional: true
'@esbuild/openharmony-arm64@0.27.2':
optional: true
- '@esbuild/openharmony-arm64@0.27.7':
+ '@esbuild/openharmony-arm64@0.27.5':
optional: true
'@esbuild/sunos-x64@0.27.2':
optional: true
- '@esbuild/sunos-x64@0.27.7':
+ '@esbuild/sunos-x64@0.27.5':
optional: true
'@esbuild/win32-arm64@0.27.2':
optional: true
- '@esbuild/win32-arm64@0.27.7':
+ '@esbuild/win32-arm64@0.27.5':
optional: true
'@esbuild/win32-ia32@0.27.2':
optional: true
- '@esbuild/win32-ia32@0.27.7':
+ '@esbuild/win32-ia32@0.27.5':
optional: true
'@esbuild/win32-x64@0.27.2':
optional: true
- '@esbuild/win32-x64@0.27.7':
+ '@esbuild/win32-x64@0.27.5':
optional: true
'@eslint-community/eslint-utils@4.9.0(eslint@9.39.2)':
@@ -4523,14 +4774,14 @@ snapshots:
'@manypkg/find-root@1.1.0':
dependencies:
- '@babel/runtime': 7.29.2
+ '@babel/runtime': 7.28.6
'@types/node': 12.20.55
find-up: 4.1.0
fs-extra: 8.1.0
'@manypkg/get-packages@1.1.3':
dependencies:
- '@babel/runtime': 7.29.2
+ '@babel/runtime': 7.28.6
'@changesets/types': 4.1.0
'@manypkg/find-root': 1.1.0
fs-extra: 8.1.0
@@ -4539,8 +4790,8 @@ snapshots:
'@napi-rs/wasm-runtime@0.2.12':
dependencies:
- '@emnapi/core': 1.10.0
- '@emnapi/runtime': 1.10.0
+ '@emnapi/core': 1.9.1
+ '@emnapi/runtime': 1.9.1
'@tybys/wasm-util': 0.10.1
optional: true
@@ -4568,142 +4819,142 @@ snapshots:
'@rollup/rollup-android-arm-eabi@4.53.5':
optional: true
- '@rollup/rollup-android-arm-eabi@4.60.2':
+ '@rollup/rollup-android-arm-eabi@4.60.1':
optional: true
'@rollup/rollup-android-arm64@4.53.5':
optional: true
- '@rollup/rollup-android-arm64@4.60.2':
+ '@rollup/rollup-android-arm64@4.60.1':
optional: true
'@rollup/rollup-darwin-arm64@4.53.5':
optional: true
- '@rollup/rollup-darwin-arm64@4.60.2':
+ '@rollup/rollup-darwin-arm64@4.60.1':
optional: true
'@rollup/rollup-darwin-x64@4.53.5':
optional: true
- '@rollup/rollup-darwin-x64@4.60.2':
+ '@rollup/rollup-darwin-x64@4.60.1':
optional: true
'@rollup/rollup-freebsd-arm64@4.53.5':
optional: true
- '@rollup/rollup-freebsd-arm64@4.60.2':
+ '@rollup/rollup-freebsd-arm64@4.60.1':
optional: true
'@rollup/rollup-freebsd-x64@4.53.5':
optional: true
- '@rollup/rollup-freebsd-x64@4.60.2':
+ '@rollup/rollup-freebsd-x64@4.60.1':
optional: true
'@rollup/rollup-linux-arm-gnueabihf@4.53.5':
optional: true
- '@rollup/rollup-linux-arm-gnueabihf@4.60.2':
+ '@rollup/rollup-linux-arm-gnueabihf@4.60.1':
optional: true
'@rollup/rollup-linux-arm-musleabihf@4.53.5':
optional: true
- '@rollup/rollup-linux-arm-musleabihf@4.60.2':
+ '@rollup/rollup-linux-arm-musleabihf@4.60.1':
optional: true
'@rollup/rollup-linux-arm64-gnu@4.53.5':
optional: true
- '@rollup/rollup-linux-arm64-gnu@4.60.2':
+ '@rollup/rollup-linux-arm64-gnu@4.60.1':
optional: true
'@rollup/rollup-linux-arm64-musl@4.53.5':
optional: true
- '@rollup/rollup-linux-arm64-musl@4.60.2':
+ '@rollup/rollup-linux-arm64-musl@4.60.1':
optional: true
'@rollup/rollup-linux-loong64-gnu@4.53.5':
optional: true
- '@rollup/rollup-linux-loong64-gnu@4.60.2':
+ '@rollup/rollup-linux-loong64-gnu@4.60.1':
optional: true
- '@rollup/rollup-linux-loong64-musl@4.60.2':
+ '@rollup/rollup-linux-loong64-musl@4.60.1':
optional: true
'@rollup/rollup-linux-ppc64-gnu@4.53.5':
optional: true
- '@rollup/rollup-linux-ppc64-gnu@4.60.2':
+ '@rollup/rollup-linux-ppc64-gnu@4.60.1':
optional: true
- '@rollup/rollup-linux-ppc64-musl@4.60.2':
+ '@rollup/rollup-linux-ppc64-musl@4.60.1':
optional: true
'@rollup/rollup-linux-riscv64-gnu@4.53.5':
optional: true
- '@rollup/rollup-linux-riscv64-gnu@4.60.2':
+ '@rollup/rollup-linux-riscv64-gnu@4.60.1':
optional: true
'@rollup/rollup-linux-riscv64-musl@4.53.5':
optional: true
- '@rollup/rollup-linux-riscv64-musl@4.60.2':
+ '@rollup/rollup-linux-riscv64-musl@4.60.1':
optional: true
'@rollup/rollup-linux-s390x-gnu@4.53.5':
optional: true
- '@rollup/rollup-linux-s390x-gnu@4.60.2':
+ '@rollup/rollup-linux-s390x-gnu@4.60.1':
optional: true
'@rollup/rollup-linux-x64-gnu@4.53.5':
optional: true
- '@rollup/rollup-linux-x64-gnu@4.60.2':
+ '@rollup/rollup-linux-x64-gnu@4.60.1':
optional: true
'@rollup/rollup-linux-x64-musl@4.53.5':
optional: true
- '@rollup/rollup-linux-x64-musl@4.60.2':
+ '@rollup/rollup-linux-x64-musl@4.60.1':
optional: true
- '@rollup/rollup-openbsd-x64@4.60.2':
+ '@rollup/rollup-openbsd-x64@4.60.1':
optional: true
'@rollup/rollup-openharmony-arm64@4.53.5':
optional: true
- '@rollup/rollup-openharmony-arm64@4.60.2':
+ '@rollup/rollup-openharmony-arm64@4.60.1':
optional: true
'@rollup/rollup-win32-arm64-msvc@4.53.5':
optional: true
- '@rollup/rollup-win32-arm64-msvc@4.60.2':
+ '@rollup/rollup-win32-arm64-msvc@4.60.1':
optional: true
'@rollup/rollup-win32-ia32-msvc@4.53.5':
optional: true
- '@rollup/rollup-win32-ia32-msvc@4.60.2':
+ '@rollup/rollup-win32-ia32-msvc@4.60.1':
optional: true
'@rollup/rollup-win32-x64-gnu@4.53.5':
optional: true
- '@rollup/rollup-win32-x64-gnu@4.60.2':
+ '@rollup/rollup-win32-x64-gnu@4.60.1':
optional: true
'@rollup/rollup-win32-x64-msvc@4.53.5':
optional: true
- '@rollup/rollup-win32-x64-msvc@4.60.2':
+ '@rollup/rollup-win32-x64-msvc@4.60.1':
optional: true
'@sinclair/typebox@0.34.49': {}
@@ -4743,6 +4994,18 @@ snapshots:
transitivePeerDependencies:
- fastestsmallesttextencoderdecoder
+ '@solana/addresses@6.6.0(typescript@5.9.3)':
+ dependencies:
+ '@solana/assertions': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-core': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-strings': 6.6.0(typescript@5.9.3)
+ '@solana/errors': 6.6.0(typescript@5.9.3)
+ '@solana/nominal-types': 6.6.0(typescript@5.9.3)
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - fastestsmallesttextencoderdecoder
+
'@solana/addresses@6.8.0(typescript@5.9.3)':
dependencies:
'@solana/assertions': 6.8.0(typescript@5.9.3)
@@ -4755,18 +5018,38 @@ snapshots:
transitivePeerDependencies:
- fastestsmallesttextencoderdecoder
+ '@solana/assertions@6.6.0(typescript@5.9.3)':
+ dependencies:
+ '@solana/errors': 6.6.0(typescript@5.9.3)
+ optionalDependencies:
+ typescript: 5.9.3
+
'@solana/assertions@6.8.0(typescript@5.9.3)':
dependencies:
'@solana/errors': 6.8.0(typescript@5.9.3)
optionalDependencies:
typescript: 5.9.3
+ '@solana/codecs-core@6.6.0(typescript@5.9.3)':
+ dependencies:
+ '@solana/errors': 6.6.0(typescript@5.9.3)
+ optionalDependencies:
+ typescript: 5.9.3
+
'@solana/codecs-core@6.8.0(typescript@5.9.3)':
dependencies:
'@solana/errors': 6.8.0(typescript@5.9.3)
optionalDependencies:
typescript: 5.9.3
+ '@solana/codecs-data-structures@6.6.0(typescript@5.9.3)':
+ dependencies:
+ '@solana/codecs-core': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-numbers': 6.6.0(typescript@5.9.3)
+ '@solana/errors': 6.6.0(typescript@5.9.3)
+ optionalDependencies:
+ typescript: 5.9.3
+
'@solana/codecs-data-structures@6.8.0(typescript@5.9.3)':
dependencies:
'@solana/codecs-core': 6.8.0(typescript@5.9.3)
@@ -4775,6 +5058,13 @@ snapshots:
optionalDependencies:
typescript: 5.9.3
+ '@solana/codecs-numbers@6.6.0(typescript@5.9.3)':
+ dependencies:
+ '@solana/codecs-core': 6.6.0(typescript@5.9.3)
+ '@solana/errors': 6.6.0(typescript@5.9.3)
+ optionalDependencies:
+ typescript: 5.9.3
+
'@solana/codecs-numbers@6.8.0(typescript@5.9.3)':
dependencies:
'@solana/codecs-core': 6.8.0(typescript@5.9.3)
@@ -4782,6 +5072,14 @@ snapshots:
optionalDependencies:
typescript: 5.9.3
+ '@solana/codecs-strings@6.6.0(typescript@5.9.3)':
+ dependencies:
+ '@solana/codecs-core': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-numbers': 6.6.0(typescript@5.9.3)
+ '@solana/errors': 6.6.0(typescript@5.9.3)
+ optionalDependencies:
+ typescript: 5.9.3
+
'@solana/codecs-strings@6.8.0(typescript@5.9.3)':
dependencies:
'@solana/codecs-core': 6.8.0(typescript@5.9.3)
@@ -4802,6 +5100,13 @@ snapshots:
transitivePeerDependencies:
- fastestsmallesttextencoderdecoder
+ '@solana/errors@6.6.0(typescript@5.9.3)':
+ dependencies:
+ chalk: 5.6.2
+ commander: 14.0.3
+ optionalDependencies:
+ typescript: 5.9.3
+
'@solana/errors@6.8.0(typescript@5.9.3)':
dependencies:
chalk: 5.6.2
@@ -4829,6 +5134,10 @@ snapshots:
optionalDependencies:
typescript: 5.9.3
+ '@solana/functional@6.6.0(typescript@5.9.3)':
+ optionalDependencies:
+ typescript: 5.9.3
+
'@solana/functional@6.8.0(typescript@5.9.3)':
optionalDependencies:
typescript: 5.9.3
@@ -4846,6 +5155,13 @@ snapshots:
transitivePeerDependencies:
- fastestsmallesttextencoderdecoder
+ '@solana/instructions@6.6.0(typescript@5.9.3)':
+ dependencies:
+ '@solana/codecs-core': 6.6.0(typescript@5.9.3)
+ '@solana/errors': 6.6.0(typescript@5.9.3)
+ optionalDependencies:
+ typescript: 5.9.3
+
'@solana/instructions@6.8.0(typescript@5.9.3)':
dependencies:
'@solana/codecs-core': 6.8.0(typescript@5.9.3)
@@ -4853,6 +5169,18 @@ snapshots:
optionalDependencies:
typescript: 5.9.3
+ '@solana/keys@6.6.0(typescript@5.9.3)':
+ dependencies:
+ '@solana/assertions': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-core': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-strings': 6.6.0(typescript@5.9.3)
+ '@solana/errors': 6.6.0(typescript@5.9.3)
+ '@solana/nominal-types': 6.6.0(typescript@5.9.3)
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - fastestsmallesttextencoderdecoder
+
'@solana/keys@6.8.0(typescript@5.9.3)':
dependencies:
'@solana/assertions': 6.8.0(typescript@5.9.3)
@@ -4900,10 +5228,29 @@ snapshots:
- fastestsmallesttextencoderdecoder
- utf-8-validate
+ '@solana/nominal-types@6.6.0(typescript@5.9.3)':
+ optionalDependencies:
+ typescript: 5.9.3
+
'@solana/nominal-types@6.8.0(typescript@5.9.3)':
optionalDependencies:
typescript: 5.9.3
+ '@solana/offchain-messages@6.6.0(typescript@5.9.3)':
+ dependencies:
+ '@solana/addresses': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-core': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-data-structures': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-numbers': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-strings': 6.6.0(typescript@5.9.3)
+ '@solana/errors': 6.6.0(typescript@5.9.3)
+ '@solana/keys': 6.6.0(typescript@5.9.3)
+ '@solana/nominal-types': 6.6.0(typescript@5.9.3)
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - fastestsmallesttextencoderdecoder
+
'@solana/offchain-messages@6.8.0(typescript@5.9.3)':
dependencies:
'@solana/addresses': 6.8.0(typescript@5.9.3)
@@ -4978,6 +5325,10 @@ snapshots:
transitivePeerDependencies:
- fastestsmallesttextencoderdecoder
+ '@solana/promises@6.6.0(typescript@5.9.3)':
+ optionalDependencies:
+ typescript: 5.9.3
+
'@solana/promises@6.8.0(typescript@5.9.3)':
optionalDependencies:
typescript: 5.9.3
@@ -5092,6 +5443,19 @@ snapshots:
optionalDependencies:
typescript: 5.9.3
+ '@solana/rpc-types@6.6.0(typescript@5.9.3)':
+ dependencies:
+ '@solana/addresses': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-core': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-numbers': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-strings': 6.6.0(typescript@5.9.3)
+ '@solana/errors': 6.6.0(typescript@5.9.3)
+ '@solana/nominal-types': 6.6.0(typescript@5.9.3)
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - fastestsmallesttextencoderdecoder
+
'@solana/rpc-types@6.8.0(typescript@5.9.3)':
dependencies:
'@solana/addresses': 6.8.0(typescript@5.9.3)
@@ -5121,6 +5485,22 @@ snapshots:
transitivePeerDependencies:
- fastestsmallesttextencoderdecoder
+ '@solana/signers@6.6.0(typescript@5.9.3)':
+ dependencies:
+ '@solana/addresses': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-core': 6.6.0(typescript@5.9.3)
+ '@solana/errors': 6.6.0(typescript@5.9.3)
+ '@solana/instructions': 6.6.0(typescript@5.9.3)
+ '@solana/keys': 6.6.0(typescript@5.9.3)
+ '@solana/nominal-types': 6.6.0(typescript@5.9.3)
+ '@solana/offchain-messages': 6.6.0(typescript@5.9.3)
+ '@solana/transaction-messages': 6.6.0(typescript@5.9.3)
+ '@solana/transactions': 6.6.0(typescript@5.9.3)
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - fastestsmallesttextencoderdecoder
+
'@solana/signers@6.8.0(typescript@5.9.3)':
dependencies:
'@solana/addresses': 6.8.0(typescript@5.9.3)
@@ -5175,6 +5555,22 @@ snapshots:
- fastestsmallesttextencoderdecoder
- utf-8-validate
+ '@solana/transaction-messages@6.6.0(typescript@5.9.3)':
+ dependencies:
+ '@solana/addresses': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-core': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-data-structures': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-numbers': 6.6.0(typescript@5.9.3)
+ '@solana/errors': 6.6.0(typescript@5.9.3)
+ '@solana/functional': 6.6.0(typescript@5.9.3)
+ '@solana/instructions': 6.6.0(typescript@5.9.3)
+ '@solana/nominal-types': 6.6.0(typescript@5.9.3)
+ '@solana/rpc-types': 6.6.0(typescript@5.9.3)
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - fastestsmallesttextencoderdecoder
+
'@solana/transaction-messages@6.8.0(typescript@5.9.3)':
dependencies:
'@solana/addresses': 6.8.0(typescript@5.9.3)
@@ -5191,6 +5587,25 @@ snapshots:
transitivePeerDependencies:
- fastestsmallesttextencoderdecoder
+ '@solana/transactions@6.6.0(typescript@5.9.3)':
+ dependencies:
+ '@solana/addresses': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-core': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-data-structures': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-numbers': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-strings': 6.6.0(typescript@5.9.3)
+ '@solana/errors': 6.6.0(typescript@5.9.3)
+ '@solana/functional': 6.6.0(typescript@5.9.3)
+ '@solana/instructions': 6.6.0(typescript@5.9.3)
+ '@solana/keys': 6.6.0(typescript@5.9.3)
+ '@solana/nominal-types': 6.6.0(typescript@5.9.3)
+ '@solana/rpc-types': 6.6.0(typescript@5.9.3)
+ '@solana/transaction-messages': 6.6.0(typescript@5.9.3)
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - fastestsmallesttextencoderdecoder
+
'@solana/transactions@6.8.0(typescript@5.9.3)':
dependencies:
'@solana/addresses': 6.8.0(typescript@5.9.3)
@@ -5210,6 +5625,34 @@ snapshots:
transitivePeerDependencies:
- fastestsmallesttextencoderdecoder
+ '@solana/wallet-account-signer@6.6.0(typescript@5.9.3)':
+ dependencies:
+ '@solana/addresses': 6.6.0(typescript@5.9.3)
+ '@solana/codecs-core': 6.6.0(typescript@5.9.3)
+ '@solana/keys': 6.6.0(typescript@5.9.3)
+ '@solana/promises': 6.6.0(typescript@5.9.3)
+ '@solana/signers': 6.6.0(typescript@5.9.3)
+ '@solana/transaction-messages': 6.6.0(typescript@5.9.3)
+ '@solana/transactions': 6.6.0(typescript@5.9.3)
+ '@solana/wallet-standard-chains': 1.1.1
+ '@solana/wallet-standard-features': 1.3.0
+ '@wallet-standard/errors': 0.1.1
+ '@wallet-standard/ui': 1.0.1
+ '@wallet-standard/ui-registry': 1.0.1
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - fastestsmallesttextencoderdecoder
+
+ '@solana/wallet-standard-chains@1.1.1':
+ dependencies:
+ '@wallet-standard/base': 1.1.0
+
+ '@solana/wallet-standard-features@1.3.0':
+ dependencies:
+ '@wallet-standard/base': 1.1.0
+ '@wallet-standard/features': 1.1.0
+
'@standard-schema/spec@1.1.0': {}
'@turbo/darwin-64@2.9.6':
@@ -5601,6 +6044,50 @@ snapshots:
convert-source-map: 2.0.0
tinyrainbow: 3.1.0
+ '@wallet-standard/app@1.1.0':
+ dependencies:
+ '@wallet-standard/base': 1.1.0
+
+ '@wallet-standard/base@1.1.0': {}
+
+ '@wallet-standard/errors@0.1.1':
+ dependencies:
+ chalk: 5.6.2
+ commander: 13.1.0
+
+ '@wallet-standard/features@1.1.0':
+ dependencies:
+ '@wallet-standard/base': 1.1.0
+
+ '@wallet-standard/ui-compare@1.0.1':
+ dependencies:
+ '@wallet-standard/base': 1.1.0
+ '@wallet-standard/ui-core': 1.0.0
+ '@wallet-standard/ui-registry': 1.0.1
+
+ '@wallet-standard/ui-core@1.0.0':
+ dependencies:
+ '@wallet-standard/base': 1.1.0
+
+ '@wallet-standard/ui-features@1.0.1':
+ dependencies:
+ '@wallet-standard/base': 1.1.0
+ '@wallet-standard/errors': 0.1.1
+ '@wallet-standard/ui-core': 1.0.0
+ '@wallet-standard/ui-registry': 1.0.1
+
+ '@wallet-standard/ui-registry@1.0.1':
+ dependencies:
+ '@wallet-standard/base': 1.1.0
+ '@wallet-standard/errors': 0.1.1
+ '@wallet-standard/ui-core': 1.0.0
+
+ '@wallet-standard/ui@1.0.1':
+ dependencies:
+ '@wallet-standard/ui-compare': 1.0.1
+ '@wallet-standard/ui-core': 1.0.0
+ '@wallet-standard/ui-features': 1.0.1
+
acorn-jsx@5.3.2(acorn@7.4.1):
dependencies:
acorn: 7.4.1
@@ -5721,7 +6208,7 @@ snapshots:
balanced-match@4.0.4: {}
- baseline-browser-mapping@2.10.20: {}
+ baseline-browser-mapping@2.10.19: {}
better-path-resolve@1.0.0:
dependencies:
@@ -5755,7 +6242,7 @@ snapshots:
browserslist@4.28.2:
dependencies:
- baseline-browser-mapping: 2.10.20
+ baseline-browser-mapping: 2.10.19
caniuse-lite: 1.0.30001790
electron-to-chromium: 1.5.343
node-releases: 2.0.38
@@ -5819,6 +6306,8 @@ snapshots:
color-name@1.1.4: {}
+ commander@13.1.0: {}
+
commander@14.0.3: {}
commander@4.1.1: {}
@@ -5911,34 +6400,34 @@ snapshots:
'@esbuild/win32-ia32': 0.27.2
'@esbuild/win32-x64': 0.27.2
- esbuild@0.27.7:
+ esbuild@0.27.5:
optionalDependencies:
- '@esbuild/aix-ppc64': 0.27.7
- '@esbuild/android-arm': 0.27.7
- '@esbuild/android-arm64': 0.27.7
- '@esbuild/android-x64': 0.27.7
- '@esbuild/darwin-arm64': 0.27.7
- '@esbuild/darwin-x64': 0.27.7
- '@esbuild/freebsd-arm64': 0.27.7
- '@esbuild/freebsd-x64': 0.27.7
- '@esbuild/linux-arm': 0.27.7
- '@esbuild/linux-arm64': 0.27.7
- '@esbuild/linux-ia32': 0.27.7
- '@esbuild/linux-loong64': 0.27.7
- '@esbuild/linux-mips64el': 0.27.7
- '@esbuild/linux-ppc64': 0.27.7
- '@esbuild/linux-riscv64': 0.27.7
- '@esbuild/linux-s390x': 0.27.7
- '@esbuild/linux-x64': 0.27.7
- '@esbuild/netbsd-arm64': 0.27.7
- '@esbuild/netbsd-x64': 0.27.7
- '@esbuild/openbsd-arm64': 0.27.7
- '@esbuild/openbsd-x64': 0.27.7
- '@esbuild/openharmony-arm64': 0.27.7
- '@esbuild/sunos-x64': 0.27.7
- '@esbuild/win32-arm64': 0.27.7
- '@esbuild/win32-ia32': 0.27.7
- '@esbuild/win32-x64': 0.27.7
+ '@esbuild/aix-ppc64': 0.27.5
+ '@esbuild/android-arm': 0.27.5
+ '@esbuild/android-arm64': 0.27.5
+ '@esbuild/android-x64': 0.27.5
+ '@esbuild/darwin-arm64': 0.27.5
+ '@esbuild/darwin-x64': 0.27.5
+ '@esbuild/freebsd-arm64': 0.27.5
+ '@esbuild/freebsd-x64': 0.27.5
+ '@esbuild/linux-arm': 0.27.5
+ '@esbuild/linux-arm64': 0.27.5
+ '@esbuild/linux-ia32': 0.27.5
+ '@esbuild/linux-loong64': 0.27.5
+ '@esbuild/linux-mips64el': 0.27.5
+ '@esbuild/linux-ppc64': 0.27.5
+ '@esbuild/linux-riscv64': 0.27.5
+ '@esbuild/linux-s390x': 0.27.5
+ '@esbuild/linux-x64': 0.27.5
+ '@esbuild/netbsd-arm64': 0.27.5
+ '@esbuild/netbsd-x64': 0.27.5
+ '@esbuild/openbsd-arm64': 0.27.5
+ '@esbuild/openbsd-x64': 0.27.5
+ '@esbuild/openharmony-arm64': 0.27.5
+ '@esbuild/sunos-x64': 0.27.5
+ '@esbuild/win32-arm64': 0.27.5
+ '@esbuild/win32-ia32': 0.27.5
+ '@esbuild/win32-x64': 0.27.5
escalade@3.2.0: {}
@@ -6961,13 +7450,13 @@ snapshots:
mlly: 1.8.0
pathe: 2.0.3
- postcss-load-config@6.0.1(postcss@8.5.10):
+ postcss-load-config@6.0.1(postcss@8.5.9):
dependencies:
lilconfig: 3.1.3
optionalDependencies:
- postcss: 8.5.10
+ postcss: 8.5.9
- postcss@8.5.10:
+ postcss@8.5.9:
dependencies:
nanoid: 3.3.11
picocolors: 1.1.1
@@ -7055,35 +7544,35 @@ snapshots:
'@rollup/rollup-win32-x64-msvc': 4.53.5
fsevents: 2.3.3
- rollup@4.60.2:
+ rollup@4.60.1:
dependencies:
'@types/estree': 1.0.8
optionalDependencies:
- '@rollup/rollup-android-arm-eabi': 4.60.2
- '@rollup/rollup-android-arm64': 4.60.2
- '@rollup/rollup-darwin-arm64': 4.60.2
- '@rollup/rollup-darwin-x64': 4.60.2
- '@rollup/rollup-freebsd-arm64': 4.60.2
- '@rollup/rollup-freebsd-x64': 4.60.2
- '@rollup/rollup-linux-arm-gnueabihf': 4.60.2
- '@rollup/rollup-linux-arm-musleabihf': 4.60.2
- '@rollup/rollup-linux-arm64-gnu': 4.60.2
- '@rollup/rollup-linux-arm64-musl': 4.60.2
- '@rollup/rollup-linux-loong64-gnu': 4.60.2
- '@rollup/rollup-linux-loong64-musl': 4.60.2
- '@rollup/rollup-linux-ppc64-gnu': 4.60.2
- '@rollup/rollup-linux-ppc64-musl': 4.60.2
- '@rollup/rollup-linux-riscv64-gnu': 4.60.2
- '@rollup/rollup-linux-riscv64-musl': 4.60.2
- '@rollup/rollup-linux-s390x-gnu': 4.60.2
- '@rollup/rollup-linux-x64-gnu': 4.60.2
- '@rollup/rollup-linux-x64-musl': 4.60.2
- '@rollup/rollup-openbsd-x64': 4.60.2
- '@rollup/rollup-openharmony-arm64': 4.60.2
- '@rollup/rollup-win32-arm64-msvc': 4.60.2
- '@rollup/rollup-win32-ia32-msvc': 4.60.2
- '@rollup/rollup-win32-x64-gnu': 4.60.2
- '@rollup/rollup-win32-x64-msvc': 4.60.2
+ '@rollup/rollup-android-arm-eabi': 4.60.1
+ '@rollup/rollup-android-arm64': 4.60.1
+ '@rollup/rollup-darwin-arm64': 4.60.1
+ '@rollup/rollup-darwin-x64': 4.60.1
+ '@rollup/rollup-freebsd-arm64': 4.60.1
+ '@rollup/rollup-freebsd-x64': 4.60.1
+ '@rollup/rollup-linux-arm-gnueabihf': 4.60.1
+ '@rollup/rollup-linux-arm-musleabihf': 4.60.1
+ '@rollup/rollup-linux-arm64-gnu': 4.60.1
+ '@rollup/rollup-linux-arm64-musl': 4.60.1
+ '@rollup/rollup-linux-loong64-gnu': 4.60.1
+ '@rollup/rollup-linux-loong64-musl': 4.60.1
+ '@rollup/rollup-linux-ppc64-gnu': 4.60.1
+ '@rollup/rollup-linux-ppc64-musl': 4.60.1
+ '@rollup/rollup-linux-riscv64-gnu': 4.60.1
+ '@rollup/rollup-linux-riscv64-musl': 4.60.1
+ '@rollup/rollup-linux-s390x-gnu': 4.60.1
+ '@rollup/rollup-linux-x64-gnu': 4.60.1
+ '@rollup/rollup-linux-x64-musl': 4.60.1
+ '@rollup/rollup-openbsd-x64': 4.60.1
+ '@rollup/rollup-openharmony-arm64': 4.60.1
+ '@rollup/rollup-win32-arm64-msvc': 4.60.1
+ '@rollup/rollup-win32-ia32-msvc': 4.60.1
+ '@rollup/rollup-win32-x64-gnu': 4.60.1
+ '@rollup/rollup-win32-x64-msvc': 4.60.1
fsevents: 2.3.3
run-parallel@1.2.0:
@@ -7246,7 +7735,7 @@ snapshots:
tslib@2.8.1:
optional: true
- tsup@8.5.1(postcss@8.5.10)(typescript@5.9.3):
+ tsup@8.5.1(postcss@8.5.9)(typescript@5.9.3):
dependencies:
bundle-require: 5.1.0(esbuild@0.27.2)
cac: 6.7.14
@@ -7257,7 +7746,7 @@ snapshots:
fix-dts-default-cjs-exports: 1.0.1
joycon: 3.1.1
picocolors: 1.1.1
- postcss-load-config: 6.0.1(postcss@8.5.10)
+ postcss-load-config: 6.0.1(postcss@8.5.9)
resolve-from: 5.0.0
rollup: 4.53.5
source-map: 0.7.6
@@ -7266,7 +7755,7 @@ snapshots:
tinyglobby: 0.2.15
tree-kill: 1.2.2
optionalDependencies:
- postcss: 8.5.10
+ postcss: 8.5.9
typescript: 5.9.3
transitivePeerDependencies:
- jiti
@@ -7359,11 +7848,11 @@ snapshots:
vite@7.3.1(@types/node@25.6.0):
dependencies:
- esbuild: 0.27.7
+ esbuild: 0.27.5
fdir: 6.5.0(picomatch@4.0.4)
picomatch: 4.0.4
- postcss: 8.5.10
- rollup: 4.60.2
+ postcss: 8.5.9
+ rollup: 4.60.1
tinyglobby: 0.2.16
optionalDependencies:
'@types/node': 25.6.0
diff --git a/wallet-plugin-spec.md b/wallet-plugin-spec.md
new file mode 100644
index 0000000..76ce266
--- /dev/null
+++ b/wallet-plugin-spec.md
@@ -0,0 +1,1319 @@
+# RFC: `wallet` Plugin for Kit
+
+**Status:** Draft
+**Package:** `@solana/kit-plugin-wallet`
+
+## Prerequisites
+
+This spec builds on two changes that must land first:
+
+- **Plugin lifecycle utilities** (`extendClient`, `withCleanup`) in `@solana/kit` (re-exported from `@solana/plugin-core`) — `extendClient` provides descriptor-preserving client extension (preserves getters and symbols through plugin composition). `withCleanup` provides `Symbol.dispose`-based cleanup chaining. `addUse` is updated to use `Object.defineProperties` instead of spread to preserve property descriptors. See the plugin lifecycle RFC.
+- **Bridge function** (`createSignerFromWalletAccount`) in `@solana/wallet-account-signer` — a framework-agnostic function that takes a `UiWalletAccount` and a `SolanaChain` and returns a `TransactionSendingSigner` or `TransactionModifyingSigner` (and optionally `MessageSigner`). Extracted from the logic currently in `@solana/react`'s `useWalletAccountTransactionSigner` / `useWalletAccountTransactionSendingSigner` hooks.
+
+### Dependencies
+
+```json
+{
+ "peerDependencies": {
+ "@solana/kit": "^6.x"
+ },
+ "dependencies": {
+ "@solana/wallet-account-signer": "^1.x",
+ "@wallet-standard/app": "^1.x",
+ "@wallet-standard/base": "^1.x",
+ "@wallet-standard/features": "^1.x",
+ "@wallet-standard/ui": "^1.x",
+ "@wallet-standard/ui-features": "^1.x",
+ "@wallet-standard/ui-registry": "^1.x"
+ }
+}
+```
+
+The bridge function (`createSignerFromWalletAccount`) is consumed via `@solana/wallet-account-signer`. `extendClient` and `withCleanup` are consumed via `@solana/kit`.
+
+## Summary
+
+A framework-agnostic Kit plugin that manages wallet discovery, connection lifecycle, and signer creation using wallet-standard. When a wallet is connected, the plugin optionally syncs its signer to the client's `payer` and/or `identity` slots via dynamic getters, throwing when no signing wallet is connected. The plugin exposes subscribable wallet state for framework adapters (React, Vue, Svelte, etc.) to consume without coupling to any specific UI framework.
+
+**SSR-safe.** All four plugin functions (`walletSigner`, `walletIdentity`, `walletPayer`, `walletWithoutSigner`) can be included in a shared client chain on both server and browser. On the server (`__BROWSER__ === false`), the plugin gracefully degrades — status stays `'pending'`, wallet list is empty, signer getters throw, storage is skipped, no registry listeners are created. On the browser it initializes fully. This means a single client chain works everywhere:
+
+```typescript
+import { walletSigner } from '@solana/kit-plugin-wallet';
+
+const client = createClient()
+ .use(rpc('https://api.mainnet-beta.solana.com'))
+ .use(walletSigner({ chain: 'solana:mainnet' }))
+ .use(systemProgram())
+ .use(planAndSendTransactions());
+
+// Server: status === 'pending', client.payer / client.identity throw
+// Browser: auto-connect fires, client.payer / client.identity become wallet signer
+```
+
+## Motivation
+
+Kit provides a composable plugin system for building Solana clients. The existing `payer` plugin works well for static signers (backend keypairs, generated signers), but frontend dApps need wallet integration — discovery, user-initiated connection, account switching, and reactive state for UI rendering.
+
+Today, `@solana/react` bridges wallet-standard wallets into Kit signers via React hooks (`useWalletAccountTransactionSigner`, etc.), but this logic is locked inside React. There is no framework-agnostic layer that manages wallet state and provides Kit-compatible signers.
+
+This plugin fills that gap. It sits between wallet-standard's raw discovery API and framework-specific hooks, providing:
+
+- Automatic wallet discovery via `getWallets()`
+- Connection lifecycle management (connect, disconnect, silent reconnect)
+- Signer creation and caching via the bridge function
+- Dynamic payer integration (via `walletAsPayer`)
+- A subscribable store that any framework can bind to
+- Cleanup via `withCleanup` and `Symbol.dispose`
+
+### Where it fits
+
+```
++---------------------------------------------------+
+| React hooks / Vue composables / Svelte stores | <- Framework adapters (thin)
+| Subscribe to client wallet state for rendering |
++---------------------------------------------------+
+| wallet() plugin | <- THIS SPEC
+| Discovery, connection, signer, payer, state |
++---------------------------------------------------+
+| Kit plugin client |
+| .use(rpc(...)) |
+| .use(wallet({ ... })) <- or .use(payer(...)) |
+| .use(planAndSendTransactions()) |
++---------------------------------------------------+
+| createSignerFromWalletAccount() | <- @solana/wallet-account-signer
++---------------------------------------------------+
+| extendClient / withCleanup | <- Plugin lifecycle (in plugin-core)
++---------------------------------------------------+
+| wallet-standard @solana/signers Kit |
++---------------------------------------------------+
+```
+
+### Relationship to `@solana/react`
+
+This plugin extracts the wallet management logic currently embedded in `@solana/react`'s `SelectedWalletAccountContextProvider` (persistence, auto-restore, account selection, signer creation) into a framework-agnostic layer. Once this plugin ships, `@solana/react` can be rewritten as a thin adapter over `client.wallet.subscribe` / `client.wallet.getState` — a handful of hooks rather than a full wallet management implementation. The same approach applies to Vue, Svelte, and Solid adapters, all consuming the same plugin.
+
+### Relationship to `payer` and `identity`
+
+The package exports four plugin functions that differ in which signer properties they set on the client:
+
+**`walletSigner()`** — adds `client.wallet`, `client.payer`, and `client.identity`. The most common entrypoint for dApps.
+
+**`walletIdentity()`** — adds `client.wallet` and `client.identity`. Use when `client.payer` is controlled by a separate `payer()` plugin (e.g. a backend relayer pays fees, but the user's wallet is the identity).
+
+**`walletPayer()`** — adds `client.wallet` and `client.payer`. Use when you need the wallet as the fee payer but don't need `client.identity`.
+
+**`walletWithoutSigner()`** — adds `client.wallet` only. Use alongside separate `payer()` and/or `identity()` plugins, or when the wallet's signer is used explicitly in instructions.
+
+All signer getters (`payer`, `identity`) are dynamic — they return the wallet signer when connected, throw `SOLANA_ERROR__WALLET__NO_SIGNER_CONNECTED` when disconnected, or throw `SOLANA_ERROR__WALLET__SIGNER_NOT_AVAILABLE` when the wallet is read-only.
+
+```typescript
+import { walletSigner } from '@solana/kit-plugin-wallet';
+import { planAndSendTransactions } from '@solana/kit-plugin-instruction-plan';
+
+const client = createClient()
+ .use(rpc('https://api.mainnet-beta.solana.com'))
+ .use(walletSigner({ chain: 'solana:mainnet' }))
+ .use(planAndSendTransactions());
+
+// No wallet connected -> client.payer / client.identity throw
+// Wallet connected -> client.payer / client.identity return wallet signer
+// Wallet disconnects -> client.payer / client.identity throw
+```
+
+The dynamic getters use `Object.defineProperty`. `addUse` preserves getter descriptors through subsequent `.use()` calls, and downstream plugins that use `extendClient` also preserve them.
+
+Downstream plugins (e.g. `planAndSendTransactions()`) depend only on `client.payer` being a `TransactionSigner`. They do not know or care whether it was set by `payer()` or `walletSigner()`.
+
+## API Surface
+
+### Plugin creation
+
+```typescript
+import { walletSigner, walletIdentity, walletPayer, walletWithoutSigner } from '@solana/kit-plugin-wallet';
+
+// Wallet as payer and identity — most dApps
+const client = createClient()
+ .use(rpc('https://api.mainnet-beta.solana.com'))
+ .use(walletSigner({ chain: 'solana:mainnet' }))
+ .use(planAndSendTransactions());
+
+// Wallet as identity only — relayer pays fees
+const client = createClient()
+ .use(rpc('https://api.mainnet-beta.solana.com'))
+ .use(payer(relayerKeypair))
+ .use(walletIdentity({ chain: 'solana:mainnet' }))
+ .use(planAndSendTransactions());
+
+// Wallet as payer only
+const client = createClient()
+ .use(rpc('https://api.mainnet-beta.solana.com'))
+ .use(walletPayer({ chain: 'solana:mainnet' }))
+ .use(planAndSendTransactions());
+
+// Wallet without signer — manual signer use
+const client = createClient()
+ .use(rpc('https://api.mainnet-beta.solana.com'))
+ .use(payer(backendKeypair))
+ .use(walletWithoutSigner({ chain: 'solana:mainnet' }))
+ .use(planAndSendTransactions());
+// client.payer is TransactionSigner (from payer plugin, untouched)
+// client.wallet.getState().connected?.signer for manual use
+```
+
+### Client type extension
+
+Both `wallet` and `walletAsPayer` add the `wallet` namespace to the client. `walletAsPayer` additionally overrides `client.payer`:
+
+```typescript
+type ClientWithWallet = {
+ wallet: {
+ // -- State --
+
+ /**
+ * Subscribe to any wallet state change. Compatible with React's
+ * useSyncExternalStore and similar framework primitives.
+ * Returns an unsubscribe function.
+ */
+ subscribe: (listener: () => void) => () => void;
+
+ /**
+ * Get the current wallet state. Referentially stable
+ * when unchanged — a new object is only created when a
+ * state field actually changes.
+ */
+ getState: () => WalletState;
+
+ // -- Actions --
+
+ /**
+ * Connect to a wallet. Calls standard:connect on the wallet, then
+ * selects the first newly authorized account (or the first account
+ * if reconnecting). Creates and caches a signer for the active account.
+ * Returns all accounts from the wallet after connection.
+ */
+ connect: (wallet: UiWallet, options?: WalletActionOptions) => Promise;
+
+ /** Disconnect the active wallet. Calls standard:disconnect if supported. */
+ disconnect: (options?: WalletActionOptions) => Promise;
+
+ /**
+ * Switch to a different account within the connected wallet.
+ * Creates and caches a new signer for the selected account.
+ */
+ selectAccount: (account: UiWalletAccount) => void;
+
+ /**
+ * Sign an arbitrary message with the connected account.
+ * Throws if no account is connected or if the wallet does not
+ * support the solana:signMessage feature.
+ * Calls the wallet's solana:signMessage feature directly
+ * (does not go through the cached signer).
+ */
+ signMessage: (message: Uint8Array, options?: WalletActionOptions) => Promise;
+
+ /**
+ * Sign In With Solana (SIWS-as-connect).
+ *
+ * Connects the wallet, calls solana:signIn, sets the returned
+ * account as active, and creates a signer. After completion, the
+ * client is in the same state as if connect() had been called.
+ *
+ * All fields on SolanaSignInInput are optional — pass {} if no
+ * sign-in customization is needed.
+ *
+ * To sign in with the already-connected wallet, pass
+ * getState().connected.wallet.
+ */
+ signIn(wallet: UiWallet, input: SolanaSignInInput, options?: WalletActionOptions): Promise;
+ };
+};
+
+/**
+ * Options accepted by each async wallet action.
+ *
+ * Currently only carries an `abortSignal`, but is kept as an object for
+ * consistency with the rest of the Kit ecosystem and to allow future
+ * additions without breaking the call-site shape.
+ */
+type WalletActionOptions = {
+ /**
+ * An optional AbortSignal used to cancel the operation.
+ *
+ * Cancellation is pre-call only: the plugin checks
+ * `abortSignal.throwIfAborted()` at the start of each action and bails
+ * out before invoking the wallet. Once the underlying wallet-standard
+ * call has been dispatched, its result is returned even if the signal
+ * is aborted mid-flight — the wallet's side effect (an approved
+ * signature, a live connection, a broadcast transaction) is the source
+ * of truth, and throwing here would discard real user work without
+ * undoing what the wallet already did.
+ */
+ abortSignal?: AbortSignal;
+};
+
+/**
+ * walletAsPayer returns ClientWithWallet & ClientWithPayer.
+ * The payer getter is dynamic — returns the wallet signer when connected,
+ * throws SOLANA_ERROR__WALLET__NO_SIGNER_CONNECTED when disconnected,
+ * or SOLANA_ERROR__WALLET__SIGNER_NOT_AVAILABLE when read-only.
+ */
+
+export function walletSigner(config: WalletPluginConfig):
+ (client: T) => T & ClientWithWallet & ClientWithPayer & ClientWithIdentity;
+
+export function walletIdentity(config: WalletPluginConfig):
+ (client: T) => T & ClientWithWallet & ClientWithIdentity;
+
+export function walletPayer(config: WalletPluginConfig):
+ (client: T) => T & ClientWithWallet & ClientWithPayer;
+
+export function walletWithoutSigner(config: WalletPluginConfig):
+ (client: T) => T & ClientWithWallet;
+
+type WalletStatus =
+ | 'pending' // not yet initialized (SSR, or browser before first storage/registry check)
+ | 'disconnected' // initialized, no wallet connected
+ | 'connecting' // user-initiated connection in progress
+ | 'connected' // wallet connected, account + signer active
+ | 'disconnecting' // user-initiated disconnection in progress
+ | 'reconnecting'; // auto-connect in progress (restoring previous session)
+
+type WalletState = {
+ wallets: readonly UiWallet[];
+ connected: {
+ wallet: UiWallet;
+ account: UiWalletAccount;
+ /** The signer for the active account, or null for read-only wallets. */
+ signer: TransactionSigner | (MessageSigner & TransactionSigner) | null;
+ } | null;
+ status: WalletStatus;
+};
+```
+
+All wallet state is accessed via `getState()`. The returned object is frozen and memoized — a new reference is only created when a field actually changes (checked via reference equality in `setState`). This ensures `useSyncExternalStore` only triggers re-renders when something meaningful changed.
+
+```tsx
+const { connected, status, wallets } = useSyncExternalStore(
+ client.wallet.subscribe,
+ client.wallet.getState,
+);
+
+if (status === 'pending') return null;
+if (!connected) return ;
+if (!connected.signer) return ;
+
+// Use signer in event handlers
+const handleSend = () => {
+ buildTransaction({ authority: connected.signer, payer: client.payer });
+};
+return ;
+```
+
+### Dynamic payer (via `walletAsPayer`)
+
+`walletAsPayer` defines a `payer` getter via `Object.defineProperty`. The getter returns the current wallet signer, or `undefined` when disconnected or when the wallet is read-only.
+
+`wallet` does not touch `client.payer`.
+
+### Cleanup
+
+The plugin registers cleanup via `withCleanup`, spread into the return object:
+
+```typescript
+// Explicit cleanup
+client[Symbol.dispose]();
+
+// With using syntax (TypeScript 5.2+)
+{
+ using client = createEmptyClient()
+ .use(rpc('https://...'))
+ .use(wallet({ chain: 'solana:mainnet' }))
+ .use(planAndSendTransactions());
+} // cleanup runs automatically
+
+// In React
+useEffect(() => {
+ const client = createEmptyClient()
+ .use(rpc('https://...'))
+ .use(wallet({ chain: 'solana:mainnet' }));
+ setClient(client);
+ return () => client[Symbol.dispose]();
+}, []);
+```
+
+Cleanup unsubscribes from wallet-standard registry events, any active wallet's `standard:events` listener, and the auto-reconnect registry watcher (if still pending). Multiple disposable plugins chain in LIFO order.
+
+## Implementation
+
+### Plugin function
+
+```typescript
+import { extendClient, withCleanup } from '@solana/kit';
+import { createSignerFromWalletAccount } from '@solana/wallet-account-signer';
+import {
+ SolanaError,
+ SOLANA_ERROR__WALLET__NOT_CONNECTED,
+ SOLANA_ERROR__WALLET__NO_SIGNER_CONNECTED,
+ SOLANA_ERROR__WALLET__SIGNER_NOT_AVAILABLE,
+} from '@solana/errors';
+import { getWallets } from '@wallet-standard/app';
+import {
+ getOrCreateUiWalletForStandardWallet_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
+} from '@wallet-standard/ui-registry';
+import { getWalletFeature } from '@wallet-standard/ui-features';
+
+import type { UiWallet, UiWalletAccount } from '@wallet-standard/ui';
+import type { IdentifierString } from '@wallet-standard/base';
+import type { TransactionSigner, MessageSigner, SolanaChain } from '@solana/kit';
+
+// Internal helper — defines a throwing signer getter on the additions object.
+function defineSignerGetter(additions, property, store) {
+ Object.defineProperty(additions, property, {
+ get() {
+ const state = store.getState();
+ if (!state.connected) {
+ throw new SolanaError(SOLANA_ERROR__WALLET__NO_SIGNER_CONNECTED, { status: state.status });
+ }
+ if (!state.connected.signer) {
+ throw new SolanaError(SOLANA_ERROR__WALLET__SIGNER_NOT_AVAILABLE);
+ }
+ return state.connected.signer;
+ },
+ enumerable: true,
+ configurable: true,
+ });
+}
+
+// Internal helper — creates a wallet plugin with the given signer properties.
+function createPlugin(config, signerProperties) {
+ return (client) => {
+ const store = createWalletStore(config);
+ const additions = { wallet: store };
+ for (const prop of signerProperties) {
+ defineSignerGetter(additions, prop, store);
+ }
+ return withCleanup(extendClient(client, additions), () => store.destroy());
+ };
+}
+
+export function walletSigner(config) { return createPlugin(config, ['payer', 'identity']); }
+export function walletIdentity(config) { return createPlugin(config, ['identity']); }
+export function walletPayer(config) { return createPlugin(config, ['payer']); }
+export function walletWithoutSigner(config) { return createPlugin(config, []); }
+```
+
+### Internal store
+
+The store is a plain object with state management -- no external dependencies. It follows the same subscribe/getState contract as React's `useSyncExternalStore`.
+
+#### State shape
+
+```typescript
+type WalletStoreState = {
+ wallets: readonly UiWallet[];
+ connectedWallet: UiWallet | null;
+ account: UiWalletAccount | null;
+ /**
+ * Cached signer derived from the active account via
+ * createSignerFromWalletAccount(). May include MessageSigner
+ * if the wallet supports solana:signMessage.
+ */
+ signer: TransactionSigner | (MessageSigner & TransactionSigner) | null;
+ status: WalletStatus;
+};
+```
+
+#### Store implementation
+
+```typescript
+function createWalletStore(config: WalletPluginConfig) {
+ // __BROWSER__ is a compile-time constant replaced by the build system.
+ // Tree-shaking removes the server/browser branches from each build target.
+
+ let state: WalletStoreState = {
+ wallets: [],
+ connectedWallet: null,
+ account: null,
+ signer: null,
+ status: 'pending',
+ };
+
+ let snapshot: WalletState = deriveSnapshot(state);
+ const listeners = new Set<() => void>();
+ let walletEventsCleanup: (() => void) | null = null;
+ let reconnectCleanup: (() => void) | null = null;
+
+ // Tracks whether the user has made an explicit selection (connect or selectAccount).
+ // When true, auto-restore from storage will not override the user's choice.
+ let userHasSelected = false;
+
+ // Resolve storage: default to localStorage in browser, null to disable.
+ // On the server (__BROWSER__ === false), this code is unreachable —
+ // the SSR guard returns early before we get here.
+ const storage = config.storage === null
+ ? null
+ : config.storage ?? localStorage;
+ const storageKey = config.storageKey ?? 'kit-wallet';
+
+ // -- State management --
+
+ function setState(updates: Partial) {
+ const prev = state;
+ state = { ...state, ...updates };
+
+ // Only create a new snapshot if snapshot-relevant fields changed.
+ // This ensures referential stability for useSyncExternalStore —
+ // React's Object.is comparison sees the same reference and skips
+ // the re-render when nothing meaningful changed.
+ if (
+ state.wallets !== prev.wallets ||
+ state.connectedWallet !== prev.connectedWallet ||
+ state.account !== prev.account ||
+ state.status !== prev.status ||
+ state.signer !== prev.signer
+ ) {
+ snapshot = deriveSnapshot(state);
+ }
+
+ listeners.forEach((l) => l());
+ }
+
+ function deriveSnapshot(s: WalletStoreState): WalletState {
+ return Object.freeze({
+ wallets: s.wallets,
+ connected: s.connectedWallet && s.account
+ ? Object.freeze({
+ wallet: s.connectedWallet,
+ account: s.account,
+ signer: s.signer,
+ })
+ : null,
+ status: s.status,
+ });
+ }
+
+ // -- SSR guard: on the server, return an inert stub --
+
+ if (!__BROWSER__) {
+ return {
+ subscribe: (listener: () => void) => {
+ listeners.add(listener);
+ return () => listeners.delete(listener);
+ },
+ getState: () => snapshot,
+ connect: () => { throw new SolanaError(SOLANA_ERROR__WALLET__NOT_CONNECTED, { operation: 'connect' }); },
+ disconnect: () => Promise.resolve(),
+ selectAccount: () => { throw new SolanaError(SOLANA_ERROR__WALLET__NOT_CONNECTED, { operation: 'selectAccount' }); },
+ signMessage: () => { throw new SolanaError(SOLANA_ERROR__WALLET__NOT_CONNECTED, { operation: 'signMessage' }); },
+ signIn: () => { throw new SolanaError(SOLANA_ERROR__WALLET__NOT_CONNECTED, { operation: 'signIn' }); }, // wallet arg ignored on server
+ destroy: () => {},
+ };
+ }
+
+ // -- Browser-only initialization below this point --
+
+ // -- Signer creation (resilient to read-only wallets and custom chains) --
+
+ function tryCreateSigner(
+ account: UiWalletAccount,
+ ): TransactionSigner | (MessageSigner & TransactionSigner) | null {
+ try {
+ // `config.chain` widens to `SolanaChain | (IdentifierString & {})` for
+ // the custom-chain escape hatch. `createSignerFromWalletAccount` types
+ // only `SolanaChain`, but at runtime it throws when the account doesn't
+ // support the chain — which we catch below. Non-Solana chains therefore
+ // degrade to `signer: null`, matching the read-only-wallet contract.
+ return createSignerFromWalletAccount(account, config.chain as SolanaChain);
+ } catch {
+ // Wallet doesn't support signing (read-only / watch wallet, or a
+ // non-Solana chain). Connection proceeds without a signer — the account
+ // is still usable for discovery, display, and persistence.
+ return null;
+ }
+ }
+
+ // -- Wallet discovery --
+
+ const registry = getWallets();
+
+ function filterWallet(wallet: Wallet): boolean {
+ const uiWallet =
+ getOrCreateUiWalletForStandardWallet_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(wallet);
+ const supportsChain = uiWallet.chains.includes(config.chain);
+ const supportsConnect = uiWallet.features.includes('standard:connect');
+ if (!supportsChain || !supportsConnect) return false;
+ // Apply custom filter if provided
+ return config.filter ? config.filter(uiWallet) : true;
+ }
+
+ function buildWalletList(): readonly UiWallet[] {
+ return Object.freeze(
+ registry.get()
+ .filter(filterWallet)
+ .map(getOrCreateUiWalletForStandardWallet_DO_NOT_USE_OR_YOU_WILL_BE_FIRED),
+ );
+ }
+
+ setState({ wallets: buildWalletList() });
+
+ const unsubRegister = registry.on('register', () => {
+ setState({ wallets: buildWalletList() });
+ });
+ const unsubUnregister = registry.on('unregister', () => {
+ const newWallets = buildWalletList();
+ const updates: Partial = { wallets: newWallets };
+
+ if (
+ state.connectedWallet &&
+ !newWallets.some((w) => w.name === state.connectedWallet!.name)
+ ) {
+ walletEventsCleanup?.();
+ walletEventsCleanup = null;
+ updates.connectedWallet = null;
+ updates.account = null;
+ updates.signer = null;
+ updates.status = 'disconnected';
+ storage?.removeItem(storageKey);
+ }
+
+ setState(updates);
+ });
+
+ // -- Connection lifecycle --
+
+ async function connect(
+ uiWallet: UiWallet,
+ options?: WalletActionOptions,
+ ): Promise {
+ options?.abortSignal?.throwIfAborted();
+ userHasSelected = true;
+ reconnectCleanup?.();
+ reconnectCleanup = null;
+ setState({ status: 'connecting' });
+
+ try {
+ const connectFeature = getWalletFeature(uiWallet, 'standard:connect') as
+ StandardConnectFeature['standard:connect'];
+
+ // Snapshot existing accounts before connect — the wallet may
+ // already have some accounts visible.
+ const existingAccounts = [...uiWallet.accounts];
+
+ await connectFeature.connect();
+
+ // Refresh UiWallet to get updated accounts after connect.
+ // UiWallet handles are immutable snapshots — the pre-connect
+ // handle won't reflect newly authorized accounts.
+ const refreshedWallet = refreshUiWallet(uiWallet);
+ const allAccounts = refreshedWallet.accounts;
+
+ if (allAccounts.length === 0) {
+ setState({ status: 'disconnected' });
+ return allAccounts;
+ }
+
+ // Prefer the first newly authorized account. If none are new
+ // (e.g. re-connecting to an already-visible wallet), take the first.
+ const newAccount = allAccounts.find(
+ (a) => !existingAccounts.some((e) => e.address === a.address),
+ );
+ const activeAccount = newAccount ?? allAccounts[0];
+
+ const signer = tryCreateSigner(activeAccount);
+
+ walletEventsCleanup?.();
+ walletEventsCleanup = subscribeToWalletEvents(refreshedWallet);
+
+ setState({
+ connectedWallet: refreshedWallet,
+ account: activeAccount,
+ signer,
+ status: 'connected',
+ });
+
+ persistAccount(activeAccount, refreshedWallet);
+ return allAccounts;
+ } catch (error) {
+ setState({ status: 'disconnected' });
+ throw error;
+ }
+ }
+
+ async function disconnect(options?: WalletActionOptions): Promise {
+ options?.abortSignal?.throwIfAborted();
+ if (!state.connectedWallet) return;
+
+ const currentWallet = state.connectedWallet;
+ setState({ status: 'disconnecting' });
+
+ try {
+ if (currentWallet && currentWallet.features.includes('standard:disconnect')) {
+ const disconnectFeature = getWalletFeature(
+ currentWallet, 'standard:disconnect',
+ ) as StandardDisconnectFeature['standard:disconnect'];
+ await disconnectFeature.disconnect();
+ }
+ } finally {
+ // Always clear local state and storage, even if standard:disconnect
+ // threw (network error, wallet bug). This is intentionally fail-safe:
+ // a broken disconnect should not leave the user in a state where they
+ // auto-reconnect into a potentially corrupt session on next page load.
+ walletEventsCleanup?.();
+ walletEventsCleanup = null;
+
+ setState({
+ connectedWallet: null,
+ account: null,
+ signer: null,
+ status: 'disconnected',
+ });
+
+ storage?.removeItem(storageKey);
+ }
+ }
+
+ /**
+ * Clear local state without calling standard:disconnect on the wallet.
+ * Used for wallet-initiated disconnections (accounts removed, chain/feature
+ * changes) where the wallet already knows it disconnected. Synchronous,
+ * so it can't race with other event handlers.
+ */
+ function disconnectLocally(): void {
+ walletEventsCleanup?.();
+ walletEventsCleanup = null;
+
+ setState({
+ connectedWallet: null,
+ account: null,
+ signer: null,
+ status: 'disconnected',
+ });
+
+ storage?.removeItem(storageKey);
+ }
+
+ function selectAccount(account: UiWalletAccount): void {
+ if (!state.connectedWallet) {
+ throw new SolanaError(SOLANA_ERROR__WALLET__NOT_CONNECTED, {
+ operation: 'selectAccount',
+ });
+ }
+ userHasSelected = true;
+ const signer = tryCreateSigner(account);
+ setState({ account, signer });
+ persistAccount(account, state.connectedWallet!);
+ }
+
+ // -- Message signing --
+
+ async function signMessage(
+ message: Uint8Array,
+ options?: WalletActionOptions,
+ ): Promise {
+ options?.abortSignal?.throwIfAborted();
+ const { connectedWallet, account } = state;
+ if (!connectedWallet || !account) {
+ throw new SolanaError(SOLANA_ERROR__WALLET__NOT_CONNECTED, {
+ operation: 'signMessage',
+ });
+ }
+ // Use the wallet feature directly rather than going through the cached
+ // signer. This decouples message signing from transaction signing —
+ // a wallet that supports solana:signMessage but not transaction signing
+ // still works. getWalletFeature throws WalletStandardError if the
+ // feature is not supported.
+ const signMessageFeature = getWalletFeature(connectedWallet, 'solana:signMessage') as
+ SolanaSignMessageFeature['solana:signMessage'];
+ const [output] = await signMessageFeature.signMessage({ account, message });
+ return output.signature;
+ }
+
+ // -- Sign In With Solana (SIWS-as-connect) --
+
+ async function signIn(
+ wallet: UiWallet,
+ input: SolanaSignInInput,
+ options?: WalletActionOptions,
+ ): Promise {
+ options?.abortSignal?.throwIfAborted();
+ userHasSelected = true;
+ reconnectCleanup?.();
+ reconnectCleanup = null;
+
+ const signInFeature = getWalletFeature(wallet, 'solana:signIn') as
+ SolanaSignInFeature['solana:signIn'];
+ const [result] = await signInFeature.signIn(input);
+
+ // Set up full connection state using the account from the sign-in response.
+ const account = result.account;
+ const signer = tryCreateSigner(account);
+
+ walletEventsCleanup?.();
+ walletEventsCleanup = subscribeToWalletEvents(wallet);
+
+ setState({
+ connectedWallet: wallet,
+ account,
+ signer,
+ status: 'connected',
+ });
+
+ persistAccount(account, wallet);
+ return result;
+ }
+
+ // -- Wallet-initiated events --
+
+ // UiWallet handles are immutable snapshots. After a connect or change
+ // event the handle may be stale. Refresh by round-tripping through the
+ // underlying raw wallet to get the latest UiWallet.
+ function refreshUiWallet(staleUiWallet: UiWallet): UiWallet {
+ const rawWallet = getWalletForHandle_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(staleUiWallet);
+ return getOrCreateUiWalletForStandardWallet_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(rawWallet);
+ }
+
+ function subscribeToWalletEvents(uiWallet: UiWallet): () => void {
+ if (!uiWallet.features.includes('standard:events')) {
+ return () => {};
+ }
+
+ const eventsFeature = getWalletFeature(uiWallet, 'standard:events') as
+ StandardEventsFeature['standard:events'];
+
+ return eventsFeature.on('change', (properties) => {
+ if (properties.accounts) {
+ handleAccountsChanged(uiWallet);
+ }
+ if (properties.chains) {
+ handleChainsChanged(uiWallet);
+ }
+ if (properties.features) {
+ handleFeaturesChanged(uiWallet);
+ }
+ });
+ }
+
+ function handleAccountsChanged(uiWallet: UiWallet): void {
+ const refreshed = refreshUiWallet(uiWallet);
+ const newAccounts = refreshed.accounts;
+
+ if (newAccounts.length === 0) {
+ disconnectLocally();
+ return;
+ }
+
+ const currentAddress = state.account?.address;
+ const stillPresent = currentAddress
+ ? newAccounts.find((a) => a.address === currentAddress)
+ : null;
+ const activeAccount = stillPresent ?? newAccounts[0];
+
+ const signer = tryCreateSigner(activeAccount);
+ setState({ account: activeAccount, connectedWallet: refreshed, signer });
+ persistAccount(activeAccount, refreshed);
+ }
+
+ function handleChainsChanged(uiWallet: UiWallet): void {
+ const refreshed = refreshUiWallet(uiWallet);
+
+ if (!refreshed.chains.includes(config.chain)) {
+ disconnectLocally();
+ return;
+ }
+ // Chain support shifted but our chain is still valid — recreate
+ // signer in case chain-related capabilities changed.
+ if (state.account) {
+ const signer = tryCreateSigner(state.account);
+ setState({ connectedWallet: refreshed, signer });
+ }
+ }
+
+ function handleFeaturesChanged(uiWallet: UiWallet): void {
+ const refreshed = refreshUiWallet(uiWallet);
+
+ // Re-run the filter — if the wallet no longer passes, disconnect.
+ if (config.filter && !config.filter(refreshed)) {
+ disconnectLocally();
+ return;
+ }
+ // Features changed but wallet is still valid — recreate signer
+ // to pick up new capabilities or drop removed ones.
+ if (state.account) {
+ const signer = tryCreateSigner(state.account);
+ setState({ connectedWallet: refreshed, signer });
+ }
+
+ // Rebuild wallet list so other wallets reflect feature changes too.
+ setState({ wallets: buildWalletList() });
+ }
+
+ // -- Auto-connect --
+
+ if (config.autoConnect !== false && storage) {
+ // Wrapped in async IIFE because storage.getItem may return a Promise
+ // (e.g. IndexedDB). Plugin setup still returns synchronously — status
+ // stays 'pending' until the storage read resolves.
+ (async () => {
+ const savedKey = await storage.getItem(storageKey);
+ if (userHasSelected) return;
+
+ if (!savedKey) {
+ setState({ status: 'disconnected' });
+ return;
+ }
+
+ const separatorIndex = savedKey.lastIndexOf(':');
+ if (separatorIndex === -1) {
+ // Malformed saved key
+ storage.removeItem(storageKey);
+ setState({ status: 'disconnected' });
+ return;
+ }
+
+ const walletName = savedKey.slice(0, separatorIndex);
+ const existing = state.wallets.find((w) => w.name === walletName);
+
+ if (existing) {
+ attemptSilentReconnect(savedKey, existing);
+ } else if (
+ registry.get().some((w) => {
+ const ui = getOrCreateUiWalletForStandardWallet_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(w);
+ return ui.name === walletName;
+ })
+ ) {
+ // Wallet is registered but doesn't pass the filter (wrong chain,
+ // missing standard:connect, or rejected by config.filter).
+ // Clear stale persistence — don't wait for it.
+ storage.removeItem(storageKey);
+ setState({ status: 'disconnected' });
+ } else {
+ // Wallet not registered yet — watch for it to appear.
+ // Revert status to 'disconnected' after 3s to avoid a perpetual
+ // spinner if the wallet is uninstalled. Keep the listener alive
+ // so slow-loading extensions can still silently reconnect.
+ setState({ status: 'reconnecting' });
+
+ const statusTimeout = setTimeout(() => {
+ if (!userHasSelected && state.status === 'reconnecting') {
+ setState({ status: 'disconnected' });
+ }
+ }, 3000);
+
+ const unsubRegisterForReconnect = registry.on('register', () => {
+ if (userHasSelected) {
+ clearTimeout(statusTimeout);
+ unsubRegisterForReconnect();
+ reconnectCleanup = null;
+ return;
+ }
+ const found = buildWalletList().find((w) => w.name === walletName);
+ if (found) {
+ clearTimeout(statusTimeout);
+ unsubRegisterForReconnect();
+ reconnectCleanup = null;
+ attemptSilentReconnect(savedKey, found);
+ } else if (
+ registry.get().some((w) => {
+ const ui = getOrCreateUiWalletForStandardWallet_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(w);
+ return ui.name === walletName;
+ })
+ ) {
+ // Wallet registered but filtered out — clear stale persistence
+ clearTimeout(statusTimeout);
+ unsubRegisterForReconnect();
+ reconnectCleanup = null;
+ storage.removeItem(storageKey);
+ setState({ status: 'disconnected' });
+ }
+ });
+
+ reconnectCleanup = () => {
+ clearTimeout(statusTimeout);
+ unsubRegisterForReconnect();
+ };
+ }
+ })().catch(() => {
+ // Storage read failed — fall back to disconnected.
+ if (!userHasSelected) {
+ setState({ status: 'disconnected' });
+ }
+ });
+ } else {
+ // No auto-connect: immediately transition from 'pending' to 'disconnected'
+ setState({ status: 'disconnected' });
+ }
+
+ async function attemptSilentReconnect(
+ savedAccountKey: string,
+ uiWallet: UiWallet,
+ ): Promise {
+ setState({ status: 'reconnecting' });
+
+ try {
+ const connectFeature = getWalletFeature(uiWallet, 'standard:connect') as
+ StandardConnectFeature['standard:connect'];
+ await connectFeature.connect({ silent: true });
+
+ const refreshedWallet = refreshUiWallet(uiWallet);
+ const allAccounts = refreshedWallet.accounts;
+
+ if (allAccounts.length === 0) {
+ setState({ status: 'disconnected' });
+ storage?.removeItem(storageKey);
+ return;
+ }
+
+ // Check again: user may have connected manually while we were awaiting
+ if (userHasSelected) return;
+
+ // Restore specific saved account, fall back to first from same wallet
+ const savedAddress = savedAccountKey.slice(savedAccountKey.lastIndexOf(':') + 1);
+ const activeAccount = allAccounts.find((a) => a.address === savedAddress)
+ ?? allAccounts[0];
+
+ const signer = tryCreateSigner(activeAccount);
+
+ walletEventsCleanup?.();
+ walletEventsCleanup = subscribeToWalletEvents(refreshedWallet);
+
+ setState({
+ connectedWallet: refreshedWallet,
+ account: activeAccount,
+ signer,
+ status: 'connected',
+ });
+ } catch {
+ setState({ status: 'disconnected' });
+ storage?.removeItem(storageKey);
+ }
+ }
+
+ // -- Persistence --
+
+ function persistAccount(account: UiWalletAccount, wallet: UiWallet): void {
+ storage?.setItem(storageKey, `${wallet.name}:${account.address}`);
+ }
+
+ // -- Public API (exposed as client.wallet) --
+
+ return {
+ subscribe: (listener: () => void) => {
+ listeners.add(listener);
+ return () => listeners.delete(listener);
+ },
+ getState: () => snapshot,
+ connect,
+ disconnect,
+ selectAccount,
+ signMessage,
+ signIn,
+ destroy: () => {
+ unsubRegister();
+ unsubUnregister();
+ walletEventsCleanup?.();
+ walletEventsCleanup = null;
+ reconnectCleanup?.();
+ reconnectCleanup = null;
+ listeners.clear();
+ },
+ };
+}
+```
+
+## Signer Caching
+
+The signer is created via `tryCreateSigner()` (wrapping `createSignerFromWalletAccount()`) when an account becomes active, and stored in `state.signer`. It is not recreated on every `client.payer` access -- the getter simply reads `state.signer`.
+
+If `createSignerFromWalletAccount` throws (e.g. the wallet doesn't support any signing features), `tryCreateSigner` catches the error and returns `null`. The wallet is still connected — the account is set, events work, persistence works — but `getState().connected.signer` is `null`. When using `walletAsPayer`, `client.payer` throws `SOLANA_ERROR__WALLET__SIGNER_NOT_AVAILABLE`.
+
+This ensures referential stability, which matters for React's dependency arrays and avoids redundant codec/wrapper creation.
+
+The signer is invalidated and recreated when:
+
+- The user connects to a different wallet
+- The user switches accounts via `selectAccount`
+- The wallet emits a `change` event that updates accounts
+- The wallet emits a `change` event for features (e.g. `solana:signMessage` added or removed)
+- The wallet emits a `change` event for chains (if the configured chain is still supported)
+
+A feature change event may cause a previously null signer to become non-null (e.g. a watch wallet adds signing support) or vice versa.
+
+### Signer types
+
+The bridge function (`createSignerFromWalletAccount`) inspects the wallet's features and returns the appropriate signer type:
+
+- `TransactionModifyingSigner` if the wallet supports `solana:signTransaction`
+- `TransactionSendingSigner` if the wallet supports `solana:signAndSendTransaction`
+- `MessageSigner` (intersected with the above) if the wallet supports `solana:signMessage`
+- Throws if the wallet supports none of the above (caught by `tryCreateSigner`)
+
+All variants satisfy `TransactionSigner`, which is what `client.payer` expects. Kit's transaction execution automatically uses the appropriate signing path (e.g. `TransactionSendingSigner` lets the wallet submit the transaction itself). The `signMessage` method on the client uses the wallet's `solana:signMessage` feature directly rather than going through the cached signer, so message signing works even for wallets that don't support transaction signing.
+
+## Signer Getter Detail
+
+### How the getters work
+
+The `walletSigner`, `walletPayer`, and `walletIdentity` plugins define dynamic getters for `payer` and/or `identity` on the additions object passed to `extendClient`. Each getter returns the current wallet signer when connected, or throws when disconnected or read-only. Getters must be defined on the additions object (not on the result) because `extendClient` freezes the returned client. The `defineSignerGetter` helper is shared by all plugin functions.
+
+These getters are preserved through subsequent `.use()` calls because:
+
+1. `addUse` (updated in the plugin lifecycle RFC) uses `Object.getOwnPropertyDescriptors` instead of spread, preserving the getter.
+2. Subsequent plugins using `extendClient` also preserve it.
+3. The final frozen client returned by `addUse` retains the getter -- `Object.freeze` does not strip getters.
+
+Note: downstream plugins should use `extendClient` rather than spread to ensure signer getters are preserved.
+
+### Interaction with planAndSendTransactions plugin
+
+The `planAndSendTransactions` plugin accesses `client.payer` at transaction time. Because the payer is a getter, it always resolves to the current value:
+
+- User connects wallet → next transaction uses the wallet signer
+- User switches accounts → next transaction uses the new account's signer
+- User disconnects → `client.payer` throws `SOLANA_ERROR__WALLET__NO_SIGNER_CONNECTED`
+
+No client reconstruction is needed. The client is a long-lived object.
+
+## Subscribability Contract
+
+All wallet state is accessed via `client.wallet.getState()`. There are no individual getters.
+
+`subscribe` fires on every internal state change. Listeners don't know what changed; they just know "something changed."
+
+`getState` returns a memoized frozen object. A new reference is only created when a state field actually changes (compared via reference equality in `setState`). React's `useSyncExternalStore` uses `Object.is` to compare successive `getState` returns — same reference means no re-render, new reference means re-render. Because we control when the object is recreated, re-renders only happen on meaningful state changes.
+
+### Framework adapter examples
+
+**React:**
+```tsx
+function useWalletState(client) {
+ return useSyncExternalStore(client.wallet.subscribe, client.wallet.getState);
+}
+```
+
+**Vue:**
+```typescript
+function useWalletState(client) {
+ const state = shallowRef(client.wallet.getState());
+ onMounted(() => {
+ const unsub = client.wallet.subscribe(() => { state.value = client.wallet.getState(); });
+ onUnmounted(unsub);
+ });
+ return state;
+}
+```
+
+**Svelte:**
+```typescript
+const walletState = readable(client.wallet.getState(), (set) => {
+ return client.wallet.subscribe(() => set(client.wallet.getState()));
+});
+```
+
+**Solid:**
+```typescript
+const [walletState, setWalletState] = createSignal(client.wallet.getState());
+onMount(() => {
+ onCleanup(client.wallet.subscribe(() => setWalletState(client.wallet.getState())));
+});
+```
+
+## Storage
+
+### Storage adapter
+
+Persistence is handled via a pluggable storage adapter following the Web Storage API shape. `localStorage` and `sessionStorage` can be passed directly with zero wrapping.
+
+```typescript
+type WalletStorage = {
+ getItem(key: string): string | null | Promise;
+ setItem(key: string, value: string): void | Promise;
+ removeItem(key: string): void | Promise;
+};
+```
+
+The type is duck-typed rather than extending the DOM `Storage` interface, so it works in any environment without requiring DOM lib types. The async-compatible signatures match wagmi's storage interface. `localStorage` and `sessionStorage` satisfy this directly since sync return values are valid where `T | Promise` is expected. Async backends like IndexedDB or encrypted storage can return Promises.
+
+### What is persisted
+
+The plugin persists a `walletName:accountAddress` string (e.g. `"Phantom:ABC123..."`). This identifies both the wallet and the specific account the user selected. On reconnect, the plugin attempts to restore the exact account; if that account is no longer available but the wallet is, it falls back to the first available account.
+
+This matches the persistence format used by Kit's existing React hooks.
+
+### Default storage
+
+When no `storage` option is provided, the plugin defaults to `localStorage` in the browser. On the server, storage is always skipped regardless of the option.
+
+### Storage examples
+
+```typescript
+// Default — uses localStorage in browser, skipped on server
+wallet({ chain: 'solana:mainnet' })
+
+// Use sessionStorage
+wallet({ chain: 'solana:mainnet', storage: sessionStorage })
+
+// Use a reactive store
+wallet({
+ chain: 'solana:mainnet',
+ storage: {
+ getItem: (key) => myStore.getState().walletKey,
+ setItem: (key, value) => myStore.setState({ walletKey: value }),
+ removeItem: (key) => myStore.setState({ walletKey: null }),
+ },
+})
+
+// Disable persistence explicitly
+wallet({ chain: 'solana:mainnet', storage: null })
+```
+
+## Configuration
+
+```typescript
+type WalletPluginConfig = {
+ /**
+ * The chain this client targets.
+ *
+ * Accepts any `SolanaChain` (with literal autocomplete for
+ * 'solana:mainnet' / 'solana:devnet' / 'solana:testnet') and, as an escape
+ * hatch, any wallet-standard `IdentifierString` (`${string}:${string}`) for
+ * custom chains or non-Solana L2s. The `& {}` preserves literal autocomplete
+ * on the Solana members — without it TS would collapse the union into the
+ * wider template literal type.
+ *
+ * The plugin's runtime is chain-agnostic: `uiWallet.chains.includes(chain)`
+ * for discovery is a plain string check, and `createSignerFromWalletAccount`
+ * throws for chains it doesn't understand — which `tryCreateSigner` already
+ * catches, degrading to `signer: null` (matching the read-only-wallet
+ * contract).
+ *
+ * One client = one chain. To switch networks, create a separate client with
+ * a different chain and RPC endpoint.
+ */
+ chain: SolanaChain | (IdentifierString & {});
+
+ /**
+ * Optional filter function for wallet discovery.
+ * Called for each wallet that supports the configured chain and
+ * standard:connect. Return true to include the wallet, false to exclude.
+ * Useful for requiring specific features, whitelisting wallets,
+ * or any other application-specific filtering.
+ *
+ * @example
+ * // Require signAndSendTransaction
+ * filter: (w) => w.features.includes('solana:signAndSendTransaction')
+ *
+ * @example
+ * // Whitelist specific wallets
+ * filter: (w) => ['Phantom', 'Solflare'].includes(w.name)
+ */
+ filter?: (wallet: UiWallet) => boolean;
+
+ /**
+ * Whether to attempt silent reconnection on startup using
+ * the persisted wallet account from storage.
+ * @default true
+ */
+ autoConnect?: boolean;
+
+ /**
+ * Storage adapter for persisting the selected wallet account.
+ * Follows the Web Storage API shape (getItem/setItem/removeItem).
+ * Supports both sync and async backends.
+ * localStorage and sessionStorage satisfy this interface directly.
+ * Pass null to disable persistence entirely.
+ * Ignored on the server (storage is always skipped in SSR).
+ * @default localStorage
+ */
+ storage?: WalletStorage | null;
+
+ /**
+ * Storage key used for persistence.
+ * @default 'kit-wallet'
+ */
+ storageKey?: string;
+};
+```
+
+## Error Handling
+
+### Error codes
+
+Three error codes from `@solana/errors`:
+
+```typescript
+SOLANA_ERROR__WALLET__NOT_CONNECTED
+// context: { operation: string }
+// message: "Cannot $operation: no wallet connected"
+
+SOLANA_ERROR__WALLET__NO_SIGNER_CONNECTED
+// context: { status: string }
+// message: "No signing wallet connected (status: $status)"
+
+SOLANA_ERROR__WALLET__SIGNER_NOT_AVAILABLE
+// context: {}
+// message: "Connected wallet does not support signing"
+```
+
+`NOT_CONNECTED` is thrown by wallet actions (signMessage, selectAccount, etc.) when no wallet is connected. `NO_SIGNER_CONNECTED` is thrown by the `payer` getter when no wallet is connected. `SIGNER_NOT_AVAILABLE` is thrown by the `payer` getter when a wallet is connected but is read-only (no signing support).
+
+Feature-not-supported errors are delegated to `getWalletFeature` from `@wallet-standard/ui-features`, which throws a `WalletStandardError` when the requested feature is not present on the wallet. This avoids duplicating error handling that wallet-standard already provides.
+
+Wallet-originated errors (e.g. user rejecting a connection prompt) are propagated unchanged.
+
+### Error behavior
+
+| Scenario | Behavior |
+|----------|----------|
+| SSR (server environment) | Status stays `'pending'`, all actions throw `SOLANA_ERROR__WALLET__NOT_CONNECTED` |
+| User rejects connection prompt | `connect()` propagates wallet error, status returns to `disconnected` |
+| Wallet does not support signing | Connection succeeds, `connected.signer` is `null`, `client.payer` throws `SOLANA_ERROR__WALLET__SIGNER_NOT_AVAILABLE`, sign methods throw |
+| Wallet does not pass filter | Filtered out at discovery time; disconnected if filter fails after feature change |
+| Wallet unregisters while connected | Automatic disconnection, subscribers notified |
+| Silent reconnect fails | Status -> `disconnected`, persisted account cleared |
+| No wallets discovered | `state.wallets` is empty, UI can prompt user to install a wallet |
+| `standard:disconnect` not supported | Disconnect proceeds -- clear local state regardless |
+| `selectAccount` without connection | Throws `SOLANA_ERROR__WALLET__NOT_CONNECTED` with `{ operation: 'selectAccount' }` |
+| `signMessage` without connection | Throws `SOLANA_ERROR__WALLET__NOT_CONNECTED` with `{ operation: 'signMessage' }` |
+| `signMessage` on wallet without feature | `getWalletFeature` throws `WalletStandardError` |
+| `signIn` on wallet without feature | `getWalletFeature` throws `WalletStandardError` |
+
+`connect()` and `disconnect()` propagate wallet errors to the caller unchanged. Internal errors (reconnect failures, storage errors) are logged via `console.warn` but do not throw.
+
+## Design Decisions
+
+**Descriptor-preserving composition.** The plugin uses `extendClient` from plugin-core to build the client, preserving getters and symbol-keyed properties from previous plugins. The updated `addUse` also preserves descriptors through `.use()` calls. Downstream plugins should use `extendClient` rather than spread to avoid flattening the dynamic payer getter.
+
+**Single chain per client.** Signers are bound to a specific chain at creation time. Switching chains requires a different RPC endpoint too. One client = one network.
+
+**Chain type includes a custom-chain escape hatch.** `WalletPluginConfig.chain` types as `SolanaChain | (IdentifierString & {})` rather than just `SolanaChain`. `SolanaChain` covers the 99% case with literal autocomplete; the `IdentifierString` escape hatch matches wallet-standard's native chain type (`UiWallet.chains: IdentifierString[]`) and unblocks custom chains or non-Solana L2s without requiring consumers to cast. The runtime is already chain-agnostic — the chain is a plain string passed to wallet-standard discovery and to `createSignerFromWalletAccount` (which throws for unknown chains, caught by `tryCreateSigner` → `signer: null`, same contract as read-only wallets).
+
+**Single wallet connection.** One active wallet at a time. dApps needing multiple can access `getState().wallets` and manage additional connections via wallet-standard APIs.
+
+**SSR-safe.** All four plugin functions gracefully degrade on the server — status stays `'pending'`, wallet list is empty, signer getters throw `SOLANA_ERROR__WALLET__NO_SIGNER_CONNECTED`, storage is skipped, all actions throw `SOLANA_ERROR__WALLET__NOT_CONNECTED`. The same client chain works on both server and browser without conditional `.use()` calls.
+
+**`pending` status.** Initial status is `'pending'`, not `'disconnected'`. This lets UI distinguish "we haven't checked yet" (render nothing / skeleton) from "we checked and there's no wallet" (render connect button). On the server, status stays `'pending'` permanently. In the browser, it transitions to `'disconnected'` or `'reconnecting'` once the storage read completes.
+
+**`localStorage` as default storage.** The plugin defaults to `localStorage` in the browser and skips storage on the server. Consumers don't need to reference `localStorage` directly (which would throw a `ReferenceError` on the server), and the common case requires no configuration.
+
+**Single subscribe listener.** Fires on any state change. Frameworks needing field-level selectivity use their own selector patterns (e.g. `useSyncExternalStoreWithSelector`).
+
+**Four plugin entrypoints.** The signer property decision is expressed at the type level, not via a config flag. `walletSigner()` sets both `payer` and `identity`, `walletIdentity()` sets only `identity`, `walletPayer()` sets only `payer`, and `walletWithoutSigner()` sets neither. The choice is in which function you import — the types tell you exactly what you get.
+
+**Web Storage API for persistence.** Duck-typed to match the `getItem`/`setItem`/`removeItem` shape used by wagmi and Zustand. Supports both sync and async backends — `localStorage` can be passed directly, and async backends (IndexedDB, encrypted storage) return Promises.
+
+**Account-level persistence.** Persists `walletName:accountAddress` (parsed with `lastIndexOf(':')` since base58 addresses never contain colons). Preserves the user's account selection across sessions.
+
+**Sync-only cleanup.** All cleanup operations (unsubscribing from events, clearing listeners) are synchronous. `Symbol.asyncDispose` support may be added to plugin-core later as a separate utility.
+
+**SIWS-as-connect.** `signIn` always takes a `UiWallet` argument and establishes full connection state using the account returned in the sign-in response — one step instead of `connect()` then separate auth. To sign in with the already-connected wallet, callers pass `getState().connected.wallet`. This avoids overload discrimination logic and keeps the API surface simple.
+
+**Signer recreation on wallet events.** When the wallet emits feature or chain changes, the signer is recreated to reflect new capabilities (e.g. `solana:signMessage` added) or drop removed ones. `createSignerFromWalletAccount` is cheap (no network calls), so this is practical on every event.
+
+**Local disconnect for wallet-initiated events.** `disconnectLocally()` clears local state synchronously without calling `standard:disconnect` on the wallet. Used when the wallet itself initiated the change (accounts removed, chain/feature changes). Avoids the async gap and redundant round-trip of calling back to a wallet that already knows it disconnected.
+
+**Status timeout on reconnect.** When waiting for a previously connected wallet to register, status reverts from `reconnecting` to `disconnected` after 3 seconds. The registry listener stays alive — if the wallet appears later, it silently reconnects. This prevents a perpetual spinner for uninstalled wallets while still supporting slow-loading extensions.
+
+**`userHasSelected` flag.** Tracks whether the user has made an explicit choice (via `connect`, `selectAccount`, or `signIn`). When true, the auto-restore flow will not override the user's selection, matching the `wasSetterInvokedRef` pattern from `@solana/react`.
+
+**Read-only wallet support.** `tryCreateSigner` wraps `createSignerFromWalletAccount` in a try/catch. If the wallet doesn't support any signing features (e.g. a watch-only wallet), connection still succeeds — the account is set, events fire, persistence works. `connected.signer` in the state is `null`, letting UI distinguish connected-with-signer from connected-without-signer. When using `walletAsPayer`, `client.payer` throws `SOLANA_ERROR__WALLET__SIGNER_NOT_AVAILABLE`.
+