@vue-solana/core 4.1.4 → 4.1.6

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/dist/index.mjs CHANGED
@@ -12,4 +12,4 @@ export { createSolanaPayReference, findTransactionSignaturesByReference, verifyS
12
12
  export { getSolanaPayPaymentStatus } from './solana-pay-status.mjs';
13
13
  export * from '@solana/kit';
14
14
  export { C as CreateTransferError, H as HTTPS_PROTOCOL, M as MEMO_PROGRAM_ID, P as ParseURLError, S as SOLANA_PROTOCOL, a as SOL_DECIMALS, T as TEN, b as TOKEN_PROGRAM_ID, c as createQR, d as createQRCanvas, e as createQRDataURL, f as createQROptions, g as createRecipient, h as createSPLToken, i as createStyledQRCode, j as encodeTransactionRequestURL, k as encodeTransferRequestURL, l as encodeURL, m as isValidSolanaAddress, p as parseURL } from './shared/core.CQFtdLrA.mjs';
15
- 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.D8oIzL0q.mjs';
15
+ 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.CSMFFbai.mjs';
@@ -1,7 +1,72 @@
1
1
  import { createDefaultAuthorizationCache, registerMwa, createDefaultWalletNotFoundHandler, createDefaultChainSelector } from '@solana-mobile/wallet-standard-mobile';
2
2
  import { s as setSolanaMobileWalletAuthorizationStore } from './shared/core.DQCWbyEu.mjs';
3
+ import { transact } from '@solana-mobile/mobile-wallet-adapter-protocol';
4
+ import { getBase64Decoder, getBase64Encoder } from '@solana/kit';
5
+ import { createSolanaError } from './errors.mjs';
3
6
  import { isSolanaMobileWalletSupported } from './mobile-wallet-support.mjs';
4
7
 
8
+ async function signMobileWalletMessages({
9
+ appIdentity,
10
+ authorizationCache,
11
+ publicKey,
12
+ messages
13
+ }) {
14
+ const cachedAuthorization = await authorizationCache.get();
15
+ if (!cachedAuthorization) {
16
+ throw createSolanaError("WALLET_NOT_CONNECTED", "Solana wallet is not connected");
17
+ }
18
+ const base64Decoder = getBase64Decoder();
19
+ const base64Encoder = getBase64Encoder();
20
+ const address = base64Decoder.decode(publicKey);
21
+ const chain = cachedAuthorization.chain;
22
+ return transact(async (wallet) => {
23
+ const authorization = await authorizeSession(
24
+ wallet,
25
+ appIdentity,
26
+ chain,
27
+ cachedAuthorization.auth_token
28
+ );
29
+ if (!authorization.accounts.some((account) => account.address === address)) {
30
+ throw createSolanaError(
31
+ "WALLET_NOT_CONNECTED",
32
+ "The wallet authorized a different account than the connected one. Connect the wallet again and retry."
33
+ );
34
+ }
35
+ if (authorization.auth_token !== cachedAuthorization.auth_token) {
36
+ await authorizationCache.set({
37
+ ...cachedAuthorization,
38
+ auth_token: authorization.auth_token,
39
+ wallet_uri_base: authorization.wallet_uri_base
40
+ });
41
+ }
42
+ const { signed_payloads } = await wallet.signMessages({
43
+ addresses: messages.map(() => address),
44
+ payloads: messages.map((message) => base64Decoder.decode(message))
45
+ });
46
+ return signed_payloads.map((payload) => Uint8Array.from(base64Encoder.encode(payload)));
47
+ });
48
+ }
49
+ async function authorizeSession(wallet, identity, chain, authToken) {
50
+ let reauthorizationError;
51
+ try {
52
+ return await wallet.authorize({ auth_token: authToken, identity, chain });
53
+ } catch (error) {
54
+ reauthorizationError = error;
55
+ }
56
+ try {
57
+ return await wallet.authorize({ identity, chain });
58
+ } catch (authorizationError) {
59
+ throw createSolanaError(
60
+ "WALLET_FAILURE",
61
+ `The wallet rejected the saved authorization (${getErrorMessage(reauthorizationError)}) and a fresh one (${getErrorMessage(authorizationError)}).`,
62
+ { cause: authorizationError }
63
+ );
64
+ }
65
+ }
66
+ function getErrorMessage(error) {
67
+ return error instanceof Error ? error.message : String(error);
68
+ }
69
+
5
70
  const DEFAULT_MOBILE_WALLET_CHAINS = ["solana:mainnet", "solana:devnet"];
6
71
  const registeredMobileWalletKeys = /* @__PURE__ */ new Set();
7
72
  function registerSolanaMobileWallet(options = {}) {
@@ -30,7 +95,8 @@ function registerSolanaMobileWallet(options = {}) {
30
95
  registeredMobileWalletKeys.add(registrationKey);
31
96
  setSolanaMobileWalletAuthorizationStore({
32
97
  get: () => authorizationCache.get(),
33
- set: (authorization) => authorizationCache.set(authorization)
98
+ set: (authorization) => authorizationCache.set(authorization),
99
+ signMessages: (publicKey, messages) => signMobileWalletMessages({ appIdentity, authorizationCache, publicKey, messages })
34
100
  });
35
101
  return true;
36
102
  }
@@ -78,10 +78,14 @@ function adaptSolanaStandardWallet(walletInfo, options = {}) {
78
78
  let manuallyDisconnected = false;
79
79
  let signingIn = false;
80
80
  const isMobileWalletAdapter = walletInfo.source === "mobile-wallet-adapter";
81
+ const pendingMobileWalletRequests = /* @__PURE__ */ new Set();
81
82
  const eventsFeature = wallet.features[StandardEvents];
82
83
  const unsubscribeChange = eventsFeature?.on("change", (properties) => {
83
84
  if (properties.accounts) {
84
85
  accounts = properties.accounts;
86
+ if (accounts.length === 0) {
87
+ rejectPendingMobileWalletRequests();
88
+ }
85
89
  if (!signingIn) {
86
90
  account = allowAccountUpdates && !manuallyDisconnected ? getSolanaAccount(accounts, options.chain) : void 0;
87
91
  }
@@ -91,6 +95,39 @@ function adaptSolanaStandardWallet(walletInfo, options = {}) {
91
95
  function dispose() {
92
96
  unsubscribeChange?.();
93
97
  }
98
+ function whileMobileWalletAuthorized(request) {
99
+ if (!isMobileWalletAdapter) {
100
+ return request();
101
+ }
102
+ let reject;
103
+ const deauthorized = new Promise((_, rejectRequest) => {
104
+ reject = rejectRequest;
105
+ });
106
+ pendingMobileWalletRequests.add(reject);
107
+ return Promise.race([request(), deauthorized]).finally(() => {
108
+ pendingMobileWalletRequests.delete(reject);
109
+ });
110
+ }
111
+ function signMessageThroughMobileWalletSession(activeAccount, message) {
112
+ const signMessages = isMobileWalletAdapter ? getSolanaMobileWalletAuthorizationStore()?.signMessages : void 0;
113
+ return signMessages?.(Uint8Array.from(activeAccount.publicKey), [message]).then(
114
+ (signedPayloads) => signedPayloads.map((signedMessage) => ({
115
+ signedMessage,
116
+ signature: signedMessage.slice(-64)
117
+ }))
118
+ );
119
+ }
120
+ function rejectPendingMobileWalletRequests() {
121
+ for (const reject of pendingMobileWalletRequests) {
122
+ reject(
123
+ createSolanaError(
124
+ "WALLET_NOT_CONNECTED",
125
+ "The wallet ended this app's session instead of signing, usually because it no longer accepts the saved authorization. Connect the wallet again and retry."
126
+ )
127
+ );
128
+ }
129
+ pendingMobileWalletRequests.clear();
130
+ }
94
131
  async function verifySignInResult(result, requestedAddress) {
95
132
  if (!result) {
96
133
  throw new Error("Solana wallet did not return a sign-in result");
@@ -242,10 +279,12 @@ function adaptSolanaStandardWallet(walletInfo, options = {}) {
242
279
  } : void 0,
243
280
  signMessage: hasSignMessage(wallet) ? async (message) => {
244
281
  const activeAccount = getActiveAccount(account);
245
- const [result] = await wallet.features[SolanaSignMessage].signMessage({
246
- account: activeAccount,
247
- message
248
- });
282
+ const [result] = await whileMobileWalletAuthorized(
283
+ () => signMessageThroughMobileWalletSession(activeAccount, message) ?? wallet.features[SolanaSignMessage].signMessage({
284
+ account: activeAccount,
285
+ message
286
+ })
287
+ );
249
288
  if (!result) {
250
289
  throw new Error("Solana wallet did not return a message signature");
251
290
  }
@@ -264,36 +303,44 @@ function adaptSolanaStandardWallet(walletInfo, options = {}) {
264
303
  } : void 0,
265
304
  signTransaction: hasSignTransaction(wallet) ? async (transaction) => {
266
305
  const activeAccount = getActiveAccount(account);
267
- const [result] = await wallet.features[SolanaSignTransaction].signTransaction({
268
- account: activeAccount,
269
- transaction: new Uint8Array(transaction),
270
- chain: options.chain
271
- });
306
+ const [result] = await whileMobileWalletAuthorized(
307
+ () => wallet.features[SolanaSignTransaction].signTransaction({
308
+ account: activeAccount,
309
+ transaction: new Uint8Array(transaction),
310
+ chain: options.chain
311
+ })
312
+ );
272
313
  if (!result) {
273
314
  throw new Error("Solana wallet did not return a signed transaction");
274
315
  }
275
316
  return result.signedTransaction;
276
317
  } : void 0,
277
- signAllTransactions: hasSignTransaction(wallet) ? async (transactions) => signAllThroughFeature(
278
- wallet,
279
- () => getActiveAccount(account),
280
- transactions,
281
- options.chain
318
+ signAllTransactions: hasSignTransaction(wallet) ? async (transactions) => whileMobileWalletAuthorized(
319
+ () => signAllThroughFeature(
320
+ wallet,
321
+ () => getActiveAccount(account),
322
+ transactions,
323
+ options.chain
324
+ )
282
325
  ) : void 0,
283
- signTransactions: hasSignTransaction(wallet) ? async (transactions) => signAllThroughFeature(
284
- wallet,
285
- () => getActiveAccount(account),
286
- transactions,
287
- options.chain
326
+ signTransactions: hasSignTransaction(wallet) ? async (transactions) => whileMobileWalletAuthorized(
327
+ () => signAllThroughFeature(
328
+ wallet,
329
+ () => getActiveAccount(account),
330
+ transactions,
331
+ options.chain
332
+ )
288
333
  ) : void 0,
289
334
  signAndSendTransaction: hasSignAndSendTransaction(wallet) ? async (transaction, sendOptions) => {
290
335
  const activeAccount = getActiveAccount(account);
291
- const [result] = await wallet.features[SolanaSignAndSendTransaction].signAndSendTransaction({
292
- account: activeAccount,
293
- transaction: new Uint8Array(transaction),
294
- chain: options.chain ?? getSolanaAccountChain(activeAccount),
295
- options: sendOptions
296
- });
336
+ const [result] = await whileMobileWalletAuthorized(
337
+ () => wallet.features[SolanaSignAndSendTransaction].signAndSendTransaction({
338
+ account: activeAccount,
339
+ transaction: new Uint8Array(transaction),
340
+ chain: options.chain ?? getSolanaAccountChain(activeAccount),
341
+ options: sendOptions
342
+ })
343
+ );
297
344
  if (!result) {
298
345
  throw new Error("Solana wallet did not return a transaction signature");
299
346
  }
@@ -302,21 +349,20 @@ function adaptSolanaStandardWallet(walletInfo, options = {}) {
302
349
  signAndSendTransactions: hasSignAndSendTransaction(wallet) ? async (transactions, sendOptions) => {
303
350
  const activeAccount = getActiveAccount(account);
304
351
  if (isMobileWalletAdapter && options.sendTransaction && transactions.length > 1 && hasSignTransaction(wallet)) {
305
- const signedTransactions = await signAllThroughFeature(
306
- wallet,
307
- () => activeAccount,
308
- transactions,
309
- options.chain
352
+ const signedTransactions = await whileMobileWalletAuthorized(
353
+ () => signAllThroughFeature(wallet, () => activeAccount, transactions, options.chain)
310
354
  );
311
355
  return sendSequentially(signedTransactions, options.sendTransaction, sendOptions);
312
356
  }
313
- const results = await wallet.features[SolanaSignAndSendTransaction].signAndSendTransaction(
314
- ...transactions.map((transaction) => ({
315
- account: activeAccount,
316
- transaction: new Uint8Array(transaction),
317
- chain: options.chain ?? getSolanaAccountChain(activeAccount),
318
- options: sendOptions
319
- }))
357
+ const results = await whileMobileWalletAuthorized(
358
+ () => wallet.features[SolanaSignAndSendTransaction].signAndSendTransaction(
359
+ ...transactions.map((transaction) => ({
360
+ account: activeAccount,
361
+ transaction: new Uint8Array(transaction),
362
+ chain: options.chain ?? getSolanaAccountChain(activeAccount),
363
+ options: sendOptions
364
+ }))
365
+ )
320
366
  );
321
367
  if (results.length !== transactions.length) {
322
368
  throw new Error(
@@ -1 +1 @@
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.D8oIzL0q.mjs';
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.CSMFFbai.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue-solana/core",
3
- "version": "4.1.4",
3
+ "version": "4.1.6",
4
4
  "description": "Framework-agnostic primitives for Vue Solana libraries.",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -115,6 +115,7 @@
115
115
  "access": "public"
116
116
  },
117
117
  "dependencies": {
118
+ "@solana-mobile/mobile-wallet-adapter-protocol": "^2.2.9",
118
119
  "@solana-mobile/wallet-standard-mobile": "^0.5.3",
119
120
  "@solana/kit": "^8.6.0",
120
121
  "@solana/kit-plugin-rpc": "^0.19.0",