@vue-solana/vue 0.3.2 → 0.4.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
@@ -11,6 +11,7 @@ New to Solana? Start with the official docs and the project concepts guide:
11
11
  - [Solana Clusters](https://solana.com/docs/references/clusters)
12
12
  - [Vue Solana Concepts Guide](https://vue-solana-docs.vercel.app/concepts/solana-for-vue-developers)
13
13
  - [`@vue-solana/vue` docs](https://vue-solana-docs.vercel.app/packages/vue)
14
+ - [Agent Skill](https://vue-solana-docs.vercel.app/agent-skill)
14
15
  - [Live demo](https://vue-solana-docs.vercel.app/demo)
15
16
 
16
17
  ## Install
@@ -151,9 +152,9 @@ const { publicKey, connected, connecting, connect, disconnect } = useWallet();
151
152
  </template>
152
153
  ```
153
154
 
154
- 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. `connect()` works after selecting a discovered wallet or configuring a custom `SolanaWallet`.
155
+ 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`.
155
156
 
156
- iOS browser wallet adapters and desktop native app wallet adapters are planned but not implemented yet.
157
+ Desktop native app wallet adapters are planned but not implemented yet.
157
158
 
158
159
  Composables return inert SSR-safe state when no plugin context is available. Real RPC and wallet operations still require the plugin-provided client context.
159
160
 
@@ -183,6 +184,16 @@ Docs: <a href="https://vue-solana-docs.vercel.app/examples/vue-vite" target="_bl
183
184
 
184
185
  Live demo: [vue-solana-docs.vercel.app/demo](https://vue-solana-docs.vercel.app/demo)
185
186
 
187
+ ## AI Agent Skill
188
+
189
+ If you use an AI coding agent, install the Vue Solana Agent Skill for plugin setup, composable imports, wallet flow guidance, transaction gotchas, and verification commands:
190
+
191
+ ```sh
192
+ npx skills add vue-solana/vue-solana --skill vue-solana
193
+ ```
194
+
195
+ Docs: [Vue Solana Agent Skill](https://vue-solana-docs.vercel.app/agent-skill)
196
+
186
197
  ## API
187
198
 
188
199
  - `createSolanaPlugin(options?)`: installs the Vue Solana context.
package/dist/index.cjs CHANGED
@@ -8,6 +8,7 @@ const useSolana = require('./shared/vue.C4tLiG3R.cjs');
8
8
  const useTransaction = require('./shared/vue.CNhelr8H.cjs');
9
9
  const useWallet = require('./shared/vue.CwPjPFN6.cjs');
10
10
  const useWallets = require('./shared/vue.P9tgeC5S.cjs');
11
+ const iosWallet = require('@vue-solana/core/ios-wallet');
11
12
  const walletStandard = require('@vue-solana/core/wallet-standard');
12
13
  const rpc = require('@vue-solana/core/rpc');
13
14
  const vue = require('vue');
@@ -66,9 +67,10 @@ function createSolanaPlugin(options = {}) {
66
67
  }
67
68
  function refreshWallets() {
68
69
  unsubscribeWallets ??= walletStandard.subscribeSolanaWallets(refreshWallets);
69
- wallets.value = walletStandard.getRegisteredSolanaWallets();
70
+ handleIosWalletCallback();
71
+ wallets.value = getDiscoveredWallets();
70
72
  if (selectedWallet.value) {
71
- selectedWallet.value = wallets.value.find((nextWallet) => nextWallet.name === selectedWallet.value?.name) ?? null;
73
+ selectedWallet.value = wallets.value.find((nextWallet) => isSameWallet(nextWallet, selectedWallet.value)) ?? null;
72
74
  if (!selectedWallet.value) {
73
75
  wallet.value = options.wallet ?? null;
74
76
  }
@@ -83,7 +85,7 @@ function createSolanaPlugin(options = {}) {
83
85
  chains: [walletStandard.getSolanaChain(context.cluster)],
84
86
  ...options.mobileWallet || {}
85
87
  });
86
- wallets.value = walletStandard.getRegisteredSolanaWallets();
88
+ wallets.value = getDiscoveredWallets();
87
89
  }).catch((cause) => {
88
90
  console.error("[Vue Solana] Mobile wallet registration failed", cause);
89
91
  }).finally(() => {
@@ -95,6 +97,14 @@ function createSolanaPlugin(options = {}) {
95
97
  wallet.value = nextWallet ? getAdaptedWallet(nextWallet) : options.wallet ?? null;
96
98
  }
97
99
  function getAdaptedWallet(walletInfo) {
100
+ if (iosWallet.isSolanaIosWalletInfo(walletInfo)) {
101
+ return iosWallet.adaptSolanaIosWallet(walletInfo, {
102
+ chain: walletStandard.getSolanaChain(context.cluster),
103
+ cluster: context.cluster,
104
+ onChange: () => vue.triggerRef(wallet),
105
+ ...options.iosWallet || {}
106
+ });
107
+ }
98
108
  if (!isObject(walletInfo.wallet)) {
99
109
  return walletStandard.adaptSolanaStandardWallet(walletInfo, {
100
110
  chain: walletStandard.getSolanaChain(context.cluster),
@@ -140,6 +150,23 @@ function createSolanaPlugin(options = {}) {
140
150
  adaptedWallets.set(walletInfo.wallet, cachedAdapter);
141
151
  return cachedAdapter;
142
152
  }
153
+ function getDiscoveredWallets() {
154
+ return [
155
+ ...walletStandard.getRegisteredSolanaWallets(),
156
+ ...options.iosWallet === false ? [] : iosWallet.getSolanaIosWallets({
157
+ chains: [walletStandard.getSolanaChain(context.cluster)],
158
+ cluster: context.cluster,
159
+ ...options.iosWallet || {}
160
+ })
161
+ ];
162
+ }
163
+ function handleIosWalletCallback() {
164
+ try {
165
+ iosWallet.handleSolanaIosWalletCallback({ clearUrl: true });
166
+ } catch (cause) {
167
+ console.error("[Vue Solana] iOS wallet callback failed", cause);
168
+ }
169
+ }
143
170
  function* getCachedWallets() {
144
171
  for (const walletInfo of wallets.value) {
145
172
  if (isObject(walletInfo.wallet)) {
@@ -178,6 +205,9 @@ function createSolanaPlugin(options = {}) {
178
205
  function isObject(value) {
179
206
  return typeof value === "object" && value !== null || typeof value === "function";
180
207
  }
208
+ function isSameWallet(wallet, selectedWallet) {
209
+ return wallet.name === selectedWallet?.name && wallet.source === selectedWallet.source && wallet.platform === selectedWallet.platform;
210
+ }
181
211
  const VueSolana = createSolanaPlugin;
182
212
  function withTimeout(promise, timeoutMs, message) {
183
213
  let timeoutId;
package/dist/index.d.cts CHANGED
@@ -7,6 +7,7 @@ export { UseTransactionOptions, useTransaction } from './useTransaction.cjs';
7
7
  export { useWallet } from './useWallet.cjs';
8
8
  export { useWallets } from './useWallets.cjs';
9
9
  export { S as SolanaConnectionStatus, V as VueSolanaContext, s as solanaInjectionKey } from './shared/vue.DGhodYJh.cjs';
10
+ import { GetSolanaIosWalletsOptions } from '@vue-solana/core/ios-wallet';
10
11
  import { RegisterSolanaMobileWalletOptions } from '@vue-solana/core/mobile-wallet';
11
12
  import { SolanaConfig, SolanaWallet } from '@vue-solana/core/types';
12
13
  import { App } from 'vue';
@@ -15,6 +16,7 @@ import '@solana/web3-compat';
15
16
  interface VueSolanaPluginOptions extends SolanaConfig {
16
17
  wallet?: SolanaWallet | null;
17
18
  mobileWallet?: false | RegisterSolanaMobileWalletOptions;
19
+ iosWallet?: false | GetSolanaIosWalletsOptions;
18
20
  }
19
21
  declare function createSolanaPlugin(options?: VueSolanaPluginOptions): {
20
22
  install(app: App): void;
package/dist/index.d.mts CHANGED
@@ -7,6 +7,7 @@ export { UseTransactionOptions, useTransaction } from './useTransaction.mjs';
7
7
  export { useWallet } from './useWallet.mjs';
8
8
  export { useWallets } from './useWallets.mjs';
9
9
  export { S as SolanaConnectionStatus, V as VueSolanaContext, s as solanaInjectionKey } from './shared/vue.DGhodYJh.mjs';
10
+ import { GetSolanaIosWalletsOptions } from '@vue-solana/core/ios-wallet';
10
11
  import { RegisterSolanaMobileWalletOptions } from '@vue-solana/core/mobile-wallet';
11
12
  import { SolanaConfig, SolanaWallet } from '@vue-solana/core/types';
12
13
  import { App } from 'vue';
@@ -15,6 +16,7 @@ import '@solana/web3-compat';
15
16
  interface VueSolanaPluginOptions extends SolanaConfig {
16
17
  wallet?: SolanaWallet | null;
17
18
  mobileWallet?: false | RegisterSolanaMobileWalletOptions;
19
+ iosWallet?: false | GetSolanaIosWalletsOptions;
18
20
  }
19
21
  declare function createSolanaPlugin(options?: VueSolanaPluginOptions): {
20
22
  install(app: App): void;
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export { UseTransactionOptions, useTransaction } from './useTransaction.js';
7
7
  export { useWallet } from './useWallet.js';
8
8
  export { useWallets } from './useWallets.js';
9
9
  export { S as SolanaConnectionStatus, V as VueSolanaContext, s as solanaInjectionKey } from './shared/vue.DGhodYJh.js';
10
+ import { GetSolanaIosWalletsOptions } from '@vue-solana/core/ios-wallet';
10
11
  import { RegisterSolanaMobileWalletOptions } from '@vue-solana/core/mobile-wallet';
11
12
  import { SolanaConfig, SolanaWallet } from '@vue-solana/core/types';
12
13
  import { App } from 'vue';
@@ -15,6 +16,7 @@ import '@solana/web3-compat';
15
16
  interface VueSolanaPluginOptions extends SolanaConfig {
16
17
  wallet?: SolanaWallet | null;
17
18
  mobileWallet?: false | RegisterSolanaMobileWalletOptions;
19
+ iosWallet?: false | GetSolanaIosWalletsOptions;
18
20
  }
19
21
  declare function createSolanaPlugin(options?: VueSolanaPluginOptions): {
20
22
  install(app: App): void;
package/dist/index.mjs CHANGED
@@ -7,7 +7,8 @@ export { t as tryUseSolana, u as useSolana } from './shared/vue.1M_c5FWA.mjs';
7
7
  export { u as useTransaction } from './shared/vue.CuhLIeDx.mjs';
8
8
  export { u as useWallet } from './shared/vue.DYf_CRDv.mjs';
9
9
  export { u as useWallets } from './shared/vue.h-uS8MXN.mjs';
10
- import { subscribeSolanaWallets, getRegisteredSolanaWallets, adaptSolanaStandardWallet, getSolanaChain } from '@vue-solana/core/wallet-standard';
10
+ import { isSolanaIosWalletInfo, adaptSolanaIosWallet, handleSolanaIosWalletCallback, getSolanaIosWallets } from '@vue-solana/core/ios-wallet';
11
+ import { subscribeSolanaWallets, getSolanaChain, adaptSolanaStandardWallet, getRegisteredSolanaWallets } from '@vue-solana/core/wallet-standard';
11
12
  import { createSolanaContext } from '@vue-solana/core/rpc';
12
13
  import { shallowRef, ref, triggerRef } from 'vue';
13
14
  import '@solana/web3-compat';
@@ -65,9 +66,10 @@ function createSolanaPlugin(options = {}) {
65
66
  }
66
67
  function refreshWallets() {
67
68
  unsubscribeWallets ??= subscribeSolanaWallets(refreshWallets);
68
- wallets.value = getRegisteredSolanaWallets();
69
+ handleIosWalletCallback();
70
+ wallets.value = getDiscoveredWallets();
69
71
  if (selectedWallet.value) {
70
- selectedWallet.value = wallets.value.find((nextWallet) => nextWallet.name === selectedWallet.value?.name) ?? null;
72
+ selectedWallet.value = wallets.value.find((nextWallet) => isSameWallet(nextWallet, selectedWallet.value)) ?? null;
71
73
  if (!selectedWallet.value) {
72
74
  wallet.value = options.wallet ?? null;
73
75
  }
@@ -82,7 +84,7 @@ function createSolanaPlugin(options = {}) {
82
84
  chains: [getSolanaChain(context.cluster)],
83
85
  ...options.mobileWallet || {}
84
86
  });
85
- wallets.value = getRegisteredSolanaWallets();
87
+ wallets.value = getDiscoveredWallets();
86
88
  }).catch((cause) => {
87
89
  console.error("[Vue Solana] Mobile wallet registration failed", cause);
88
90
  }).finally(() => {
@@ -94,6 +96,14 @@ function createSolanaPlugin(options = {}) {
94
96
  wallet.value = nextWallet ? getAdaptedWallet(nextWallet) : options.wallet ?? null;
95
97
  }
96
98
  function getAdaptedWallet(walletInfo) {
99
+ if (isSolanaIosWalletInfo(walletInfo)) {
100
+ return adaptSolanaIosWallet(walletInfo, {
101
+ chain: getSolanaChain(context.cluster),
102
+ cluster: context.cluster,
103
+ onChange: () => triggerRef(wallet),
104
+ ...options.iosWallet || {}
105
+ });
106
+ }
97
107
  if (!isObject(walletInfo.wallet)) {
98
108
  return adaptSolanaStandardWallet(walletInfo, {
99
109
  chain: getSolanaChain(context.cluster),
@@ -139,6 +149,23 @@ function createSolanaPlugin(options = {}) {
139
149
  adaptedWallets.set(walletInfo.wallet, cachedAdapter);
140
150
  return cachedAdapter;
141
151
  }
152
+ function getDiscoveredWallets() {
153
+ return [
154
+ ...getRegisteredSolanaWallets(),
155
+ ...options.iosWallet === false ? [] : getSolanaIosWallets({
156
+ chains: [getSolanaChain(context.cluster)],
157
+ cluster: context.cluster,
158
+ ...options.iosWallet || {}
159
+ })
160
+ ];
161
+ }
162
+ function handleIosWalletCallback() {
163
+ try {
164
+ handleSolanaIosWalletCallback({ clearUrl: true });
165
+ } catch (cause) {
166
+ console.error("[Vue Solana] iOS wallet callback failed", cause);
167
+ }
168
+ }
142
169
  function* getCachedWallets() {
143
170
  for (const walletInfo of wallets.value) {
144
171
  if (isObject(walletInfo.wallet)) {
@@ -177,6 +204,9 @@ function createSolanaPlugin(options = {}) {
177
204
  function isObject(value) {
178
205
  return typeof value === "object" && value !== null || typeof value === "function";
179
206
  }
207
+ function isSameWallet(wallet, selectedWallet) {
208
+ return wallet.name === selectedWallet?.name && wallet.source === selectedWallet.source && wallet.platform === selectedWallet.platform;
209
+ }
180
210
  const VueSolana = createSolanaPlugin;
181
211
  function withTimeout(promise, timeoutMs, message) {
182
212
  let timeoutId;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue-solana/vue",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "Vue plugin and composables for Solana applications.",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -78,7 +78,7 @@
78
78
  "access": "public"
79
79
  },
80
80
  "dependencies": {
81
- "@vue-solana/core": "0.3.2"
81
+ "@vue-solana/core": "0.4.0"
82
82
  },
83
83
  "peerDependencies": {
84
84
  "@solana/web3-compat": "^0.0.21",