@vue-solana/vue 4.0.0-rc.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,6 +7,16 @@
7
7
 
8
8
  Solana wallet, RPC, account, message signing, and transaction composables for Vue 3.
9
9
 
10
+ ## Related packages
11
+
12
+ This package is part of the Vue Solana family. Choose based on your app framework:
13
+
14
+ - [`@vue-solana/core`](https://www.npmjs.com/package/@vue-solana/core) — framework-agnostic Solana primitives: Kit RPC client helpers, wallet types, Android MWA registration, iOS browser wallet helpers, message signing, token account reads, and transaction helpers. **Use this directly** when you want shared RPC/wallet/transaction helpers without installing a Vue plugin (non-Vue apps, server/relayer code, or your own framework integration).
15
+ - [`@vue-solana/vue`](https://www.npmjs.com/package/@vue-solana/vue) — Vue 3 plugin plus composables for RPC, account, balance, wallet, message signing, live data, and transactions. **Use this** in plain Vue 3 apps (Vite, etc.). (This package.)
16
+ - [`@vue-solana/nuxt`](https://www.npmjs.com/package/@vue-solana/nuxt) — Nuxt module that installs the Vue plugin and auto-imports the composables. **Use this** in Nuxt 3/4 apps.
17
+
18
+ This package builds on `@vue-solana/core`; install `@vue-solana/vue` for plain Vue apps and `@vue-solana/nuxt` for Nuxt apps.
19
+
10
20
  Use this package in Vue 3 apps that need Solana RPC access, balance reads, wallet state, message signing, and transaction helper state.
11
21
 
12
22
  New to Solana? Start with the official docs and the project concepts guide:
@@ -64,20 +74,22 @@ import { createApp } from "vue";
64
74
  import { createSolanaPlugin } from "@vue-solana/vue";
65
75
  import App from "./App.vue";
66
76
 
67
- createApp(App)
68
- .use(
69
- createSolanaPlugin({
70
- cluster: "devnet",
71
- mobileWallet: {
72
- appIdentity: {
73
- name: "My Vue Solana App",
74
- uri: "https://example.com",
75
- icon: "favicon.ico",
76
- },
77
- },
78
- }),
79
- )
80
- .mount("#app");
77
+ const solana = createSolanaPlugin({
78
+ cluster: "devnet",
79
+ mobileWallet: {
80
+ appIdentity: {
81
+ name: "My Vue Solana App",
82
+ uri: "https://example.com",
83
+ icon: "favicon.ico",
84
+ },
85
+ },
86
+ });
87
+
88
+ createApp(App).use(solana).mount("#app");
89
+
90
+ // On teardown:
91
+ // app.unmount();
92
+ // solana.dispose();
81
93
  ```
82
94
 
83
95
  Android Mobile Wallet Adapter registration is enabled by default on supported Android Chrome clients. Pass `mobileWallet` options to customize the MWA app identity, or pass `mobileWallet: false` to disable Android mobile wallet registration.
@@ -227,6 +239,8 @@ const signatureStatus = useSignatureStatus(signature, {
227
239
  });
228
240
  ```
229
241
 
242
+ There is no per-call `commitment` option for `useSignatureStatus()`; `getSignatureStatuses` takes no per-call commitment, so reads use the commitment baked into the endpoint. Polling uses chained timeouts and `stopPolling()` prevents further ticks until the watched signature changes (which restarts polling). Invalid `pollIntervalMs` values return an `RPC_FAILURE` `SolanaError`.
243
+
230
244
  Read SPL token accounts and balances through Kit RPC `jsonParsed`:
231
245
 
232
246
  ```ts
@@ -276,6 +290,8 @@ const { publicKey, connected, connecting, canSignMessage, connect, disconnect }
276
290
 
277
291
  Browser extension wallets are discovered through the Solana Wallet Standard. Android Mobile Wallet Adapter wallets are registered through `@solana-mobile/wallet-standard-mobile` and exposed through the same `useWallets()` list on supported Android Chrome clients. iOS Phantom, Solflare, and Backpack entries are exposed through wallet-specific universal links on iOS browsers. `connect()` works after selecting a discovered wallet or configuring a custom `SolanaWallet`.
278
292
 
293
+ Connecting a wallet also disconnects every other discovered wallet through its `standard:disconnect` feature, so only one wallet stays authorized for the app. An extension the user authorized in an earlier page session can otherwise keep answering signing requests, which is the usual cause of the wrong wallet prompting for a `signMessage` confirmation. A wallet that fails or never answers its disconnect is ignored after a 2 second timeout, and `connect()` resolves only after the sweep finishes.
294
+
279
295
  Selected discovered wallets are persisted under `localStorage["vue-solana:selected-wallet"]` as non-sensitive identity metadata: `name`, and `platform`/`source` when available. On reload, Vue Solana restores the selected wallet if the same wallet is discovered again. Pass `autoConnect: true` to opt into calling `connect()` for that restored wallet; arbitrary installed wallets are never auto-connected. Calling `selectWallet(null)` or `setWallet(customWallet)` clears the stored selection.
280
296
 
281
297
  Desktop native app wallet adapters are planned but not implemented yet.
@@ -488,7 +504,7 @@ import { useRequestSwr } from "@vue-solana/vue/swr";
488
504
  const balance = useRequestSwr(["balance", address], () => client.rpc.getBalance(address).send());
489
505
  ```
490
506
 
491
- The SWR cache is module-level and shared across the whole app, including across SSR requests. Namespace cache keys per request (for example by including a request or session id) or call `clearSwrCache()` at the start of each server request to avoid leaking one request's cached data into another. On the client the cache is intentionally shared for stale-while-revalidate seeding.
507
+ The SWR cache is module-level and shared across the whole app, including across SSR requests. Namespace cache keys per request (for example by including a request or session id) or call `clearSwrCache()` at the start of each server request to avoid leaking one request's cached data into another. On the client the cache is intentionally shared for stale-while-revalidate seeding. It is capped at 1024 entries with oldest-first eviction. Use `deleteSwrKey(key)` to evict a single entry by its full cache key (including the adapter prefix like `request:`).
492
508
 
493
509
  ### Cancellation & Timeouts
494
510
 
@@ -592,9 +608,9 @@ Docs: [Vue Solana Agent Skill](https://vue-solana-docs.vercel.app/agent-skill)
592
608
 
593
609
  | API | Description |
594
610
  | ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
595
- | `createSolanaPlugin(options?)` | Installs the Vue Solana context. |
611
+ | `createSolanaPlugin(options?)` | Installs the Vue Solana context and returns `{ install, context, dispose }`. `dispose()` stops wallet discovery/subscriptions. |
596
612
  | `VueSolana` | Alias for `createSolanaPlugin`. |
597
- | `useSolana()` | Returns the full injected Solana context; throws when no plugin context is available. |
613
+ | `useSolana()` | Returns the full injected Solana context; throws when no plugin context is available (SSR fallback uses a fresh inert context per call). |
598
614
  | `tryUseSolana()` | Returns the injected Solana context or `null` when no plugin context is available (SSR-safe). |
599
615
  | `MissingClientCapabilityError` | Thrown by `useClientCapability()` (and client-sent composables) when the configured client lacks a required capability. |
600
616
  | `useRpc()` | Returns cluster, endpoint, connection status, latest blockhash, the Kit `client`, and `checkConnection()`. |
@@ -619,12 +635,14 @@ Docs: [Vue Solana Agent Skill](https://vue-solana-docs.vercel.app/agent-skill)
619
635
  | `useTrackedData(source, options?)` | Slot-deduplicated fetch plus subscription over Kit's slot-tracking store. |
620
636
  | `useRequestSwr(key, ...)` / `useSubscriptionSwr(key, ...)` / `useTrackedDataSwr(key, ...)` | Cache-keyed SWR adapters seeding fresh mounts from the last-known result. |
621
637
  | `clearSwrCache()` | Clears every cached SWR entry. |
638
+ | `deleteSwrKey(key)` | Removes a single cached SWR entry by full cache key (including adapter prefix). |
622
639
  | `useSignIn(input?)` | Sign In With Solana (SIWS) trigger returning `{ account, signedMessage, signature }` for server-side verification. |
623
640
  | `useSelectedWalletAccount()` | App-wide selected wallet account context: `[selectedAccount, setSelectedAccount, filteredWallets]`. |
624
641
  | `SelectedWalletAccountProvider` | Component that provides the selected wallet account context to its subtree. |
625
642
  | `useSignTransactions()` | Batch-signs transactions through the wallet, preferring `signTransactions` and falling back to `signAllTransactions`. |
626
643
  | `useSignAndSendTransactions()` | Signs and sends multiple transactions, returning one signature each, with a singular sequential fallback. |
627
644
  | `useClientCapability(capability, options?)` | Fails fast with a clear error when the configured Solana client lacks a requested capability. |
645
+ | `tryUseSolana()` | Returns the injected Solana context or `null` when no plugin context is available (SSR-safe). |
628
646
  | `usePayer()` | Reactive Kit client `payer` signer ref. The default client exposes a configured payer when supplied. |
629
647
  | `useIdentity()` | Reactive Kit client `identity` signer ref (requires an identity signer on a custom client). |
630
648
  | `usePlanTransaction()` | Plans a single transaction message from instruction inputs without signing or sending; the default client includes the official planner. |
package/dist/index.mjs CHANGED
@@ -11,12 +11,12 @@ export { u as useRequest } from './shared/vue.B8VvC8d2.mjs';
11
11
  export { u as useRpc } from './shared/vue.D8zNWw2t.mjs';
12
12
  export { S as SelectedWalletAccountProvider, c as createSelectedWalletAccountContext, p as provideSelectedWalletAccount, s as selectedWalletAccountInjectionKey, u as useSelectedWalletAccount } from './shared/vue.BngCaeXJ.mjs';
13
13
  export { u as useSendTransaction, a as useSendTransactions } from './shared/vue.CLAqNcLp.mjs';
14
- export { u as useSignMessage } from './shared/vue.DbJG4-ku.mjs';
15
- export { u as useSignAndSendTransaction } from './shared/vue.4ne5EBD9.mjs';
16
- export { u as useSignTransactions } from './shared/vue.CW-1AuSO.mjs';
17
- export { P as PartialSignAndSendError, u as useSignAndSendTransactions } from './shared/vue.UrCjmf0T.mjs';
14
+ export { u as useSignMessage } from './shared/vue.Ddf_Cdjx.mjs';
15
+ export { u as useSignAndSendTransaction } from './shared/vue.BTD4usyi.mjs';
16
+ export { u as useSignTransactions } from './shared/vue.BHBifdbc.mjs';
17
+ export { P as PartialSignAndSendError, u as useSignAndSendTransactions } from './shared/vue.C-7v1l8q.mjs';
18
18
  export { u as useSignatureStatus } from './shared/vue.Bu2cQ690.mjs';
19
- export { u as useSignIn } from './shared/vue.BBN9aU6D.mjs';
19
+ export { u as useSignIn } from './shared/vue.SeuJipQ8.mjs';
20
20
  export { t as tryUseSolana, u as useSolana } from './shared/vue.CcOZ9858.mjs';
21
21
  export { u as useSolanaClient } from './shared/vue.CZApWQAY.mjs';
22
22
  export { u as useSubscription } from './shared/vue.D5pqR5Fa.mjs';
@@ -25,7 +25,7 @@ export { u as useTokenBalance } from './shared/vue.FehFeE3w.mjs';
25
25
  export { u as useTrackedData } from './shared/vue.BNJTXSnQ.mjs';
26
26
  export { u as useTransaction } from './shared/vue.5euWd6-V.mjs';
27
27
  export { g as getConfirmedTransactionStatus, u as useTransactionConfirmation } from './shared/vue.DPwdqRO_.mjs';
28
- export { u as useWallet } from './shared/vue.DY9VadLH.mjs';
28
+ export { u as useWallet } from './shared/vue.Bc_Kbwr5.mjs';
29
29
  export { u as useWallets } from './shared/vue.DyLgoSbX.mjs';
30
30
  import { s as solanaInjectionKey } from './shared/vue.D_P5SqqD.mjs';
31
31
  import { createSolanaError, normalizeSolanaError } from '@vue-solana/core/errors';
@@ -33,7 +33,7 @@ export { SolanaError, isSolanaError } from '@vue-solana/core/errors';
33
33
  import { isSolanaMobileWalletSupported } from '@vue-solana/core/mobile-wallet-support';
34
34
  import { createSolanaContext } from '@vue-solana/core/rpc';
35
35
  import { withTimeout } from '@vue-solana/core/timeout';
36
- import { getRegisteredSolanaWallets, getSolanaChain, adaptSolanaStandardWallet, subscribeSolanaWallets } from '@vue-solana/core/wallet-standard';
36
+ import { getRegisteredSolanaWallets, getSolanaChain, adaptSolanaStandardWallet, disconnectSolanaStandardWallet, subscribeSolanaWallets } from '@vue-solana/core/wallet-standard';
37
37
  import { shallowRef, ref, triggerRef } from 'vue';
38
38
  import { handleSolanaIosWalletCallback, getSolanaIosWallets, isSolanaIosWalletInfo, adaptSolanaIosWallet } from '@vue-solana/core/ios-wallet';
39
39
  export * from '@vue-solana/core/types';
@@ -112,6 +112,7 @@ function getLocalStorage() {
112
112
  }
113
113
  }
114
114
 
115
+ const DISCONNECT_TIMEOUT_MS = 2e3;
115
116
  function createSolanaWalletRegistry(options) {
116
117
  const adaptedWallets = /* @__PURE__ */ new WeakMap();
117
118
  const adaptedPrimitiveWallets = /* @__PURE__ */ new Map();
@@ -126,25 +127,31 @@ function createSolanaWalletRegistry(options) {
126
127
  if (cachedIosWallet) {
127
128
  return cachedIosWallet;
128
129
  }
129
- const iosAdapter = adaptSolanaIosWallet(walletInfo, {
130
- chain: getSolanaChain(options.cluster),
131
- cluster: options.cluster,
132
- onChange: options.onWalletChange,
133
- ...options.iosWallet || {}
134
- });
130
+ const iosAdapter = makeConnectExclusive(
131
+ adaptSolanaIosWallet(walletInfo, {
132
+ chain: getSolanaChain(options.cluster),
133
+ cluster: options.cluster,
134
+ onChange: options.onWalletChange,
135
+ ...options.iosWallet || {}
136
+ }),
137
+ walletInfo
138
+ );
135
139
  adaptedWallets.set(walletInfo.wallet, iosAdapter);
136
140
  return trackAdapter(iosAdapter);
137
141
  }
138
142
  if (!isObject(walletInfo.wallet)) {
139
- const primitiveKey = `${walletInfo.name}::${String(walletInfo.wallet)}`;
143
+ const primitiveKey = getPrimitiveWalletKey(walletInfo);
140
144
  const cachedPrimitiveWallet = adaptedPrimitiveWallets.get(primitiveKey);
141
145
  if (cachedPrimitiveWallet) {
142
146
  return cachedPrimitiveWallet;
143
147
  }
144
- const primitiveAdapter = adaptSolanaStandardWallet(walletInfo, {
145
- chain: getSolanaChain(options.cluster),
146
- onChange: options.onWalletChange
147
- });
148
+ const primitiveAdapter = makeConnectExclusive(
149
+ adaptSolanaStandardWallet(walletInfo, {
150
+ chain: getSolanaChain(options.cluster),
151
+ onChange: options.onWalletChange
152
+ }),
153
+ walletInfo
154
+ );
148
155
  adaptedPrimitiveWallets.set(primitiveKey, primitiveAdapter);
149
156
  return trackAdapter(primitiveAdapter);
150
157
  }
@@ -152,30 +159,19 @@ function createSolanaWalletRegistry(options) {
152
159
  if (cachedWallet) {
153
160
  return cachedWallet;
154
161
  }
155
- const adaptedWallet = adaptSolanaStandardWallet(walletInfo, {
156
- chain: getSolanaChain(options.cluster),
157
- onChange: options.onWalletChange
158
- });
159
- const cachedAdapter = new Proxy(adaptedWallet, {
160
- get(target, property) {
161
- if (property === "connect") {
162
- return connectAndDisconnectOthers;
163
- }
164
- const value = Reflect.get(target, property);
165
- return typeof value === "function" ? value.bind(target) : value;
166
- }
167
- });
168
- async function connectAndDisconnectOthers() {
169
- await adaptedWallet.connect();
170
- await Promise.all(
171
- Array.from(getCachedWallets()).map(
172
- (otherWallet) => otherWallet !== cachedAdapter && otherWallet.connected ? otherWallet.disconnect() : void 0
173
- )
174
- );
175
- }
162
+ const cachedAdapter = makeConnectExclusive(
163
+ adaptSolanaStandardWallet(walletInfo, {
164
+ chain: getSolanaChain(options.cluster),
165
+ onChange: options.onWalletChange
166
+ }),
167
+ walletInfo
168
+ );
176
169
  adaptedWallets.set(walletInfo.wallet, cachedAdapter);
177
170
  return trackAdapter(cachedAdapter);
178
171
  }
172
+ function getCachedAdapter(walletInfo) {
173
+ return isObject(walletInfo.wallet) ? adaptedWallets.get(walletInfo.wallet) : adaptedPrimitiveWallets.get(getPrimitiveWalletKey(walletInfo));
174
+ }
179
175
  function getDiscoveredWallets() {
180
176
  return [
181
177
  ...getRegisteredSolanaWallets(),
@@ -190,17 +186,41 @@ function createSolanaWalletRegistry(options) {
190
186
  try {
191
187
  handleSolanaIosWalletCallback({ clearUrl: true });
192
188
  } catch (cause) {
189
+ options.onError?.(cause);
193
190
  }
194
191
  }
195
- function* getCachedWallets() {
196
- for (const walletInfo of options.getWalletInfos()) {
197
- if (isObject(walletInfo.wallet)) {
198
- const cachedWallet = adaptedWallets.get(walletInfo.wallet);
199
- if (cachedWallet) {
200
- yield cachedWallet;
192
+ function makeConnectExclusive(adapter, walletInfo) {
193
+ const connect = adapter.connect.bind(adapter);
194
+ adapter.connect = async () => {
195
+ await connect();
196
+ await disconnectOtherWallets(walletInfo, adapter);
197
+ };
198
+ return adapter;
199
+ }
200
+ async function disconnectOtherWallets(currentWallet, currentAdapter) {
201
+ await Promise.all(
202
+ options.getWalletInfos().map(async (walletInfo) => {
203
+ const cachedWallet = getCachedAdapter(walletInfo);
204
+ if (cachedWallet === currentAdapter || isSameWalletInfo(walletInfo, currentWallet)) {
205
+ return;
201
206
  }
202
- }
207
+ try {
208
+ await withTimeout(
209
+ disconnectWallet(walletInfo, cachedWallet),
210
+ DISCONNECT_TIMEOUT_MS,
211
+ () => new Error(`Solana wallet "${walletInfo.name}" did not disconnect within its timeout`)
212
+ );
213
+ } catch {
214
+ }
215
+ })
216
+ );
217
+ }
218
+ async function disconnectWallet(walletInfo, cachedWallet) {
219
+ if (cachedWallet) {
220
+ await cachedWallet.disconnect();
221
+ return;
203
222
  }
223
+ await disconnectSolanaStandardWallet(walletInfo);
204
224
  }
205
225
  function disposeAllAdaptedWallets() {
206
226
  for (const adapter of trackedAdapters) {
@@ -217,6 +237,12 @@ function createSolanaWalletRegistry(options) {
217
237
  function isObject(value) {
218
238
  return typeof value === "object" && value !== null || typeof value === "function";
219
239
  }
240
+ function getPrimitiveWalletKey(walletInfo) {
241
+ return `${walletInfo.name}::${String(walletInfo.wallet)}`;
242
+ }
243
+ function isSameWalletInfo(a, b) {
244
+ return a.wallet === b.wallet || a.name === b.name && a.source === b.source;
245
+ }
220
246
 
221
247
  const RPC_CHECK_TIMEOUT_MS = 1e4;
222
248
  function createSolanaPlugin(options = {}) {
@@ -235,7 +261,11 @@ function createSolanaPlugin(options = {}) {
235
261
  cluster: context.cluster,
236
262
  iosWallet: options.iosWallet,
237
263
  getWalletInfos: () => wallets.value,
238
- onWalletChange: () => triggerRef(wallet)
264
+ onWalletChange: () => triggerRef(wallet),
265
+ onError: (cause) => {
266
+ error.value = normalizeSolanaError(cause, "WALLET_FAILURE");
267
+ logDevError("Failed to handle Solana iOS wallet callback", cause);
268
+ }
239
269
  });
240
270
  let unsubscribeWallets = null;
241
271
  let mobileWalletRegistrationPromise = null;
@@ -267,6 +297,7 @@ function createSolanaPlugin(options = {}) {
267
297
  }
268
298
  status.value = "error";
269
299
  error.value = normalizeSolanaError(cause, "RPC_FAILURE");
300
+ logDevError("Connection failed", cause);
270
301
  }
271
302
  }
272
303
  function refreshWallets() {
@@ -286,6 +317,7 @@ function createSolanaPlugin(options = {}) {
286
317
  const persistedWallet = readSelectedWallet();
287
318
  if (persistedWallet.error) {
288
319
  error.value = persistedWallet.error;
320
+ logDevError("Failed to read the persisted Solana wallet", persistedWallet.error);
289
321
  }
290
322
  restoredWallet = persistedWallet.wallet ? wallets.value.find(
291
323
  (nextWallet) => isSameWallet(nextWallet, persistedWallet.wallet)
@@ -316,6 +348,8 @@ function createSolanaPlugin(options = {}) {
316
348
  });
317
349
  refreshWallets();
318
350
  }).catch((cause) => {
351
+ error.value = normalizeSolanaError(cause, "WALLET_FAILURE");
352
+ logDevError("Failed to register Solana mobile wallet", cause);
319
353
  }).finally(() => {
320
354
  mobileWalletRegistrationPromise = null;
321
355
  });
@@ -326,6 +360,7 @@ function createSolanaPlugin(options = {}) {
326
360
  const storageError = writeSelectedWallet(nextWallet);
327
361
  if (storageError) {
328
362
  error.value = storageError;
363
+ logDevError("Failed to persist the selected Solana wallet", storageError);
329
364
  }
330
365
  }
331
366
  function autoConnectWallet(walletInfo) {
@@ -339,6 +374,8 @@ function createSolanaPlugin(options = {}) {
339
374
  }
340
375
  attemptedAutoConnectWallet = storageValue;
341
376
  void activeWallet.connect().catch((cause) => {
377
+ error.value = normalizeSolanaError(cause, "WALLET_FAILURE");
378
+ logDevError("Failed to auto-connect Solana wallet", cause);
342
379
  }).finally(() => {
343
380
  triggerRef(wallet);
344
381
  });
@@ -360,6 +397,7 @@ function createSolanaPlugin(options = {}) {
360
397
  const storageError = writeSelectedWallet(null);
361
398
  if (storageError) {
362
399
  error.value = storageError;
400
+ logDevError("Failed to clear the persisted Solana wallet", storageError);
363
401
  }
364
402
  }
365
403
  };
@@ -378,11 +416,13 @@ function createSolanaPlugin(options = {}) {
378
416
  };
379
417
  if (typeof window !== "undefined") {
380
418
  bootstrapId = window.setTimeout(() => {
419
+ void checkConnection();
381
420
  try {
382
421
  refreshWallets();
383
422
  } catch (cause) {
423
+ error.value = normalizeSolanaError(cause, "WALLET_FAILURE");
424
+ logDevError("Failed to refresh Solana wallets", cause);
384
425
  }
385
- void checkConnection();
386
426
  }, 0);
387
427
  }
388
428
  },
@@ -395,6 +435,24 @@ function createSolanaPlugin(options = {}) {
395
435
  function isSameWallet(wallet, selectedWallet) {
396
436
  return wallet.name === selectedWallet?.name && wallet.source === selectedWallet.source && wallet.platform === selectedWallet.platform;
397
437
  }
438
+ function isDevEnvironment() {
439
+ try {
440
+ if (import.meta.env?.DEV === true) {
441
+ return true;
442
+ }
443
+ } catch {
444
+ }
445
+ if (typeof process === "undefined") {
446
+ return false;
447
+ }
448
+ const mode = process.env?.NODE_ENV;
449
+ return mode === "development" || mode === "test";
450
+ }
451
+ function logDevError(message, cause) {
452
+ if (isDevEnvironment()) {
453
+ console.error(`[Vue Solana] ${message}`, cause);
454
+ }
455
+ }
398
456
  const VueSolana = createSolanaPlugin;
399
457
 
400
458
  export { VueSolana, createSolanaPlugin, solanaInjectionKey };
@@ -1,7 +1,7 @@
1
1
  import { createNoWalletSelectedError, assertWalletCanSignTransactions } from '@vue-solana/core/wallet';
2
2
  import { shallowRef } from 'vue';
3
3
  import { u as useExecution } from './vue.BiKE9Xuv.mjs';
4
- import { u as useWallet } from './vue.DY9VadLH.mjs';
4
+ import { u as useWallet } from './vue.Bc_Kbwr5.mjs';
5
5
 
6
6
  function useSignTransactions() {
7
7
  const { wallet } = useWallet();
@@ -4,7 +4,7 @@ import { signAndSendTransaction, confirmTransactionSignature } from '@vue-solana
4
4
  import { createNoWalletSelectedError } from '@vue-solana/core/wallet';
5
5
  import { ref, computed } from 'vue';
6
6
  import { u as useSolanaClient } from './vue.CZApWQAY.mjs';
7
- import { u as useWallet } from './vue.DY9VadLH.mjs';
7
+ import { u as useWallet } from './vue.Bc_Kbwr5.mjs';
8
8
  import { g as getConfirmedTransactionStatus } from './vue.DPwdqRO_.mjs';
9
9
 
10
10
  const SIGN_AND_SEND_TIMEOUT_MS = 12e4;
@@ -8,6 +8,12 @@ function useWallet() {
8
8
  const wallet = solana.wallet;
9
9
  const connecting = ref(false);
10
10
  const disconnecting = ref(false);
11
+ function clearWalletError() {
12
+ const current = solana.error.value;
13
+ if (current?.code === "WALLET_FAILURE" || current?.code === "USER_REJECTED") {
14
+ solana.error.value = null;
15
+ }
16
+ }
11
17
  async function connect() {
12
18
  if (connecting.value || wallet.value?.connecting) {
13
19
  return;
@@ -22,9 +28,10 @@ function useWallet() {
22
28
  triggerRef(wallet);
23
29
  await connection;
24
30
  assertWalletConnected(activeWallet);
31
+ clearWalletError();
25
32
  triggerRef(wallet);
26
33
  } catch (error) {
27
- const normalizedError = normalizeSolanaError(error, "RPC_FAILURE");
34
+ const normalizedError = normalizeSolanaError(error, "WALLET_FAILURE");
28
35
  triggerRef(wallet);
29
36
  throw normalizedError;
30
37
  } finally {
@@ -39,9 +46,10 @@ function useWallet() {
39
46
  disconnecting.value = true;
40
47
  try {
41
48
  await activeWallet.disconnect();
49
+ clearWalletError();
42
50
  triggerRef(wallet);
43
51
  } catch (error) {
44
- const normalizedError = normalizeSolanaError(error, "RPC_FAILURE");
52
+ const normalizedError = normalizeSolanaError(error, "WALLET_FAILURE");
45
53
  triggerRef(wallet);
46
54
  throw normalizedError;
47
55
  } finally {
@@ -3,7 +3,7 @@ import { withSolanaTimeout } from '@vue-solana/core/timeout';
3
3
  import { createNoWalletSelectedError, assertWalletCanSignAndSendTransactions } from '@vue-solana/core/wallet';
4
4
  import { shallowRef } from 'vue';
5
5
  import { u as useExecution } from './vue.BiKE9Xuv.mjs';
6
- import { u as useWallet } from './vue.DY9VadLH.mjs';
6
+ import { u as useWallet } from './vue.Bc_Kbwr5.mjs';
7
7
 
8
8
  const SIGN_AND_SEND_TIMEOUT_MS = 12e4;
9
9
  class PartialSignAndSendError extends SolanaError {
@@ -1,7 +1,7 @@
1
1
  import { createNoWalletSelectedError, assertWalletCanSignMessage } from '@vue-solana/core/wallet';
2
2
  import { ref } from 'vue';
3
3
  import { u as useExecution } from './vue.BiKE9Xuv.mjs';
4
- import { u as useWallet } from './vue.DY9VadLH.mjs';
4
+ import { u as useWallet } from './vue.Bc_Kbwr5.mjs';
5
5
 
6
6
  function useSignMessage() {
7
7
  const { wallet } = useWallet();
@@ -1,7 +1,7 @@
1
1
  import { createNoWalletSelectedError, assertWalletCanSignIn } from '@vue-solana/core/wallet';
2
2
  import { shallowRef } from 'vue';
3
3
  import { u as useExecution } from './vue.BiKE9Xuv.mjs';
4
- import { u as useWallet } from './vue.DY9VadLH.mjs';
4
+ import { u as useWallet } from './vue.Bc_Kbwr5.mjs';
5
5
 
6
6
  function useSignIn() {
7
7
  const { wallet } = useWallet();
@@ -1 +1 @@
1
- export { u as useSignAndSendTransaction } from './shared/vue.4ne5EBD9.mjs';
1
+ export { u as useSignAndSendTransaction } from './shared/vue.BTD4usyi.mjs';
@@ -1 +1 @@
1
- export { P as PartialSignAndSendError, u as useSignAndSendTransactions } from './shared/vue.UrCjmf0T.mjs';
1
+ export { P as PartialSignAndSendError, u as useSignAndSendTransactions } from './shared/vue.C-7v1l8q.mjs';
@@ -1 +1 @@
1
- export { u as useSignIn } from './shared/vue.BBN9aU6D.mjs';
1
+ export { u as useSignIn } from './shared/vue.SeuJipQ8.mjs';
@@ -1 +1 @@
1
- export { u as useSignMessage } from './shared/vue.DbJG4-ku.mjs';
1
+ export { u as useSignMessage } from './shared/vue.Ddf_Cdjx.mjs';
@@ -1 +1 @@
1
- export { u as useSignTransactions } from './shared/vue.CW-1AuSO.mjs';
1
+ export { u as useSignTransactions } from './shared/vue.BHBifdbc.mjs';
@@ -1 +1 @@
1
- export { u as useWallet } from './shared/vue.DY9VadLH.mjs';
1
+ export { u as useWallet } from './shared/vue.Bc_Kbwr5.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue-solana/vue",
3
- "version": "4.0.0-rc.0",
3
+ "version": "4.0.0",
4
4
  "description": "Vue plugin and composables for Solana applications.",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -178,7 +178,7 @@
178
178
  "access": "public"
179
179
  },
180
180
  "dependencies": {
181
- "@vue-solana/core": "4.0.0-rc.0"
181
+ "@vue-solana/core": "4.0.0"
182
182
  },
183
183
  "peerDependencies": {
184
184
  "vue": "^3.5.0"