@meshconnect/web-link-sdk 3.2.14 → 3.2.15

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.
Files changed (101) hide show
  1. package/jest.setup.ts +4 -0
  2. package/package.json +20 -8
  3. package/src/Link.test.ts +434 -0
  4. package/src/Link.ts +491 -0
  5. package/src/index.ts +3 -0
  6. package/src/utils/__snapshots__/popup.test.ts.snap +89 -0
  7. package/src/utils/connectors/evm/chainConfigs.ts +120 -0
  8. package/src/utils/connectors/evm/chainSwitching.ts +165 -0
  9. package/src/utils/connectors/evm/index.ts +8 -0
  10. package/src/utils/connectors/evm/provider.ts +22 -0
  11. package/src/utils/connectors/evm/signing.ts +39 -0
  12. package/src/utils/connectors/evm/transactions.ts +356 -0
  13. package/src/utils/connectors/evm/types.ts +63 -0
  14. package/src/utils/connectors/evm/walletConnection.ts +140 -0
  15. package/src/utils/connectors/evm/walletDiscovery.ts +67 -0
  16. package/src/utils/connectors/solana/connection.ts +69 -0
  17. package/src/utils/connectors/solana/index.ts +5 -0
  18. package/src/utils/connectors/solana/providerDiscovery.ts +153 -0
  19. package/src/utils/connectors/solana/signing.ts +18 -0
  20. package/src/utils/connectors/solana/transaction.ts +382 -0
  21. package/src/utils/connectors/solana/types.ts +66 -0
  22. package/{utils/event-types.js → src/utils/event-types.test.ts} +15 -5
  23. package/src/utils/event-types.ts +350 -0
  24. package/src/utils/popup.test.ts +50 -0
  25. package/src/utils/popup.ts +123 -0
  26. package/src/utils/sdk-specs.test.ts +18 -0
  27. package/src/utils/sdk-specs.ts +7 -0
  28. package/src/utils/style.test.ts +33 -0
  29. package/src/utils/style.ts +15 -0
  30. package/src/utils/types.ts +270 -0
  31. package/src/utils/version.ts +1 -0
  32. package/src/utils/wallet/EVMWalletStrategy.ts +176 -0
  33. package/src/utils/wallet/SolanaWalletStrategy.ts +207 -0
  34. package/src/utils/wallet/WalletStrategy.ts +99 -0
  35. package/src/utils/wallet/WalletStrategyFactory.ts +46 -0
  36. package/src/utils/wallet/__tests__/EVMWalletStrategy.test.ts +233 -0
  37. package/src/utils/wallet/__tests__/SolanaWalletStrategy.test.ts +253 -0
  38. package/src/utils/wallet/__tests__/WalletStrategy.test.ts +77 -0
  39. package/src/utils/wallet/__tests__/WalletStrategyFactory.test.ts +65 -0
  40. package/src/utils/wallet/index.ts +4 -0
  41. package/src/utils/wallet-browser-event-types.ts +190 -0
  42. package/tools/copy.js +26 -0
  43. package/tools/update-version.js +10 -0
  44. package/tsconfig.json +14 -0
  45. package/Link.d.ts +0 -2
  46. package/Link.js +0 -530
  47. package/index.d.ts +0 -3
  48. package/index.js +0 -3
  49. package/utils/connectors/evm/chainConfigs.d.ts +0 -2
  50. package/utils/connectors/evm/chainConfigs.js +0 -115
  51. package/utils/connectors/evm/chainSwitching.d.ts +0 -15
  52. package/utils/connectors/evm/chainSwitching.js +0 -242
  53. package/utils/connectors/evm/index.d.ts +0 -8
  54. package/utils/connectors/evm/index.js +0 -8
  55. package/utils/connectors/evm/provider.d.ts +0 -6
  56. package/utils/connectors/evm/provider.js +0 -13
  57. package/utils/connectors/evm/signing.d.ts +0 -1
  58. package/utils/connectors/evm/signing.js +0 -78
  59. package/utils/connectors/evm/transactions.d.ts +0 -28
  60. package/utils/connectors/evm/transactions.js +0 -381
  61. package/utils/connectors/evm/types.d.ts +0 -57
  62. package/utils/connectors/evm/types.js +0 -1
  63. package/utils/connectors/evm/walletConnection.d.ts +0 -20
  64. package/utils/connectors/evm/walletConnection.js +0 -160
  65. package/utils/connectors/evm/walletDiscovery.d.ts +0 -10
  66. package/utils/connectors/evm/walletDiscovery.js +0 -55
  67. package/utils/connectors/solana/connection.d.ts +0 -4
  68. package/utils/connectors/solana/connection.js +0 -108
  69. package/utils/connectors/solana/index.d.ts +0 -5
  70. package/utils/connectors/solana/index.js +0 -5
  71. package/utils/connectors/solana/providerDiscovery.d.ts +0 -3
  72. package/utils/connectors/solana/providerDiscovery.js +0 -127
  73. package/utils/connectors/solana/signing.d.ts +0 -1
  74. package/utils/connectors/solana/signing.js +0 -59
  75. package/utils/connectors/solana/transaction.d.ts +0 -17
  76. package/utils/connectors/solana/transaction.js +0 -362
  77. package/utils/connectors/solana/types.d.ts +0 -71
  78. package/utils/connectors/solana/types.js +0 -8
  79. package/utils/event-types.d.ts +0 -233
  80. package/utils/popup.d.ts +0 -3
  81. package/utils/popup.js +0 -36
  82. package/utils/sdk-specs.d.ts +0 -5
  83. package/utils/sdk-specs.js +0 -6
  84. package/utils/style.d.ts +0 -3
  85. package/utils/style.js +0 -13
  86. package/utils/types.d.ts +0 -234
  87. package/utils/types.js +0 -1
  88. package/utils/version.d.ts +0 -1
  89. package/utils/version.js +0 -1
  90. package/utils/wallet/EVMWalletStrategy.d.ts +0 -31
  91. package/utils/wallet/EVMWalletStrategy.js +0 -265
  92. package/utils/wallet/SolanaWalletStrategy.d.ts +0 -33
  93. package/utils/wallet/SolanaWalletStrategy.js +0 -293
  94. package/utils/wallet/WalletStrategy.d.ts +0 -61
  95. package/utils/wallet/WalletStrategy.js +0 -25
  96. package/utils/wallet/WalletStrategyFactory.d.ts +0 -15
  97. package/utils/wallet/WalletStrategyFactory.js +0 -31
  98. package/utils/wallet/index.d.ts +0 -4
  99. package/utils/wallet/index.js +0 -4
  100. package/utils/wallet-browser-event-types.d.ts +0 -116
  101. package/utils/wallet-browser-event-types.js +0 -17
