@vue-solana/core 4.0.0-rc.0 → 4.0.0-rc.1
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 +1 -0
- 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
|
@@ -185,6 +185,7 @@ The client-sent API is the official Kit `ClientWithTransactionSending` capabilit
|
|
|
185
185
|
| `getSolanaIosWallets(options?)` | Builds iOS browser wallet entries (Phantom, Solflare, Backpack) as universal links. |
|
|
186
186
|
| `handleSolanaIosWalletCallback()` | Completes a pending iOS wallet deep-link callback after redirect. |
|
|
187
187
|
| `adaptSolanaStandardWallet(wallet)` | Adapts a Solana Wallet Standard wallet into `SolanaWallet`. |
|
|
188
|
+
| `disconnectSolanaStandardWallet(walletInfo)` | Disconnects a discovered Wallet Standard wallet through its own `standard:disconnect` feature, without adapting it. |
|
|
188
189
|
| `getRegisteredSolanaWallets()` | Returns the Wallet Standard wallets currently registered in the app. |
|
|
189
190
|
| `withTimeout(promise, timeoutMs, options?)` | Races a promise against a timeout, with optional abort signal. |
|
|
190
191
|
| `withSolanaTimeout(promise, timeoutMs, options?)` | Solana-specific timeout wrapper with abort and error-code support. |
|
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';
|