@vue-solana/vue 3.0.1 → 4.0.0-rc.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 +8 -4
- package/dist/index.d.ts +12 -0
- package/dist/index.mjs +79 -47
- package/dist/shared/{vue.CjSw0Hh1.mjs → vue.4ne5EBD9.mjs} +4 -4
- package/dist/shared/{vue.C9OOmvkD.mjs → vue.BBN9aU6D.mjs} +2 -2
- package/dist/shared/{vue.CsFY1mfz.mjs → vue.BXNjyJ2c.mjs} +1 -1
- package/dist/shared/{vue.DlihC5GG.mjs → vue.BiKE9Xuv.mjs} +6 -4
- package/dist/shared/{vue.CXB4NEMA.mjs → vue.Bu2cQ690.mjs} +47 -17
- package/dist/shared/{vue.CpkwC8Th.mjs → vue.C6OkOK2W.mjs} +1 -1
- package/dist/shared/{vue.B9uRpSDJ.mjs → vue.CAltY57B.mjs} +6 -3
- package/dist/shared/{vue.DDQxNX5q.mjs → vue.CELGI7de.mjs} +9 -9
- package/dist/shared/{vue.BxtOHzY_.mjs → vue.CLAqNcLp.mjs} +1 -1
- package/dist/shared/{vue.hG_FieA3.mjs → vue.CW-1AuSO.mjs} +2 -2
- package/dist/shared/{vue.Mxc8w6Qk.mjs → vue.CZApWQAY.mjs} +1 -1
- package/dist/shared/vue.CbmzveKF.mjs +44 -0
- package/dist/shared/{vue.CQh3AUE8.mjs → vue.CcOZ9858.mjs} +3 -5
- package/dist/shared/{vue.B-xtuLtD.mjs → vue.D2J7_NpQ.mjs} +2 -2
- package/dist/shared/{vue.BsGwt78R.mjs → vue.D8zNWw2t.mjs} +1 -1
- package/dist/shared/{vue.CaAgH2Xt.mjs → vue.DPwdqRO_.mjs} +3 -3
- package/dist/shared/{vue.DNKD6jqM.mjs → vue.DTpvqDyY.mjs} +3 -3
- package/dist/shared/{vue.D218Ow7t.mjs → vue.DY9VadLH.mjs} +1 -8
- package/dist/shared/vue.DZVdVfy1.mjs +7 -0
- package/dist/shared/{vue.CvenSbZZ.mjs → vue.DZhPXLZz.mjs} +4 -4
- package/dist/shared/{vue.o98pAmDg.mjs → vue.DbJG4-ku.mjs} +2 -2
- package/dist/shared/{vue.BFSboXMB.mjs → vue.DbJKnSrl.mjs} +3 -3
- package/dist/shared/{vue.1Qwco2kv.mjs → vue.DcZ_R_RH.mjs} +4 -4
- package/dist/shared/{vue.C_4qJDiF.mjs → vue.DyLgoSbX.mjs} +1 -1
- package/dist/shared/{vue.XlfH_nkc.mjs → vue.FehFeE3w.mjs} +3 -3
- package/dist/shared/{vue.C1JbUTpJ.mjs → vue.UrCjmf0T.mjs} +2 -2
- package/dist/swr.d.ts +7 -1
- package/dist/swr.mjs +16 -1
- package/dist/useAccountInfo.mjs +1 -1
- package/dist/useAirdrop.mjs +1 -1
- package/dist/useBalance.mjs +1 -1
- package/dist/useClientCapability.d.ts +6 -1
- package/dist/useClientCapability.mjs +1 -1
- package/dist/useConnection.d.ts +14 -7
- package/dist/useConnection.mjs +1 -1
- package/dist/useIdentity.mjs +1 -1
- package/dist/usePayer.mjs +1 -1
- package/dist/usePlanTransaction.mjs +1 -1
- package/dist/usePlanTransactions.mjs +1 -1
- package/dist/useProgramAccounts.mjs +1 -1
- package/dist/useRpc.d.ts +12 -6
- package/dist/useRpc.mjs +1 -1
- package/dist/useSelectedWalletAccount.d.ts +3 -0
- package/dist/useSendTransaction.mjs +1 -1
- package/dist/useSendTransactions.mjs +1 -1
- package/dist/useSignAndSendTransaction.mjs +1 -1
- package/dist/useSignAndSendTransactions.mjs +1 -1
- package/dist/useSignIn.mjs +1 -1
- package/dist/useSignMessage.mjs +1 -1
- package/dist/useSignTransactions.mjs +1 -1
- package/dist/useSignatureStatus.d.ts +0 -1
- package/dist/useSignatureStatus.mjs +1 -1
- package/dist/useSolana.mjs +1 -1
- package/dist/useSolanaClient.d.ts +12 -6
- package/dist/useSolanaClient.mjs +1 -1
- package/dist/useTokenAccounts.mjs +1 -1
- package/dist/useTokenBalance.mjs +1 -1
- package/dist/useTransactionConfirmation.mjs +1 -1
- package/dist/useWallet.mjs +1 -1
- package/dist/useWallets.mjs +1 -1
- package/package.json +8 -5
- package/dist/buffer-polyfill.d.mts +0 -2
- package/dist/index.d.mts +0 -64
- package/dist/kit.d.mts +0 -1
- package/dist/shared/vue.BGGixph-.d.mts +0 -5
- package/dist/shared/vue.Bfu1dCKe.mjs +0 -10
- package/dist/shared/vue.CGv0ip3w.mjs +0 -52
- package/dist/shared/vue.DL3z5PxP.d.mts +0 -21
- package/dist/swr.d.mts +0 -41
- package/dist/useAccountInfo.d.mts +0 -24
- package/dist/useAction.d.mts +0 -45
- package/dist/useAirdrop.d.mts +0 -27
- package/dist/useBalance.d.mts +0 -15
- package/dist/useClientCapability.d.mts +0 -39
- package/dist/useConnection.d.mts +0 -46
- package/dist/useIdentity.d.mts +0 -3
- package/dist/usePayer.d.mts +0 -18
- package/dist/usePlanTransaction.d.mts +0 -44
- package/dist/usePlanTransactions.d.mts +0 -5
- package/dist/useProgramAccounts.d.mts +0 -45
- package/dist/useRequest.d.mts +0 -73
- package/dist/useRpc.d.mts +0 -55
- package/dist/useSelectedWalletAccount.d.mts +0 -117
- package/dist/useSendTransaction.d.mts +0 -50
- package/dist/useSendTransactions.d.mts +0 -5
- package/dist/useSignAndSendTransaction.d.mts +0 -40
- package/dist/useSignAndSendTransactions.d.mts +0 -35
- package/dist/useSignIn.d.mts +0 -23
- package/dist/useSignMessage.d.mts +0 -236
- package/dist/useSignTransactions.d.mts +0 -24
- package/dist/useSignatureStatus.d.mts +0 -26
- package/dist/useSolana.d.mts +0 -9
- package/dist/useSolanaClient.d.mts +0 -45
- package/dist/useSubscription.d.mts +0 -70
- package/dist/useTokenAccounts.d.mts +0 -19
- package/dist/useTokenBalance.d.mts +0 -17
- package/dist/useTrackedData.d.mts +0 -98
- package/dist/useTransaction.d.mts +0 -27
- package/dist/useTransactionConfirmation.d.mts +0 -38
- package/dist/useWallet.d.mts +0 -31
- package/dist/useWallets.d.mts +0 -11
package/README.md
CHANGED
|
@@ -98,7 +98,7 @@ createApp(App).use(
|
|
|
98
98
|
|
|
99
99
|
Supported clusters are `mainnet` (legacy alias `mainnet-beta`), `devnet`, `testnet`, and `localnet`. Use `mainnet` for Solana mainnet; this is Solana's official mainnet cluster name.
|
|
100
100
|
|
|
101
|
-
`payer` and `payerSecretKey` are supported by direct Vue/core clients. A client-sent transaction requires a payer. Never put a raw secret or `payerSecretKey` in Nuxt public runtime config, and never ship a funded signing key to an end-user browser. The default `createSolanaPlugin()` client composes
|
|
101
|
+
`payer` and `payerSecretKey` are supported by direct Vue/core clients. A client-sent transaction requires a payer. Never put a raw secret or `payerSecretKey` in Nuxt public runtime config, and never ship a funded signing key to an end-user browser. The default `createSolanaPlugin()` client composes `solanaRpc()` followed by `rpcAirdrop()`; `solanaRpc()` installs `rpcTransactionPlanner()`, `rpcTransactionPlanSigningExecutor()`, and `rpcTransactionPlanSendingExecutor()` itself, so the client exposes RPC reads and subscriptions plus `planTransaction(s)`, `signTransaction(s)`, and `sendTransaction(s)` with no extra plugin. The old custom fallback sender is not used.
|
|
102
102
|
|
|
103
103
|
### Plugin Options
|
|
104
104
|
|
|
@@ -312,7 +312,7 @@ async function signIn() {
|
|
|
312
312
|
</template>
|
|
313
313
|
```
|
|
314
314
|
|
|
315
|
-
Message signing proves wallet ownership for flows like authentication challenges. It does not sign, submit, or authorize Solana transactions. For authentication, issue a server-generated nonce, include domain and expiration details in the message, and verify the returned signature server-side.
|
|
315
|
+
Message signing proves wallet ownership for flows like authentication challenges. It does not sign, submit, or authorize Solana transactions. For authentication, issue a server-generated nonce, include domain and expiration details in the message, and verify the returned signature server-side. The adapter also checks the signature against the account's public key before resolving, where Ed25519 (WebCrypto) is available — a best-effort client-side guard that rejects with `INVALID_SIGNATURE`, not a replacement for server-side verification.
|
|
316
316
|
|
|
317
317
|
## Transaction State
|
|
318
318
|
|
|
@@ -391,7 +391,7 @@ Configure a direct client with `payer` or `payerSecretKey`. `payerSecretKey` is
|
|
|
391
391
|
|
|
392
392
|
Use the client flow for automated or server-backed signing (airdrop faucet, cron jobs, relayer fees paid by your keypair), and the wallet flow when the end user must own and approve each transaction.
|
|
393
393
|
|
|
394
|
-
**Default client composition.** `createSolanaPlugin()` and `createSolanaClient()`
|
|
394
|
+
**Default client composition.** `createSolanaPlugin()` and `createSolanaClient()` compose `solanaRpc()` followed by `rpcAirdrop()` by default; `solanaRpc()` installs `rpcTransactionPlanner()`, `rpcTransactionPlanSigningExecutor()`, and `rpcTransactionPlanSendingExecutor()` itself. The old custom fallback sender is not used, so `useSendTransaction()` and `useSendTransactions()` do not need a second manual plugin installation. The official executor waits for `confirmed` commitment before `execute()` resolves and the composable reports `sent`. A custom client must still provide the planner and sending executor and a `payer`.
|
|
395
395
|
|
|
396
396
|
```ts
|
|
397
397
|
import { useSendTransaction } from "@vue-solana/vue/useSendTransaction";
|
|
@@ -488,6 +488,8 @@ import { useRequestSwr } from "@vue-solana/vue/swr";
|
|
|
488
488
|
const balance = useRequestSwr(["balance", address], () => client.rpc.getBalance(address).send());
|
|
489
489
|
```
|
|
490
490
|
|
|
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.
|
|
492
|
+
|
|
491
493
|
### Cancellation & Timeouts
|
|
492
494
|
|
|
493
495
|
`useRequest()`, `useSubscription()`, and `useTrackedData()` accept a `getAbortSignal` option — a factory called once per attempt (request) or connection (subscription/tracked data). It is the natural place for a timeout:
|
|
@@ -592,7 +594,9 @@ Docs: [Vue Solana Agent Skill](https://vue-solana-docs.vercel.app/agent-skill)
|
|
|
592
594
|
| ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
|
593
595
|
| `createSolanaPlugin(options?)` | Installs the Vue Solana context. |
|
|
594
596
|
| `VueSolana` | Alias for `createSolanaPlugin`. |
|
|
595
|
-
| `useSolana()` | Returns the full injected Solana context.
|
|
597
|
+
| `useSolana()` | Returns the full injected Solana context; throws when no plugin context is available. |
|
|
598
|
+
| `tryUseSolana()` | Returns the injected Solana context or `null` when no plugin context is available (SSR-safe). |
|
|
599
|
+
| `MissingClientCapabilityError` | Thrown by `useClientCapability()` (and client-sent composables) when the configured client lacks a required capability. |
|
|
596
600
|
| `useRpc()` | Returns cluster, endpoint, connection status, latest blockhash, the Kit `client`, and `checkConnection()`. |
|
|
597
601
|
| `useSolanaClient()` | Returns the injected Kit client as `{ client, rpc }`. The recommended RPC path. |
|
|
598
602
|
| `useConnection()` | Returns the Kit `client`. Deprecated in favor of `useSolanaClient()`. |
|
package/dist/index.d.ts
CHANGED
|
@@ -56,6 +56,18 @@ interface VueSolanaPlugin {
|
|
|
56
56
|
* context to consumers that run outside a component setup.
|
|
57
57
|
*/
|
|
58
58
|
context: VueSolanaContext | null;
|
|
59
|
+
/**
|
|
60
|
+
* Stops the wallet discovery subscription and the deferred bootstrap started
|
|
61
|
+
* by `install`. Vue has no plugin unmount hook, so call this from an app
|
|
62
|
+
* teardown hook (`app.onUnmount` in Nuxt, after `app.unmount()` in Vue).
|
|
63
|
+
* Safe to call more than once and before `install`. Without it the Wallet
|
|
64
|
+
* Standard subscription outlives the app that created it. After `dispose()`,
|
|
65
|
+
* `refreshWallets()` is a no-op, so a late mobile-wallet import or manual
|
|
66
|
+
* call cannot resurrect the subscription. A connected wallet stays
|
|
67
|
+
* connected; `dispose()` does not disconnect it or abort an in-flight
|
|
68
|
+
* `connect()`.
|
|
69
|
+
*/
|
|
70
|
+
dispose(): void;
|
|
59
71
|
}
|
|
60
72
|
declare function createSolanaPlugin(options?: VueSolanaPluginOptions): VueSolanaPlugin;
|
|
61
73
|
declare const VueSolana: typeof createSolanaPlugin;
|
package/dist/index.mjs
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
export { u as useAccountInfo } from './shared/vue.
|
|
1
|
+
export { u as useAccountInfo } from './shared/vue.DZhPXLZz.mjs';
|
|
2
2
|
export { u as useAction } from './shared/vue.DYk0Xfr3.mjs';
|
|
3
|
-
export { u as useAirdrop } from './shared/vue.
|
|
4
|
-
export { u as useBalance } from './shared/vue.
|
|
5
|
-
export { M as MissingClientCapabilityError, u as useClientCapability } from './shared/vue.
|
|
6
|
-
export { u as useConnection } from './shared/vue.
|
|
7
|
-
export { u as usePlanTransaction, a as usePlanTransactions } from './shared/vue.
|
|
8
|
-
export { u as useProgramAccounts } from './shared/vue.
|
|
9
|
-
export { u as useIdentity, a as usePayer } from './shared/vue.
|
|
3
|
+
export { u as useAirdrop } from './shared/vue.CELGI7de.mjs';
|
|
4
|
+
export { u as useBalance } from './shared/vue.DbJKnSrl.mjs';
|
|
5
|
+
export { M as MissingClientCapabilityError, u as useClientCapability } from './shared/vue.CAltY57B.mjs';
|
|
6
|
+
export { u as useConnection } from './shared/vue.C6OkOK2W.mjs';
|
|
7
|
+
export { u as usePlanTransaction, a as usePlanTransactions } from './shared/vue.BXNjyJ2c.mjs';
|
|
8
|
+
export { u as useProgramAccounts } from './shared/vue.DcZ_R_RH.mjs';
|
|
9
|
+
export { u as useIdentity, a as usePayer } from './shared/vue.D2J7_NpQ.mjs';
|
|
10
10
|
export { u as useRequest } from './shared/vue.B8VvC8d2.mjs';
|
|
11
|
-
export { u as useRpc } from './shared/vue.
|
|
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
|
-
export { u as useSendTransaction, a as useSendTransactions } from './shared/vue.
|
|
14
|
-
export { u as useSignMessage } from './shared/vue.
|
|
15
|
-
export { u as useSignAndSendTransaction } from './shared/vue.
|
|
16
|
-
export { u as useSignTransactions } from './shared/vue.
|
|
17
|
-
export { P as PartialSignAndSendError, u as useSignAndSendTransactions } from './shared/vue.
|
|
18
|
-
export { u as useSignatureStatus } from './shared/vue.
|
|
19
|
-
export { u as useSignIn } from './shared/vue.
|
|
20
|
-
export { t as tryUseSolana, u as useSolana } from './shared/vue.
|
|
21
|
-
export { u as useSolanaClient } from './shared/vue.
|
|
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';
|
|
18
|
+
export { u as useSignatureStatus } from './shared/vue.Bu2cQ690.mjs';
|
|
19
|
+
export { u as useSignIn } from './shared/vue.BBN9aU6D.mjs';
|
|
20
|
+
export { t as tryUseSolana, u as useSolana } from './shared/vue.CcOZ9858.mjs';
|
|
21
|
+
export { u as useSolanaClient } from './shared/vue.CZApWQAY.mjs';
|
|
22
22
|
export { u as useSubscription } from './shared/vue.D5pqR5Fa.mjs';
|
|
23
|
-
export { u as useTokenAccounts } from './shared/vue.
|
|
24
|
-
export { u as useTokenBalance } from './shared/vue.
|
|
23
|
+
export { u as useTokenAccounts } from './shared/vue.DTpvqDyY.mjs';
|
|
24
|
+
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
|
-
export { g as getConfirmedTransactionStatus, u as useTransactionConfirmation } from './shared/vue.
|
|
28
|
-
export { u as useWallet } from './shared/vue.
|
|
29
|
-
export { u as useWallets } from './shared/vue.
|
|
27
|
+
export { g as getConfirmedTransactionStatus, u as useTransactionConfirmation } from './shared/vue.DPwdqRO_.mjs';
|
|
28
|
+
export { u as useWallet } from './shared/vue.DY9VadLH.mjs';
|
|
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';
|
|
32
32
|
export { SolanaError, isSolanaError } from '@vue-solana/core/errors';
|
|
@@ -114,20 +114,39 @@ function getLocalStorage() {
|
|
|
114
114
|
|
|
115
115
|
function createSolanaWalletRegistry(options) {
|
|
116
116
|
const adaptedWallets = /* @__PURE__ */ new WeakMap();
|
|
117
|
+
const adaptedPrimitiveWallets = /* @__PURE__ */ new Map();
|
|
118
|
+
const trackedAdapters = /* @__PURE__ */ new Set();
|
|
119
|
+
function trackAdapter(adapter) {
|
|
120
|
+
trackedAdapters.add(adapter);
|
|
121
|
+
return adapter;
|
|
122
|
+
}
|
|
117
123
|
function getAdaptedWallet(walletInfo) {
|
|
118
124
|
if (isSolanaIosWalletInfo(walletInfo)) {
|
|
119
|
-
|
|
125
|
+
const cachedIosWallet = adaptedWallets.get(walletInfo.wallet);
|
|
126
|
+
if (cachedIosWallet) {
|
|
127
|
+
return cachedIosWallet;
|
|
128
|
+
}
|
|
129
|
+
const iosAdapter = adaptSolanaIosWallet(walletInfo, {
|
|
120
130
|
chain: getSolanaChain(options.cluster),
|
|
121
131
|
cluster: options.cluster,
|
|
122
132
|
onChange: options.onWalletChange,
|
|
123
133
|
...options.iosWallet || {}
|
|
124
134
|
});
|
|
135
|
+
adaptedWallets.set(walletInfo.wallet, iosAdapter);
|
|
136
|
+
return trackAdapter(iosAdapter);
|
|
125
137
|
}
|
|
126
138
|
if (!isObject(walletInfo.wallet)) {
|
|
127
|
-
|
|
139
|
+
const primitiveKey = `${walletInfo.name}::${String(walletInfo.wallet)}`;
|
|
140
|
+
const cachedPrimitiveWallet = adaptedPrimitiveWallets.get(primitiveKey);
|
|
141
|
+
if (cachedPrimitiveWallet) {
|
|
142
|
+
return cachedPrimitiveWallet;
|
|
143
|
+
}
|
|
144
|
+
const primitiveAdapter = adaptSolanaStandardWallet(walletInfo, {
|
|
128
145
|
chain: getSolanaChain(options.cluster),
|
|
129
146
|
onChange: options.onWalletChange
|
|
130
147
|
});
|
|
148
|
+
adaptedPrimitiveWallets.set(primitiveKey, primitiveAdapter);
|
|
149
|
+
return trackAdapter(primitiveAdapter);
|
|
131
150
|
}
|
|
132
151
|
const cachedWallet = adaptedWallets.get(walletInfo.wallet);
|
|
133
152
|
if (cachedWallet) {
|
|
@@ -155,7 +174,7 @@ function createSolanaWalletRegistry(options) {
|
|
|
155
174
|
);
|
|
156
175
|
}
|
|
157
176
|
adaptedWallets.set(walletInfo.wallet, cachedAdapter);
|
|
158
|
-
return cachedAdapter;
|
|
177
|
+
return trackAdapter(cachedAdapter);
|
|
159
178
|
}
|
|
160
179
|
function getDiscoveredWallets() {
|
|
161
180
|
return [
|
|
@@ -171,7 +190,6 @@ function createSolanaWalletRegistry(options) {
|
|
|
171
190
|
try {
|
|
172
191
|
handleSolanaIosWalletCallback({ clearUrl: true });
|
|
173
192
|
} catch (cause) {
|
|
174
|
-
console.error("[Vue Solana] iOS wallet callback failed", cause);
|
|
175
193
|
}
|
|
176
194
|
}
|
|
177
195
|
function* getCachedWallets() {
|
|
@@ -184,10 +202,16 @@ function createSolanaWalletRegistry(options) {
|
|
|
184
202
|
}
|
|
185
203
|
}
|
|
186
204
|
}
|
|
205
|
+
function disposeAllAdaptedWallets() {
|
|
206
|
+
for (const adapter of trackedAdapters) {
|
|
207
|
+
adapter.dispose?.();
|
|
208
|
+
}
|
|
209
|
+
}
|
|
187
210
|
return {
|
|
188
211
|
getAdaptedWallet,
|
|
189
212
|
getDiscoveredWallets,
|
|
190
|
-
handleIosWalletCallback
|
|
213
|
+
handleIosWalletCallback,
|
|
214
|
+
disposeAllAdaptedWallets
|
|
191
215
|
};
|
|
192
216
|
}
|
|
193
217
|
function isObject(value) {
|
|
@@ -196,6 +220,7 @@ function isObject(value) {
|
|
|
196
220
|
|
|
197
221
|
const RPC_CHECK_TIMEOUT_MS = 1e4;
|
|
198
222
|
function createSolanaPlugin(options = {}) {
|
|
223
|
+
let teardown = null;
|
|
199
224
|
const plugin = {
|
|
200
225
|
context: null,
|
|
201
226
|
install(app) {
|
|
@@ -216,15 +241,12 @@ function createSolanaPlugin(options = {}) {
|
|
|
216
241
|
let mobileWalletRegistrationPromise = null;
|
|
217
242
|
let attemptedAutoConnectWallet = null;
|
|
218
243
|
let rpcCheckId = 0;
|
|
244
|
+
let bootstrapId = 0;
|
|
245
|
+
let disposed = false;
|
|
219
246
|
async function checkConnection() {
|
|
220
247
|
const checkId = ++rpcCheckId;
|
|
221
248
|
status.value = "checking";
|
|
222
249
|
error.value = null;
|
|
223
|
-
console.info("[Vue Solana] Checking RPC connection", {
|
|
224
|
-
cluster: context.cluster,
|
|
225
|
-
endpoint: context.endpoint,
|
|
226
|
-
wsEndpoint: context.wsEndpoint
|
|
227
|
-
});
|
|
228
250
|
try {
|
|
229
251
|
const response = await withTimeout(
|
|
230
252
|
context.client.rpc.getLatestBlockhash().send(),
|
|
@@ -239,22 +261,18 @@ function createSolanaPlugin(options = {}) {
|
|
|
239
261
|
}
|
|
240
262
|
latestBlockhash.value = blockhash.blockhash;
|
|
241
263
|
status.value = "connected";
|
|
242
|
-
console.info("[Vue Solana] Connected", {
|
|
243
|
-
cluster: context.cluster,
|
|
244
|
-
endpoint: context.endpoint,
|
|
245
|
-
wsEndpoint: context.wsEndpoint,
|
|
246
|
-
blockhash
|
|
247
|
-
});
|
|
248
264
|
} catch (cause) {
|
|
249
265
|
if (checkId !== rpcCheckId) {
|
|
250
266
|
return;
|
|
251
267
|
}
|
|
252
268
|
status.value = "error";
|
|
253
269
|
error.value = normalizeSolanaError(cause, "RPC_FAILURE");
|
|
254
|
-
console.error("[Vue Solana] Connection failed", cause);
|
|
255
270
|
}
|
|
256
271
|
}
|
|
257
272
|
function refreshWallets() {
|
|
273
|
+
if (disposed) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
258
276
|
unsubscribeWallets ??= subscribeSolanaWallets(refreshWallets);
|
|
259
277
|
walletRegistry.handleIosWalletCallback();
|
|
260
278
|
wallets.value = walletRegistry.getDiscoveredWallets();
|
|
@@ -268,7 +286,6 @@ function createSolanaPlugin(options = {}) {
|
|
|
268
286
|
const persistedWallet = readSelectedWallet();
|
|
269
287
|
if (persistedWallet.error) {
|
|
270
288
|
error.value = persistedWallet.error;
|
|
271
|
-
console.error("[Vue Solana] Selected wallet restoration failed", persistedWallet.error);
|
|
272
289
|
}
|
|
273
290
|
restoredWallet = persistedWallet.wallet ? wallets.value.find(
|
|
274
291
|
(nextWallet) => isSameWallet(nextWallet, persistedWallet.wallet)
|
|
@@ -286,14 +303,19 @@ function createSolanaPlugin(options = {}) {
|
|
|
286
303
|
}
|
|
287
304
|
}
|
|
288
305
|
function registerMobileWallets() {
|
|
306
|
+
if (disposed) {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
289
309
|
mobileWalletRegistrationPromise ??= import('@vue-solana/core/mobile-wallet').then(({ registerSolanaMobileWallet }) => {
|
|
310
|
+
if (disposed) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
290
313
|
registerSolanaMobileWallet({
|
|
291
314
|
chains: [getSolanaChain(context.cluster)],
|
|
292
315
|
...options.mobileWallet || {}
|
|
293
316
|
});
|
|
294
317
|
refreshWallets();
|
|
295
318
|
}).catch((cause) => {
|
|
296
|
-
console.error("[Vue Solana] Mobile wallet registration failed", cause);
|
|
297
319
|
}).finally(() => {
|
|
298
320
|
mobileWalletRegistrationPromise = null;
|
|
299
321
|
});
|
|
@@ -304,7 +326,6 @@ function createSolanaPlugin(options = {}) {
|
|
|
304
326
|
const storageError = writeSelectedWallet(nextWallet);
|
|
305
327
|
if (storageError) {
|
|
306
328
|
error.value = storageError;
|
|
307
|
-
console.error("[Vue Solana] Selected wallet persistence failed", storageError);
|
|
308
329
|
}
|
|
309
330
|
}
|
|
310
331
|
function autoConnectWallet(walletInfo) {
|
|
@@ -318,7 +339,6 @@ function createSolanaPlugin(options = {}) {
|
|
|
318
339
|
}
|
|
319
340
|
attemptedAutoConnectWallet = storageValue;
|
|
320
341
|
void activeWallet.connect().catch((cause) => {
|
|
321
|
-
console.error("[Vue Solana] Wallet auto-connect failed", cause);
|
|
322
342
|
}).finally(() => {
|
|
323
343
|
triggerRef(wallet);
|
|
324
344
|
});
|
|
@@ -340,22 +360,34 @@ function createSolanaPlugin(options = {}) {
|
|
|
340
360
|
const storageError = writeSelectedWallet(null);
|
|
341
361
|
if (storageError) {
|
|
342
362
|
error.value = storageError;
|
|
343
|
-
console.error("[Vue Solana] Selected wallet persistence failed", storageError);
|
|
344
363
|
}
|
|
345
364
|
}
|
|
346
365
|
};
|
|
347
366
|
app.provide(solanaInjectionKey, vueContext);
|
|
348
367
|
plugin.context = vueContext;
|
|
368
|
+
teardown = () => {
|
|
369
|
+
disposed = true;
|
|
370
|
+
if (typeof window !== "undefined") {
|
|
371
|
+
window.clearTimeout(bootstrapId);
|
|
372
|
+
}
|
|
373
|
+
unsubscribeWallets?.();
|
|
374
|
+
unsubscribeWallets = null;
|
|
375
|
+
walletRegistry.disposeAllAdaptedWallets();
|
|
376
|
+
rpcCheckId += 1;
|
|
377
|
+
teardown = null;
|
|
378
|
+
};
|
|
349
379
|
if (typeof window !== "undefined") {
|
|
350
|
-
window.setTimeout(() => {
|
|
380
|
+
bootstrapId = window.setTimeout(() => {
|
|
351
381
|
try {
|
|
352
382
|
refreshWallets();
|
|
353
383
|
} catch (cause) {
|
|
354
|
-
console.error("[Vue Solana] Wallet refresh failed", cause);
|
|
355
384
|
}
|
|
356
385
|
void checkConnection();
|
|
357
386
|
}, 0);
|
|
358
387
|
}
|
|
388
|
+
},
|
|
389
|
+
dispose() {
|
|
390
|
+
teardown?.();
|
|
359
391
|
}
|
|
360
392
|
};
|
|
361
393
|
return plugin;
|
|
@@ -3,13 +3,13 @@ import { withSolanaTimeout } from '@vue-solana/core/timeout';
|
|
|
3
3
|
import { signAndSendTransaction, confirmTransactionSignature } from '@vue-solana/core/transaction';
|
|
4
4
|
import { createNoWalletSelectedError } from '@vue-solana/core/wallet';
|
|
5
5
|
import { ref, computed } from 'vue';
|
|
6
|
-
import { u as
|
|
7
|
-
import { u as useWallet } from './vue.
|
|
8
|
-
import { g as getConfirmedTransactionStatus } from './vue.
|
|
6
|
+
import { u as useSolanaClient } from './vue.CZApWQAY.mjs';
|
|
7
|
+
import { u as useWallet } from './vue.DY9VadLH.mjs';
|
|
8
|
+
import { g as getConfirmedTransactionStatus } from './vue.DPwdqRO_.mjs';
|
|
9
9
|
|
|
10
10
|
const SIGN_AND_SEND_TIMEOUT_MS = 12e4;
|
|
11
11
|
function useSignAndSendTransaction() {
|
|
12
|
-
const client =
|
|
12
|
+
const client = useSolanaClient().client;
|
|
13
13
|
const { wallet } = useWallet();
|
|
14
14
|
const signature = ref(null);
|
|
15
15
|
const confirmation = ref(null);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createNoWalletSelectedError, assertWalletCanSignIn } from '@vue-solana/core/wallet';
|
|
2
2
|
import { shallowRef } from 'vue';
|
|
3
|
-
import { u as useExecution } from './vue.
|
|
4
|
-
import { u as useWallet } from './vue.
|
|
3
|
+
import { u as useExecution } from './vue.BiKE9Xuv.mjs';
|
|
4
|
+
import { u as useWallet } from './vue.DY9VadLH.mjs';
|
|
5
5
|
|
|
6
6
|
function useSignIn() {
|
|
7
7
|
const { wallet } = useWallet();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { u as useClientAction } from './vue.
|
|
1
|
+
import { u as useClientAction } from './vue.CbmzveKF.mjs';
|
|
2
2
|
|
|
3
3
|
const PLANNING_PROVIDER_HINT = "Install a planner plugin, e.g. `createClient().use(rpcTransactionPlanner())` from `@solana/kit-plugin-rpc`, and plan with a client that has a `payer` signer \u2014 Kit reads `client.payer` to set the fee payer.";
|
|
4
4
|
const PLAN_STATUSES = {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { normalizeSolanaError } from '@vue-solana/core/errors';
|
|
2
2
|
import { shallowRef, onScopeDispose, computed } from 'vue';
|
|
3
3
|
|
|
4
|
-
function useExecution(busy) {
|
|
5
|
-
const
|
|
4
|
+
function useExecution(busy, statuses = {}) {
|
|
5
|
+
const errorStatus = statuses.error ?? "error";
|
|
6
|
+
const idleStatus = statuses.idle ?? "idle";
|
|
7
|
+
const status = shallowRef(idleStatus);
|
|
6
8
|
const error = shallowRef(null);
|
|
7
9
|
let id = 0;
|
|
8
10
|
async function execute(run, settled) {
|
|
@@ -19,14 +21,14 @@ function useExecution(busy) {
|
|
|
19
21
|
const normalizedError = normalizeSolanaError(cause, "RPC_FAILURE");
|
|
20
22
|
if (currentId === id) {
|
|
21
23
|
error.value = normalizedError;
|
|
22
|
-
status.value =
|
|
24
|
+
status.value = errorStatus;
|
|
23
25
|
}
|
|
24
26
|
throw normalizedError;
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
29
|
function reset() {
|
|
28
30
|
id += 1;
|
|
29
|
-
status.value =
|
|
31
|
+
status.value = idleStatus;
|
|
30
32
|
error.value = null;
|
|
31
33
|
}
|
|
32
34
|
onScopeDispose(() => {
|
|
@@ -1,19 +1,36 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import { shallowRef, onMounted,
|
|
4
|
-
import { u as
|
|
5
|
-
import { t as tryUseSolana } from './vue.
|
|
1
|
+
import { getBase58Encoder } from '@vue-solana/core/kit';
|
|
2
|
+
import { createSolanaError, normalizeSolanaError } from '@vue-solana/core/errors';
|
|
3
|
+
import { shallowRef, onMounted, onScopeDispose, watch, toValue } from 'vue';
|
|
4
|
+
import { u as useSolanaClient } from './vue.CZApWQAY.mjs';
|
|
5
|
+
import { t as tryUseSolana } from './vue.CcOZ9858.mjs';
|
|
6
6
|
|
|
7
7
|
function useSignatureStatus(signature, options = {}) {
|
|
8
8
|
const solana = tryUseSolana();
|
|
9
|
-
const client = solana?.client ??
|
|
9
|
+
const client = solana?.client ?? useSolanaClient().client;
|
|
10
10
|
const status = shallowRef(null);
|
|
11
11
|
const loading = shallowRef(false);
|
|
12
12
|
const error = shallowRef(null);
|
|
13
13
|
let refreshId = 0;
|
|
14
|
-
let
|
|
14
|
+
let pollTimer = null;
|
|
15
15
|
let manuallyStoppedPolling = false;
|
|
16
|
+
let refreshInFlight = null;
|
|
16
17
|
async function refresh() {
|
|
18
|
+
const value = toValue(signature);
|
|
19
|
+
const inFlight = refreshInFlight;
|
|
20
|
+
if (inFlight && inFlight.value === value) {
|
|
21
|
+
return inFlight.promise;
|
|
22
|
+
}
|
|
23
|
+
const promise = runRefresh();
|
|
24
|
+
refreshInFlight = { value, promise };
|
|
25
|
+
try {
|
|
26
|
+
return await promise;
|
|
27
|
+
} finally {
|
|
28
|
+
if (refreshInFlight?.promise === promise) {
|
|
29
|
+
refreshInFlight = null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function runRefresh() {
|
|
17
34
|
const requestId = ++refreshId;
|
|
18
35
|
const value = toValue(signature);
|
|
19
36
|
if (!value || !solana) {
|
|
@@ -53,16 +70,22 @@ function useSignatureStatus(signature, options = {}) {
|
|
|
53
70
|
stopCurrentPolling();
|
|
54
71
|
}
|
|
55
72
|
function stopCurrentPolling() {
|
|
56
|
-
if (
|
|
73
|
+
if (pollTimer === null) {
|
|
57
74
|
return;
|
|
58
75
|
}
|
|
59
|
-
|
|
60
|
-
|
|
76
|
+
clearTimeout(pollTimer);
|
|
77
|
+
pollTimer = null;
|
|
61
78
|
}
|
|
62
|
-
function
|
|
79
|
+
function schedulePoll() {
|
|
63
80
|
stopCurrentPolling();
|
|
81
|
+
if (!options.pollIntervalMs || !solana) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (manuallyStoppedPolling) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
64
87
|
const value = toValue(signature);
|
|
65
|
-
if (
|
|
88
|
+
if (!value) {
|
|
66
89
|
return;
|
|
67
90
|
}
|
|
68
91
|
if (options.pollIntervalMs <= 0) {
|
|
@@ -75,15 +98,22 @@ function useSignatureStatus(signature, options = {}) {
|
|
|
75
98
|
error.value = normalizeSolanaError(cause, "RPC_FAILURE");
|
|
76
99
|
return;
|
|
77
100
|
}
|
|
78
|
-
|
|
79
|
-
|
|
101
|
+
pollTimer = setTimeout(() => {
|
|
102
|
+
pollTimer = null;
|
|
103
|
+
void refresh().catch(() => void 0).finally(() => {
|
|
104
|
+
schedulePoll();
|
|
105
|
+
});
|
|
80
106
|
}, options.pollIntervalMs);
|
|
81
107
|
}
|
|
108
|
+
function startPolling() {
|
|
109
|
+
manuallyStoppedPolling = false;
|
|
110
|
+
schedulePoll();
|
|
111
|
+
}
|
|
82
112
|
onMounted(() => {
|
|
83
113
|
void refresh().catch(() => void 0);
|
|
84
|
-
|
|
114
|
+
schedulePoll();
|
|
85
115
|
});
|
|
86
|
-
|
|
116
|
+
onScopeDispose(() => {
|
|
87
117
|
refreshId += 1;
|
|
88
118
|
stopPolling();
|
|
89
119
|
});
|
|
@@ -105,7 +135,7 @@ function useSignatureStatus(signature, options = {}) {
|
|
|
105
135
|
function parseTransactionSignature(signature) {
|
|
106
136
|
let decodedSignature;
|
|
107
137
|
try {
|
|
108
|
-
decodedSignature =
|
|
138
|
+
decodedSignature = getBase58Encoder().encode(signature);
|
|
109
139
|
} catch (cause) {
|
|
110
140
|
throw new TypeError("Invalid Solana transaction signature", { cause });
|
|
111
141
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SolanaError } from '@vue-solana/core/errors';
|
|
2
|
+
import { u as useSolanaClient } from './vue.CZApWQAY.mjs';
|
|
2
3
|
|
|
3
|
-
class MissingClientCapabilityError extends
|
|
4
|
+
class MissingClientCapabilityError extends SolanaError {
|
|
4
5
|
/** Name of the hook that requested the capability, e.g. `usePayer`. */
|
|
5
6
|
hookName;
|
|
6
7
|
/** Human guidance for installing the capability on the client. */
|
|
@@ -9,7 +10,9 @@ class MissingClientCapabilityError extends Error {
|
|
|
9
10
|
capabilities;
|
|
10
11
|
constructor(hookName, capabilities, providerHint) {
|
|
11
12
|
super(
|
|
12
|
-
|
|
13
|
+
"MISSING_CLIENT_CAPABILITY",
|
|
14
|
+
`${hookName} requires the ${capabilities.map((capability) => `\`${capability}\``).join(" and ")} capabilit${capabilities.length === 1 ? "y" : "ies"} on the Solana client, but none ${capabilities.length === 1 ? "was" : "were"} found. ` + providerHint,
|
|
15
|
+
{}
|
|
13
16
|
);
|
|
14
17
|
this.name = "MissingClientCapabilityError";
|
|
15
18
|
this.hookName = hookName;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { createSolanaError } from '@vue-solana/core/errors';
|
|
1
2
|
import { u as useAction } from './vue.DYk0Xfr3.mjs';
|
|
2
|
-
import { u as useClientCapability } from './vue.
|
|
3
|
-
import { u as useSolanaClient } from './vue.
|
|
3
|
+
import { u as useClientCapability, M as MissingClientCapabilityError } from './vue.CAltY57B.mjs';
|
|
4
|
+
import { u as useSolanaClient } from './vue.CZApWQAY.mjs';
|
|
4
5
|
|
|
5
6
|
function toReadableAirdropError(error) {
|
|
6
7
|
if (error instanceof Error) {
|
|
@@ -9,23 +10,22 @@ function toReadableAirdropError(error) {
|
|
|
9
10
|
if (!isThrottled) {
|
|
10
11
|
throw error;
|
|
11
12
|
}
|
|
12
|
-
throw
|
|
13
|
+
throw createSolanaError(
|
|
14
|
+
"RPC_FAILURE",
|
|
13
15
|
`${error.message} This likely means the network's airdrop faucet is rate-limited or out of test SOL. Retry later, use https://faucet.solana.com, or point the client at a local validator.`,
|
|
14
16
|
{ cause: error }
|
|
15
17
|
);
|
|
16
18
|
}
|
|
17
|
-
throw
|
|
19
|
+
throw createSolanaError("RPC_FAILURE", `Airdrop failed: ${String(error)}`, { cause: error });
|
|
18
20
|
}
|
|
19
21
|
function useAirdrop() {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
providerHint: "Install it by adding the airdrop capability with `createClient().use(solanaRpc({ ... })).use(rpcAirdrop())` from `@solana/kit-plugin-rpc`, on a client that has a `payer` signer to sign the request."
|
|
23
|
-
});
|
|
22
|
+
const providerHint = "Install it by adding the airdrop capability with `createClient().use(solanaRpc({ ... })).use(rpcAirdrop())` from `@solana/kit-plugin-rpc`, on a client that has a `payer` signer to sign the request.";
|
|
23
|
+
useClientCapability("airdrop", { hookName: "useAirdrop", providerHint });
|
|
24
24
|
const { client } = useSolanaClient();
|
|
25
25
|
return useAction((abortSignal, address, amount) => {
|
|
26
26
|
const airdrop = client.airdrop;
|
|
27
27
|
if (!airdrop) {
|
|
28
|
-
throw new
|
|
28
|
+
throw new MissingClientCapabilityError("useAirdrop", ["airdrop"], providerHint);
|
|
29
29
|
}
|
|
30
30
|
return airdrop(address, amount, abortSignal).catch(toReadableAirdropError);
|
|
31
31
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { u as useClientAction } from './vue.
|
|
1
|
+
import { u as useClientAction } from './vue.CbmzveKF.mjs';
|
|
2
2
|
|
|
3
3
|
const SENDING_PROVIDER_HINT = "Use a client created by `createSolanaClient({ payer })` \u2014 or any client with a `payer` signer. Kit reads `client.payer` when it plans a transaction from an instruction plan.";
|
|
4
4
|
const SEND_STATUSES = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createNoWalletSelectedError, assertWalletCanSignTransactions } from '@vue-solana/core/wallet';
|
|
2
2
|
import { shallowRef } from 'vue';
|
|
3
|
-
import { u as useExecution } from './vue.
|
|
4
|
-
import { u as useWallet } from './vue.
|
|
3
|
+
import { u as useExecution } from './vue.BiKE9Xuv.mjs';
|
|
4
|
+
import { u as useWallet } from './vue.DY9VadLH.mjs';
|
|
5
5
|
|
|
6
6
|
function useSignTransactions() {
|
|
7
7
|
const { wallet } = useWallet();
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { shallowRef, onScopeDispose } from 'vue';
|
|
2
|
+
import { u as useExecution } from './vue.BiKE9Xuv.mjs';
|
|
3
|
+
import { u as useClientCapability, M as MissingClientCapabilityError } from './vue.CAltY57B.mjs';
|
|
4
|
+
import { u as useSolanaClient } from './vue.CZApWQAY.mjs';
|
|
5
|
+
|
|
6
|
+
function useClientAction(config) {
|
|
7
|
+
const { capability, hookName, providerHint, statuses } = config;
|
|
8
|
+
useClientCapability([capability, "payer"], { hookName, providerHint });
|
|
9
|
+
const { client } = useSolanaClient();
|
|
10
|
+
const data = shallowRef(null);
|
|
11
|
+
let abortController;
|
|
12
|
+
onScopeDispose(() => abortController?.abort());
|
|
13
|
+
const execution = useExecution(statuses.working, {
|
|
14
|
+
error: statuses.error,
|
|
15
|
+
idle: statuses.idle
|
|
16
|
+
});
|
|
17
|
+
async function execute(input, options = {}) {
|
|
18
|
+
const method = client?.[capability];
|
|
19
|
+
if (typeof method !== "function") {
|
|
20
|
+
throw new MissingClientCapabilityError(hookName, [capability], providerHint);
|
|
21
|
+
}
|
|
22
|
+
abortController?.abort();
|
|
23
|
+
const controller = new AbortController();
|
|
24
|
+
abortController = controller;
|
|
25
|
+
data.value = null;
|
|
26
|
+
const abortSignal = options.abortSignal ? AbortSignal.any([controller.signal, options.abortSignal]) : controller.signal;
|
|
27
|
+
return execution.execute(
|
|
28
|
+
() => method(input, { abortSignal }),
|
|
29
|
+
(result) => {
|
|
30
|
+
data.value = result;
|
|
31
|
+
return statuses.success;
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
data,
|
|
37
|
+
status: execution.status,
|
|
38
|
+
loading: execution.loading,
|
|
39
|
+
error: execution.error,
|
|
40
|
+
execute
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export { useClientAction as u };
|