@@ -0,0 +1,140 @@
1
+ import { ethers } from 'ethers'
2
+ import { EVMProvider, EVMConnectResult, EIP6963ProviderDetail } from './types'
3
+ import {
4
+ setActiveEVMProvider,
5
+ getActiveRawProvider,
6
+ clearActiveProviders
7
+ } from './provider'
8
+ import { switchEVMChain } from './chainSwitching'
9
+ import {
10
+ initializeWalletDiscovery,
11
+ findAvailableProviders
12
+ } from './walletDiscovery'
13
+
14
+ // Extend Window interface
15
+ declare global {
16
+ interface Window {
17
+ ethereum?: EVMProvider & {
18
+ providers?: EVMProvider[]
19
+ }
20
+ }
21
+ }
22
+
23
+ initializeWalletDiscovery()
24
+
25
+ /**
26
+ * Gets an EVM provider for a specific wallet
27
+ */
28
+ export const getEVMProvider = (
29
+ walletName?: string,
30
+ walletDetail?: EIP6963ProviderDetail
31
+ ): EVMProvider => {
32
+ if (walletDetail?.provider) {
33
+ return walletDetail.provider as EVMProvider
34
+ }
35
+
36
+ if (!walletName) {
37
+ throw new Error('Wallet name is required')
38
+ }
39
+
40
+ const providers = findAvailableProviders()
41
+
42
+ const matchingProvider = providers.find(
43
+ p =>
44
+ p.name.toLowerCase() === walletName.toLowerCase() ||
45
+ p.name.toLowerCase().includes(walletName.toLowerCase())
46
+ )
47
+
48
+ if (matchingProvider) {
49
+ return matchingProvider.injectedData.provider
50
+ }
51
+
52
+ if (window.ethereum) {
53
+ return window.ethereum
54
+ }
55
+
56
+ throw new Error(
57
+ `No provider found for wallet ${walletName}. Please make sure the wallet is installed and enabled.`
58
+ )
59
+ }
60
+
61
+ /**
62
+ * Connects to an EVM wallet
63
+ */
64
+ export const connectToEVMWallet = async (
65
+ walletName: string,
66
+ targetChainId?: number,
67
+ walletDetail?: EIP6963ProviderDetail
68
+ ): Promise<EVMConnectResult | Error> => {
69
+ try {
70
+ let provider: EVMProvider
71
+ try {
72
+ provider = getEVMProvider(walletName, walletDetail)
73
+ } catch (error) {
74
+ throw new Error(`No provider found for wallet ${walletName}`)
75
+ }
76
+
77
+ const browserProvider = new ethers.BrowserProvider(provider)
78
+ setActiveEVMProvider(browserProvider, provider)
79
+
80
+ let existingAccounts
81
+ try {
82
+ existingAccounts = await provider.request({ method: 'eth_accounts' })
83
+ } catch (error) {
84
+ existingAccounts = []
85
+ }
86
+ if (!existingAccounts || existingAccounts.length === 0) {
87
+ await browserProvider.send('eth_requestAccounts', [])
88
+ }
89
+
90
+ const signer = await browserProvider.getSigner()
91
+ const address = await signer.getAddress()
92
+ let chainId = await browserProvider
93
+ .getNetwork()
94
+ .then(network => Number(network.chainId))
95
+
96
+ if (targetChainId && chainId !== targetChainId) {
97
+ const switchResult = await switchEVMChain(targetChainId, provider)
98
+ if (switchResult instanceof Error) {
99
+ throw switchResult
100
+ }
101
+ chainId = switchResult.chainId
102
+ }
103
+
104
+ return {
105
+ accounts: [address],
106
+ chainId,
107
+ isConnected: true
108
+ }
109
+ } catch (error) {
110
+ console.error('EVM wallet connection error:', error)
111
+ return error instanceof Error
112
+ ? error
113
+ : new Error(`Failed to connect to ${walletName} wallet`)
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Disconnects from an EVM wallet
119
+ */
120
+ export const disconnectFromEVMWallet = async (
121
+ walletName: string
122
+ ): Promise<void | Error> => {
123
+ try {
124
+ const provider = getActiveRawProvider()
125
+ if (!provider) {
126
+ return
127
+ }
128
+
129
+ if (provider.removeAllListeners) {
130
+ provider.removeAllListeners()
131
+ }
132
+
133
+ clearActiveProviders()
134
+ } catch (error) {
135
+ console.error('EVM wallet disconnection error:', error)
136
+ return error instanceof Error
137
+ ? error
138
+ : new Error(`Failed to disconnect from ${walletName} wallet`)
139
+ }
140
+ }
@@ -0,0 +1,67 @@
1
+ import {
2
+ EVMProvider,
3
+ InjectedProviderInfo,
4
+ EIP6963ProviderDetail
5
+ } from './types'
6
+
7
+ let discoveredWallets: EIP6963ProviderDetail[] = []
8
+
9
+ /**
10
+ * Initializes EIP-6963 wallet discovery protocol
11
+ * @returns Cleanup function for event listeners
12
+ */
13
+ export const initializeWalletDiscovery = (): (() => void) => {
14
+ const handleAnnouncement = (event: CustomEvent) => {
15
+ const providerDetail = event.detail as EIP6963ProviderDetail
16
+ discoveredWallets = [...discoveredWallets, providerDetail]
17
+ }
18
+
19
+ window.addEventListener(
20
+ 'eip6963:announceProvider',
21
+ handleAnnouncement as EventListener
22
+ )
23
+ window.dispatchEvent(new Event('eip6963:requestProvider'))
24
+
25
+ return () => {
26
+ window.removeEventListener(
27
+ 'eip6963:announceProvider',
28
+ handleAnnouncement as EventListener
29
+ )
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Finds all available EVM providers using EIP-6963
35
+ */
36
+ export const findAvailableProviders = (): InjectedProviderInfo[] => {
37
+ const providers: InjectedProviderInfo[] = []
38
+
39
+ // Initialize wallet discovery if not already done
40
+ if (discoveredWallets.length === 0) {
41
+ initializeWalletDiscovery()
42
+ }
43
+
44
+ // Add EIP-6963 discovered wallets
45
+ discoveredWallets.forEach(wallet => {
46
+ const injectedData: any = {
47
+ provider: wallet.provider as EVMProvider
48
+ }
49
+
50
+ // Copy all boolean properties that start with 'is'
51
+ for (const key in wallet.provider) {
52
+ const provider = wallet.provider as unknown as { [key: string]: unknown }
53
+ if (key.startsWith('is') && typeof provider[key] === 'boolean') {
54
+ injectedData[key] = provider[key]
55
+ }
56
+ }
57
+
58
+ providers.push({
59
+ name: wallet.info.name,
60
+ id: wallet.info.uuid,
61
+ icon: wallet.info.icon,
62
+ injectedData
63
+ })
64
+ })
65
+
66
+ return providers
67
+ }
@@ -0,0 +1,69 @@
1
+ import { SolanaConnectResult } from './types'
2
+ import { getSolanaProvider } from './providerDiscovery'
3
+ import { Buffer } from 'buffer'
4
+ import { WalletBrowserPayload } from '../../types'
5
+
6
+ if (typeof window !== 'undefined') {
7
+ window.Buffer = window.Buffer || Buffer
8
+ }
9
+
10
+ export const connectToSolanaWallet = async (
11
+ walletPayload: WalletBrowserPayload
12
+ ): Promise<SolanaConnectResult | Error> => {
13
+ try {
14
+ const provider = getSolanaProvider(walletPayload.integrationName)
15
+
16
+ // Try eager connect first, fall back to regular connect
17
+ const response = await provider
18
+ .connect({ onlyIfTrusted: true })
19
+ .catch(() => provider.connect())
20
+
21
+ // Handle Phantom wallet which returns response.publicKey
22
+ if (response?.publicKey) {
23
+ if (walletPayload.targetChainId == '103') {
24
+ return {
25
+ accounts: [response.publicKey.toString()],
26
+ chainId: '103',
27
+ isConnected: true
28
+ }
29
+ }
30
+ return {
31
+ accounts: [response.publicKey.toString()],
32
+ chainId: '101',
33
+ isConnected: true
34
+ }
35
+ }
36
+
37
+ // Handle other wallets that update provider.publicKey directly
38
+ if (provider.publicKey) {
39
+ return {
40
+ accounts: [provider.publicKey.toString()],
41
+ chainId: '101',
42
+ isConnected: true
43
+ }
44
+ }
45
+
46
+ throw new Error(
47
+ `${walletPayload.integrationName} connection failed - no public key returned`
48
+ )
49
+ } catch (error) {
50
+ return error instanceof Error
51
+ ? error
52
+ : new Error(
53
+ `Failed to connect to ${walletPayload.integrationName} wallet`
54
+ )
55
+ }
56
+ }
57
+
58
+ export const disconnectFromSolanaWallet = async (
59
+ walletName: string
60
+ ): Promise<void | Error> => {
61
+ try {
62
+ const provider = getSolanaProvider(walletName)
63
+ await provider.disconnect()
64
+ } catch (error) {
65
+ return error instanceof Error
66
+ ? error
67
+ : new Error(`Failed to disconnect from ${walletName} wallet`)
68
+ }
69
+ }
@@ -0,0 +1,5 @@
1
+ export * from './types'
2
+ export * from './providerDiscovery'
3
+ export * from './connection'
4
+ export * from './transaction'
5
+ export * from './signing'
@@ -0,0 +1,153 @@
1
+ import {
2
+ SolanaProvider,
3
+ WindowWithSolanaProviders,
4
+ SolanaWalletType
5
+ } from './types'
6
+
7
+ declare const window: WindowWithSolanaProviders
8
+
9
+ const identifyWalletType = (
10
+ provider: SolanaProvider & { [key: string]: any }
11
+ ): SolanaWalletType => {
12
+ if (provider.isPhantom) return SolanaWalletType.PHANTOM
13
+ if (provider.isSolflare) return SolanaWalletType.SOLFLARE
14
+ if (provider.isTrust || provider.isTrustWallet) return SolanaWalletType.TRUST
15
+ if (provider.isExodus) return SolanaWalletType.EXODUS
16
+ return SolanaWalletType.UNKNOWN
17
+ }
18
+
19
+ // Type-safe validation functions
20
+ type WalletValidationFn = (provider: SolanaProvider) => boolean
21
+
22
+ const walletValidations: Record<SolanaWalletType, WalletValidationFn> = {
23
+ [SolanaWalletType.PHANTOM]: (provider: SolanaProvider): boolean =>
24
+ provider.isPhantom === true &&
25
+ provider.isSolflare !== true &&
26
+ provider.isTrust !== true &&
27
+ provider.isTrustWallet !== true &&
28
+ provider.isExodus !== true,
29
+
30
+ [SolanaWalletType.SOLFLARE]: (provider: SolanaProvider): boolean =>
31
+ provider.isSolflare === true &&
32
+ provider.isPhantom !== true &&
33
+ provider.isTrust !== true &&
34
+ provider.isTrustWallet !== true &&
35
+ provider.isExodus !== true,
36
+
37
+ [SolanaWalletType.TRUST]: (provider: SolanaProvider): boolean =>
38
+ (provider.isTrust === true || provider.isTrustWallet === true) &&
39
+ provider.isPhantom !== true &&
40
+ provider.isSolflare !== true &&
41
+ provider.isExodus !== true,
42
+
43
+ [SolanaWalletType.EXODUS]: (provider: SolanaProvider): boolean =>
44
+ provider.isExodus === true &&
45
+ provider.isSolflare !== true &&
46
+ provider.isTrust !== true &&
47
+ provider.isTrustWallet !== true,
48
+ // Note: Exodus may also inject isPhantom, so we don't exclude it
49
+
50
+ [SolanaWalletType.UNKNOWN]: (provider: SolanaProvider): boolean =>
51
+ provider.isPhantom !== true &&
52
+ provider.isSolflare !== true &&
53
+ provider.isTrust !== true &&
54
+ provider.isTrustWallet !== true &&
55
+ provider.isExodus !== true
56
+ }
57
+
58
+ const getProviderByType = (
59
+ type: SolanaWalletType
60
+ ): SolanaProvider | undefined => {
61
+ // Then check known provider locations
62
+ switch (type) {
63
+ case SolanaWalletType.PHANTOM:
64
+ if (
65
+ window.phantom?.solana &&
66
+ walletValidations[type](window.phantom.solana)
67
+ ) {
68
+ return window.phantom.solana
69
+ }
70
+ return undefined
71
+ case SolanaWalletType.SOLFLARE:
72
+ if (window.solflare && walletValidations[type](window.solflare)) {
73
+ return window.solflare
74
+ }
75
+ return undefined
76
+ case SolanaWalletType.TRUST:
77
+ if (
78
+ window.trustwallet?.solana &&
79
+ walletValidations[type](window.trustwallet.solana)
80
+ ) {
81
+ return window.trustwallet.solana
82
+ }
83
+ return undefined
84
+ case SolanaWalletType.EXODUS:
85
+ if (
86
+ window.exodus?.solana &&
87
+ walletValidations[type](window.exodus.solana)
88
+ ) {
89
+ return window.exodus.solana
90
+ }
91
+ return undefined
92
+ case SolanaWalletType.UNKNOWN:
93
+ if (window.solana && walletValidations[type](window.solana)) {
94
+ return window.solana
95
+ }
96
+ return undefined
97
+ default:
98
+ return undefined
99
+ }
100
+ }
101
+
102
+ export const findAvailableSolanaProviders = (): {
103
+ [key in SolanaWalletType]?: boolean
104
+ } => {
105
+ const providers: { [key in SolanaWalletType]?: boolean } = {}
106
+
107
+ // Check all known wallet types
108
+ Object.values(SolanaWalletType).forEach(type => {
109
+ if (getProviderByType(type)) {
110
+ providers[type] = true
111
+ }
112
+ })
113
+
114
+ // Also check window.solana if not already found
115
+ if (window.solana && !Object.keys(providers).length) {
116
+ const walletType = identifyWalletType(window.solana)
117
+ providers[walletType] = true
118
+ }
119
+
120
+ return providers
121
+ }
122
+
123
+ export const getSolanaProvider = (walletName: string): SolanaProvider => {
124
+ const normalizedName = walletName
125
+ .toLowerCase()
126
+ .replace(/\s+/g, '') as SolanaWalletType
127
+ const availableProviders = findAvailableSolanaProviders()
128
+
129
+ // First check if the requested wallet is available
130
+ if (availableProviders[normalizedName]) {
131
+ const provider = getProviderByType(normalizedName)
132
+ if (provider) return provider
133
+ }
134
+
135
+ // If not found and it's a dynamic provider, try direct access
136
+ const dynamicProvider = (window as any)[normalizedName]?.solana
137
+ if (dynamicProvider) {
138
+ return dynamicProvider
139
+ }
140
+
141
+ // If still not found, check window.solana as last resort
142
+ if (window.solana) {
143
+ const detectedType = identifyWalletType(window.solana)
144
+ if (
145
+ detectedType === normalizedName ||
146
+ normalizedName === SolanaWalletType.UNKNOWN
147
+ ) {
148
+ return window.solana
149
+ }
150
+ }
151
+
152
+ throw new Error(`Provider not found for wallet: ${walletName}`)
153
+ }
@@ -0,0 +1,18 @@
1
+ import bs58 from 'bs58'
2
+ import { getSolanaProvider } from './providerDiscovery'
3
+
4
+ export const signSolanaMessage = async (
5
+ walletName: string,
6
+ message: string
7
+ ): Promise<string | Error> => {
8
+ try {
9
+ const provider = getSolanaProvider(walletName)
10
+ const messageBytes = new TextEncoder().encode(message)
11
+ const signedMessage = await provider.signMessage(messageBytes)
12
+ return bs58.encode(signedMessage.signature)
13
+ } catch (error) {
14
+ return error instanceof Error
15
+ ? error
16
+ : new Error(`Failed to sign message with ${walletName} wallet`)
17
+ }
18
+ }