@dynamic-labs/solana 4.40.1 → 4.41.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/CHANGELOG.md CHANGED
@@ -1,4 +1,23 @@
1
1
 
2
+ ## [4.41.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.40.2...v4.41.0) (2025-10-29)
3
+
4
+
5
+ ### Features
6
+
7
+ * **react-native:** add MFA recovery methods ([#9788](https://github.com/dynamic-labs/dynamic-auth/issues/9788)) ([664e0d5](https://github.com/dynamic-labs/dynamic-auth/commit/664e0d5878530abc9e645c8801a87f3109cfd8f9))
8
+
9
+
10
+ ### Bug Fixes
11
+
12
+ * crypto.com link opening on mobile ([#9779](https://github.com/dynamic-labs/dynamic-auth/issues/9779)) ([3439ac9](https://github.com/dynamic-labs/dynamic-auth/commit/3439ac9e2610360c6204f6195433ae3e05e26c30))
13
+
14
+ ### [4.40.2](https://github.com/dynamic-labs/dynamic-auth/compare/v4.40.1...v4.40.2) (2025-10-28)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * upgrade node to 20.20 in sanity-yarn-add-sdk job for compatibility ([#9743](https://github.com/dynamic-labs/dynamic-auth/issues/9743)) ([58d7e32](https://github.com/dynamic-labs/dynamic-auth/commit/58d7e32cd3965fba983c91c6345eae3bfe8dd1d5))
20
+
2
21
  ### [4.40.1](https://github.com/dynamic-labs/dynamic-auth/compare/v4.40.0...v4.40.1) (2025-10-24)
3
22
 
4
23
  ### Bug Fixes
package/package.cjs CHANGED
@@ -3,6 +3,6 @@
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
- var version = "4.40.1";
6
+ var version = "4.41.0";
7
7
 
8
8
  exports.version = version;
package/package.js CHANGED
@@ -1,4 +1,4 @@
1
1
  'use client'
2
- var version = "4.40.1";
2
+ var version = "4.41.0";
3
3
 
4
4
  export { version };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynamic-labs/solana",
3
- "version": "4.40.1",
3
+ "version": "4.41.0",
4
4
  "description": "A React SDK for implementing wallet web3 authentication and authorization to your website.",
5
5
  "author": "Dynamic Labs, Inc.",
6
6
  "license": "MIT",
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "homepage": "https://www.dynamic.xyz/",
20
20
  "dependencies": {
21
- "@dynamic-labs/wallet-connect": "4.40.1",
21
+ "@dynamic-labs/wallet-connect": "4.41.0",
22
22
  "@solana/web3.js": "1.98.1",
23
23
  "@wallet-standard/app": "1.0.1",
24
24
  "@wallet-standard/base": "1.0.1",
@@ -29,17 +29,17 @@
29
29
  "@walletconnect/sign-client": "2.21.5",
30
30
  "@walletconnect/utils": "2.21.5",
31
31
  "@walletconnect/types": "2.21.5",
32
- "@dynamic-labs/assert-package-version": "4.40.1",
33
- "@dynamic-labs/embedded-wallet-solana": "4.40.1",
34
- "@dynamic-labs/logger": "4.40.1",
35
- "@dynamic-labs/rpc-providers": "4.40.1",
32
+ "@dynamic-labs/assert-package-version": "4.41.0",
33
+ "@dynamic-labs/embedded-wallet-solana": "4.41.0",
34
+ "@dynamic-labs/logger": "4.41.0",
35
+ "@dynamic-labs/rpc-providers": "4.41.0",
36
36
  "@dynamic-labs/sdk-api-core": "0.0.813",
37
- "@dynamic-labs/solana-core": "4.40.1",
38
- "@dynamic-labs/types": "4.40.1",
39
- "@dynamic-labs/utils": "4.40.1",
40
- "@dynamic-labs/waas-svm": "4.40.1",
41
- "@dynamic-labs/wallet-book": "4.40.1",
42
- "@dynamic-labs/wallet-connector-core": "4.40.1",
37
+ "@dynamic-labs/solana-core": "4.41.0",
38
+ "@dynamic-labs/types": "4.41.0",
39
+ "@dynamic-labs/utils": "4.41.0",
40
+ "@dynamic-labs/waas-svm": "4.41.0",
41
+ "@dynamic-labs/wallet-book": "4.41.0",
42
+ "@dynamic-labs/wallet-connector-core": "4.41.0",
43
43
  "eventemitter3": "5.0.1"
44
44
  },
45
45
  "peerDependencies": {}
@@ -5,13 +5,15 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
6
  var _tslib = require('../../_virtual/_tslib.cjs');
7
7
  var utils = require('@dynamic-labs/utils');
8
+ var walletBook = require('@dynamic-labs/wallet-book');
8
9
  var InjectedWalletBase = require('../injected/InjectedWalletBase/InjectedWalletBase.cjs');
9
10
 
10
11
  class Solflare extends InjectedWalletBase.InjectedWalletBase {
11
- constructor() {
12
- super(...arguments);
12
+ constructor(props) {
13
+ super(props);
13
14
  this.name = 'Solflare';
14
15
  this.overrideKey = 'solflare';
16
+ this.walletConnectWalletBookEntry = walletBook.findWalletBookWallet(props.walletBook, this.key);
15
17
  }
16
18
  getAddress() {
17
19
  return _tslib.__awaiter(this, void 0, void 0, function* () {
@@ -1,7 +1,9 @@
1
+ import { SolanaWalletConnectorOpts } from '@dynamic-labs/solana-core';
1
2
  import { InjectedWalletBase } from '../injected/InjectedWalletBase';
2
3
  export declare class Solflare extends InjectedWalletBase {
3
4
  name: string;
4
5
  overrideKey: string;
6
+ constructor(props: SolanaWalletConnectorOpts);
5
7
  getAddress(): Promise<string | undefined>;
6
8
  signMessage(messageToSign: string): Promise<string | undefined>;
7
9
  }
@@ -1,13 +1,15 @@
1
1
  'use client'
2
2
  import { __awaiter } from '../../_virtual/_tslib.js';
3
3
  import { isMobile, handleMobileWalletRedirect, bufferToBase64 } from '@dynamic-labs/utils';
4
+ import { findWalletBookWallet } from '@dynamic-labs/wallet-book';
4
5
  import { InjectedWalletBase } from '../injected/InjectedWalletBase/InjectedWalletBase.js';
5
6
 
6
7
  class Solflare extends InjectedWalletBase {
7
- constructor() {
8
- super(...arguments);
8
+ constructor(props) {
9
+ super(props);
9
10
  this.name = 'Solflare';
10
11
  this.overrideKey = 'solflare';
12
+ this.walletConnectWalletBookEntry = findWalletBookWallet(props.walletBook, this.key);
11
13
  }
12
14
  getAddress() {
13
15
  return __awaiter(this, void 0, void 0, function* () {
package/src/index.cjs CHANGED
@@ -12,7 +12,6 @@ var SolanaWalletConnectors = require('./SolanaWalletConnectors.cjs');
12
12
  var SolanaWalletConnectorsWithConfig = require('./SolanaWalletConnectorsWithConfig/SolanaWalletConnectorsWithConfig.cjs');
13
13
  var isBackpackSolanaSigner = require('./utils/isBackpackSolanaSigner.cjs');
14
14
  var isSignedMessage = require('./utils/isSignedMessage.cjs');
15
- require('@dynamic-labs/wallet-book');
16
15
  require('@dynamic-labs/wallet-connector-core');
17
16
  require('@dynamic-labs/utils');
18
17
  require('./CoinbaseSolana/CoinbaseSolana.cjs');
package/src/index.js CHANGED
@@ -8,7 +8,6 @@ export { SolanaWalletConnectors } from './SolanaWalletConnectors.js';
8
8
  export { SolanaWalletConnectorsWithConfig } from './SolanaWalletConnectorsWithConfig/SolanaWalletConnectorsWithConfig.js';
9
9
  export { isBackpackSolanaSigner } from './utils/isBackpackSolanaSigner.js';
10
10
  export { isSignedMessage } from './utils/isSignedMessage.js';
11
- import '@dynamic-labs/wallet-book';
12
11
  import '@dynamic-labs/wallet-connector-core';
13
12
  import '@dynamic-labs/utils';
14
13
  import './CoinbaseSolana/CoinbaseSolana.js';
@@ -5,13 +5,15 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
6
  var _tslib = require('../../../_virtual/_tslib.cjs');
7
7
  var utils = require('@dynamic-labs/utils');
8
+ var walletBook = require('@dynamic-labs/wallet-book');
8
9
  var InjectedWalletBase = require('../InjectedWalletBase/InjectedWalletBase.cjs');
9
10
 
10
11
  class BackpackSol extends InjectedWalletBase.InjectedWalletBase {
11
- constructor() {
12
- super(...arguments);
12
+ constructor(props) {
13
+ super(props);
13
14
  this.name = 'Backpack';
14
15
  this.overrideKey = 'backpacksol';
16
+ this.walletConnectWalletBookEntry = walletBook.findWalletBookWallet(props.walletBook, this.key);
15
17
  }
16
18
  getSigner() {
17
19
  return _tslib.__awaiter(this, void 0, void 0, function* () {
@@ -1,7 +1,9 @@
1
+ import { SolanaWalletConnectorOpts } from '@dynamic-labs/solana-core';
1
2
  import { InjectedWalletBase } from '../InjectedWalletBase';
2
3
  export declare class BackpackSol extends InjectedWalletBase {
3
4
  name: string;
4
5
  overrideKey: string;
6
+ constructor(props: SolanaWalletConnectorOpts);
5
7
  getSigner<IBackpackSolanaSigner>(): Promise<IBackpackSolanaSigner | undefined>;
6
8
  signMessage(messageToSign: string): Promise<string | undefined>;
7
9
  }
@@ -1,13 +1,15 @@
1
1
  'use client'
2
2
  import { __awaiter } from '../../../_virtual/_tslib.js';
3
3
  import { bufferToBase64 } from '@dynamic-labs/utils';
4
+ import { findWalletBookWallet } from '@dynamic-labs/wallet-book';
4
5
  import { InjectedWalletBase } from '../InjectedWalletBase/InjectedWalletBase.js';
5
6
 
6
7
  class BackpackSol extends InjectedWalletBase {
7
- constructor() {
8
- super(...arguments);
8
+ constructor(props) {
9
+ super(props);
9
10
  this.name = 'Backpack';
10
11
  this.overrideKey = 'backpacksol';
12
+ this.walletConnectWalletBookEntry = findWalletBookWallet(props.walletBook, this.key);
11
13
  }
12
14
  getSigner() {
13
15
  return __awaiter(this, void 0, void 0, function* () {
@@ -36,10 +36,7 @@ class InjectedWalletBase extends solanaCore.SolanaWalletConnector {
36
36
  return this;
37
37
  }
38
38
  // if the wallet is not installed on the browser and WC is available, return the WC connector
39
- const wcConnector = new SolanaWalletConnectConnector.SolanaWalletConnectConnector(Object.assign(Object.assign({}, this.constructorProps), { metadata: walletConnectorCore.getWalletMetadataFromWalletBook({
40
- walletBookWallet: this.walletConnectWalletBookEntry,
41
- walletKey: this.key,
42
- }), overrideKey: this.key, walletName: this.name }));
39
+ const wcConnector = new SolanaWalletConnectConnector.SolanaWalletConnectConnector(Object.assign(Object.assign({}, this.constructorProps), { metadata: walletConnectorCore.getWalletMetadataFromWalletBook(Object.assign(Object.assign({}, this.metadata), { walletBookWallet: this.walletConnectWalletBookEntry, walletKey: this.key })), overrideKey: this.key, walletName: this.name }));
43
40
  wcConnector.init();
44
41
  return wcConnector;
45
42
  }
@@ -32,10 +32,7 @@ class InjectedWalletBase extends SolanaWalletConnector {
32
32
  return this;
33
33
  }
34
34
  // if the wallet is not installed on the browser and WC is available, return the WC connector
35
- const wcConnector = new SolanaWalletConnectConnector(Object.assign(Object.assign({}, this.constructorProps), { metadata: getWalletMetadataFromWalletBook({
36
- walletBookWallet: this.walletConnectWalletBookEntry,
37
- walletKey: this.key,
38
- }), overrideKey: this.key, walletName: this.name }));
35
+ const wcConnector = new SolanaWalletConnectConnector(Object.assign(Object.assign({}, this.constructorProps), { metadata: getWalletMetadataFromWalletBook(Object.assign(Object.assign({}, this.metadata), { walletBookWallet: this.walletConnectWalletBookEntry, walletKey: this.key })), overrideKey: this.key, walletName: this.name }));
39
36
  wcConnector.init();
40
37
  return wcConnector;
41
38
  }
@@ -3,7 +3,6 @@
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
- var walletBook = require('@dynamic-labs/wallet-book');
7
6
  var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
8
7
  var utils = require('@dynamic-labs/utils');
9
8
  var CoinbaseSolana = require('../CoinbaseSolana/CoinbaseSolana.cjs');
@@ -53,9 +52,9 @@ const shouldAddWalletStandardConnector = (wallet, walletBook, authMode) => {
53
52
  });
54
53
  return !shouldHandleFromWalletBook && hasAllFeatures;
55
54
  };
56
- const fetchInjectedWalletConnectors = ({ walletBook: walletBook$1, authMode, }) => {
55
+ const fetchInjectedWalletConnectors = ({ walletBook, authMode, }) => {
57
56
  var _a;
58
- const walletBookConnectors = Object.entries((_a = walletBook$1 === null || walletBook$1 === void 0 ? void 0 : walletBook$1.wallets) !== null && _a !== void 0 ? _a : {})
57
+ const walletBookConnectors = Object.entries((_a = walletBook === null || walletBook === void 0 ? void 0 : walletBook.wallets) !== null && _a !== void 0 ? _a : {})
59
58
  .filter(([key, wallet]) => {
60
59
  var _a, _b, _c;
61
60
  const injectedConfig = (_a = wallet.injectedConfig) === null || _a === void 0 ? void 0 : _a.find((config) => config.chain === 'sol');
@@ -66,21 +65,26 @@ const fetchInjectedWalletConnectors = ({ walletBook: walletBook$1, authMode, })
66
65
  ((_c = (_b = injectedConfig === null || injectedConfig === void 0 ? void 0 : injectedConfig.walletStandard) === null || _b === void 0 ? void 0 : _b.features) === null || _c === void 0 ? void 0 : _c.length);
67
66
  return isSolanaWallet && !shouldBeFiltered;
68
67
  })
69
- .map(([key, wallet]) => getConnectorConstructorInjectedWallet.getConnectorConstructorInjectedWallet({ key, wallet, walletBook: walletBook$1 }));
68
+ .map(([key, wallet]) => getConnectorConstructorInjectedWallet.getConnectorConstructorInjectedWallet({ key, wallet, walletBook }));
70
69
  const walletStandardWallets = getWalletStandardWallets.getWalletStandardWallets();
71
70
  const walletStandardConnectors = walletStandardWallets
72
- .filter((wallet) => shouldAddWalletStandardConnector(wallet, walletBook$1, authMode))
71
+ .filter((wallet) => shouldAddWalletStandardConnector(wallet, walletBook, authMode))
73
72
  .map((wallet) => {
74
- const walletBookWallet = walletBook.findWalletBookWalletByNameAndChain(walletBook$1, wallet.name, 'sol');
73
+ var _a, _b;
74
+ const [walletBookKey, walletBookWallet] = (_b = Object.entries((_a = walletBook === null || walletBook === void 0 ? void 0 : walletBook.wallets) !== null && _a !== void 0 ? _a : {}).find(([, walletBookEntry]) => {
75
+ var _a, _b;
76
+ return walletBookEntry.name === wallet.name &&
77
+ ((_b = (_a = walletBookEntry.injectedConfig) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.chain) === 'sol';
78
+ })) !== null && _b !== void 0 ? _b : [];
75
79
  // if the wallet book wallet is found, we want to use it to get the metadata
76
80
  // to merge with the wallet standard metadata, specially the supportedHardwareWallets prop
77
81
  const walletBookMetadata = walletBookWallet &&
78
82
  walletConnectorCore.getWalletMetadataFromWalletBook({
79
- walletBook: walletBook$1,
83
+ walletBook,
80
84
  walletBookWallet,
81
- walletKey: `sanitizeName(${wallet.name})sol`,
85
+ walletKey: walletBookKey !== null && walletBookKey !== void 0 ? walletBookKey : `${utils.sanitizeName(wallet.name)}sol`,
82
86
  });
83
- return getConnectorConstructorForWalletStandardWallet.getConnectorConstructorForWalletStandardWallet(wallet, walletBookMetadata);
87
+ return getConnectorConstructorForWalletStandardWallet.getConnectorConstructorForWalletStandardWallet(wallet, walletBookMetadata, walletBookKey);
84
88
  });
85
89
  logger.logger.logVerboseTroubleshootingMessage('[SOL fetchInjectedWalletConnectors] walletStandardConnectors', walletStandardConnectors.map((w) => w.name));
86
90
  return [...walletBookConnectors, ...walletStandardConnectors];
@@ -1,5 +1,4 @@
1
1
  'use client'
2
- import { findWalletBookWalletByNameAndChain } from '@dynamic-labs/wallet-book';
3
2
  import { getWalletMetadataFromWalletBook } from '@dynamic-labs/wallet-connector-core';
4
3
  import { sanitizeName } from '@dynamic-labs/utils';
5
4
  import { CoinbaseSolana } from '../CoinbaseSolana/CoinbaseSolana.js';
@@ -67,16 +66,21 @@ const fetchInjectedWalletConnectors = ({ walletBook, authMode, }) => {
67
66
  const walletStandardConnectors = walletStandardWallets
68
67
  .filter((wallet) => shouldAddWalletStandardConnector(wallet, walletBook, authMode))
69
68
  .map((wallet) => {
70
- const walletBookWallet = findWalletBookWalletByNameAndChain(walletBook, wallet.name, 'sol');
69
+ var _a, _b;
70
+ const [walletBookKey, walletBookWallet] = (_b = Object.entries((_a = walletBook === null || walletBook === void 0 ? void 0 : walletBook.wallets) !== null && _a !== void 0 ? _a : {}).find(([, walletBookEntry]) => {
71
+ var _a, _b;
72
+ return walletBookEntry.name === wallet.name &&
73
+ ((_b = (_a = walletBookEntry.injectedConfig) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.chain) === 'sol';
74
+ })) !== null && _b !== void 0 ? _b : [];
71
75
  // if the wallet book wallet is found, we want to use it to get the metadata
72
76
  // to merge with the wallet standard metadata, specially the supportedHardwareWallets prop
73
77
  const walletBookMetadata = walletBookWallet &&
74
78
  getWalletMetadataFromWalletBook({
75
79
  walletBook,
76
80
  walletBookWallet,
77
- walletKey: `sanitizeName(${wallet.name})sol`,
81
+ walletKey: walletBookKey !== null && walletBookKey !== void 0 ? walletBookKey : `${sanitizeName(wallet.name)}sol`,
78
82
  });
79
- return getConnectorConstructorForWalletStandardWallet(wallet, walletBookMetadata);
83
+ return getConnectorConstructorForWalletStandardWallet(wallet, walletBookMetadata, walletBookKey);
80
84
  });
81
85
  logger.logVerboseTroubleshootingMessage('[SOL fetchInjectedWalletConnectors] walletStandardConnectors', walletStandardConnectors.map((w) => w.name));
82
86
  return [...walletBookConnectors, ...walletStandardConnectors];
@@ -7,9 +7,9 @@ var utils = require('@dynamic-labs/utils');
7
7
  var InjectedWalletBase = require('../../InjectedWalletBase/InjectedWalletBase.cjs');
8
8
  var createSolanaSignerFromWalletStandard = require('../createSolanaSignerFromWalletStandard/createSolanaSignerFromWalletStandard.cjs');
9
9
 
10
- const getConnectorConstructorForWalletStandardWallet = (wallet, walletBookMetadata = {}) => {
10
+ const getConnectorConstructorForWalletStandardWallet = (wallet, walletBookMetadata = {}, walletBookKey = undefined) => {
11
11
  const sanitizedName = utils.sanitizeName(wallet.name);
12
- return class extends InjectedWalletBase.InjectedWalletBase {
12
+ const ConnectorConstructor = class extends InjectedWalletBase.InjectedWalletBase {
13
13
  constructor(props) {
14
14
  super(Object.assign(Object.assign({}, props), { metadata: Object.assign(Object.assign({}, walletBookMetadata), { groupKey: sanitizedName, icon: wallet.icon, id: sanitizedName, name: wallet.name }) }));
15
15
  this.name = wallet.name;
@@ -23,6 +23,11 @@ const getConnectorConstructorForWalletStandardWallet = (wallet, walletBookMetada
23
23
  return this._provider;
24
24
  }
25
25
  };
26
+ Object.defineProperty(ConnectorConstructor, 'key', {
27
+ value: walletBookKey !== null && walletBookKey !== void 0 ? walletBookKey : sanitizedName,
28
+ writable: false,
29
+ });
30
+ return ConnectorConstructor;
26
31
  };
27
32
 
28
33
  exports.getConnectorConstructorForWalletStandardWallet = getConnectorConstructorForWalletStandardWallet;
@@ -1,3 +1,3 @@
1
1
  import { Wallet } from '@wallet-standard/base';
2
2
  import { WalletConnectorConstructor, WalletMetadata } from '@dynamic-labs/wallet-connector-core';
3
- export declare const getConnectorConstructorForWalletStandardWallet: (wallet: Wallet, walletBookMetadata?: Partial<WalletMetadata>) => WalletConnectorConstructor;
3
+ export declare const getConnectorConstructorForWalletStandardWallet: (wallet: Wallet, walletBookMetadata?: Partial<WalletMetadata>, walletBookKey?: string | undefined) => WalletConnectorConstructor;
@@ -3,9 +3,9 @@ import { sanitizeName } from '@dynamic-labs/utils';
3
3
  import { InjectedWalletBase } from '../../InjectedWalletBase/InjectedWalletBase.js';
4
4
  import { createSolanaSignerFromWalletStandard } from '../createSolanaSignerFromWalletStandard/createSolanaSignerFromWalletStandard.js';
5
5
 
6
- const getConnectorConstructorForWalletStandardWallet = (wallet, walletBookMetadata = {}) => {
6
+ const getConnectorConstructorForWalletStandardWallet = (wallet, walletBookMetadata = {}, walletBookKey = undefined) => {
7
7
  const sanitizedName = sanitizeName(wallet.name);
8
- return class extends InjectedWalletBase {
8
+ const ConnectorConstructor = class extends InjectedWalletBase {
9
9
  constructor(props) {
10
10
  super(Object.assign(Object.assign({}, props), { metadata: Object.assign(Object.assign({}, walletBookMetadata), { groupKey: sanitizedName, icon: wallet.icon, id: sanitizedName, name: wallet.name }) }));
11
11
  this.name = wallet.name;
@@ -19,6 +19,11 @@ const getConnectorConstructorForWalletStandardWallet = (wallet, walletBookMetada
19
19
  return this._provider;
20
20
  }
21
21
  };
22
+ Object.defineProperty(ConnectorConstructor, 'key', {
23
+ value: walletBookKey !== null && walletBookKey !== void 0 ? walletBookKey : sanitizedName,
24
+ writable: false,
25
+ });
26
+ return ConnectorConstructor;
22
27
  };
23
28
 
24
29
  export { getConnectorConstructorForWalletStandardWallet };
@@ -55,11 +55,18 @@ class SolanaWalletConnectConnector extends solanaCore.SolanaWalletConnector {
55
55
  }
56
56
  return SolanaWalletConnectConnector.signClientReference;
57
57
  }
58
+ getAvailableMethods() {
59
+ var _a, _b;
60
+ if (!this.session) {
61
+ return [];
62
+ }
63
+ return (_b = (_a = this.session.namespaces.solana) === null || _a === void 0 ? void 0 : _a.methods) !== null && _b !== void 0 ? _b : [];
64
+ }
58
65
  getSupportedNetworks() {
59
66
  return _tslib.__awaiter(this, void 0, void 0, function* () {
60
67
  var _a, _b;
61
68
  if (!this.session) {
62
- return [];
69
+ return this.solNetworks.map((network) => network.chainId.toString());
63
70
  }
64
71
  const sessionChains = (_b = (_a = this.session.namespaces.solana) === null || _a === void 0 ? void 0 : _a.chains) !== null && _b !== void 0 ? _b : [];
65
72
  return this.solNetworks
@@ -80,6 +87,46 @@ class SolanaWalletConnectConnector extends solanaCore.SolanaWalletConnector {
80
87
  this.activeAccountEmitter.off('activeAccountDidChange', listener);
81
88
  };
82
89
  }
90
+ isSendBalanceUnsupported() {
91
+ // If there is no session, we assume the wallet supports send balance
92
+ // If we didn't, the send TX button would turn disabled on a refresh
93
+ if (!this.session) {
94
+ return false;
95
+ }
96
+ const supportedMethods = this.getAvailableMethods();
97
+ return (!supportedMethods.includes('solana_signAndSendTransaction') &&
98
+ !supportedMethods.includes('solana_signTransaction'));
99
+ }
100
+ createUiTransaction(from) {
101
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
102
+ yield this.validateActiveWallet(from);
103
+ if (this.isSendBalanceUnsupported()) {
104
+ throw new utils.DynamicError('Wallet does not support signing transactions. Please connect to a wallet that supports signing transactions.');
105
+ }
106
+ const transaction = new solanaCore.SolanaUiTransaction({
107
+ connection: this.getWalletClient(),
108
+ from,
109
+ onSubmit: (transaction) => _tslib.__awaiter(this, void 0, void 0, function* () {
110
+ var _a;
111
+ if (!transaction)
112
+ return;
113
+ const blockhash = yield this.getWalletClient().getLatestBlockhash();
114
+ if ('version' in transaction) {
115
+ transaction.message.recentBlockhash =
116
+ blockhash.blockhash;
117
+ }
118
+ else {
119
+ // Use the 'from' parameter which is the validated active wallet address
120
+ transaction.recentBlockhash = blockhash.blockhash;
121
+ transaction.feePayer =
122
+ (_a = transaction.feePayer) !== null && _a !== void 0 ? _a : new web3_js.PublicKey(from);
123
+ }
124
+ return yield this.signAndSendTransaction(transaction);
125
+ }),
126
+ });
127
+ return transaction;
128
+ });
129
+ }
83
130
  getSigner() {
84
131
  return _tslib.__awaiter(this, void 0, void 0, function* () {
85
132
  return createSolanaSignerForWalletConnect.createSolanaSignerForWalletConnect({ walletConnector: this });
@@ -125,7 +172,8 @@ class SolanaWalletConnectConnector extends solanaCore.SolanaWalletConnector {
125
172
  const chainParam = event.data;
126
173
  let chainId = chainParam;
127
174
  // Handle potentially CAIP-2 format
128
- if (chainParam.startsWith('solana:')) {
175
+ if (typeof chainParam === 'string' &&
176
+ chainParam.startsWith('solana:')) {
129
177
  const chainHash = chainParam.split(':')[1];
130
178
  chainId =
131
179
  (_b = (_a = this.solNetworks
@@ -137,7 +185,7 @@ class SolanaWalletConnectConnector extends solanaCore.SolanaWalletConnector {
137
185
  return;
138
186
  }
139
187
  // This will already emit an event so no need to call this.emit('chainChange', { chain: chainId });
140
- this.switchNetwork({ networkChainId: parseInt(chainId) });
188
+ this.switchNetwork({ networkChainId: parseInt(String(chainId)) });
141
189
  return;
142
190
  }
143
191
  if (event.name === 'accountsChanged') {
@@ -189,6 +237,9 @@ class SolanaWalletConnectConnector extends solanaCore.SolanaWalletConnector {
189
237
  return _tslib.__awaiter(this, void 0, void 0, function* () {
190
238
  var _a;
191
239
  logger.logger.debug('[SolanaWalletConnect] getAddress', opts);
240
+ if (this.session) {
241
+ return this.getActiveAddress();
242
+ }
192
243
  /**
193
244
  * In mobile/Safari, if the user just navigates back after the deeplink prompt the connection
194
245
  * is not rejected, so the previous connection URI is still valid and we can use it to handle the connection
@@ -198,10 +249,6 @@ class SolanaWalletConnectConnector extends solanaCore.SolanaWalletConnector {
198
249
  this.displayUri(opts);
199
250
  return;
200
251
  }
201
- /**
202
- * If we are already connected to a session, we need to end it first
203
- */
204
- yield this.endSession();
205
252
  logger.logger.logVerboseTroubleshootingMessage('[WalletConnectConnector] getAddress', {
206
253
  inAppBrowserUrl: (_a = this.metadata) === null || _a === void 0 ? void 0 : _a.inAppBrowserUrl,
207
254
  isMobile: utils.isMobile(),
@@ -213,8 +260,14 @@ class SolanaWalletConnectConnector extends solanaCore.SolanaWalletConnector {
213
260
  }
214
261
  logger.logger.debug('[SolanaWalletConnect] getAddress - connecting to WalletConnect');
215
262
  const chains = this.solNetworks.map((network) => `solana:${network.genesisHash}`);
263
+ // Await for the promise in case this gets called right as the window is loaded
264
+ // and the sign client is still initializing
265
+ const signClient = yield SolanaWalletConnectConnector.signClientPromise;
266
+ if (!signClient) {
267
+ throw new utils.DynamicError('Failed to access sign client for Wallet Connect Solana: Sign client not initialized');
268
+ }
216
269
  try {
217
- const { approval, uri } = yield this.signClient.connect({
270
+ const { approval, uri } = yield signClient.connect({
218
271
  optionalNamespaces: {
219
272
  solana: {
220
273
  chains,
@@ -331,12 +384,27 @@ class SolanaWalletConnectConnector extends solanaCore.SolanaWalletConnector {
331
384
  if (!activeAddress) {
332
385
  throw new utils.DynamicError('Active account address is required');
333
386
  }
387
+ logger.logger.debug('[SolanaWalletConnect] Signing transaction', {
388
+ activeAddress,
389
+ isVersioned: 'version' in transaction,
390
+ transaction,
391
+ });
334
392
  const serializedTransaction = this.serializeTransaction(transaction);
393
+ logger.logger.debug('[SolanaWalletConnect] Sending to wallet for signing', {
394
+ serializedLength: serializedTransaction.length,
395
+ });
335
396
  const { transaction: signedTransaction } = yield this.signClientRequest({
336
397
  method: 'solana_signTransaction',
337
398
  params: { transaction: serializedTransaction },
338
399
  });
400
+ logger.logger.debug('[SolanaWalletConnect] Received signed transaction from wallet', {
401
+ signedTransactionLength: signedTransaction.length,
402
+ signedTransactionPreview: signedTransaction.substring(0, 50),
403
+ });
339
404
  const decodedTransaction = bs58__default["default"].decode(signedTransaction);
405
+ logger.logger.debug('[SolanaWalletConnect] Decoded signed transaction', {
406
+ decodedLength: decodedTransaction.length,
407
+ });
340
408
  if (solanaCore.isVersionedTransaction(transaction)) {
341
409
  return web3_js.VersionedTransaction.deserialize(decodedTransaction);
342
410
  }
@@ -362,12 +430,45 @@ class SolanaWalletConnectConnector extends solanaCore.SolanaWalletConnector {
362
430
  }
363
431
  signAndSendTransaction(transaction, options) {
364
432
  return _tslib.__awaiter(this, void 0, void 0, function* () {
365
- const serializedTransaction = this.serializeTransaction(transaction);
366
- const { signature } = yield this.signClientRequest({
367
- method: 'solana_signAndSendTransaction',
368
- params: { options, transaction: serializedTransaction },
369
- });
370
- return signature;
433
+ const supportedMethods = this.getAvailableMethods();
434
+ // Try to use signAndSendTransaction if supported
435
+ if (supportedMethods.includes('solana_signAndSendTransaction')) {
436
+ const serializedTransaction = this.serializeTransaction(transaction);
437
+ const { signature } = yield this.signClientRequest({
438
+ method: 'solana_signAndSendTransaction',
439
+ params: { options, transaction: serializedTransaction },
440
+ });
441
+ return signature;
442
+ }
443
+ // Fallback: use signTransaction + sendRawTransaction
444
+ if (supportedMethods.includes('solana_signTransaction')) {
445
+ logger.logger.debug('[SolanaWalletConnect] Using fallback: signTransaction + sendRawTransaction');
446
+ const signedTransaction = yield this.signTransaction(transaction);
447
+ const isSigned = solanaCore.isTxAlreadySigned(signedTransaction);
448
+ logger.logger.debug('[SolanaWalletConnect] Transaction signed, checking signatures', {
449
+ hasSignatures: 'signatures' in signedTransaction &&
450
+ signedTransaction.signatures.length > 0,
451
+ isSigned,
452
+ signaturesLength: 'signatures' in signedTransaction
453
+ ? signedTransaction.signatures.length
454
+ : 'N/A',
455
+ });
456
+ if (!isSigned) {
457
+ throw new utils.DynamicError('Transaction returned from wallet was not properly signed. The wallet may have rejected the signing request.');
458
+ }
459
+ // When sending a signed transaction, serialize it without flags
460
+ // (requireAllSignatures and verifySignatures are only for unsigned transactions)
461
+ const serialized = signedTransaction.serialize();
462
+ logger.logger.debug('[SolanaWalletConnect] Transaction serialized', {
463
+ serializedLength: serialized.length,
464
+ });
465
+ const signature = yield this.getWalletClient().sendRawTransaction(serialized, options);
466
+ logger.logger.debug('[SolanaWalletConnect] Transaction sent successfully', {
467
+ signature,
468
+ });
469
+ return signature;
470
+ }
471
+ throw new utils.DynamicError('Wallet does not support signing and sending transactions. Please connect to a wallet that supports at least solana_signTransaction.');
371
472
  });
372
473
  }
373
474
  getDeepLink() {
@@ -2,7 +2,8 @@ import { SendOptions, Transaction, VersionedTransaction } from '@solana/web3.js'
2
2
  import SignClient from '@walletconnect/sign-client';
3
3
  import type { SessionTypes } from '@walletconnect/types';
4
4
  import { ISolanaSigner, SolanaWalletConnector, SolanaWalletConnectorOpts } from '@dynamic-labs/solana-core';
5
- import { DeepLinkVariant, GetAddressOpts, IWalletConnectConnector } from '@dynamic-labs/wallet-connector-core';
5
+ import { DeepLinkVariant, GetAddressOpts, ISendBalanceWalletConnector, IWalletConnectConnector } from '@dynamic-labs/wallet-connector-core';
6
+ import { IUITransaction } from '@dynamic-labs/types';
6
7
  export type SolanaWalletConnectConnectorOpts = SolanaWalletConnectorOpts & {
7
8
  projectId?: string;
8
9
  walletName: string;
@@ -11,7 +12,7 @@ export type SolanaWalletConnectConnectorOpts = SolanaWalletConnectorOpts & {
11
12
  appName?: string;
12
13
  overrideKey?: string;
13
14
  };
14
- export declare class SolanaWalletConnectConnector extends SolanaWalletConnector implements IWalletConnectConnector {
15
+ export declare class SolanaWalletConnectConnector extends SolanaWalletConnector implements IWalletConnectConnector, ISendBalanceWalletConnector {
15
16
  name: string;
16
17
  static signClientReference: SignClient | undefined;
17
18
  static signClientPromise: Promise<SignClient> | undefined;
@@ -35,9 +36,12 @@ export declare class SolanaWalletConnectConnector extends SolanaWalletConnector
35
36
  * immediately available.
36
37
  */
37
38
  get signClient(): SignClient;
39
+ getAvailableMethods(): string[];
38
40
  getSupportedNetworks(): Promise<string[]>;
39
41
  getActiveAddress(): string | undefined;
40
42
  listenToActiveAccountChange(listener: (account: string) => void): VoidFunction;
43
+ isSendBalanceUnsupported(): boolean;
44
+ createUiTransaction(from: string): Promise<IUITransaction>;
41
45
  getSigner(): Promise<ISolanaSigner>;
42
46
  connect(): Promise<void>;
43
47
  init(): Promise<void>;
@@ -4,7 +4,7 @@ import { PublicKey, VersionedTransaction, Transaction } from '@solana/web3.js';
4
4
  import { SDK_ERRORS } from '@walletconnect/utils';
5
5
  import bs58 from 'bs58';
6
6
  import EventEmitter from 'eventemitter3';
7
- import { SolanaWalletConnector, isVersionedTransaction } from '@dynamic-labs/solana-core';
7
+ import { SolanaWalletConnector, SolanaUiTransaction, isVersionedTransaction, isTxAlreadySigned } from '@dynamic-labs/solana-core';
8
8
  import { StorageService, DynamicError, filterDuplicates, isMobile, PlatformService, bufferToBase64 } from '@dynamic-labs/utils';
9
9
  import { getSignClientSingleton } from '@dynamic-labs/wallet-connect';
10
10
  import { performPlatformSpecificConnectionMethod, getDeepLink, isSameAddress } from '@dynamic-labs/wallet-connector-core';
@@ -46,11 +46,18 @@ class SolanaWalletConnectConnector extends SolanaWalletConnector {
46
46
  }
47
47
  return SolanaWalletConnectConnector.signClientReference;
48
48
  }
49
+ getAvailableMethods() {
50
+ var _a, _b;
51
+ if (!this.session) {
52
+ return [];
53
+ }
54
+ return (_b = (_a = this.session.namespaces.solana) === null || _a === void 0 ? void 0 : _a.methods) !== null && _b !== void 0 ? _b : [];
55
+ }
49
56
  getSupportedNetworks() {
50
57
  return __awaiter(this, void 0, void 0, function* () {
51
58
  var _a, _b;
52
59
  if (!this.session) {
53
- return [];
60
+ return this.solNetworks.map((network) => network.chainId.toString());
54
61
  }
55
62
  const sessionChains = (_b = (_a = this.session.namespaces.solana) === null || _a === void 0 ? void 0 : _a.chains) !== null && _b !== void 0 ? _b : [];
56
63
  return this.solNetworks
@@ -71,6 +78,46 @@ class SolanaWalletConnectConnector extends SolanaWalletConnector {
71
78
  this.activeAccountEmitter.off('activeAccountDidChange', listener);
72
79
  };
73
80
  }
81
+ isSendBalanceUnsupported() {
82
+ // If there is no session, we assume the wallet supports send balance
83
+ // If we didn't, the send TX button would turn disabled on a refresh
84
+ if (!this.session) {
85
+ return false;
86
+ }
87
+ const supportedMethods = this.getAvailableMethods();
88
+ return (!supportedMethods.includes('solana_signAndSendTransaction') &&
89
+ !supportedMethods.includes('solana_signTransaction'));
90
+ }
91
+ createUiTransaction(from) {
92
+ return __awaiter(this, void 0, void 0, function* () {
93
+ yield this.validateActiveWallet(from);
94
+ if (this.isSendBalanceUnsupported()) {
95
+ throw new DynamicError('Wallet does not support signing transactions. Please connect to a wallet that supports signing transactions.');
96
+ }
97
+ const transaction = new SolanaUiTransaction({
98
+ connection: this.getWalletClient(),
99
+ from,
100
+ onSubmit: (transaction) => __awaiter(this, void 0, void 0, function* () {
101
+ var _a;
102
+ if (!transaction)
103
+ return;
104
+ const blockhash = yield this.getWalletClient().getLatestBlockhash();
105
+ if ('version' in transaction) {
106
+ transaction.message.recentBlockhash =
107
+ blockhash.blockhash;
108
+ }
109
+ else {
110
+ // Use the 'from' parameter which is the validated active wallet address
111
+ transaction.recentBlockhash = blockhash.blockhash;
112
+ transaction.feePayer =
113
+ (_a = transaction.feePayer) !== null && _a !== void 0 ? _a : new PublicKey(from);
114
+ }
115
+ return yield this.signAndSendTransaction(transaction);
116
+ }),
117
+ });
118
+ return transaction;
119
+ });
120
+ }
74
121
  getSigner() {
75
122
  return __awaiter(this, void 0, void 0, function* () {
76
123
  return createSolanaSignerForWalletConnect({ walletConnector: this });
@@ -116,7 +163,8 @@ class SolanaWalletConnectConnector extends SolanaWalletConnector {
116
163
  const chainParam = event.data;
117
164
  let chainId = chainParam;
118
165
  // Handle potentially CAIP-2 format
119
- if (chainParam.startsWith('solana:')) {
166
+ if (typeof chainParam === 'string' &&
167
+ chainParam.startsWith('solana:')) {
120
168
  const chainHash = chainParam.split(':')[1];
121
169
  chainId =
122
170
  (_b = (_a = this.solNetworks
@@ -128,7 +176,7 @@ class SolanaWalletConnectConnector extends SolanaWalletConnector {
128
176
  return;
129
177
  }
130
178
  // This will already emit an event so no need to call this.emit('chainChange', { chain: chainId });
131
- this.switchNetwork({ networkChainId: parseInt(chainId) });
179
+ this.switchNetwork({ networkChainId: parseInt(String(chainId)) });
132
180
  return;
133
181
  }
134
182
  if (event.name === 'accountsChanged') {
@@ -180,6 +228,9 @@ class SolanaWalletConnectConnector extends SolanaWalletConnector {
180
228
  return __awaiter(this, void 0, void 0, function* () {
181
229
  var _a;
182
230
  logger.debug('[SolanaWalletConnect] getAddress', opts);
231
+ if (this.session) {
232
+ return this.getActiveAddress();
233
+ }
183
234
  /**
184
235
  * In mobile/Safari, if the user just navigates back after the deeplink prompt the connection
185
236
  * is not rejected, so the previous connection URI is still valid and we can use it to handle the connection
@@ -189,10 +240,6 @@ class SolanaWalletConnectConnector extends SolanaWalletConnector {
189
240
  this.displayUri(opts);
190
241
  return;
191
242
  }
192
- /**
193
- * If we are already connected to a session, we need to end it first
194
- */
195
- yield this.endSession();
196
243
  logger.logVerboseTroubleshootingMessage('[WalletConnectConnector] getAddress', {
197
244
  inAppBrowserUrl: (_a = this.metadata) === null || _a === void 0 ? void 0 : _a.inAppBrowserUrl,
198
245
  isMobile: isMobile(),
@@ -204,8 +251,14 @@ class SolanaWalletConnectConnector extends SolanaWalletConnector {
204
251
  }
205
252
  logger.debug('[SolanaWalletConnect] getAddress - connecting to WalletConnect');
206
253
  const chains = this.solNetworks.map((network) => `solana:${network.genesisHash}`);
254
+ // Await for the promise in case this gets called right as the window is loaded
255
+ // and the sign client is still initializing
256
+ const signClient = yield SolanaWalletConnectConnector.signClientPromise;
257
+ if (!signClient) {
258
+ throw new DynamicError('Failed to access sign client for Wallet Connect Solana: Sign client not initialized');
259
+ }
207
260
  try {
208
- const { approval, uri } = yield this.signClient.connect({
261
+ const { approval, uri } = yield signClient.connect({
209
262
  optionalNamespaces: {
210
263
  solana: {
211
264
  chains,
@@ -322,12 +375,27 @@ class SolanaWalletConnectConnector extends SolanaWalletConnector {
322
375
  if (!activeAddress) {
323
376
  throw new DynamicError('Active account address is required');
324
377
  }
378
+ logger.debug('[SolanaWalletConnect] Signing transaction', {
379
+ activeAddress,
380
+ isVersioned: 'version' in transaction,
381
+ transaction,
382
+ });
325
383
  const serializedTransaction = this.serializeTransaction(transaction);
384
+ logger.debug('[SolanaWalletConnect] Sending to wallet for signing', {
385
+ serializedLength: serializedTransaction.length,
386
+ });
326
387
  const { transaction: signedTransaction } = yield this.signClientRequest({
327
388
  method: 'solana_signTransaction',
328
389
  params: { transaction: serializedTransaction },
329
390
  });
391
+ logger.debug('[SolanaWalletConnect] Received signed transaction from wallet', {
392
+ signedTransactionLength: signedTransaction.length,
393
+ signedTransactionPreview: signedTransaction.substring(0, 50),
394
+ });
330
395
  const decodedTransaction = bs58.decode(signedTransaction);
396
+ logger.debug('[SolanaWalletConnect] Decoded signed transaction', {
397
+ decodedLength: decodedTransaction.length,
398
+ });
331
399
  if (isVersionedTransaction(transaction)) {
332
400
  return VersionedTransaction.deserialize(decodedTransaction);
333
401
  }
@@ -353,12 +421,45 @@ class SolanaWalletConnectConnector extends SolanaWalletConnector {
353
421
  }
354
422
  signAndSendTransaction(transaction, options) {
355
423
  return __awaiter(this, void 0, void 0, function* () {
356
- const serializedTransaction = this.serializeTransaction(transaction);
357
- const { signature } = yield this.signClientRequest({
358
- method: 'solana_signAndSendTransaction',
359
- params: { options, transaction: serializedTransaction },
360
- });
361
- return signature;
424
+ const supportedMethods = this.getAvailableMethods();
425
+ // Try to use signAndSendTransaction if supported
426
+ if (supportedMethods.includes('solana_signAndSendTransaction')) {
427
+ const serializedTransaction = this.serializeTransaction(transaction);
428
+ const { signature } = yield this.signClientRequest({
429
+ method: 'solana_signAndSendTransaction',
430
+ params: { options, transaction: serializedTransaction },
431
+ });
432
+ return signature;
433
+ }
434
+ // Fallback: use signTransaction + sendRawTransaction
435
+ if (supportedMethods.includes('solana_signTransaction')) {
436
+ logger.debug('[SolanaWalletConnect] Using fallback: signTransaction + sendRawTransaction');
437
+ const signedTransaction = yield this.signTransaction(transaction);
438
+ const isSigned = isTxAlreadySigned(signedTransaction);
439
+ logger.debug('[SolanaWalletConnect] Transaction signed, checking signatures', {
440
+ hasSignatures: 'signatures' in signedTransaction &&
441
+ signedTransaction.signatures.length > 0,
442
+ isSigned,
443
+ signaturesLength: 'signatures' in signedTransaction
444
+ ? signedTransaction.signatures.length
445
+ : 'N/A',
446
+ });
447
+ if (!isSigned) {
448
+ throw new DynamicError('Transaction returned from wallet was not properly signed. The wallet may have rejected the signing request.');
449
+ }
450
+ // When sending a signed transaction, serialize it without flags
451
+ // (requireAllSignatures and verifySignatures are only for unsigned transactions)
452
+ const serialized = signedTransaction.serialize();
453
+ logger.debug('[SolanaWalletConnect] Transaction serialized', {
454
+ serializedLength: serialized.length,
455
+ });
456
+ const signature = yield this.getWalletClient().sendRawTransaction(serialized, options);
457
+ logger.debug('[SolanaWalletConnect] Transaction sent successfully', {
458
+ signature,
459
+ });
460
+ return signature;
461
+ }
462
+ throw new DynamicError('Wallet does not support signing and sending transactions. Please connect to a wallet that supports at least solana_signTransaction.');
362
463
  });
363
464
  }
364
465
  getDeepLink() {