@vue-solana/core 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 +12 -1
- package/dist/errors.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/ios-wallet.mjs +26 -10
- package/dist/shared/{core.BlqTJRXd.mjs → core.A4I__4IR.mjs} +37 -8
- package/dist/transaction.mjs +3 -0
- package/dist/wallet-standard.d.ts +13 -1
- package/dist/wallet-standard.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,6 +7,16 @@
|
|
|
7
7
|
|
|
8
8
|
Framework-agnostic Solana primitives for Vue Solana libraries and apps that want shared RPC, wallet, and transaction helpers without installing a Vue plugin.
|
|
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.).
|
|
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 (`@vue-solana/core`) is the foundation the other two build on; most apps should install `@vue-solana/vue` or `@vue-solana/nuxt` rather than this package directly.
|
|
19
|
+
|
|
10
20
|
Use this package directly when you want Kit RPC client helpers, shared wallet types, Android Mobile Wallet Adapter registration helpers, message signing support, token account reads, and transaction helpers without installing the Vue plugin.
|
|
11
21
|
|
|
12
22
|
`@vue-solana/core` builds on `@solana/kit`. It exposes `createSolanaClient()` and re-exports all of `@solana/kit` from `@vue-solana/core/kit`. The legacy `@solana/web3-compat` surface and the `web3` subpaths were removed in v2.0.0; transactions flow through the packages as raw `Uint8Array` wire bytes.
|
|
@@ -185,6 +195,7 @@ The client-sent API is the official Kit `ClientWithTransactionSending` capabilit
|
|
|
185
195
|
| `getSolanaIosWallets(options?)` | Builds iOS browser wallet entries (Phantom, Solflare, Backpack) as universal links. |
|
|
186
196
|
| `handleSolanaIosWalletCallback()` | Completes a pending iOS wallet deep-link callback after redirect. |
|
|
187
197
|
| `adaptSolanaStandardWallet(wallet)` | Adapts a Solana Wallet Standard wallet into `SolanaWallet`. |
|
|
198
|
+
| `disconnectSolanaStandardWallet(walletInfo)` | Disconnects a discovered Wallet Standard wallet through its own `standard:disconnect` feature, without adapting it. Resolves `false` if the wallet has no disconnect feature, and ignores failures after a 2 s timeout. |
|
|
188
199
|
| `getRegisteredSolanaWallets()` | Returns the Wallet Standard wallets currently registered in the app. |
|
|
189
200
|
| `withTimeout(promise, timeoutMs, options?)` | Races a promise against a timeout, with optional abort signal. |
|
|
190
201
|
| `withSolanaTimeout(promise, timeoutMs, options?)` | Solana-specific timeout wrapper with abort and error-code support. |
|
|
@@ -210,7 +221,7 @@ const wallet: SolanaWallet = {
|
|
|
210
221
|
|
|
211
222
|
Browser extension wallets discovered through the Solana Wallet Standard are adapted into `SolanaWallet`. Android Mobile Wallet Adapter is registered through `@solana-mobile/wallet-standard-mobile` and then adapted through the same Wallet Standard adapter on supported Android Chrome clients. iOS browser wallet entries for Phantom, Solflare, and Backpack are adapted through wallet-specific universal links. Wallet capability metadata exposes whether each wallet supports message signing, transaction signing, and sign-and-send flows. You can also provide a custom object that implements `SolanaWallet` for tests or custom adapters.
|
|
212
223
|
|
|
213
|
-
The Wallet Standard adapter verifies the signature a wallet returns from `signMessage` / `signIn` against the account's public key before resolving, where Ed25519 (WebCrypto) is available. A signature over the wrong bytes or from a different account rejects with `INVALID_SIGNATURE`. This is a best-effort, client-side guard —
|
|
224
|
+
The Wallet Standard adapter verifies the signature a wallet returns from `signMessage` / `signIn` against the account's public key before resolving, where Ed25519 (WebCrypto) is available. A signature over the wrong bytes or from a different account rejects with `INVALID_SIGNATURE`. `signIn` also binds the result to the requested account (or active account) and rejects if the account is absent from `wallet.accounts`. This is a best-effort, client-side guard — a malformed signature is rejected even if Ed25519 verification is unavailable, but full verification is skipped where Ed25519 is unavailable — so server-side verification remains mandatory for auth flows. Connecting a wallet disconnects every other discovered wallet (swept over discovery, uncached wallets disconnected via `standard:disconnect`), so only one wallet stays authorized.
|
|
214
225
|
|
|
215
226
|
Current wallet support:
|
|
216
227
|
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
type SolanaErrorCode = "NO_WALLET_SELECTED" | "WALLET_NOT_CONNECTED" | "WALLET_FEATURE_UNSUPPORTED" | "USER_REJECTED" | "INVALID_ADDRESS" | "TRANSACTION_TIMEOUT" | "TRANSACTION_NOT_FOUND" | "TRANSACTION_FAILED" | "RPC_FAILURE" | "STORAGE_FAILURE" | "INVALID_INPUT" | "DECRYPTION_FAILED" | "REDIRECT_TIMEOUT" | "MISSING_CLIENT_CAPABILITY" | "INVALID_SIGNATURE";
|
|
1
|
+
type SolanaErrorCode = "NO_WALLET_SELECTED" | "WALLET_NOT_CONNECTED" | "WALLET_FEATURE_UNSUPPORTED" | "WALLET_FAILURE" | "USER_REJECTED" | "INVALID_ADDRESS" | "TRANSACTION_TIMEOUT" | "TRANSACTION_NOT_FOUND" | "TRANSACTION_FAILED" | "RPC_FAILURE" | "STORAGE_FAILURE" | "INVALID_INPUT" | "DECRYPTION_FAILED" | "REDIRECT_TIMEOUT" | "MISSING_CLIENT_CAPABILITY" | "INVALID_SIGNATURE";
|
|
2
2
|
interface SolanaErrorOptions {
|
|
3
3
|
cause?: unknown;
|
|
4
4
|
feature?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,6 @@ export { confirmTransactionSignature, signAndSendTransaction } from './transacti
|
|
|
9
9
|
export { WithTimeoutOptions, withSolanaTimeout, withTimeout } from './timeout.js';
|
|
10
10
|
export { SolanaWalletError, SolanaWalletErrorCode, assertWalletCanSign, assertWalletCanSignAndSendTransactions, assertWalletCanSignIn, assertWalletCanSignMessage, assertWalletCanSignTransactions, assertWalletConnected, createNoWalletSelectedError, isWalletConnected } from './wallet.js';
|
|
11
11
|
export * from '@solana/kit';
|
|
12
|
-
export { AdaptSolanaWalletOptions, AdaptedSolanaWallet, SOLANA_CHAINS, SOLANA_MOBILE_WALLET_ADAPTER_WALLET_NAME, adaptSolanaStandardWallet, getRegisteredSolanaWallets, getSolanaChain, isSolanaStandardWallet, subscribeSolanaWallets } from './wallet-standard.js';
|
|
12
|
+
export { AdaptSolanaWalletOptions, AdaptedSolanaWallet, SOLANA_CHAINS, SOLANA_MOBILE_WALLET_ADAPTER_WALLET_NAME, adaptSolanaStandardWallet, disconnectSolanaStandardWallet, getRegisteredSolanaWallets, getSolanaChain, isSolanaStandardWallet, subscribeSolanaWallets } from './wallet-standard.js';
|
|
13
13
|
import '@solana/kit-plugin-rpc';
|
|
14
14
|
import '@wallet-standard/base';
|
package/dist/index.mjs
CHANGED
|
@@ -9,4 +9,4 @@ export { confirmTransactionSignature, signAndSendTransaction } from './transacti
|
|
|
9
9
|
export { withSolanaTimeout, withTimeout } from './timeout.mjs';
|
|
10
10
|
export { SolanaWalletError, assertWalletCanSign, assertWalletCanSignAndSendTransactions, assertWalletCanSignIn, assertWalletCanSignMessage, assertWalletCanSignTransactions, assertWalletConnected, createNoWalletSelectedError, isWalletConnected } from './wallet.mjs';
|
|
11
11
|
export * from '@solana/kit';
|
|
12
|
-
export { S as SOLANA_CHAINS, a as SOLANA_MOBILE_WALLET_ADAPTER_WALLET_NAME, b as adaptSolanaStandardWallet, g as getRegisteredSolanaWallets, c as getSolanaChain, i as isSolanaStandardWallet, s as subscribeSolanaWallets } from './shared/core.
|
|
12
|
+
export { S as SOLANA_CHAINS, a as SOLANA_MOBILE_WALLET_ADAPTER_WALLET_NAME, b as adaptSolanaStandardWallet, d as disconnectSolanaStandardWallet, g as getRegisteredSolanaWallets, c as getSolanaChain, i as isSolanaStandardWallet, s as subscribeSolanaWallets } from './shared/core.A4I__4IR.mjs';
|
package/dist/ios-wallet.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createSolanaError } from './errors.mjs';
|
|
1
|
+
import { createSolanaError, normalizeSolanaError } from './errors.mjs';
|
|
2
2
|
import { getBase58Encoder, getBase58Decoder, isAddress } from '@solana/kit';
|
|
3
3
|
import * as naclModule from 'tweetnacl';
|
|
4
4
|
|
|
@@ -359,17 +359,23 @@ function handleSolanaIosWalletCallback(options = {}) {
|
|
|
359
359
|
if (errorCode || errorMessage) {
|
|
360
360
|
clearPendingRequest();
|
|
361
361
|
cleanCallbackUrl(url, options.clearUrl);
|
|
362
|
-
throw
|
|
362
|
+
throw normalizeSolanaError(
|
|
363
|
+
new Error(errorMessage || `iOS wallet request failed: ${errorCode}`),
|
|
364
|
+
"WALLET_FAILURE"
|
|
365
|
+
);
|
|
363
366
|
}
|
|
364
367
|
const pending = getPendingRequest();
|
|
365
368
|
if (!pending) {
|
|
366
369
|
cleanCallbackUrl(url, options.clearUrl);
|
|
367
|
-
throw
|
|
370
|
+
throw createSolanaError(
|
|
371
|
+
"INVALID_INPUT",
|
|
372
|
+
"Received an iOS wallet callback without a pending request"
|
|
373
|
+
);
|
|
368
374
|
}
|
|
369
375
|
if (isPendingRequestExpired(pending)) {
|
|
370
376
|
clearPendingRequest();
|
|
371
377
|
cleanCallbackUrl(url, options.clearUrl);
|
|
372
|
-
throw
|
|
378
|
+
throw createSolanaError("REDIRECT_TIMEOUT", "Received an expired iOS wallet callback");
|
|
373
379
|
}
|
|
374
380
|
const definition = getIosWalletDefinitionById(pending.walletId);
|
|
375
381
|
const walletEncryptionPublicKey = url.searchParams.get(definition.encryptionPublicKeyParam);
|
|
@@ -378,7 +384,7 @@ function handleSolanaIosWalletCallback(options = {}) {
|
|
|
378
384
|
if (!nonce || !data) {
|
|
379
385
|
clearPendingRequest();
|
|
380
386
|
cleanCallbackUrl(url, options.clearUrl);
|
|
381
|
-
throw
|
|
387
|
+
throw createSolanaError("INVALID_INPUT", "Received an incomplete iOS wallet callback");
|
|
382
388
|
}
|
|
383
389
|
try {
|
|
384
390
|
const sharedSecret = getSharedSecret(
|
|
@@ -389,7 +395,10 @@ function handleSolanaIosWalletCallback(options = {}) {
|
|
|
389
395
|
const result = createCallbackResult(pending, payload);
|
|
390
396
|
if (pending.method === "connect") {
|
|
391
397
|
if (!walletEncryptionPublicKey) {
|
|
392
|
-
throw
|
|
398
|
+
throw createSolanaError(
|
|
399
|
+
"DECRYPTION_FAILED",
|
|
400
|
+
"iOS wallet connect callback did not include an encryption public key"
|
|
401
|
+
);
|
|
393
402
|
}
|
|
394
403
|
const publicKey = getPublicKeyField(payload, "public_key");
|
|
395
404
|
storeSession({
|
|
@@ -428,10 +437,14 @@ function createCallbackResult(pending, payload) {
|
|
|
428
437
|
if (pending.method === "signAllTransactions") {
|
|
429
438
|
const transactions = payload.transactions;
|
|
430
439
|
if (!Array.isArray(transactions) || transactions.some((transaction) => typeof transaction !== "string")) {
|
|
431
|
-
throw
|
|
440
|
+
throw createSolanaError(
|
|
441
|
+
"DECRYPTION_FAILED",
|
|
442
|
+
"iOS wallet returned invalid signed transactions"
|
|
443
|
+
);
|
|
432
444
|
}
|
|
433
445
|
if (typeof pending.requestedTransactionCount === "number" && transactions.length !== pending.requestedTransactionCount) {
|
|
434
|
-
throw
|
|
446
|
+
throw createSolanaError(
|
|
447
|
+
"WALLET_FAILURE",
|
|
435
448
|
`iOS wallet returned ${transactions.length} signed transactions for ${pending.requestedTransactionCount} requested transactions`
|
|
436
449
|
);
|
|
437
450
|
}
|
|
@@ -452,14 +465,17 @@ function createCallbackResult(pending, payload) {
|
|
|
452
465
|
function getStringField(payload, field) {
|
|
453
466
|
const value = payload[field];
|
|
454
467
|
if (typeof value !== "string" || !value) {
|
|
455
|
-
throw
|
|
468
|
+
throw createSolanaError("DECRYPTION_FAILED", `iOS wallet callback is missing ${field}`);
|
|
456
469
|
}
|
|
457
470
|
return value;
|
|
458
471
|
}
|
|
459
472
|
function getPublicKeyField(payload, field) {
|
|
460
473
|
const value = getStringField(payload, field);
|
|
461
474
|
if (!isAddress(value)) {
|
|
462
|
-
throw
|
|
475
|
+
throw createSolanaError(
|
|
476
|
+
"DECRYPTION_FAILED",
|
|
477
|
+
`iOS wallet callback returned an invalid ${field}`
|
|
478
|
+
);
|
|
463
479
|
}
|
|
464
480
|
return value;
|
|
465
481
|
}
|
|
@@ -5,6 +5,12 @@ import { createSolanaError } from '../errors.mjs';
|
|
|
5
5
|
import { getWallets } from '@wallet-standard/app';
|
|
6
6
|
|
|
7
7
|
async function assertWalletSignature(publicKey, signedMessage, signature, label) {
|
|
8
|
+
if (!isSignatureBytes(signature)) {
|
|
9
|
+
throw createSolanaError(
|
|
10
|
+
"INVALID_SIGNATURE",
|
|
11
|
+
`The wallet returned a malformed ${label} signature.`
|
|
12
|
+
);
|
|
13
|
+
}
|
|
8
14
|
let key;
|
|
9
15
|
try {
|
|
10
16
|
key = await globalThis.crypto.subtle.importKey(
|
|
@@ -17,12 +23,6 @@ async function assertWalletSignature(publicKey, signedMessage, signature, label)
|
|
|
17
23
|
} catch {
|
|
18
24
|
return;
|
|
19
25
|
}
|
|
20
|
-
if (!isSignatureBytes(signature)) {
|
|
21
|
-
throw createSolanaError(
|
|
22
|
-
"INVALID_SIGNATURE",
|
|
23
|
-
`The wallet returned a malformed ${label} signature.`
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
26
|
let valid;
|
|
27
27
|
try {
|
|
28
28
|
valid = await verifySignature(key, signature, signedMessage);
|
|
@@ -149,8 +149,24 @@ function adaptSolanaStandardWallet(walletInfo, options = {}) {
|
|
|
149
149
|
throw new Error("Solana wallet did not return a sign-in result");
|
|
150
150
|
}
|
|
151
151
|
const signInResult = toSolanaSignInResult(result);
|
|
152
|
+
const requestedAddress = input?.address ?? account?.address;
|
|
153
|
+
const signInAccount = accounts.find(
|
|
154
|
+
(candidate) => candidate.address === signInResult.account.address
|
|
155
|
+
);
|
|
156
|
+
if (!signInAccount) {
|
|
157
|
+
throw createSolanaError(
|
|
158
|
+
"INVALID_SIGNATURE",
|
|
159
|
+
"The wallet returned a sign-in account it does not expose."
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
if (requestedAddress !== void 0 && requestedAddress !== signInAccount.address) {
|
|
163
|
+
throw createSolanaError(
|
|
164
|
+
"INVALID_SIGNATURE",
|
|
165
|
+
`The wallet signed in as ${signInResult.account.address} instead of the requested ${requestedAddress}.`
|
|
166
|
+
);
|
|
167
|
+
}
|
|
152
168
|
await assertWalletSignature(
|
|
153
|
-
|
|
169
|
+
signInAccount.publicKey,
|
|
154
170
|
signInResult.signedMessage,
|
|
155
171
|
signInResult.signature,
|
|
156
172
|
"sign-in"
|
|
@@ -235,6 +251,19 @@ function adaptSolanaStandardWallet(walletInfo, options = {}) {
|
|
|
235
251
|
} : void 0
|
|
236
252
|
};
|
|
237
253
|
}
|
|
254
|
+
async function disconnectSolanaStandardWallet(walletInfo) {
|
|
255
|
+
const wallet = walletInfo.wallet;
|
|
256
|
+
if (typeof wallet !== "object" && typeof wallet !== "function") {
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
const features = wallet?.features;
|
|
260
|
+
const feature = features?.[StandardDisconnect];
|
|
261
|
+
if (typeof feature?.disconnect !== "function") {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
await feature.disconnect();
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
238
267
|
async function signAllThroughFeature(wallet, getAccount, transactions, chain) {
|
|
239
268
|
const activeAccount = getAccount();
|
|
240
269
|
const results = await wallet.features[SolanaSignTransaction].signTransaction(
|
|
@@ -352,4 +381,4 @@ function getWalletUrl(wallet) {
|
|
|
352
381
|
return "url" in wallet && typeof wallet.url === "string" ? wallet.url : void 0;
|
|
353
382
|
}
|
|
354
383
|
|
|
355
|
-
export { SOLANA_CHAINS as S, SOLANA_MOBILE_WALLET_ADAPTER_WALLET_NAME as a, adaptSolanaStandardWallet as b, getSolanaChain as c, getRegisteredSolanaWallets as g, isSolanaStandardWallet as i, subscribeSolanaWallets as s };
|
|
384
|
+
export { SOLANA_CHAINS as S, SOLANA_MOBILE_WALLET_ADAPTER_WALLET_NAME as a, adaptSolanaStandardWallet as b, getSolanaChain as c, disconnectSolanaStandardWallet as d, getRegisteredSolanaWallets as g, isSolanaStandardWallet as i, subscribeSolanaWallets as s };
|
package/dist/transaction.mjs
CHANGED
|
@@ -78,6 +78,9 @@ async function confirmTransactionSignature(client, signature, options = {}) {
|
|
|
78
78
|
`Timed out waiting for transaction ${signature} to reach ${commitment} commitment.`
|
|
79
79
|
);
|
|
80
80
|
} catch (cause) {
|
|
81
|
+
if (abortSignal?.aborted) {
|
|
82
|
+
throw abortSignal.reason ?? cause;
|
|
83
|
+
}
|
|
81
84
|
if (isAbortErrorLike(cause)) {
|
|
82
85
|
throw cause;
|
|
83
86
|
}
|
|
@@ -17,6 +17,18 @@ interface AdaptedSolanaWallet extends SolanaWallet {
|
|
|
17
17
|
dispose(): void;
|
|
18
18
|
}
|
|
19
19
|
declare function adaptSolanaStandardWallet(walletInfo: SolanaWalletInfo, options?: AdaptSolanaWalletOptions): AdaptedSolanaWallet;
|
|
20
|
+
/**
|
|
21
|
+
* Disconnects a discovered Wallet Standard wallet without adapting it.
|
|
22
|
+
*
|
|
23
|
+
* Reads `standard:disconnect` straight off the wallet instead of going through
|
|
24
|
+
* an adapter on purpose: a wallet the app authorized in an earlier page session
|
|
25
|
+
* has no adapter yet, so an adapter-only sweep misses it, and adapting it just
|
|
26
|
+
* to disconnect would register a `change` subscription for a wallet the user
|
|
27
|
+
* never selects. Resolves `false` when the wallet exposes no disconnect feature
|
|
28
|
+
* (for example an iOS deep-link definition); rejects with the wallet's own
|
|
29
|
+
* error, so a caller sweeping a list should catch per wallet.
|
|
30
|
+
*/
|
|
31
|
+
declare function disconnectSolanaStandardWallet(walletInfo: SolanaWalletInfo): Promise<boolean>;
|
|
20
32
|
|
|
21
33
|
declare const SOLANA_CHAINS: readonly SolanaChain[];
|
|
22
34
|
declare function getSolanaChain(cluster: SolanaCluster): SolanaChain;
|
|
@@ -26,5 +38,5 @@ declare function isSolanaStandardWallet(wallet: Wallet): boolean;
|
|
|
26
38
|
declare function getRegisteredSolanaWallets(): SolanaWalletInfo[];
|
|
27
39
|
declare function subscribeSolanaWallets(listener: () => void): () => void;
|
|
28
40
|
|
|
29
|
-
export { SOLANA_CHAINS, SOLANA_MOBILE_WALLET_ADAPTER_WALLET_NAME, adaptSolanaStandardWallet, getRegisteredSolanaWallets, getSolanaChain, isSolanaStandardWallet, subscribeSolanaWallets };
|
|
41
|
+
export { SOLANA_CHAINS, SOLANA_MOBILE_WALLET_ADAPTER_WALLET_NAME, adaptSolanaStandardWallet, disconnectSolanaStandardWallet, getRegisteredSolanaWallets, getSolanaChain, isSolanaStandardWallet, subscribeSolanaWallets };
|
|
30
42
|
export type { AdaptSolanaWalletOptions, AdaptedSolanaWallet };
|
package/dist/wallet-standard.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { S as SOLANA_CHAINS, a as SOLANA_MOBILE_WALLET_ADAPTER_WALLET_NAME, b as adaptSolanaStandardWallet, g as getRegisteredSolanaWallets, c as getSolanaChain, i as isSolanaStandardWallet, s as subscribeSolanaWallets } from './shared/core.
|
|
1
|
+
export { S as SOLANA_CHAINS, a as SOLANA_MOBILE_WALLET_ADAPTER_WALLET_NAME, b as adaptSolanaStandardWallet, d as disconnectSolanaStandardWallet, g as getRegisteredSolanaWallets, c as getSolanaChain, i as isSolanaStandardWallet, s as subscribeSolanaWallets } from './shared/core.A4I__4IR.mjs';
|